From c85b0ee3db85d5fdb5cca9708f1d1fed9f24052e Mon Sep 17 00:00:00 2001 From: Shakker Date: Fri, 5 Jun 2026 16:48:32 +0100 Subject: [PATCH] test: scope subagent sqlite state env --- .../subagent-registry.store.sqlite.test.ts | 116 ++++++++++-------- 1 file changed, 63 insertions(+), 53 deletions(-) diff --git a/src/agents/subagent-registry.store.sqlite.test.ts b/src/agents/subagent-registry.store.sqlite.test.ts index d498dad4cc15..1589d2e7cbe3 100644 --- a/src/agents/subagent-registry.store.sqlite.test.ts +++ b/src/agents/subagent-registry.store.sqlite.test.ts @@ -8,7 +8,7 @@ import { closeOpenClawStateDatabaseForTest, openOpenClawStateDatabase, } from "../state/openclaw-state-db.js"; -import { captureEnv } from "../test-utils/env.js"; +import { withEnvAsync } from "../test-utils/env.js"; import { loadSubagentRegistryFromSqlite, saveSubagentRegistryToSqlite, @@ -56,12 +56,10 @@ function createRun(overrides: Partial = {}): SubagentRunRecor } describe("subagent registry sqlite store", () => { - const envSnapshot = captureEnv(["OPENCLAW_STATE_DIR"]); let tempStateDir: string | null = null; beforeEach(async () => { tempStateDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-subagent-sqlite-")); - process.env.OPENCLAW_STATE_DIR = tempStateDir; }); afterEach(async () => { @@ -70,69 +68,81 @@ describe("subagent registry sqlite store", () => { await fs.rm(tempStateDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 50 }); tempStateDir = null; } - envSnapshot.restore(); }); + async function withTempStateEnv(fn: () => Promise): Promise { + if (!tempStateDir) { + throw new Error("expected temp state dir"); + } + return await withEnvAsync({ OPENCLAW_STATE_DIR: tempStateDir }, fn); + } + it("persists subagent runs in the shared sqlite state database", async () => { - const run = createRun(); + await withTempStateEnv(async () => { + const run = createRun(); - saveSubagentRegistryToSqlite(new Map([[run.runId, run]])); + saveSubagentRegistryToSqlite(new Map([[run.runId, run]])); - const restored = loadSubagentRegistryFromSqlite(); - expect(restored.get(run.runId)).toMatchObject({ - runId: run.runId, - childSessionKey: run.childSessionKey, - requesterSessionKey: run.requesterSessionKey, - task: run.task, - endedAt: run.endedAt, - outcome: run.outcome, - completion: run.completion, - delivery: run.delivery, + const restored = loadSubagentRegistryFromSqlite(); + expect(restored.get(run.runId)).toMatchObject({ + runId: run.runId, + childSessionKey: run.childSessionKey, + requesterSessionKey: run.requesterSessionKey, + task: run.task, + endedAt: run.endedAt, + outcome: run.outcome, + completion: run.completion, + delivery: run.delivery, + }); + expect(await fs.stat(path.join(tempStateDir!, "state", "openclaw.sqlite"))).toBeTruthy(); + await expect(fs.stat(path.join(tempStateDir!, "subagents", "runs.json"))).rejects.toThrow(); }); - expect(await fs.stat(path.join(tempStateDir!, "state", "openclaw.sqlite"))).toBeTruthy(); - await expect(fs.stat(path.join(tempStateDir!, "subagents", "runs.json"))).rejects.toThrow(); }); - it("uses save calls as whole-registry snapshots", () => { - const first = createRun({ runId: "run-one", childSessionKey: "agent:main:subagent:one" }); - const second = createRun({ runId: "run-two", childSessionKey: "agent:main:subagent:two" }); + it("uses save calls as whole-registry snapshots", async () => { + await withTempStateEnv(async () => { + const first = createRun({ runId: "run-one", childSessionKey: "agent:main:subagent:one" }); + const second = createRun({ runId: "run-two", childSessionKey: "agent:main:subagent:two" }); - saveSubagentRegistryToSqlite( - new Map([ - [first.runId, first], - [second.runId, second], - ]), - ); - saveSubagentRegistryToSqlite(new Map([[second.runId, second]])); + saveSubagentRegistryToSqlite( + new Map([ + [first.runId, first], + [second.runId, second], + ]), + ); + saveSubagentRegistryToSqlite(new Map([[second.runId, second]])); - expect([...loadSubagentRegistryFromSqlite().keys()]).toEqual(["run-two"]); + expect([...loadSubagentRegistryFromSqlite().keys()]).toEqual(["run-two"]); + }); }); it("imports the legacy json registry when sqlite has no runs", async () => { - // Import deletes the JSON source after the first successful migration so - // later loads treat SQLite as canonical state. - const legacyRun = createRun({ - runId: "legacy-run", - childSessionKey: "agent:main:subagent:legacy", - task: "import legacy registry", + await withTempStateEnv(async () => { + // Import deletes the JSON source after the first successful migration so + // later loads treat SQLite as canonical state. + const legacyRun = createRun({ + runId: "legacy-run", + childSessionKey: "agent:main:subagent:legacy", + task: "import legacy registry", + }); + const registryPath = path.join(tempStateDir!, "subagents", "runs.json"); + await fs.mkdir(path.dirname(registryPath), { recursive: true }); + await fs.writeFile( + registryPath, + `${JSON.stringify({ version: 2, runs: { [legacyRun.runId]: legacyRun } })}\n`, + "utf8", + ); + + const imported = loadSubagentRegistryFromSqlite(); + + expect(imported.get(legacyRun.runId)?.task).toBe("import legacy registry"); + await expect(fs.stat(registryPath)).rejects.toThrow(); + expect(loadSubagentRegistryFromSqlite().get(legacyRun.runId)?.task).toBe( + "import legacy registry", + ); + expect( + openOpenClawStateDatabase().db.prepare("SELECT COUNT(*) AS count FROM subagent_runs").get(), + ).toEqual({ count: 1 }); }); - const registryPath = path.join(tempStateDir!, "subagents", "runs.json"); - await fs.mkdir(path.dirname(registryPath), { recursive: true }); - await fs.writeFile( - registryPath, - `${JSON.stringify({ version: 2, runs: { [legacyRun.runId]: legacyRun } })}\n`, - "utf8", - ); - - const imported = loadSubagentRegistryFromSqlite(); - - expect(imported.get(legacyRun.runId)?.task).toBe("import legacy registry"); - await expect(fs.stat(registryPath)).rejects.toThrow(); - expect(loadSubagentRegistryFromSqlite().get(legacyRun.runId)?.task).toBe( - "import legacy registry", - ); - expect( - openOpenClawStateDatabase().db.prepare("SELECT COUNT(*) AS count FROM subagent_runs").get(), - ).toEqual({ count: 1 }); }); });