@openclaw/matrix 2026.7.2-beta.7 → 2026.8.1-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/{account-selection-kqquRzCf.js → account-selection-CWuhuFn1.js} +7 -8
  2. package/dist/{accounts-DfngqebB.js → accounts-BCzyubQt.js} +3 -3
  3. package/dist/api.js +7 -10
  4. package/dist/{approval-handler.runtime-DSeaIsGa.js → approval-handler.runtime-CJXCUdRg.js} +5 -5
  5. package/dist/{approval-ids-BdJGPAJT.js → approval-ids-7rf7etWE.js} +1 -1
  6. package/dist/{approval-reaction-auth-BjOpELxu.js → approval-reaction-auth-wBwbEDpZ.js} +2 -2
  7. package/dist/{approval-reactions-D-BxBK_L.js → approval-reactions-tXh9KYrW.js} +2 -8
  8. package/dist/auth-presence.js +2 -2
  9. package/dist/{channel-vj788dNZ.js → channel-VSrHgTON.js} +156 -136
  10. package/dist/channel-plugin-api.js +1 -1
  11. package/dist/{channel.runtime-CLoF2S9T.js → channel.runtime-pOOL0uT_.js} +70 -56
  12. package/dist/{config-schema-Djxw3C6b.js → channel.setup-PpxRP9Du.js} +50 -3
  13. package/dist/{cli-DMqfDE-q.js → cli-CkTfKC_c.js} +16 -16
  14. package/dist/{cli-metadata-C7D53SND.js → cli-metadata-B1d1aGM5.js} +1 -1
  15. package/dist/cli-metadata.js +1 -1
  16. package/dist/client-CeGw0G5S.js +784 -0
  17. package/dist/{client-bootstrap-XsIkHNt0.js → client-bootstrap-BFwT_2VT.js} +25 -61
  18. package/dist/{client-6eRENr7k.js → client-sJesKQmp.js} +4 -4
  19. package/dist/client-support-DLj4vDeu.js +93 -0
  20. package/dist/config-update-Bor_Pjsv.js +150 -0
  21. package/dist/contract-api.js +2 -2
  22. package/dist/{credentials-W2EmwRhu.js → credentials-BdAaWuiR.js} +2 -1
  23. package/dist/credentials-read-B37cQknZ.js +51 -0
  24. package/dist/credentials-state-B3cuUFwZ.js +27 -0
  25. package/dist/{credentials-write.runtime-Be9zNSUw.js → credentials-write.runtime-nAV2-5uR.js} +1 -1
  26. package/dist/{crypto-runtime-D9_6J5tZ.js → crypto-runtime-Bnz3zEcS.js} +55 -32
  27. package/dist/direct-room-RinHjtqX.js +71 -0
  28. package/dist/{directory-live-C8dVBiCc.js → directory-live-Bvg2wAnR.js} +1 -2
  29. package/dist/{doctor-CM8ijNpW.js → doctor-EWf9CDso.js} +2 -2
  30. package/dist/{doctor-contract-BMSJkkAE.js → doctor-contract-DEt4O4Zt.js} +2 -3
  31. package/dist/doctor-contract-api.js +202 -90
  32. package/dist/{draft-stream-CtvOXq0Z.js → draft-stream-BRi7PRRS.js} +20 -23
  33. package/dist/{encryption-guidance-CbEFe38F.js → encryption-guidance-DmLY8NiO.js} +1 -1
  34. package/dist/{env-auth-CQsYbz-p.js → env-auth-MVS-Vv41.js} +4 -3
  35. package/dist/{env-vars-B0NxQnPk.js → env-vars-dGqak9dN.js} +1 -1
  36. package/dist/{errors-C47hvAF8.js → errors-DKVS3_DO.js} +2 -5
  37. package/dist/{file-sync-store-DiiFsayX.js → file-sync-store-DjskBX2o.js} +24 -3
  38. package/dist/helper-api.js +2 -2
  39. package/dist/{idb-persistence-B6x7dMsF.js → idb-persistence-BM0P27Zg.js} +3 -2
  40. package/dist/{inbound-dedupe-CaBLblef.js → inbound-dedupe-RvSLqdsz.js} +2 -2
  41. package/dist/index.js +1 -1
  42. package/dist/{logger-D0GCSDQq.js → logger-B_71hN6W.js} +1 -1
  43. package/dist/{logging-DV-p52N0.js → logging-DRjvUOIh.js} +1 -1
  44. package/dist/{media-text-BTwzADS_.js → media-text-JudlYOSc.js} +1 -1
  45. package/dist/{messages-DxQJkhxs.js → messages-BW0s-6Y9.js} +7 -7
  46. package/dist/{monitor-VyWlSLwo.js → monitor-Ddfc-vjX.js} +394 -384
  47. package/dist/plugin-entry.handlers.runtime.js +3 -3
  48. package/dist/probe.runtime-Dr91B_X3.js +2 -0
  49. package/dist/profile-D-Wubo0A.js +108 -0
  50. package/dist/{profile-update-CffmyW_4.js → profile-update-BkgWYDIp.js} +3 -2
  51. package/dist/{reaction-events-B00WSi98.js → reaction-events-nfUbFLdV.js} +9 -6
  52. package/dist/{recovery-key-store-BNnHvXdk.js → recovery-key-store-CognuDys.js} +5 -4
  53. package/dist/{resolve-targets-nm2L48sh.js → resolve-targets-BJAPY4Vb.js} +1 -1
  54. package/dist/{resolver.runtime-DS6uPaEe.js → resolver.runtime-LWJELYq5.js} +1 -1
  55. package/dist/{room-info-CAFZ3Z9J.js → room-info-BXQA7y10.js} +12 -3
  56. package/dist/runtime-api.js +6 -3
  57. package/dist/{sdk-bUytQHx7.js → sdk-DjaQFCHc.js} +229 -120
  58. package/dist/{secret-contract-M3hRmGO-.js → secret-contract-CufozuyJ.js} +1 -1
  59. package/dist/secret-contract-api.js +1 -1
  60. package/dist/{send-BldGYG8g.js → send-ZDLU4JTk.js} +1462 -1196
  61. package/dist/session-binding-contract-api.js +1 -1
  62. package/dist/{setup-bootstrap-Deleiibz.js → setup-bootstrap-BaXkhgJg.js} +4 -4
  63. package/dist/{setup-core-BVfBv2ai.js → setup-core-DQn6b5vi.js} +17 -266
  64. package/dist/setup-plugin-api.js +1 -44
  65. package/dist/{setup-surface-BBq3WeqX.js → setup-surface-DlhJdrNI.js} +9 -11
  66. package/dist/{startup-verification-wm3_i88s.js → startup-verification-Cs08ca8u.js} +3 -3
  67. package/dist/{storage-BvAkgzvT.js → storage-BsGuHngK.js} +3 -3
  68. package/dist/{thread-bindings-DGbl3vDW.js → thread-bindings-CcHZP3w2.js} +7 -4
  69. package/dist/{tool-actions.runtime-uu9blSqO.js → tool-actions.runtime-DmdRL0bN.js} +35 -18
  70. package/dist/{verification-DYMQ1QpI.js → verification-C7ig-bQE.js} +2 -2
  71. package/openclaw.plugin.json +54 -1
  72. package/package.json +4 -4
  73. package/dist/active-client-DXvz2gCo.js +0 -20
  74. package/dist/client-Dbso3-0V.js +0 -30
  75. package/dist/create-client-BmSU-q-D.js +0 -61
  76. package/dist/credentials-read-DVmFCm7X.js +0 -77
  77. package/dist/exec-approval-resolver-BCgqRtZS.js +0 -16
  78. package/dist/preflight-audio.runtime-BZxxQsxY.js +0 -11
  79. package/dist/probe.runtime-BuieqmS3.js +0 -3
  80. package/dist/record-shared-CWWx6fvI.js +0 -2
  81. package/dist/shared-CUMWxcMz.js +0 -673
  82. package/dist/sync-state-CWbp0QSY.js +0 -12
  83. package/dist/{runtime-api-D1xI_cvh.js → runtime-api-BGO16Fu8.js} +3 -3
@@ -1,19 +1,25 @@
1
- import { n as formatMatrixErrorReason, r as isMatrixNotFoundError, t as formatMatrixErrorMessage } from "./errors-C47hvAF8.js";
2
- import { t as SqliteBackedMatrixSyncStore } from "./file-sync-store-DiiFsayX.js";
3
- import { n as LogService, r as noop, t as ConsoleLogger } from "./logger-D0GCSDQq.js";
1
+ import "./reaction-common-DkrQdBSZ.js";
2
+ import { t as SqliteBackedMatrixSyncStore } from "./file-sync-store-DjskBX2o.js";
3
+ import { n as LogService, r as noop, t as ConsoleLogger } from "./logger-B_71hN6W.js";
4
4
  import { t as MATRIX_IDB_PERSIST_INTERVAL_MS } from "./idb-persistence-lock-DAJ49nZX.js";
5
- import { c as createMatrixStartupAbortError, u as throwIfMatrixStartupAborted } from "./shared-CUMWxcMz.js";
5
+ import { n as isMatrixNotFoundError, t as formatMatrixErrorReason } from "./errors-DKVS3_DO.js";
6
+ import { a as throwIfMatrixStartupAborted, r as createMatrixStartupAbortError } from "./client-CeGw0G5S.js";
6
7
  import { a as matrixEventToRaw, n as createMatrixGuardedFetch, o as parseMxc, t as MatrixAuthedHttpClient } from "./http-client-CycYxU9-.js";
7
8
  import { n as resolveMatrixRoomKeyBackupReadinessError } from "./backup-health-Dm_YMVFT.js";
