<!-- GENERATED by scripts/build-llms.mjs from llms/agent-tools.md — do not edit this file. -->

# `lr-agent-run`

- **Import** `import '@aceshooting/lyra-ui/components/lr-agent-run.js';` (stable tag alias; registers the tag)
- **Class** `LyraAgentRun`, also available unregistered from `@aceshooting/lyra-ui/components/agent-tools/agent-run/agent-run.class.js`
- **Family** `components/agent-tools/` — see `llms/index.md` for its siblings
- **Status** `stable` since `4.1.0` — see the maturity and deprecation policy in `llms/shared.md`
- **Release history** [CHANGELOG.md](../../CHANGELOG.md); family-wide breaking-change summaries: [llms-full.txt](../../llms-full.txt)
- **Deprecations** none
- **Optional peers** none
- **Themeable via** 25 parts, 10 custom properties — see this component's own `@csspart`/`@cssprop` list below
- **Library-wide behavior** (events, form association, `locale`/`strings`, tokens, TS types): `llms/shared.md`

---

## `lr-agent-run`

Top-level shell for one agent run: status, elapsed time, current step, model/cost summary, arbitrary
metrics, and Cancel/Retry actions. Built-in and application-defined lifecycle statuses are supported;
`statusLabels` and `statusVariants` customize unknown status kinds. Named `header` and `summary` slots
replace the corresponding built-in chrome, while `tasks`, `tools`, `reasoning`, `output`, and
`actions` support host-controlled composition.

The nine built-in status kinds are `idle`, `queued`, `collecting`, `running`, `waiting-input`,
`waiting-approval`, `done`, `error`, and `cancelled`; arbitrary application-defined string kinds are
also accepted. Live elapsed time and Cancel are available for `running`, `collecting`,
`waiting-input`, and `waiting-approval`. `queued` is pending rather than actively ticking or
cancelable. Retry is available for `error` and `cancelled`.

**Properties:**

- `run: AgentRun | null = null` (attribute: false) — **`AgentRun`, imported from
  `@aceshooting/lyra-ui/ai`**: `{ id: string; status: AgentStatus; startedAt?:
number; endedAt?: number; model?: string; costEstimate?: number; steps: readonly AgentStep[] }`, where
  `AgentStatus { kind: AgentStatusKind; message?: string }` and `AgentStep { id: string; kind:
string; label: string; status: AgentStatus; startedAt?: number; endedAt?: number }`. All timestamps
  are epoch milliseconds; `AgentStep.kind` is deliberately free-form (an agent's own step taxonomy is
  application-defined) — unlike `LyraSpan['kind']`'s closed union. The record and its nested step
  collection are clone-owned, bounded, and frozen; pass a new object to update it. `null` renders
  the shared `lr-empty` `noData` state. A runtime summary record that has not loaded `steps` yet
  renders with an empty task slot, and a step whose status has not arrived yet renders as pending
- `metrics: readonly AgentRunMetric[] = []` (attribute: false) — `AgentRunMetric { id: string; label: string;
value: string | number; variant?: BadgeVariant }` (exported here), e.g. prompt/completion token
  counts; `variant` tones `[part="metric-value"]` via `data-variant`, including the full
  `neutral`/`brand`/`success`/`warning`/`danger` badge vocabulary. Empty/blank ids and later duplicates are omitted
  before metric rendering
- `formatCost?: (cost: number) => string` (attribute: false) — overrides the default plain
  `Intl.NumberFormat` rendering of `run.costEstimate` fed to the composed `lr-usage-badge`'s
  `cost-text`; use it to add a currency symbol, which this library never assumes on a host's behalf
- `statusLabels: Readonly<Record<string, string>> = {}` (attribute: false) — clone-owned labels for
  _application-defined_ `AgentStatusKind` values; the nine built-in kinds stay localized by Lyra
- `statusVariants: Readonly<Record<string, BadgeVariant>> = {}` (attribute: false) — clone-owned
  badge variants for application-defined kinds; unknown kinds default to `neutral`

