mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-19 18:00:15 +01:00
✨ refactor: Integrate Capabilities into Agent File Uploads and Tool Handling (#5048)
* refactor: support drag/drop files for agents, handle undefined tool_resource edge cases * refactor: consolidate endpoints config logic to dedicated getter * refactor: Enhance agent tools loading logic to respect capabilities and filter tools accordingly * refactor: Integrate endpoint capabilities into file upload dropdown for dynamic resource handling * refactor: Implement capability checks for agent file upload operations * fix: non-image tool_resource check
This commit is contained in:
parent
d68c874db4
commit
3fbbcb1cfe
17 changed files with 449 additions and 189 deletions
|
|
@ -1,42 +1,76 @@
|
|||
import { useState, useMemo } from 'react';
|
||||
import { useDrop } from 'react-dnd';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { NativeTypes } from 'react-dnd-html5-backend';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import {
|
||||
isAgentsEndpoint,
|
||||
EModelEndpoint,
|
||||
AgentCapabilities,
|
||||
QueryKeys,
|
||||
} from 'librechat-data-provider';
|
||||
import type * as t from 'librechat-data-provider';
|
||||
import type { DropTargetMonitor } from 'react-dnd';
|
||||
import useFileHandling from './useFileHandling';
|
||||
import store from '~/store';
|
||||
|
||||
export default function useDragHelpers() {
|
||||
const { files, handleFiles } = useFileHandling();
|
||||
const queryClient = useQueryClient();
|
||||
const { handleFiles } = useFileHandling();
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const [draggedFiles, setDraggedFiles] = useState<File[]>([]);
|
||||
const conversation = useRecoilValue(store.conversationByIndex(0)) || undefined;
|
||||
|
||||
const handleOptionSelect = (toolResource: string | undefined) => {
|
||||
handleFiles(draggedFiles, toolResource);
|
||||
setShowModal(false);
|
||||
setDraggedFiles([]);
|
||||
};
|
||||
|
||||
const isAgents = useMemo(
|
||||
() => isAgentsEndpoint(conversation?.endpoint),
|
||||
[conversation?.endpoint],
|
||||
);
|
||||
|
||||
const [{ canDrop, isOver }, drop] = useDrop(
|
||||
() => ({
|
||||
accept: [NativeTypes.FILE],
|
||||
drop(item: { files: File[] }) {
|
||||
console.log('drop', item.files);
|
||||
handleFiles(item.files);
|
||||
},
|
||||
canDrop() {
|
||||
// console.log('canDrop', item.files, item.items);
|
||||
return true;
|
||||
},
|
||||
// hover() {
|
||||
// // console.log('hover', item.files, item.items);
|
||||
// },
|
||||
collect: (monitor: DropTargetMonitor) => {
|
||||
// const item = monitor.getItem() as File[];
|
||||
// if (item) {
|
||||
// console.log('collect', item.files, item.items);
|
||||
// }
|
||||
if (!isAgents) {
|
||||
handleFiles(item.files);
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
isOver: monitor.isOver(),
|
||||
canDrop: monitor.canDrop(),
|
||||
};
|
||||
const endpointsConfig = queryClient.getQueryData<t.TEndpointsConfig>([QueryKeys.endpoints]);
|
||||
const agentsConfig = endpointsConfig?.[EModelEndpoint.agents];
|
||||
const codeEnabled =
|
||||
agentsConfig?.capabilities?.includes(AgentCapabilities.execute_code) === true;
|
||||
const fileSearchEnabled =
|
||||
agentsConfig?.capabilities?.includes(AgentCapabilities.file_search) === true;
|
||||
if (!codeEnabled && !fileSearchEnabled) {
|
||||
handleFiles(item.files);
|
||||
return;
|
||||
}
|
||||
setDraggedFiles(item.files);
|
||||
setShowModal(true);
|
||||
},
|
||||
canDrop: () => true,
|
||||
collect: (monitor: DropTargetMonitor) => ({
|
||||
isOver: monitor.isOver(),
|
||||
canDrop: monitor.canDrop(),
|
||||
}),
|
||||
}),
|
||||
[files],
|
||||
[],
|
||||
);
|
||||
|
||||
return {
|
||||
canDrop,
|
||||
isOver,
|
||||
drop,
|
||||
showModal,
|
||||
setShowModal,
|
||||
draggedFiles,
|
||||
handleOptionSelect,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,8 +187,9 @@ const useFileHandling = (params?: UseFileHandling) => {
|
|||
if (!agent_id) {
|
||||
formData.append('message_file', 'true');
|
||||
}
|
||||
if (toolResource != null) {
|
||||
formData.append('tool_resource', toolResource);
|
||||
const tool_resource = extendedFile.tool_resource ?? toolResource;
|
||||
if (tool_resource != null) {
|
||||
formData.append('tool_resource', tool_resource);
|
||||
}
|
||||
if (conversation?.agent_id != null && formData.get('agent_id') == null) {
|
||||
formData.append('agent_id', conversation.agent_id);
|
||||
|
|
@ -327,7 +328,7 @@ const useFileHandling = (params?: UseFileHandling) => {
|
|||
img.src = preview;
|
||||
};
|
||||
|
||||
const handleFiles = async (_files: FileList | File[]) => {
|
||||
const handleFiles = async (_files: FileList | File[], _toolResource?: string) => {
|
||||
abortControllerRef.current = new AbortController();
|
||||
const fileList = Array.from(_files);
|
||||
/* Validate files */
|
||||
|
|
@ -358,9 +359,22 @@ const useFileHandling = (params?: UseFileHandling) => {
|
|||
size: originalFile.size,
|
||||
};
|
||||
|
||||
if (_toolResource != null && _toolResource !== '') {
|
||||
extendedFile.tool_resource = _toolResource;
|
||||
}
|
||||
|
||||
const isImage = originalFile.type.split('/')[0] === 'image';
|
||||
const tool_resource =
|
||||
extendedFile.tool_resource ?? params?.additionalMetadata?.tool_resource ?? toolResource;
|
||||
if (isAgentsEndpoint(endpoint) && !isImage && tool_resource == null) {
|
||||
/** Note: this needs to be removed when we can support files to providers */
|
||||
setError('com_error_files_unsupported_capability');
|
||||
continue;
|
||||
}
|
||||
|
||||
addFile(extendedFile);
|
||||
|
||||
if (originalFile.type.split('/')[0] === 'image') {
|
||||
if (isImage) {
|
||||
loadImage(extendedFile, preview);
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue