diff --git a/go/plugins/googlegenai/gemini.go b/go/plugins/googlegenai/gemini.go index c7e49a8bec..d4d48dd9a1 100644 --- a/go/plugins/googlegenai/gemini.go +++ b/go/plugins/googlegenai/gemini.go @@ -807,6 +807,7 @@ func translateCandidate(cand *genai.Candidate) (*ai.ModelResponse, error) { if part.FileData != nil { partFound++ p = ai.NewMediaPart(part.FileData.MIMEType, part.FileData.FileURI) + } if part.FunctionCall != nil { partFound++ @@ -836,6 +837,13 @@ func translateCandidate(cand *genai.Candidate) (*ai.ModelResponse, error) { continue } + if len(part.ThoughtSignature) > 0 { + if p.Metadata == nil { + p.Metadata = make(map[string]any) + } + p.Metadata["signature"] = part.ThoughtSignature + } + msg.Content = append(msg.Content, p) } m.Message = msg @@ -892,37 +900,33 @@ func toGeminiParts(parts []*ai.Part) ([]*genai.Part, error) { // toGeminiPart converts a [ai.Part] to a [genai.Part]. func toGeminiPart(p *ai.Part) (*genai.Part, error) { + var gp *genai.Part switch { case p.IsReasoning(): - // TODO: go-genai does not support genai.NewPartFromThought() - signature := []byte{} - if p.Metadata != nil { - if sig, ok := p.Metadata["signature"].([]byte); ok { - signature = sig - } + // NOTE: go-genai does not support genai.NewPartFromThought() + gp = &genai.Part{ + Thought: true, + Text: p.Text, } - return &genai.Part{ - Thought: true, - Text: p.Text, - ThoughtSignature: signature, - }, nil case p.IsText(): - return genai.NewPartFromText(p.Text), nil + gp = genai.NewPartFromText(p.Text) case p.IsMedia(): if strings.HasPrefix(p.Text, "data:") { contentType, data, err := uri.Data(p) if err != nil { return nil, err } - return genai.NewPartFromBytes(data, contentType), nil + gp = genai.NewPartFromBytes(data, contentType) + } else { + gp = genai.NewPartFromURI(p.Text, p.ContentType) } - return genai.NewPartFromURI(p.Text, p.ContentType), nil case p.IsData(): contentType, data, err := uri.Data(p) if err != nil { return nil, err } - return genai.NewPartFromBytes(data, contentType), nil + gp = genai.NewPartFromBytes(data, contentType) + case p.IsToolResponse(): toolResp := p.ToolResponse var output map[string]any @@ -934,8 +938,7 @@ func toGeminiPart(p *ai.Part) (*genai.Part, error) { "content": toolResp.Output, } } - fr := genai.NewPartFromFunctionResponse(toolResp.Name, output) - return fr, nil + gp = genai.NewPartFromFunctionResponse(toolResp.Name, output) case p.IsToolRequest(): toolReq := p.ToolRequest var input map[string]any @@ -946,11 +949,19 @@ func toGeminiPart(p *ai.Part) (*genai.Part, error) { "input": toolReq.Input, } } - fc := genai.NewPartFromFunctionCall(toolReq.Name, input) - return fc, nil + gp = genai.NewPartFromFunctionCall(toolReq.Name, input) + default: - panic("unknown part type in a request") + return nil, fmt.Errorf("unknown part in the request: %q", p.Kind) } + + if p.Metadata != nil { + if sig, ok := p.Metadata["signature"].([]byte); ok { + gp.ThoughtSignature = sig + } + } + + return gp, nil } // validToolName checks whether the provided tool name matches the