@openclaw/matrix 2026.5.28 → 2026.5.30-beta.1

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 (63) hide show
  1. package/dist/api.js +7 -7
  2. package/dist/{approval-handler.runtime-Cso-m9Q7.js → approval-handler.runtime-nfyxbtVZ.js} +5 -5
  3. package/dist/{approval-ids-IrHynnHK.js → approval-ids-vw7teE3M.js} +1 -1
  4. package/dist/{approval-reaction-auth-D0nZ_4ik.js → approval-reaction-auth-kAazIsvu.js} +2 -2
  5. package/dist/auth-presence.js +1 -1
  6. package/dist/{channel-D7FK_lEY.js → channel-DwJf74NH.js} +23 -18
  7. package/dist/channel-plugin-api.js +1 -1
  8. package/dist/{channel.runtime-CBrW2dLp.js → channel.runtime-6ITv13UJ.js} +8 -8
  9. package/dist/{cli-C1xFg7Q-.js → cli-BXd9cN_x.js} +14 -13
  10. package/dist/{cli-metadata-zz9Cmwcs.js → cli-metadata-CkMUnkMl.js} +1 -1
  11. package/dist/cli-metadata.js +1 -1
  12. package/dist/{client-BIBY50VG.js → client-CpSI5BON.js} +2 -2
  13. package/dist/{client-bootstrap-Chmkqhy7.js → client-bootstrap-DOlQb7Jx.js} +1 -1
  14. package/dist/{client-BMoZSA2L.js → client-spaouc7I.js} +2 -2
  15. package/dist/{config-schema-wK02TzmZ.js → config-schema-Bx-Pb1Kw.js} +3 -3
  16. package/dist/contract-api.js +4 -4
  17. package/dist/{create-client-B1a3Am-I.js → create-client-B4CPKa5P.js} +3 -3
  18. package/dist/{credentials-CDjQjIds.js → credentials-Bi0pTJDK.js} +1 -1
  19. package/dist/{credentials-read-DySnJlLx.js → credentials-read-DpxFOhx0.js} +2 -2
  20. package/dist/{credentials-write.runtime-Ca2MN99y.js → credentials-write.runtime-BB5QuM4Z.js} +1 -1
  21. package/dist/{crypto-runtime-oweQ3RiB.js → crypto-runtime-3hgwY-d6.js} +7 -6
  22. package/dist/{directory-live-M-3KeudM.js → directory-live-DgjzYeC_.js} +2 -2
  23. package/dist/{doctor-CENc9ks0.js → doctor-D3wfD2UP.js} +17 -3
  24. package/dist/{draft-stream-r49dgIZc.js → draft-stream-DQN43iqS.js} +1 -1
  25. package/dist/{encryption-guidance-CU-OAPMg.js → encryption-guidance-aEUzD940.js} +1 -1
  26. package/dist/helper-api.js +2 -2
  27. package/dist/index.js +2 -2
  28. package/dist/{legacy-crypto-restore-BgW3I87R.js → legacy-crypto-restore--9Wu5rsx.js} +1 -1
  29. package/dist/{logging-yEwXx4Hm.js → logging-C7wjdKK5.js} +1 -1
  30. package/dist/{matrix-migration.runtime-CZOep_JX.js → matrix-migration.runtime-RzIEp7RP.js} +3 -3
  31. package/dist/{media-text-C4IBQI5B.js → media-text-C8b9cJiE.js} +1 -1
  32. package/dist/{messages-CMx2qIs1.js → messages-DyU_49Ws.js} +3 -3
  33. package/dist/{monitor-COOR-Ksj.js → monitor-C-w1IkPI.js} +133 -104
  34. package/dist/plugin-entry.handlers.runtime.js +1 -1
  35. package/dist/probe.runtime-BegszwhP.js +3 -0
  36. package/dist/{profile-update-Cl7wAFCq.js → profile-update-DON3UoVK.js} +2 -2
  37. package/dist/{reaction-events-D3jtYqTp.js → reaction-events-Cf-zAwa6.js} +1 -1
  38. package/dist/{recovery-key-store-DfQ_9s6u.js → recovery-key-store-BRnvY8XS.js} +1 -1
  39. package/dist/{resolve-targets-D-K3tTPe.js → resolve-targets-CLuzv_Jl.js} +1 -1
  40. package/dist/{resolver.runtime-BRG9o8iL.js → resolver.runtime-VywXDAZv.js} +1 -1
  41. package/dist/runtime-api.js +3 -3
  42. package/dist/runtime-heavy-api.js +1 -1
  43. package/dist/{sdk-ymjYByhr.js → sdk-C2iC7PJZ.js} +6 -6
  44. package/dist/{send-peVVVL75.js → send-CAmsWgZ2.js} +3 -3
  45. package/dist/{setup-bootstrap-CiX7Pd07.js → setup-bootstrap-5ki8dOiM.js} +2 -2
  46. package/dist/{setup-core-DOhHYRrZ.js → setup-core-X-qaIzVT.js} +4 -4
  47. package/dist/setup-plugin-api.js +3 -3
  48. package/dist/{setup-surface-CrUp7oeN.js → setup-surface-D6gS45Pz.js} +6 -6
  49. package/dist/{shared-CmsjJY4i.js → shared-DjJds8e0.js} +6 -6
  50. package/dist/startup-verification-DdSXlCLn.js +233 -0
  51. package/dist/{storage-onzulLbU.js → storage-Ds-2Iur5.js} +18 -6
  52. package/dist/subagent-hooks-api.js +18 -2
  53. package/dist/{subagent-hooks-api-bedE4GYl.js → subagent-hooks-dkPAF6Et.js} +3 -30
  54. package/dist/{thread-bindings-DAg6grT8.js → thread-bindings-yt8HTZo0.js} +141 -39
  55. package/dist/{tool-actions.runtime-DwbLBrRr.js → tool-actions.runtime-DOh3pfFu.js} +7 -7
  56. package/dist/{verification-BM7g0BeT.js → verification-BkvujZrn.js} +2 -2
  57. package/npm-shrinkwrap.json +3 -3
  58. package/package.json +4 -4
  59. package/dist/probe.runtime-DgSABMiF.js +0 -3
  60. package/dist/startup-verification-BmTEngvU.js +0 -132
  61. package/dist/{account-selection-C3arLOhC.js → account-selection-DEMtY2cn.js} +1 -1
  62. package/dist/{runtime-api-CsF7Kokd.js → runtime-api-CsBoesCU.js} +2 -2
  63. package/dist/{storage-paths-BV2Z7bns.js → storage-paths-BWo_ZEMC.js} +1 -1