The collection and status-map properties above are bounded frozen snapshots. Mutating a previously
assigned array or record has no effect; create and reassign a new value after changes.

- `showCancel: boolean = true` (attribute `show-cancel`) / `showRetry: boolean = true` (attribute
  `show-retry`) — whether the built-in buttons may render at all, still gated by the run's own
  status. Both use a `true`-defaulting string converter, so plain-HTML `show-cancel="false"` works; a
  `?show-cancel=${false}` boolean-attribute binding starting from absent markup does not
- `compact: boolean = false` (reflected) — tighter root padding and header/body gap for dense
  contexts (a run rendered as a row in a list, or in a side panel); same convention as `lr-empty`'s
  `compact`. Purely a density knob: the border and background stay, so reach for
  `frame="plain"` instead when the goal is to drop the chrome entirely
- `frame: LyraFrame = 'card'` (reflected) — container treatment, in the library-wide `frame`
  vocabulary (`'card' | 'plain'`), the same property `<lr-card>` and every other card-shaped
  component carries. `'card'` keeps the bordered, filled, padded box; `'plain'` removes the
  border, background, padding and corner radius, so a run nested inside a host container that
  already draws a border doesn't double it. `plain` wins over `compact` when both are set — there is
  no padding left to tighten. The built-in Cancel/Retry buttons draw their own border and background
  and stay visibly interactive either way. The exported alias `AgentRunAppearance` is retained as a
  name for the same union

**Events:** `lr-cancel` (`detail: CancelEventDetail` = `{ reason?: string }`, from
`@aceshooting/lyra-ui/ai`; `reason` is `undefined` from the built-in button), `lr-run-retry`
(`detail: RetryEventDetail` = `{ attempt: number; messageId?: string }`, same module — `attempt` is
this component's own retry counter, reset when `run.id` changes).

**Slots:** `header` and `summary` replace the corresponding built-in chrome; `tasks`, `tools`,
`reasoning`, `output`, and `actions` are host-controlled composition regions.

**CSS parts:** `base`, `header`, `status`, `status-badge`, `status-message`,
`elapsed` (the live ticker), `elapsed-static` (a terminal run's frozen duration), `summary`, `model`,
`usage`, `current-step`, `current-step-icon`, `current-step-label`, `body`, `tasks`, `tools`,
`reasoning`, `output`, `actions`, `cancel-button`, `retry-button`, `metric-label`, `metric-value`
(carries `data-variant`), `metric` (one metric label/value pair), `empty`.

**Themeable custom properties:** `--lr-agent-run-spin` (default `var(--lr-transition-ambient)`, i.e.
`1.8s ease-in-out`, collapsing to `0.001ms linear` under `prefers-reduced-motion`) — the
current-step icon's rotation duration/timing. `--lr-agent-run-compact-padding` (default
`var(--lr-space-s)`) and `--lr-agent-run-compact-gap` (default `var(--lr-space-s)`) — `[part="base"]`'s
padding, and the gap between its header and body, while `compact`; both are ignored while `compact`
is unset. Like the other density/state properties in this family they are inline `var()` fallbacks at
their point of use rather than `:host` declarations, so either can be set on the element _or on any
ancestor_ — one rule on a run list retunes every compact run inside it.
`--lr-agent-run-background` (default `var(--lr-color-surface)`), `--lr-agent-run-border-color`
(default `var(--lr-color-border)`) and `--lr-agent-run-radius` (default `var(--lr-radius)`) retune
`[part="base"]`'s card chrome without a `::part(base)` override; `frame="plain"` still removes all
three outright.

**Additional API surface:**

- `--lr-agent-run-metric-brand-color` — Brand metric value. Default: `var(--lr-color-brand)`.
- `--lr-agent-run-metric-danger-color` — Danger metric value. Default: `var(--lr-color-danger)`.
- `--lr-agent-run-metric-success-color` — Success metric value. Default: `var(--lr-color-success)`.
- `--lr-agent-run-metric-warning-color` — Warning metric value. Default: `var(--lr-color-warning)`.
