import { EarthIcon } from 'lucide-react'; import { useCallback, useEffect, useRef } from 'react'; import { useFormContext, Controller } from 'react-hook-form'; 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 { TAgentCapabilities, AgentForm } from '~/common'; import { cn, createProviderOption, processAgentOption, getDefaultAgentFormValues } from '~/utils'; import { useListAgentsQuery, useGetStartupConfig } from '~/data-provider'; import ControlCombobox from '~/components/ui/ControlCombobox'; import { useLocalize } from '~/hooks'; const keys = new Set(Object.keys(defaultAgentFormValues)); export default function AgentSelect({ agentQuery, selectedAgentId = null, setCurrentAgentId, createMutation, }: { selectedAgentId: string | null; agentQuery: QueryObserverResult; setCurrentAgentId: React.Dispatch>; createMutation: UseMutationResult; }) { const localize = useLocalize(); const lastSelectedAgent = useRef(null); const { control, reset } = useFormContext(); const { data: startupConfig } = useGetStartupConfig(); const { data: agents = null } = useListAgentsQuery(undefined, { select: (res) => res.data.map((agent) => processAgentOption({ agent: { ...agent, name: agent.name || agent.id, }, instanceProjectId: startupConfig?.instanceProjectId, }), ), }); const resetAgentForm = useCallback( (fullAgent: Agent) => { const isGlobal = fullAgent.isPublic ?? false; const update = { ...fullAgent, provider: createProviderOption(fullAgent.provider), label: fullAgent.name ?? '', value: fullAgent.id || '', icon: isGlobal ? : null, }; const capabilities: TAgentCapabilities = { [AgentCapabilities.web_search]: false, [AgentCapabilities.file_search]: false, [AgentCapabilities.execute_code]: 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, // Ensure the category is properly set for the form category: fullAgent.category || 'general', // Make sure support_contact is properly loaded support_contact: fullAgent.support_contact, }; Object.entries(fullAgent).forEach(([name, value]) => { if (name === 'model_parameters') { formValues[name] = value; return; } if (capabilities[name] !== undefined) { formValues[name] = value; return; } if ( name === 'agent_ids' && Array.isArray(value) && value.every((item) => typeof item === 'string') ) { formValues[name] = value; return; } if (!keys.has(name)) { return; } if (name === 'recursion_limit' && typeof value === 'number') { formValues[name] = value; 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(getDefaultAgentFormValues()); } 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'); return ( ( ({ label: agent.name ?? '', value: agent.id ?? '', icon: agent.icon, })) ?? [ { label: 'Loading...', value: '', }, ] } className={cn( 'z-50 flex h-[40px] w-full flex-none items-center justify-center truncate rounded-md bg-transparent font-bold', )} ariaLabel={localize('com_ui_agent')} isCollapsed={false} showCarat={true} /> )} /> ); }