"use client"; import { CopilotKit, useCoAgent, useCoAgentStateRender, useCopilotAction, } from "@copilotkit/react-core"; import { CopilotChat } from "@copilotkit/react-ui"; import { useCallback, useEffect, useState } from "react"; import "@copilotkit/react-ui/styles.css"; import CitationBlock from "./CitationBlock"; import DbInfo from "./DbInfo"; import SettingsPanel, { STORAGE_KEY } from "./SettingsPanel"; // Must match AGUI_STATE_KEY from haiku.rag.agents.chat const AGUI_STATE_KEY = "haiku.rag.chat"; interface Citation { index: number; document_id: string; chunk_id: string; document_uri: string; document_title: string | null; page_numbers: number[]; headings: string[] | null; content: string; } interface QAResponse { question: string; answer: string; confidence: number; citations: Citation[]; } interface ChatSessionState { session_id: string; citations: Citation[]; qa_history: QAResponse[]; background_context: string | null; } // AG-UI state is namespaced under AGUI_STATE_KEY interface AgentState { [AGUI_STATE_KEY]?: ChatSessionState; } function SpinnerIcon() { return ( ); } function CheckIcon() { return ( ); } function SearchIcon() { return ( ); } function MessageIcon() { return ( ); } function FileIcon() { return ( ); } function SettingsIcon() { return ( ); } function ToolCallIndicator({ toolName, status, args, }: { toolName: string; status: string; args: Record; }) { const isComplete = status === "complete"; const getToolIcon = () => { switch (toolName) { case "search": return ; case "ask": return ; case "get_document": return ; default: return ; } }; const getToolLabel = () => { switch (toolName) { case "search": return "Search"; case "ask": return "Ask"; case "get_document": return "Document"; default: return toolName; } }; const getDescription = () => { switch (toolName) { case "search": { const query = args.query as string; const docName = args.document_name as string | undefined; return ( <> {query} {docName && ( {" "} in {docName} )} > ); } case "ask": { const question = args.question as string; const docName = args.document_name as string | undefined; return ( <> {question} {docName && ( {" "} from {docName} )} > ); } case "get_document": return {args.query as string}; default: return Processing...; } }; return ( {isComplete ? : } {getToolIcon()} {getToolLabel()} {isComplete ? "Done" : "Working..."} {getDescription()} ); } function ChatContentInner({ backgroundContext, setBackgroundContext, }: { backgroundContext: string; setBackgroundContext: (value: string) => void; }) { const [settingsOpen, setSettingsOpen] = useState(false); const handleSaveContext = useCallback( (value: string) => { setBackgroundContext(value); if (value) { localStorage.setItem(STORAGE_KEY, value); } else { localStorage.removeItem(STORAGE_KEY); } }, [setBackgroundContext], ); useCoAgent({ name: "chat_agent", initialState: { [AGUI_STATE_KEY]: { session_id: "", citations: [], qa_history: [], background_context: backgroundContext || null, }, }, }); useCoAgentStateRender({ name: "chat_agent", render: ({ state }) => { const chatState = state[AGUI_STATE_KEY]; if (chatState?.citations.length) { return ; } return null; }, }); useCopilotAction({ name: "search", available: "disabled", parameters: [ { name: "query", type: "string" }, { name: "document_name", type: "string" }, ], render: ({ status, args }) => ( } /> ), }); useCopilotAction({ name: "ask", available: "disabled", parameters: [ { name: "question", type: "string" }, { name: "document_name", type: "string" }, ], render: ({ status, args }) => ( } /> ), }); useCopilotAction({ name: "get_document", available: "disabled", parameters: [{ name: "query", type: "string" }], render: ({ status, args }) => ( } /> ), }); return ( <> setSettingsOpen(true)} title={ backgroundContext ? "Background context is set" : "Set background context" } > Context setSettingsOpen(false)} onSave={handleSaveContext} currentValue={backgroundContext} /> > ); } function ChatContent() { const [backgroundContext, setBackgroundContext] = useState( null, ); useEffect(() => { const stored = localStorage.getItem(STORAGE_KEY); setBackgroundContext(stored || ""); }, []); if (backgroundContext === null) { return null; } return ( ); } export default function Chat() { return ( ); }