AgentPlan
The steps of a run and how far along it is, with the messages waiting behind it.
SourcePackage @kerf-js/veneer
Preview
tsx
import { state } from '@kerf-js/core'import { AgentPlan, Button, Row, Stack} from '@kerf-js/veneer'import type { PlanStep, QueuedMessage} from '@kerf-js/veneer'export function Rollback() { const steps = state(STEPS) const queue = state<QueuedMessage[]>([ { id: 'q1', text: 'Post a note in #incidents when it is done', }, { id: 'q2', text: 'Then open a fix branch' }, ]) const removeQueued = (id: string) => (queue.value = queue.value.filter((q) => q.id !== id)) return ( <Stack gap="related"> <AgentPlan title="Rollback" steps={steps.value} queue={queue.value} onRemoveQueued={removeQueued} /> <Row gap="related"> <Button emphasis="outline" tone="neutral" size="sm" onClick={() => (steps.value = advance(steps.value)) } > Finish this step </Button> <Button emphasis="ghost" tone="neutral" size="sm" onClick={() => (steps.value = STEPS)} > Reset </Button> </Row> </Stack> )}const STEPS: PlanStep[] = [ { id: 'logs', title: 'Read the build log', state: 'done', }, { id: 'check', title: 'Check that d-4801 is healthy', state: 'running', }, { id: 'roll', title: 'Roll back ap-south', state: 'pending', }, { id: 'watch', title: 'Watch the health checks for 5 minutes', state: 'pending', },]const advance = (steps: PlanStep[]) => { const at = steps.findIndex((s) => s.state === 'running') return steps.map((s, i): PlanStep => i === at ? { ...s, state: 'done' } : i === at + 1 ? { ...s, state: 'running' } : s, )}Installation
npm install @kerf-js/veneerUsage
tsx
import { AgentPlan } from '@kerf-js/veneer'Blocked
A blocked step is waiting for you.
tsx
import { AgentPlan } from '@kerf-js/veneer'export function Blocked() { return ( <AgentPlan steps={[ { id: 'a', title: 'Check that d-4801 is healthy', state: 'done', }, { id: 'b', title: 'Roll back ap-south', state: 'blocked', }, { id: 'c', title: 'Watch the health checks', state: 'pending', }, ]} /> )}Accessibility
- This has no shortcuts of its own: controls inside it use Tab, Enter and Space as usual, and veneer's parts keep their roles and labels.
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
steps | PlanStep[] | — | Each step is pending, running, done or blocked. |
queue | QueuedMessage[] | — | Messages sent during the run. |
title | unknown | 'Plan' | The heading. |
| Event | Type | Default | Description |
|---|---|---|---|
onRemoveQueued | ((id: string) => void) | — | Removing a queued message. |
Parts
Every element carries a stable name, so you can style it from your own CSS: [data-scope="plan"] [data-part="header"]
headerboxqueueeyebrow