From 12e427e9d5b7b6ffc8e992caced7e9f9833ebe2f Mon Sep 17 00:00:00 2001 From: Badri Narayanan S Date: Sat, 3 Jan 2026 23:24:52 +0530 Subject: [PATCH] Fix needsThinkingRecovery to require tool loop context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/format/request-converter.js | 2 +- src/format/thinking-utils.js | 21 +++++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/format/request-converter.js b/src/format/request-converter.js index fa2d920..98a378c 100644 --- a/src/format/request-converter.js +++ b/src/format/request-converter.js @@ -83,7 +83,7 @@ export function convertAnthropicToGoogle(anthropicRequest) { let processedMessages = messages; const targetFamily = isClaudeModel ? 'claude' : isGeminiModel ? 'gemini' : null; - if (isThinking && targetFamily && needsThinkingRecovery(messages, targetFamily)) { + if (isThinking && targetFamily && needsThinkingRecovery(messages)) { logger.debug(`[RequestConverter] Applying thinking recovery for ${targetFamily}`); processedMessages = closeToolLoopForThinking(messages, targetFamily); } diff --git a/src/format/thinking-utils.js b/src/format/thinking-utils.js index 9017a8c..3dcf883 100644 --- a/src/format/thinking-utils.js +++ b/src/format/thinking-utils.js @@ -388,23 +388,24 @@ export function analyzeConversationState(messages) { /** * Check if conversation needs thinking recovery. * - * For Gemini: recovery needed when (tool loop OR interrupted tool) AND no valid thinking - * For Claude: recovery needed when no valid compatible thinking (cross-model detection) + * Recovery is only needed when: + * 1. We're in a tool loop or have an interrupted tool, AND + * 2. No valid thinking blocks exist in the current turn + * + * Cross-model signature compatibility is handled by stripInvalidThinkingBlocks + * during recovery (not here). * * @param {Array} messages - Array of messages - * @param {string} targetFamily - Target model family ('claude' or 'gemini') * @returns {boolean} True if thinking recovery is needed */ -export function needsThinkingRecovery(messages, targetFamily = null) { +export function needsThinkingRecovery(messages) { const state = analyzeConversationState(messages); - if (targetFamily === 'claude') { - // Claude: only check if thinking is valid/compatible - return !state.turnHasThinking; - } + // Recovery is only needed in tool loops or interrupted tools + if (!state.inToolLoop && !state.interruptedTool) return false; - // Gemini (default): check tool loop/interrupted AND no thinking - return (state.inToolLoop || state.interruptedTool) && !state.turnHasThinking; + // Need recovery if no valid thinking blocks exist + return !state.turnHasThinking; } /**