@@ -1,11 +1,11 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
- import { a as resolveMatrixDefaultOrOnlyAccountId, n as requiresExplicitMatrixDefaultAccount, o as resolveMatrixAccountStringValues } from "./account-selection-C3arLOhC.js";
2
+ import { a as resolveMatrixDefaultOrOnlyAccountId, n as requiresExplicitMatrixDefaultAccount, o as resolveMatrixAccountStringValues } from "./account-selection-DEMtY2cn.js";
3
3
  import { t as getMatrixScopedEnvVarNames } from "./env-vars-KzaYveuy.js";
4
4
  import { i as findMatrixAccountConfig, l as resolveMatrixBaseConfig, o as listNormalizedMatrixAccountIds, t as resolveMatrixConfigFieldPath } from "./config-paths-ZBCMwSos.js";
5
5
  import { i as resolveScopedMatrixEnvConfig, n as resolveGlobalMatrixEnvConfig } from "./env-auth-DIzOApj0.js";
6
6
  import { t as getMatrixRuntime } from "./runtime-6S3DNFNv.js";
7
7
  import { t as resolveValidatedMatrixHomeserverUrl } from "./url-validation-GRHde6lq.js";
8
- import { r as repairCurrentTokenStorageMetaDeviceId } from "./storage-onzulLbU.js";
8
+ import { i as repairCurrentTokenStorageMetaDeviceId } from "./storage-Ds-2Iur5.js";
9
9
  import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, normalizeAccountId as normalizeAccountId$1, normalizeOptionalAccountId, normalizeOptionalAccountId as normalizeOptionalAccountId$1 } from "openclaw/plugin-sdk/account-id";
