import { AlertTriangle, CheckCircle2, GitBranch, Layers3 } from "lucide-react"; import type React from "react"; import type { AiTraceSummary, PipelineTraceSummary } from "../services/designAgentApi"; interface PipelineTracePanelProps { trace: PipelineTraceSummary | null | undefined; aiTrace?: AiTraceSummary | null; } const stateClass: Record = { rendered: "bg-emerald-50 text-emerald-700 border-emerald-200", render_blocked: "bg-red-50 text-red-700 border-red-200", filtered: "bg-amber-50 text-amber-700 border-amber-200", covered_not_rendered: "bg-orange-50 text-orange-700 border-orange-200", uncovered: "bg-slate-50 text-slate-500 border-slate-200", }; function Chip({ children, tone = "slate" }: { children: React.ReactNode; tone?: "slate" | "red" | "green" | "amber" }) { const tones = { slate: "bg-slate-100 text-slate-600", red: "bg-red-100 text-red-700", green: "bg-emerald-100 text-emerald-700", amber: "bg-amber-100 text-amber-700", }; return ( {children} ); } export default function PipelineTracePanel({ trace, aiTrace }: PipelineTracePanelProps) { if (!trace) { return (

No Trace Loaded

); } return (

Pipeline Trace

0 ? "amber" : "green"}>{trace.status}
{trace.warnings.length > 0 && (
Warnings
{trace.warnings.map((warning) => ( {warning} ))}
)}
Sections
{trace.sections.map((section) => (
{section.id} {section.state}
{section.title &&
{section.title}
} {section.child_ids.length > 0 && (
children: {section.child_ids.join(", ")}
)} {section.reasons.length > 0 && (
{section.reasons.map((reason) => ( {reason} ))}
)}
))}
Units
{trace.units.map((unit) => (
{unit.unit_id || "(empty unit)"}
frame{unit.selected_frame ?? "-"} candidates{unit.candidate_count} path{unit.selection_path ?? "-"} label{unit.label ?? "-"}
{unit.warnings.length > 0 && (
{unit.warnings.map((warning) => {warning})}
)}
))}
Zones / Render
{trace.zones.map((zone) => { const filled = zone.slot_status === "filled"; return (
{zone.position} {zone.slot_status}
sections: {zone.source_section_ids.join(", ") || "-"}
template: {zone.template_id ?? "-"}
slot keys: {zone.slot_key_count}
{zone.warnings.length > 0 ? (
{zone.warnings.map((warning) => {warning})}
) : (
render payload ready
)}
); })}
AI Status
{!aiTrace ? (
AI trace not loaded.
) : (
{aiTrace.artifact_present ? "artifact" : "missing"} enabled {aiTrace.ai_enabled === null ? "unknown" : String(aiTrace.ai_enabled)} 0 ? "green" : "slate"}> called {aiTrace.ai_called_count} 0 ? "amber" : "slate"}> eligible {aiTrace.eligible_count} 0 ? "red" : "slate"}> errors {aiTrace.error_count}
status{aiTrace.status} coverage{aiTrace.coverage_status ?? "-"} provider{aiTrace.provider ?? "-"} human review{String(aiTrace.human_review_required)}
{Object.keys(aiTrace.skip_reasons).length > 0 && (
Skip Reasons
{Object.entries(aiTrace.skip_reasons).map(([reason, count]) => ( {reason}: {count} ))}
)} {aiTrace.units.length > 0 && (
{aiTrace.units.map((unit) => (
{unit.source_section_ids.join("+") || `unit-${unit.unit_index}`} {unit.ai_called ? "called" : "not called"}
route{unit.route_hint ?? "-"} skip{unit.skip_reason ?? "-"} apply{unit.apply_status ?? "-"} error{unit.error ?? "-"}
))}
)}
)}
); }