mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
fix(gemini): split model messages with mixed signed/unsigned thoughtSignature parts
Gemini API rejects requests where parts WITH thoughtSignature and parts WITHOUT coexist in the same Content message (400 error). This happens when an assistant message has both plain text (no signature) and functionCall parts (with signature). The fix splits such messages into two Content objects: unsigned parts first, signed parts second. Reference: https://ai.google.dev/gemini-api/docs/thought-signatures "Don't merge one part with a signature with another part without a signature"
This commit is contained in:
parent
44fd975b17
commit
dec135545e
1 changed files with 30 additions and 6 deletions
|
|
@ -180,6 +180,17 @@ export function convertAnthropicContentToGemini(
|
|||
return parts
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an Anthropic message to Gemini Content objects.
|
||||
*
|
||||
* For model (assistant) messages, Gemini requires that parts WITH thoughtSignature
|
||||
* and parts WITHOUT are NOT mixed in the same Content. When a message contains
|
||||
* both (e.g. text without signature + functionCall with signature), we split them
|
||||
* into separate Content objects: unsigned first, signed second.
|
||||
*
|
||||
* Reference: https://ai.google.dev/gemini-api/docs/thought-signatures
|
||||
* "Don't merge one part with a signature with another part without a signature"
|
||||
*/
|
||||
export function convertAnthropicMessageToGemini(
|
||||
message: Anthropic.Messages.MessageParam,
|
||||
options?: { includeThoughtSignatures?: boolean; toolIdToName?: Map<string, string> },
|
||||
|
|
@ -190,10 +201,23 @@ export function convertAnthropicMessageToGemini(
|
|||
return []
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
role: message.role === "assistant" ? "model" : "user",
|
||||
parts,
|
||||
},
|
||||
]
|
||||
const role = message.role === "assistant" ? "model" : "user"
|
||||
|
||||
// Only split model messages — user messages don't have thoughtSignature concerns
|
||||
if (role === "model" && parts.length > 1) {
|
||||
const signed = parts.filter((p) => "thoughtSignature" in p && (p as PartWithThoughtSignature).thoughtSignature)
|
||||
const unsigned = parts.filter(
|
||||
(p) => !("thoughtSignature" in p && (p as PartWithThoughtSignature).thoughtSignature),
|
||||
)
|
||||
|
||||
if (signed.length > 0 && unsigned.length > 0) {
|
||||
// Split: unsigned parts first (text), then signed parts (functionCall/thinking)
|
||||
return [
|
||||
{ role, parts: unsigned },
|
||||
{ role, parts: signed },
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
return [{ role, parts }]
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue