# Build the "Live step stream" pattern: `StepStream`

## Stack (edit this block to match your project)
- React 18+ with TypeScript: one function component, typed props, no `any`.
- Tailwind CSS, using your design system's tokens if you have them.
- Presentational only: data comes in through props, decisions go out through callbacks. No fetching or global state inside.
- If your codebase already has conventions (naming, shared components, tokens), follow them over this spec.

## What the pattern is for
A running log of steps and tool calls as they happen, collapsible to a one-line summary.

Use it when: Long autonomous runs where silence reads as failure.

## What to build
A running log of an agent's steps and tool calls as they happen, each shown as one readable line with its result, collapsible to a one-line summary with step count and elapsed time. Warnings stand out, and raw tool output is available per step but hidden by default. It renders under a request in a chat or in a run panel, and stays readable after the run.

### Props
- `events`: Array<{ id: string; at: number; tool: string; text: string; result?: string; kind?: "normal" | "warn" | "write" | "error"; raw?: string }>, typed events appended by the parent from the stream.
- `status`: "starting" | "running" | "done" | "stopped" | "error".
- `elapsedSeconds`: number, supplied by the parent.
- `collapsed`: boolean and `onCollapsedChange(v: boolean)`, controlled.
- `summary?`: string, the one-line summary used when collapsed, e.g. "Reading exit surveys" or "8 steps, 0:58, 1 warning".
- `onStop?()`: optional stop control while running.
- `maxVisible?`: number, events kept rendered before older ones are grouped (default 50).

### States it must render
- Starting: "Starting" with "0 steps, 0:00".
- Running: each event shows time, tool name and a plain sentence, e.g. "Searched tickets mentioning cancel or downgrade since 1 Jul, 212 tickets"; the newest line is marked live.
- Warning: a warn event is amber with its consequence, e.g. "Billing export is missing 1 to 3 July. Using invoices for those days instead", and the collapsed summary counts it.
- Collapsed: one line with current step, count and elapsed time.
- Done: the live marker is removed and the header reads e.g. "8 steps, 0:58"; the log remains expandable and searchable.
- Error or stopped: the last event is marked and the header says which step it ended on.

### Interactions
- The header toggles `collapsed`.
- Each event with `raw` has a "raw output" toggle that reveals a monospaced block for that step only.
- The view follows new events only if the reader is at the bottom; otherwise a "Jump to latest" button appears.
- A text filter (after the run) narrows events by tool or text.

### Edge cases
- Raw output is never the default view; even when every event has raw output, lines show the readable sentence first.
- Bursts of events: batch renders per animation frame and keep earlier lines from shifting.
- Very long runs: group older events ("Read 40 documents") and keep warnings ungrouped.
- Events arriving out of order: sort by `at`.

## Must avoid
Raw stack-trace verbosity as the default view, burying the one line that mattered.

## Engineering constraint
Stream typed events over SSE or the AG-UI protocol; keep the log queryable after the run.

## Accessibility
- The log is a `log` role region; announce only warnings, errors and completion, not every event.
- Raw output toggles have `aria-expanded` and labels naming the step.

## House rules
- Real `<button>`/`<input>` elements, full keyboard use, visible focus; announce status changes with `aria-live="polite"`; respect `prefers-reduced-motion`.
- All user-facing text comes from props (or a `labels` prop) so it can be translated.
- One consistent accent marks anything the AI made or is doing; amber means "needs a person", red means risky, green means done. Never rely on colour alone.
- Fits a 360 px wide container without horizontal scrolling.

## Acceptance checks
- [ ] Every state above can be rendered by passing props, with no internal fake data.
- [ ] Every interaction and edge case above behaves as described.
- [ ] Nothing in "Must avoid" can happen with this component.

## Deliver
1. The component file with its exported prop types.
2. A short usage example that renders each state.
