Restore the live agents panel above the prompt - #385
Merged
TheGreatAxios merged 5 commits intoAug 8, 2026
Merged
Conversation
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.
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
agents: 5 live · 4 cancelled); this restores the pre-cutover behavior of one row per running agent (elapsed, current tool, stalled marker), reusing the existingagentProgress()computation rather than a second progress model.AGENTS_PANEL_MAX_VISIBLErows 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.shell.tsis 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
agentszone'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 testall green through the repo's test-lock wrapper (one pre-existing, unrelated failure:lsp-availability.test.ts's environment-dependent language-server-detection check)bun src/tui-opentui/demo.tsunder tmux and toggling the agents chrome zone live — confirmed the panel renders above the transcript with real elapsed/tool detail