diff --git a/CHANGELOG.md b/CHANGELOG.md index 3db4cdfbe26..e7c6b61610a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -244,7 +244,7 @@ Docs: https://docs.openclaw.ai - Plugins/facades: resolve globally installed bundled-plugin runtime facades from registry roots so bundled channels like LINE still boot when the winning plugin install lives under the global extensions directory with an encoded scoped folder name. (#61297) Thanks @openperf. - Matrix: avoid failing startup when token auth already knows the user ID but still needs optional device metadata, retry transient auth bootstrap requests, and backfill missing device IDs after startup while keeping unknown-device storage reuse conservative until metadata is repaired. (#61383) Thanks @gumadeiras. - Agents/exec: stop streaming `tool_execution_update` events after an exec session backgrounds, preventing delayed background output from hitting a stale listener and crashing the gateway while keeping the output available through `process poll/log`. (#61627) Thanks @openperf. -- Matrix: pass configured `deviceId` through health probes and keep probe-only client setup from rewriting `storage-meta.json`, so health checks preserve the correct device identity during probe cycles. (#61581) thanks @MoerAI. +- Matrix: pass configured `deviceId` through health probes and keep probe-only client setup out of durable Matrix storage, so health checks preserve the correct device identity without rewriting `storage-meta.json` or related probe state on disk. (#61581) thanks @MoerAI. ## 2026.4.2 diff --git a/extensions/matrix/src/matrix/client/create-client.test.ts b/extensions/matrix/src/matrix/client/create-client.test.ts index b26b2005d96..4a2b28105a3 100644 --- a/extensions/matrix/src/matrix/client/create-client.test.ts +++ b/extensions/matrix/src/matrix/client/create-client.test.ts @@ -68,18 +68,48 @@ describe("createMatrixClient", () => { accountId: undefined, deviceId: undefined, }); - expect(MatrixClientMock).toHaveBeenCalledTimes(1); + expect(resolveMatrixStoragePathsMock).toHaveBeenCalledTimes(1); + expect(MatrixClientMock).toHaveBeenCalledWith("https://matrix.example.org", "tok", { + userId: "@bot:example.org", + password: undefined, + deviceId: undefined, + encryption: undefined, + localTimeoutMs: undefined, + initialSyncLimit: undefined, + storagePath: storagePaths.storagePath, + recoveryKeyPath: storagePaths.recoveryKeyPath, + idbSnapshotPath: storagePaths.idbSnapshotPath, + cryptoDatabasePrefix: "openclaw-matrix-default-token-hash", + autoBootstrapCrypto: undefined, + ssrfPolicy: undefined, + dispatcherPolicy: undefined, + }); }); - it("skips storage metadata writes when persistence is disabled", async () => { + it("skips persistent storage wiring when persistence is disabled", async () => { await createMatrixClient({ homeserver: "https://matrix.example.org", userId: "@bot:example.org", accessToken: "tok", - persistStorageMeta: false, + persistStorage: false, }); + expect(resolveMatrixStoragePathsMock).not.toHaveBeenCalled(); expect(writeStorageMetaMock).not.toHaveBeenCalled(); - expect(MatrixClientMock).toHaveBeenCalledTimes(1); + expect(MatrixClientMock).toHaveBeenCalledWith("https://matrix.example.org", "tok", { + userId: "@bot:example.org", + password: undefined, + deviceId: undefined, + encryption: undefined, + localTimeoutMs: undefined, + initialSyncLimit: undefined, + storagePath: undefined, + recoveryKeyPath: undefined, + idbSnapshotPath: undefined, + cryptoDatabasePrefix: undefined, + autoBootstrapCrypto: undefined, + ssrfPolicy: undefined, + dispatcherPolicy: undefined, + }); }); }); diff --git a/extensions/matrix/src/matrix/client/create-client.ts b/extensions/matrix/src/matrix/client/create-client.ts index 6a28e446f69..009f727a943 100644 --- a/extensions/matrix/src/matrix/client/create-client.ts +++ b/extensions/matrix/src/matrix/client/create-client.ts @@ -33,7 +33,7 @@ export async function createMatrixClient(params: { accessToken: string; password?: string; deviceId?: string; - persistStorageMeta?: boolean; + persistStorage?: boolean; encryption?: boolean; localTimeoutMs?: number; initialSyncLimit?: number; @@ -46,29 +46,29 @@ export async function createMatrixClient(params: { const { MatrixClient, ensureMatrixSdkLoggingConfigured } = await loadMatrixCreateClientRuntimeDeps(); ensureMatrixSdkLoggingConfigured(); - const env = process.env; const homeserver = await resolveValidatedMatrixHomeserverUrl(params.homeserver, { dangerouslyAllowPrivateNetwork: params.allowPrivateNetwork, }); const userId = params.userId?.trim() || "unknown"; const matrixClientUserId = params.userId?.trim() || undefined; + const persistStorage = params.persistStorage !== false; + const storagePaths = persistStorage + ? resolveMatrixStoragePaths({ + homeserver, + userId, + accessToken: params.accessToken, + accountId: params.accountId, + deviceId: params.deviceId, + env: process.env, + }) + : null; - const storagePaths = resolveMatrixStoragePaths({ - homeserver, - userId, - accessToken: params.accessToken, - accountId: params.accountId, - deviceId: params.deviceId, - env, - }); - await maybeMigrateLegacyStorage({ - storagePaths, - env, - }); - fs.mkdirSync(storagePaths.rootDir, { recursive: true }); - - // Health probes still need validated paths, but they must not rewrite durable identity metadata. - if (params.persistStorageMeta !== false) { + if (storagePaths) { + await maybeMigrateLegacyStorage({ + storagePaths, + env: process.env, + }); + fs.mkdirSync(storagePaths.rootDir, { recursive: true }); writeStorageMeta({ storagePaths, homeserver, @@ -78,7 +78,9 @@ export async function createMatrixClient(params: { }); } - const cryptoDatabasePrefix = `openclaw-matrix-${storagePaths.accountKey}-${storagePaths.tokenHash}`; + const cryptoDatabasePrefix = storagePaths + ? `openclaw-matrix-${storagePaths.accountKey}-${storagePaths.tokenHash}` + : undefined; return new MatrixClient(homeserver, params.accessToken, { userId: matrixClientUserId, @@ -87,9 +89,9 @@ export async function createMatrixClient(params: { encryption: params.encryption, localTimeoutMs: params.localTimeoutMs, initialSyncLimit: params.initialSyncLimit, - storagePath: storagePaths.storagePath, - recoveryKeyPath: storagePaths.recoveryKeyPath, - idbSnapshotPath: storagePaths.idbSnapshotPath, + storagePath: storagePaths?.storagePath, + recoveryKeyPath: storagePaths?.recoveryKeyPath, + idbSnapshotPath: storagePaths?.idbSnapshotPath, cryptoDatabasePrefix, autoBootstrapCrypto: params.autoBootstrapCrypto, ssrfPolicy: params.ssrfPolicy, diff --git a/extensions/matrix/src/matrix/probe.test.ts b/extensions/matrix/src/matrix/probe.test.ts index 04c62865591..8ad2f708e93 100644 --- a/extensions/matrix/src/matrix/probe.test.ts +++ b/extensions/matrix/src/matrix/probe.test.ts @@ -34,7 +34,7 @@ describe("probeMatrix", () => { homeserver: "https://matrix.example.org", userId: undefined, accessToken: "tok", - persistStorageMeta: false, + persistStorage: false, localTimeoutMs: 1234, }); }); @@ -51,7 +51,7 @@ describe("probeMatrix", () => { homeserver: "https://matrix.example.org", userId: "@bot:example.org", accessToken: "tok", - persistStorageMeta: false, + persistStorage: false, localTimeoutMs: 500, }); }); @@ -69,7 +69,7 @@ describe("probeMatrix", () => { homeserver: "https://matrix.example.org", userId: "@bot:example.org", accessToken: "tok", - persistStorageMeta: false, + persistStorage: false, localTimeoutMs: 500, accountId: "ops", }); @@ -90,7 +90,7 @@ describe("probeMatrix", () => { homeserver: "https://matrix.example.org", userId: undefined, accessToken: "tok", - persistStorageMeta: false, + persistStorage: false, localTimeoutMs: 500, dispatcherPolicy: { mode: "explicit-proxy", @@ -114,7 +114,7 @@ describe("probeMatrix", () => { userId: "@bot:example.org", accessToken: "tok", deviceId: "ABCDEF", - persistStorageMeta: false, + persistStorage: false, localTimeoutMs: 500, accountId: "ops", }); @@ -132,7 +132,7 @@ describe("probeMatrix", () => { userId: undefined, accessToken: "tok", deviceId: undefined, - persistStorageMeta: false, + persistStorage: false, localTimeoutMs: 500, }); }); diff --git a/extensions/matrix/src/matrix/probe.ts b/extensions/matrix/src/matrix/probe.ts index 91591d0a103..2ab83e49f75 100644 --- a/extensions/matrix/src/matrix/probe.ts +++ b/extensions/matrix/src/matrix/probe.ts @@ -67,7 +67,7 @@ export async function probeMatrix(params: { userId: inputUserId, accessToken: params.accessToken, deviceId: params.deviceId, - persistStorageMeta: false, + persistStorage: false, localTimeoutMs: params.timeoutMs, accountId: params.accountId, allowPrivateNetwork: params.allowPrivateNetwork,