161 lines
4.5 KiB
Go
161 lines
4.5 KiB
Go
package antigravity
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestNormalizeClaudeCodeToolName(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
expected string
|
|
}{
|
|
{name: "read alias", input: "read_file", expected: "Read"},
|
|
{name: "grep alias", input: "search_files", expected: "Grep"},
|
|
{name: "webfetch alias", input: "fetch", expected: "WebFetch"},
|
|
{name: "plan alias", input: "enter_plan_mode", expected: "EnterPlanMode"},
|
|
{name: "native passthrough", input: "TaskUpdate", expected: "TaskUpdate"},
|
|
{name: "mcp passthrough", input: "mcp__github__list_prs", expected: "mcp__github__list_prs"},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
tt := tt
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
require.Equal(t, tt.expected, normalizeClaudeCodeToolName(tt.input))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestBuildPartsNormalizesClaudeCodeToolNames(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
toolIDToName := make(map[string]string)
|
|
assistantParts, stripped, err := buildParts(json.RawMessage(`[
|
|
{"type":"tool_use","id":"tool-1","name":"read_file","input":{"file_path":"/tmp/demo.txt"}}
|
|
]`), toolIDToName, false)
|
|
require.NoError(t, err)
|
|
require.False(t, stripped)
|
|
require.Len(t, assistantParts, 1)
|
|
require.NotNil(t, assistantParts[0].FunctionCall)
|
|
require.Equal(t, "Read", assistantParts[0].FunctionCall.Name)
|
|
require.Equal(t, "Read", toolIDToName["tool-1"])
|
|
|
|
userParts, stripped, err := buildParts(json.RawMessage(`[
|
|
{"type":"tool_result","tool_use_id":"tool-1","content":[{"type":"text","text":"ok"}]}
|
|
]`), toolIDToName, false)
|
|
require.NoError(t, err)
|
|
require.False(t, stripped)
|
|
require.Len(t, userParts, 1)
|
|
require.NotNil(t, userParts[0].FunctionResponse)
|
|
require.Equal(t, "Read", userParts[0].FunctionResponse.Name)
|
|
}
|
|
|
|
func TestBuildToolsNormalizesClaudeCodeBuiltinNamesOnly(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
result := buildTools([]ClaudeTool{
|
|
{
|
|
Name: "search_files",
|
|
Description: "Search the workspace",
|
|
InputSchema: map[string]any{
|
|
"type": "object",
|
|
},
|
|
},
|
|
{
|
|
Name: "mcp__github__list_prs",
|
|
Description: "List pull requests",
|
|
InputSchema: map[string]any{
|
|
"type": "object",
|
|
},
|
|
},
|
|
})
|
|
|
|
require.Len(t, result, 1)
|
|
require.Len(t, result[0].FunctionDeclarations, 2)
|
|
require.Equal(t, "Grep", result[0].FunctionDeclarations[0].Name)
|
|
require.Equal(t, "mcp__github__list_prs", result[0].FunctionDeclarations[1].Name)
|
|
}
|
|
|
|
func TestNonStreamingProcessorNormalizesClaudeCodeToolName(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
processor := NewNonStreamingProcessor()
|
|
response := processor.Process(&GeminiResponse{
|
|
Candidates: []GeminiCandidate{
|
|
{
|
|
Content: &GeminiContent{
|
|
Parts: []GeminiPart{
|
|
{
|
|
FunctionCall: &GeminiFunctionCall{
|
|
Name: "web_fetch",
|
|
Args: map[string]any{"url": "https://example.com"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
FinishReason: "STOP",
|
|
},
|
|
},
|
|
}, "resp-1", "claude-sonnet-4-5")
|
|
|
|
require.Len(t, response.Content, 1)
|
|
require.Equal(t, "tool_use", response.Content[0].Type)
|
|
require.Equal(t, "WebFetch", response.Content[0].Name)
|
|
require.True(t, strings.HasPrefix(response.Content[0].ID, "WebFetch-"))
|
|
require.NotNil(t, response.Content[0].Caller)
|
|
require.Equal(t, "direct", response.Content[0].Caller.Type)
|
|
require.Equal(t, "tool_use", response.StopReason)
|
|
}
|
|
|
|
func TestStreamingProcessorNormalizesClaudeCodeToolName(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
processor := NewStreamingProcessor("claude-sonnet-4-5")
|
|
output := processor.processFunctionCall(&GeminiFunctionCall{
|
|
Name: "search_files",
|
|
Args: map[string]any{"pattern": "TODO"},
|
|
}, "")
|
|
|
|
events := parseSSEDataEvents(t, output)
|
|
require.Len(t, events, 3)
|
|
|
|
contentBlock, ok := events[0]["content_block"].(map[string]any)
|
|
require.True(t, ok)
|
|
require.Equal(t, "tool_use", contentBlock["type"])
|
|
require.Equal(t, "Grep", contentBlock["name"])
|
|
|
|
toolID, ok := contentBlock["id"].(string)
|
|
require.True(t, ok)
|
|
require.True(t, strings.HasPrefix(toolID, "Grep-"))
|
|
|
|
caller, ok := contentBlock["caller"].(map[string]any)
|
|
require.True(t, ok)
|
|
require.Equal(t, "direct", caller["type"])
|
|
}
|
|
|
|
func parseSSEDataEvents(t *testing.T, payload []byte) []map[string]any {
|
|
t.Helper()
|
|
|
|
lines := strings.Split(string(payload), "\n")
|
|
events := make([]map[string]any, 0)
|
|
|
|
for _, line := range lines {
|
|
if !strings.HasPrefix(line, "data: ") {
|
|
continue
|
|
}
|
|
|
|
var event map[string]any
|
|
require.NoError(t, json.Unmarshal([]byte(strings.TrimPrefix(line, "data: ")), &event))
|
|
events = append(events, event)
|
|
}
|
|
|
|
return events
|
|
}
|