📂 refactor: Cleanup File Filtering Logic, Improve Validation (#10414)

* feat: add filterFilesByEndpointConfig to filter disabled file processing by provider

* chore: explicit define of endpointFileConfig for better debugging

* refactor: move `normalizeEndpointName` to data-provider as used app-wide

* chore: remove overrideEndpoint from useFileHandling

* refactor: improve endpoint file config selection

* refactor: update filterFilesByEndpointConfig to accept structured parameters and improve endpoint file config handling

* refactor: replace defaultFileConfig with getEndpointFileConfig for improved file configuration handling across components

* test: add comprehensive unit tests for getEndpointFileConfig to validate endpoint configuration handling

* refactor: streamline agent endpoint assignment and improve file filtering logic

* feat: add error handling for disabled file uploads in endpoint configuration

* refactor: update encodeAndFormat functions to accept structured parameters for provider and endpoint

* refactor: streamline requestFiles handling in initializeAgent function

* fix: getEndpointFileConfig partial config merging scenarios

* refactor: enhance mergeWithDefault function to support document-supported providers with comprehensive MIME types

* refactor: user-configured default file config in getEndpointFileConfig

* fix: prevent file handling when endpoint is disabled and file is dragged to chat

* refactor: move `getEndpointField` to `data-provider` and update usage across components and hooks

* fix: prioritize endpointType based on agent.endpoint in file filtering logic

* fix: prioritize agent.endpoint in file filtering logic and remove unnecessary endpointType defaulting
This commit is contained in:
Danny Avila 2025-11-10 19:05:30 -05:00 committed by GitHub
parent 06c060b983
commit 2524d33362
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
62 changed files with 2352 additions and 290 deletions

View file

@ -1,4 +1,4 @@
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import React, { useCallback, useEffect, useRef, useMemo, useState } from 'react';
import { v4 } from 'uuid';
import { useSetRecoilState } from 'recoil';
import { useToastContext } from '@librechat/client';
@ -6,16 +6,14 @@ import { useQueryClient } from '@tanstack/react-query';
import {
QueryKeys,
Constants,
EModelEndpoint,
EToolResources,
mergeFileConfig,
isAgentsEndpoint,
isAssistantsEndpoint,
getEndpointFileConfig,
defaultAssistantsVersion,
fileConfig as defaultFileConfig,
} from 'librechat-data-provider';
import debounce from 'lodash/debounce';
import type { EndpointFileConfig, TEndpointsConfig, TError } from 'librechat-data-provider';
import type { TEndpointsConfig, TError } from 'librechat-data-provider';
import type { ExtendedFile, FileSetter } from '~/common';
import { useGetFileConfig, useUploadFileMutation } from '~/data-provider';
import useLocalize, { TranslationKeys } from '~/hooks/useLocalize';
@ -29,9 +27,7 @@ import useUpdateFiles from './useUpdateFiles';
type UseFileHandling = {
fileSetter?: FileSetter;
overrideEndpoint?: EModelEndpoint;
fileFilter?: (file: File) => boolean;
overrideEndpointFileConfig?: EndpointFileConfig;
additionalMetadata?: Record<string, string | undefined>;
};
@ -54,17 +50,13 @@ const useFileHandling = (params?: UseFileHandling) => {
const agent_id = params?.additionalMetadata?.agent_id ?? '';
const assistant_id = params?.additionalMetadata?.assistant_id ?? '';
const endpointType = useMemo(() => conversation?.endpointType, [conversation?.endpointType]);
const endpoint = useMemo(() => conversation?.endpoint ?? 'default', [conversation?.endpoint]);
const { data: fileConfig = null } = useGetFileConfig({
select: (data) => mergeFileConfig(data),
});
const endpoint = useMemo(
() =>
params?.overrideEndpoint ?? conversation?.endpointType ?? conversation?.endpoint ?? 'default',
[params?.overrideEndpoint, conversation?.endpointType, conversation?.endpoint],
);
const displayToast = useCallback(() => {
if (errors.length > 1) {
// TODO: this should not be a dynamic localize input!!
@ -169,10 +161,7 @@ const useFileHandling = (params?: UseFileHandling) => {
const formData = new FormData();
formData.append('endpoint', endpoint);
formData.append(
'original_endpoint',
conversation?.endpointType || conversation?.endpoint || '',
);
formData.append('endpointType', endpointType ?? '');
formData.append('file', extendedFile.file as File, encodeURIComponent(filename));
formData.append('file_id', extendedFile.file_id);
@ -194,7 +183,7 @@ const useFileHandling = (params?: UseFileHandling) => {
}
}
if (isAgentsEndpoint(endpoint)) {
if (!isAssistantsEndpoint(endpointType ?? endpoint)) {
if (!agent_id) {
formData.append('message_file', 'true');
}
@ -205,9 +194,7 @@ const useFileHandling = (params?: UseFileHandling) => {
if (conversation?.agent_id != null && formData.get('agent_id') == null) {
formData.append('agent_id', conversation.agent_id);
}
}
if (!isAssistantsEndpoint(endpoint)) {
uploadFile.mutate(formData);
return;
}
@ -264,18 +251,19 @@ const useFileHandling = (params?: UseFileHandling) => {
/* Validate files */
let filesAreValid: boolean;
try {
const endpointFileConfig = getEndpointFileConfig({
endpoint,
fileConfig,
endpointType,
});
filesAreValid = validateFiles({
files,
fileList,
setError,
endpointFileConfig:
params?.overrideEndpointFileConfig ??
fileConfig?.endpoints?.[endpoint] ??
fileConfig?.endpoints?.default ??
defaultFileConfig.endpoints[endpoint] ??
defaultFileConfig.endpoints.default,
fileConfig,
endpointFileConfig,
toolResource: _toolResource,
fileConfig: fileConfig,
});
} catch (error) {
console.error('file validation error', error);