| import debounce from 'lodash/debounce'; |
| import { FileSources, EToolResources, removeNullishValues } from 'librechat-data-provider'; |
| import { useCallback, useState, useEffect } from 'react'; |
| import type * as t from 'librechat-data-provider'; |
| import type { UseMutateAsyncFunction } from '@tanstack/react-query'; |
| import type { ExtendedFile, GenericSetter } from '~/common'; |
| import useSetFilesToDelete from './useSetFilesToDelete'; |
|
|
| type FileMapSetter = GenericSetter<Map<string, ExtendedFile>>; |
|
|
| const useFileDeletion = ({ |
| mutateAsync, |
| agent_id, |
| assistant_id, |
| tool_resource, |
| }: { |
| mutateAsync: UseMutateAsyncFunction<t.DeleteFilesResponse, unknown, t.DeleteFilesBody, unknown>; |
| agent_id?: string; |
| assistant_id?: string; |
| tool_resource?: EToolResources; |
| }) => { |
| const [_batch, setFileDeleteBatch] = useState<t.BatchFile[]>([]); |
| const setFilesToDelete = useSetFilesToDelete(); |
|
|
| const executeBatchDelete = useCallback( |
| ({ |
| filesToDelete, |
| agent_id, |
| assistant_id, |
| tool_resource, |
| }: { |
| filesToDelete: t.BatchFile[]; |
| agent_id?: string; |
| assistant_id?: string; |
| tool_resource?: EToolResources; |
| }) => { |
| const payload = removeNullishValues({ |
| agent_id, |
| assistant_id, |
| tool_resource, |
| }); |
| console.log('Deleting files:', filesToDelete, payload); |
| mutateAsync({ files: filesToDelete, ...payload }); |
| setFileDeleteBatch([]); |
| }, |
| [mutateAsync], |
| ); |
|
|
| |
| const debouncedDelete = useCallback(debounce(executeBatchDelete, 1000), []); |
|
|
| useEffect(() => { |
| |
| return () => debouncedDelete.cancel(); |
| }, [debouncedDelete]); |
|
|
| const deleteFile = useCallback( |
| ({ file: _file, setFiles }: { file: ExtendedFile | t.TFile; setFiles?: FileMapSetter }) => { |
| const { |
| file_id, |
| temp_file_id = '', |
| filepath = '', |
| source = FileSources.local, |
| embedded, |
| attached = false, |
| } = _file as t.TFile & { attached?: boolean }; |
|
|
| const progress = _file['progress'] ?? 1; |
|
|
| if (progress < 1) { |
| return; |
| } |
| const file: t.BatchFile = { |
| file_id, |
| embedded, |
| filepath, |
| source, |
| }; |
|
|
| if (setFiles) { |
| setFiles((currentFiles) => { |
| const updatedFiles = new Map(currentFiles); |
| updatedFiles.delete(file_id); |
| updatedFiles.delete(temp_file_id); |
| const files = Object.fromEntries(updatedFiles); |
| setFilesToDelete(files); |
| return updatedFiles; |
| }); |
| } |
|
|
| if (attached) { |
| return; |
| } |
|
|
| setFileDeleteBatch((prevBatch) => { |
| const newBatch = [...prevBatch, file]; |
| debouncedDelete({ |
| filesToDelete: newBatch, |
| agent_id, |
| assistant_id, |
| tool_resource, |
| }); |
| return newBatch; |
| }); |
| }, |
| [debouncedDelete, setFilesToDelete, agent_id, assistant_id, tool_resource], |
| ); |
|
|
| const deleteFiles = useCallback( |
| ({ files, setFiles }: { files: ExtendedFile[] | t.TFile[]; setFiles?: FileMapSetter }) => { |
| const batchFiles: t.BatchFile[] = []; |
| for (const _file of files) { |
| const { |
| file_id, |
| embedded, |
| temp_file_id, |
| filepath = '', |
| source = FileSources.local, |
| } = _file; |
|
|
| batchFiles.push({ |
| source, |
| file_id, |
| filepath, |
| temp_file_id, |
| embedded: embedded ?? false, |
| }); |
| } |
|
|
| if (setFiles) { |
| setFiles((currentFiles) => { |
| const updatedFiles = new Map(currentFiles); |
| batchFiles.forEach((file) => { |
| updatedFiles.delete(file.file_id); |
| if (file.temp_file_id) { |
| updatedFiles.delete(file.temp_file_id); |
| } |
| }); |
| const filesToUpdate = Object.fromEntries(updatedFiles); |
| setFilesToDelete(filesToUpdate); |
| return updatedFiles; |
| }); |
| } |
|
|
| setFileDeleteBatch((prevBatch) => { |
| const newBatch = [...prevBatch, ...batchFiles]; |
| debouncedDelete({ |
| filesToDelete: newBatch, |
| agent_id, |
| assistant_id, |
| }); |
| return newBatch; |
| }); |
| }, |
| [debouncedDelete, setFilesToDelete, agent_id, assistant_id], |
| ); |
|
|
| return { deleteFile, deleteFiles }; |
| }; |
|
|
| export default useFileDeletion; |
|
|