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 <noreply@anthropic.com>
This commit is contained in:
Badri Narayanan S
2026-01-14 21:04:36 +05:30
parent 97e1d9c417
commit 772dabe7e4
2 changed files with 9 additions and 4 deletions

View File

@@ -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;
}

View File

@@ -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