From b2ff1f85a65adbb0a26ad33c6b99f8827f2191ea Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 15 May 2026 16:59:08 +0100 Subject: [PATCH] fix(acpx): key sqlite sessions by record id --- extensions/acpx/src/runtime.test.ts | 40 +++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/extensions/acpx/src/runtime.test.ts b/extensions/acpx/src/runtime.test.ts index d6700b09e18..bc98087fe1f 100644 --- a/extensions/acpx/src/runtime.test.ts +++ b/extensions/acpx/src/runtime.test.ts @@ -1,7 +1,8 @@ import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; -import { beforeEach, describe, expect, it, vi } from "vitest"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { resetPluginStateStoreForTests } from "../../../src/plugin-state/plugin-state-store.js"; import { AcpRuntimeError, type AcpRuntime, @@ -9,7 +10,7 @@ import { type AcpRuntimeTurn, } from "../runtime-api.js"; import { OPENCLAW_ACPX_LEASE_ID_ARG, OPENCLAW_GATEWAY_INSTANCE_ID_ARG } from "./process-lease.js"; -import { AcpxRuntime, testing } from "./runtime.js"; +import { AcpxRuntime, createSqliteSessionStore, testing } from "./runtime.js"; type TestSessionStore = { load(sessionId: string): Promise | undefined>; @@ -24,6 +25,7 @@ const CODEX_ACP_WRAPPER_COMMAND_WITH_LEASE = `${CODEX_ACP_WRAPPER_COMMAND} ${OPE const LOCAL_NODE_MODULES_CODEX_COMMAND = `node "${path.resolve( "node_modules/@zed-industries/codex-acp/bin/codex-acp.js", )}"`; +const ORIGINAL_STATE_DIR = process.env.OPENCLAW_STATE_DIR; function makeRuntime( baseStore: TestSessionStore, @@ -142,6 +144,40 @@ describe("AcpxRuntime fresh reset wrapper", () => { vi.restoreAllMocks(); }); + afterEach(() => { + if (ORIGINAL_STATE_DIR === undefined) { + delete process.env.OPENCLAW_STATE_DIR; + } else { + process.env.OPENCLAW_STATE_DIR = ORIGINAL_STATE_DIR; + } + resetPluginStateStoreForTests(); + }); + + it("keys SQLite session records by acpxRecordId before display name", async () => { + const stateDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-acpx-session-store-")); + process.env.OPENCLAW_STATE_DIR = stateDir; + resetPluginStateStoreForTests(); + + const store = createSqliteSessionStore(); + const record = { + name: "agent:codex:acp:oneshot", + sessionKey: "agent:codex:acp:oneshot", + acpxRecordId: "agent:codex:acp:oneshot:run-1", + }; + + try { + await store.save(record as never); + + await expect(store.load(record.acpxRecordId)).resolves.toMatchObject({ + acpxRecordId: record.acpxRecordId, + }); + await expect(store.load(record.name)).resolves.toBeUndefined(); + } finally { + resetPluginStateStoreForTests(); + await fs.rm(stateDir, { recursive: true, force: true }); + } + }); + it("rejects unsupported runtime session modes with a clear AcpRuntimeError (issue #73071)", async () => { const baseStore: TestSessionStore = { load: vi.fn(async () => undefined),