Skip to content

[Feature] Add read-only agent monitor TUI (Graph + Timeline) - #5339

Open
ychu-msft wants to merge 7 commits into
github:mainfrom
ychu-msft:agent-monitor-tui
Open

ychu-msft wants to merge 7 commits into
github:mainfrom
ychu-msft:agent-monitor-tui

Conversation

@ychu-msft

@ychu-msft ychu-msft commented Nov 3, 2026 •

Copy link
Copy Markdown

Summary

Add an independent, read-only terminal viewer under tools/agent-monitor for one explicitly selected local Copilot CLI session, styled with Copilot CLI's own interface language. It answers the questions in the feature request: which agent launched which, who waited on whom and for how long, and what each finished execution produced.

Related: #1783

This is a standalone sidecar TUI, not a change to the Copilot CLI runtime or its built-in /tasks interface.

Screenshots

From a fictional demo session (synthetic events, no real transcript).

Graph (default view): spawn tree with launch modes and recorded wait durations; the dialog shows the selected agent's task, result and relationships.

Graph view

Graph, selecting an agent that is blocked on the sync agent it launched:

Graph view with a waiting agent

Timeline: one swimlane per execution plus the main session's turns, waiting segments (╍), wait connectors (▾), a later turn of a reused agent, and the now cursor.

Timeline view

Open it from Copilot CLI

tools/agent-monitor/extension is an experimental Copilot CLI extension that adds /agent-monitor [graph|timeline|text] to the session you are working in. It prints the session's agent tree in the conversation, then opens the interactive Graph or Timeline beside the CLI as a Windows Terminal (or tmux) split pane:

● Agents · 7 executions: 1 running, 1 waiting, 3 done, 1 replied, 1 failed
  ○ main session · idle · 2m 41s
  ├─ ✓ api-consumers · explore · 9.0s · done
  │  └─ ↩ api-consumers · explore · turn · 6.7s · replied
  ├─ ✓ paging-scout · explore · 6.3s · done
  ├─ ✓ plan-critic · rubber-duck · 17.1s · done
  ├─ ◌ paging-impl · general-purpose · waiting on unit-tests 42.8s
  │  └─ ◐ unit-tests · task · 42.7s · running
  └─ ✗ web-build · task · 53.5s · failed

Proposal: a built-in Agents tab

The extension API has no way to add a tab to Copilot CLI's own tab bar, so the views open beside it. Built into the CLI, they could be one more tab next to Current and Sessions, with Graph and Timeline as sub-views:

Mockup: Agents tab with the Graph view

Mockup: Agents tab with the Timeline view

What changed

  • Copilot CLI look: tab bar, blue query chips, ·-separated key hints, bordered detail dialog, and Primer semantic colors for the /theme modes (--theme default|light|dim|high-contrast|colorblind).
  • Graph (default view): spawn tree with automatic layout. Edges show bg / sync plus recorded wait durations, naming the waiter when it is not the edge's parent. A reused agent's later turns sit side by side under its first turn. Cards narrow to fit a wide fan-out; beyond that the graph scrolls with the selection.
  • Timeline view: swimlanes for every execution plus the main session's turns, waiting segments and connectors, a now cursor, and zoom/pan. The default window focuses on agent activity.
  • Detail dialog: task prompt, final message or error (latest message while running), and recorded relationships. Tool calls stay hidden until t is pressed. Below 100 columns the dialog uses one column.
  • Statuses: done, failed, cancelled (recorded cancelled: true, not a failure), replied (final answer and turn end recorded without a lifecycle event), and last-observed running / waiting.
  • Replay and live follow remain read-only; partial records, source resets, session shutdown/resume, unsupported agent data, and source errors stay explicit.
  • Copilot CLI extension (experimental): /agent-monitor [graph|timeline|text] prints the agent tree in the conversation and opens the interactive view beside the CLI; the viewer also takes --view graph|timeline.

Review

