mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 05:51:15 +08:00
test: scope subagent sqlite state env
This commit is contained in:
@@ -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<SubagentRunRecord> = {}): 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<T>(fn: () => Promise<T>): Promise<T> {
|
||||
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 });
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user