diff --git a/internal/llm/client.go b/internal/llm/client.go index de54322..1773282 100644 --- a/internal/llm/client.go +++ b/internal/llm/client.go @@ -523,7 +523,10 @@ func (c *AnthropicClient) CompletionsWithCtx(ctx context.Context, req ChatReques model = c.cfg.Model } - params := c.buildAnthropicParams(model, req) + params, err := c.buildAnthropicParams(model, req) + if err != nil { + return nil, err + } var opts []option.RequestOption for k, v := range c.cfg.ExtraBody { @@ -539,7 +542,7 @@ func (c *AnthropicClient) CompletionsWithCtx(ctx context.Context, req ChatReques } // buildAnthropicParams converts the shared ChatRequest into Anthropic SDK parameters. -func (c *AnthropicClient) buildAnthropicParams(model string, req ChatRequest) anthropic.MessageNewParams { +func (c *AnthropicClient) buildAnthropicParams(model string, req ChatRequest) (anthropic.MessageNewParams, error) { var systemBlocks []anthropic.TextBlockParam var messages []anthropic.MessageParam var pendingToolResults []Message @@ -578,7 +581,9 @@ func (c *AnthropicClient) buildAnthropicParams(model string, req ChatRequest) an for _, tc := range msg.ToolCalls { argsMap := map[string]any{} if tc.Function.Arguments != "" { - json.Unmarshal([]byte(tc.Function.Arguments), &argsMap) + if err := json.Unmarshal([]byte(tc.Function.Arguments), &argsMap); err != nil { + return anthropic.MessageNewParams{}, fmt.Errorf("invalid tool call arguments for %s: %w", tc.Function.Name, err) + } } blocks = append(blocks, anthropic.NewToolUseBlock(tc.ID, argsMap, tc.Function.Name)) } @@ -644,7 +649,7 @@ func (c *AnthropicClient) buildAnthropicParams(model string, req ChatRequest) an params.Temperature = anthropic.Float(*req.Temperature) } - return params + return params, nil } func buildToolInputSchema(params map[string]any) anthropic.ToolInputSchemaParam { diff --git a/internal/llm/client_test.go b/internal/llm/client_test.go index 377e680..2aedfa3 100644 --- a/internal/llm/client_test.go +++ b/internal/llm/client_test.go @@ -110,7 +110,10 @@ func TestBuildAnthropicParams_CacheControl(t *testing.T) { }, } - params := client.buildAnthropicParams("claude-sonnet-4-20250514", req) + params, err := client.buildAnthropicParams("claude-sonnet-4-20250514", req) + if err != nil { + t.Fatalf("buildAnthropicParams: %v", err) + } t.Run("last system block has cache control", func(t *testing.T) { if len(params.System) < 2 { @@ -169,7 +172,10 @@ func TestBuildAnthropicParams_CacheControl_NoTools(t *testing.T) { }, } - params := client.buildAnthropicParams("claude-sonnet-4-20250514", req) + params, err := client.buildAnthropicParams("claude-sonnet-4-20250514", req) + if err != nil { + t.Fatalf("buildAnthropicParams: %v", err) + } if len(params.System) == 0 { t.Fatal("expected system blocks") @@ -195,7 +201,10 @@ func TestBuildAnthropicParams_CacheControl_NoSystem(t *testing.T) { }, } - params := client.buildAnthropicParams("claude-sonnet-4-20250514", req) + params, err := client.buildAnthropicParams("claude-sonnet-4-20250514", req) + if err != nil { + t.Fatalf("buildAnthropicParams: %v", err) + } if len(params.System) != 0 { t.Errorf("expected no system blocks, got %d", len(params.System)) diff --git a/internal/tool/code_comment.go b/internal/tool/code_comment.go index c114a1b..5fda7f6 100644 --- a/internal/tool/code_comment.go +++ b/internal/tool/code_comment.go @@ -38,7 +38,9 @@ func ParseComments(args map[string]any) ([]model.LlmComment, string) { if arr, ok := args["comments"].([]any); ok && len(arr) > 0 { rawComments = arr } else if s, ok := args["comments"].(string); ok && s != "" { - _ = json.Unmarshal([]byte(s), &rawComments) + if err := json.Unmarshal([]byte(s), &rawComments); err != nil { + return nil, fmt.Sprintf("Error: failed to parse 'comments' JSON string: %v", err) + } } if len(rawComments) == 0 { raw, _ := json.Marshal(args)