Reviewed adversarially by two opposing agent groups, each with a separate production-code and test-code reviewer: one group argued for defects, the other challenged each claim against the event schema, synthetic reproductions, and aggregate counts from local logs. Confirmed findings were fixed in e40bc24. All 13 findings from the automated Copilot review on this PR were confirmed and fixed in f1b635c (control-sequence cleaning for every drawn string, read-failure reporting, shutdown/resume and superseded-turn lifecycle cases, early waits, multi-day timeline ticks, and tree-build cost).

Findings and resolutions
Area Finding Resolution
Lifecycle session.resume after session.shutdown left the session ended with a frozen clock Resume makes the session live again (+test)
Lifecycle A completion or cancellation for a reused agent rewrote its first execution; cancelled: true was shown as done Settles the agent's open execution, never overwrites a recorded outcome, new cancelled status (+test)
Lifecycle Progress (phase: commentary) messages became results; stale replied state and end time Only phase-less or final_answer replies count; replied needs a final answer in the current turn (+test)
Lifecycle Rejected/blocked session.task_complete would show as done Only accepted completions complete an agent (+test)
Robustness Tool arguments of unexpected types stopped the viewer Ignored; only read_agent targets are read (+test)
Layout Each follow-up nested one level deeper, so long conversations overflowed the Timeline labels Later turns grouped under the first turn; Timeline indentation capped (+test)
Layout Five parallel agents overflowed 120 columns; 80-column header overlap; a tick label glued to now; a wide character at the right edge widened a row Adaptive card width, progressive header, label gap, wide-character fix (+tests)
Performance Off-screen graph drawing and re-wrapping long results on every frame; unused retained strings Viewport clipping, wrap cache, unused fields removed
Accuracy Main tool count capped at the 200-entry buffer; silent relationship truncation; text cache ignored log generation; clock kept moving after the source stopped Total count, +N more line, generation-aware key, frozen clock
Tests Assertions that could not fail (sanitization, legend-matched Timeline checks, duplicate events) Rewritten as lane-specific and visible-text checks
Tests Gaps: reader offsets past 64 KB and across polls, lazy-load race, reset, display names vs. agent IDs, graph scrolling Added; guard tests mutation-checked
Decision Defense objected to labelling waits from non-parents on a spawn edge, and to adaptive card widths Kept: the label names the waiter explicitly (as later-turn edges already did), and common 4–5-way fan-outs now fit without hiding cards

Validation

  • npm run typecheck and the strict unused-code check (--noUnusedLocals --noUnusedParameters) pass.
  • npm test: 37/37 pass. The 10 tests for the review fixes fail on the previous commit; each of the 5 new guard tests fails when its guard is removed; the 8 tests added for the automated review findings fail without f1b635c.
  • npm run build passes; built --help verified.
  • Replay of 219 local session logs (aggregate counts only, no content committed): 5,040 Graph/Timeline frames at 80×24, 120×36 and 160×48 rendered with 0 errors and 0 mis-sized rows; maximum tree depth is now 6. Of 9 recorded cancellations, 1 cancels a follow-up turn (now cancelled); 8 arrive after the agent had already completed with no follow-up turn and now keep completed instead of moving its end time to the cancellation. One CLI 1.0.21 log is rejected with an explicit diagnostic.
  • Windows ConPTY end-to-end run of the built CLI on this branch: Graph/Timeline switching, resizing through a too-small terminal and back, live follow of session.shutdown (ended) and session.resume (following again), quit with exit code 0 and alternate-screen restore, the source log left byte-for-byte unchanged, and a malformed record stopping the source with exit code 1. The run also found that keys arriving in one input chunk (a held key during a slow render) were dropped; fixed in e021792 with a test.
  • Extension, in a real Copilot CLI 1.0.105 session started with --experimental under ConPTY: /extensions manage lists agent-monitor as running, and /agent-monitor text prints the tree in the conversation. The split-pane launch was checked in Windows Terminal: the pane's process received the viewer arguments intact, including a Node.js path containing spaces.
  • Only synthetic fixtures and fictional screenshots are committed; private session logs are not.

Local preview

Requires Node.js 22+ and a truecolor terminal (Windows Terminal works). In a separate terminal tab:

