Repository navigation
fix(swarm): restore the lead's team task list when a session is resumed - #236
Conversation
After the CLI process of a lead session restarts, nothing sets the leader's team name again, so getTaskListId() falls back to the session id and TaskList cannot see the team's tasks. Look for the team whose leadSessionId is the resumed session and set it as the leader's team name again. runHeadless does this for --resume and --continue when agent teams are enabled. Closes GoDiao#216
GoDiao
left a comment
There was a problem hiding this comment.
Thanks for the fix, and for the clear description. The approach matches what #216 suggests, and I checked the main points against the code: the team name goes through the same sanitizeName as TeamCreate, leadSessionId equals the session id after a non-fork resume, and a missing teams/ directory or a malformed config.json is skipped without throwing.
Two changes before we merge.
1. Test the call site, not only restoreLeaderTeamName().
The four tests call restoreLeaderTeamName() directly. Nothing covers the call in runHeadless (src/cli/print.ts) or the isAgentSwarmsEnabled() gate, so removing or moving that call would leave every test green and bring #216 back. #216 asks for a test that starts the resume path.
Could you move the gated call into a small function, for example restoreLeaderTeamNameOnResume() in reconnection.ts, have runHeadless call it, and add tests for it:
- agent teams enabled: the team name is restored and
getTaskListId()returns it - agent teams disabled: nothing is restored
2. Pin down the forked resume.
--resume <id> --fork-session creates a new session id, while the team's leadSessionId is still the old one, so the fork does not adopt the team. That looks right to us, because a fork is a new lead, and it fits where we are taking agent teams (#162). It is not tested or mentioned yet. Could you:
- add a test where the current session id differs from the team's
leadSessionId(the fork case) andgetTaskListId()does not return the team name - add one sentence to the PR description saying a forked resume intentionally does not take over the team
CI runs will need our approval after each push, since this is your first contribution. We will approve them.
restoreLeaderTeamNameOnResume() holds the agent-teams check, runHeadless calls it, and the tests cover the enabled, disabled and forked-resume cases.
|
Pushed 6e46cd8 for both points.
|
GoDiao
left a comment
There was a problem hiding this comment.
Thanks for the quick follow-up. Both points are in, and I checked them locally: the tests pass on their own and in a randomized run, and removing the agent-teams check makes the disabled test fail. I added the thanks line to the CHANGELOG entry.
Closes #216
After the CLI process of a lead session restarts, the lead can no longer see its team's tasks.
getTaskListId()resolves the lead's list fromleaderTeamName, which onlyTeamCreatesets, so the new process falls through to the session id and readstasks/<session id>/.TaskListthen returns nothing, and tasks the lead creates go to a different list than the one the teammates read.This adds
restoreLeaderTeamName()tosrc/utils/swarm/reconnection.ts. It looks throughteams/*/config.jsonfor a team whoseleadSessionIdis the current session id and sets it as the leader's team name again. If the session led more than one team it uses the newest.restoreLeaderTeamNameOnResume()in the same file wraps it behindisAgentSwarmsEnabled(), andrunHeadlesscalls that after the resumed conversation is loaded, for--resumeand--continue.A forked resume (
--resume <id> --fork-session) gets a new session id while the team'sleadSessionIdis still the old one, so the fork does not take over the team. This is intentional: a fork is a new lead.Only the task list resolution is restored.
AppState.teamContextis still not set for the lead after a restart, so that part is unchanged and I left it out of this PR.Tests, run on Windows with bun 1.4.4:
bun test src/utils/swarm/reconnection.test.ts: 7 pass. Four coverrestoreLeaderTeamName(): they set up a team on disk withleadSessionIdset to the current session, call it withoutTeamCreate, and expectgetTaskListId()to return the team name andlistTasksto find the team's task; a team led by another session is ignored, the newest team wins, and no teams directory is a no-op. Three coverrestoreLeaderTeamNameOnResume(): with agent teams enabled the team name is restored, with them disabled nothing is restored, and when the current session id differs from the team'sleadSessionId(the fork case)getTaskListId()still returns the session id.setLeaderTeamNamecall removed, the first and the newest-team tests fail. With theisAgentSwarmsEnabled()check removed, the disabled test fails. With theleadSessionIdcomparison removed, the fork test and the other-session test fail.bun test --randomize --seed=1on that file together withinProcessRunner.test.tsandinit.teamCleanup.test.ts: 10 pass.bun test src/server/__tests__/teams.test.ts src/server/__tests__/team-watcher.test.ts: 56 pass.A full
bun teston my Windows machine also shows failures in git, worktree, artifact and session tests (git initand 5 s timeouts). I ran the conversations, sessions and business-flow files onmainand on this branch and got the same kinds of failures on both; the swarm tests pass.init.teamCleanup.test.tspasses in the subset runs but hit its 5 s timeout once in the full run, on a cold import.Not run: I did not start the desktop app, so the restart scenario from the issue (stop a session with a team, send another message) was not exercised end to end.
runHeadlessmakes one call torestoreLeaderTeamNameOnResume()inside the--resume/--continuecheck, and that call itself has no test; the function it calls does. The desktop lint and vitest were not run because no desktop code changed.I added a line under Unreleased in CHANGELOG.md.