🪨 feat: AWS Bedrock Document Uploads (#11912)
Some checks are pending
Docker Dev Branch Images Build / build (Dockerfile, lc-dev, node) (push) Waiting to run
Docker Dev Branch Images Build / build (Dockerfile.multi, lc-dev-api, api-build) (push) Waiting to run
Docker Dev Images Build / build (Dockerfile, librechat-dev, node) (push) Waiting to run
Docker Dev Images Build / build (Dockerfile.multi, librechat-dev-api, api-build) (push) Waiting to run
Sync Locize Translations & Create Translation PR / Sync Translation Keys with Locize (push) Waiting to run
Sync Locize Translations & Create Translation PR / Create Translation PR on Version Published (push) Blocked by required conditions

* feat: add aws bedrock upload to provider support

* chore: address copilot comments

* feat: add shared Bedrock document format types and MIME mapping

Bedrock Converse API accepts 9 document formats beyond PDF. Add
BedrockDocumentFormat union type, MIME-to-format mapping, and helpers
in data-provider so both client and backend can reference them.

* refactor: generalize Bedrock PDF validation to support all document types

Rename validateBedrockPdf to validateBedrockDocument with MIME-aware
logic: 4.5MB hard limit applies to all types, PDF header check only
runs for application/pdf. Adds test coverage for non-PDF documents.

* feat: support all Bedrock document formats in encoding pipeline

Widen file type gates to accept csv, doc, docx, xls, xlsx, html, txt,
md for Bedrock. Uses shared MIME-to-format map instead of hardcoded
'pdf'. Other providers' PDF-only paths remain unchanged.

* feat: expand Bedrock file upload UI to accept all document types

Add 'image_document_extended' upload type for Bedrock with accept
filters for all 9 supported formats. Update drag-and-drop validation
to use isBedrockDocumentType helper.

* fix: route Bedrock document types through provider pipeline
This commit is contained in:
Dustin Healy 2026-02-23 19:32:44 -08:00 committed by GitHub
parent b349f2f876
commit 1d0a4c501f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 528 additions and 47 deletions

View file

@ -8,13 +8,6 @@ import {
FileImageIcon,
TerminalSquareIcon,
} from 'lucide-react';
import {
Providers,
EToolResources,
EModelEndpoint,
defaultAgentCapabilities,
isDocumentSupportedProvider,
} from 'librechat-data-provider';
import {
FileUpload,
TooltipAnchor,
@ -22,6 +15,14 @@ import {
AttachmentIcon,
SharePointIcon,
} from '@librechat/client';
import {
Providers,
EToolResources,
EModelEndpoint,
defaultAgentCapabilities,
bedrockDocumentExtensions,
isDocumentSupportedProvider,
} from 'librechat-data-provider';
import type { EndpointFileConfig } from 'librechat-data-provider';
import {
useAgentToolPermissions,
@ -37,7 +38,12 @@ import { ephemeralAgentByConvoId } from '~/store';
import { MenuItemProps } from '~/common';
import { cn } from '~/utils';
type FileUploadType = 'image' | 'document' | 'image_document' | 'image_document_video_audio';
type FileUploadType =
| 'image'
| 'document'
| 'image_document'
| 'image_document_extended'
| 'image_document_video_audio';
interface AttachFileMenuProps {
agentId?: string | null;
@ -99,6 +105,8 @@ const AttachFileMenu = ({
inputRef.current.accept = '.pdf,application/pdf';
} else if (fileType === 'image_document') {
inputRef.current.accept = 'image/*,.heif,.heic,.pdf,application/pdf';
} else if (fileType === 'image_document_extended') {
inputRef.current.accept = `image/*,.heif,.heic,${bedrockDocumentExtensions}`;
} else if (fileType === 'image_document_video_audio') {
inputRef.current.accept = 'image/*,.heif,.heic,.pdf,application/pdf,video/*,audio/*';
} else {
@ -134,6 +142,11 @@ const AttachFileMenu = ({
let fileType: Exclude<FileUploadType, 'image' | 'document'> = 'image_document';
if (currentProvider === Providers.GOOGLE || currentProvider === Providers.OPENROUTER) {
fileType = 'image_document_video_audio';
} else if (
currentProvider === Providers.BEDROCK ||
endpointType === EModelEndpoint.bedrock
) {
fileType = 'image_document_extended';
}
onAction(fileType);
},

View file

@ -1,14 +1,6 @@
import React, { useMemo } from 'react';
import { useRecoilValue } from 'recoil';
import { OGDialog, OGDialogTemplate } from '@librechat/client';
import {
Providers,
inferMimeType,
EToolResources,
EModelEndpoint,
defaultAgentCapabilities,
isDocumentSupportedProvider,
} from 'librechat-data-provider';
import {
ImageUpIcon,
FileSearch,
@ -16,6 +8,15 @@ import {
FileImageIcon,
TerminalSquareIcon,
} from 'lucide-react';
import {
Providers,
inferMimeType,
EToolResources,
EModelEndpoint,
isBedrockDocumentType,
defaultAgentCapabilities,
isDocumentSupportedProvider,
} from 'librechat-data-provider';
import {
useAgentToolPermissions,
useAgentCapabilities,
@ -77,20 +78,26 @@ const DragDropModal = ({ onOptionSelect, setShowModal, files, isVisible }: DragD
) {
const supportsImageDocVideoAudio =
currentProvider === EModelEndpoint.google || currentProvider === Providers.OPENROUTER;
const validFileTypes = supportsImageDocVideoAudio
? files.every((file) => {
const type = getFileType(file);
return (
type?.startsWith('image/') ||
type?.startsWith('video/') ||
type?.startsWith('audio/') ||
type === 'application/pdf'
);
})
: files.every((file) => {
const type = getFileType(file);
return type?.startsWith('image/') || type === 'application/pdf';
});
const isBedrock =
currentProvider === Providers.BEDROCK || endpointType === EModelEndpoint.bedrock;
const isValidProviderFile = (file: File): boolean => {
const type = getFileType(file);
if (supportsImageDocVideoAudio) {
return (
type?.startsWith('image/') ||
type?.startsWith('video/') ||
type?.startsWith('audio/') ||
type === 'application/pdf'
);
}
if (isBedrock) {
return type?.startsWith('image/') || isBedrockDocumentType(type);
}
return type?.startsWith('image/') || type === 'application/pdf';
};
const validFileTypes = files.every(isValidProviderFile);
_options.push({
label: localize('com_ui_upload_provider'),