📂 fix: Respect supportedMimeTypes Config in File Picker Accept Filter (#12596)

* fix: respect supportedMimeTypes config in file picker accept filter

The browser file picker's accept attribute was hardcoded by provider
identity, ignoring the endpoint's supportedMimeTypes from fileConfig.
Users who configured permissive MIME types (e.g., '.*') still saw a
restrictive filter in the upload dialog.

Add isPermissiveMimeConfig utility that detects wildcard patterns in
the endpoint's supportedMimeTypes. When permissive, the file picker
accept attribute is set to empty (unrestricted). Non-permissive
configs retain the existing provider-based defaults.

Closes #12589

* fix: address review findings for isPermissiveMimeConfig

- Use non-standard MIME namespace probe (x-librechat/x-probe) so
  category-wildcard patterns like ^application\/.*$ no longer
  false-positive as permissive
- Add single-line JSDoc to isPermissiveMimeConfig
- Use !== undefined instead of != null (fileType is never null)
- Add endpointFileConfig to dropdownItems useMemo deps to prevent
  stale closure when config changes without endpoint change
- Add tests for broad application and multi-category patterns

* fix: wrap handleUploadClick in useCallback to satisfy exhaustive-deps

handleUploadClick is captured inside the dropdownItems useMemo but was
not in its dependency array. Wrap it in useCallback with
endpointFileConfig.supportedMimeTypes as the sole dependency, then
reference the stable callback in the useMemo deps.
This commit is contained in:
Danny Avila 2026-04-09 17:43:53 -04:00 committed by GitHub
parent 81275ff0e0
commit daa8f0ea6b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 100 additions and 21 deletions

View file

@ -1,4 +1,4 @@
import React, { useRef, useState, useMemo } from 'react';
import React, { useRef, useState, useMemo, useCallback } from 'react';
import { useRecoilState } from 'recoil';
import * as Ariakit from '@ariakit/react';
import {
@ -19,6 +19,7 @@ import {
Providers,
EToolResources,
EModelEndpoint,
isPermissiveMimeConfig,
defaultAgentCapabilities,
bedrockDocumentExtensions,
isDocumentSupportedProvider,
@ -110,27 +111,35 @@ const AttachFileMenu = ({
ephemeralAgent,
);
const handleUploadClick = (fileType?: FileUploadType) => {
if (!inputRef.current) {
return;
}
inputRef.current.value = '';
if (fileType === 'image') {
inputRef.current.accept = 'image/*,.heif,.heic';
} else if (fileType === 'document') {
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 {
const handleUploadClick = useCallback(
(fileType?: FileUploadType) => {
if (!inputRef.current) {
return;
}
inputRef.current.value = '';
if (
fileType !== undefined &&
isPermissiveMimeConfig(endpointFileConfig?.supportedMimeTypes)
) {
inputRef.current.accept = '';
} else if (fileType === 'image') {
inputRef.current.accept = 'image/*,.heif,.heic';
} else if (fileType === 'document') {
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 {
inputRef.current.accept = '';
}
inputRef.current.click();
inputRef.current.accept = '';
}
inputRef.current.click();
inputRef.current.accept = '';
};
},
[endpointFileConfig?.supportedMimeTypes],
);
const dropdownItems = useMemo(() => {
const createMenuItems = (onAction: (fileType?: FileUploadType) => void) => {
@ -247,6 +256,7 @@ const AttachFileMenu = ({
endpointType,
capabilities,
useResponsesApi,
handleUploadClick,
setToolResource,
setEphemeralAgent,
sharePointEnabled,