mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-03 23:40:21 +00:00
fix: let subagent kill cascade through ended parents
This commit is contained in:
@@ -515,7 +515,7 @@ export async function killControlledSubagentRun(params: {
|
||||
};
|
||||
}
|
||||
const currentEntry = getSubagentRunByChildSessionKey(params.entry.childSessionKey);
|
||||
if (!currentEntry || currentEntry.runId !== params.entry.runId || currentEntry.endedAt) {
|
||||
if (!currentEntry || currentEntry.runId !== params.entry.runId) {
|
||||
return {
|
||||
status: "done" as const,
|
||||
runId: params.entry.runId,
|
||||
@@ -527,7 +527,7 @@ export async function killControlledSubagentRun(params: {
|
||||
const killCache = new Map<string, Record<string, SessionEntry>>();
|
||||
const stopResult = await killSubagentRun({
|
||||
cfg: params.cfg,
|
||||
entry: params.entry,
|
||||
entry: currentEntry,
|
||||
cache: killCache,
|
||||
});
|
||||
const seenChildSessionKeys = new Set<string>();
|
||||
|
||||
@@ -3,7 +3,6 @@ import {
|
||||
killControlledSubagentRun,
|
||||
} from "../../../agents/subagent-control.js";
|
||||
import type { CommandHandlerResult } from "../commands-types.js";
|
||||
import { formatRunLabel } from "../subagents-utils.js";
|
||||
import {
|
||||
type SubagentsCommandContext,
|
||||
COMMAND,
|
||||
@@ -43,9 +42,6 @@ export async function handleSubagentsKillAction(
|
||||
if ("reply" in targetResolution) {
|
||||
return targetResolution.reply;
|
||||
}
|
||||
if (targetResolution.entry.endedAt) {
|
||||
return stopWithText(`${formatRunLabel(targetResolution.entry)} is already finished.`);
|
||||
}
|
||||
|
||||
const controller = resolveCommandSubagentController(params, requesterKey);
|
||||
const result = await killControlledSubagentRun({
|
||||
|
||||
@@ -107,8 +107,12 @@ vi.mock("./commands-context-report.js", () => ({
|
||||
|
||||
vi.resetModules();
|
||||
|
||||
const { addSubagentRunForTests, listSubagentRunsForRequester, resetSubagentRegistryForTests } =
|
||||
await import("../../agents/subagent-registry.js");
|
||||
const {
|
||||
addSubagentRunForTests,
|
||||
getSubagentRunByChildSessionKey,
|
||||
listSubagentRunsForRequester,
|
||||
resetSubagentRegistryForTests,
|
||||
} = await import("../../agents/subagent-registry.js");
|
||||
const { setDefaultChannelPluginRegistryForTests } =
|
||||
await import("../../commands/channel-test-helpers.js");
|
||||
const internalHooks = await import("../../hooks/internal-hooks.js");
|
||||
@@ -1974,6 +1978,46 @@ describe("handleCommands subagents", () => {
|
||||
expect(result.reply).toBeUndefined();
|
||||
});
|
||||
|
||||
it("kills descendants when numeric target 1 is an ended orchestrator still waiting on children", async () => {
|
||||
const now = Date.now();
|
||||
const parentKey = "agent:main:subagent:orchestrator-ended";
|
||||
const childKey = "agent:main:subagent:orchestrator-ended:subagent:worker";
|
||||
|
||||
addSubagentRunForTests({
|
||||
runId: "run-orchestrator-ended",
|
||||
childSessionKey: parentKey,
|
||||
requesterSessionKey: "agent:main:main",
|
||||
requesterDisplayKey: "main",
|
||||
task: "orchestrate child workers",
|
||||
cleanup: "keep",
|
||||
createdAt: now - 120_000,
|
||||
startedAt: now - 120_000,
|
||||
endedAt: now - 110_000,
|
||||
outcome: { status: "ok" },
|
||||
});
|
||||
addSubagentRunForTests({
|
||||
runId: "run-orchestrator-child-active",
|
||||
childSessionKey: childKey,
|
||||
requesterSessionKey: parentKey,
|
||||
requesterDisplayKey: "subagent:orchestrator-ended",
|
||||
task: "child worker still running",
|
||||
cleanup: "keep",
|
||||
createdAt: now - 60_000,
|
||||
startedAt: now - 60_000,
|
||||
});
|
||||
|
||||
const cfg = {
|
||||
commands: { text: true },
|
||||
channels: { whatsapp: { allowFrom: ["*"] } },
|
||||
} as OpenClawConfig;
|
||||
const params = buildParams("/kill 1", cfg);
|
||||
const result = await handleCommands(params);
|
||||
|
||||
expect(result.shouldContinue).toBe(false);
|
||||
expect(result.reply).toBeUndefined();
|
||||
expect(getSubagentRunByChildSessionKey(childKey)?.endedAt).toBeTypeOf("number");
|
||||
});
|
||||
|
||||
it("sends follow-up messages to finished subagents", async () => {
|
||||
callGatewayMock.mockImplementation(async (opts: unknown) => {
|
||||
const request = opts as { method?: string; params?: { runId?: string } };
|
||||
|
||||
Reference in New Issue
Block a user