mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix: wake yielded parent after subagents finish (#97090)
* fix: wake yielded subagent parents after descendants settle * fix: wake yielded subagent parents after descendants settle --------- Co-authored-by: Galin Iliev <Galin.Iliev@microsoft.com>
This commit is contained in:
@@ -3373,6 +3373,61 @@ describe("subagent registry seam flow", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("wakes a sessions_yield-paused parent when pending descendants settle", async () => {
|
||||
mocks.loadSessionStore.mockReturnValue({
|
||||
"agent:main:subagent:parent": {
|
||||
sessionId: "sess-parent",
|
||||
updatedAt: 1,
|
||||
},
|
||||
"agent:main:subagent:child": {
|
||||
sessionId: "sess-child",
|
||||
updatedAt: 1,
|
||||
},
|
||||
});
|
||||
|
||||
mod.addSubagentRunForTests({
|
||||
runId: "run-yielded-parent",
|
||||
childSessionKey: "agent:main:subagent:parent",
|
||||
requesterSessionKey: "agent:main:main",
|
||||
requesterDisplayKey: "main",
|
||||
task: "yielded parent waiting on descendants",
|
||||
cleanup: "keep",
|
||||
createdAt: Date.parse("2026-06-26T02:17:00Z"),
|
||||
startedAt: Date.parse("2026-06-26T02:18:00Z"),
|
||||
endedAt: Date.parse("2026-06-26T02:19:00Z"),
|
||||
pauseReason: "sessions_yield",
|
||||
wakeOnDescendantSettle: true,
|
||||
cleanupHandled: false,
|
||||
cleanupCompletedAt: undefined,
|
||||
});
|
||||
|
||||
mod.registerSubagentRun({
|
||||
runId: "run-yielded-child-finished",
|
||||
childSessionKey: "agent:main:subagent:child",
|
||||
requesterSessionKey: "agent:main:subagent:parent",
|
||||
requesterDisplayKey: "parent",
|
||||
task: "descendant settles after yield",
|
||||
cleanup: "keep",
|
||||
});
|
||||
|
||||
await waitForFast(() => {
|
||||
expect(mocks.runSubagentAnnounceFlow).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
expectRecordFields(
|
||||
getMockCallArg(mocks.runSubagentAnnounceFlow, 0, 0, "child finished announce"),
|
||||
{ childRunId: "run-yielded-child-finished" },
|
||||
"child finished announce params",
|
||||
);
|
||||
expectRecordFields(
|
||||
getMockCallArg(mocks.runSubagentAnnounceFlow, 1, 0, "yielded parent wake announce"),
|
||||
{
|
||||
childRunId: "run-yielded-parent",
|
||||
wakeOnDescendantSettle: true,
|
||||
},
|
||||
"yielded parent wake announce params",
|
||||
);
|
||||
});
|
||||
|
||||
it("loads runtime plugins before emitting killed subagent ended hooks", async () => {
|
||||
const endedHookRunner = {
|
||||
hasHooks: (hookName: string) => hookName === "subagent_ended",
|
||||
|
||||
@@ -626,7 +626,9 @@ function resumeSubagentRun(runId: string) {
|
||||
if (typeof entry.endedAt === "number" && isDeliverySuspended(entry)) {
|
||||
return;
|
||||
}
|
||||
if (entry.pauseReason === "sessions_yield") {
|
||||
// Yielded runs stay paused until explicitly steered, except orchestrators
|
||||
// waiting on descendants: their settle retry must reach the wake path.
|
||||
if (entry.pauseReason === "sessions_yield" && entry.wakeOnDescendantSettle !== true) {
|
||||
return;
|
||||
}
|
||||
// Skip entries that have exhausted their retry budget or expired (#18264).
|
||||
|
||||
Reference in New Issue
Block a user