From 6b4b0f11c0222b034ba1bb91bf1ccce72524962a Mon Sep 17 00:00:00 2001 From: iris Date: Wed, 10 Jun 2026 15:38:04 +0200 Subject: [PATCH] docs(web-ui): document turn start/end times + duration on the agent terminal Follow-up to the turn-time feature: the terminal now stamps a wall-clock time on the turn-start / turn-end rows and an elapsed duration on turn-end, sourced from a per-event `ts` (unix seconds) that the backend serializes as a flattened sibling of the event tag on both the live SSE frame and each history row. - terminal-rendering.md: add the `.turn-time` row to the taxonomy table + a note on the ts source and the graceful degradation when a frame omits ts. - web-ui/agent.md: note the ts sibling on the emitted events, and the time/duration suffixes on the TurnStart / TurnEnd renderings. --- docs/terminal-rendering.md | 10 ++++++++++ docs/web-ui/agent.md | 12 +++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/docs/terminal-rendering.md b/docs/terminal-rendering.md index f62d5c47..ed2946a3 100644 --- a/docs/terminal-rendering.md +++ b/docs/terminal-rendering.md @@ -38,6 +38,7 @@ parent's negative pull. | `.turn-body` | (child div under turn-start) | fg | same | the wake-prompt body | | `.turn-end-ok` | `✓ turn ok` | green, left rule | `LiveEvent::TurnEnd { ok: true }` | harness | | `.turn-end-fail` | `✗ turn fail — note` | red, left rule | `LiveEvent::TurnEnd { ok: false }` | harness | +| `.turn-time` | `· HH:MM:SS` on turn-start; `· HH:MM:SS · ` on turn-end (child span) | muted, smaller | per-event `ts` (unix seconds) on the live frame + history row | harness | | `.text` | (no prefix; markdown body) | fg | claude `assistant.content[].text` | stream-json | | `.thinking` | `· thinking …` | muted, italic | claude `assistant.content[].thinking` | stream-json | | `.tool-use` (flat) | `→ Name args…` | cyan | tool_use w/o rich renderer | stream-json | @@ -55,6 +56,15 @@ parent's negative pull. | `.sys` | `! {json…}` | amber/orange | catch-all for stream shapes `renderStream` didn't classify | catch-all | | Banner shimmer | mauve | turn in flight (ref-counted) | — | `setBannerActive` | +The `.turn-time` span is appended to the turn-start / turn-end rows from +the event's `ts` (unix seconds), which the backend serializes as a +flattened sibling of `kind` on both the live SSE frame and each history +row — so the same renderer path stamps live tail and replayed scrollback +identically. Turn-end also shows the elapsed duration (end − start), +paired against the most recent open turn-start. The read is guarded on a +numeric `ts`: if a frame omits it the rows render without the time +suffix, so the terminal degrades cleanly against older event shapes. + ## Renderer dispatch `renderStream(v, api)` walks each stream-json line: diff --git a/docs/web-ui/agent.md b/docs/web-ui/agent.md index d0b35e3c..3d93cfef 100644 --- a/docs/web-ui/agent.md +++ b/docs/web-ui/agent.md @@ -182,7 +182,9 @@ Each agent runs an `events::Bus`: a `tokio::sync::broadcast` plus a sqlite-backed history at `/state/hyperhive-events.sqlite`. The harness emits `TurnStart { from, body, unread }`, `Stream(value)` (one per parsed stream-json line), `Note`, -`TurnEnd { ok, note }`. The web UI: +`TurnEnd { ok, note }`. Each event also carries a `ts` (unix +seconds) — a flattened sibling of the event tag on both the live +SSE frame and the replayed history rows. The web UI: - fetches `GET /events/history` on page load and replays the last 2000 events (oldest first, with `.no-anim` so they don't @@ -212,8 +214,12 @@ Per-stream rendering: - `Stream` `system init`, `result`, `rate_limit_event` are dropped — too noisy. - `Note` → `· text`. -- `TurnEnd` → `✓ turn ok` / `✗ turn fail — note`, triggers a - `refreshState()`. +- `TurnStart` → `◆ TURN ← ` with the wake-prompt body; a + muted `· HH:MM:SS` time suffix from the event `ts`. +- `TurnEnd` → `✓ turn ok` / `✗ turn fail — note`, with a + `· HH:MM:SS · ` suffix (duration = end − the paired + turn-start), triggers a `refreshState()`. The time suffix is + guarded on a numeric `ts`, so rows degrade cleanly when absent. ## Terminal-embedded prompt