import { formatUsd } from "./status-widget.js"; import { isTerminal } from "../controller/state-machine.js"; import type { UltraController } from "../controller/controller.js"; import type { ControllerState } from "../controller/state-machine.js"; export const HUD_KEY = "ultrapi"; /** The minimum a person needs to know a fleet is alive: what stage, how many, on what, at what cost. */ export function hudLine(controller: UltraController): string | undefined { const status = controller.status(); const live = status.activeRuns.filter((run) => !isTerminal(run.state as ControllerState)); const run = live.at(-1); if (!run) return undefined; const queued = live.length > 1 ? ` +${live.length - 1}` : ""; const working = run.nodes.filter((node) => node.state !== "done").length; const health = status.health.state === "healthy" ? "" : ` · ${status.health.state}`; const agents = working ? ` · ${working} agent${working === 1 ? "" : "s"}` : ""; return `UltraPi ${run.topology}/${run.state}${queued} · [${run.progress.done}/${run.progress.total}]${agents} · ${run.model ?? "model unselected"}${health} · est. ${formatUsd(status.spentUsd)}`; } export interface HudSurface { setStatus?: (key: string, text: string | undefined) => void } /** * A painter that writes the line into Pi's footer whenever it changes, and clears it when the * last run settles. It holds the last painted text so an idle session never touches the status * bar and a busy one repaints only on real movement. * * Painting can never throw. A HUD exists to tell you a run is alive; a HUD that can end the run * it reports on is worse than no HUD, so every failure here — a host without `setStatus`, a * controller that is not ready, a renderer that rejects the string — is swallowed. Losing a * frame costs the user a moment of not knowing; propagating would cost them the run. */ export function createHudPainter(controller: UltraController): (ui: HudSurface | undefined) => void { let painted: string | undefined; return (ui) => { try { if (typeof ui?.setStatus !== "function") return; const line = hudLine(controller); if (line === painted) return; painted = line; ui.setStatus(HUD_KEY, line); } catch {} }; } export function clearHud(ui: HudSurface | undefined): void { try { ui?.setStatus?.(HUD_KEY, undefined); } catch {} }