Skip to content

Commit 6378e7c

Browse files
FL4TLiN3claude
andcommitted
fix: preserve providerMetadata on tool call parts for thought_signature
The previous fix only handled thought_signature on reasoning parts, but Gemini 3 also requires thought_signature on functionCall parts in the conversation history. This was the actual root cause of the "Function call is missing a thought_signature" error. - Add providerMetadata field to ToolCallPart schema - Preserve providerMetadata from AI SDK tool call results - Pass providerMetadata as providerOptions when converting back to AI SDK messages Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent a04e339 commit 6378e7c

File tree

3 files changed

+13
-1
lines changed

3 files changed

+13
-1
lines changed

packages/core/src/schemas/message-part.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,13 +129,16 @@ export interface ToolCallPart extends BasePart {
129129
toolName: string
130130
/** Arguments to pass to the tool */
131131
args: Record<string, unknown>
132+
/** Provider-specific metadata for this tool call (e.g., Google thought_signature) */
133+
providerMetadata?: Record<string, Record<string, unknown>>
132134
}
133135

134136
export const toolCallPartSchema = basePartSchema.extend({
135137
type: z.literal("toolCallPart"),
136138
toolCallId: z.string(),
137139
toolName: z.string(),
138140
args: z.record(z.string(), z.unknown()),
141+
providerMetadata: z.record(z.string(), z.record(z.string(), z.unknown())).optional(),
139142
})
140143
toolCallPartSchema satisfies z.ZodType<ToolCallPart>
141144

packages/runtime/src/messages/message.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ function toolCallPartToCoreToolCallPart(part: ToolCallPart): ToolCallModelPart {
237237
toolCallId: part.toolCallId,
238238
toolName: part.toolName,
239239
input: part.args,
240+
providerOptions: part.providerMetadata as ToolCallModelPart["providerOptions"],
240241
}
241242
}
242243
function thinkingPartToCoreThinkingPart(part: ThinkingPart): {

packages/runtime/src/state-machine/states/generating-tool-call.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,16 @@ type ClassifiedToolCall = {
3434
toolName: string
3535
input: Record<string, unknown>
3636
adapter: SkillAdapter
37+
providerMetadata?: Record<string, Record<string, unknown>>
3738
}
3839

3940
function classifyToolCalls(
40-
toolCalls: Array<{ toolCallId: string; toolName: string; input: unknown }>,
41+
toolCalls: Array<{
42+
toolCallId: string
43+
toolName: string
44+
input: unknown
45+
providerMetadata?: Record<string, Record<string, unknown>>
46+
}>,
4147
skillManager: SkillManager,
4248
): ClassifiedToolCall[] {
4349
return toolCalls.map((tc) => {
@@ -47,6 +53,7 @@ function classifyToolCalls(
4753
toolName: tc.toolName,
4854
input: tc.input as Record<string, unknown>,
4955
adapter,
56+
providerMetadata: tc.providerMetadata,
5057
}
5158
})
5259
}
@@ -64,6 +71,7 @@ function buildToolCallParts(toolCalls: ClassifiedToolCall[]): Array<Omit<ToolCal
6471
toolCallId: tc.toolCallId,
6572
toolName: tc.toolName,
6673
args: tc.input,
74+
providerMetadata: tc.providerMetadata,
6775
}))
6876
}
6977

0 commit comments

Comments
 (0)