From 35cac9eb6ed9120ceb01b71551e7e76c7efde240 Mon Sep 17 00:00:00 2001 From: Anton Castro Date: Tue, 21 Jul 2026 00:14:30 -0700 Subject: [PATCH] =?UTF-8?q?feat:=20full=20lap=20demo=20=E2=80=94=20every?= =?UTF-8?q?=20component=20driven=20through=20one=20interruptible=20agent?= =?UTF-8?q?=20run?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/full-lap/lap-run.tsx | 270 ++++++++++++++++++++++++++++++++++++ app/full-lap/page.tsx | 50 +++++++ app/page.tsx | 7 + components/docs/sidebar.tsx | 1 + 4 files changed, 328 insertions(+) create mode 100644 app/full-lap/lap-run.tsx create mode 100644 app/full-lap/page.tsx diff --git a/app/full-lap/lap-run.tsx b/app/full-lap/lap-run.tsx new file mode 100644 index 0000000..f9a7280 --- /dev/null +++ b/app/full-lap/lap-run.tsx @@ -0,0 +1,270 @@ +"use client"; + +/** + * LapRun — the whole system on one circuit. + * A scripted agent run drives every component through a real sequence: + * contract, telemetry, budget, failure, recovery, and a final gate. + * The controls are not decoration: Stop actually stops the run, steering + * is acknowledged, and the irreversible step waits for a real click. + */ + +import { useEffect, useMemo, useState } from "react"; +import { AnimatePresence, motion } from "motion/react"; +import { ToolCallCard } from "@/registry/tool-call-card/tool-call-card"; +import { ApprovalGate } from "@/registry/approval-gate/approval-gate"; +import { AgentTaskList, type AgentTask } from "@/registry/agent-task-list/agent-task-list"; +import { InterruptBar } from "@/registry/interrupt-bar/interrupt-bar"; +import { ConfidenceMeter } from "@/registry/confidence-meter/confidence-meter"; +import { ContextBudget } from "@/registry/context-budget/context-budget"; +import { PitFlag } from "@/components/docs/pit-flag"; + +/** step machine: each step runs for `dur` ticks; gates hold until decided */ +const STEPS = [ + { id: "contract", dur: 3 }, + { id: "plan", dur: 2 }, + { id: "search", dur: 3 }, + { id: "compare", dur: 3 }, + { id: "confidence", dur: 3 }, + { id: "hold-fail", dur: 3 }, + { id: "hold-retry", dur: 3 }, + { id: "book-gate", dur: Infinity }, + { id: "booked", dur: 2 }, + { id: "done", dur: Infinity }, +] as const; + +type StepId = (typeof STEPS)[number]["id"]; +type Phase = "running" | "stopped" | "denied"; + +export function LapRun() { + const [stepIndex, setStepIndex] = useState(0); + const [tick, setTick] = useState(0); + const [elapsed, setElapsed] = useState(0); + const [phase, setPhase] = useState("running"); + const [ack, setAck] = useState(undefined); + + const step: StepId = STEPS[stepIndex].id; + const atOrPast = (id: StepId) => + STEPS.findIndex((s) => s.id === id) <= stepIndex; + const past = (id: StepId) => STEPS.findIndex((s) => s.id === id) < stepIndex; + + useEffect(() => { + if (phase !== "running" || STEPS[stepIndex].dur === Infinity) return; + const t = setInterval(() => { + setElapsed((e) => e + 1); + setTick((s) => { + if (s + 1 >= STEPS[stepIndex].dur) { + setStepIndex((i) => Math.min(i + 1, STEPS.length - 1)); + return 0; + } + return s + 1; + }); + }, 1000); + return () => clearInterval(t); + }, [phase, stepIndex]); + + const reset = () => { + setStepIndex(0); + setTick(0); + setElapsed(0); + setPhase("running"); + setAck(undefined); + }; + + const advance = () => { + setStepIndex((i) => Math.min(i + 1, STEPS.length - 1)); + setTick(0); + }; + + const tasks: AgentTask[] = useMemo(() => { + const holdStatus = + step === "hold-fail" && tick >= 1 + ? "failed" + : past("hold-retry") + ? "done" + : step === "hold-retry" + ? "active" + : step === "hold-fail" + ? "active" + : "pending"; + return [ + { title: "Find flights SFO → JFK", status: past("search") ? "done" : atOrPast("search") ? "active" : "pending" }, + { + title: "Compare against the $400 cap", + status: past("compare") ? "done" : step === "compare" ? "active" : "pending", + detail: step === "compare" ? "14 flights found" : undefined, + }, + { + title: "Hold the best option", + status: holdStatus as AgentTask["status"], + detail: + holdStatus === "failed" + ? "Fare expired. Trying the next option." + : step === "hold-retry" + ? "Holding JetBlue 616…" + : undefined, + }, + { + title: "Book with your approval", + status: past("booked") || step === "done" ? "done" : step === "book-gate" || step === "booked" ? "active" : "pending", + detail: step === "book-gate" ? "Waiting at the gate" : undefined, + }, + ]; + }, [step, tick, stepIndex]); + + const spend = atOrPast("booked") ? 278 : past("hold-retry") ? 278 : 0; + const finished = step === "done"; + const interrupted = phase !== "running"; + + return ( +
+ {/* transcript */} +
+
+
+ Book my New York trip, Aug 12. Keep it under $400. +
+
+ + + + + {atOrPast("search") && ( + + + + )} + + + + {atOrPast("confidence") && ( + + + + )} + + + + {(step === "hold-fail" || atOrPast("hold-retry")) && ( + + = 1 + ? "error" + : past("hold-retry") + ? "success" + : "running" + } + args={'{ "flight": "B6-616", "fare": 278 }'} + detail={ + step === "hold-fail" && tick >= 1 + ? "FareExpiredError: retrying with next fare class (attempt 2/3)" + : past("hold-retry") + ? "Held for 20 minutes. No charge yet." + : undefined + } + /> + + )} + + + + {atOrPast("book-gate") && !interrupted && ( + + setPhase("denied")} + scope={[ + { label: "Charge your saved card $278", risky: true }, + { label: "Send confirmation to your email" }, + ]} + approveLabel="Book it" + denyLabel="Not now" + /> + + )} + + + + {finished && ( + + +
+ Lap complete in {elapsed}s.{" "} + One failure recovered, one steer honored, nothing irreversible without you. +
+
+ )} +
+ + {phase === "denied" && ( +
+ + Stopped at the gate. The hold and the plan are kept; nothing was charged. +
+ )} +
+ + {/* pit wall */} +
+ t.status === "active")?.title ?? "Starting the run…" + } + elapsed={elapsed} + state={phase === "stopped" ? "stopped" : "running"} + keptOnStop="Plan and 14 search results kept" + onStop={() => setPhase("stopped")} + onSteer={(msg) => setAck(`Got it: "${msg}". Adjusting without restarting.`)} + acknowledgment={ack} + /> + + `$${n}` }, + { label: "Time", used: elapsed, cap: 120, format: (n) => `${n}s` }, + ]} + /> + +
+
+ ); +} diff --git a/app/full-lap/page.tsx b/app/full-lap/page.tsx new file mode 100644 index 0000000..e14a6ed --- /dev/null +++ b/app/full-lap/page.tsx @@ -0,0 +1,50 @@ +import Link from "next/link"; +import { PitFlag } from "@/components/docs/pit-flag"; +import { LapRun } from "./lap-run"; + +export const metadata = { + title: "The Full Lap — Agent Pit Stop", + description: + "Every component, one agent run: contract, telemetry, budget, a failure recovered, and a gate that waits for you. The stop button is real.", +}; + +export default function FullLapPage() { + return ( +
+
+ + + AGENT PIT STOP + + + The Full Lap + +
+ +
+

+ Every component. One lap. +

+

+ A scripted agent run drives the whole system: contract at the start line, live + telemetry, a budget, one failure recovered, and an irreversible step that waits + for you. The controls aren't a movie. Stop actually stops it, steering is + acknowledged, and nothing books until you say so. +

+
+ + + +

+ Built entirely from the{" "} + + 8 open components + + , unmodified. Install any of them with one command. +

+
+ ); +} diff --git a/app/page.tsx b/app/page.tsx index 74fa74f..2cac664 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -141,6 +141,13 @@ export default function Home() { Principles and React components for approval, steering, and recovery. Free, MIT, and built to be copied.

+ + + WATCH THE FULL LAP + {/* three link cards */} diff --git a/components/docs/sidebar.tsx b/components/docs/sidebar.tsx index 469ed1f..92b3b7a 100644 --- a/components/docs/sidebar.tsx +++ b/components/docs/sidebar.tsx @@ -51,6 +51,7 @@ export function Sidebar() {
+