import { useEffect, useReducer, useState } from "react"; import { useSessionStore } from "../store/sessionStore"; /** Last few words of a string — a compact "what the model is doing now" tail. */ function lastWords(s: string, n = 8): string { const w = s.trim().split(/\s+/).filter(Boolean); return w.slice(-n).join(" "); } /** The minimal central view: the user's last input/choice, a live "working" indicator * (elapsed time + a short tail of the model stream) while the model is busy, and the * gate's curated messages for the current step. The full verbose stream lives in the * left Model-activity panel. */ export function CentralStatus({ working }: { working: boolean }) { const lastUserEntry = useSessionStore((s) => s.lastUserEntry); const stepMessages = useSessionStore((s) => s.stepMessages); const transcript = useSessionStore((s) => s.transcript); const [startedAt, setStartedAt] = useState(null); const [, tick] = useReducer((x: number) => x + 1, 0); // Start the per-step timer when work begins; tick once a second so the elapsed // display updates; clear it when work stops. useEffect(() => { if (!working) { setStartedAt(null); return; } setStartedAt((prev) => prev ?? Date.now()); const id = setInterval(tick, 1000); return () => clearInterval(id); }, [working]); if (!working && !lastUserEntry && stepMessages.length === 0) return null; const elapsed = startedAt ? Math.max(0, Math.floor((Date.now() - startedAt) / 1000)) : 0; const tail = lastWords(transcript.at(-1)?.text ?? ""); return (
{lastUserEntry && (
{lastUserEntry.kind === "input" ? "You asked" : "You chose"}

{lastUserEntry.text}

)} {working && (
{elapsed}s {tail && · {tail}} ThothII is working
)} {stepMessages.map((m, i) => (

{m.text}

))}
); }