Set-Location "<checkout>\tools\agent-monitor"
npm ci
npm run build
node .\dist\cli.js --session "<absolute-session-directory>"

Keys: j/k select, Tab or v switches Graph/Timeline, f filters, t toggles tool calls, Page Up/Down scrolls the result, +/- and ←/→ zoom and pan the Timeline, q quits. To use it from inside Copilot CLI, see the extension section of the README.

Limitations

  • The verified on-disk format is Copilot CLI 1.0.104 and 1.0.105 and is version-sensitive.
  • Copilot CLI extensions are experimental, and the extension API cannot add tabs to the CLI's own tab bar.
  • Spawn edges and recorded waits are not a complete prerequisite DAG. Unrecorded dependencies are labeled not recorded rather than inferred.
  • Ephemeral events, such as live shell output, and unrecorded results, cancellation, or liveness cannot be reconstructed.
  • Building this package does not rebuild or replace the copilot executable.

ychu-msft and others added 5 commits November 2, 2026 14:00
Add an independent terminal viewer for invocation relationships,
explicit waits, and retained agent results from local CLI event logs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the list view with Graph (default) and Timeline tabs that use
Copilot CLI's tab bar, query chips, key-hint footer, detail dialog and
Primer theme modes. Record wait history, main-session turns, launch mode,
prompts and follow-up links; keep tool calls hidden until toggled.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Lifecycle and attribution:
- session.resume after session.shutdown makes the session live again.
- subagent.completed/failed settle the agent's open execution instead of
  rewriting its first one; recorded outcomes are never overwritten.
- cancelled: true is shown as its own "cancelled" status, not done/failed.
- Only phase-less or final_answer messages count as results; "replied"
  requires a final answer in the current model turn.
- Rejected or blocked session.task_complete requests no longer complete
  an agent.
- Tool arguments of unexpected types no longer stop the viewer.

Rendering:
- Later turns of a reused agent sit under its first turn (bounded depth);
  Timeline indentation is capped.
- Graph cards narrow to fit wide fan-outs before scrolling; off-screen
  content is skipped; edge labels use the free space on their row.
- Timeline tick labels keep a gap from the now marker; header chips stay
  readable at 80 columns; the inspector splits at 100 columns as documented
  and shows tool calls in single-column mode; relationship overflow is
  reported; wrapped text is cached; wide characters at the right edge no
  longer widen a row.
- Main tool count reports the total, not the 200-entry buffer.

Tests cover each fix plus reader offsets across polls/64 KB chunks, the
lazy-load race, reset, display names and graph scrolling.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Graph and Timeline captures from a fictional demo session, linked from the
README.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Ink delivers ordinary keys that arrive together (a held key while a frame
renders, buffered input) as one string, so the viewer dropped them. Apply
each key in order, rebuilding the tree per key so a filter change followed
by navigation in the same chunk stays consistent.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ychu-msft
ychu-msft requested review from a team and an auto review from Copilot November 3, 2026 01:44
@ychu-msft ychu-msft changed the title Add read-only agent monitor TUI (Graph + Timeline) [Feature] Add read-only agent monitor TUI (Graph + Timeline) Nov 3, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unsanitized launch IDs can trigger clipboard-changing terminal sequences on exit, while uncleaned display text can overflow reserved UI fields.

13 open issues
1 file not reviewed
  • tools/agent-monitor/package-lock.json: Generated file
What changed in this PR

Adds a standalone, read-only terminal monitor for one explicitly selected local Copilot CLI session. It provides agent-execution visibility related to #1783 without changing the CLI runtime or built-in /tasks interface.

Changes:

  • Adds Graph and Timeline views for recorded launches, waits, execution outcomes, and reused-agent turns.
  • Implements incremental log replay and live following, on-demand text loading, and source diagnostics.
  • Provides themed, responsive layouts, keyboard controls, synthetic tests, and setup documentation.
