"use client"; import { useCallback, useMemo, useRef, useState } from "react"; import { useTranslations } from "next-intl"; import { ChatMention } from "app-types/chat"; import { DefaultToolName } from "lib/ai/tools"; import { cn, noop } from "lib/utils"; import equal from "lib/equal"; import { ChevronDownIcon, HammerIcon, Loader, XIcon } from "lucide-react"; import { ChatMentionInputSuggestion } from "@/components/chat-mention-input"; import { DefaultToolIcon } from "@/components/default-tool-icon"; import { MCPIcon } from "ui/mcp-icon"; import { Avatar, AvatarFallback, AvatarImage } from "ui/avatar"; interface AgentToolSelectorProps { mentions: ChatMention[]; isLoading?: boolean; disabled?: boolean; hasEditAccess?: boolean; onChange: (mentions: ChatMention[]) => void; } export function AgentToolSelector({ mentions, isLoading = false, disabled = false, hasEditAccess = true, onChange, }: AgentToolSelectorProps) { const t = useTranslations(); const triggerRef = useRef(null); const [open, setOpen] = useState(false); const triggerRect = useMemo(() => { return triggerRef.current?.getBoundingClientRect(); }, [open]); const handleSelectMention = useCallback( (item: { label: string; id: string }) => { const mention = JSON.parse(item.id) as ChatMention; const newMentions = [...mentions]; const index = newMentions.findIndex((m) => equal(m, mention)); if (index !== -1) { newMentions.splice(index, 1); } else { newMentions.push(mention); } onChange(newMentions); }, [mentions, onChange], ); const handleDeleteMention = useCallback( (mention: ChatMention) => { onChange(mentions.filter((m) => !equal(m, mention))); }, [mentions, onChange], ); const selectedIds = useMemo(() => { return mentions.map((m) => JSON.stringify(m)); }, [mentions]); const selectedMentions = useMemo(() => { return mentions.map((m, i) => (
{ e.stopPropagation(); if (hasEditAccess) { handleDeleteMention(m); } }} >
{m.type === "defaultTool" ? ( ) : m.type === "mcpServer" ? ( ) : m.type === "workflow" ? ( {m.name.slice(0, 1)} ) : ( )}
{m.name} {hasEditAccess && ( )}
)); }, [mentions, hasEditAccess, handleDeleteMention]); return ( hasEditAccess && !disabled && setOpen(newOpen)} top={0} left={0} selectedIds={selectedIds} style={{ width: triggerRect?.width ?? 0, }} >
{isLoading ? ( {t("Agent.loadingTools")} ) : selectedMentions.length === 0 ? ( {t("Agent.addTools")} ) : ( selectedMentions )}
{isLoading ? ( ) : ( )}
); }