8
- import { t as createMatrixJsSdkClientLogger } from "./logging-DV-p52N0.js";
9
- import { n as isMatrixReadySyncState, r as isMatrixTerminalSyncState } from "./sync-state-CWbp0QSY.js";
10
- import { n as isRepairableSecretStorageAccessError, t as MatrixRecoveryKeyStore } from "./recovery-key-store-BNnHvXdk.js";
9
+ import { t as createMatrixJsSdkClientLogger } from "./logging-DRjvUOIh.js";
10
+ import { a as isMatrixAccessTokenInvalidatedError, c as resolveMatrixLocalTimeoutMs, f as isMatrixReadySyncState, i as createMatrixExplicitBootstrapOptions, l as unresolvedMatrixDeviceVerificationStatus, n as MATRIX_INITIAL_CRYPTO_BOOTSTRAP_OPTIONS, o as resolveMatrixDiagnostic, p as isMatrixTerminalSyncState, r as MATRIX_STATUS_DIAGNOSTIC_TIMEOUT_MS, s as resolveMatrixDiagnosticResult, t as MATRIX_AUTOMATIC_REPAIR_BOOTSTRAP_OPTIONS, u as unresolvedMatrixRoomKeyBackupStatus } from "./client-support-DLj4vDeu.js";
11
+ import { n as isRepairableSecretStorageAccessError, t as MatrixRecoveryKeyStore } from "./recovery-key-store-CognuDys.js";
12
+ import { createRequire } from "node:module";
11
13
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
12
14
  import { normalizeNullableString, normalizeStringEntries, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
15
+ import { createHash } from "node:crypto";
16
+ import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
13
17
  import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
14
- import { ClientEvent, Filter, MatrixEventEvent, Preset, createClient } from "matrix-js-sdk/lib/matrix.js";
18
+ import { ClientEvent, EventType, Filter, MatrixError, MatrixEventEvent, MsgType, Preset, createClient } from "matrix-js-sdk/lib/matrix.js";
15
19
  import { EventEmitter } from "node:events";
16
20
  import { VerificationMethod } from "matrix-js-sdk/lib/types.js";
21
+ import { SyncApi, SyncState } from "matrix-js-sdk/lib/sync.js";
22
+ import { EventStatus } from "matrix-js-sdk/lib/models/event-status.js";
17
23
  //#region extensions/matrix/src/matrix/sdk/client-device-info.ts
18
24
  async function resolveMatrixCrossSigningPublicationStatus(params) {
19
25
  if (!params.userId) return {
@@ -78,8 +84,8 @@ function registerMatrixClientBridge(params) {
78
84
  });
79
85
  params.client.on(ClientEvent.Room, params.emitMembershipForRoom);
80
86
  params.client.on(ClientEvent.Sync, (state, prevState, data) => {
81
- params.setCurrentSyncState(state);
82
87
  const error = data && typeof data === "object" && "error" in data ? data.error : void 0;
88
+ params.setCurrentSyncState(state, error);
83
89
  params.emitter.emit("sync.state", state, prevState, error);
84
90
  });
85
91
  params.client.on(ClientEvent.SyncUnexpectedError, (error) => {
@@ -115,89 +121,81 @@ function refreshMatrixDmRoomIds(direct, dmRoomIds) {
115
121
  return true;
116
122
  }
117
123
  //#endregion
118
- //#region extensions/matrix/src/matrix/sdk/client-support.ts
119
- const MATRIX_STATUS_DIAGNOSTIC_TIMEOUT_MS = 1e4;
120
- const DEFAULT_MATRIX_LOCAL_TIMEOUT_MS = 6e4;
121
- function resolveMatrixLocalTimeoutMs(raw) {
122
- if (typeof raw !== "number" || !Number.isFinite(raw)) return DEFAULT_MATRIX_LOCAL_TIMEOUT_MS;
123
- return Math.max(1, Math.floor(raw));
124
+ //#region extensions/matrix/src/matrix/sdk/client-sync-quiesce.ts
125
+ const MATRIX_SYNC_QUIESCE_TIMEOUT_MS = 5e3;
126
+ const MATRIX_JS_SDK_SYNC_VERSION = "41.9.0";
127
+ const matrixJsSdkPackage = createRequire(import.meta.url)("matrix-js-sdk/package.json");
128
+ function assertMatrixJsSdkSyncVersion() {
129
+ const version = matrixJsSdkPackage.version;
130
+ if (version !== MATRIX_JS_SDK_SYNC_VERSION) throw new Error(`Matrix sync quiesce requires matrix-js-sdk ${MATRIX_JS_SDK_SYNC_VERSION}; found ${String(version)}`);
124
131
  }
125
- function unresolvedMatrixRoomKeyBackupStatus() {
126
- return {
127
- serverVersion: null,
128
- activeVersion: null,
129
- trusted: null,
130
- matchesDecryptionKey: null,
131
- decryptionKeyCached: null,
132
- keyLoadAttempted: false,
133
- keyLoadError: null
134
- };
135
- }
136
- function unresolvedMatrixDeviceVerificationStatus(params) {
137
- return {
138
- encryptionEnabled: true,
139
- userId: params.userId,
140
- deviceId: params.deviceId,
141
- verified: false,
142
- localVerified: false,
143
- crossSigningVerified: false,
144
- signedByOwner: false
145
- };
146
- }
147
- async function resolveMatrixDiagnostic(promise, timeoutMs) {
148
- return (await resolveMatrixDiagnosticResult(promise, timeoutMs)).value;
149
- }
150
- async function resolveMatrixDiagnosticResult(promise, timeoutMs) {
151
- let timeoutId;
132
+ async function quiesceMatrixClientSync(params) {
133
+ await params.syncStore?.freezeSyncCursorPersistence();
152
134
  try {
153
- const guarded = promise.then((value) => ({
154
- error: null,
155
- timedOut: false,
156
- value
157
- })).catch((error) => ({
158
- error,
159
- timedOut: false,
160
- value: null
161
- }));
162
- const timeout = new Promise((resolve) => {
163
- timeoutId = setTimeout(() => resolve({
164
- error: null,
165
- timedOut: true,
166
- value: null
167
- }), timeoutMs);
168
- timeoutId.unref?.();
169
- });
170
- return await Promise.race([guarded, timeout]);
171
- } finally {
172
- if (timeoutId) clearTimeout(timeoutId);
135
+ assertMatrixJsSdkSyncVersion();
136
+ } catch (error) {
137
+ params.syncStore?.discardPendingSyncCursorPersistence();
138
+ throw error;
139
+ }
140
+ const syncApi = params.client.syncApi;
141
+ if (syncApi === void 0 && !params.started) return;
142
+ if (!(syncApi instanceof SyncApi)) {
143
+ params.syncStore?.discardPendingSyncCursorPersistence();
144
+ throw new Error(syncApi === void 0 ? "Matrix sync quiesce requires the classic matrix-js-sdk SyncApi, but none is active" : "Matrix sync quiesce rejected a sliding or unknown matrix-js-sdk sync implementation");
145
+ }
146
+ if (syncApi.getSyncState() === SyncState.Stopped) {
147
+ params.markStopped();
148
+ return;
173
149
  }
150
+ await new Promise((resolve, reject) => {
151
+ let settled = false;
152
+ const settle = (error) => {
153
+ if (settled) return;
154
+ settled = true;
155
+ clearTimeout(timeout);
156
+ params.emitter.off("sync.state", onSyncState);
157
+ if (error) reject(error);
158
+ else {
159
+ params.markStopped();
160
+ resolve();
161
+ }
162
+ };
163
+ const onSyncState = (state) => {
164
+ if (state === "STOPPED") settle();
165
+ };
166
+ const timeout = setTimeout(() => {
167
+ params.syncStore?.discardPendingSyncCursorPersistence();
168
+ settle(/* @__PURE__ */ new Error(`Matrix classic sync did not reach STOPPED within 5000ms`));
169
+ }, MATRIX_SYNC_QUIESCE_TIMEOUT_MS);
170
+ timeout.unref?.();
171
+ params.emitter.on("sync.state", onSyncState);
172
+ try {
173
+ syncApi.stop();
174
+ } catch (error) {
175
+ params.syncStore?.discardPendingSyncCursorPersistence();
176
+ settle(error instanceof Error ? error : new Error(String(error)));
177
+ }
178
+ });
174
179
  }
175
- function isMatrixAccessTokenInvalidatedError(error) {
176
- if (!error || typeof error !== "object") return false;
177
- const err = error;
178
- const errcode = err.body?.errcode ?? err.data?.errcode;
179
- if (err.statusCode === 401 && errcode === "M_UNKNOWN_TOKEN") return true;
180
- const reason = formatMatrixErrorReason(error);
181
- return reason.includes("m_unknown_token") || reason.includes("unknown token") || reason.includes("access token") && (reason.includes("invalid") || reason.includes("unrecognized") || reason.includes("unknown"));
182
- }
183
- const MATRIX_INITIAL_CRYPTO_BOOTSTRAP_OPTIONS = { allowAutomaticCrossSigningReset: false };
184
- const MATRIX_AUTOMATIC_REPAIR_BOOTSTRAP_OPTIONS = {
185
- forceResetCrossSigning: true,
186
- allowSecretStorageRecreateWithoutRecoveryKey: true,
187
- strict: true
188
- };
189
- function createMatrixExplicitBootstrapOptions(params) {
180
+ //#endregion
181
+ //#region extensions/matrix/src/matrix/sdk/client-base.ts
182
+ function resolveMessageWireDispatch(resource, init) {
183
+ if ((init?.method ?? (resource instanceof Request ? resource.method : "GET")).toUpperCase() !== "PUT") return null;
184
+ const rawUrl = typeof resource === "string" ? resource : resource instanceof URL ? resource.href : resource.url;
185
+ const segments = new URL(rawUrl).pathname.split("/").filter(Boolean);
186
+ const roomsIndex = segments.lastIndexOf("rooms");
187
+ if (roomsIndex < 0 || segments[roomsIndex + 2] !== "send" || segments.length !== roomsIndex + 5) return null;
188
+ const eventType = decodeURIComponent(segments[roomsIndex + 3] ?? "");
189
+ if (eventType !== "m.room.message" && eventType !== "m.room.encrypted") return null;
190
190
  return {
191
- forceResetCrossSigning: params?.forceResetCrossSigning === true,
192
- allowAutomaticCrossSigningReset: params?.allowAutomaticCrossSigningReset !== false,
193
- allowSecretStorageRecreateWithoutRecoveryKey: true,
194
- strict: params?.strict !== false
191
+ roomId: decodeURIComponent(segments[roomsIndex + 1] ?? ""),
192
+ eventType,
193
+ transactionId: decodeURIComponent(segments[roomsIndex + 4] ?? ""),
194
+ requestPath: new URL(rawUrl).pathname
195
195
  };
196
196
  }
197
- //#endregion
198
- //#region extensions/matrix/src/matrix/sdk/client-base.ts
199
197
  let loadedMatrixCryptoRuntime = null;
200
- const loadMatrixCryptoRuntime = createLazyRuntimeModule(() => import("./crypto-runtime-D9_6J5tZ.js").then((runtime) => {
198
+ const loadMatrixCryptoRuntime = createLazyRuntimeModule(() => import("./crypto-runtime-Bnz3zEcS.js").then((runtime) => {
201
199
  loadedMatrixCryptoRuntime = runtime;
202
200
  return runtime;
203
201
  }));
@@ -213,6 +211,11 @@ var MatrixClientBase = class {
213
211
  this.stopPersistPromise = null;
214
212
  this.verificationSummaryListenerBound = false;
215
213
  this.currentSyncState = null;
214
+ this.currentSyncError = void 0;
215
+ this.transactionScopeId = null;
216
+ this.transactionScopePromise = null;
217
+ this.messageWireDispatchGuards = /* @__PURE__ */ new Map();
218
+ this.sdkStopped = false;
216
219
  this.dms = {
217
220
  update: async () => {
218
221
  return await this.refreshDmCache();
@@ -220,6 +223,9 @@ var MatrixClientBase = class {
220
223
  isDm: (roomId) => this.dmRoomIds.has(roomId)
221
224
  };
222
225
  this.idbPersistTimer = null;
226
+ this.transactionScopeHomeserver = homeserver;
227
+ this.transactionScopeAccessTokenHash = createHash("sha256").update(accessToken).digest("hex");
228
+ this.transactionScopeDeviceId = opts.deviceId?.trim() || null;
223
229
  this.httpClient = new MatrixAuthedHttpClient({
224
230
  homeserver,
225
231
  accessToken,
@@ -239,6 +245,10 @@ var MatrixClientBase = class {
239
245
  this.autoBootstrapCrypto = opts.autoBootstrapCrypto !== false;
240
246
  this.recoveryKeyStore = new MatrixRecoveryKeyStore(opts.recoveryKeyPath);
241
247
  const cryptoCallbacks = this.encryptionEnabled ? this.recoveryKeyStore.buildCryptoCallbacks() : void 0;
248
+ const guardedFetch = createMatrixGuardedFetch({
249
+ ssrfPolicy: opts.ssrfPolicy,
250
+ dispatcherPolicy: opts.dispatcherPolicy
251
+ });
242
252
  this.client = createClient({
243
253
  baseUrl: homeserver,
244
254
  accessToken,
@@ -246,9 +256,10 @@ var MatrixClientBase = class {
246
256
  deviceId: opts.deviceId,
247
257
  logger: createMatrixJsSdkClientLogger("MatrixClient"),
248
258
  localTimeoutMs: this.localTimeoutMs,
249
- fetchFn: createMatrixGuardedFetch({
250
- ssrfPolicy: opts.ssrfPolicy,
251
- dispatcherPolicy: opts.dispatcherPolicy
259
+ fetchFn: (async (resource, init) => {
260
+ const dispatch = resolveMessageWireDispatch(resource, init);
261
+ if (dispatch) await this.messageWireDispatchGuards.get(dispatch.transactionId)?.(dispatch);
262
+ return await guardedFetch(resource, init);
252
263
  }),
253
264
  store: this.syncStore,
254
265
  cryptoCallbacks,
@@ -260,6 +271,16 @@ var MatrixClientBase = class {
260
271
  ]
261
272
  });
262
273
  }
274
+ async withMessageWireDispatchGuard(params) {
275
+ if (!params.transactionId || !params.guard) return await params.run();
276
+ if (this.messageWireDispatchGuards.has(params.transactionId)) throw new Error(`Matrix transaction ${params.transactionId} already has a dispatch guard`);
277
+ this.messageWireDispatchGuards.set(params.transactionId, params.guard);
278
+ try {
279
+ return await params.run();
280
+ } finally {
281
+ this.messageWireDispatchGuards.delete(params.transactionId);
282
+ }
283
+ }
263
284
  on(eventName, listener) {
264
285
  this.emitter.on(eventName, listener);
265
286
  return this;
@@ -314,7 +335,7 @@ var MatrixClientBase = class {
314
335
  client: this.client,
315
336
  verificationManager: this.verificationManager,
316
337
  recoveryKeyStore: this.recoveryKeyStore,
317
- getRoomStateEvent: (roomId, eventType, stateKey = "") => this.getRoomStateEvent(roomId, eventType, stateKey),
338
+ isRoomEncrypted: async (roomId) => await this.getMessageWireEventType(roomId) === "m.room.encrypted",
318
339
  downloadContent: (mxcUrl, opts) => this.downloadContent(mxcUrl, opts)
319
340
  });
320
341
  if (!this.verificationSummaryListenerBound) {
@@ -334,6 +355,7 @@ var MatrixClientBase = class {
334
355
  async waitForInitialSyncReady(params = {}) {
335
356
  const timeoutMs = params.timeoutMs ?? 3e4;
336
357
  if (isMatrixReadySyncState(this.currentSyncState)) return;
358
+ if (isMatrixAccessTokenInvalidatedError(this.currentSyncError)) throw this.currentSyncError instanceof Error ? this.currentSyncError : new Error("Matrix access token invalidated", { cause: this.currentSyncError });
337
359
  if (isMatrixTerminalSyncState(this.currentSyncState)) throw new Error(`Matrix sync entered ${this.currentSyncState} during startup`);
338
360
  await new Promise((resolve, reject) => {
339
361
  let settled = false;
@@ -365,6 +387,10 @@ var MatrixClientBase = class {
365
387
  settleResolve();
366
388
  return;
367
389
  }
390
+ if (isMatrixAccessTokenInvalidatedError(error)) {
391
+ settleReject(error instanceof Error ? error : /* @__PURE__ */ new Error("Matrix access token invalidated"));
392
+ return;
393
+ }
368
394
  if (isMatrixTerminalSyncState(state)) settleReject(new Error(error instanceof Error && error.message ? error.message : `Matrix sync entered ${state} during startup`));
369
395
  };
370
396
  const onUnexpectedError = (error) => {
@@ -388,6 +414,7 @@ var MatrixClientBase = class {
388
414
  }
389
415
  async startSyncSession(opts) {
390
416
  if (this.started) return;
417
+ if (this.sdkStopped) throw new Error("Matrix client has been fully stopped and cannot be restarted; acquire a new shared client generation");
391
418
  throwIfMatrixStartupAborted(opts.abortSignal);
392
419
  await this.ensureCryptoSupportInitialized();
393
420
  throwIfMatrixStartupAborted(opts.abortSignal);
@@ -425,43 +452,57 @@ var MatrixClientBase = class {
425
452
  if (this.started) return;
426
453
  await this.startSyncSession({ bootstrapCrypto: false });
427
454
  }
428
- stopSyncWithoutPersist() {
455
+ stopSdkClient() {
456
+ if (this.sdkStopped) return;
429
457
  if (this.idbPersistTimer) {
430
458
  clearInterval(this.idbPersistTimer);
431
459
  this.idbPersistTimer = null;
432
460
  }
433
461
  this.currentSyncState = null;
462
+ this.currentSyncError = void 0;
434
463
  this.client.stopClient();
464
+ this.sdkStopped = true;
435
465
  this.started = false;
436
466
  }
467
+ async quiesceSync() {
468
+ await quiesceMatrixClientSync({
469
+ client: this.client,
470
+ emitter: this.emitter,
471
+ markStopped: () => {
472
+ this.started = false;
473
+ },
474
+ started: this.started,
475
+ syncStore: this.syncStore
476
+ });
477
+ }
437
478
  async drainPendingDecryptions(reason = "matrix client shutdown") {
438
479
  await this.decryptBridge?.drainPendingDecryptions(reason);
439
480
  }
440
481
  stop() {
441
- this.stopSyncWithoutPersist();
442
- this.decryptBridge?.stop();
443
- this.syncStore?.markCleanShutdown();
444
- if (loadedMatrixCryptoRuntime) {
445
- const { persistIdbToDisk } = loadedMatrixCryptoRuntime;
446
- this.stopPersistPromise = Promise.all([persistIdbToDisk({
447
- snapshotPath: this.idbSnapshotPath,
448
- databasePrefix: this.cryptoDatabasePrefix
449
- }).catch(noop), this.syncStore?.flush().catch(noop)]).then(() => void 0);
482
+ this.stopAndPersist().catch(() => this.stopWithoutPersist()).catch(noop);
483
+ }
484
+ async stopAndPersist() {
485
+ if (this.stopPersistPromise) {
486
+ await this.stopPersistPromise;
450
487
  return;
451
488
  }
452
- this.stopPersistPromise = loadMatrixCryptoRuntime().then(async ({ persistIdbToDisk }) => {
453
- await Promise.all([persistIdbToDisk({
489
+ this.stopPersistPromise = (async () => {
490
+ await this.quiesceSync();
491
+ this.stopSdkClient();
492
+ this.decryptBridge?.stop();
493
+ await (loadedMatrixCryptoRuntime ?? await loadMatrixCryptoRuntime()).persistIdbToDisk({
454
494
  snapshotPath: this.idbSnapshotPath,
455
- databasePrefix: this.cryptoDatabasePrefix
456
- }).catch(noop), this.syncStore?.flush().catch(noop)]);
457
- }).catch(noop).then(() => void 0);
458
- }
459
- async stopAndPersist() {
460
- this.stop();
495
+ databasePrefix: this.cryptoDatabasePrefix,
496
+ strict: true
497
+ });
498
+ this.syncStore?.markCleanShutdown();
499
+ await this.syncStore?.flush();
500
+ })();
461
501
  await this.stopPersistPromise;
462
502
  }
463
503
  stopWithoutPersist() {
464
- this.stopSyncWithoutPersist();
504
+ this.syncStore?.discardPendingSyncCursorPersistence();
505
+ this.stopSdkClient();
465
506
  this.decryptBridge?.stop();
466
507
  this.stopPersistPromise = Promise.resolve();
467
508
  }
@@ -537,6 +578,30 @@ var MatrixClientCore = class extends MatrixClientBase {
537
578
  const joined = await this.doRequest("GET", "/_matrix/client/v3/joined_rooms");
538
579
  return Array.isArray(joined.joined_rooms) ? joined.joined_rooms : [];
539
580
  }
581
+ async getTransactionScopeId() {
582
+ if (this.transactionScopeId) return this.transactionScopeId;
583
+ const active = this.transactionScopePromise ?? (async () => {
584
+ const configuredUserId = this.client.getUserId()?.trim() || this.selfUserId;
585
+ const configuredDeviceId = this.transactionScopeDeviceId || this.client.getDeviceId()?.trim() || null;
586
+ const whoami = await this.doRequest("GET", "/_matrix/client/v3/account/whoami");
587
+ const userId = whoami.user_id?.trim() || null;
588
+ const deviceId = whoami.device_id?.trim() || null;
589
+ if (!userId) throw new Error("Matrix whoami did not return user_id");
590
+ if (configuredUserId && configuredUserId !== userId) throw new Error("Matrix access token user does not match the configured userId");
591
+ if (configuredDeviceId && deviceId && configuredDeviceId !== deviceId) throw new Error("Matrix access token device does not match the configured deviceId");
592
+ this.selfUserId = userId;
593
+ this.transactionScopeDeviceId = deviceId;
594
+ return createHash("sha256").update(this.transactionScopeHomeserver).update("\0").update(userId).update("\0").update(deviceId ?? "").update("\0").update(this.transactionScopeAccessTokenHash).digest("hex");
595
+ })();
596
+ this.transactionScopePromise = active;
597
+ try {
598
+ const resolved = await active;
599
+ this.transactionScopeId = resolved;
600
+ return resolved;
601
+ } finally {
602
+ if (this.transactionScopePromise === active) this.transactionScopePromise = null;
603
+ }
604
+ }
540
605
  async getJoinedRoomMembers(roomId) {
541
606
  const joined = (await this.client.getJoinedRoomMembers(roomId))?.joined;
542
607
  if (!joined || typeof joined !== "object") return [];
@@ -577,13 +642,56 @@ var MatrixClientCore = class extends MatrixClientBase {
577
642
  initial_state: initialState
578
643
  })).room_id;
579
644
  }
580
- async sendMessage(roomId, content) {
645
+ async sendMessage(roomId, content, transactionId, beforeWireDispatch) {
581
646
  return await this.runSerializedRoomSend(roomId, async () => {
582
- return (await this.client.sendMessage(roomId, content)).event_id;
647
+ return await this.withMessageWireDispatchGuard({
648
+ transactionId,
649
+ guard: beforeWireDispatch,
650
+ run: async () => {
651
+ if (transactionId) {
652
+ const room = this.client.getRoom(roomId);
653
+ const existing = room?.getEventForTxnId?.(transactionId);
654
+ if (existing) {
655
+ const existingId = existing.getId();
656
+ if (existing.status === EventStatus.SENT && existingId && !existingId.startsWith("~")) return existingId;
657
+ if (existing.status === EventStatus.NOT_SENT && room) {
658
+ await this.prepareRoomForMessageSend(roomId, existing.getContent());
659
+ return (await this.client.resendEvent(existing, room)).event_id;
660
+ }
661
+ throw new Error(`Matrix transaction ${transactionId} is already active with status ${existing.status ?? "unknown"}`);
662
+ }
663
+ }
664
+ await this.prepareRoomForMessageSend(roomId, content);
665
+ return (await this.client.sendMessage(roomId, content, transactionId)).event_id;
666
+ }
667
+ });
583
668
  });
584
669
  }
670
+ async getMessageWireEventType(roomId) {
671
+ if (this.client.getRoom(roomId)?.hasEncryptionStateEvent() === true) return "m.room.encrypted";
672
+ const crypto = this.client.getCrypto();
673
+ if (crypto && await crypto.isEncryptionEnabledInRoom(roomId)) return "m.room.encrypted";
674
+ try {
675
+ await this.getRoomStateEvent(roomId, "m.room.encryption", "");
676
+ return "m.room.encrypted";
677
+ } catch (error) {
678
+ if (error instanceof MatrixError && error.httpStatus === 404 && error.errcode === "M_NOT_FOUND") return "m.room.message";
679
+ throw error;
680
+ }
681
+ }
682
+ async prepareRoomForMessageSend(roomId, content) {
683
+ if (await this.getMessageWireEventType(roomId) === "m.room.message") return "m.room.message";
684
+ const crypto = this.client.getCrypto();
685
+ if (!crypto) throw new Error("Encrypted Matrix room: enable encryption before sending messages");
686
+ const room = this.client.getRoom(roomId);
687
+ if (!room || !room.hasEncryptionStateEvent() && !await crypto.isEncryptionEnabledInRoom(roomId)) throw new Error("Encrypted Matrix room is not ready: wait for room sync before sending");
688
+ if (content && ((content.msgtype === MsgType.Image || content.msgtype === MsgType.Audio || content.msgtype === MsgType.Video || content.msgtype === MsgType.File) && typeof content.url === "string" || content.info && "thumbnail_url" in content.info && typeof content.info.thumbnail_url === "string")) throw new Error("Encrypted Matrix room contains unencrypted media; retry the send");
689
+ return "m.room.encrypted";
690
+ }
585
691
  async sendEvent(roomId, eventType, content) {
586
692
  return await this.runSerializedRoomSend(roomId, async () => {
693
+ if (eventType === EventType.RoomMessageEncrypted.toString() || eventType === EventType.RoomRedaction.toString()) throw new Error(eventType === EventType.RoomRedaction.toString() ? "Matrix redaction wire events must use redactEvent" : "Matrix encrypted wire events must be generated by the SDK");
694
+ if (eventType !== "m.reaction") await this.prepareRoomForMessageSend(roomId, content);
587
695
  return (await this.client.sendEvent(roomId, eventType, content)).event_id;
588
696
  });
589
697
  }
@@ -698,7 +806,7 @@ var MatrixClientCore = class extends MatrixClientBase {
698
806
  };
699
807
  //#endregion
700
808
  //#region extensions/matrix/src/matrix/sdk/client-verification.ts
701
- const normalizeOptionalString$1 = normalizeNullableString;
809
+ const normalizeNullableVerificationString = normalizeNullableString;
702
810
  var MatrixClientVerification = class extends MatrixClientCore {
703
811
  async getRoomKeyBackupStatus() {
704
812
  if (!this.encryptionEnabled) return {
@@ -733,7 +841,7 @@ var MatrixClientVerification = class extends MatrixClientCore {
733
841
  try {
734
842
  await crypto.loadSessionBackupPrivateKeyFromSecretStorage();
735
843
  } catch (err) {
736
- keyLoadError = formatMatrixErrorMessage(err);
844
+ keyLoadError = formatErrorMessage(err);
737
845
  }
738
846
  } else keyLoadError = "Matrix crypto backend does not support loading backup keys from secret storage";
739
847
  if (!keyLoadError) await this.enableTrustedRoomKeyBackupIfPossible(crypto);
@@ -830,7 +938,7 @@ var MatrixClientVerification = class extends MatrixClientCore {
830
938
  async resolveActiveRoomKeyBackupVersion(crypto) {
831
939
  if (typeof crypto.getActiveSessionBackupVersion !== "function") return null;
832
940
  const version = await crypto.getActiveSessionBackupVersion().catch(() => null);
833
- return normalizeOptionalString$1(version);
941
+ return normalizeNullableVerificationString(version);
834
942
  }
835
943
  async resolveCachedRoomKeyBackupDecryptionKey(crypto) {
836
944
  const read = Reflect.get(crypto, "getSessionBackupPrivateKey");
@@ -862,7 +970,7 @@ var MatrixClientVerification = class extends MatrixClientCore {
862
970
  let matchesDecryptionKey = null;
863
971
  if (typeof crypto.getKeyBackupInfo === "function") {
864
972
  const info = await crypto.getKeyBackupInfo().catch(() => null);
865
- serverVersion = normalizeOptionalString$1(info?.version) ?? serverVersion;
973
+ serverVersion = normalizeNullableVerificationString(info?.version) ?? serverVersion;
866
974
  if (info && typeof crypto.isKeyBackupTrusted === "function") {
867
975
  const trustInfo = await crypto.isKeyBackupTrusted(info).catch(() => null);
868
976
  trusted = typeof trustInfo?.trusted === "boolean" ? trustInfo.trusted : null;
@@ -883,7 +991,7 @@ var MatrixClientVerification = class extends MatrixClientCore {
883
991
  async resolveRoomKeyBackupVersion() {
884
992
  try {
885
993
  const response = await this.doRequest("GET", "/_matrix/client/v3/room_keys/version");
886
- return normalizeOptionalString$1(response.version);
994
+ return normalizeNullableVerificationString(response.version);
887
995
  } catch {
888
996
  return null;
889
997
  }
@@ -932,7 +1040,7 @@ var MatrixClient = class extends MatrixClientVerification {
932
1040
  keyId: stagedKeyId
933
1041
  });
934
1042
  } catch (err) {
935
- return await fail(formatMatrixErrorMessage(err));
1043
+ return await fail(formatErrorMessage(err));
936
1044
  }
937
1045
  const storedRecoveryKeyMatches = this.recoveryKeyStore.getRecoveryKeySummary()?.encodedPrivateKey?.trim() === trimmedRecoveryKey;
938
1046
  if (backupUsableBeforeStagedRecovery && storedRecoveryKeyMatches) {
@@ -1033,7 +1141,7 @@ var MatrixClient = class extends MatrixClientVerification {
1033
1141
  };
1034
1142
  } catch (err) {
1035
1143
  this.recoveryKeyStore.discardStagedRecoveryKey();
1036
- return await fail(formatMatrixErrorMessage(err));
1144
+ return await fail(formatErrorMessage(err));
1037
1145
  }
1038
1146
  }
1039
1147
  async restoreRoomKeyBackup(params = {}) {
@@ -1088,7 +1196,7 @@ var MatrixClient = class extends MatrixClientVerification {
1088
1196
  };
1089
1197
  } catch (err) {
1090
1198
  this.recoveryKeyStore.discardStagedRecoveryKey();
1091
- return await fail(formatMatrixErrorMessage(err));
1199
+ return await fail(formatErrorMessage(err));
1092
1200
  }
1093
1201
  }
1094
1202
  async resetRoomKeyBackup(options = {}) {
@@ -1143,7 +1251,7 @@ var MatrixClient = class extends MatrixClientVerification {
1143
1251
  backup
1144
1252
  };
1145
1253
  } catch (err) {
1146
- return await fail(formatMatrixErrorMessage(err));
1254
+ return await fail(formatErrorMessage(err));
1147
1255
  }
1148
1256
  }
1149
1257
  async getOwnCrossSigningPublicationStatus() {
@@ -1185,7 +1293,7 @@ var MatrixClient = class extends MatrixClientVerification {
1185
1293
  await this.ensureRoomKeyBackupEnabled(crypto);
1186
1294
  } catch (err) {
1187
1295
  this.recoveryKeyStore.discardStagedRecoveryKey();
1188
- bootstrapError = formatMatrixErrorMessage(err);
1296
+ bootstrapError = formatErrorMessage(err);
1189
1297
  }
1190
1298
  const verification = await this.getOwnDeviceVerificationStatus();
1191
1299
  const crossSigning = await this.getOwnCrossSigningPublicationStatus();
@@ -1249,8 +1357,9 @@ var MatrixClient = class extends MatrixClientVerification {
1249
1357
  emitter: this.emitter,
1250
1358
  emitMembershipForRoom: (room) => this.emitMembershipForRoom(room),
1251
1359
  getSelfUserId: () => this.client.getUserId() ?? this.selfUserId ?? "",
1252
- setCurrentSyncState: (state) => {
1360
+ setCurrentSyncState: (state, error) => {
1253
1361
  this.currentSyncState = state;
1362
+ this.currentSyncError = error;
1254
1363
  }
1255
1364
  });
1256
1365
  }
@@ -1,4 +1,4 @@
1
- import { t as getMatrixScopedEnvVarNames } from "./env-vars-B0NxQnPk.js";
1
+ import { t as getMatrixScopedEnvVarNames } from "./env-vars-dGqak9dN.js";
2
2
  import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
3
3
  import { collectSecretInputAssignment, createChannelSecretTargetRegistryEntries, getChannelSurface, hasConfiguredSecretInputValue, hasOwnProperty, normalizeSecretStringValue } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
4
4
  //#region extensions/matrix/src/secret-contract.ts
@@ -1,2 +1,2 @@
1
- import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries, t as channelSecrets } from "./secret-contract-M3hRmGO-.js";
1
+ import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries, t as channelSecrets } from "./secret-contract-CufozuyJ.js";
2
2
  export { channelSecrets, collectRuntimeConfigAssignments, secretTargetRegistryEntries };