import { Plus } from 'lucide-react'; import { useCallback, useEffect, useRef } from 'react'; import { defaultAssistantFormValues, defaultOrderQuery, FileSources, } from 'librechat-data-provider'; import type { UseFormReset } from 'react-hook-form'; import type { UseMutationResult } from '@tanstack/react-query'; import type { Assistant, AssistantCreateParams } from 'librechat-data-provider'; import type { AssistantForm, Actions, TAssistantOption, ExtendedFile } from '~/common'; import SelectDropDown from '~/components/ui/SelectDropDown'; import { useListAssistantsQuery } from '~/data-provider'; import { useFileMapContext } from '~/Providers'; import { useLocalize } from '~/hooks'; import { cn } from '~/utils/'; const keys = new Set(['name', 'id', 'description', 'instructions', 'model']); export default function AssistantSelect({ reset, value, selectedAssistant, setCurrentAssistantId, createMutation, }: { reset: UseFormReset; value: TAssistantOption; selectedAssistant: string | null; setCurrentAssistantId: React.Dispatch>; createMutation: UseMutationResult; }) { const localize = useLocalize(); const fileMap = useFileMapContext(); const lastSelectedAssistant = useRef(null); const assistants = useListAssistantsQuery(defaultOrderQuery, { select: (res) => res.data.map((_assistant) => { const assistant = { ..._assistant, label: _assistant?.name ?? '', value: _assistant.id, files: _assistant?.file_ids ? ([] as Array<[string, ExtendedFile]>) : undefined, }; if (assistant.files && _assistant.file_ids) { _assistant.file_ids.forEach((file_id) => { const file = fileMap?.[file_id]; if (file) { assistant.files?.push([ file_id, { file_id: file.file_id, type: file.type, filepath: file.filepath, filename: file.filename, width: file.width, height: file.height, size: file.bytes, preview: file.filepath, progress: 1, source: FileSources.openai, }, ]); } }); } return assistant; }), }); const onSelect = useCallback( (value: string) => { const assistant = assistants.data?.find((assistant) => assistant.id === value); createMutation.reset(); if (!assistant) { setCurrentAssistantId(undefined); return reset(defaultAssistantFormValues); } const update = { ...assistant, label: assistant?.name ?? '', value: assistant?.id ?? '', }; const actions: Actions = { code_interpreter: false, retrieval: false, }; assistant?.tools ?.filter((tool) => tool.type !== 'function') ?.map((tool) => tool.type) .forEach((tool) => { actions[tool] = true; }); const functions = assistant?.tools ?.filter((tool) => tool.type === 'function') ?.map((tool) => tool.function?.name ?? '') ?? []; const formValues: Partial = { functions, ...actions, assistant: update, }; Object.entries(assistant).forEach(([name, value]) => { if (typeof value === 'number') { return; } else if (typeof value === 'object') { return; } if (keys.has(name)) { formValues[name] = value; } }); reset(formValues); setCurrentAssistantId(assistant?.id); }, [assistants.data, reset, setCurrentAssistantId, createMutation], ); useEffect(() => { let timerId: NodeJS.Timeout | null = null; if (selectedAssistant === lastSelectedAssistant.current) { return; } if (selectedAssistant && assistants.data) { timerId = setTimeout(() => { lastSelectedAssistant.current = selectedAssistant; onSelect(selectedAssistant); }, 5); } return () => { if (timerId) { clearTimeout(timerId); } }; }, [selectedAssistant, assistants.data, onSelect]); const createAssistant = localize('com_ui_create') + ' ' + localize('com_ui_assistant'); return ( ( {createAssistant} )} /> ); }