export const ACTIVE_STATUSES = ["running", "queued", "waiting_approval"] as const; export type TaskStatus = | "queued" | "running" | "waiting_approval" | "succeeded" | "failed" | "cancelled"; export type TaskEvent = { id?: number; kind: string; message: string | null; payload?: Record | null; ts?: string; created_at?: string; replay?: boolean; }; export type TaskOverview = { id: number; title: string; issue: string; status: TaskStatus; vessel_id: number | null; vessel_name?: string | null; summary?: string | null; key_finding?: string | null; devices_checked: string[]; resolved?: boolean | null; memory_id?: string | null; obsidian_path?: string | null; obsidian_push_error?: string | null; run_cost_usd?: number | null; created_at: string; updated_at: string; }; export type TaskPreview = { vessel_id: number; vessel_name?: string | null; devices: { catalog_key: string; name: string; label: string; checks: string[] }[]; rule_id?: string | null; rule_name?: string | null; severity?: string | null; hints: string[]; warning?: string | null; }; export function isActiveStatus(status: string) { return ACTIVE_STATUSES.includes(status as (typeof ACTIVE_STATUSES)[number]); } export function taskPhaseLabel(status: string, events: TaskEvent[] = []) { if (status === "queued") return "Waiting in queue"; if (status === "waiting_approval") return "Waiting for approval"; if (status === "succeeded") return "Report complete"; if (status === "failed") return "Failed"; if (status === "cancelled") return "Stopped"; const last = [...events].reverse().find((e) => e.kind !== "log"); if (!last) return "Starting"; if (last.kind === "context") return "Gathering context"; if (last.kind === "triage" || last.kind === "rule") return "Planning checks"; if (last.kind === "connect") return "Connecting to devices"; if (last.kind === "tool_start" || last.kind === "tool_call" || last.kind === "diagnose") { const device = last.payload?.device; const tool = humanToolName(String(last.payload?.tool || "")); return [device, tool].filter(Boolean).join(": ") || "Running diagnostics"; } if (last.kind === "reason") return "Analyzing findings"; if (last.kind === "report") return "Writing report"; return last.message || "Running"; } export function humanToolName(tool: string) { const known: Record = { pfsense_get_system_status: "pfSense system status", pfsense_list_interfaces: "pfSense interfaces", pfsense_list_gateways: "pfSense gateways", pfsense_get_gateway_status: "pfSense gateway status", pfsense_list_firewall_rules: "pfSense firewall rules", pfsense_list_port_forwards: "pfSense port forwards", pfsense_list_outbound_nat_mappings: "pfSense outbound NAT", proxmox_list_nodes: "Proxmox nodes", proxmox_list_qemu: "Proxmox VMs", proxmox_list_lxc: "Proxmox LXCs", proxmox_get_qemu_status: "VM status", proxmox_get_qemu_config: "VM config", ssh_run: "SSH command", }; return known[tool] || tool.replace(/_/g, " "); }