























@@ -2421,6 +2421,70 @@ describe("task-registry", () => {
24212421});
24222422});
242324232424+it("keeps fresh childless copilot-native subagent tasks live", async () => {
2425+await withTaskRegistryTempDir(async () => {
2426+resetTaskRegistryForTests();
2427+const now = Date.now();
2428+2429+const task = createTaskRecord({
2430+runtime: "subagent",
2431+taskKind: "copilot-native",
2432+ownerKey: "agent:main:main",
2433+scopeKind: "session",
2434+sourceId: "copilot-agent:child-agent",
2435+runId: "copilot-agent:child-agent",
2436+task: "Copilot native child",
2437+status: "running",
2438+deliveryStatus: "not_applicable",
2439+notifyPolicy: "silent",
2440+lastEventAt: now - 10 * 60_000,
2441+});
2442+2443+expect(await runTaskRegistryMaintenance()).toEqual({
2444+reconciled: 0,
2445+recovered: 0,
2446+cleanupStamped: 0,
2447+pruned: 0,
2448+});
2449+expectRecordFields(requireTaskById(task.taskId), {
2450+status: "running",
2451+lastEventAt: now - 10 * 60_000,
2452+});
2453+});
2454+});
2455+2456+it("marks stale childless copilot-native subagent tasks lost", async () => {
2457+await withTaskRegistryTempDir(async () => {
2458+resetTaskRegistryForTests();
2459+const now = Date.now();
2460+2461+const task = createTaskRecord({
2462+runtime: "subagent",
2463+taskKind: "copilot-native",
2464+ownerKey: "agent:main:main",
2465+scopeKind: "session",
2466+sourceId: "copilot-agent:child-agent",
2467+runId: "copilot-agent:child-agent",
2468+task: "Copilot native child",
2469+status: "running",
2470+deliveryStatus: "not_applicable",
2471+notifyPolicy: "silent",
2472+lastEventAt: now - 31 * 60_000,
2473+});
2474+2475+expect(await runTaskRegistryMaintenance()).toEqual({
2476+reconciled: 1,
2477+recovered: 0,
2478+cleanupStamped: 0,
2479+pruned: 0,
2480+});
2481+expectRecordFields(requireTaskById(task.taskId), {
2482+status: "lost",
2483+error: "Native subagent stopped reporting progress",
2484+});
2485+});
2486+});
2487+24242488it("does not mark unrelated childless subagent tasks lost", async () => {
24252489await withTaskRegistryTempDir(async () => {
24262490resetTaskRegistryForTests();
@@ -3794,6 +3858,43 @@ describe("task-registry", () => {
37943858});
37953859});
379638603861+it("cancels childless copilot-native tasks without routing through OpenClaw subagent sessions", async () => {
3862+await withTaskRegistryTempDir(async () => {
3863+resetTaskRegistryForTests();
3864+const task = createTaskRecord({
3865+runtime: "subagent",
3866+taskKind: "copilot-native",
3867+ownerKey: "agent:main:main",
3868+scopeKind: "session",
3869+sourceId: "copilot-agent:child-agent",
3870+runId: "copilot-agent:child-agent",
3871+task: "Copilot native child",
3872+status: "running",
3873+deliveryStatus: "not_applicable",
3874+notifyPolicy: "silent",
3875+});
3876+3877+const result = await cancelTaskById({
3878+cfg: {} as never,
3879+taskId: task.taskId,
3880+});
3881+3882+expectRecordFields(result, {
3883+found: true,
3884+cancelled: true,
3885+});
3886+expectRecordFields(result.task, {
3887+taskId: task.taskId,
3888+status: "cancelled",
3889+endedAt: expect.any(Number),
3890+lastEventAt: expect.any(Number),
3891+cleanupAfter: expect.any(Number),
3892+error: "Cancelled by operator.",
3893+});
3894+expect(hoisted.killSubagentRunAdminMock).not.toHaveBeenCalled();
3895+});
3896+});
3897+37973898it("does not cancel unrelated childless subagent tasks", async () => {
37983899await withTaskRegistryTempDir(async () => {
37993900resetTaskRegistryForTests();
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。