docs: update web-ui.md for agent header redesign and in-flight rebuild badge (#394 #398)

This commit is contained in:
lexis 2026-05-25 01:43:54 +02:00
parent c08218acdc
commit 38920d3af1

View file

@ -256,9 +256,13 @@ guess from container state.
`forge``http://host:3000`, `external` → already absolute). `forge``http://host:3000`, `external` → already absolute).
Status badges follow — `⊘ rate limited` (red, while the harness Status badges follow — `⊘ rate limited` (red, while the harness
is parked after a 429), `needs login`, `needs update` — in-flight is parked after a 429), `needs login`, `needs update` — in-flight
`◐ `◐ pending-state…` pill (replaces buttons during operator-initiated
pending-state…` pill (replaces buttons during start / stop / start / stop / restart / rebuild / destroy). Additionally, when a
restart / rebuild / destroy), container name + port, and a rebuild-queue entry for this agent is `queued` or `running` but no
operator-initiated transient is set, the card surfaces a `building…` /
`meta-updating…` badge sourced from `rebuildQueueState` (#398) —
so the SW4RM tab shows the same rebuild progress visible on the
SYST3M tab's R3BU1LD QU3U3. Container name + port, and a
`ctx · Nk` chip showing the agent's last-turn context size `ctx · Nk` chip showing the agent's last-turn context size
(from `ContainerView.ctx_tokens`, read from the turn-stats (from `ContainerView.ctx_tokens`, read from the turn-stats
sqlite on each `build_all` sweep; absent until the first turn). sqlite on each `build_all` sweep; absent until the first turn).
@ -476,43 +480,51 @@ Three fixed-position layers frame a full-viewport terminal:
**Fixed-overlay header** (`<header class="agent-header">`): frosted **Fixed-overlay header** (`<header class="agent-header">`): frosted
glass — `backdrop-filter: blur` lets scrolled terminal rows show glass — `backdrop-filter: blur` lets scrolled terminal rows show
through. Left to right: through. Three flex columns (#394 redesign):
- Agent icon (`<img src="/icon">`).
- Title (`<h2 id="title">`) + meta-nav (`<nav id="meta-links">`): - **Agent icon** (`<img class="agent-icon">`): full-height square
backend-supplied `StateSnapshot.links` rendered as icon-only identity anchor (6em, `height: 100%; aspect-ratio: 1`). Falls back
anchors. Always includes `📊 stats` (`kind = Container`); to the dimmed hyperhive mark on load error.
`🖥 screen` when the VNC compositor is enabled; `⬡ forge` (profile) - **Main column** (`.agent-header-main`): two rows.
+ `↳ config` (agent-configs mirror) when the agent has a forge - Row 1 (`.agent-header-title-row`): title (`<h2 id="title">`) +
account; followed by any `hyperhive.dashboardLinks` extras meta-nav (`<nav id="meta-links">`). Meta-nav renders
(`kind = External`). The dashboard card's icon strip is the same backend-supplied `StateSnapshot.links` as icon-only anchors — always
list via `GET /api/agent/{name}/links` — agent backend is the `📊 stats` (`kind = Container`); `🖥 screen` when VNC is enabled;
single source of truth. `⬡ forge` (profile) + `↳ config` (agent-configs mirror) when the
- **State row** (`<div id="state-row">`): alive badge + state badge agent has a forge account; any `hyperhive.dashboardLinks` extras
+ model chip + ctx badge + cost badge + last-turn chip + cancel (`kind = External`). A `↑ dashboard` link is prepended by the JS
button + new-session button. so the host dashboard is one click away. `GET /api/agent/{name}/links`
- Alive badge: `● alive` (green) / `⊘ rate limited` (red) / is the single source of truth.
`◌ needs login` / `◌ logging in` / `○ offline` / `… connecting`. - Row 2 (`.agent-state-row`): alive badge + state badge + model chip
Driven by `LiveEvent::StatusChanged`. + ctx badge + cost badge + last-turn chip + cancel button.
- State badge: `💤 idle` / `🧠 thinking` / `📦 compacting` / - Alive badge: `● alive` (green) / `⊘ rate limited` (red) /
`○ offline` / `… booting` + age suffix. Driven by `◌ needs login` / `◌ logging in` / `○ offline` / `… connecting`.
`LiveEvent::TurnStateChanged ({ state, since_unix })`. Driven by `LiveEvent::StatusChanged`.
- Model chip: `model · <name>`. Driven by `LiveEvent::ModelChanged`. - State badge: `💤 idle` / `🧠 thinking` / `📦 compacting` /
- Ctx badge: `ctx · 142k` — last inference's prompt size (the `○ offline` / `… booting` + age suffix. Driven by
context window utilisation number to watch before compacting). `LiveEvent::TurnStateChanged ({ state, since_unix })`.
Tooltip shows % of window when `context_window_tokens` is known. - Model chip: `model · <name>`. Driven by `LiveEvent::ModelChanged`.
- Cost badge: `cost · 1.3M` — cumulative tokens billed across every - Ctx badge: `ctx · 142k` — last inference's prompt size.
inference in the last turn. Tool-heavy turns rebill the cached Tooltip shows % of window when `context_window_tokens` is known.
prefix per call, so this routinely exceeds the window — cost - Cost badge: `cost · 1.3M` — cumulative tokens billed across every
signal, not size signal. inference in the last turn (tool-heavy turns rebill the cached
- Both driven by `LiveEvent::TokenUsageChanged { ctx, cost }` at prefix per call — cost signal, not size signal).
turn-end. - Both driven by `LiveEvent::TokenUsageChanged { ctx, cost }` at
- `■ cancel turn` (visible while thinking) → `POST /api/cancel`. turn-end.
- `↻ new session` (always, amber) → `POST /api/new-session`; next - `■ cancel turn` (visible while thinking) → `POST /api/cancel`.
turn drops `--continue`. - **Right cluster** (`.agent-header-pills`): flyout pills + overflow.
- **Inbox pill** (`📬 inbox · N`): hidden when empty; click opens the - **Inbox pill** (`📬 inbox · N`): hidden when empty; click opens
inbox flyout in the side panel. the inbox flyout in the side panel.
- **Loose-ends pill** (`🪢 loose ends · N`): hidden when empty; click - **Loose-ends pill** (`🪢 loose ends · N`): hidden when empty;
opens the loose-ends flyout in the side panel. click opens the loose-ends flyout.
- **Overflow button** (`⋯`): always visible. Opens a frosted popover
(`#overflow-menu`, positioned outside the header to escape any
stacking context) with three rows: `↑ dashboard` (link), `↻ rebuild
container` (POST confirm, same action as the dashboard R3BU1LD
button), `↻ new claude session` (POST confirm → `POST
/api/new-session`; next turn drops `--continue`). Both destructive
actions require one extra click to acknowledge (#394 — rare ops
shouldn't live in the primary state strip).
`/api/state` is fetched once on cold load (+ while `/api/state` is fetched once on cold load (+ while
`status === 'needs_login_in_progress'`); all other updates arrive via `status === 'needs_login_in_progress'`); all other updates arrive via