Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ describe('generateContentResponseUtilities', () => {
]);
});

it('should handle llmContent with fileData for Gemini 3 model (should be siblings)', () => {
it('should handle llmContent with fileData for Gemini 3 model (should be nested)', () => {
const llmContent: Part = {
fileData: { mimeType: 'application/pdf', fileUri: 'gs://...' },
};
Expand All @@ -174,9 +174,9 @@ describe('generateContentResponseUtilities', () => {
name: toolName,
id: callId,
response: { output: 'Binary content provided (1 item(s)).' },
parts: [llmContent],
},
},
llmContent,
]);
});

Expand All @@ -202,7 +202,7 @@ describe('generateContentResponseUtilities', () => {
]);
});

it('should handle llmContent with fileData for non-Gemini 3 models', () => {
it('should handle llmContent with fileData for non-Gemini 3 models (should omit siblings)', () => {
const llmContent: Part = {
fileData: { mimeType: 'application/pdf', fileUri: 'gs://...' },
};
Expand All @@ -220,7 +220,6 @@ describe('generateContentResponseUtilities', () => {
response: { output: 'Binary content provided (1 item(s)).' },
},
},
llmContent,
]);
});

Expand Down
21 changes: 12 additions & 9 deletions packages/core/src/utils/generateContentResponseUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,17 +97,18 @@ export function convertToFunctionResponse(
};

const isMultimodalFRSupported = supportsMultimodalFunctionResponse(model);
const siblingParts: Part[] = [...fileDataParts];
const siblingParts: Part[] = [];

if (inlineDataParts.length > 0) {
if (isMultimodalFRSupported) {
// Nest inlineData if supported by the model
if (isMultimodalFRSupported) {
const binaryParts = [...fileDataParts, ...inlineDataParts];
if (binaryParts.length > 0) {
// Nest all binary content if supported by the model
(part.functionResponse as unknown as { parts: Part[] }).parts =
inlineDataParts;
} else {
// Otherwise treat as siblings
siblingParts.push(...inlineDataParts);
binaryParts;
}
} else {
// Otherwise treat as siblings (which will be dropped below)
siblingParts.push(...fileDataParts, ...inlineDataParts);
}

// Add descriptive text if the response object is empty but we have binary content
Expand All @@ -122,7 +123,9 @@ export function convertToFunctionResponse(
}

if (siblingParts.length > 0) {
return [part, ...siblingParts];
debugLogger.warn(
`Model ${model} does not support multimodal function responses. Sibling parts will be omitted to prevent API errors in parallel function calling.`,
);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

This logic correctly warns and drops sibling parts for non-multimodal models. However, there's a related issue: the code at lines 115-123 has already added a descriptive text like output: 'Binary content provided (...)' to the response. This message becomes misleading because the binary content is now being dropped. The model will be told binary content is provided when it has actually been omitted.

To fix this, we should clear this misleading message from the response object when we drop the parts and there was no original text content. This will also require updating the test 'should handle llmContent with fileData for non-Gemini 3 models (should omit siblings)' to expect response: {}.

Suggested change
if (siblingParts.length > 0) {
return [part, ...siblingParts];
debugLogger.warn(
`Model ${model} does not support multimodal function responses. Sibling parts will be omitted to prevent API errors in parallel function calling.`,
);
}
if (siblingParts.length > 0) {
debugLogger.warn(
`Model ${model} does not support multimodal function responses. Sibling parts will be omitted to prevent API errors in parallel function calling.`,
);
// If there was no original text, the response object may contain a misleading
// "Binary content provided" message from the dropped parts. Clear it.
if (textParts.length === 0) {
part.functionResponse!.response = {};
}
}


return [part];
Expand Down