Skip to content

fix(web): restore swarm member list after page refresh#1589

Open
wbxl2000 wants to merge 2 commits into
mainfrom
fix/web-swarm-roster-refresh
Open

fix(web): restore swarm member list after page refresh#1589
wbxl2000 wants to merge 2 commits into
mainfrom
fix/web-swarm-roster-refresh

Conversation

@wbxl2000

Copy link
Copy Markdown
Collaborator

Related Issue

No linked issue — the problem is explained below.

Problem

In the web UI, an AgentSwarm tool card loses its whole member list when the page is refreshed while subagents are still running: the card falls back to the "waiting for subtasks to join…" placeholder until the swarm's final tool result lands. Completed subagents never reappear at all.

Root cause: the card's live member rows only exist in the client's in-memory task store, populated by WS events. Only subagent.spawned carries the swarm identity metadata (parentToolCallId / swarmIndex / description), and on refresh that event is never replayed — the snapshot has no subagent roster, REST /tasks only serves the main agent's background tasks, and later subagent.* events carry just the subagentId, so the identity metadata is unrecoverable client-side.

What changed

  • Server: a new SubagentRosterTracker (same volatile-state pattern as the existing InFlightTurnTracker, owned by WSBroadcastService and updated inside its per-session dispatch queue) accumulates the live subagent roster per session and drops it on turn.ended, after which the swarm's <agent_swarm_result> tool output in the wire transcript is the restore source. The roster rides the session snapshot as an optional subagents field (protocol schema extended; optional for cross-version tolerance).
  • Web: the snapshot sync seeds tasksBySession from the roster (preserving any accumulated streamed output), and the taskCreated merge no longer lets a post-refresh skeleton re-projection clobber the roster-seeded description with the 'Sub Agent' placeholder. The explicit run_in_background flag now round-trips so foreground swarm members aren't misclassified as background agents.

This fits the existing refresh architecture: the snapshot is already the designated rebuild channel for volatile stream state (in_flight_turn, pending approvals/questions), and the roster is the same class of data. Older servers/clients interoperate both ways since the field is additive and optional.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

@changeset-bot

changeset-bot Bot commented Jul 13, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: be0ac31

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jul 13, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@be0ac31
npx https://pkg.pr.new/@moonshot-ai/kimi-code@be0ac31

commit: be0ac31

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f87202de26

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +91 to +95
case 'turn.ended': {
// After turn end the swarm's `<agent_swarm_result>` tool output is in
// the wire transcript and becomes the restore source; dropping the
// roster here also bounds its lifetime.
this.bySession.delete(sessionId);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Restrict roster clearing to the main turn

When any subagent finishes, its own turn.ended frame is published on the same session with agentId set to the subagent, and existing code already treats non-main turn frames specially (the web projector routes them as subagent progress and InFlightTurnTracker filters them out). This unconditional delete clears the whole roster as soon as the first child turn ends, so a refresh while the parent AgentSwarm call is still waiting on other subagents again loses the member list before the final swarm result is in the transcript; only the main agent's turn.ended should drop the roster.

Useful? React with 👍 / 👎.

@wbxl2000 wbxl2000 force-pushed the fix/web-swarm-roster-refresh branch from f87202d to be0ac31 Compare July 13, 2026 08:01
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