Skip to content
TuffTasks, docs and chat for teams and AI agents

Observability

Lap Timer

A pipeline run as a stopwatch — the hand sweeps through each stage's sector, with splits and the delta against the best lap.

1 variantMIT

Preview

Pipeline lap

eval run 418 · support-qa

Live

00:00.0

Lap 3 · 0 of 3 sectorsbest 44.1 s
51015202530354045505560S1
Sector splits against best
SectorSplitDelta vs best
S1retrieve0.0 s
S2generate—
S3score—

Installation

Copies the component into components/ui and installs its dependencies and theme tokens.

pnpm dlx shadcn@latest add https://tuffui.com/r/lap-timer.json

Usage

Pass your own data and wire the callbacks to your agent runtime.

import { LapTimer } from "@/components/ui/lap-timer";

export function PipelineLap({ run }: { run: PipelineRun }) {
  // Re-render on a frame clock (or every 100 ms) while the run is live.
  const elapsed = useElapsed(run.startedAt, run.finishedAt);

  return (
    <LapTimer
      title="Pipeline lap"
      subtitle={`eval run ${run.id}`}
      lap={`Lap ${run.attempt}`}
      elapsed={elapsed}
      best={run.bestLap} // seconds
      running={!run.finishedAt}
      sectors={run.stages.map((stage) => ({
        id: stage.id,
        label: stage.name, // "retrieve", "generate", "score"
        best: stage.bestSplit,
        split: stage.finishedAt ? stage.duration : undefined,
      }))}
    />
  );
}

Props

PropTypeDefaultDescription
sectors*LapSector[]—Stages in order. Each one paints its arc on the dial; the first one without a split is the running one.
elapsed*number—Seconds since the lap started. Drives the hand and the clock.
bestnumbersum of sector bestsBest full lap in seconds. Marked on the dial and used for the delta next to the clock.
runningbooleantrueWhether the lap is still going. When false, the last split ends the lap.
dialnumberautoSeconds per turn of the dial. Left out, it picks the smallest of 10 s, 15 s, 20 s, 30 s, 1 min… that fits the best lap.
title*string—Header title.
subtitlestring—Secondary line under the title.
lapstring—Label above the dial next to the sector count, e.g. "Lap 3".
asideReactNode—Extra content on the right of the header, e.g. a status pill.
format(seconds: number) => strings.toFixed(1) + ' s'Formats split times and the best lap. The clock is always mm:ss.t.
classNamestring—Extra classes for the root element.
type LapSector = {
  id: string;
  label: string;  // stage name
  best: number;   // best split, seconds
  split?: number; // seconds, once the stage is done
};