File Description
tools/​agent-monitor/​tsconfig.json Configures strict TypeScript checking.
tools/​agent-monitor/​tsconfig.build.json Configures source compilation into dist.
tools/​agent-monitor/​test/​tree.test.ts Tests hierarchy, filtering, layout, and activity spans.
tools/​agent-monitor/​test/​model.test.ts Tests lifecycle, outcomes, relationships, and follow-ups.
tools/​agent-monitor/​test/​fixture.ts Supplies synthetic session events.
tools/​agent-monitor/​test/​events.test.ts Tests incremental reads, lazy text loading, resets, and malformed records.
tools/​agent-monitor/​test/​App.test.tsx Tests views, controls, responsive layouts, and asynchronous loading.
tools/​agent-monitor/​src/​tree.ts Builds filtered execution trees and shared status/time labels.
tools/​agent-monitor/​src/​timeline.ts Draws execution lanes, waits, time axes, zoom, and pan.
tools/​agent-monitor/​src/​theme.ts Defines five semantic color palettes.
tools/​agent-monitor/​src/​screen.ts Implements styled terminal cells, clipping, and text helpers.
tools/​agent-monitor/​src/​model.ts Reconstructs agent executions, lifecycle states, and recorded relationships.
tools/​agent-monitor/​src/​graph.ts Draws adaptive spawn trees with wait labels and scrolling.
tools/​agent-monitor/​src/​events.ts Reads JSONL incrementally and loads recorded text on demand.
tools/​agent-monitor/​src/​cli.tsx Adds session selection, theme options, and terminal startup/cleanup.
tools/​agent-monitor/​src/​chrome.ts Draws tabs, hints, and the detail inspector.
tools/​agent-monitor/​src/​App.tsx Coordinates live following, selection, input, and rendering.
tools/​agent-monitor/​README.md Documents setup, controls, compatibility, and limitations.
tools/​agent-monitor/​package.json Defines standalone dependencies and development scripts.
tools/​agent-monitor/​package-lock.json Locks package dependencies.
tools/​agent-monitor/​.gitignore Excludes dependencies and generated build output.

Review effort: Max (auto)

Comment thread tools/agent-monitor/src/cli.tsx Resolved
Comment thread tools/agent-monitor/src/screen.ts Resolved
Comment thread tools/agent-monitor/src/App.tsx Resolved
Comment thread tools/agent-monitor/src/App.tsx Resolved
Comment thread tools/agent-monitor/src/App.tsx Resolved
Comment thread tools/agent-monitor/src/model.ts Resolved
Comment thread tools/agent-monitor/src/model.ts Resolved
Comment thread tools/agent-monitor/src/model.ts Resolved
Comment thread tools/agent-monitor/src/timeline.ts Resolved
Comment thread tools/agent-monitor/src/tree.ts Resolved
ychu-msft and others added 2 commits November 3, 2026 09:56
- Clean terminal control sequences in every drawn, measured or fitted
  string, and in the error printed after the alternate screen is restored.
- Report task-prompt read failures, wrap read errors to the message
  column, show current warnings ahead of an informational reset notice,
  and only reuse loaded text within the same source generation.
- Close the open main turn on session.shutdown; mark an execution
  superseded by an idle follow-up as unknown; show the main session as
  waiting whenever it has an outstanding blocking read; attach waits
  recorded before their target was known to its first execution.
- Let timeline ticks grow in whole days for long windows.
- Copy the unconsumed reader tail instead of retaining the whole buffer,
  and resolve first turns once per tree build (2,000-turn chain:
  219 ms to 5 ms per build).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- extension/extension.mjs: experimental Copilot CLI extension adding
  /agent-monitor [graph|timeline|text]. It prints the session's agent tree in
  the conversation and opens the interactive view beside the CLI in a
  Windows Terminal or tmux split pane (otherwise it prints the command).
- src/summary.ts: the plain-text agent tree, built from the same model.
- --view graph|timeline, and v as a second key for switching views.
- Treat 1.0.105 session logs as verified (local 1.0.105 sessions replay
  without errors).
- docs/: mockups of the two views as an Agents tab in Copilot CLI's own
  tab bar, for discussing a built-in version.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants