import React, { useState } from 'react'; import * as Ariakit from '@ariakit/react'; import { ChevronDown } from 'lucide-react'; import { useFormContext } from 'react-hook-form'; import * as AccordionPrimitive from '@radix-ui/react-accordion'; import { useUpdateUserPluginsMutation } from 'librechat-data-provider/react-query'; import { Accordion, AccordionItem, AccordionContent, TrashIcon, CircleHelpIcon, OGDialog, OGDialogTrigger, Label, Checkbox, OGDialogTemplate, useToastContext, } from '@librechat/client'; import type { AgentToolType } from 'librechat-data-provider'; import type { AgentForm } from '~/common'; import { useLocalize } from '~/hooks'; import { cn } from '~/utils'; export default function AgentTool({ tool, allTools, }: { tool: string; allTools?: Record; agent_id?: string; }) { const [isHovering, setIsHovering] = useState(false); const [isFocused, setIsFocused] = useState(false); const [hoveredToolId, setHoveredToolId] = useState(null); const [accordionValue, setAccordionValue] = useState(''); const localize = useLocalize(); const { showToast } = useToastContext(); const updateUserPlugins = useUpdateUserPluginsMutation(); const { getValues, setValue } = useFormContext(); if (!allTools) { return null; } const currentTool = allTools[tool]; const getSelectedTools = () => { if (!currentTool?.tools) return []; const formTools = getValues('tools') || []; return currentTool.tools.filter((t) => formTools.includes(t.tool_id)).map((t) => t.tool_id); }; const updateFormTools = (newSelectedTools: string[]) => { const currentTools = getValues('tools') || []; const otherTools = currentTools.filter( (t: string) => !currentTool?.tools?.some((st) => st.tool_id === t), ); setValue('tools', [...otherTools, ...newSelectedTools]); }; const removeTool = (toolId: string) => { if (toolId) { const toolIdsToRemove = isGroup && currentTool.tools ? [toolId, ...currentTool.tools.map((t) => t.tool_id)] : [toolId]; updateUserPlugins.mutate( { pluginKey: toolId, action: 'uninstall', auth: {}, isEntityTool: true }, { onError: (error: unknown) => { showToast({ message: `Error while deleting the tool: ${error}`, status: 'error' }); }, onSuccess: () => { const remainingToolIds = getValues('tools')?.filter( (toolId: string) => !toolIdsToRemove.includes(toolId), ); setValue('tools', remainingToolIds); showToast({ message: 'Tool deleted successfully', status: 'success' }); }, }, ); } }; if (!currentTool) { return null; } const isGroup = currentTool.tools && currentTool.tools.length > 0; const selectedTools = getSelectedTools(); const isExpanded = accordionValue === currentTool.tool_id; if (!isGroup) { return (
setIsHovering(true)} onMouseLeave={() => setIsHovering(false)} onFocus={() => setIsFocused(true)} onBlur={(e) => { // Check if focus is moving to a child element if (!e.currentTarget.contains(e.relatedTarget)) { setIsFocused(false); } }} >
{currentTool.metadata.icon && (
)}
{currentTool.metadata.name}
{localize('com_ui_delete_tool_confirm')} } selection={{ selectHandler: () => removeTool(currentTool.tool_id), selectClasses: 'bg-red-700 dark:bg-red-600 hover:bg-red-800 dark:hover:bg-red-800 transition-color duration-200 text-white', selectText: localize('com_ui_delete'), }} /> ); } // Group tool with accordion return (
setIsHovering(true)} onMouseLeave={() => setIsHovering(false)} onFocus={() => setIsFocused(true)} onBlur={(e) => { // Check if focus is moving to a child element if (!e.currentTarget.contains(e.relatedTarget)) { setIsFocused(false); } }} >
{currentTool.tools?.map((subTool) => ( ))}
{localize('com_ui_delete_tool_confirm')} } selection={{ selectHandler: () => removeTool(currentTool.tool_id), selectClasses: 'bg-red-700 dark:bg-red-600 hover:bg-red-800 dark:hover:bg-red-800 transition-color duration-200 text-white', selectText: localize('com_ui_delete'), }} />
); }