10
10
  import { coerceSecretRef, normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input-runtime";
11
11
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
@@ -22,21 +22,21 @@ let matrixCredentialsWriteRuntimePromise;
22
22
  let matrixSecretInputDepsPromise;
23
23
  const MATRIX_AUTH_REQUEST_RETRY_RE = /\b(fetch failed|econnreset|econnrefused|enotfound|etimedout|ehostunreach|enetunreach|eai_again|und_err_|socket hang up|network|headers timeout|body timeout|connect timeout)\b/i;
24
24
  async function loadMatrixAuthClientDeps() {
25
- matrixAuthClientDepsPromise ??= Promise.all([import("./sdk-ymjYByhr.js"), import("./logging-yEwXx4Hm.js")]).then(([sdkModule, loggingModule]) => ({
25
+ matrixAuthClientDepsPromise ??= Promise.all([import("./sdk-C2iC7PJZ.js"), import("./logging-C7wjdKK5.js")]).then(([sdkModule, loggingModule]) => ({
26
26
  MatrixClient: sdkModule.MatrixClient,
27
27
  ensureMatrixSdkLoggingConfigured: loggingModule.ensureMatrixSdkLoggingConfigured
28
28
  }));
29
29
  return await matrixAuthClientDepsPromise;
30
30
  }
31
31
  async function loadMatrixCredentialsReadDeps() {
32
- matrixCredentialsReadDepsPromise ??= import("./credentials-read-DySnJlLx.js").then((n) => n.r).then((credentialsReadModule) => ({
32
+ matrixCredentialsReadDepsPromise ??= import("./credentials-read-DpxFOhx0.js").then((n) => n.r).then((credentialsReadModule) => ({
33
33
  loadMatrixCredentials: credentialsReadModule.loadMatrixCredentials,
34
34
  credentialsMatchConfig: credentialsReadModule.credentialsMatchConfig
35
35
  }));
36
36
  return await matrixCredentialsReadDepsPromise;
37
37
  }
38
38
  async function loadMatrixCredentialsWriteRuntime() {
39
- matrixCredentialsWriteRuntimePromise ??= import("./credentials-write.runtime-Ca2MN99y.js");
39
+ matrixCredentialsWriteRuntimePromise ??= import("./credentials-write.runtime-BB5QuM4Z.js");
40
40
  return await matrixCredentialsWriteRuntimePromise;
41
41
  }
42
42
  async function loadMatrixSecretInputDeps() {
@@ -569,7 +569,7 @@ var shared_exports = /* @__PURE__ */ __exportAll({
569
569
  });
570
570
  let matrixCreateClientDepsPromise;
571
571
  async function loadMatrixCreateClientDeps() {
572
- matrixCreateClientDepsPromise ??= import("./create-client-B1a3Am-I.js").then((n) => n.n).then((runtime) => ({ createMatrixClient: runtime.createMatrixClient }));
572
+ matrixCreateClientDepsPromise ??= import("./create-client-B4CPKa5P.js").then((n) => n.n).then((runtime) => ({ createMatrixClient: runtime.createMatrixClient }));
573
573
  return await matrixCreateClientDepsPromise;
574
574
  }
575
575
  const sharedClientStates = /* @__PURE__ */ new Map();
@@ -0,0 +1,233 @@
1
+ import { t as getMatrixRuntime } from "./runtime-6S3DNFNv.js";
2
+ import { t as formatMatrixErrorMessage } from "./errors-C47hvAF8.js";
3
+ import { o as resolveMatrixStoragePaths, r as recordCurrentStorageMetaDeviceId } from "./storage-Ds-2Iur5.js";
4
+ import { n as resolveMatrixSqliteStateEnv } from "./thread-bindings-yt8HTZo0.js";
5
+ import path from "node:path";
6
+ import { createHash } from "node:crypto";
7
+ import { timestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
8
+ import { readJsonFileWithFallback } from "openclaw/plugin-sdk/json-store";
9
+ import fs from "node:fs/promises";
10
+ //#region extensions/matrix/src/matrix/monitor/startup-verification.ts
11
+ const STARTUP_VERIFICATION_STATE_FILENAME = "startup-verification.json";
12
+ const STARTUP_VERIFICATION_NAMESPACE = "startup-verification";
13
+ const STARTUP_VERIFICATION_MIGRATIONS_NAMESPACE = "startup-verification-migrations";
14
+ const STARTUP_VERIFICATION_MAX_ENTRIES = 1e3;
15
+ const DEFAULT_STARTUP_VERIFICATION_MODE = "if-unverified";
16
+ const DEFAULT_STARTUP_VERIFICATION_COOLDOWN_HOURS = 24;
17
+ const DEFAULT_STARTUP_VERIFICATION_FAILURE_COOLDOWN_MS = 3600 * 1e3;
18
+ function normalizeCooldownHours(value) {
19
+ if (typeof value !== "number" || !Number.isFinite(value)) return DEFAULT_STARTUP_VERIFICATION_COOLDOWN_HOURS;
20
+ return Math.max(0, value);
21
+ }
22
+ function resolveStartupVerificationStatePath(params) {
23
+ const storagePaths = resolveMatrixStoragePaths({
24
+ homeserver: params.auth.homeserver,
25
+ userId: params.auth.userId,
26
+ accessToken: params.auth.accessToken,
27
+ accountId: params.auth.accountId,
28
+ deviceId: params.auth.deviceId,
29
+ env: params.env,
30
+ stateDir: params.stateDir
31
+ });
32
+ return path.join(storagePaths.rootDir, STARTUP_VERIFICATION_STATE_FILENAME);
33
+ }
34
+ function buildStartupVerificationKey(auth) {
35
+ return auth.accountId.trim() || "default";
36
+ }
37
+ function createStartupVerificationStore(params) {
38
+ return getMatrixRuntime().state.openKeyedStore({
39
+ namespace: STARTUP_VERIFICATION_NAMESPACE,
40
+ maxEntries: STARTUP_VERIFICATION_MAX_ENTRIES,
41
+ env: resolveMatrixSqliteStateEnv(params)
42
+ });
43
+ }
44
+ function createStartupVerificationMigrationStore(params) {
45
+ return getMatrixRuntime().state.openKeyedStore({
46
+ namespace: STARTUP_VERIFICATION_MIGRATIONS_NAMESPACE,
47
+ maxEntries: STARTUP_VERIFICATION_MAX_ENTRIES,
48
+ env: resolveMatrixSqliteStateEnv(params)
49
+ });
50
+ }
51
+ function buildStartupVerificationImportKey(params) {
52
+ const accountId = params.auth.accountId.trim() || "default";
53
+ return `${accountId}:${createHash("sha256").update(accountId).update("\0").update(params.legacyFilePath).digest("hex")}`;
54
+ }
55
+ async function readLegacyStartupVerificationState(filePath) {
56
+ const { value } = await readJsonFileWithFallback(filePath, null);
57
+ return value && typeof value === "object" ? value : null;
58
+ }
59
+ async function readStartupVerificationState(params) {
60
+ const store = createStartupVerificationStore(params);
61
+ const key = buildStartupVerificationKey(params.auth);
62
+ const value = await store.lookup(key);
63
+ if (value && typeof value === "object") return value;
64
+ const migrationStore = createStartupVerificationMigrationStore(params);
65
+ const legacyImportKey = buildStartupVerificationImportKey({
66
+ auth: params.auth,
67
+ legacyFilePath: params.legacyFilePath
68
+ });
69
+ if (await migrationStore.lookup(legacyImportKey)) return null;
70
+ const legacy = await readLegacyStartupVerificationState(params.legacyFilePath);
71
+ if (legacy) await store.register(key, legacy).then(async () => {
72
+ if (typeof legacy.deviceId === "string" && legacy.deviceId.trim()) recordCurrentStorageMetaDeviceId({
73
+ rootDir: path.dirname(params.legacyFilePath),
74
+ deviceId: legacy.deviceId
75
+ });
76
+ await migrationStore.register(legacyImportKey, { importedAt: Date.now() });
77
+ await fs.rm(params.legacyFilePath, { force: true }).catch(() => {});
78
+ }).catch(() => {});
79
+ return legacy;
80
+ }
81
+ async function writeStartupVerificationState(params) {
82
+ await createStartupVerificationStore(params).register(buildStartupVerificationKey(params.auth), params.state);
83
+ await createStartupVerificationMigrationStore(params).register(buildStartupVerificationImportKey({
84
+ auth: params.auth,
85
+ legacyFilePath: params.legacyFilePath
86
+ }), { importedAt: Date.now() }).catch(() => {});
87
+ if (typeof params.state.deviceId === "string" && params.state.deviceId.trim()) recordCurrentStorageMetaDeviceId({
88
+ rootDir: path.dirname(params.legacyFilePath),
89
+ deviceId: params.state.deviceId
90
+ });
91
+ await fs.rm(params.legacyFilePath, { force: true }).catch(() => {});
92
+ }
93
+ async function clearStartupVerificationState(params) {
94
+ await createStartupVerificationStore(params).delete(buildStartupVerificationKey(params.auth)).catch(() => {});
95
+ await createStartupVerificationMigrationStore(params).register(buildStartupVerificationImportKey({
96
+ auth: params.auth,
97
+ legacyFilePath: params.legacyFilePath
98
+ }), { importedAt: Date.now() }).catch(() => {});
99
+ await fs.rm(params.legacyFilePath, { force: true }).catch(() => {});
100
+ }
101
+ function resolveStateCooldownMs(state, cooldownMs) {
102
+ if (state?.outcome === "failed") return Math.min(cooldownMs, DEFAULT_STARTUP_VERIFICATION_FAILURE_COOLDOWN_MS);
103
+ return cooldownMs;
104
+ }
105
+ function resolveRetryAfterMs(params) {
106
+ const attemptedAtMs = Date.parse(params.attemptedAt ?? "");
107
+ if (!Number.isFinite(attemptedAtMs)) return;
108
+ const remaining = attemptedAtMs + params.cooldownMs - params.nowMs;
109
+ return remaining > 0 ? remaining : void 0;
110
+ }
111
+ function resolveStartupVerificationTimestamp(nowMs) {
112
+ return timestampMsToIsoString(nowMs) ?? timestampMsToIsoString(Date.now()) ?? "1970-01-01T00:00:00.000Z";
113
+ }
114
+ function shouldHonorCooldown(params) {
115
+ if (!params.state || params.stateCooldownMs <= 0) return false;
116
+ if (params.state.userId && params.verification.userId && params.state.userId !== params.verification.userId) return false;
117
+ if (params.state.deviceId && params.verification.deviceId && params.state.deviceId !== params.verification.deviceId) return false;
118
+ return resolveRetryAfterMs({
119
+ attemptedAt: params.state.attemptedAt,
120
+ cooldownMs: params.stateCooldownMs,
121
+ nowMs: params.nowMs
122
+ }) !== void 0;
123
+ }
124
+ function hasPendingSelfVerification(verifications) {
125
+ return verifications.some((entry) => entry.isSelfVerification && !entry.completed && entry.pending);
126
+ }
127
+ async function ensureMatrixStartupVerification(params) {
128
+ if (params.auth.encryption !== true || !params.client.crypto) return { kind: "unsupported" };
129
+ const verification = await params.client.getOwnDeviceVerificationStatus();
130
+ const statePath = params.stateFilePath ?? resolveStartupVerificationStatePath({
131
+ auth: params.auth,
132
+ env: params.env,
133
+ stateDir: params.stateDir
134
+ });
135
+ const stateDir = params.stateDir ?? path.dirname(statePath);
136
+ if (verification.verified) {
137
+ await clearStartupVerificationState({
138
+ auth: params.auth,
139
+ env: params.env,
140
+ stateDir,
141
+ legacyFilePath: statePath
142
+ });
143
+ return {
144
+ kind: "verified",
145
+ verification
146
+ };
147
+ }
148
+ if ((params.accountConfig.startupVerification ?? DEFAULT_STARTUP_VERIFICATION_MODE) === "off") {
149
+ await clearStartupVerificationState({
150
+ auth: params.auth,
151
+ env: params.env,
152
+ stateDir,
153
+ legacyFilePath: statePath
154
+ });
155
+ return {
156
+ kind: "disabled",
157
+ verification
158
+ };
159
+ }
160
+ if (hasPendingSelfVerification(await params.client.crypto.listVerifications().catch(() => []))) return {
161
+ kind: "pending",
162
+ verification
163
+ };
164
+ const cooldownMs = normalizeCooldownHours(params.accountConfig.startupVerificationCooldownHours) * 60 * 60 * 1e3;
165
+ const nowMs = params.nowMs ?? Date.now();
166
+ const attemptedAt = resolveStartupVerificationTimestamp(nowMs);
167
+ const state = await readStartupVerificationState({
168
+ auth: params.auth,
169
+ env: params.env,
170
+ stateDir,
171
+ legacyFilePath: statePath
172
+ });
173
+ const stateCooldownMs = resolveStateCooldownMs(state, cooldownMs);
174
+ if (shouldHonorCooldown({
175
+ state,
176
+ verification,
177
+ stateCooldownMs,
178
+ nowMs
179
+ })) return {
180
+ kind: "cooldown",
181
+ verification,
182
+ retryAfterMs: resolveRetryAfterMs({
183
+ attemptedAt: state?.attemptedAt,
184
+ cooldownMs: stateCooldownMs,
185
+ nowMs
186
+ })
187
+ };
188
+ try {
189
+ const request = await params.client.crypto.requestVerification({ ownUser: true });
190
+ await writeStartupVerificationState({
191
+ auth: params.auth,
192
+ env: params.env,
193
+ stateDir,
194
+ legacyFilePath: statePath,
195
+ state: {
196
+ userId: verification.userId,
197
+ deviceId: verification.deviceId,
198
+ attemptedAt,
199
+ outcome: "requested",
200
+ requestId: request.id,
201
+ transactionId: request.transactionId
202
+ }
203
+ });
204
+ return {
205
+ kind: "requested",
206
+ verification,
207
+ requestId: request.id,
208
+ transactionId: request.transactionId ?? void 0
209
+ };
210
+ } catch (err) {
211
+ const error = formatMatrixErrorMessage(err);
212
+ await writeStartupVerificationState({
213
+ auth: params.auth,
214
+ env: params.env,
215
+ stateDir,
216
+ legacyFilePath: statePath,
217
+ state: {
218
+ userId: verification.userId,
219
+ deviceId: verification.deviceId,
220
+ attemptedAt,
221
+ outcome: "failed",
222
+ error
223
+ }
224
+ }).catch(() => {});
225
+ return {
226
+ kind: "request-failed",
227
+ verification,
228
+ error
229
+ };
230
+ }
231
+ }
232
+ //#endregion
233
+ export { ensureMatrixStartupVerification };
@@ -1,6 +1,6 @@
1
- import { a as resolveMatrixDefaultOrOnlyAccountId, n as requiresExplicitMatrixDefaultAccount } from "./account-selection-C3arLOhC.js";
1
+ import { a as resolveMatrixDefaultOrOnlyAccountId, n as requiresExplicitMatrixDefaultAccount } from "./account-selection-DEMtY2cn.js";
2
2
  import { t as getMatrixRuntime } from "./runtime-6S3DNFNv.js";
3
- import { n as resolveMatrixAccountStorageRoot, s as resolveMatrixLegacyFlatStoragePaths } from "./storage-paths-BV2Z7bns.js";
3
+ import { n as resolveMatrixAccountStorageRoot, s as resolveMatrixLegacyFlatStoragePaths } from "./storage-paths-BWo_ZEMC.js";
4
4
  import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
5
5
  import fs from "node:fs";
6
6
  import os from "node:os";
@@ -13,7 +13,6 @@ const THREAD_BINDINGS_FILENAME = "thread-bindings.json";
13
13
  const LEGACY_CRYPTO_MIGRATION_FILENAME = "legacy-crypto-migration.json";
14
14
  const RECOVERY_KEY_FILENAME = "recovery-key.json";
15
15
  const IDB_SNAPSHOT_FILENAME = "crypto-idb-snapshot.json";
16
- const STARTUP_VERIFICATION_FILENAME = "startup-verification.json";
17
16
  function resolveLegacyStoragePaths(env = process.env) {
18
17
  const legacy = resolveMatrixLegacyFlatStoragePaths(getMatrixRuntime().state.resolveStateDir(env, os.homedir));
19
18
  return {
@@ -59,8 +58,6 @@ function readStoredRootMetadata(rootDir) {
59
58
  if (parsed.currentTokenStateClaimed === true) metadata.currentTokenStateClaimed = true;
60
59
  if (typeof parsed.createdAt === "string" && parsed.createdAt.trim()) metadata.createdAt = parsed.createdAt.trim();
61
60
  }
62
- const verification = loadJsonFile(path.join(rootDir, STARTUP_VERIFICATION_FILENAME));
63
- if (!metadata.deviceId && typeof verification?.deviceId === "string" && verification.deviceId.trim()) metadata.deviceId = verification.deviceId.trim();
64
61
  return metadata;
65
62
  }
66
63
  function isCompatibleStorageRoot(params) {
@@ -261,6 +258,21 @@ function claimCurrentTokenStorageState(params) {
261
258
  createdAt: metadata.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
262
259
  });
263
260
  }
261
+ function recordCurrentStorageMetaDeviceId(params) {
262
+ const deviceId = params.deviceId.trim();
263
+ if (!deviceId) return false;
264
+ const metadata = readStoredRootMetadata(params.rootDir);
265
+ if (!metadata.accessTokenHash?.trim()) return false;
266
+ return writeStoredRootMetadata(path.join(params.rootDir, STORAGE_META_FILENAME), {
267
+ homeserver: metadata.homeserver,
268
+ userId: metadata.userId,
269
+ accountId: metadata.accountId ?? DEFAULT_ACCOUNT_KEY,
270
+ accessTokenHash: metadata.accessTokenHash,
271
+ deviceId,
272
+ currentTokenStateClaimed: metadata.currentTokenStateClaimed === true,
273
+ createdAt: metadata.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
274
+ });
275
+ }
264
276
  function repairCurrentTokenStorageMetaDeviceId(params) {
265
277
  return writeStorageMeta({
266
278
  storagePaths: resolveMatrixStoragePaths({
@@ -278,4 +290,4 @@ function repairCurrentTokenStorageMetaDeviceId(params) {
278
290
  });
279
291
  }
280
292
  //#endregion
281
- export { resolveMatrixStoragePaths as a, resolveMatrixStateFilePath as i, maybeMigrateLegacyStorage as n, writeStorageMeta as o, repairCurrentTokenStorageMetaDeviceId as r, claimCurrentTokenStorageState as t };
293
+ export { resolveMatrixStateFilePath as a, repairCurrentTokenStorageMetaDeviceId as i, maybeMigrateLegacyStorage as n, resolveMatrixStoragePaths as o, recordCurrentStorageMetaDeviceId as r, writeStorageMeta as s, claimCurrentTokenStorageState as t };
@@ -1,2 +1,18 @@
1
- import { i as handleMatrixSubagentSpawning, n as handleMatrixSubagentDeliveryTarget, r as handleMatrixSubagentEnded, t as registerMatrixSubagentHooks } from "./subagent-hooks-api-bedE4GYl.js";
2
- export { handleMatrixSubagentDeliveryTarget, handleMatrixSubagentEnded, handleMatrixSubagentSpawning, registerMatrixSubagentHooks };
1
+ //#region extensions/matrix/subagent-hooks-api.ts
2
+ let matrixSubagentHooksPromise = null;
3
+ function loadMatrixSubagentHooksModule() {
4
+ matrixSubagentHooksPromise ??= import("./subagent-hooks-dkPAF6Et.js");
5
+ return matrixSubagentHooksPromise;
6
+ }
7
+ function registerMatrixSubagentHooks(api) {
8
+ api.on("subagent_ended", async (event) => {
9
+ const { handleMatrixSubagentEnded } = await loadMatrixSubagentHooksModule();
10
+ await handleMatrixSubagentEnded(event);
11
+ });
12
+ api.on("subagent_delivery_target", async (event) => {
13
+ const { handleMatrixSubagentDeliveryTarget } = await loadMatrixSubagentHooksModule();
14
+ return handleMatrixSubagentDeliveryTarget(event);
15
+ });
16
+ }
17
+ //#endregion
18
+ export { registerMatrixSubagentHooks };
@@ -1,16 +1,10 @@
1
- import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
1
  import { a as resolveMatrixTargetIdentity } from "./target-ids-B-5aQxwn.js";
3
2
  import { a as listBindingsForAccount, c as resolveBindingKey, i as listAllBindings, n as getMatrixThreadBindingManager, o as removeBindingRecord } from "./thread-bindings-shared-CKnY4LSd.js";
4
- import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
5
- import { getSessionBindingService } from "openclaw/plugin-sdk/conversation-binding-runtime";
6
3
  import { formatThreadBindingDisabledError, formatThreadBindingSpawnDisabledError, resolveThreadBindingSpawnPolicy } from "openclaw/plugin-sdk/conversation-runtime";
7
4
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
5
+ import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
6
+ import { getSessionBindingService } from "openclaw/plugin-sdk/conversation-binding-runtime";
8
7
  //#region extensions/matrix/src/matrix/subagent-hooks.ts
9
- var subagent_hooks_exports = /* @__PURE__ */ __exportAll({
10
- handleMatrixSubagentDeliveryTarget: () => handleMatrixSubagentDeliveryTarget,
11
- handleMatrixSubagentEnded: () => handleMatrixSubagentEnded,
12
- handleMatrixSubagentSpawning: () => handleMatrixSubagentSpawning
13
- });
14
8
  function summarizeError(err) {
15
9
  if (err instanceof Error) return err.message;
16
10
  if (typeof err === "string") return err;
@@ -146,25 +140,4 @@ function handleMatrixSubagentDeliveryTarget(event) {
146
140
  } };
147
141
  }
148
142
  //#endregion
149
- //#region extensions/matrix/subagent-hooks-api.ts
150
- let matrixSubagentHooksPromise = null;
151
- function loadMatrixSubagentHooksModule() {
152
- matrixSubagentHooksPromise ??= Promise.resolve().then(() => subagent_hooks_exports);
153
- return matrixSubagentHooksPromise;
154
- }
155
- function registerMatrixSubagentHooks(api) {
156
- api.on("subagent_spawning", async (event) => {
157
- const { handleMatrixSubagentSpawning } = await loadMatrixSubagentHooksModule();
158
- return await handleMatrixSubagentSpawning(api, event);
159
- });
160
- api.on("subagent_ended", async (event) => {
161
- const { handleMatrixSubagentEnded } = await loadMatrixSubagentHooksModule();
162
- await handleMatrixSubagentEnded(event);
163
- });
164
- api.on("subagent_delivery_target", async (event) => {
165
- const { handleMatrixSubagentDeliveryTarget } = await loadMatrixSubagentHooksModule();
166
- return handleMatrixSubagentDeliveryTarget(event);
167
- });
168
- }
169
- //#endregion
170
- export { handleMatrixSubagentSpawning as i, handleMatrixSubagentDeliveryTarget as n, handleMatrixSubagentEnded as r, registerMatrixSubagentHooks as t };
143
+ export { handleMatrixSubagentDeliveryTarget, handleMatrixSubagentEnded, handleMatrixSubagentSpawning };
@@ -1,13 +1,39 @@
1
+ import { t as getMatrixRuntime } from "./runtime-6S3DNFNv.js";
1
2
  import { a as listBindingsForAccount, c as resolveBindingKey, f as setMatrixThreadBindingManagerEntry, h as toSessionBindingRecord, l as resolveEffectiveBindingExpiry, m as toMatrixBindingTargetKind, o as removeBindingRecord, r as getMatrixThreadBindingManagerEntry, t as deleteMatrixThreadBindingManagerEntry, u as setBindingRecord } from "./thread-bindings-shared-CKnY4LSd.js";
2
- import { i as resolveMatrixStateFilePath, t as claimCurrentTokenStorageState } from "./storage-onzulLbU.js";
3
- import { a as sendMessageMatrix } from "./send-peVVVL75.js";
3
+ import { a as resolveMatrixStateFilePath, t as claimCurrentTokenStorageState } from "./storage-Ds-2Iur5.js";
4
+ import { a as sendMessageMatrix } from "./send-CAmsWgZ2.js";
4
5
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
5
- import { registerSessionBindingAdapter, resolveThreadBindingFarewellText, unregisterSessionBindingAdapter } from "openclaw/plugin-sdk/thread-bindings-session-runtime";
6
+ import os from "node:os";
6
7
  import path from "node:path";
7
- import { readJsonFileWithFallback, writeJsonFileAtomically } from "openclaw/plugin-sdk/json-store";
8
+ import { createHash } from "node:crypto";
9
+ import { registerSessionBindingAdapter, resolveThreadBindingFarewellText, unregisterSessionBindingAdapter } from "openclaw/plugin-sdk/thread-bindings-session-runtime";
10
+ import { readJsonFileWithFallback } from "openclaw/plugin-sdk/json-store";
11
+ import fs from "node:fs/promises";
8
12
  import { resolveAgentIdFromSessionKey } from "openclaw/plugin-sdk/session-key-runtime";
13
+ //#region extensions/matrix/src/matrix/sqlite-state.ts
14
+ function resolveStateDirOverride(options) {
15
+ if (!options) return;
16
+ if (options.stateDir) return options.stateDir;
17
+ if (options.stateRootDir) return options.stateRootDir;
18
+ return getMatrixRuntime().state.resolveStateDir(options.env ?? process.env, os.homedir);
19
+ }
20
+ function resolveMatrixSqliteStateKey(options) {
21
+ return resolveStateDirOverride(options) ?? "";
22
+ }
23
+ function resolveMatrixSqliteStateEnv(options) {
24
+ const stateDir = resolveStateDirOverride(options);
25
+ if (!stateDir) return options?.env;
26
+ return {
27
+ ...options?.env ?? process.env,
28
+ OPENCLAW_STATE_DIR: stateDir
29
+ };
30
+ }
31
+ //#endregion
9
32
  //#region extensions/matrix/src/matrix/thread-bindings.ts
10
33
  const STORE_VERSION = 1;
34
+ const THREAD_BINDINGS_NAMESPACE = "thread-bindings";
35
+ const THREAD_BINDINGS_MIGRATIONS_NAMESPACE = "thread-bindings-migrations";
36
+ const THREAD_BINDINGS_MAX_ENTRIES = 1e4;
11
37
  const THREAD_BINDINGS_SWEEP_INTERVAL_MS = 6e4;
12
38
  const TOUCH_PERSIST_DELAY_MS = 3e4;
13
39
  function resolveBindingsPath(params) {
@@ -19,43 +45,80 @@ function resolveBindingsPath(params) {
19
45
  filename: "thread-bindings.json"
20
46
  });
21
47
  }
22
- async function loadBindingsFromDisk(filePath, accountId) {
48
+ function createThreadBindingStore(params) {
49
+ return getMatrixRuntime().state.openKeyedStore({
50
+ namespace: THREAD_BINDINGS_NAMESPACE,
51
+ maxEntries: THREAD_BINDINGS_MAX_ENTRIES,
52
+ env: resolveMatrixSqliteStateEnv(params)
53
+ });
54
+ }
55
+ function createThreadBindingMigrationStore(params) {
56
+ return getMatrixRuntime().state.openKeyedStore({
57
+ namespace: THREAD_BINDINGS_MIGRATIONS_NAMESPACE,
58
+ maxEntries: 1e3,
59
+ env: resolveMatrixSqliteStateEnv(params)
60
+ });
61
+ }
62
+ function buildThreadBindingStoreKey(record) {
63
+ const digest = createHash("sha256").update(record.accountId).update("\0").update(record.parentConversationId ?? "").update("\0").update(record.conversationId).digest("hex");
64
+ return `${record.accountId}:${digest}`;
65
+ }
66
+ function buildLegacyThreadBindingsImportKey(params) {
67
+ const digest = createHash("sha256").update(params.accountId).update("\0").update(params.legacyFilePath).digest("hex");
68
+ return `${params.accountId}:${digest}`;
69
+ }
70
+ function normalizeBindingRecord(entry, accountId) {
71
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) return null;
72
+ const record = entry;
73
+ if (record.accountId && record.accountId !== accountId) return null;
74
+ const conversationId = normalizeOptionalString(record.conversationId);
75
+ const parentConversationId = normalizeOptionalString(record.parentConversationId);
76
+ const targetSessionKey = normalizeOptionalString(record.targetSessionKey) ?? "";
77
+ if (!conversationId || !targetSessionKey) return null;
78
+ const boundAt = typeof record.boundAt === "number" && Number.isFinite(record.boundAt) ? Math.floor(record.boundAt) : Date.now();
79
+ const lastActivityAt = typeof record.lastActivityAt === "number" && Number.isFinite(record.lastActivityAt) ? Math.floor(record.lastActivityAt) : boundAt;
80
+ return {
81
+ accountId,
82
+ conversationId,
83
+ ...parentConversationId ? { parentConversationId } : {},
84
+ targetKind: record.targetKind === "subagent" ? "subagent" : "acp",
85
+ targetSessionKey,
86
+ agentId: normalizeOptionalString(record.agentId) || void 0,
87
+ label: normalizeOptionalString(record.label) || void 0,
88
+ boundBy: normalizeOptionalString(record.boundBy) || void 0,
89
+ boundAt,
90
+ lastActivityAt: Math.max(lastActivityAt, boundAt),
91
+ idleTimeoutMs: typeof record.idleTimeoutMs === "number" && Number.isFinite(record.idleTimeoutMs) ? Math.max(0, Math.floor(record.idleTimeoutMs)) : void 0,
92
+ maxAgeMs: typeof record.maxAgeMs === "number" && Number.isFinite(record.maxAgeMs) ? Math.max(0, Math.floor(record.maxAgeMs)) : void 0
93
+ };
94
+ }
95
+ async function loadBindingsFromLegacyDisk(filePath, accountId) {
23
96
  const { value } = await readJsonFileWithFallback(filePath, null);
24
97
  if (value?.version !== STORE_VERSION || !Array.isArray(value.bindings)) return [];
25
98
  const loaded = [];
26
99
  for (const entry of value.bindings) {
27
- const conversationId = normalizeOptionalString(entry?.conversationId);
28
- const parentConversationId = normalizeOptionalString(entry?.parentConversationId);
29
- const targetSessionKey = normalizeOptionalString(entry?.targetSessionKey) ?? "";
30
- if (!conversationId || !targetSessionKey) continue;
31
- const boundAt = typeof entry?.boundAt === "number" && Number.isFinite(entry.boundAt) ? Math.floor(entry.boundAt) : Date.now();
32
- const lastActivityAt = typeof entry?.lastActivityAt === "number" && Number.isFinite(entry.lastActivityAt) ? Math.floor(entry.lastActivityAt) : boundAt;
33
- loaded.push({
34
- accountId,
35
- conversationId,
36
- ...parentConversationId ? { parentConversationId } : {},
37
- targetKind: entry?.targetKind === "subagent" ? "subagent" : "acp",
38
- targetSessionKey,
39
- agentId: normalizeOptionalString(entry?.agentId) || void 0,
40
- label: normalizeOptionalString(entry?.label) || void 0,
41
- boundBy: normalizeOptionalString(entry?.boundBy) || void 0,
42
- boundAt,
43
- lastActivityAt: Math.max(lastActivityAt, boundAt),
44
- idleTimeoutMs: typeof entry?.idleTimeoutMs === "number" && Number.isFinite(entry.idleTimeoutMs) ? Math.max(0, Math.floor(entry.idleTimeoutMs)) : void 0,
45
- maxAgeMs: typeof entry?.maxAgeMs === "number" && Number.isFinite(entry.maxAgeMs) ? Math.max(0, Math.floor(entry.maxAgeMs)) : void 0
46
- });
100
+ const record = normalizeBindingRecord(entry, accountId);
101
+ if (record) loaded.push(record);
47
102
  }
48
103
  return loaded;
49
104
  }
50
- function toStoredBindingsState(bindings) {
51
- return {
52
- version: STORE_VERSION,
53
- bindings: [...bindings].toSorted((a, b) => a.boundAt - b.boundAt)
54
- };
105
+ async function loadBindingsFromPluginState(params) {
106
+ const store = createThreadBindingStore(params);
107
+ const loaded = [];
108
+ for (const entry of await store.entries()) {
109
+ const record = normalizeBindingRecord(entry.value, params.accountId);
110
+ if (record) loaded.push(record);
111
+ }
112
+ return loaded;
113
+ }
114
+ function toPluginJsonValue(value) {
115
+ return JSON.parse(JSON.stringify(value));
55
116
  }
56
- async function persistBindingsSnapshot(filePath, bindings) {
57
- await writeJsonFileAtomically(filePath, toStoredBindingsState(bindings));
58
- claimCurrentTokenStorageState({ rootDir: path.dirname(filePath) });
117
+ async function persistBindingsSnapshot(params) {
118
+ const store = createThreadBindingStore(params);
119
+ const liveKeys = new Set(params.bindings.map((record) => buildThreadBindingStoreKey(record)));
120
+ for (const entry of await store.entries()) if (normalizeBindingRecord(entry.value, params.accountId) && !liveKeys.has(entry.key)) await store.delete(entry.key);
121
+ for (const record of params.bindings) await store.register(buildThreadBindingStoreKey(record), toPluginJsonValue(record));
59
122
  }
60
123
  function buildMatrixBindingIntroText(params) {
61
124
  const introText = normalizeOptionalString(params.metadata?.introText);
@@ -94,24 +157,56 @@ async function sendFarewellMessage(params) {
94
157
  }
95
158
  async function createMatrixThreadBindingManager(params) {
96
159
  if (params.auth.accountId !== params.accountId) throw new Error(`Matrix thread binding account mismatch: requested ${params.accountId}, auth resolved ${params.auth.accountId}`);
97
- const filePath = resolveBindingsPath({
160
+ const legacyFilePath = resolveBindingsPath({
98
161
  auth: params.auth,
99
162
  accountId: params.accountId,
100
163
  env: params.env,
101
164
  stateDir: params.stateDir
102
165
  });
166
+ const sqliteStateDir = path.dirname(legacyFilePath);
167
+ const storageKey = resolveMatrixSqliteStateKey({
168
+ env: params.env,
169
+ stateDir: sqliteStateDir
170
+ });
103
171
  const existingEntry = getMatrixThreadBindingManagerEntry(params.accountId);
104
172
  if (existingEntry) {
105
- if (existingEntry.filePath === filePath) return existingEntry.manager;
173
+ if (existingEntry.storageKey === storageKey) return existingEntry.manager;
106
174
  existingEntry.manager.stop();
107
175
  }
108
- const loaded = await loadBindingsFromDisk(filePath, params.accountId);
176
+ const pluginLoaded = await loadBindingsFromPluginState({
177
+ accountId: params.accountId,
178
+ env: params.env,
179
+ stateDir: sqliteStateDir
180
+ });
181
+ const migrationStore = createThreadBindingMigrationStore({
182
+ env: params.env,
183
+ stateDir: sqliteStateDir
184
+ });
185
+ const legacyImportKey = buildLegacyThreadBindingsImportKey({
186
+ accountId: params.accountId,
187
+ legacyFilePath
188
+ });
189
+ const pluginLoadedKeys = new Set(pluginLoaded.map((record) => buildThreadBindingStoreKey(record)));
190
+ let legacyHadRows = false;
191
+ let legacyLoaded = [];
192
+ if (!await migrationStore.lookup(legacyImportKey)) {
193
+ const legacyCandidates = await loadBindingsFromLegacyDisk(legacyFilePath, params.accountId);
194
+ legacyHadRows = legacyCandidates.length > 0;
195
+ legacyLoaded = legacyCandidates.filter((record) => !pluginLoadedKeys.has(buildThreadBindingStoreKey(record)));
196
+ }
197
+ const loaded = [...pluginLoaded, ...legacyLoaded];
109
198
  for (const record of loaded) setBindingRecord(record);
110
199
  let persistQueue = Promise.resolve();
111
200
  const enqueuePersist = (bindings) => {
112
201
  const snapshot = bindings ?? listBindingsForAccount(params.accountId);
113
202
  const next = persistQueue.catch(() => {}).then(async () => {
114
- await persistBindingsSnapshot(filePath, snapshot);
203
+ await persistBindingsSnapshot({
204
+ accountId: params.accountId,
205
+ bindings: snapshot,
206
+ env: params.env,
207
+ stateDir: sqliteStateDir
208
+ });
209
+ claimCurrentTokenStorageState({ rootDir: sqliteStateDir });
115
210
  });
116
211
  persistQueue = next;
117
212
  return next;
@@ -126,6 +221,13 @@ async function createMatrixThreadBindingManager(params) {
126
221
  idleTimeoutMs: params.idleTimeoutMs,
127
222
  maxAgeMs: params.maxAgeMs
128
223
  };
224
+ if (legacyHadRows) {
225
+ if (legacyLoaded.length > 0) await persist();
226
+ await migrationStore.register(legacyImportKey, { importedAt: Date.now() });
227
+ await fs.rm(legacyFilePath, { force: true }).catch((err) => {
228
+ params.logVerboseMessage?.(`matrix: failed removing migrated legacy thread bindings account=${params.accountId}: ${String(err)}`);
229
+ });
230
+ }
129
231
  let persistTimer = null;
130
232
  const schedulePersist = (delayMs) => {
131
233
  if (persistTimer) return;
@@ -343,10 +445,10 @@ async function createMatrixThreadBindingManager(params) {
343
445
  sweepTimer.unref?.();
344
446
  }
345
447
  setMatrixThreadBindingManagerEntry(params.accountId, {
346
- filePath,
448
+ storageKey,
347
449
  manager
348
450
  });
349
451
  return manager;
350
452
  }
351
453
  //#endregion
352
- export { createMatrixThreadBindingManager as t };
454
+ export { resolveMatrixSqliteStateEnv as n, createMatrixThreadBindingManager as t };