feat(providers): add thought_signature support for gemini
Add support for persisting thought_signature metadata from Google/Gemini 3 models. This introduces ExtraContent and GoogleExtra types to handle provider-specific metadata, and ensures thought signatures are properly preserved through the tool call lifecycle.
This commit is contained in:
parent
68cdafc5f2
commit
7f241647be
4 changed files with 54 additions and 14 deletions
|
|
@ -600,21 +600,24 @@ func (al *AgentLoop) runLLMIteration(ctx context.Context, agent *AgentInstance,
|
||||||
}
|
}
|
||||||
for _, tc := range normalizedToolCalls {
|
for _, tc := range normalizedToolCalls {
|
||||||
argumentsJSON, _ := json.Marshal(tc.Arguments)
|
argumentsJSON, _ := json.Marshal(tc.Arguments)
|
||||||
|
// Copy ExtraContent to ensure thought_signature is persisted for Gemini 3
|
||||||
|
extraContent := tc.ExtraContent
|
||||||
thoughtSignature := ""
|
thoughtSignature := ""
|
||||||
if tc.Function != nil {
|
if tc.Function != nil {
|
||||||
thoughtSignature = tc.Function.ThoughtSignature
|
thoughtSignature = tc.Function.ThoughtSignature
|
||||||
}
|
}
|
||||||
|
|
||||||
assistantMsg.ToolCalls = append(assistantMsg.ToolCalls, providers.ToolCall{
|
assistantMsg.ToolCalls = append(assistantMsg.ToolCalls, providers.ToolCall{
|
||||||
ID: tc.ID,
|
ID: tc.ID,
|
||||||
Type: "function",
|
Type: "function",
|
||||||
Name: tc.Name,
|
Name: tc.Name,
|
||||||
Arguments: tc.Arguments,
|
|
||||||
Function: &providers.FunctionCall{
|
Function: &providers.FunctionCall{
|
||||||
Name: tc.Name,
|
Name: tc.Name,
|
||||||
Arguments: string(argumentsJSON),
|
Arguments: string(argumentsJSON),
|
||||||
ThoughtSignature: thoughtSignature,
|
ThoughtSignature: thoughtSignature,
|
||||||
},
|
},
|
||||||
|
ExtraContent: extraContent,
|
||||||
|
ThoughtSignature: thoughtSignature,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
messages = append(messages, assistantMsg)
|
messages = append(messages, assistantMsg)
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@ type UsageInfo = protocoltypes.UsageInfo
|
||||||
type Message = protocoltypes.Message
|
type Message = protocoltypes.Message
|
||||||
type ToolDefinition = protocoltypes.ToolDefinition
|
type ToolDefinition = protocoltypes.ToolDefinition
|
||||||
type ToolFunctionDefinition = protocoltypes.ToolFunctionDefinition
|
type ToolFunctionDefinition = protocoltypes.ToolFunctionDefinition
|
||||||
|
type ExtraContent = protocoltypes.ExtraContent
|
||||||
|
type GoogleExtra = protocoltypes.GoogleExtra
|
||||||
|
|
||||||
type Provider struct {
|
type Provider struct {
|
||||||
apiKey string
|
apiKey string
|
||||||
|
|
@ -145,6 +147,11 @@ func parseResponse(body []byte) (*LLMResponse, error) {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Arguments string `json:"arguments"`
|
Arguments string `json:"arguments"`
|
||||||
} `json:"function"`
|
} `json:"function"`
|
||||||
|
ExtraContent *struct {
|
||||||
|
Google *struct {
|
||||||
|
ThoughtSignature string `json:"thought_signature"`
|
||||||
|
} `json:"google"`
|
||||||
|
} `json:"extra_content"`
|
||||||
} `json:"tool_calls"`
|
} `json:"tool_calls"`
|
||||||
} `json:"message"`
|
} `json:"message"`
|
||||||
FinishReason string `json:"finish_reason"`
|
FinishReason string `json:"finish_reason"`
|
||||||
|
|
@ -169,6 +176,12 @@ func parseResponse(body []byte) (*LLMResponse, error) {
|
||||||
arguments := make(map[string]interface{})
|
arguments := make(map[string]interface{})
|
||||||
name := ""
|
name := ""
|
||||||
|
|
||||||
|
// Extract thought_signature from Gemini/Google-specific extra content
|
||||||
|
thoughtSignature := ""
|
||||||
|
if tc.ExtraContent != nil && tc.ExtraContent.Google != nil {
|
||||||
|
thoughtSignature = tc.ExtraContent.Google.ThoughtSignature
|
||||||
|
}
|
||||||
|
|
||||||
if tc.Function != nil {
|
if tc.Function != nil {
|
||||||
name = tc.Function.Name
|
name = tc.Function.Name
|
||||||
if tc.Function.Arguments != "" {
|
if tc.Function.Arguments != "" {
|
||||||
|
|
@ -179,11 +192,23 @@ func parseResponse(body []byte) (*LLMResponse, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toolCalls = append(toolCalls, ToolCall{
|
// Build ToolCall with ExtraContent for Gemini 3 thought_signature persistence
|
||||||
ID: tc.ID,
|
toolCall := ToolCall{
|
||||||
Name: name,
|
ID: tc.ID,
|
||||||
Arguments: arguments,
|
Name: name,
|
||||||
})
|
Arguments: arguments,
|
||||||
|
ThoughtSignature: thoughtSignature,
|
||||||
|
}
|
||||||
|
|
||||||
|
if thoughtSignature != "" {
|
||||||
|
toolCall.ExtraContent = &ExtraContent{
|
||||||
|
Google: &GoogleExtra{
|
||||||
|
ThoughtSignature: thoughtSignature,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toolCalls = append(toolCalls, toolCall)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &LLMResponse{
|
return &LLMResponse{
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,21 @@
|
||||||
package protocoltypes
|
package protocoltypes
|
||||||
|
|
||||||
type ToolCall struct {
|
type ToolCall struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
Function *FunctionCall `json:"function,omitempty"`
|
Function *FunctionCall `json:"function,omitempty"`
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
Arguments map[string]interface{} `json:"arguments,omitempty"`
|
Arguments map[string]interface{} `json:"arguments,omitempty"`
|
||||||
|
ThoughtSignature string `json:"-"` // Internal use only
|
||||||
|
ExtraContent *ExtraContent `json:"extra_content,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExtraContent struct {
|
||||||
|
Google *GoogleExtra `json:"google,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GoogleExtra struct {
|
||||||
|
ThoughtSignature string `json:"thought_signature,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type FunctionCall struct {
|
type FunctionCall struct {
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ type UsageInfo = protocoltypes.UsageInfo
|
||||||
type Message = protocoltypes.Message
|
type Message = protocoltypes.Message
|
||||||
type ToolDefinition = protocoltypes.ToolDefinition
|
type ToolDefinition = protocoltypes.ToolDefinition
|
||||||
type ToolFunctionDefinition = protocoltypes.ToolFunctionDefinition
|
type ToolFunctionDefinition = protocoltypes.ToolFunctionDefinition
|
||||||
|
type ExtraContent = protocoltypes.ExtraContent
|
||||||
|
type GoogleExtra = protocoltypes.GoogleExtra
|
||||||
|
|
||||||
type LLMProvider interface {
|
type LLMProvider interface {
|
||||||
Chat(ctx context.Context, messages []Message, tools []ToolDefinition, model string, options map[string]interface{}) (*LLMResponse, error)
|
Chat(ctx context.Context, messages []Message, tools []ToolDefinition, model string, options map[string]interface{}) (*LLMResponse, error)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue