"use client"; import { humanToolName, taskPhaseLabel, TaskEvent } from "@/lib/task-types"; const PHASES = [ { id: "context", label: "Context" }, { id: "triage", label: "Plan" }, { id: "connect", label: "Connect" }, { id: "diagnose", label: "Diagnose" }, { id: "reason", label: "Analyze" }, { id: "report", label: "Report" }, ] as const; function phaseIndex(phase: string | undefined): number { if (!phase) return -1; return PHASES.findIndex((p) => p.id === phase); } function derivePhase(events: TaskEvent[], taskStatus?: string): string { if (taskStatus === "succeeded" || taskStatus === "waiting_approval") return "report"; for (let i = events.length - 1; i >= 0; i--) { const p = events[i].payload?.phase as string | undefined; if (p) return p; const k = events[i].kind; if (k === "context" || k === "rule") return "context"; if (k === "triage") return "triage"; if (k === "connect") return "connect"; if (k === "diagnose" || k === "tool_start" || k === "tool_call") return "diagnose"; if (k === "reason") return "reason"; if (k === "report") return "report"; } return "context"; } function activeTool(events: TaskEvent[]): TaskEvent | null { for (let i = events.length - 1; i >= 0; i--) { const ev = events[i]; if (ev.kind === "tool_start") return ev; if (ev.kind === "tool_call" || ev.kind === "error") return null; } return null; } export default function TaskLiveStatus({ events, taskStatus, }: { events: TaskEvent[]; taskStatus: string; }) { const running = taskStatus === "running" || taskStatus === "queued"; const currentPhase = derivePhase(events, taskStatus); const currentIdx = phaseIndex(currentPhase); const active = activeTool(events); const lastProgress = [...events].reverse().find((e) => e.kind === "progress"); const devices = Array.from( new Set( events .map((e) => e.payload?.device) .filter((device): device is string => typeof device === "string" && !!device) ) ); const nowDoing = active ? `${active.payload?.device || "Device"}: ${humanToolName(String(active.payload?.tool || "diagnostic"))}` : taskPhaseLabel(taskStatus, events); return (
{nowDoing}
{lastProgress.message}
)} {active && (
$ {active.payload.command}
)}
$ {p.command}
{p.output}
{p.error}
)}