feat: update providers and agent loop
This commit is contained in:
parent
7e2050345f
commit
1d0e9b7b29
4 changed files with 80 additions and 23 deletions
|
|
@ -378,8 +378,9 @@ func (al *AgentLoop) runLLMIteration(ctx context.Context, messages []providers.M
|
||||||
|
|
||||||
// Build assistant message with tool calls
|
// Build assistant message with tool calls
|
||||||
assistantMsg := providers.Message{
|
assistantMsg := providers.Message{
|
||||||
Role: "assistant",
|
Role: "assistant",
|
||||||
Content: response.Content,
|
Content: response.Content,
|
||||||
|
ThinkingContent: response.ThinkingContent,
|
||||||
}
|
}
|
||||||
for _, tc := range response.ToolCalls {
|
for _, tc := range response.ToolCalls {
|
||||||
argumentsJSON, _ := json.Marshal(tc.Arguments)
|
argumentsJSON, _ := json.Marshal(tc.Arguments)
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,14 @@ func buildClaudeParams(messages []Message, tools []ToolDefinition, model string,
|
||||||
case "assistant":
|
case "assistant":
|
||||||
if len(msg.ToolCalls) > 0 {
|
if len(msg.ToolCalls) > 0 {
|
||||||
var blocks []anthropic.ContentBlockParamUnion
|
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 != "" {
|
if msg.Content != "" {
|
||||||
blocks = append(blocks, anthropic.NewTextBlock(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...))
|
anthropicMessages = append(anthropicMessages, anthropic.NewAssistantMessage(blocks...))
|
||||||
} else {
|
} else {
|
||||||
anthropicMessages = append(anthropicMessages,
|
var blocks []anthropic.ContentBlockParamUnion
|
||||||
anthropic.NewAssistantMessage(anthropic.NewTextBlock(msg.Content)),
|
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":
|
case "tool":
|
||||||
anthropicMessages = append(anthropicMessages,
|
anthropicMessages = append(anthropicMessages,
|
||||||
|
|
@ -150,10 +165,14 @@ func translateToolsForClaude(tools []ToolDefinition) []anthropic.ToolUnionParam
|
||||||
|
|
||||||
func parseClaudeResponse(resp *anthropic.Message) *LLMResponse {
|
func parseClaudeResponse(resp *anthropic.Message) *LLMResponse {
|
||||||
var content string
|
var content string
|
||||||
|
var thinkingContent string
|
||||||
var toolCalls []ToolCall
|
var toolCalls []ToolCall
|
||||||
|
|
||||||
for _, block := range resp.Content {
|
for _, block := range resp.Content {
|
||||||
switch block.Type {
|
switch block.Type {
|
||||||
|
case "thinking":
|
||||||
|
tb := block.AsThinking()
|
||||||
|
thinkingContent += tb.Thinking
|
||||||
case "text":
|
case "text":
|
||||||
tb := block.AsText()
|
tb := block.AsText()
|
||||||
content += tb.Text
|
content += tb.Text
|
||||||
|
|
@ -182,9 +201,10 @@ func parseClaudeResponse(resp *anthropic.Message) *LLMResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
return &LLMResponse{
|
return &LLMResponse{
|
||||||
Content: content,
|
Content: content,
|
||||||
ToolCalls: toolCalls,
|
ThinkingContent: thinkingContent,
|
||||||
FinishReason: finishReason,
|
ToolCalls: toolCalls,
|
||||||
|
FinishReason: finishReason,
|
||||||
Usage: &UsageInfo{
|
Usage: &UsageInfo{
|
||||||
PromptTokens: int(resp.Usage.InputTokens),
|
PromptTokens: int(resp.Usage.InputTokens),
|
||||||
CompletionTokens: int(resp.Usage.OutputTokens),
|
CompletionTokens: int(resp.Usage.OutputTokens),
|
||||||
|
|
|
||||||
|
|
@ -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{}{
|
requestBody := map[string]interface{}{
|
||||||
"model": model,
|
"model": model,
|
||||||
"messages": messages,
|
"messages": apiMessages,
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(tools) > 0 {
|
if len(tools) > 0 {
|
||||||
|
|
@ -126,8 +158,9 @@ func (p *HTTPProvider) parseResponse(body []byte) (*LLMResponse, error) {
|
||||||
var apiResponse struct {
|
var apiResponse struct {
|
||||||
Choices []struct {
|
Choices []struct {
|
||||||
Message struct {
|
Message struct {
|
||||||
Content string `json:"content"`
|
Content string `json:"content"`
|
||||||
ToolCalls []struct {
|
ReasoningContent string `json:"reasoning_content"`
|
||||||
|
ToolCalls []struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Function *struct {
|
Function *struct {
|
||||||
|
|
@ -185,10 +218,11 @@ func (p *HTTPProvider) parseResponse(body []byte) (*LLMResponse, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return &LLMResponse{
|
return &LLMResponse{
|
||||||
Content: choice.Message.Content,
|
Content: choice.Message.Content,
|
||||||
ToolCalls: toolCalls,
|
ThinkingContent: choice.Message.ReasoningContent,
|
||||||
FinishReason: choice.FinishReason,
|
ToolCalls: toolCalls,
|
||||||
Usage: apiResponse.Usage,
|
FinishReason: choice.FinishReason,
|
||||||
|
Usage: apiResponse.Usage,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,11 @@ type FunctionCall struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type LLMResponse struct {
|
type LLMResponse struct {
|
||||||
Content string `json:"content"`
|
Content string `json:"content"`
|
||||||
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
|
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
|
||||||
FinishReason string `json:"finish_reason"`
|
FinishReason string `json:"finish_reason"`
|
||||||
Usage *UsageInfo `json:"usage,omitempty"`
|
Usage *UsageInfo `json:"usage,omitempty"`
|
||||||
|
ThinkingContent string `json:"thinking_content,omitempty"` // For Claude extended thinking
|
||||||
}
|
}
|
||||||
|
|
||||||
type UsageInfo struct {
|
type UsageInfo struct {
|
||||||
|
|
@ -29,10 +30,11 @@ type UsageInfo struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Message struct {
|
type Message struct {
|
||||||
Role string `json:"role"`
|
Role string `json:"role"`
|
||||||
Content string `json:"content"`
|
Content string `json:"content"`
|
||||||
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
|
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
|
||||||
ToolCallID string `json:"tool_call_id,omitempty"`
|
ToolCallID string `json:"tool_call_id,omitempty"`
|
||||||
|
ThinkingContent string `json:"thinking_content,omitempty"` // For Claude extended thinking
|
||||||
}
|
}
|
||||||
|
|
||||||
type LLMProvider interface {
|
type LLMProvider interface {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue