Skip to content

Commit 425bd89

Browse files
xaeon2026mbelinky
andauthored
Allow ACP sessions.patch lineage fields on ACP session keys (#40995)
Merged via squash. Prepared head SHA: c1191ed Co-authored-by: xaeon2026 <[email protected]> Co-authored-by: mbelinky <[email protected]> Reviewed-by: @mbelinky
1 parent 54be30e commit 425bd89

File tree

3 files changed

+33
-4
lines changed

3 files changed

+33
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Docs: https://docs.openclaw.ai
1515
- Models/Kimi Coding: send `anthropic-messages` tools in native Anthropic format again so `kimi-coding` stops degrading tool calls into XML/plain-text pseudo invocations instead of real `tool_use` blocks. (#38669, #39907, #40552) Thanks @opriz.
1616
- Context engine/tests: add bundled-registry regression coverage for cross-chunk resolution, plugin-sdk re-exports, and concurrent chunk registration. (#40460) thanks @dsantoreis.
1717
- Agents/embedded runner: bound compaction retry waiting and drain embedded runs during SIGUSR1 restart so session lanes recover instead of staying blocked behind compaction. (#40324) thanks @cgdusek.
18+
- ACP/sessions.patch: allow `spawnedBy` and `spawnDepth` lineage fields on ACP session keys so `sessions_spawn` with `runtime: "acp"` no longer fails during child-session setup. Fixes #40971. (#40995) thanks @xaeon2026.
1819

1920
## 2026.3.8
2021

src/gateway/sessions-patch.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,29 @@ describe("gateway sessions patch", () => {
252252
expect(entry.spawnDepth).toBe(2);
253253
});
254254

255+
test("sets spawnedBy for ACP sessions", async () => {
256+
const entry = expectPatchOk(
257+
await runPatch({
258+
storeKey: "agent:main:acp:child",
259+
patch: {
260+
key: "agent:main:acp:child",
261+
spawnedBy: "agent:main:main",
262+
},
263+
}),
264+
);
265+
expect(entry.spawnedBy).toBe("agent:main:main");
266+
});
267+
268+
test("sets spawnDepth for ACP sessions", async () => {
269+
const entry = expectPatchOk(
270+
await runPatch({
271+
storeKey: "agent:main:acp:child",
272+
patch: { key: "agent:main:acp:child", spawnDepth: 2 },
273+
}),
274+
);
275+
expect(entry.spawnDepth).toBe(2);
276+
});
277+
255278
test("rejects spawnDepth on non-subagent sessions", async () => {
256279
const result = await runPatch({
257280
patch: { key: MAIN_SESSION_KEY, spawnDepth: 1 },

src/gateway/sessions-patch.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
import type { OpenClawConfig } from "../config/config.js";
2020
import type { SessionEntry } from "../config/sessions.js";
2121
import {
22+
isAcpSessionKey,
2223
isSubagentSessionKey,
2324
normalizeAgentId,
2425
parseAgentSessionKey,
@@ -62,6 +63,10 @@ function normalizeExecAsk(raw: string): "off" | "on-miss" | "always" | undefined
6263
return undefined;
6364
}
6465

66+
function supportsSpawnLineage(storeKey: string): boolean {
67+
return isSubagentSessionKey(storeKey) || isAcpSessionKey(storeKey);
68+
}
69+
6570
export async function applySessionsPatchToStore(params: {
6671
cfg: OpenClawConfig;
6772
store: Record<string, SessionEntry>;
@@ -97,8 +102,8 @@ export async function applySessionsPatchToStore(params: {
97102
if (!trimmed) {
98103
return invalid("invalid spawnedBy: empty");
99104
}
100-
if (!isSubagentSessionKey(storeKey)) {
101-
return invalid("spawnedBy is only supported for subagent:* sessions");
105+
if (!supportsSpawnLineage(storeKey)) {
106+
return invalid("spawnedBy is only supported for subagent:* or acp:* sessions");
102107
}
103108
if (existing?.spawnedBy && existing.spawnedBy !== trimmed) {
104109
return invalid("spawnedBy cannot be changed once set");
@@ -114,8 +119,8 @@ export async function applySessionsPatchToStore(params: {
114119
return invalid("spawnDepth cannot be cleared once set");
115120
}
116121
} else if (raw !== undefined) {
117-
if (!isSubagentSessionKey(storeKey)) {
118-
return invalid("spawnDepth is only supported for subagent:* sessions");
122+
if (!supportsSpawnLineage(storeKey)) {
123+
return invalid("spawnDepth is only supported for subagent:* or acp:* sessions");
119124
}
120125
const numeric = Number(raw);
121126
if (!Number.isInteger(numeric) || numeric < 0) {

0 commit comments

Comments
 (0)