/** A Planner-launched workflow run: is it alive, what is it doing, does it need anyone. */ import { useEffect, useState } from "react"; import { CheckIcon, CloseIcon, WarningIcon } from "@chopin/icons"; import type { Chat as Wire } from "@chopin/protocol"; const SHOWN_STAGES = 6; const STATUS: Record = { running: "running", waiting: "waiting on Decisions", paused: "paused", finished: "finished", failed: "failed", stopped: "stopped", }; const STAGE: Record = { pending: "pending", running: "running", awaiting_input: "waiting on Decisions", paused: "paused", blocked: "blocked", completed: "done", failed: "failed", skipped: "skipped", }; /** "45s", "6m", "1h 4m". */ export function elapsed(seconds: number): string { let s = Math.max(0, Math.floor(seconds)); if (s < 60) return `${s}s`; let m = Math.floor(s / 60); if (m < 60) return `${m}m`; return `${Math.floor(m / 60)}h ${m % 60}m`; } function useNow(live: boolean): number { let [now, setNow] = useState(() => Date.now() / 1000); useEffect(() => { if (!live) return; let timer = setInterval(() => setNow(Date.now() / 1000), 5_000); return () => clearInterval(timer); }, [live]); return now; } /** A dot that pulses while work is live; it stays still under reduced motion. */ function RunPulse() { return