import { m } from "motion/react"; import { PREPARE_THESIS_REPORT_RECIPE } from "../demo/agent/recipes.js"; import type { AgentMessage, AgentMessagePart } from "../demo/agent/events.js"; import type { PresentationState } from "./presentation-state.js"; import { compositionForState } from "./presentation-state.js"; type OperatorChatProps = { readonly state: PresentationState; readonly messages?: ReadonlyArray | undefined; readonly onApprove?: (() => void) | undefined; readonly onDeny?: (() => void) | undefined; }; const fallbackMessages = (state: PresentationState): ReadonlyArray => [ { id: "fallback-user", role: "user", parts: [{ type: "text", text: PREPARE_THESIS_REPORT_RECIPE.userPrompt }] }, { id: "fallback-system", role: "assistant", parts: [ { type: "text", text: `Found prepared workflow recipe: ${PREPARE_THESIS_REPORT_RECIPE.id}.` }, { type: "text", text: state.playbackMode === "replay" ? "Replay mode is active. Live execution is available when connected." : "Live execution is active. Operations are being sent to the connected workflow server.", }, ], }, ]; const renderPart = ( part: AgentMessagePart, key: string, onApprove?: () => void, onDeny?: () => void, ) => { switch (part.type) { case "text": return

{part.text}

; case "tool-call": if (part.call.name === "startPreparedReportRun") { return ( Workflow operation {part.call.name} ); } return (
Tool call {part.call.name}
); case "tool-result": return (
Tool result {part.result.name} {part.result.status}
); case "presentation-action": return (
Presentation action {part.action.type}
); case "approval-request": return (
Approval required {part.name}

{part.prompt}

); case "error": return

{part.message}

; default: return null; } }; const partKey = (messageId: string, part: AgentMessagePart): string => { switch (part.type) { case "text": return `${messageId}-text-${part.text}`; case "tool-call": return `${messageId}-call-${part.call.id}`; case "tool-result": return `${messageId}-result-${part.result.callId}`; case "presentation-action": return `${messageId}-action-${JSON.stringify(part.action)}`; case "approval-request": return `${messageId}-approval-${part.callId}`; case "error": return `${messageId}-error-${part.message}`; } }; export const OperatorChat = ({ state, messages, onApprove, onDeny }: OperatorChatProps) => { const visibleMessages = messages && messages.length > 0 ? messages : fallbackMessages(state); const composition = compositionForState(state); return ( ); };