From 33915fb712ecb0dccbdfe2e31617251aa6a983e1 Mon Sep 17 00:00:00 2001 From: mrbeandev Date: Mon, 16 Feb 2026 17:40:23 +0530 Subject: [PATCH] fix(gemini): preserve thought_signature in tool calls to prevent 400 errors --- pkg/agent/loop.go | 10 ++++++++-- pkg/providers/http_provider.go | 26 +++++++++++++------------- pkg/providers/types.go | 5 +++-- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/pkg/agent/loop.go b/pkg/agent/loop.go index d3afa298e..edbd1d6a3 100644 --- a/pkg/agent/loop.go +++ b/pkg/agent/loop.go @@ -624,12 +624,18 @@ func (al *AgentLoop) runLLMIteration(ctx context.Context, messages []providers.M } for _, tc := range response.ToolCalls { argumentsJSON, _ := json.Marshal(tc.Arguments) + thoughtSignature := "" + if tc.Function != nil { + thoughtSignature = tc.Function.ThoughtSignature + } + assistantMsg.ToolCalls = append(assistantMsg.ToolCalls, providers.ToolCall{ ID: tc.ID, Type: "function", Function: &providers.FunctionCall{ - Name: tc.Name, - Arguments: string(argumentsJSON), + Name: tc.Name, + Arguments: string(argumentsJSON), + ThoughtSignature: thoughtSignature, }, }) } diff --git a/pkg/providers/http_provider.go b/pkg/providers/http_provider.go index 4cf2c6db2..a72df6087 100644 --- a/pkg/providers/http_provider.go +++ b/pkg/providers/http_provider.go @@ -132,8 +132,9 @@ func (p *HTTPProvider) parseResponse(body []byte) (*LLMResponse, error) { ID string `json:"id"` Type string `json:"type"` Function *struct { - Name string `json:"name"` - Arguments string `json:"arguments"` + Name string `json:"name"` + Arguments string `json:"arguments"` + ThoughtSignature string `json:"thought_signature"` } `json:"function"` } `json:"tool_calls"` } `json:"message"` @@ -159,18 +160,11 @@ func (p *HTTPProvider) parseResponse(body []byte) (*LLMResponse, error) { for _, tc := range choice.Message.ToolCalls { arguments := make(map[string]interface{}) name := "" + thoughtSignature := "" - // Handle OpenAI format with nested function object - if tc.Type == "function" && tc.Function != nil { - name = tc.Function.Name - if tc.Function.Arguments != "" { - if err := json.Unmarshal([]byte(tc.Function.Arguments), &arguments); err != nil { - arguments["raw"] = tc.Function.Arguments - } - } - } else if tc.Function != nil { - // Legacy format without type field + if tc.Function != nil { name = tc.Function.Name + thoughtSignature = tc.Function.ThoughtSignature if tc.Function.Arguments != "" { if err := json.Unmarshal([]byte(tc.Function.Arguments), &arguments); err != nil { arguments["raw"] = tc.Function.Arguments @@ -179,7 +173,13 @@ func (p *HTTPProvider) parseResponse(body []byte) (*LLMResponse, error) { } toolCalls = append(toolCalls, ToolCall{ - ID: tc.ID, + ID: tc.ID, + Type: tc.Type, + Function: &FunctionCall{ + Name: name, + Arguments: tc.Function.Arguments, + ThoughtSignature: thoughtSignature, + }, Name: name, Arguments: arguments, }) diff --git a/pkg/providers/types.go b/pkg/providers/types.go index 88b62e975..107331d9e 100644 --- a/pkg/providers/types.go +++ b/pkg/providers/types.go @@ -11,8 +11,9 @@ type ToolCall struct { } type FunctionCall struct { - Name string `json:"name"` - Arguments string `json:"arguments"` + Name string `json:"name"` + Arguments string `json:"arguments"` + ThoughtSignature string `json:"thought_signature,omitempty"` } type LLMResponse struct {