"use client"; import type React from "react"; import { useRef, useEffect, useState } from "react"; import Image from "next/image"; import { ScrollArea } from "@/components/ui/scroll-area"; import ExamplePanel from "./chat-example-panel"; import { Message } from "ai"; import { convertToLegalXml, replaceNodes } from "@/lib/utils"; import { useDiagram } from "@/contexts/diagram-context"; interface ChatMessageDisplayProps { messages: Message[]; error?: Error | null; setInput: (input: string) => void; setFiles: (files: File[]) => void; } export function ChatMessageDisplay({ messages, error, setInput, setFiles, }: ChatMessageDisplayProps) { const { chartXML, loadDiagram: onDisplayChart } = useDiagram(); const messagesEndRef = useRef(null); const previousXML = useRef(""); const [expandedTools, setExpandedTools] = useState>( {} ); useEffect(() => { if (messagesEndRef.current) { messagesEndRef.current.scrollIntoView({ behavior: "smooth" }); } }, [messages]); // Auto-collapse args when diagrams are generated useEffect(() => { messages.forEach((message) => { if (message.parts) { message.parts.forEach((part) => { if ( part.type === "tool-invocation" && part.toolInvocation.state === "result" ) { const callId = part.toolInvocation.toolCallId; setExpandedTools((prev) => ({ ...prev, [callId]: false, })); } }); } }); }, [messages]); function handleDisplayChart(xml: string) { const currentXml = xml || ""; const convertedXml = convertToLegalXml(currentXml); if (convertedXml !== previousXML.current) { previousXML.current = convertedXml; const replacedXML = replaceNodes(chartXML, convertedXml); onDisplayChart(replacedXML); } } const renderToolInvocation = (toolInvocation: any) => { const callId = toolInvocation.toolCallId; const { toolName, args, state } = toolInvocation; const isExpanded = expandedTools[callId] ?? true; handleDisplayChart(args?.xml); const toggleExpanded = () => { setExpandedTools((prev) => ({ ...prev, [callId]: !isExpanded, })); }; return (
Tool: display_diagram
{args && Object.keys(args).length > 0 && ( )}
{args && isExpanded && (
{typeof args === "object" && Object.keys(args).length > 0 && `Args: ${JSON.stringify(args, null, 2)}`}
)}
{state === "partial-call" ? (
) : state === "result" ? (
Diagram generated
) : null}
); }; return ( {messages.length === 0 ? ( ) : ( messages.map((message) => (
{message.parts ? message.parts.map((part, index) => { switch (part.type) { case "text": return (
{part.text}
); case "tool-invocation": return renderToolInvocation( part.toolInvocation ); default: return null; } }) : message.content}
{message?.experimental_attachments ?.filter((attachment) => attachment?.contentType?.startsWith("image/") ) .map((attachment, index) => (
{
))} {(message as any).function_call && (
Using tool:{" "} {(message as any).function_call.name} ...
)}
)) )} {error && (
Error: {error.message}
)}
); }