fix: handle unsigned thinking blocks in tool loops (#120)

When Claude Code strips thinking signatures it doesn't recognize,
the proxy would drop unsigned thinking blocks, causing the error
"Expected thinking but found text". This fix detects unsigned
thinking blocks and triggers recovery to close the tool loop.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Badri Narayanan S
2026-01-14 23:01:13 +05:30
parent dee7512bd8
commit fa29de7183
5 changed files with 171 additions and 6 deletions

View File

@@ -16,6 +16,7 @@ import {
reorderAssistantContent,
filterUnsignedThinkingBlocks,
hasGeminiHistory,
hasUnsignedThinkingBlocks,
needsThinkingRecovery,
closeToolLoopForThinking
} from './thinking-utils.js';
@@ -87,10 +88,11 @@ export function convertAnthropicToGoogle(anthropicRequest) {
processedMessages = closeToolLoopForThinking(messages, 'gemini');
}
// For Claude: apply recovery only for cross-model (Gemini→Claude) switch
// Detected by checking if history has Gemini-style tool_use with thoughtSignature
if (isClaudeModel && isThinking && hasGeminiHistory(messages) && needsThinkingRecovery(messages)) {
logger.debug('[RequestConverter] Applying thinking recovery for Claude (cross-model from Gemini)');
// For Claude: apply recovery for cross-model (Gemini→Claude) or unsigned thinking blocks
// Unsigned thinking blocks occur when Claude Code strips signatures it doesn't understand
const needsClaudeRecovery = hasGeminiHistory(messages) || hasUnsignedThinkingBlocks(messages);
if (isClaudeModel && isThinking && needsClaudeRecovery && needsThinkingRecovery(messages)) {
logger.debug('[RequestConverter] Applying thinking recovery for Claude');
processedMessages = closeToolLoopForThinking(messages, 'claude');
}