diff --git a/extensions/matrix/src/matrix/client/storage.test.ts b/extensions/matrix/src/matrix/client/storage.test.ts index 13369dad23a..30181e74d52 100644 --- a/extensions/matrix/src/matrix/client/storage.test.ts +++ b/extensions/matrix/src/matrix/client/storage.test.ts @@ -28,6 +28,7 @@ vi.mock("../../../../../src/infra/backup-create.js", async (importOriginal) => { }); let maybeMigrateLegacyStorage: typeof import("./storage.js").maybeMigrateLegacyStorage; +let resolveMatrixStateFilePath: typeof import("./storage.js").resolveMatrixStateFilePath; let resolveMatrixStoragePaths: typeof import("./storage.js").resolveMatrixStoragePaths; describe("matrix client storage paths", () => { @@ -39,7 +40,8 @@ describe("matrix client storage paths", () => { }; beforeAll(async () => { - ({ maybeMigrateLegacyStorage, resolveMatrixStoragePaths } = await import("./storage.js")); + ({ maybeMigrateLegacyStorage, resolveMatrixStateFilePath, resolveMatrixStoragePaths } = + await import("./storage.js")); }); afterEach(() => { @@ -111,6 +113,26 @@ describe("matrix client storage paths", () => { }); } + it("resolves state file paths inside the selected storage root", () => { + setupStateDir(); + const filePath = resolveMatrixStateFilePath({ + auth: { + ...defaultStorageAuth, + accountId: "ops", + deviceId: "DEVICE1", + }, + filename: "thread-bindings.json", + env: {}, + }); + + expect(filePath).toBe( + path.join( + resolveDefaultStoragePaths({ accountId: "ops", deviceId: "DEVICE1" }).rootDir, + "thread-bindings.json", + ), + ); + }); + function writeLegacyMatrixStorage( stateDir: string, params: { diff --git a/extensions/matrix/src/matrix/client/storage.ts b/extensions/matrix/src/matrix/client/storage.ts index 887834e0122..8ef49bca4aa 100644 --- a/extensions/matrix/src/matrix/client/storage.ts +++ b/extensions/matrix/src/matrix/client/storage.ts @@ -11,6 +11,7 @@ import { resolveMatrixAccountStorageRoot, resolveMatrixLegacyFlatStoragePaths, } from "../../storage-paths.js"; +import type { MatrixAuth } from "./types.js"; import type { MatrixStoragePaths } from "./types.js"; export const DEFAULT_ACCOUNT_KEY = "default"; @@ -293,6 +294,25 @@ export function resolveMatrixStoragePaths(params: { }; } +export function resolveMatrixStateFilePath(params: { + auth: MatrixAuth; + filename: string; + accountId?: string | null; + env?: NodeJS.ProcessEnv; + stateDir?: string; +}): string { + const storagePaths = resolveMatrixStoragePaths({ + homeserver: params.auth.homeserver, + userId: params.auth.userId, + accessToken: params.auth.accessToken, + accountId: params.accountId ?? params.auth.accountId, + deviceId: params.auth.deviceId, + env: params.env, + stateDir: params.stateDir, + }); + return path.join(storagePaths.rootDir, params.filename); +} + export async function maybeMigrateLegacyStorage(params: { storagePaths: MatrixStoragePaths; env?: NodeJS.ProcessEnv; diff --git a/extensions/matrix/src/matrix/monitor/inbound-dedupe.ts b/extensions/matrix/src/matrix/monitor/inbound-dedupe.ts index 43dd5fc303b..035206d78dd 100644 --- a/extensions/matrix/src/matrix/monitor/inbound-dedupe.ts +++ b/extensions/matrix/src/matrix/monitor/inbound-dedupe.ts @@ -1,7 +1,6 @@ -import path from "node:path"; import { readJsonFileWithFallback, writeJsonFileAtomically } from "../../runtime-api.js"; import { createAsyncLock } from "../async-lock.js"; -import { resolveMatrixStoragePaths } from "../client/storage.js"; +import { resolveMatrixStateFilePath } from "../client/storage.js"; import type { MatrixAuth } from "../client/types.js"; import { LogService } from "../sdk/logger.js"; @@ -44,16 +43,12 @@ function resolveInboundDedupeStatePath(params: { env?: NodeJS.ProcessEnv; stateDir?: string; }): string { - const storagePaths = resolveMatrixStoragePaths({ - homeserver: params.auth.homeserver, - userId: params.auth.userId, - accessToken: params.auth.accessToken, - accountId: params.auth.accountId, - deviceId: params.auth.deviceId, + return resolveMatrixStateFilePath({ + auth: params.auth, env: params.env, stateDir: params.stateDir, + filename: INBOUND_DEDUPE_FILENAME, }); - return path.join(storagePaths.rootDir, INBOUND_DEDUPE_FILENAME); } function normalizeTimestamp(raw: unknown): number | null { diff --git a/extensions/matrix/src/matrix/thread-bindings.test.ts b/extensions/matrix/src/matrix/thread-bindings.test.ts index a22243b2147..663a5887d16 100644 --- a/extensions/matrix/src/matrix/thread-bindings.test.ts +++ b/extensions/matrix/src/matrix/thread-bindings.test.ts @@ -8,7 +8,7 @@ import { } from "../../../../src/infra/outbound/session-binding-service.js"; import type { PluginRuntime } from "../../runtime-api.js"; import { setMatrixRuntime } from "../runtime.js"; -import { resolveMatrixStoragePaths } from "./client/storage.js"; +import { resolveMatrixStateFilePath, resolveMatrixStoragePaths } from "./client/storage.js"; import { createMatrixThreadBindingManager, resetMatrixThreadBindingsForTests, @@ -87,14 +87,12 @@ describe("matrix thread bindings", () => { } function resolveBindingsFilePath(customStateDir?: string) { - return path.join( - resolveMatrixStoragePaths({ - ...auth, - env: process.env, - ...(customStateDir ? { stateDir: customStateDir } : {}), - }).rootDir, - "thread-bindings.json", - ); + return resolveMatrixStateFilePath({ + auth, + env: process.env, + ...(customStateDir ? { stateDir: customStateDir } : {}), + filename: "thread-bindings.json", + }); } async function readPersistedLastActivityAt(bindingsPath: string) { diff --git a/extensions/matrix/src/matrix/thread-bindings.ts b/extensions/matrix/src/matrix/thread-bindings.ts index 1bc3945ccc2..69b04a7f98c 100644 --- a/extensions/matrix/src/matrix/thread-bindings.ts +++ b/extensions/matrix/src/matrix/thread-bindings.ts @@ -1,4 +1,3 @@ -import path from "node:path"; import type { SessionBindingAdapter } from "openclaw/plugin-sdk/conversation-runtime"; import { readJsonFileWithFallback, @@ -8,7 +7,7 @@ import { unregisterSessionBindingAdapter, writeJsonFileAtomically, } from "../runtime-api.js"; -import { resolveMatrixStoragePaths } from "./client/storage.js"; +import { resolveMatrixStateFilePath } from "./client/storage.js"; import type { MatrixAuth } from "./client/types.js"; import type { MatrixClient } from "./sdk.js"; import { sendMessageMatrix } from "./send.js"; @@ -62,16 +61,13 @@ function resolveBindingsPath(params: { env?: NodeJS.ProcessEnv; stateDir?: string; }): string { - const storagePaths = resolveMatrixStoragePaths({ - homeserver: params.auth.homeserver, - userId: params.auth.userId, - accessToken: params.auth.accessToken, + return resolveMatrixStateFilePath({ + auth: params.auth, accountId: params.accountId, - deviceId: params.auth.deviceId, env: params.env, stateDir: params.stateDir, + filename: "thread-bindings.json", }); - return path.join(storagePaths.rootDir, "thread-bindings.json"); } async function loadBindingsFromDisk(filePath: string, accountId: string) {