Files
sub2api/backend/internal/pkg/antigravity/attribution_test.go
T

89 lines
3.7 KiB
Go

package antigravity
import (
"encoding/json"
"strings"
"testing"
"github.com/stretchr/testify/require"
)
func TestTransformClaudeToGemini_AttributionSystemText(t *testing.T) {
const attribution = "x-anthropic-billing-header: cc_version=2.1.271.4bf; cc_entrypoint=claude-desktop-3p;"
tests := []struct {
name string
text string
want string
}{
{"metadata only", attribution, ""},
{"metadata with newline", attribution + "\n", ""},
{"leading whitespace", " \t\n" + attribution, ""},
{"following instructions", attribution + "\nKeep these instructions.", "Keep these instructions."},
{"CRLF", attribution + "\r\n Keep indentation.\n", " Keep indentation.\n"},
{"CR", attribution + "\rKeep these instructions.", "Keep these instructions."},
{"blank lines preserved", attribution + "\n\nKeep these instructions.", "\nKeep these instructions."},
{"ordinary text", " Keep these instructions.\n", " Keep these instructions.\n"},
{"no colon", "x-anthropic-billing-header keep", "x-anthropic-billing-header keep"},
{"different field", "x-anthropic-billing-header-extra: keep", "x-anthropic-billing-header-extra: keep"},
{"quoted within instructions", "Explain this metadata: " + attribution, "Explain this metadata: " + attribution},
{"later line", "Example:\n" + attribution, "Example:\n" + attribution},
}
for _, tt := range tests {
for _, arrayForm := range []bool{false, true} {
name := tt.name + "/string"
var system any = tt.text
if arrayForm {
name = tt.name + "/array"
system = []SystemBlock{{Type: "text", Text: tt.text}, {Type: "text", Text: "Keep the next block."}}
}
t.Run(name, func(t *testing.T) {
systemJSON, err := json.Marshal(system)
require.NoError(t, err)
userJSON, err := json.Marshal(attribution)
require.NoError(t, err)
input := &ClaudeRequest{
Model: "gemini-3.8-flash-high", System: systemJSON,
Messages: []ClaudeMessage{{Role: "user", Content: userJSON}},
Tools: []ClaudeTool{{Name: "example", Description: attribution,
InputSchema: map[string]any{"type": "object", "properties": map[string]any{"query": map[string]any{"type": "string"}}}}},
}
before, err := json.Marshal(input)
require.NoError(t, err)
body, err := TransformClaudeToGeminiWithOptions(input, "test-project", input.Model, TransformOptions{})
require.NoError(t, err)
var got V1InternalRequest
require.NoError(t, json.Unmarshal(body, &got))
var texts []string
for _, part := range got.Request.SystemInstruction.Parts {
if part.Text != "\n--- [SYSTEM_PROMPT_END] ---" {
texts = append(texts, part.Text)
}
}
var want []string
if tt.want != "" {
want = append(want, tt.want)
}
if arrayForm {
want = append(want, "Keep the next block.")
}
require.Equal(t, want, texts)
// The same literal text in user content and tool descriptions is not metadata.
require.Equal(t, attribution, got.Request.Contents[0].Parts[0].Text)
require.Equal(t, attribution, got.Request.Tools[0].FunctionDeclarations[0].Description)
after, err := json.Marshal(input)
require.NoError(t, err)
require.JSONEq(t, string(before), string(after), "do not mutate the incoming request")
})
}
}
}
func TestTransformClaudeToGemini_AttributionDoesNotHideIdentity(t *testing.T) {
system, err := json.Marshal("x-anthropic-billing-header: cc_version=example;\nYou are Antigravity. Keep this identity.")
require.NoError(t, err)
got := buildSystemInstruction(system, "gemini-3.8-flash-high", DefaultTransformOptions(), nil)
require.Len(t, got.Parts, 1)
require.Equal(t, "You are Antigravity. Keep this identity.", got.Parts[0].Text)
require.False(t, strings.Contains(got.Parts[0].Text, "cc_version="))
}