From 12a5b384d954ca0d0c01d963f6e458fdc737f021 Mon Sep 17 00:00:00 2001 From: wyRainBow Date: Wed, 11 Mar 2026 21:40:26 +0800 Subject: [PATCH] fix(anthropic): preserve all assistant parts for tool use Fixes #1468 --- llms/anthropic/anthropicllm.go | 59 ++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/llms/anthropic/anthropicllm.go b/llms/anthropic/anthropicllm.go index 417de1b25..6adafaf94 100644 --- a/llms/anthropic/anthropicllm.go +++ b/llms/anthropic/anthropicllm.go @@ -384,34 +384,43 @@ func handleHumanMessage(msg llms.MessageContent) (anthropicclient.ChatMessage, e } func handleAIMessage(msg llms.MessageContent) (anthropicclient.ChatMessage, error) { - if toolCall, ok := msg.Parts[0].(llms.ToolCall); ok { - var inputStruct map[string]interface{} - err := json.Unmarshal([]byte(toolCall.FunctionCall.Arguments), &inputStruct) - if err != nil { - return anthropicclient.ChatMessage{}, fmt.Errorf("anthropic: failed to unmarshal tool call arguments: %w", err) - } - toolUse := anthropicclient.ToolUseContent{ - Type: "tool_use", - ID: toolCall.ID, - Name: toolCall.FunctionCall.Name, - Input: inputStruct, - } - - return anthropicclient.ChatMessage{ - Role: RoleAssistant, - Content: []anthropicclient.Content{toolUse}, - }, nil + if len(msg.Parts) == 0 { + return anthropicclient.ChatMessage{}, fmt.Errorf("anthropic: no valid content in AI message") } - if textContent, ok := msg.Parts[0].(llms.TextContent); ok { - return anthropicclient.ChatMessage{ - Role: RoleAssistant, - Content: []anthropicclient.Content{&anthropicclient.TextContent{ + + contents := make([]anthropicclient.Content, 0, len(msg.Parts)) + for _, part := range msg.Parts { + switch p := part.(type) { + case llms.ToolCall: + var inputStruct map[string]interface{} + err := json.Unmarshal([]byte(p.FunctionCall.Arguments), &inputStruct) + if err != nil { + return anthropicclient.ChatMessage{}, fmt.Errorf("anthropic: failed to unmarshal tool call arguments: %w", err) + } + contents = append(contents, &anthropicclient.ToolUseContent{ + Type: "tool_use", + ID: p.ID, + Name: p.FunctionCall.Name, + Input: inputStruct, + }) + case llms.TextContent: + contents = append(contents, &anthropicclient.TextContent{ Type: "text", - Text: textContent.Text, - }}, - }, nil + Text: p.Text, + }) + default: + return anthropicclient.ChatMessage{}, fmt.Errorf("anthropic: unsupported AI message part type: %T", part) + } } - return anthropicclient.ChatMessage{}, fmt.Errorf("anthropic: %w for AI message", ErrInvalidContentType) + + if len(contents) == 0 { + return anthropicclient.ChatMessage{}, fmt.Errorf("anthropic: no valid content in AI message") + } + + return anthropicclient.ChatMessage{ + Role: RoleAssistant, + Content: contents, + }, nil } type ToolResult struct {