diff --git a/llms/anthropic/anthropicllm.go b/llms/anthropic/anthropicllm.go index 417de1b25..5de7b35eb 100644 --- a/llms/anthropic/anthropicllm.go +++ b/llms/anthropic/anthropicllm.go @@ -384,34 +384,41 @@ 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, - } + var contents []anthropicclient.Content - return anthropicclient.ChatMessage{ - Role: RoleAssistant, - Content: []anthropicclient.Content{toolUse}, - }, nil + for _, part := range msg.Parts { + switch p := part.(type) { + case llms.ToolCall: + var inputStruct map[string]interface{} + if err := json.Unmarshal([]byte(p.FunctionCall.Arguments), &inputStruct); 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: + if p.Text != "" { + contents = append(contents, &anthropicclient.TextContent{ + Type: "text", + Text: p.Text, + }) + } + default: + return anthropicclient.ChatMessage{}, fmt.Errorf("anthropic: %w for AI message part type %T", ErrInvalidContentType, part) + } } - if textContent, ok := msg.Parts[0].(llms.TextContent); ok { - return anthropicclient.ChatMessage{ - Role: RoleAssistant, - Content: []anthropicclient.Content{&anthropicclient.TextContent{ - Type: "text", - Text: textContent.Text, - }}, - }, nil + + if len(contents) == 0 { + return anthropicclient.ChatMessage{}, fmt.Errorf("anthropic: no valid content in AI message") } - return anthropicclient.ChatMessage{}, fmt.Errorf("anthropic: %w for AI message", ErrInvalidContentType) + + return anthropicclient.ChatMessage{ + Role: RoleAssistant, + Content: contents, + }, nil } type ToolResult struct { diff --git a/llms/anthropic/internal/anthropicclient/anthropicclient.go b/llms/anthropic/internal/anthropicclient/anthropicclient.go index fd3404d36..71ec7661b 100644 --- a/llms/anthropic/internal/anthropicclient/anthropicclient.go +++ b/llms/anthropic/internal/anthropicclient/anthropicclient.go @@ -130,7 +130,7 @@ type MessageRequest struct { Model string `json:"model"` Messages []ChatMessage `json:"messages"` System string `json:"system,omitempty"` - Temperature float64 `json:"temperature"` + Temperature float64 `json:"temperature,omitempty"` MaxTokens int `json:"max_tokens,omitempty"` TopP float64 `json:"top_p,omitempty"` Tools []Tool `json:"tools,omitempty"` @@ -142,7 +142,7 @@ type MessageRequest struct { // BetaHeaders are additional beta feature headers to include BetaHeaders []string `json:"-"` - StreamingFunc func(ctx context.Context, chunk []byte) error `json:"-"` + StreamingFunc func(ctx context.Context, chunk []byte) error `json:"-"` StreamingReasoningFunc func(ctx context.Context, reasoningChunk, chunk []byte) error `json:"-"` } diff --git a/llms/anthropic/internal/anthropicclient/messages.go b/llms/anthropic/internal/anthropicclient/messages.go index b200b6cad..b98250f20 100644 --- a/llms/anthropic/internal/anthropicclient/messages.go +++ b/llms/anthropic/internal/anthropicclient/messages.go @@ -40,14 +40,14 @@ type messagePayload struct { MaxTokens int `json:"max_tokens,omitempty"` StopWords []string `json:"stop_sequences,omitempty"` Stream bool `json:"stream,omitempty"` - Temperature float64 `json:"temperature"` + Temperature float64 `json:"temperature,omitempty"` Tools []Tool `json:"tools,omitempty"` TopP float64 `json:"top_p,omitempty"` // Extended thinking parameters (Claude 3.7+) Thinking *ThinkingConfig `json:"thinking,omitempty"` - StreamingFunc func(ctx context.Context, chunk []byte) error `json:"-"` + StreamingFunc func(ctx context.Context, chunk []byte) error `json:"-"` StreamingReasoningFunc func(ctx context.Context, reasoningChunk, chunk []byte) error `json:"-"` }