import { useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@/components/ui/collapsible"; import { LuChevronsUpDown } from "react-icons/lu"; import type { ToolCall } from "@/types/chat"; type ToolCallsGroupProps = { toolCalls: ToolCall[]; }; function normalizeName(name: string): string { return name .replace(/_/g, " ") .split(" ") .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) .join(" "); } export function ToolCallsGroup({ toolCalls }: ToolCallsGroupProps) { const grouped = useMemo(() => { const map = new Map(); for (const tc of toolCalls) { const existing = map.get(tc.name); if (existing) { existing.push(tc); } else { map.set(tc.name, [tc]); } } return map; }, [toolCalls]); if (toolCalls.length === 0) return null; return (
{[...grouped.entries()].map(([name, calls]) => ( ))}
); } type ToolCallRowProps = { name: string; calls: ToolCall[]; }; function ToolCallRow({ name, calls }: ToolCallRowProps) { const { t } = useTranslation(["views/chat"]); const [open, setOpen] = useState(false); const displayName = normalizeName(name); const label = calls.length > 1 ? `${displayName} (\u00d7${calls.length})` : displayName; return ( {label}
{calls.map((tc, idx) => (
1 ? "space-y-1 border-l-2 border-border pl-3" : "space-y-1" } > {tc.arguments && Object.keys(tc.arguments).length > 0 && (
{t("arguments")}
                    {JSON.stringify(tc.arguments, null, 2)}
                  
)} {tc.response && tc.response !== "" && (
{t("response")}
                    {tc.response}
                  
)}
))}
); }