"use client"; import { useEffect, useState } from "react"; /* ───────────────────────────────────────────────────────── * TOOL CHIPS * An agent run as compact rows: tool calls with inline * chips, then file-diff chips summarizing the edits. * Hover a row to reveal its chevron; every row expands * to show what the tool actually did. * ───────────────────────────────────────────────────────── */ const STEP_MS = 700; const Icons: Record = { think: , write: , run: , read: , }; type DetailLine = { text: string; tone?: "add" }; const ROWS: { icon: string; label: string; chip: string; mono: boolean; detailMono: boolean; detail: DetailLine[] }[] = [ { icon: "think", label: "Thinking", chip: "Planning the churn schedule…", mono: false, detailMono: false, detail: [ { text: "Weekend demand carries pistachio, so it churns first." }, { text: "Batch capacity leaves two evening freezer windows." }, ], }, { icon: "write", label: "Write 204 lines", chip: "ChurnSchedule.tsx", mono: true, detailMono: true, detail: [ { text: "+ const windows = slots.filter((s) => s.temp <= -12)", tone: "add" }, { text: "+ return schedule(windows, { hero: \"pistachio\" })", tone: "add" }, ], }, { icon: "run", label: "Rebuild and verify", chip: "npm run freeze", mono: true, detailMono: true, detail: [ { text: "✓ built in 1.2s" }, { text: "✓ 34 checks passed" }, ], }, { icon: "read", label: "Read image", chip: "flavor-chart.png", mono: true, detailMono: false, detail: [ { text: "1280 × 720 · line chart, three summers." }, { text: "Mint chip trends up 12% through July." }, ], }, ]; const DIFFS = [ { file: "flavors.css", add: 13, del: 0 }, { file: "ChurnSchedule.tsx", add: 74, del: 41 }, { file: "menu.ts", add: 8, del: 2 }, ]; export default function ToolChips() { const [step, setStep] = useState(0); const [open, setOpen] = useState(true); const [openRows, setOpenRows] = useState>(new Set()); const total = ROWS.length + 1; // rows, then diff chips useEffect(() => { if (step >= total) return; const t = setTimeout(() => setStep((s) => s + 1), STEP_MS); return () => clearTimeout(t); }, [step, total]); const toggleRow = (label: string) => setOpenRows((current) => { const next = new Set(current); next.has(label) ? next.delete(label) : next.add(label); return next; }); return (
{/* collapsed run header */} {/* tool call rows */}
{/* -mx-1 + px-1.5 keeps content at the same x while giving the row hover pills room inside this overflow-hidden clip box */}
{ROWS.slice(0, step).map((row) => { const rowOpen = openRows.has(row.label); return (
{/* expanded detail */}
{row.detail.map((line) => ( {line.text} ))}
); })}
{/* file-diff chips */} {step >= total && (
{DIFFS.map((d, i) => ( {d.file} +{d.add} {d.del > 0 && −{d.del}} ))}
)}
); }