diff --git a/README.md b/README.md index 015d534e3..6ccf10139 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,8 @@ Split a job across workers and get typed results back. task fans out into isolat _[Watch the capture ↗](https://omp.sh/clips/irc.mp4)_ +Watch the fan-out while it runs: `Alt+A` opens [Agent Hub](docs/agent-hub.md), where the roster shows current activity and usage for every subagent. Open one to read its live transcript, type a steering message, revive a parked worker, or kill a stuck one without aborting the parent session. + ### 06 · A second model, watching every turn. Pair a reviewer model to the 'advisor' role and it reads every turn the main agent takes, injecting notes inline — a quiet aside, a concern, or a hard blocker. It runs on its own context and its own model, so it catches what the doer rushed past. The main agent sees the note and course-corrects, or tells you why it won't. diff --git a/docs/advisor-watchdog.md b/docs/advisor-watchdog.md index e75afefd2..6d7594a7c 100644 --- a/docs/advisor-watchdog.md +++ b/docs/advisor-watchdog.md @@ -326,8 +326,8 @@ Paths derive from the owning session file (not the shared artifacts root), so ea Why a file: - **Usage attribution.** `omp stats` scans each session folder recursively, so advisor assistant turns (with their usage/cost) are attributed to the same project/session like any other subagent. Advisor "session update" prompts are persisted as `synthetic`, agent-attributed user messages so they never inflate user-message metrics. -- **Observability.** The Agent Hub discovers legacy and named `__advisor*.jsonl` files on open and shows each as a read-only `advisor`-kind transcript under its owning session. +- **Observability.** [Agent Hub](./agent-hub.md) discovers legacy and named `__advisor*.jsonl` files on open and shows each as a read-only `advisor`-kind transcript under its owning session. The file follows session switches: on `/new`, resume/switch, and branch the recorder reopens at the new session's path on the next advisor turn; before a `/drop` deletes the old artifacts dir the recorder feed is detached and drained so a queued write cannot recreate the deleted file. The on-disk log is append-only and independent of the in-memory context — re-primes and compaction never truncate it. -The advisor is never a peer. The `advisor`-kind registry ref is excluded from every agent-facing surface — the `hub` peer roster and broadcast targets, the subagent peer prompt, and the `history://` index/lookup/completions — and cannot be messaged (`hub` send and collab chat refuse it) or revived/killed from the Agent Hub or collab. It is not addressable as a peer, regardless of what tools it has been granted. +The advisor is never a peer. The `advisor`-kind registry ref is excluded from every agent-facing surface — the `hub` peer roster and broadcast targets, the subagent peer prompt, and the `history://` index/lookup/completions — and cannot be messaged (`hub` send and collab chat refuse it) or [revived or killed from Agent Hub](./agent-hub.md#persisted-agents-and-advisors) or collab. It is not addressable as a peer, regardless of what tools it has been granted. diff --git a/docs/agent-hub.md b/docs/agent-hub.md new file mode 100644 index 000000000..2208836b9 --- /dev/null +++ b/docs/agent-hub.md @@ -0,0 +1,95 @@ +# Agent Hub + +Agent Hub is the interactive TUI for watching and controlling subagents associated with the current session. It combines a live roster, per-agent activity and usage, transcript access, steering, revive, and kill controls. The main agent is not listed because its conversation is the ambient session view. + +The Hub also discovers parked subagents from the current session's persisted artifacts when a session is resumed. Advisor transcript files appear as read-only rows. + +## Open the Hub + +| Input | Behavior | +| -------------- | ---------------------------------------------------------------------------------------------- | +| `Alt+A` | Open or close Agent Hub through `app.agents.hub`. This opens the roster even when it is empty. | +| `Ctrl+S` | Open or close the same Hub through the legacy `app.session.observe` action. | +| Double-tap `←` | Open the Hub from an empty main-session editor when the current session has an agent to show. | + +Run `/hotkeys` to see the active chords. Remap either action in `~/.omp/agent/keybindings.yml`: + +```yaml +app.agents.hub: Alt+A +app.session.observe: Ctrl+S +``` + +The double-`←` gesture is not a keybinding action. While focused on a subagent, double-`←` returns to the main session instead of opening the Hub. + +## Roster and inspector + +The roster updates from the session's agent registry and progress events. Its responsive rows show: + +- status (`running`, `idle`, `parked`, or `aborted`), agent identity, parent, and unread IRC count; +- model role, resolved model, and age since last activity; +- assigned task or current activity; +- cost, active time or elapsed span, request count, tool-call count, and tokens. + +The header aggregates status and usage across measured agents. Press `t` to switch between the stable flat roster and a parent/child tree. + +On a wide terminal, the selected agent's inspector appears beside the roster. On a narrow terminal, press `Tab` to replace the roster with it. The inspector adds: + +- the current tool and arguments, last intent, and retry state; +- context-window use when available; +- parent and child lineage; +- output and patch paths, plus isolated-worktree branch metadata when present. + +Metrics depend on the progress or persisted usage data available for that agent. Missing data appears as `usage —` rather than an estimate. + +### Roster controls + +| Key or input | Action | +| --------------------------- | ---------------------------------------------------------------------------- | +| `j` / `k`, `↑` / `↓`, wheel | Select an agent. | +| `Enter` or click | Open the selected agent. | +| `t` | Toggle flat and parent/child views. | +| `Tab` | Toggle the inspector on narrow terminals. | +| `PageUp` / `PageDown` | Scroll an open inspector. | +| `r` | Revive the selected parked agent. | +| `x` | Abort a running turn if necessary, then kill and release the selected agent. | +| `Esc` | Close the inspector first on narrow terminals, then close the Hub. | + +Only `parked` agents can be revived. `x` is immediate; use it only when you intend to discard that agent instance. + +## Read and steer a subagent + +For a normal local subagent, `Enter` or click focuses the main TUI on that agent's session and closes the Hub. Focusing a parked agent revives it. The transcript, status line, and editor then belong to that subagent: + +1. Read its live transcript and tool activity. +2. Type a message and press `Enter` to steer a running turn or prompt an idle agent. +3. Press `Esc` with an empty editor, or double-tap `←`, to return to the main session. + +Steering uses the normal prompt path, so the message and response are written to the subagent's persisted session history. While a subagent is focused, `Esc` returns to the main session; it does not interrupt the subagent. + +Contexts without a local focusable session use the Hub's full-screen transcript viewer instead. This includes collab guests and advisor rows. The viewer incrementally tails the file-backed transcript and provides an input line only when the selected agent can be messaged. Sending there has the same semantics: revive if parked, steer if running, and prompt if idle. + +## Persisted agents and advisors + +Opening the Hub for a persisted session scans that session's artifact tree. Historical subagent JSONL files become parked rows; a killed agent's tombstone keeps it aborted. Nested subagents retain their parent/child lineage. Output and patch artifacts are attached to the corresponding inspector row. + +Advisor transcript files (`__advisor*.jsonl`) appear as `advisor`-kind rows under their owning session. They are observability records, not peers: + +- their transcripts can be opened and followed; +- they cannot be messaged; +- they cannot be revived; +- they cannot be killed. + +These restrictions also apply to collab guests controlling the host's Hub. + +## Related surfaces + +Agent Hub is the human-facing live session view. Adjacent commands and internal URLs serve narrower purposes: + +- `/jobs` prints a snapshot of running and recently settled asynchronous tool jobs. It does not replace the per-agent transcript or control view. +- `history://` gives the coding agent a concise transcript for a live or parked subagent. +- `agent://` resolves a subagent's saved final output artifact; it is not the live transcript. +- `hub` `list` exposes the peer roster to the coding agent, and `hub` `send` steers or follows up with a normal subagent programmatically. Messaging a parked subagent revives it. + +Advisor rows are intentionally excluded from the agent-facing `hub`, `history://`, and `agent://` peer workflows. + +See also [Task Agent Discovery and Selection](./task-agent-discovery.md), [Collaboration](./collab.md), and [Advisor, WATCHDOG.md, and WATCHDOG.yml](./advisor-watchdog.md). diff --git a/docs/collab.md b/docs/collab.md index 9aada8422..1a32139de 100644 --- a/docs/collab.md +++ b/docs/collab.md @@ -85,7 +85,7 @@ Guests with a full link can: - read the entire session (including the back-transcript at join time), - prompt the agent (rendered with their name badge on every participant's transcript; the LLM sees the prompt text verbatim — names are display-only), - interrupt the agent (Esc), -- use the Agent Hub against the host's subagents: live table and progress, chat (steers the host's subagent), kill, revive, and transcript viewing (fetched from the host on demand). +- use [Agent Hub](./agent-hub.md) against the host's subagents: live table and progress, chat (steers the host's subagent), kill, revive, and transcript viewing (fetched from the host on demand). - answer host interactive `select` and `editor` requests. The host broadcasts each pending request only to writable guests; the first submitted or cancelled response settles it and dismisses the other presentations. Guests with a view-only link can read everything live — back-transcript, streaming text, tool cards, subagent transcripts — but the host rejects prompting, interrupting, and agent control from them. diff --git a/docs/keybindings.md b/docs/keybindings.md index 824f00ea9..a06b30519 100644 --- a/docs/keybindings.md +++ b/docs/keybindings.md @@ -47,7 +47,7 @@ app.history.search: [] | `app.clipboard.pasteImage` | Linux: `Ctrl+V`; macOS: `Ctrl+V`, `Cmd+V`; Windows: `Ctrl+V`, `Alt+V` | Paste from the clipboard (image preferred, text fallback) | | `app.stt.toggle` | Unbound (hold `Space`) | Toggle speech-to-text. By default there is no key chord — hold the space bar to record (push-to-talk) and release to transcribe; bind a chord here for a press-to-toggle alternative | | `app.live.toggle` | `Ctrl+L` | Start or stop live voice mode (same as `/live`) | -| `app.agents.hub` | `Alt+A` | Open the agent hub | +| `app.agents.hub` | `Alt+A` | [Open the Agent Hub](./agent-hub.md) | On Windows Terminal, `Ctrl+V` may be handled by the terminal paste command before `omp` sees it; use the `Alt+V` fallback when clipboard image paste appears to do nothing. When the clipboard holds no image, `app.clipboard.pasteImage` pastes the clipboard text instead, so hosts that deliver only this chord (VS Code's integrated terminal when configured to forward `Ctrl+V`, Windows clipboard history via `Win+V`) work for both payload kinds. Windows Terminal also swallows `Ctrl+Enter`, so the `app.message.followUp` chord also binds `Ctrl+Q` — the same chord GitHub Copilot CLI uses — and the same chord submits the agent dashboard's new-agent description and hook-editor prompts. If your existing `keybindings.yml` already assigns `Ctrl+Q` to another action, that user remap wins and follow-up keeps `Ctrl+Enter` unless you explicitly bind `app.message.followUp`. diff --git a/docs/task-agent-discovery.md b/docs/task-agent-discovery.md index 77fa54e3d..f42729019 100644 --- a/docs/task-agent-discovery.md +++ b/docs/task-agent-discovery.md @@ -85,6 +85,10 @@ For a dispatch, set the agent name and task: `/model`'s Roles view can assign and persist custom role mappings such as `review`, `fast`, and `good`. Changing only the active or default session selection does not remap those roles. +## Watch running agents + +After dispatch, press `Alt+A` to open [Agent Hub](./agent-hub.md). Its live roster shows each task agent's status, current activity, model, age, and usage. Select an agent to read its transcript and steer it directly; parked agents can be revived from the same view. + ### `vibe_spawn` tier routing `vibe_spawn` maps `fast` to bundled `sonic` and `good` to bundled `task`. Both resolve through `task.agentModelOverrides` before their bundled agent model defaults (`src/vibe/runtime.ts`, `src/task/agents.ts`). diff --git a/docs/tui.md b/docs/tui.md index 82f90af98..a50ee6253 100644 --- a/docs/tui.md +++ b/docs/tui.md @@ -99,6 +99,10 @@ Then use `isKeyRelease()` / `isKeyRepeat()` if needed. - Overlay APIs exist in `TUI` (`showOverlay`, `OverlayHandle`). In interactive extension/custom UI, `custom(..., { overlay: true })` mounts your component through `TUI.showOverlay(...)`; without `overlay`, it replaces the editor component area directly. - Overlay custom UI is anchored at `bottom-center` with full terminal width/max height and is removed through the returned overlay handle when `done(...)` closes the flow. +### Built-in full-screen surfaces + +The coding-agent integration also mounts built-in full-screen surfaces outside `ctx.ui.custom(...)`. [Agent Hub](./agent-hub.md) is the live roster and control surface for subagents. Its file-backed transcript viewer borrows the alternate screen while it is open, then restores the Hub beneath it on close. + ## Mount points and return contracts ## 1) Extension UI (`ExtensionUIContext`)