"use client"; import type React from "react"; import { StatusBadge } from "@/components/ui"; import { TimelineEvent } from "@/components/TaskLiveStatus"; import { humanToolName, TaskEvent } from "@/lib/task-types"; export type LlmUsage = { step: string; provider: string; backend: string; model: string; display: string; input_tokens: number; output_tokens: number; cost_usd: number; }; export type RunHistory = { run_number: number; follow_up?: string | null; summary?: string; resolved?: boolean; run_cost_usd?: number; llm_usage?: LlmUsage[]; }; export function formatCost(usd: number | undefined | null) { if (usd === undefined || usd === null) return "$0.0000"; if (usd === 0) return "$0.00 (local)"; return `$${usd.toFixed(4)}`; } export function TaskScopeCard({ task, report }: { task: any; report: any }) { const rule = report?.matched_rule; const checked = report?.devices_checked || []; return (

Scope

Requested

{task.issue}

Devices selected
{checked.length ? ( checked.map((device: string) => ( {device} )) ) : ( Selection pending )}
{rule && (
Rule

{rule.name || rule.id}

)}
); } export function TaskTimelinePanel({ events, wsConnected, pinnedToBottom, scrollBoxRef, endRef, onScroll, onJump, loading, }: { events: TaskEvent[]; wsConnected: boolean; pinnedToBottom: boolean; scrollBoxRef: React.RefObject; endRef: React.RefObject; onScroll: () => void; onJump: () => void; loading: boolean; }) { return (

Run Timeline

Plain-language progress; expand events only when evidence is needed.

{wsConnected ? "live" : "reconnecting"}
{events.map((ev, i) => ( ))} {events.length === 0 &&
{loading ? "Loading..." : "Waiting for events..."}
}
{!pinnedToBottom && events.length > 0 && ( )}
); } function MarkdownTable({ text }: { text: string }) { const lines = text.trim().split("\n"); const tableLines = lines.filter((line) => line.trim().startsWith("|") && line.trim().endsWith("|")); if (tableLines.length < 2) return null; const rows = tableLines .filter((line) => !/^\|\s*-+/.test(line)) .map((line) => line.split("|").slice(1, -1).map((cell) => cell.trim())); const [head, ...body] = rows; if (!head || body.length === 0) return null; return (
{head.map((cell, i) => ( ))} {body.map((row, i) => ( {row.map((cell, j) => ( ))} ))}
{cell}
{cell}
); } function DiagnosticEvidence({ diagnostic }: { diagnostic: any }) { const text = diagnostic.formatted || diagnostic.summary || diagnostic.output || "_No output_"; const table = typeof text === "string" ? : null; return (
[{diagnostic.device}] {humanToolName(diagnostic.tool || "tool")} {diagnostic.output_chars ? {diagnostic.output_chars} chars : null}
{table || (
            {text}
          
)}
); } export function TaskReportPanel({ report, pendingApprovals }: { report: any; pendingApprovals: number }) { const summary = report.executive_summary || report.summary; const findings = report.findings || []; const scope = report.scope_checked || report.devices_checked || []; return (

Report

0 ? "waiting_approval" : report.resolved ? "succeeded" : "running"} />
{summary && (
Summary

{summary}

)} {scope.length > 0 && (
Scope checked
{scope.map((item: any) => ( {typeof item === "string" ? item : item.device} ))}
)} {findings.length > 0 ? (
Findings
{findings.map((finding: any, i: number) => (
{finding.title || finding.summary || String(finding)}
{finding.description &&

{finding.description}

}
))}
) : (
Finding

{report.root_cause || report.resolution || "No notable finding recorded."}

)} {report.recommendations?.length > 0 && (
Recommendations
    {report.recommendations.map((r: { description?: string }, i: number) => (
  • {r.description || JSON.stringify(r)}
  • ))}
)} {report.actions_taken?.length > 0 && (
Actions taken
    {report.actions_taken.map((s: string, i: number) => (
  • {s}
  • ))}
)} {report.diagnostics?.length > 0 && (
Evidence
{report.diagnostics.map((d: any, i: number) => ( ))}
)}
); } export function TaskArtifactsPanel({ task, report }: { task: any; report: any }) { return (

Saved Artifacts

); } function ArtifactRow({ label, value, detail, bad = false }: { label: string; value?: string | null; detail?: string; bad?: boolean }) { return (
{label} {detail}
{value || "Not saved"}
); } function providerLabel(provider: string) { return provider === "local" ? "Local" : "API"; } export function TaskCostPanel({ report, llmUsage }: { report: any; llmUsage: LlmUsage[] }) { return (

Models & Cost

This run
{formatCost(report.run_cost_usd)}
Total
{formatCost(report.total_cost_usd)}
{llmUsage.length > 0 ? (
{llmUsage.map((u, i) => ( ))}
Step Type Model Cost
{u.step} {providerLabel(u.provider)} {u.display || u.model} {formatCost(u.cost_usd)}
) : (

No LLM usage recorded.

)}
); } export function TaskRunHistoryPanel({ runs }: { runs: RunHistory[] }) { if (runs.length <= 1) return null; return (

Run History

{runs.map((r) => (
Run {r.run_number} {formatCost(r.run_cost_usd)}
{r.follow_up &&

Follow-up: {r.follow_up}

} {r.summary &&

{r.summary}

}
))}
); }