@openclaw/matrix 2026.6.5-beta.2 → 2026.6.5-beta.5

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 (65) hide show
  1. package/dist/{account-selection-DEMtY2cn.js → account-selection-Bv_ZuOu4.js} +2 -3
  2. package/dist/api.js +5 -5
  3. package/dist/{approval-handler.runtime-DBUlR5vu.js → approval-handler.runtime-D88ERXxc.js} +4 -4
  4. package/dist/{approval-ids-BWuh0wZT.js → approval-ids-B2J320aL.js} +1 -1
  5. package/dist/{approval-reaction-auth-NgDjrK6V.js → approval-reaction-auth-ryklScll.js} +2 -2
  6. package/dist/{channel-6UUus7Ba.js → channel-DtT1oc4C.js} +13 -13
  7. package/dist/channel-plugin-api.js +1 -1
  8. package/dist/{channel.runtime-CPXd3XKs.js → channel.runtime-CoCkSJV6.js} +6 -6
  9. package/dist/{cli-CM0h-B_j.js → cli-BX7_GgmS.js} +10 -10
  10. package/dist/{cli-metadata-CW6xSM2K.js → cli-metadata-C9_um_Yj.js} +1 -1
  11. package/dist/cli-metadata.js +1 -1
  12. package/dist/{client-CdP9vWOu.js → client-CPfb6TMG.js} +2 -2
  13. package/dist/{client-bootstrap-D5vrHEms.js → client-bootstrap-Dj2242_Y.js} +1 -1
  14. package/dist/{client-DRRL7Zv5.js → client-dLfa0qNk.js} +2 -2
  15. package/dist/{config-schema-CVJYP50t.js → config-schema-NrB2XGxM.js} +1 -1
  16. package/dist/contract-api.js +4 -4
  17. package/dist/{create-client-B90Sb7LG.js → create-client-MnSzqELZ.js} +4 -4
  18. package/dist/{credentials-Bi0pTJDK.js → credentials-G8lNmiME.js} +1 -1
  19. package/dist/{credentials-read-DpxFOhx0.js → credentials-read-TzTOQPOM.js} +1 -1
  20. package/dist/{credentials-write.runtime-BB5QuM4Z.js → credentials-write.runtime-cZhhyGAZ.js} +1 -1
  21. package/dist/{crypto-runtime-DWVNNqa3.js → crypto-runtime-B4WWNpMk.js} +4 -174
  22. package/dist/crypto-state-store-DK2tcEyP.js +352 -0
  23. package/dist/{directory-live-5uWtLQ41.js → directory-live-C7aYHtRU.js} +2 -2
  24. package/dist/{doctor-BKjr6uua.js → doctor-BwpkOBwr.js} +5 -5
  25. package/dist/{doctor-contract-D9oKDvsJ.js → doctor-contract-Dq8OZWHF.js} +1 -1
  26. package/dist/doctor-contract-api.js +265 -2
  27. package/dist/{draft-stream-DZ2X1RHP.js → draft-stream-PqFfvyV9.js} +1 -1
  28. package/dist/{encryption-guidance-aEUzD940.js → encryption-guidance-D_KhjprO.js} +1 -1
  29. package/dist/file-sync-store-Ni-pkFde.js +402 -0
  30. package/dist/helper-api.js +1 -1
  31. package/dist/idb-persistence-BGY1CJ7J.js +229 -0
  32. package/dist/idb-persistence-lock-DAJ49nZX.js +32 -0
  33. package/dist/index.js +1 -1
  34. package/dist/{legacy-crypto-restore-CbVSppMd.js → legacy-crypto-restore-Bm6HmeN5.js} +36 -28
  35. package/dist/logger-D0GCSDQq.js +78 -0
  36. package/dist/{logging-Cm8vxO3E.js → logging-QH-48Gr6.js} +1 -1
  37. package/dist/{matrix-migration.runtime-RzIEp7RP.js → matrix-migration.runtime-dvxE3e5l.js} +24 -25
  38. package/dist/{media-text-DVhXN81h.js → media-text-D0uvrHo1.js} +1 -1
  39. package/dist/{messages-sk1eTx7H.js → messages-C00n-MG_.js} +3 -3
  40. package/dist/{monitor-DXW0sFfU.js → monitor-BWHn9jy2.js} +21 -19
  41. package/dist/plugin-entry.handlers.runtime.js +1 -1
  42. package/dist/probe.runtime-DcSBLSet.js +3 -0
  43. package/dist/{profile-update-rzynJvpi.js → profile-update-CWvjc5i_.js} +2 -2
  44. package/dist/{reaction-events-DRKzlo8q.js → reaction-events-CdkYjlyo.js} +1 -1
  45. package/dist/{recovery-key-store-D6RbiZMM.js → recovery-key-store-TSlOpcEG.js} +22 -53
  46. package/dist/{resolve-targets-CAwsoBQK.js → resolve-targets-0dT0vJZJ.js} +1 -1
  47. package/dist/{resolver.runtime-phS2hwm9.js → resolver.runtime-BD2ZRhKw.js} +1 -1
  48. package/dist/runtime-api.js +1 -1
  49. package/dist/runtime-heavy-api.js +1 -1
  50. package/dist/{sdk-BdCZ5WwA.js → sdk-CdMhAFz3.js} +9 -202
  51. package/dist/{send-DEgWxp1p.js → send-Bus9xhUh.js} +1 -1
  52. package/dist/{setup-bootstrap-B4xc58Ww.js → setup-bootstrap-C9tUX9Ty.js} +2 -2
  53. package/dist/{setup-core-DJosJdWt.js → setup-core-CUyFBi5x.js} +3 -3
  54. package/dist/setup-plugin-api.js +3 -3
  55. package/dist/{setup-surface-CqxGV1WL.js → setup-surface-BRlTR6to.js} +5 -5
  56. package/dist/{shared-BbT5LdPp.js → shared-Bk7pOHMb.js} +8 -84
  57. package/dist/{startup-verification-D1p_LRmg.js → startup-verification-BoDITB_u.js} +2 -2
  58. package/dist/{storage-DSVcH_zM.js → storage-C10h2piS.js} +122 -26
  59. package/dist/{thread-bindings-gLQYbsB9.js → thread-bindings-CnviJ9Ff.js} +4 -23
  60. package/dist/{tool-actions.runtime-o06m9bgN.js → tool-actions.runtime-dStqVKMT.js} +6 -6
  61. package/dist/{verification-BiA5IWPK.js → verification-jZ1KWtb5.js} +2 -2
  62. package/npm-shrinkwrap.json +3 -3
  63. package/package.json +4 -4
  64. package/dist/probe.runtime-BO0mNIe8.js +0 -3
  65. package/dist/record-shared-CvzjvHRn.js +0 -2
@@ -0,0 +1,402 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
+ import { o as isRecord } from "./account-selection-Bv_ZuOu4.js";
3
+ import { t as getMatrixRuntime } from "./runtime-6S3DNFNv.js";
4
+ import { O as resolveMatrixSqliteStateEnv } from "./crypto-state-store-DK2tcEyP.js";
5
+ import { t as claimCurrentTokenStorageState } from "./storage-C10h2piS.js";
6
+ import { t as createAsyncLock } from "./async-lock-BcLS4KOc.js";
7
+ import { n as LogService } from "./logger-D0GCSDQq.js";
8
+ import path from "node:path";
9
+ import { createHash, randomUUID } from "node:crypto";
10
+ import fs from "node:fs/promises";
11
+ import { Category, MemoryStore, SyncAccumulator } from "matrix-js-sdk/lib/matrix.js";
12
+ //#region extensions/matrix/src/matrix/client/file-sync-store.ts
13
+ var file_sync_store_exports = /* @__PURE__ */ __exportAll({
14
+ SqliteBackedMatrixSyncStore: () => SqliteBackedMatrixSyncStore,
15
+ hasMatrixSyncCacheStateInStore: () => hasMatrixSyncCacheStateInStore,
16
+ openMatrixSyncCacheStoreOptions: () => openMatrixSyncCacheStoreOptions,
17
+ readLegacyMatrixSyncCacheState: () => readLegacyMatrixSyncCacheState,
18
+ writeMatrixSyncCacheStateToStore: () => writeMatrixSyncCacheStateToStore
19
+ });
20
+ const STORE_VERSION = 1;
21
+ const PERSIST_DEBOUNCE_MS = 250;
22
+ const SYNC_CACHE_NAMESPACE = "sync-cache";
23
+ const SYNC_CACHE_MAX_ENTRIES = 2e4;
24
+ const SYNC_CACHE_MAX_CHUNKS = Math.floor((SYNC_CACHE_MAX_ENTRIES - 1) / 2);
25
+ const SYNC_CACHE_STATE_KEY = "current";
26
+ const SYNC_CACHE_CHUNK_BYTES = 24e3;
27
+ function normalizeRoomsData(value) {
28
+ if (!isRecord(value)) return null;
29
+ return {
30
+ [Category.Join]: isRecord(value[Category.Join]) ? value[Category.Join] : {},
31
+ [Category.Invite]: isRecord(value[Category.Invite]) ? value[Category.Invite] : {},
32
+ [Category.Leave]: isRecord(value[Category.Leave]) ? value[Category.Leave] : {},
33
+ [Category.Knock]: isRecord(value[Category.Knock]) ? value[Category.Knock] : {}
34
+ };
35
+ }
36
+ function toPersistedSyncData(value) {
37
+ if (!isRecord(value)) return null;
38
+ if (typeof value.nextBatch === "string" && value.nextBatch.trim()) {
39
+ const roomsData = normalizeRoomsData(value.roomsData);
40
+ if (!Array.isArray(value.accountData) || !roomsData) return null;
41
+ return {
42
+ nextBatch: value.nextBatch,
43
+ accountData: value.accountData,
44
+ roomsData
45
+ };
46
+ }
47
+ if (typeof value.next_batch === "string" && value.next_batch.trim()) {
48
+ const roomsData = normalizeRoomsData(value.rooms);
49
+ if (!roomsData) return null;
50
+ return {
51
+ nextBatch: value.next_batch,
52
+ accountData: isRecord(value.account_data) && Array.isArray(value.account_data.events) ? value.account_data.events : [],
53
+ roomsData
54
+ };
55
+ }
56
+ return null;
57
+ }
58
+ function normalizePersistedStore(value) {
59
+ if (!isRecord(value) || value.version !== STORE_VERSION) return null;
60
+ return {
61
+ version: STORE_VERSION,
62
+ savedSync: toPersistedSyncData(value.savedSync),
63
+ clientOptions: isRecord(value.clientOptions) ? value.clientOptions : void 0,
64
+ cleanShutdown: value.cleanShutdown === true
65
+ };
66
+ }
67
+ function normalizeLegacyPersistedStore(value) {
68
+ const persisted = normalizePersistedStore(value);
69
+ if (persisted) return persisted;
70
+ return {
71
+ version: STORE_VERSION,
72
+ savedSync: toPersistedSyncData(value),
73
+ cleanShutdown: false
74
+ };
75
+ }
76
+ function cloneJson(value) {
77
+ return structuredClone(value);
78
+ }
79
+ function syncDataToSyncResponse(syncData) {
80
+ return {
81
+ next_batch: syncData.nextBatch,
82
+ rooms: syncData.roomsData,
83
+ account_data: { events: syncData.accountData }
84
+ };
85
+ }
86
+ var SqliteBackedMatrixSyncStore = class extends MemoryStore {
87
+ constructor(storageRootDir) {
88
+ super();
89
+ this.storageRootDir = storageRootDir;
90
+ this.persistLock = createAsyncLock();
91
+ this.accumulator = new SyncAccumulator();
92
+ this.savedSync = null;
93
+ this.cleanShutdown = false;
94
+ this.dirty = false;
95
+ this.persistTimer = null;
96
+ this.persistPromise = null;
97
+ this.stateKey = resolveSyncCacheStateKey(storageRootDir);
98
+ let restoredSavedSync = null;
99
+ let restoredClientOptions;
100
+ let restoredCleanShutdown = false;
101
+ let syncCacheStore = createNoopMatrixSyncCacheStore();
102
+ let syncCacheStoreUnavailableError;
103
+ try {
104
+ syncCacheStore = openMatrixSyncCacheStore(storageRootDir);
105
+ const persisted = readPersistedStoreFromSyncStore(syncCacheStore, this.stateKey);
106
+ if (persisted) {
107
+ restoredSavedSync = persisted.savedSync;
108
+ restoredClientOptions = persisted.clientOptions;
109
+ restoredCleanShutdown = persisted.cleanShutdown === true;
110
+ }
111
+ } catch (err) {
112
+ syncCacheStoreUnavailableError = err;
113
+ LogService.warn("MatrixSyncCacheStore", "Failed to load Matrix sync cache:", err);
114
+ }
115
+ this.store = syncCacheStore;
116
+ this.storeUnavailableError = syncCacheStoreUnavailableError;
117
+ this.savedSync = restoredSavedSync;
118
+ this.savedClientOptions = restoredClientOptions;
119
+ this.hadSavedSyncOnLoad = restoredSavedSync !== null;
120
+ this.hadCleanShutdownOnLoad = this.hadSavedSyncOnLoad && restoredCleanShutdown;
121
+ this.cleanShutdown = this.hadCleanShutdownOnLoad;
122
+ if (this.savedSync) {
123
+ this.accumulator.accumulate(syncDataToSyncResponse(this.savedSync), true);
124
+ super.setSyncToken(this.savedSync.nextBatch);
125
+ }
126
+ if (this.savedClientOptions) super.storeClientOptions(this.savedClientOptions);
127
+ }
128
+ hasSavedSync() {
129
+ return this.hadSavedSyncOnLoad;
130
+ }
131
+ hasSavedSyncFromCleanShutdown() {
132
+ return this.hadCleanShutdownOnLoad;
133
+ }
134
+ getSavedSync() {
135
+ return Promise.resolve(this.savedSync ? cloneJson(this.savedSync) : null);
136
+ }
137
+ getSavedSyncToken() {
138
+ return Promise.resolve(this.savedSync?.nextBatch ?? null);
139
+ }
140
+ setSyncData(syncData) {
141
+ this.accumulator.accumulate(syncData);
142
+ this.savedSync = this.accumulator.getJSON();
143
+ this.markDirtyAndSchedulePersist();
144
+ return Promise.resolve();
145
+ }
146
+ getClientOptions() {
147
+ return Promise.resolve(this.savedClientOptions ? cloneJson(this.savedClientOptions) : void 0);
148
+ }
149
+ storeClientOptions(options) {
150
+ this.savedClientOptions = cloneJson(options);
151
+ super.storeClientOptions(options);
152
+ this.markDirtyAndSchedulePersist();
153
+ return Promise.resolve();
154
+ }
155
+ save(force = false) {
156
+ if (force) return this.flush();
157
+ return Promise.resolve();
158
+ }
159
+ wantsSave() {
160
+ return false;
161
+ }
162
+ async deleteAllData() {
163
+ this.assertStoreAvailable();
164
+ if (this.persistTimer) {
165
+ clearTimeout(this.persistTimer);
166
+ this.persistTimer = null;
167
+ }
168
+ this.dirty = false;
169
+ await this.persistPromise?.catch(() => void 0);
170
+ await super.deleteAllData();
171
+ this.savedSync = null;
172
+ this.savedClientOptions = void 0;
173
+ this.cleanShutdown = false;
174
+ this.store.delete(metaKey(this.stateKey));
175
+ for (const row of this.store.entries()) if (row.key.startsWith(chunkKeyPrefix(this.stateKey))) this.store.delete(row.key);
176
+ await fs.rm(resolveLegacySyncCachePath(this.storageRootDir), { force: true }).catch(() => void 0);
177
+ }
178
+ markCleanShutdown() {
179
+ this.cleanShutdown = true;
180
+ this.dirty = true;
181
+ }
182
+ async flush() {
183
+ if (this.persistTimer) {
184
+ clearTimeout(this.persistTimer);
185
+ this.persistTimer = null;
186
+ }
187
+ while (this.dirty || this.persistPromise) {
188
+ if (this.dirty && !this.persistPromise) this.persistPromise = this.persist().finally(() => {
189
+ this.persistPromise = null;
190
+ });
191
+ await this.persistPromise;
192
+ }
193
+ }
194
+ markDirtyAndSchedulePersist() {
195
+ this.cleanShutdown = false;
196
+ this.dirty = true;
197
+ if (this.persistTimer) return;
198
+ this.persistTimer = setTimeout(() => {
199
+ this.persistTimer = null;
200
+ this.flush().catch((err) => {
201
+ LogService.warn("MatrixSyncCacheStore", "Failed to persist Matrix sync store:", err);
202
+ });
203
+ }, PERSIST_DEBOUNCE_MS);
204
+ this.persistTimer.unref?.();
205
+ }
206
+ async persist() {
207
+ this.assertStoreAvailable();
208
+ this.dirty = false;
209
+ const payload = {
210
+ version: STORE_VERSION,
211
+ savedSync: this.savedSync ? cloneJson(this.savedSync) : null,
212
+ cleanShutdown: this.cleanShutdown,
213
+ ...this.savedClientOptions ? { clientOptions: cloneJson(this.savedClientOptions) } : {}
214
+ };
215
+ try {
216
+ await this.persistLock(async () => {
217
+ this.writePersistedStore(payload);
218
+ claimCurrentTokenStorageState({ rootDir: this.storageRootDir });
219
+ });
220
+ } catch (err) {
221
+ this.dirty = true;
222
+ throw err;
223
+ }
224
+ }
225
+ writePersistedStore(payload) {
226
+ const rows = buildSyncCacheRows(this.stateKey, payload);
227
+ for (const row of rows.chunks) this.store.register(row.key, row.value);
228
+ this.store.register(rows.meta.key, rows.meta.value);
229
+ for (const row of this.store.entries()) if (row.key.startsWith(chunkKeyPrefix(this.stateKey)) && !rows.nextChunkKeys.has(row.key)) this.store.delete(row.key);
230
+ }
231
+ assertStoreAvailable() {
232
+ if (this.storeUnavailableError == null) return;
233
+ throw new Error("Matrix sync cache SQLite store is unavailable; cannot persist sync state", { cause: this.storeUnavailableError });
234
+ }
235
+ };
236
+ function createNoopMatrixSyncCacheStore() {
237
+ return {
238
+ register: () => {},
239
+ registerIfAbsent: () => false,
240
+ lookup: () => void 0,
241
+ consume: () => void 0,
242
+ delete: () => false,
243
+ entries: () => [],
244
+ clear: () => {}
245
+ };
246
+ }
247
+ function readPersistedStoreFromSyncStore(store, stateKey) {
248
+ const meta = store.lookup(metaKey(stateKey));
249
+ if (!isSyncCacheMeta(meta)) return null;
250
+ const chunks = [];
251
+ for (let index = 0; index < meta.chunkCount; index += 1) {
252
+ const chunk = store.lookup(chunkKey(stateKey, meta.generation, index));
253
+ if (!isSyncCacheChunk(chunk) || chunk.index !== index) return normalizePersistedStore({
254
+ version: STORE_VERSION,
255
+ savedSync: null,
256
+ clientOptions: meta.clientOptions,
257
+ cleanShutdown: false
258
+ });
259
+ chunks.push(chunk.data);
260
+ }
261
+ let savedSync = null;
262
+ if (chunks.length > 0) {
263
+ const syncJson = chunks.join("");
264
+ if (meta.syncDigest !== digestText(syncJson)) return normalizePersistedStore({
265
+ version: STORE_VERSION,
266
+ savedSync: null,
267
+ clientOptions: meta.clientOptions,
268
+ cleanShutdown: false
269
+ });
270
+ try {
271
+ savedSync = toPersistedSyncData(JSON.parse(syncJson));
272
+ } catch {
273
+ savedSync = null;
274
+ }
275
+ }
276
+ return normalizePersistedStore({
277
+ version: STORE_VERSION,
278
+ savedSync,
279
+ clientOptions: meta.clientOptions,
280
+ cleanShutdown: meta.cleanShutdown
281
+ });
282
+ }
283
+ function openMatrixSyncCacheStore(storageRootDir) {
284
+ return getMatrixRuntime().state.openSyncKeyedStore(openMatrixSyncCacheStoreOptions(storageRootDir));
285
+ }
286
+ function resolveSyncCacheStateKey(_storageRootDir) {
287
+ return SYNC_CACHE_STATE_KEY;
288
+ }
289
+ function metaKey(stateKey) {
290
+ return `${stateKey}:meta`;
291
+ }
292
+ function chunkKeyPrefix(stateKey) {
293
+ return `${stateKey}:sync:`;
294
+ }
295
+ function chunkKey(stateKey, generation, index) {
296
+ return `${chunkKeyPrefix(stateKey)}${generation}:${index}`;
297
+ }
298
+ function resolveLegacySyncCachePath(storageRootDir) {
299
+ return path.join(storageRootDir, "bot-storage.json");
300
+ }
301
+ function digestText(value) {
302
+ return createHash("sha256").update(value, "utf8").digest("hex");
303
+ }
304
+ function isSyncCacheMeta(value) {
305
+ return isRecord(value) && value.kind === "meta" && value.version === STORE_VERSION && typeof value.generation === "string" && value.generation.trim() !== "" && typeof value.chunkCount === "number" && Number.isSafeInteger(value.chunkCount) && value.chunkCount >= 0 && value.chunkCount <= SYNC_CACHE_MAX_CHUNKS;
306
+ }
307
+ function isSyncCacheChunk(value) {
308
+ return isRecord(value) && value.kind === "sync-chunk" && typeof value.index === "number" && Number.isSafeInteger(value.index) && value.index >= 0 && typeof value.data === "string";
309
+ }
310
+ function chunkSyncCacheJson(value) {
311
+ const chunks = [];
312
+ const pushChunk = (chunk) => {
313
+ if (chunks.length >= SYNC_CACHE_MAX_CHUNKS) throw new Error("Matrix sync cache exceeds SQLite chunk limit");
314
+ chunks.push(chunk);
315
+ };
316
+ let current = "";
317
+ let currentBytes = 0;
318
+ for (const char of value) {
319
+ const charBytes = Buffer.byteLength(char, "utf8");
320
+ if (current && currentBytes + charBytes > SYNC_CACHE_CHUNK_BYTES) {
321
+ pushChunk(current);
322
+ current = "";
323
+ currentBytes = 0;
324
+ }
325
+ current += char;
326
+ currentBytes += charBytes;
327
+ }
328
+ if (current) pushChunk(current);
329
+ return chunks;
330
+ }
331
+ function buildSyncCacheRows(stateKey, payload) {
332
+ const generation = randomUUID().replaceAll("-", "");
333
+ const syncJson = payload.savedSync ? JSON.stringify(payload.savedSync) : "";
334
+ const chunks = (syncJson ? chunkSyncCacheJson(syncJson) : []).map((data, index) => ({
335
+ key: chunkKey(stateKey, generation, index),
336
+ value: {
337
+ kind: "sync-chunk",
338
+ index,
339
+ data
340
+ }
341
+ }));
342
+ return {
343
+ chunks,
344
+ nextChunkKeys: new Set(chunks.map((chunk) => chunk.key)),
345
+ meta: {
346
+ key: metaKey(stateKey),
347
+ value: {
348
+ kind: "meta",
349
+ version: STORE_VERSION,
350
+ generation,
351
+ chunkCount: chunks.length,
352
+ ...syncJson ? { syncDigest: digestText(syncJson) } : {},
353
+ ...payload.clientOptions ? { clientOptions: payload.clientOptions } : {},
354
+ cleanShutdown: payload.cleanShutdown === true
355
+ }
356
+ }
357
+ };
358
+ }
359
+ async function readLegacyMatrixSyncCacheState(storageRootDir) {
360
+ try {
361
+ const raw = await fs.readFile(resolveLegacySyncCachePath(storageRootDir), "utf8");
362
+ const persisted = normalizeLegacyPersistedStore(JSON.parse(raw));
363
+ if (!persisted?.savedSync && !persisted?.clientOptions) return null;
364
+ return persisted;
365
+ } catch {
366
+ return null;
367
+ }
368
+ }
369
+ async function hasMatrixSyncCacheStateInStore(params) {
370
+ const stateKey = resolveSyncCacheStateKey(params.storageRootDir);
371
+ const meta = await params.store.lookup(metaKey(stateKey));
372
+ if (!isSyncCacheMeta(meta) || meta.chunkCount <= 0) return false;
373
+ const chunks = [];
374
+ for (let index = 0; index < meta.chunkCount; index += 1) {
375
+ const chunk = await params.store.lookup(chunkKey(stateKey, meta.generation, index));
376
+ if (!isSyncCacheChunk(chunk) || chunk.index !== index) return false;
377
+ chunks.push(chunk.data);
378
+ }
379
+ const syncJson = chunks.join("");
380
+ if (meta.syncDigest !== digestText(syncJson)) return false;
381
+ try {
382
+ return toPersistedSyncData(JSON.parse(syncJson)) !== null;
383
+ } catch {
384
+ return false;
385
+ }
386
+ }
387
+ async function writeMatrixSyncCacheStateToStore(params) {
388
+ const stateKey = resolveSyncCacheStateKey(params.storageRootDir);
389
+ const rows = buildSyncCacheRows(stateKey, params.payload);
390
+ for (const row of rows.chunks) await params.store.register(row.key, row.value);
391
+ await params.store.register(rows.meta.key, rows.meta.value);
392
+ for (const row of await params.store.entries()) if (row.key.startsWith(chunkKeyPrefix(stateKey)) && !rows.nextChunkKeys.has(row.key)) await params.store.delete(row.key);
393
+ }
394
+ function openMatrixSyncCacheStoreOptions(storageRootDir) {
395
+ return {
396
+ namespace: SYNC_CACHE_NAMESPACE,
397
+ maxEntries: SYNC_CACHE_MAX_ENTRIES,
398
+ env: resolveMatrixSqliteStateEnv({ stateDir: storageRootDir })
399
+ };
400
+ }
401
+ //#endregion
402
+ export { readLegacyMatrixSyncCacheState as a, openMatrixSyncCacheStoreOptions as i, file_sync_store_exports as n, writeMatrixSyncCacheStateToStore as o, hasMatrixSyncCacheStateInStore as r, SqliteBackedMatrixSyncStore as t };
@@ -1,4 +1,4 @@
1
- import { a as resolveMatrixDefaultOrOnlyAccountId, i as resolveMatrixChannelConfig, n as requiresExplicitMatrixDefaultAccount, r as resolveConfiguredMatrixAccountIds, t as findMatrixAccountEntry } from "./account-selection-DEMtY2cn.js";
1
+ import { a as resolveMatrixDefaultOrOnlyAccountId, i as resolveMatrixChannelConfig, n as requiresExplicitMatrixDefaultAccount, r as resolveConfiguredMatrixAccountIds, t as findMatrixAccountEntry } from "./account-selection-Bv_ZuOu4.js";
2
2
  import { n as listMatrixEnvAccountIds, r as resolveMatrixEnvAccountToken, t as getMatrixScopedEnvVarNames } from "./env-vars-KzaYveuy.js";
