fix: preserve extra_content for Gemini 3 thought_signature support#5267
Conversation
🦋 Changeset detectedLatest commit: 543050c The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
6fe7ba4 to
ea3fb9d
Compare
ea3fb9d to
1467783
Compare
| name: toolCall.function?.name, | ||
| arguments: toolCall.function?.arguments, | ||
| // Preserve extra_content for Gemini 3 thought_signature support | ||
| extra_content: (toolCall as any).extra_content, |
There was a problem hiding this comment.
[WARNING]: Unvalidated as any cast on untrusted API response data
(toolCall as any).extra_content extracts an arbitrary property from the API stream response without any validation. This value flows through the entire pipeline and is eventually sent back to the API in subsequent requests.
Consider adding minimal validation (e.g., checking it's a plain object) to prevent unexpected data types from propagating:
const rawExtra = (toolCall as Record<string, unknown>).extra_content
extra_content: rawExtra != null && typeof rawExtra === 'object' && !Array.isArray(rawExtra)
? rawExtra as Record<string, unknown>
: undefined,| } | ||
| seenToolUseIds.add(sanitizedId) | ||
| assistantContent.push({ | ||
| const toolUseBlock: any = { |
There was a problem hiding this comment.
[WARNING]: Type safety regression — const toolUseBlock: any loses type checking
The previous code pushed a typed object literal directly into assistantContent (typed as Array<Anthropic.ContentBlockParam>). Changing to any disables all type checking on this object.
Consider using an intersection type instead to preserve type safety while allowing the extra property:
const toolUseBlock: Anthropic.ToolUseBlockParam & { extra_content?: Record<string, unknown> } = {
type: "tool_use" as const,
id: sanitizedId,
name: mcpBlock.name,
input: mcpBlock.arguments,
}The same applies to the second toolUseBlock: any on line 3828.
Code Review SummaryStatus: 3 Issues Found | Recommendation: Address before merge Fix these issues in Kilo Cloud Overview
Issue Details (click to expand)WARNING
Other Observations (not in diff)Issues found in unchanged code or cross-cutting concerns that cannot receive inline comments:
Files Reviewed (7 files)
|
| }, | ||
| } | ||
| // Preserve extra_content for Gemini 3 thought_signature support | ||
| const toolMessageWithExtra = toolMessage as any |
There was a problem hiding this comment.
[WARNING]: Unvalidated as any cast on toolMessage to access extra_content
Same pattern as in openai.ts:528. The toolMessage is typed as Anthropic.ToolUseBlockParam which doesn't include extra_content. Consider adding a type guard or extending the type with an intersection to avoid silently accepting any shape:
interface ToolUseBlockWithExtra extends Anthropic.ToolUseBlockParam {
extra_content?: Record<string, unknown>
}
const toolMessageWithExtra = toolMessage as ToolUseBlockWithExtraThis would provide compile-time safety while still allowing the extra field.
Context
This PR adds support for preserving
extra_content(including Gemini 3'sthought_signature) throughout the tool call lifecycle.Gemini 3 models include
extra_contentwiththought_signaturein tool call responses. This metadata was being lost during multi-turn conversations, potentially affecting model coherence and performance.Implementation
extra_contentfield toToolUse,McpToolUse, and streaming interfacesextra_contentin OpenAI and OpenRouter providers during streamingextra_contentthrough message format conversionextra_contentduring tool call streaming lifecycle in Task.tsChanges:
src/api/providers/openai.ts- Extract and preserveextra_contentsrc/api/providers/openrouter.ts- Extract and preserveextra_contentsrc/api/transform/openai-format.ts- Includeextra_contentin conversionsrc/api/transform/stream.ts- Addextra_contentto streaming interfacessrc/core/assistant-message/NativeToolCallParser.ts- Parse and trackextra_contentsrc/core/task/Task.ts- Preserveextra_contentin tool call event handlingsrc/shared/tools.ts- Addextra_contenttoToolUseandMcpToolUseinterfacesBackward Compatibility:
All changes are backward compatible:
extra_contentis optional (?)extra_contentcontinue to work unchangedScreenshots
How to Test
Get in Touch