From 772dabe7e47b8d15e9464236eddd8b0eafb4829b Mon Sep 17 00:00:00 2001 From: Badri Narayanan S Date: Wed, 14 Jan 2026 21:04:36 +0530 Subject: [PATCH] fix: defer inlineData parts to end of array for parallel tool calls (#91) When multiple tool_results contain images, the inlineData parts were being interleaved between functionResponse parts, breaking Claude's API requirement that functionResponse parts be consecutive. Co-Authored-By: Claude --- src/format/content-converter.js | 10 ++++++++-- src/format/request-converter.js | 3 +-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/format/content-converter.js b/src/format/content-converter.js index 8599847..98f5c0d 100644 --- a/src/format/content-converter.js +++ b/src/format/content-converter.js @@ -35,6 +35,7 @@ export function convertContentToParts(content, isClaudeModel = false, isGeminiMo } const parts = []; + const deferredInlineData = []; // Collect inlineData to add at the end (Issue #91) for (const block of content) { if (!block) continue; @@ -152,8 +153,9 @@ export function convertContentToParts(content, isClaudeModel = false, isGeminiMo parts.push({ functionResponse }); - // Add any images from the tool result as separate parts - parts.push(...imageParts); + // Defer images from the tool result to end of parts array (Issue #91) + // This ensures all functionResponse parts are consecutive + deferredInlineData.push(...imageParts); } else if (block.type === 'thinking') { // Handle thinking blocks with signature compatibility check if (block.signature && block.signature.length >= MIN_SIGNATURE_LENGTH) { @@ -183,5 +185,9 @@ export function convertContentToParts(content, isClaudeModel = false, isGeminiMo } } + // Add deferred inlineData at the end (Issue #91) + // This ensures functionResponse parts are consecutive, which Claude's API requires + parts.push(...deferredInlineData); + return parts; } diff --git a/src/format/request-converter.js b/src/format/request-converter.js index a03bfc8..5225422 100644 --- a/src/format/request-converter.js +++ b/src/format/request-converter.js @@ -95,8 +95,7 @@ export function convertAnthropicToGoogle(anthropicRequest) { } // Convert messages to contents, then filter unsigned thinking blocks - for (let i = 0; i < processedMessages.length; i++) { - const msg = processedMessages[i]; + for (const msg of processedMessages) { let msgContent = msg.content; // For assistant messages, process thinking blocks and reorder content