From a885c76c09fd2561f7185acd4a40c47a523b4d83 Mon Sep 17 00:00:00 2001 From: xaeon2026 Date: Mon, 9 Mar 2026 08:38:52 -0400 Subject: [PATCH] Allow ACP lineage in sessions.patch --- src/gateway/sessions-patch.test.ts | 23 +++++++++++++++++++++++ src/gateway/sessions-patch.ts | 13 +++++++++---- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/gateway/sessions-patch.test.ts b/src/gateway/sessions-patch.test.ts index 78d8a71aecb..2249c7f5c77 100644 --- a/src/gateway/sessions-patch.test.ts +++ b/src/gateway/sessions-patch.test.ts @@ -252,6 +252,29 @@ describe("gateway sessions patch", () => { expect(entry.spawnDepth).toBe(2); }); + test("sets spawnedBy for ACP sessions", async () => { + const entry = expectPatchOk( + await runPatch({ + storeKey: "agent:main:acp:child", + patch: { + key: "agent:main:acp:child", + spawnedBy: "agent:main:main", + }, + }), + ); + expect(entry.spawnedBy).toBe("agent:main:main"); + }); + + test("sets spawnDepth for ACP sessions", async () => { + const entry = expectPatchOk( + await runPatch({ + storeKey: "agent:main:acp:child", + patch: { key: "agent:main:acp:child", spawnDepth: 2 }, + }), + ); + expect(entry.spawnDepth).toBe(2); + }); + test("rejects spawnDepth on non-subagent sessions", async () => { const result = await runPatch({ patch: { key: MAIN_SESSION_KEY, spawnDepth: 1 }, diff --git a/src/gateway/sessions-patch.ts b/src/gateway/sessions-patch.ts index d55cf2cf1a4..b4e5ce6e06e 100644 --- a/src/gateway/sessions-patch.ts +++ b/src/gateway/sessions-patch.ts @@ -19,6 +19,7 @@ import { import type { OpenClawConfig } from "../config/config.js"; import type { SessionEntry } from "../config/sessions.js"; import { + isAcpSessionKey, isSubagentSessionKey, normalizeAgentId, parseAgentSessionKey, @@ -62,6 +63,10 @@ function normalizeExecAsk(raw: string): "off" | "on-miss" | "always" | undefined return undefined; } +function supportsSpawnLineage(storeKey: string): boolean { + return isSubagentSessionKey(storeKey) || isAcpSessionKey(storeKey); +} + export async function applySessionsPatchToStore(params: { cfg: OpenClawConfig; store: Record; @@ -97,8 +102,8 @@ export async function applySessionsPatchToStore(params: { if (!trimmed) { return invalid("invalid spawnedBy: empty"); } - if (!isSubagentSessionKey(storeKey)) { - return invalid("spawnedBy is only supported for subagent:* sessions"); + if (!supportsSpawnLineage(storeKey)) { + return invalid("spawnedBy is only supported for subagent:* or acp:* sessions"); } if (existing?.spawnedBy && existing.spawnedBy !== trimmed) { return invalid("spawnedBy cannot be changed once set"); @@ -114,8 +119,8 @@ export async function applySessionsPatchToStore(params: { return invalid("spawnDepth cannot be cleared once set"); } } else if (raw !== undefined) { - if (!isSubagentSessionKey(storeKey)) { - return invalid("spawnDepth is only supported for subagent:* sessions"); + if (!supportsSpawnLineage(storeKey)) { + return invalid("spawnDepth is only supported for subagent:* or acp:* sessions"); } const numeric = Number(raw); if (!Number.isInteger(numeric) || numeric < 0) {