fix(tui): name agents in the spawn tree and keep teammates past their turn - #956
Merged
Merged
Conversation
… turn The agents overlay listed each spawn only by its task description. A persistent teammate also dropped out of the overlay once the turn that spawned it ended, even though it kept working. - gatewayClient and types: keep the spawn's `name` and `subagent_type` next to its description. Any status that isn't live, including `interrupted`, now ends the run. - Overlay rows start with the name, or else an agent type that isn't one of the defaults. The detail pane shows both, and replayed trees keep them. - A session-scoped roster ($sessionAgents) outlives the turn state. The overlay carries over running agents that the current turn no longer lists. Finished entries are pruned at turn start, and the roster is cleared only when the backend exits. - agent.py: per-message progress sends the resolved agent type. The sync end-of-run frame sends the spawn's own name instead of its type. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Test Results 5 files 1 021 suites 20m 38s ⏱️ Results for commit c3fcdb0. |
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
This fixes two problems in the TUI's agents overlay (the "Spawn tree"). Both came up while running a math team of named, persistent teammates.
1. Rows didn't name the agent
Each row showed only the task description, so a team of named specialists looked like a list of anonymous tasks.
name,descriptionandsubagent_typeas separate fields. The TUI lost the name in three places:gatewayClientusednameonly as a fallback for the goal (goal: description || name). The Agent tool always requires a description, so the name never survived.SubagentProgresshad no field for the name or the type.goal.nameandagentType.general-purpose,worker,fork) stay hidden, following the reference'suserFacingName.agent.py's per-message progress now sends the resolvedagent_def.agent_type. It used to send the raw tool input, which wasNonewhen the call didn't specify a type. The sync end-of-run frame now sends the spawn's ownname; it used to put the type there.2. Teammates vanished after the turn that spawned them
turnState.subagentsis turn-scoped.startMessage()andidle()both clear it, and the idle layout depends on that.gatewayClient.seenSubagentsis never cleared, though. So a teammate's later frames arrive assubagent.progress/subagent.complete, which only update existing rows and never create them. A persistent teammate therefore disappeared from the overlay while it kept working.$sessionAgents, that every subagent event updates.withCarriedAgents)./clear,/newand resume, because those keep the same agent-server process and its teammates keep running. It is cleared only when the backend process exits (forgetSessionAgents()).gatewayClientpublishedsubagent.completeonly forcompleted,failedandkilled. Aninterruptedframe fell through, and the row stayedrunningforever; with the roster, it would also have stayed pinned in the overlay. The backend reportsinterruptedfor a foreground subagent stopped with ESC or from the overlay (agent.py), a killed teammate (team_runtime.py), and an aborted workflow agent (workflow/runner.py). Any status other thanrunningorqueuednow ends the run.Before / after
The real built TUI was run in a PTY against a fake agent-server.
● Pin environment encode statement● fl-formalizer · Pin environment encode statement● Explore · Find cutoff…and● fl-formalizer · …Test plan
interruptedfullReset()and is emptied byforgetSessionAgents()subagentIdentity,subagentTitle,subagentAgentLabel,withCarriedAgentsandisSubagentAlivefullReset().main(7 pre-existing, plus 1 timing-sensitive test under load). Typecheck is clean. ESLint shows only pre-existing warnings, none on changed lines.test_system_prompt_full::…damped_wording…) also fails onmain; it comes from the developer's memory text.Follow-ups (not in this PR)
[away in history.delegation.status.Agent(<description>), not the agent's name.labelOfstill usesnameonly as a fallback.keepTerminalElseRunning).killed.normalizeSubagentStatusdoesn't recognize that status and falls back tocompleted, so the row shows ✓ instead of interrupted.🤖 Generated with Claude Code