Skip to content

Commit bea6a42

Browse files
authored
Merge pull request #265 from Opencode-DCP/fix/gemini-thought-signature-injection
fix: use text injection for Gemini models to avoid thought signature errors
2 parents 018a0d6 + a2ae844 commit bea6a42

File tree

1 file changed

+44
-18
lines changed

1 file changed

+44
-18
lines changed

lib/messages/utils.ts

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,58 @@ const SYNTHETIC_MESSAGE_ID = "msg_01234567890123456789012345"
77
const SYNTHETIC_PART_ID = "prt_01234567890123456789012345"
88
const SYNTHETIC_CALL_ID = "call_01234567890123456789012345"
99

10+
const isGeminiModel = (modelID: string): boolean => {
11+
const lowerModelID = modelID.toLowerCase()
12+
return lowerModelID.includes("gemini")
13+
}
14+
1015
export const createSyntheticAssistantMessageWithToolPart = (
1116
baseMessage: WithParts,
1217
content: string,
1318
variant?: string,
1419
): WithParts => {
1520
const userInfo = baseMessage.info as UserMessage
1621
const now = Date.now()
17-
return {
18-
info: {
19-
id: SYNTHETIC_MESSAGE_ID,
20-
sessionID: userInfo.sessionID,
21-
role: "assistant",
22-
agent: userInfo.agent || "code",
23-
parentID: userInfo.id,
24-
modelID: userInfo.model.modelID,
25-
providerID: userInfo.model.providerID,
26-
mode: "default",
27-
path: {
28-
cwd: "/",
29-
root: "/",
30-
},
31-
time: { created: now, completed: now },
32-
cost: 0,
33-
tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } },
34-
...(variant !== undefined && { variant }),
22+
23+
const baseInfo = {
24+
id: SYNTHETIC_MESSAGE_ID,
25+
sessionID: userInfo.sessionID,
26+
role: "assistant" as const,
27+
agent: userInfo.agent || "code",
28+
parentID: userInfo.id,
29+
modelID: userInfo.model.modelID,
30+
providerID: userInfo.model.providerID,
31+
mode: "default",
32+
path: {
33+
cwd: "/",
34+
root: "/",
3535
},
36+
time: { created: now, completed: now },
37+
cost: 0,
38+
tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } },
39+
...(variant !== undefined && { variant }),
40+
}
41+
42+
// For Gemini models, inject as text to avoid thought signature requirements
43+
// Gemini 3+ has strict validation requiring thoughtSignature on functionCall parts
44+
if (isGeminiModel(userInfo.model.modelID)) {
45+
return {
46+
info: baseInfo,
47+
parts: [
48+
{
49+
id: SYNTHETIC_PART_ID,
50+
sessionID: userInfo.sessionID,
51+
messageID: SYNTHETIC_MESSAGE_ID,
52+
type: "text",
53+
text: content,
54+
},
55+
],
56+
}
57+
}
58+
59+
// For other models, use tool part for cleaner context
60+
return {
61+
info: baseInfo,
3662
parts: [
3763
{
3864
id: SYNTHETIC_PART_ID,

0 commit comments

Comments
 (0)