Skip to content

Restore the live agents panel above the prompt - #385

Merged
TheGreatAxios merged 5 commits into
mainfrom
cl-5646-live-sub-agent-panel-above-the-prompt-regressed-to-a-single
Aug 8, 2026
Merged

Restore the live agents panel above the prompt#385
TheGreatAxios merged 5 commits into
mainfrom
cl-5646-live-sub-agent-panel-above-the-prompt-regressed-to-a-single

Conversation

@TheGreatAxios

Copy link
Copy Markdown
Collaborator

Summary

  • The OpenTUI cutover collapsed live sub-agents to a single chrome line of counts (agents: 5 live · 4 cancelled); this restores the pre-cutover behavior of one row per running agent (elapsed, current tool, stalled marker), reusing the existing agentProgress() computation rather than a second progress model.
  • The panel is bounded to AGENTS_PANEL_MAX_VISIBLE rows with a trailing +N more, sized through the geometry resolver's zone max (never a fixed guess), and costs zero rows/zero chrome when nothing is running.
  • The sticky 200ms poll now also repaints the agents panel so the elapsed clock and stalled flag stay live on wall clock, not just on the next unrelated chrome push. Row rebuild in shell.ts is skipped unless the panel's actual lines changed.

Overlap with in-flight work

CL-5205 (chrome diet), CL-4867 (drop glyph icons), and CL-5468 (prompt model bar paints over overlays) are all in progress in this same chrome/layout area. This diff only touches the agents zone's row budget and content — no glyphs added, no other zone's collapse behavior changed.

Test plan

  • bun run typecheck / bun run build / bun run test all green through the repo's test-lock wrapper (one pre-existing, unrelated failure: lsp-availability.test.ts's environment-dependent language-server-detection check)
  • New tests: geometry bounds (N running → N rows, capped, zero → zero), chrome-state row formatting (stalled distinct from working, "+N more" bounding, observe override), row-diff/rebuild-skip regression, sticky-poll-driven clock refresh
  • Verified by running bun src/tui-opentui/demo.ts under tmux and toggling the agents chrome zone live — confirmed the panel renders above the transcript with real elapsed/tool detail

The OpenTUI cutover collapsed live sub-agents to a single chrome line
of counts ("agents: 5 live · 4 cancelled"), losing the one-row-per-agent
panel the pre-cutover Ink shell rendered. Per-agent elapsed/tool/stall
detail already existed in agent-progress.ts but only reached a
transcript row trailer that scrolled away.

The agents zone now renders one row per running agent (elapsed, current
tool, stalled marker), bounded to AGENTS_PANEL_MAX_VISIBLE with a
trailing "+N more" row, and sized through the geometry resolver's zone
max rather than a fixed guess. Zero running agents costs zero rows.
…changed

Critique review found two gaps in the agents panel: its elapsed clock
and stalled flag only refreshed on the next unrelated chrome event
(goal change, subagent progress), so a worker that went quiet with no
further events never flipped to stalled; and setChromeZones rebuilt
every agent row's TextRenderable on every call, including pushes that
only touched goal or task.

The sticky poll now repaints the agents panel on its own 200ms tick,
matching the cadence already used for the transcript trailer. Row
rebuild is now skipped unless the panel's actual lines changed.
@linear-code

linear-code Bot commented Aug 8, 2026

Copy link
Copy Markdown

CL-5646

Second-review pass found that the panel took whatever order the caller
passed running agents in. The real feed sorts running sessions
newest-first, so a fan-out past the visible cap folded the oldest —
and therefore most likely stalled — worker into the trailing "+N more"
row, silently hiding the one agent an operator most needs to see.

Rows are now selected oldest-last-activity-first before slicing to the
visible cap. Also shares the "stalled" row suffix as one constant
between the formatter and the renderer instead of two independent
string literals, and gives the panel's working rows a color distinct
from the task zone immediately above it.
Greybeard's review found the fan-out fix from the previous commit had
introduced a worse bug: sorting visible rows by lastActivityAt made
every busy agent's row jump position on its next tool event, since
that field changes on nearly every repaint. Selection (which agents
survive a fan-out past the visible cap) and presentation (the order
those survivors render in) are different questions — selection keeps
the staleness sort so a stalled agent is never hidden, presentation
now keys on startedAt, which is stable for the life of a running
agent, with agentId as a tiebreak.

Also: the agents zone now shrinks one row at a time under space
pressure instead of collapsing straight to zero, matching how the
progress zone already degrades — a 1-row panel is still meaningful
(it carries the stalest agent plus its "+N more" trailer), so it earns
gradual treatment instead of vanishing under exactly the pressure an
operator most needs it. Rows are now width-clamped to the zone's
measured content width, ellipsizing the free-form label while always
preserving the elapsed/tool/stalled tail. The panel's stalled flag is
now carried as an explicit field on each row instead of being encoded
as a string suffix the renderer had to parse back out. The sticky
poll's per-tick chrome repaint is now gated on a running agent
actually existing, since it was otherwise repainting chrome twice a
tick through setChromeZones's own unchanged-zone repaint.
fitAgentRow measured with String.length and cut with String.slice, so a
CJK or emoji description — free-form model-authored text — undercounted
its true width and the row overflowed its zone and wrapped, which is the
bug the clamp exists to prevent. Route through stringWidth/sliceToWidth,
which the repo already owns and holds to a contract test against OpenTUI.

The degenerate branch also contradicted its comment: it promised the
tail and returned the head of the label. Add sliceTailToWidth so it keeps
the tail's trailing end, where the stalled marker lives.
@TheGreatAxios
TheGreatAxios merged commit 34c1acf into main Aug 8, 2026
3 checks passed
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.

1 participant