import { Plus, EarthIcon } from 'lucide-react'; import { useCallback, useEffect, useRef } from 'react'; import { AgentCapabilities, defaultAgentFormValues } from 'librechat-data-provider'; import type { UseMutationResult, QueryObserverResult } from '@tanstack/react-query'; import type { Agent, AgentCreateParams } from 'librechat-data-provider'; import type { UseFormReset } from 'react-hook-form'; import type { TAgentCapabilities, AgentForm, TAgentOption } from '~/common'; import { cn, createDropdownSetter, createProviderOption, processAgentOption } from '~/utils'; import { useListAgentsQuery, useGetStartupConfig } from '~/data-provider'; import SelectDropDown from '~/components/ui/SelectDropDown'; import { useLocalize } from '~/hooks'; const keys = new Set(Object.keys(defaultAgentFormValues)); export default function AgentSelect({ reset, agentQuery, value: currentAgentValue, selectedAgentId = null, setCurrentAgentId, createMutation, }: { reset: UseFormReset; value?: TAgentOption; selectedAgentId: string | null; agentQuery: QueryObserverResult; setCurrentAgentId: React.Dispatch>; createMutation: UseMutationResult; }) { const localize = useLocalize(); const lastSelectedAgent = useRef(null); const { data: startupConfig } = useGetStartupConfig(); const { data: agents = null } = useListAgentsQuery(undefined, { select: (res) => res.data.map((agent) => processAgentOption({ agent, instanceProjectId: startupConfig?.instanceProjectId, }), ), }); const resetAgentForm = useCallback( (fullAgent: Agent) => { const { instanceProjectId } = startupConfig ?? {}; const isGlobal = (instanceProjectId != null && fullAgent.projectIds?.includes(instanceProjectId)) ?? false; const update = { ...fullAgent, provider: createProviderOption(fullAgent.provider), label: fullAgent.name ?? '', value: fullAgent.id || '', icon: isGlobal ? : null, }; const capabilities: TAgentCapabilities = { [AgentCapabilities.execute_code]: false, [AgentCapabilities.file_search]: false, [AgentCapabilities.end_after_tools]: false, [AgentCapabilities.hide_sequential_outputs]: false, }; const agentTools: string[] = []; (fullAgent.tools ?? []).forEach((tool) => { if (capabilities[tool] !== undefined) { capabilities[tool] = true; return; } agentTools.push(tool); }); const formValues: Partial = { ...capabilities, agent: update, model: update.model, tools: agentTools, }; Object.entries(fullAgent).forEach(([name, value]) => { if (name === 'model_parameters') { formValues[name] = value; return; } if (!keys.has(name)) { return; } if (typeof value !== 'number' && typeof value !== 'object') { formValues[name] = value; } }); reset(formValues); }, [reset, startupConfig], ); const onSelect = useCallback( (selectedId: string) => { const agentExists = !!(selectedId ? (agents ?? []).find((agent) => agent.id === selectedId) : undefined); createMutation.reset(); if (!agentExists) { setCurrentAgentId(undefined); return reset({ ...defaultAgentFormValues, }); } setCurrentAgentId(selectedId); const agent = agentQuery.data; if (!agent) { console.warn('Agent not found'); return; } resetAgentForm(agent); }, [agents, createMutation, setCurrentAgentId, agentQuery.data, resetAgentForm, reset], ); useEffect(() => { if (agentQuery.data && agentQuery.isSuccess) { resetAgentForm(agentQuery.data); } }, [agentQuery.data, agentQuery.isSuccess, resetAgentForm]); useEffect(() => { let timerId: NodeJS.Timeout | null = null; if (selectedAgentId === lastSelectedAgent.current) { return; } if (selectedAgentId != null && selectedAgentId !== '' && agents) { timerId = setTimeout(() => { lastSelectedAgent.current = selectedAgentId; onSelect(selectedAgentId); }, 5); } return () => { if (timerId) { clearTimeout(timerId); } }; }, [selectedAgentId, agents, onSelect]); const createAgent = localize('com_ui_create') + ' ' + localize('com_ui_agent'); const hasAgentValue = !!(typeof currentAgentValue === 'object' ? currentAgentValue.value != null && currentAgentValue.value !== '' : typeof currentAgentValue !== 'undefined'); return ( ( {createAgent} )} /> ); }