diff --git a/src/agents/pi-tools.create-openclaw-coding-tools.test.ts b/src/agents/pi-tools.create-openclaw-coding-tools.test.ts index 045854eb13c..1ace0b9c64e 100644 --- a/src/agents/pi-tools.create-openclaw-coding-tools.test.ts +++ b/src/agents/pi-tools.create-openclaw-coding-tools.test.ts @@ -45,6 +45,44 @@ function collectActionValues(schema: unknown, values: Set): void { } } +async function writeSessionStore( + storeTemplate: string, + agentId: string, + entries: Record, +) { + await fs.writeFile( + storeTemplate.replaceAll("{agentId}", agentId), + JSON.stringify(entries, null, 2), + "utf-8", + ); +} + +function createToolsForStoredSession(storeTemplate: string, sessionKey: string) { + return createOpenClawCodingTools({ + sessionKey, + config: { + session: { + store: storeTemplate, + }, + agents: { + defaults: { + subagents: { + maxSpawnDepth: 2, + }, + }, + }, + }, + }); +} + +function expectNoSubagentControlTools(tools: ReturnType) { + const names = new Set(tools.map((tool) => tool.name)); + expect(names.has("sessions_spawn")).toBe(false); + expect(names.has("sessions_list")).toBe(false); + expect(names.has("sessions_history")).toBe(false); + expect(names.has("subagents")).toBe(false); +} + describe("createOpenClawCodingTools", () => { const testConfig: OpenClawConfig = {}; @@ -196,43 +234,16 @@ describe("createOpenClawCodingTools", () => { const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-depth-policy-")); try { const storeTemplate = path.join(tmpDir, "sessions-{agentId}.json"); - const storePath = storeTemplate.replaceAll("{agentId}", "main"); - await fs.writeFile( - storePath, - JSON.stringify( - { - "agent:main:subagent:flat": { - sessionId: "session-flat-depth-2", - updatedAt: Date.now(), - spawnDepth: 2, - }, - }, - null, - 2, - ), - "utf-8", - ); - - const tools = createOpenClawCodingTools({ - sessionKey: "agent:main:subagent:flat", - config: { - session: { - store: storeTemplate, - }, - agents: { - defaults: { - subagents: { - maxSpawnDepth: 2, - }, - }, - }, + await writeSessionStore(storeTemplate, "main", { + "agent:main:subagent:flat": { + sessionId: "session-flat-depth-2", + updatedAt: Date.now(), + spawnDepth: 2, }, }); - const names = new Set(tools.map((tool) => tool.name)); - expect(names.has("sessions_spawn")).toBe(false); - expect(names.has("sessions_list")).toBe(false); - expect(names.has("sessions_history")).toBe(false); - expect(names.has("subagents")).toBe(false); + + const tools = createToolsForStoredSession(storeTemplate, "agent:main:subagent:flat"); + expectNoSubagentControlTools(tools); } finally { await fs.rm(tmpDir, { recursive: true, force: true }); } @@ -242,112 +253,47 @@ describe("createOpenClawCodingTools", () => { const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-acp-subagent-policy-")); try { const storeTemplate = path.join(tmpDir, "sessions-{agentId}.json"); - const mainStorePath = storeTemplate.replaceAll("{agentId}", "main"); - const writerStorePath = storeTemplate.replaceAll("{agentId}", "writer"); - await fs.writeFile( - mainStorePath, - JSON.stringify( - { - "agent:main:acp:child": { - sessionId: "session-acp-child", - updatedAt: Date.now(), - spawnedBy: "agent:main:subagent:parent", - spawnDepth: 2, - subagentRole: "leaf", - subagentControlScope: "none", - }, - "agent:main:acp:plain": { - sessionId: "session-acp-plain", - updatedAt: Date.now(), - spawnedBy: "agent:main:main", - }, - "agent:main:acp:parent": { - sessionId: "session-acp-parent", - updatedAt: Date.now(), - spawnedBy: "agent:main:subagent:parent", - }, - }, - null, - 2, - ), - "utf-8", - ); - await fs.writeFile( - writerStorePath, - JSON.stringify( - { - "agent:writer:acp:child": { - sessionId: "session-acp-cross-agent-child", - updatedAt: Date.now(), - spawnedBy: "agent:main:acp:parent", - }, - }, - null, - 2, - ), - "utf-8", - ); - - const persistedEnvelopeTools = createOpenClawCodingTools({ - sessionKey: "agent:main:acp:child", - config: { - session: { - store: storeTemplate, - }, - agents: { - defaults: { - subagents: { - maxSpawnDepth: 2, - }, - }, - }, + await writeSessionStore(storeTemplate, "main", { + "agent:main:acp:child": { + sessionId: "session-acp-child", + updatedAt: Date.now(), + spawnedBy: "agent:main:subagent:parent", + spawnDepth: 2, + subagentRole: "leaf", + subagentControlScope: "none", + }, + "agent:main:acp:plain": { + sessionId: "session-acp-plain", + updatedAt: Date.now(), + spawnedBy: "agent:main:main", + }, + "agent:main:acp:parent": { + sessionId: "session-acp-parent", + updatedAt: Date.now(), + spawnedBy: "agent:main:subagent:parent", }, }); - const persistedEnvelopeNames = new Set(persistedEnvelopeTools.map((tool) => tool.name)); - expect(persistedEnvelopeNames.has("sessions_spawn")).toBe(false); - expect(persistedEnvelopeNames.has("sessions_list")).toBe(false); - expect(persistedEnvelopeNames.has("sessions_history")).toBe(false); - expect(persistedEnvelopeNames.has("subagents")).toBe(false); - - const restrictedTools = createOpenClawCodingTools({ - sessionKey: "agent:main:acp:plain", - config: { - session: { - store: storeTemplate, - }, - agents: { - defaults: { - subagents: { - maxSpawnDepth: 2, - }, - }, - }, + await writeSessionStore(storeTemplate, "writer", { + "agent:writer:acp:child": { + sessionId: "session-acp-cross-agent-child", + updatedAt: Date.now(), + spawnedBy: "agent:main:acp:parent", }, }); + + const persistedEnvelopeTools = createToolsForStoredSession( + storeTemplate, + "agent:main:acp:child", + ); + expectNoSubagentControlTools(persistedEnvelopeTools); + + const restrictedTools = createToolsForStoredSession(storeTemplate, "agent:main:acp:plain"); const restrictedNames = new Set(restrictedTools.map((tool) => tool.name)); expect(restrictedNames.has("sessions_spawn")).toBe(true); expect(restrictedNames.has("subagents")).toBe(true); - const ancestryTools = createOpenClawCodingTools({ - sessionKey: "agent:writer:acp:child", - config: { - session: { - store: storeTemplate, - }, - agents: { - defaults: { - subagents: { - maxSpawnDepth: 2, - }, - }, - }, - }, - }); - const ancestryNames = new Set(ancestryTools.map((tool) => tool.name)); - expect(ancestryNames.has("sessions_spawn")).toBe(false); - expect(ancestryNames.has("sessions_list")).toBe(false); - expect(ancestryNames.has("sessions_history")).toBe(false); - expect(ancestryNames.has("subagents")).toBe(false); + const ancestryTools = createToolsForStoredSession(storeTemplate, "agent:writer:acp:child"); + expectNoSubagentControlTools(ancestryTools); } finally { await fs.rm(tmpDir, { recursive: true, force: true }); } @@ -357,59 +303,23 @@ describe("createOpenClawCodingTools", () => { const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-cross-agent-subagent-")); try { const storeTemplate = path.join(tmpDir, "sessions-{agentId}.json"); - const mainStorePath = storeTemplate.replaceAll("{agentId}", "main"); - const writerStorePath = storeTemplate.replaceAll("{agentId}", "writer"); - await fs.writeFile( - mainStorePath, - JSON.stringify( - { - "agent:main:subagent:parent": { - sessionId: "session-main-parent", - updatedAt: Date.now(), - spawnedBy: "agent:main:main", - }, - }, - null, - 2, - ), - "utf-8", - ); - await fs.writeFile( - writerStorePath, - JSON.stringify( - { - "agent:writer:subagent:child": { - sessionId: "session-writer-child", - updatedAt: Date.now(), - spawnedBy: "agent:main:subagent:parent", - }, - }, - null, - 2, - ), - "utf-8", - ); - - const tools = createOpenClawCodingTools({ - sessionKey: "agent:writer:subagent:child", - config: { - session: { - store: storeTemplate, - }, - agents: { - defaults: { - subagents: { - maxSpawnDepth: 2, - }, - }, - }, + await writeSessionStore(storeTemplate, "main", { + "agent:main:subagent:parent": { + sessionId: "session-main-parent", + updatedAt: Date.now(), + spawnedBy: "agent:main:main", }, }); - const names = new Set(tools.map((tool) => tool.name)); - expect(names.has("sessions_spawn")).toBe(false); - expect(names.has("sessions_list")).toBe(false); - expect(names.has("sessions_history")).toBe(false); - expect(names.has("subagents")).toBe(false); + await writeSessionStore(storeTemplate, "writer", { + "agent:writer:subagent:child": { + sessionId: "session-writer-child", + updatedAt: Date.now(), + spawnedBy: "agent:main:subagent:parent", + }, + }); + + const tools = createToolsForStoredSession(storeTemplate, "agent:writer:subagent:child"); + expectNoSubagentControlTools(tools); } finally { await fs.rm(tmpDir, { recursive: true, force: true }); }