fix: resume subagent registry safely (#831) (thanks @roshanasingh4)

This commit is contained in:
Peter Steinberger
2026-01-13 10:10:15 +00:00
parent 714de9d996
commit b071f73fef
6 changed files with 115 additions and 35 deletions

View File

@@ -18,7 +18,7 @@ vi.mock("../infra/agent-events.js", () => ({
onAgentEvent: vi.fn(() => noop),
}));
const announceSpy = vi.fn(async () => {});
const announceSpy = vi.fn(async () => true);
vi.mock("./subagent-announce.js", () => ({
runSubagentAnnounceFlow: (...args: unknown[]) => announceSpy(...args),
}));
@@ -67,7 +67,8 @@ describe("subagent registry persistence", () => {
// Simulate a process restart: module re-import should load persisted runs
// and trigger the announce flow once the run resolves.
vi.resetModules();
await import("./subagent-registry.js");
const mod2 = await import("./subagent-registry.js");
mod2.initSubagentRegistry();
// allow queued async wait/announce to execute
await new Promise((r) => setTimeout(r, 0));
@@ -82,4 +83,44 @@ describe("subagent registry persistence", () => {
expect(first.childRunId).toBe("run-1");
expect(first.childSessionKey).toBe("agent:main:subagent:test");
});
it("retries announce even when announceHandled was persisted", async () => {
tempStateDir = await fs.mkdtemp(
path.join(os.tmpdir(), "clawdbot-subagent-"),
);
process.env.CLAWDBOT_STATE_DIR = tempStateDir;
const registryPath = path.join(tempStateDir, "subagents", "runs.json");
const persisted = {
version: 1,
runs: {
"run-2": {
runId: "run-2",
childSessionKey: "agent:main:subagent:two",
requesterSessionKey: "agent:main:main",
requesterDisplayKey: "main",
task: "do the other thing",
cleanup: "keep",
createdAt: 1,
startedAt: 1,
endedAt: 2,
announceHandled: true,
},
},
};
await fs.mkdir(path.dirname(registryPath), { recursive: true });
await fs.writeFile(registryPath, `${JSON.stringify(persisted)}\n`, "utf8");
vi.resetModules();
const mod = await import("./subagent-registry.js");
mod.initSubagentRegistry();
await new Promise((r) => setTimeout(r, 0));
const calls = announceSpy.mock.calls.map((call) => call[0]);
const match = calls.find(
(params) => (params as { childRunId?: string }).childRunId === "run-2",
);
expect(match).toBeTruthy();
});
});