🛂 fix: Honor Claude Document Limits Through Inference Gateways (#14650)

This commit is contained in:
Danny Avila 2026-08-05 17:38:06 -04:00 • committed by GitHub
parent 489bc02d4a
commit 9b7a30743b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 69 additions and 6 deletions

View file

@ -888,6 +888,60 @@ describe('encodeAndFormatDocuments - fileConfig integration', () => {
expect(mockedGetFileStream).not.toHaveBeenCalled();
});
it('should apply Claude document restrictions through an OpenAI-compatible gateway', async () => {
const req = createMockRequest(30) as ServerRequest;
const file = createMockDocFile(
1,
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'report.xlsx',
);
const result = await encodeAndFormatDocuments(
req,
[file],
{ provider: Providers.OPENAI, model: 'anthropic/claude-sonnet-4-6' },
mockStrategyFunctions,
);
expect(result.documents).toHaveLength(0);
expect(result.files).toHaveLength(0);
expect(mockedGetFileStream).not.toHaveBeenCalled();
});
it('should retain XLSX support for non-Claude OpenAI models', async () => {
const req = createMockRequest(30) as ServerRequest;
const file = createMockDocFile(
1,
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'report.xlsx',
);
const mockContent = Buffer.from('xlsx-content').toString('base64');
mockedGetFileStream.mockResolvedValue({
file,
content: mockContent,
metadata: file,
});
const result = await encodeAndFormatDocuments(
req,
[file],
{ provider: Providers.OPENAI, model: 'gpt-5.4' },
mockStrategyFunctions,
);
expect(result.documents).toMatchObject([
{
type: 'file',
file: {
filename: 'report.xlsx',
file_data: `data:${file.type};base64,${mockContent}`,
},
},
]);
expect(result.files).toEqual([file]);
expect(mockedGetFileStream).toHaveBeenCalledTimes(1);
});
it('should still encode supported Anthropic documents when mixed with unsupported ones', async () => {
const req = createMockRequest(30) as ServerRequest;
const docxFile = createMockDocFile(1, 'application/vnd.ms-excel', 'sheet.xls');

View file

@ -106,15 +106,24 @@ function formatDocumentBlock(
/**
* Filters out files the provider's document path cannot send to the model.
* Anthropic rejects non-PDF base64 documents with a 400 that recurs on every
* retry, so unsupported types are skipped instead of bricking the conversation.
* Claude rejects non-PDF binary documents with a 400 that recurs on every retry,
* including when it is reached through an OpenAI-compatible gateway. Unsupported
* types are skipped instead of bricking the conversation.
*/
function filterProviderDocumentFiles(provider: Providers, files: IMongoFile[]): IMongoFile[] {
function filterProviderDocumentFiles(
provider: Providers,
files: IMongoFile[],
model?: string,
): IMongoFile[] {
if (provider === Providers.BEDROCK) {
return files.filter((file) => isBedrockDocumentType(file.type));
}
if (provider !== Providers.ANTHROPIC) {
const usesAnthropicDocumentCapabilities =
provider === Providers.ANTHROPIC ||
(isOpenAILikeProvider(provider) && model?.toLowerCase().includes('claude'));
if (!usesAnthropicDocumentCapabilities) {
return files;
}
@ -130,7 +139,7 @@ function filterProviderDocumentFiles(provider: Providers, files: IMongoFile[]):
if (skipped.length) {
console.warn(
`Skipping attachment(s) unsupported by Anthropic document input: ${skipped.join(', ')}`,
`Skipping attachment(s) unsupported by Claude document input: ${skipped.join(', ')}`,
);
}
@ -182,7 +191,7 @@ export async function encodeAndFormatDocuments(
return result;
}
const processableFiles = filterProviderDocumentFiles(provider, files);
const processableFiles = filterProviderDocumentFiles(provider, files, model);
if (!processableFiles.length) {
return result;