3
3
  import { a as resolveMatrixCredentialsPath, c as resolveMatrixLegacyFlatStoreRoot, i as resolveMatrixCredentialsFilename, l as sanitizeMatrixPathSegment, n as resolveMatrixAccountStorageRoot, o as resolveMatrixHomeserverKey, r as resolveMatrixCredentialsDir, s as resolveMatrixLegacyFlatStoragePaths, t as hashMatrixAccessToken } from "./storage-paths-BWo_ZEMC.js";
4
4
  export { findMatrixAccountEntry, getMatrixScopedEnvVarNames, hashMatrixAccessToken, listMatrixEnvAccountIds, requiresExplicitMatrixDefaultAccount, resolveConfiguredMatrixAccountIds, resolveMatrixAccountStorageRoot, resolveMatrixChannelConfig, resolveMatrixCredentialsDir, resolveMatrixCredentialsFilename, resolveMatrixCredentialsPath, resolveMatrixDefaultOrOnlyAccountId, resolveMatrixEnvAccountToken, resolveMatrixHomeserverKey, resolveMatrixLegacyFlatStoragePaths, resolveMatrixLegacyFlatStoreRoot, sanitizeMatrixPathSegment };
@@ -0,0 +1,229 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
+ import { g as readMatrixIdbSnapshotJson, t as MATRIX_IDB_SNAPSHOT_FILENAME, x as writeMatrixIdbSnapshotJson } from "./crypto-state-store-DK2tcEyP.js";
3
+ import { n as LogService } from "./logger-D0GCSDQq.js";
4
+ import { n as MATRIX_IDB_SNAPSHOT_LOCK_OPTIONS } from "./idb-persistence-lock-DAJ49nZX.js";
5
+ import fs from "node:fs";
6
+ import path from "node:path";
7
+ import { indexedDB } from "fake-indexeddb";
8
+ import { withFileLock } from "openclaw/plugin-sdk/file-lock";
9
+ //#region extensions/matrix/src/matrix/sdk/idb-persistence.ts
10
+ var idb_persistence_exports = /* @__PURE__ */ __exportAll({
11
+ persistIdbToDisk: () => persistIdbToDisk,
12
+ readLegacyMatrixIdbSnapshotState: () => readLegacyMatrixIdbSnapshotState,
13
+ restoreIdbFromDisk: () => restoreIdbFromDisk
14
+ });
15
+ function isValidIdbIndexSnapshot(value) {
16
+ if (!value || typeof value !== "object") return false;
17
+ const candidate = value;
18
+ return typeof candidate.name === "string" && (typeof candidate.keyPath === "string" || Array.isArray(candidate.keyPath) && candidate.keyPath.every((entry) => typeof entry === "string")) && typeof candidate.multiEntry === "boolean" && typeof candidate.unique === "boolean";
19
+ }
20
+ function isValidIdbRecordSnapshot(value) {
21
+ if (!value || typeof value !== "object") return false;
22
+ return "key" in value && "value" in value;
23
+ }
24
+ function isValidIdbStoreSnapshot(value) {
25
+ if (!value || typeof value !== "object") return false;
26
+ const candidate = value;
27
+ const validKeyPath = candidate.keyPath === null || typeof candidate.keyPath === "string" || Array.isArray(candidate.keyPath) && candidate.keyPath.every((entry) => typeof entry === "string");
28
+ return typeof candidate.name === "string" && validKeyPath && typeof candidate.autoIncrement === "boolean" && Array.isArray(candidate.indexes) && candidate.indexes.every((entry) => isValidIdbIndexSnapshot(entry)) && Array.isArray(candidate.records) && candidate.records.every((entry) => isValidIdbRecordSnapshot(entry));
29
+ }
30
+ function isValidIdbDatabaseSnapshot(value) {
31
+ if (!value || typeof value !== "object") return false;
32
+ const candidate = value;
33
+ return typeof candidate.name === "string" && typeof candidate.version === "number" && Number.isFinite(candidate.version) && candidate.version > 0 && Array.isArray(candidate.stores) && candidate.stores.every((entry) => isValidIdbStoreSnapshot(entry));
34
+ }
35
+ function parseSnapshotPayload(data) {
36
+ const parsed = JSON.parse(data);
37
+ if (!Array.isArray(parsed) || parsed.length === 0) return null;
38
+ if (!parsed.every((entry) => isValidIdbDatabaseSnapshot(entry))) throw new Error("Malformed IndexedDB snapshot payload");
39
+ return parsed;
40
+ }
41
+ function idbReq(req) {
42
+ return new Promise((resolve, reject) => {
43
+ req.addEventListener("success", () => resolve(req.result), { once: true });
44
+ req.addEventListener("error", () => reject(toLintErrorObject(req.error, "Non-Error rejection")), { once: true });
45
+ });
46
+ }
47
+ async function dumpIndexedDatabases(databasePrefix) {
48
+ const idb = indexedDB;
49
+ const dbList = await idb.databases();
50
+ const snapshot = [];
51
+ const expectedPrefix = databasePrefix ? `${databasePrefix}::` : null;
52
+ for (const { name, version } of dbList) {
53
+ if (!name || !version) continue;
54
+ if (expectedPrefix && !name.startsWith(expectedPrefix)) continue;
55
+ const db = await new Promise((resolve, reject) => {
56
+ const r = idb.open(name, version);
57
+ r.addEventListener("success", () => resolve(r.result), { once: true });
58
+ r.addEventListener("error", () => reject(toLintErrorObject(r.error, "Non-Error rejection")), { once: true });
59
+ });
60
+ const stores = [];
61
+ for (const storeName of db.objectStoreNames) {
62
+ const store = db.transaction(storeName, "readonly").objectStore(storeName);
63
+ const storeInfo = {
64
+ name: storeName,
65
+ keyPath: store.keyPath,
66
+ autoIncrement: store.autoIncrement,
67
+ indexes: [],
68
+ records: []
69
+ };
70
+ for (const idxName of store.indexNames) {
71
+ const idx = store.index(idxName);
72
+ storeInfo.indexes.push({
73
+ name: idxName,
74
+ keyPath: idx.keyPath,
75
+ multiEntry: idx.multiEntry,
76
+ unique: idx.unique
77
+ });
78
+ }
79
+ const keys = await idbReq(store.getAllKeys());
80
+ const values = await idbReq(store.getAll());
81
+ storeInfo.records = keys.map((k, i) => ({
82
+ key: k,
83
+ value: values[i]
84
+ }));
85
+ stores.push(storeInfo);
86
+ }
87
+ snapshot.push({
88
+ name,
89
+ version,
90
+ stores
91
+ });
92
+ db.close();
93
+ }
94
+ return snapshot;
95
+ }
96
+ async function restoreIndexedDatabases(snapshot) {
97
+ const idb = indexedDB;
98
+ for (const dbSnap of snapshot) await new Promise((resolve, reject) => {
99
+ const r = idb.open(dbSnap.name, dbSnap.version);
100
+ r.addEventListener("upgradeneeded", () => {
101
+ const db = r.result;
102
+ for (const storeSnap of dbSnap.stores) {
103
+ const opts = {};
104
+ if (storeSnap.keyPath !== null) opts.keyPath = storeSnap.keyPath;
105
+ if (storeSnap.autoIncrement) opts.autoIncrement = true;
106
+ const store = db.createObjectStore(storeSnap.name, opts);
107
+ for (const idx of storeSnap.indexes) store.createIndex(idx.name, idx.keyPath, {
108
+ unique: idx.unique,
109
+ multiEntry: idx.multiEntry
110
+ });
111
+ }
112
+ });
113
+ r.addEventListener("success", () => {
114
+ (async () => {
115
+ const db = r.result;
116
+ for (const storeSnap of dbSnap.stores) {
117
+ if (storeSnap.records.length === 0) continue;
118
+ const tx = db.transaction(storeSnap.name, "readwrite");
119
+ const store = tx.objectStore(storeSnap.name);
120
+ for (const rec of storeSnap.records) if (storeSnap.keyPath !== null) store.put(rec.value);
121
+ else store.put(rec.value, rec.key);
122
+ await new Promise((res) => {
123
+ tx.addEventListener("complete", () => res(), { once: true });
124
+ });
125
+ }
126
+ db.close();
127
+ resolve();
128
+ })().catch(reject);
129
+ }, { once: true });
130
+ r.addEventListener("error", () => reject(toLintErrorObject(r.error, "Non-Error rejection")), { once: true });
131
+ });
132
+ }
133
+ function resolveDefaultIdbSnapshotPath() {
134
+ const stateDir = process.env.OPENCLAW_STATE_DIR || path.join(process.env.HOME || "/tmp", ".openclaw");
135
+ return path.join(stateDir, "matrix", "crypto-idb-snapshot.json");
136
+ }
137
+ async function restoreIdbFromDisk(snapshotPath) {
138
+ const candidatePaths = snapshotPath ? [snapshotPath] : [resolveDefaultIdbSnapshotPath()];
139
+ for (const resolvedPath of candidatePaths) {
140
+ const storageRootDir = path.dirname(resolvedPath);
141
+ try {
142
+ if (await withFileLock(resolvedPath, MATRIX_IDB_SNAPSHOT_LOCK_OPTIONS, async () => {
143
+ try {
144
+ const storedSnapshotJson = readMatrixIdbSnapshotJson(storageRootDir);
145
+ if (storedSnapshotJson) {
146
+ const snapshot = parseSnapshotPayload(storedSnapshotJson);
147
+ if (snapshot) {
148
+ await restoreIndexedDatabases(snapshot);
149
+ LogService.info("IdbPersistence", `Restored ${snapshot.length} IndexedDB database(s) from Matrix SQLite state`);
150
+ return true;
151
+ }
152
+ }
153
+ } catch (err) {
154
+ LogService.warn("IdbPersistence", "Failed to restore IndexedDB snapshot from SQLite:", err);
155
+ }
156
+ if (!fs.existsSync(resolvedPath)) return false;
157
+ const data = fs.readFileSync(resolvedPath, "utf8");
158
+ const snapshot = parseSnapshotPayload(data);
159
+ if (!snapshot) return false;
160
+ let migratedToSqlite = false;
161
+ try {
162
+ writeMatrixIdbSnapshotJson({
163
+ storageRootDir,
164
+ snapshotJson: data,
165
+ databaseCount: snapshot.length
166
+ });
167
+ archiveLegacyIdbSnapshotFile(resolvedPath);
168
+ migratedToSqlite = true;
169
+ } catch (err) {
170
+ LogService.warn("IdbPersistence", `Failed to migrate IndexedDB snapshot to SQLite from ${resolvedPath}:`, err);
171
+ }
172
+ await restoreIndexedDatabases(snapshot);
173
+ LogService.info("IdbPersistence", migratedToSqlite ? `Migrated and restored ${snapshot.length} IndexedDB database(s) from ${resolvedPath}` : `Restored ${snapshot.length} IndexedDB database(s) from legacy snapshot ${resolvedPath}`);
174
+ return true;
175
+ })) return true;
176
+ } catch (err) {
177
+ LogService.warn("IdbPersistence", `Failed to restore IndexedDB snapshot from ${resolvedPath}:`, err);
178
+ continue;
179
+ }
180
+ }
181
+ return false;
182
+ }
183
+ async function persistIdbToDisk(params) {
184
+ const snapshotPath = params?.snapshotPath ?? resolveDefaultIdbSnapshotPath();
185
+ try {
186
+ fs.mkdirSync(path.dirname(snapshotPath), { recursive: true });
187
+ const persistedCount = await withFileLock(snapshotPath, MATRIX_IDB_SNAPSHOT_LOCK_OPTIONS, async () => {
188
+ const snapshot = await dumpIndexedDatabases(params?.databasePrefix);
189
+ if (snapshot.length === 0) return 0;
190
+ writeMatrixIdbSnapshotJson({
191
+ storageRootDir: path.dirname(snapshotPath),
192
+ snapshotJson: JSON.stringify(snapshot),
193
+ databaseCount: snapshot.length
194
+ });
195
+ archiveLegacyIdbSnapshotFile(snapshotPath);
196
+ return snapshot.length;
197
+ });
198
+ if (persistedCount === 0) return;
199
+ LogService.debug("IdbPersistence", `Persisted ${persistedCount} IndexedDB database(s) to Matrix SQLite state`);
200
+ } catch (err) {
201
+ LogService.warn("IdbPersistence", "Failed to persist IndexedDB snapshot:", err);
202
+ }
203
+ }
204
+ async function readLegacyMatrixIdbSnapshotState(storageRootDir) {
205
+ const snapshotPath = path.join(storageRootDir, MATRIX_IDB_SNAPSHOT_FILENAME);
206
+ if (!fs.existsSync(snapshotPath)) return null;
207
+ try {
208
+ return await withFileLock(snapshotPath, MATRIX_IDB_SNAPSHOT_LOCK_OPTIONS, async () => {
209
+ return parseSnapshotPayload(fs.readFileSync(snapshotPath, "utf8"));
210
+ });
211
+ } catch {
212
+ return null;
213
+ }
214
+ }
215
+ function archiveLegacyIdbSnapshotFile(snapshotPath) {
216
+ if (!fs.existsSync(snapshotPath)) return;
217
+ const archivedPath = `${snapshotPath}.migrated`;
218
+ if (fs.existsSync(archivedPath)) return;
219
+ fs.renameSync(snapshotPath, archivedPath);
220
+ }
221
+ function toLintErrorObject(value, fallbackMessage) {
222
+ if (value instanceof Error) return value;
223
+ if (typeof value === "string") return new Error(value);
224
+ const error = new Error(fallbackMessage, { cause: value });
225
+ if (typeof value === "object" && value !== null || typeof value === "function") Object.assign(error, value);
226
+ return error;
227
+ }
228
+ //#endregion
229
+ export { restoreIdbFromDisk as i, persistIdbToDisk as n, readLegacyMatrixIdbSnapshotState as r, idb_persistence_exports as t };
@@ -0,0 +1,32 @@
1
+ //#region extensions/matrix/src/matrix/sdk/idb-persistence-lock.ts
2
+ const MATRIX_IDB_PERSIST_INTERVAL_MS = 6e4;
3
+ const IDB_SNAPSHOT_LOCK_STALE_MS = 5 * 6e4;
4
+ const IDB_SNAPSHOT_LOCK_RETRY_BASE = {
5
+ factor: 2,
6
+ minTimeout: 50,
7
+ maxTimeout: 5e3,
8
+ randomize: true
9
+ };
10
+ function computeRetryDelayMs(retries, attempt) {
11
+ return Math.min(retries.maxTimeout, Math.max(retries.minTimeout, retries.minTimeout * retries.factor ** attempt));
12
+ }
13
+ function computeMinimumRetryWindowMs(retries) {
14
+ let total = 0;
15
+ const attempts = Math.max(1, retries.retries + 1);
16
+ for (let attempt = 0; attempt < attempts - 1; attempt += 1) total += computeRetryDelayMs(retries, attempt);
17
+ return total;
18
+ }
19
+ function resolveRetriesForMinimumWindowMs(retries, minimumWindowMs) {
20
+ const resolved = {
21
+ ...retries,
22
+ retries: 0
23
+ };
24
+ while (computeMinimumRetryWindowMs(resolved) < minimumWindowMs) resolved.retries += 1;
25
+ return resolved;
26
+ }
27
+ const MATRIX_IDB_SNAPSHOT_LOCK_OPTIONS = {
28
+ retries: resolveRetriesForMinimumWindowMs(IDB_SNAPSHOT_LOCK_RETRY_BASE, MATRIX_IDB_PERSIST_INTERVAL_MS),
29
+ stale: IDB_SNAPSHOT_LOCK_STALE_MS
30
+ };
31
+ //#endregion
32
+ export { MATRIX_IDB_SNAPSHOT_LOCK_OPTIONS as n, MATRIX_IDB_PERSIST_INTERVAL_MS as t };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { n as registerMatrixCliMetadata } from "./cli-metadata-CW6xSM2K.js";
1
+ import { n as registerMatrixCliMetadata } from "./cli-metadata-C9_um_Yj.js";
2
2
  import { registerMatrixSubagentHooks } from "./subagent-hooks-api.js";
3
3
  import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
4
4
  //#region extensions/matrix/index.ts