"use client" import { Check, ChevronDown, ChevronUp, Copy, Cpu } from "lucide-react" import type { Dispatch, SetStateAction } from "react" import { CodeBlock } from "@/components/code-block" import { isMxCellXmlComplete } from "@/lib/utils" import type { DiagramOperation, ToolPartLike } from "./types" interface ToolCallCardProps { part: ToolPartLike expandedTools: Record setExpandedTools: Dispatch>> onCopy: (callId: string, text: string, isToolCall: boolean) => void copiedToolCallId: string | null copyFailedToolCallId: string | null dict: { tools: { complete: string } chat: { copied: string; failedToCopy: string; copyResponse: string } } } function OperationsDisplay({ operations }: { operations: DiagramOperation[] }) { return (
{operations.map((op, index) => (
{op.operation} cell_id: {op.cell_id}
{op.new_xml && (
                                {op.new_xml}
                            
)}
))}
) } export function ToolCallCard({ part, expandedTools, setExpandedTools, onCopy, copiedToolCallId, copyFailedToolCallId, dict, }: ToolCallCardProps) { const callId = part.toolCallId const { state, input, output } = part // Default to collapsed if tool is complete, expanded if still streaming const isExpanded = expandedTools[callId] ?? state !== "output-available" const toolName = part.type?.replace("tool-", "") const isCopied = copiedToolCallId === callId const toggleExpanded = () => { setExpandedTools((prev) => ({ ...prev, [callId]: !isExpanded, })) } const getToolDisplayName = (name: string) => { switch (name) { case "display_diagram": return "Generate Diagram" case "edit_diagram": return "Edit Diagram" case "get_shape_library": return "Get Shape Library" default: return name } } const handleCopy = () => { let textToCopy = "" if (input && typeof input === "object") { if (input.xml) { textToCopy = input.xml } else if (input.operations && Array.isArray(input.operations)) { textToCopy = JSON.stringify(input.operations, null, 2) } else if (Object.keys(input).length > 0) { textToCopy = JSON.stringify(input, null, 2) } } if ( output && toolName === "get_shape_library" && typeof output === "string" ) { textToCopy = output } if (textToCopy) { onCopy(callId, textToCopy, true) } } return (
{getToolDisplayName(toolName)}
{state === "input-streaming" && (
)} {state === "output-available" && ( <> {dict.tools.complete} {isExpanded && ( )} )} {state === "output-error" && (() => { // Check if this is a truncation (incomplete XML) vs real error const isTruncated = (toolName === "display_diagram" || toolName === "append_diagram") && !isMxCellXmlComplete(input?.xml) return isTruncated ? ( Truncated ) : ( Error ) })()} {input && Object.keys(input).length > 0 && ( )}
{input && isExpanded && (
{typeof input === "object" && input.xml ? ( ) : typeof input === "object" && input.operations && Array.isArray(input.operations) ? ( ) : typeof input === "object" && Object.keys(input).length > 0 ? ( ) : null}
)} {output && state === "output-error" && (() => { const isTruncated = (toolName === "display_diagram" || toolName === "append_diagram") && !isMxCellXmlComplete(input?.xml) return (
{isTruncated ? "Output truncated due to length limits. Try a simpler request or increase the maxOutputLength." : output}
) })()} {/* Show get_shape_library output on success */} {output && toolName === "get_shape_library" && state === "output-available" && isExpanded && (
Library loaded ( {typeof output === "string" ? output.length : 0}{" "} chars)
                            {typeof output === "string"
                                ? output.substring(0, 800) +
                                  (output.length > 800 ? "\n..." : "")
                                : String(output)}
                        
)}
) }