feat: update providers and agent loop
This commit is contained in:
parent
7e2050345f
commit
1d0e9b7b29
4 changed files with 80 additions and 23 deletions
|
|
@ -380,6 +380,7 @@ func (al *AgentLoop) runLLMIteration(ctx context.Context, messages []providers.M
|
|||
assistantMsg := providers.Message{
|
||||
Role: "assistant",
|
||||
Content: response.Content,
|
||||
ThinkingContent: response.ThinkingContent,
|
||||
}
|
||||
for _, tc := range response.ToolCalls {
|
||||
argumentsJSON, _ := json.Marshal(tc.Arguments)
|
||||
|
|
|
|||
|
|
@ -77,6 +77,14 @@ func buildClaudeParams(messages []Message, tools []ToolDefinition, model string,
|
|||
case "assistant":
|
||||
if len(msg.ToolCalls) > 0 {
|
||||
var blocks []anthropic.ContentBlockParamUnion
|
||||
// Add thinking block if present (required for extended thinking mode)
|
||||
if msg.ThinkingContent != "" {
|
||||
blocks = append(blocks, anthropic.ContentBlockParamUnion{
|
||||
OfThinking: &anthropic.ThinkingBlockParam{
|
||||
Thinking: msg.ThinkingContent,
|
||||
},
|
||||
})
|
||||
}
|
||||
if msg.Content != "" {
|
||||
blocks = append(blocks, anthropic.NewTextBlock(msg.Content))
|
||||
}
|
||||
|
|
@ -85,9 +93,16 @@ func buildClaudeParams(messages []Message, tools []ToolDefinition, model string,
|
|||
}
|
||||
anthropicMessages = append(anthropicMessages, anthropic.NewAssistantMessage(blocks...))
|
||||
} else {
|
||||
anthropicMessages = append(anthropicMessages,
|
||||
anthropic.NewAssistantMessage(anthropic.NewTextBlock(msg.Content)),
|
||||
)
|
||||
var blocks []anthropic.ContentBlockParamUnion
|
||||
if msg.ThinkingContent != "" {
|
||||
blocks = append(blocks, anthropic.ContentBlockParamUnion{
|
||||
OfThinking: &anthropic.ThinkingBlockParam{
|
||||
Thinking: msg.ThinkingContent,
|
||||
},
|
||||
})
|
||||
}
|
||||
blocks = append(blocks, anthropic.NewTextBlock(msg.Content))
|
||||
anthropicMessages = append(anthropicMessages, anthropic.NewAssistantMessage(blocks...))
|
||||
}
|
||||
case "tool":
|
||||
anthropicMessages = append(anthropicMessages,
|
||||
|
|
@ -150,10 +165,14 @@ func translateToolsForClaude(tools []ToolDefinition) []anthropic.ToolUnionParam
|
|||
|
||||
func parseClaudeResponse(resp *anthropic.Message) *LLMResponse {
|
||||
var content string
|
||||
var thinkingContent string
|
||||
var toolCalls []ToolCall
|
||||
|
||||
for _, block := range resp.Content {
|
||||
switch block.Type {
|
||||
case "thinking":
|
||||
tb := block.AsThinking()
|
||||
thinkingContent += tb.Thinking
|
||||
case "text":
|
||||
tb := block.AsText()
|
||||
content += tb.Text
|
||||
|
|
@ -183,6 +202,7 @@ func parseClaudeResponse(resp *anthropic.Message) *LLMResponse {
|
|||
|
||||
return &LLMResponse{
|
||||
Content: content,
|
||||
ThinkingContent: thinkingContent,
|
||||
ToolCalls: toolCalls,
|
||||
FinishReason: finishReason,
|
||||
Usage: &UsageInfo{
|
||||
|
|
|
|||
|
|
@ -60,9 +60,41 @@ func (p *HTTPProvider) Chat(ctx context.Context, messages []Message, tools []Too
|
|||
}
|
||||
}
|
||||
|
||||
// Convert messages to API format, including reasoning_content for thinking models
|
||||
apiMessages := make([]map[string]interface{}, 0, len(messages))
|
||||
for _, msg := range messages {
|
||||
apiMsg := map[string]interface{}{
|
||||
"role": msg.Role,
|
||||
"content": msg.Content,
|
||||
}
|
||||
// Include reasoning_content for assistant messages with thinking content
|
||||
if msg.Role == "assistant" && msg.ThinkingContent != "" {
|
||||
apiMsg["reasoning_content"] = msg.ThinkingContent
|
||||
}
|
||||
if len(msg.ToolCalls) > 0 {
|
||||
toolCalls := make([]map[string]interface{}, 0, len(msg.ToolCalls))
|
||||
for _, tc := range msg.ToolCalls {
|
||||
argsJSON, _ := json.Marshal(tc.Arguments)
|
||||
toolCalls = append(toolCalls, map[string]interface{}{
|
||||
"id": tc.ID,
|
||||
"type": "function",
|
||||
"function": map[string]interface{}{
|
||||
"name": tc.Name,
|
||||
"arguments": string(argsJSON),
|
||||
},
|
||||
})
|
||||
}
|
||||
apiMsg["tool_calls"] = toolCalls
|
||||
}
|
||||
if msg.ToolCallID != "" {
|
||||
apiMsg["tool_call_id"] = msg.ToolCallID
|
||||
}
|
||||
apiMessages = append(apiMessages, apiMsg)
|
||||
}
|
||||
|
||||
requestBody := map[string]interface{}{
|
||||
"model": model,
|
||||
"messages": messages,
|
||||
"messages": apiMessages,
|
||||
}
|
||||
|
||||
if len(tools) > 0 {
|
||||
|
|
@ -127,6 +159,7 @@ func (p *HTTPProvider) parseResponse(body []byte) (*LLMResponse, error) {
|
|||
Choices []struct {
|
||||
Message struct {
|
||||
Content string `json:"content"`
|
||||
ReasoningContent string `json:"reasoning_content"`
|
||||
ToolCalls []struct {
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
|
|
@ -186,6 +219,7 @@ func (p *HTTPProvider) parseResponse(body []byte) (*LLMResponse, error) {
|
|||
|
||||
return &LLMResponse{
|
||||
Content: choice.Message.Content,
|
||||
ThinkingContent: choice.Message.ReasoningContent,
|
||||
ToolCalls: toolCalls,
|
||||
FinishReason: choice.FinishReason,
|
||||
Usage: apiResponse.Usage,
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ type LLMResponse struct {
|
|||
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
|
||||
FinishReason string `json:"finish_reason"`
|
||||
Usage *UsageInfo `json:"usage,omitempty"`
|
||||
ThinkingContent string `json:"thinking_content,omitempty"` // For Claude extended thinking
|
||||
}
|
||||
|
||||
type UsageInfo struct {
|
||||
|
|
@ -33,6 +34,7 @@ type Message struct {
|
|||
Content string `json:"content"`
|
||||
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
|
||||
ToolCallID string `json:"tool_call_id,omitempty"`
|
||||
ThinkingContent string `json:"thinking_content,omitempty"` // For Claude extended thinking
|
||||
}
|
||||
|
||||
type LLMProvider interface {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue