package claude import ( "testing" "ds2api/internal/config" ) func TestNormalizeClaudeRequest(t *testing.T) { t.Setenv("DS2API_CONFIG_JSON", `{}`) store := config.LoadStore() req := map[string]any{ "model": "claude-opus-4-6", "messages": []any{ map[string]any{"role": "user", "content": "hello"}, }, "stream": true, "tools": []any{ map[string]any{"name": "search", "description": "Search"}, }, } norm, err := normalizeClaudeRequest(store, req) if err != nil { t.Fatalf("normalize failed: %v", err) } if norm.Standard.ResolvedModel == "" { t.Fatalf("expected resolved model") } if !norm.Standard.Stream { t.Fatalf("expected stream=true") } if len(norm.Standard.ToolNames) == 0 { t.Fatalf("expected tool names") } if norm.Standard.ToolsRaw == nil { t.Fatalf("expected ToolsRaw preserved for downstream normalization") } if norm.Standard.FinalPrompt == "" { t.Fatalf("expected non-empty final prompt") } } func TestNormalizeClaudeRequestSupportsCamelCaseInputSchemaPromptInjection(t *testing.T) { t.Setenv("DS2API_CONFIG_JSON", `{}`) store := config.LoadStore() req := map[string]any{ "model": "claude-sonnet-4-5", "messages": []any{ map[string]any{"role": "user", "content": "hello"}, }, "tools": []any{ map[string]any{ "name": "todowrite", "description": "Write todos", "inputSchema": map[string]any{"type": "object", "properties": map[string]any{"todos": map[string]any{"type": "array"}}}, }, }, } norm, err := normalizeClaudeRequest(store, req) if err != nil { t.Fatalf("normalize failed: %v", err) } if !containsStr(norm.Standard.FinalPrompt, `"type":"array"`) { t.Fatalf("expected inputSchema to be injected into prompt, got=%q", norm.Standard.FinalPrompt) } } func TestNormalizeClaudeRequestInjectsToolsIntoExistingSystemMessage(t *testing.T) { t.Setenv("DS2API_CONFIG_JSON", `{}`) store := config.LoadStore() req := map[string]any{ "model": "claude-sonnet-4-5", "messages": []any{ map[string]any{"role": "system", "content": "baseline rule"}, map[string]any{"role": "user", "content": "hello"}, }, "tools": []any{ map[string]any{"name": "search", "description": "Search"}, }, } norm, err := normalizeClaudeRequest(store, req) if err != nil { t.Fatalf("normalize failed: %v", err) } if !containsStr(norm.Standard.FinalPrompt, "You have access to these tools") { t.Fatalf("expected tool prompt injected into final prompt, got=%q", norm.Standard.FinalPrompt) } if !containsStr(norm.Standard.FinalPrompt, "baseline rule") { t.Fatalf("expected existing system message preserved, got=%q", norm.Standard.FinalPrompt) } } func TestNormalizeClaudeRequestInjectsToolsIntoTopLevelSystem(t *testing.T) { t.Setenv("DS2API_CONFIG_JSON", `{}`) store := config.LoadStore() req := map[string]any{ "model": "claude-sonnet-4-5", "system": "top-level system", "messages": []any{ map[string]any{"role": "user", "content": "hello"}, }, "tools": []any{ map[string]any{"name": "search", "description": "Search"}, }, } norm, err := normalizeClaudeRequest(store, req) if err != nil { t.Fatalf("normalize failed: %v", err) } if !containsStr(norm.Standard.FinalPrompt, "top-level system") { t.Fatalf("expected top-level system preserved, got=%q", norm.Standard.FinalPrompt) } if !containsStr(norm.Standard.FinalPrompt, "You have access to these tools") { t.Fatalf("expected tool prompt injected, got=%q", norm.Standard.FinalPrompt) } }