@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.
- package/dist/api.js +7 -7
- package/dist/{approval-handler.runtime-Cso-m9Q7.js → approval-handler.runtime-nfyxbtVZ.js} +5 -5
- package/dist/{approval-ids-IrHynnHK.js → approval-ids-vw7teE3M.js} +1 -1
- package/dist/{approval-reaction-auth-D0nZ_4ik.js → approval-reaction-auth-kAazIsvu.js} +2 -2
- package/dist/auth-presence.js +1 -1
- package/dist/{channel-D7FK_lEY.js → channel-DwJf74NH.js} +23 -18
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-CBrW2dLp.js → channel.runtime-6ITv13UJ.js} +8 -8
- package/dist/{cli-C1xFg7Q-.js → cli-BXd9cN_x.js} +14 -13
- package/dist/{cli-metadata-zz9Cmwcs.js → cli-metadata-CkMUnkMl.js} +1 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/{client-BIBY50VG.js → client-CpSI5BON.js} +2 -2
- package/dist/{client-bootstrap-Chmkqhy7.js → client-bootstrap-DOlQb7Jx.js} +1 -1
- package/dist/{client-BMoZSA2L.js → client-spaouc7I.js} +2 -2
- package/dist/{config-schema-wK02TzmZ.js → config-schema-Bx-Pb1Kw.js} +3 -3
- package/dist/contract-api.js +4 -4
- package/dist/{create-client-B1a3Am-I.js → create-client-B4CPKa5P.js} +3 -3
- package/dist/{credentials-CDjQjIds.js → credentials-Bi0pTJDK.js} +1 -1
- package/dist/{credentials-read-DySnJlLx.js → credentials-read-DpxFOhx0.js} +2 -2
- package/dist/{credentials-write.runtime-Ca2MN99y.js → credentials-write.runtime-BB5QuM4Z.js} +1 -1
- package/dist/{crypto-runtime-oweQ3RiB.js → crypto-runtime-3hgwY-d6.js} +7 -6
- package/dist/{directory-live-M-3KeudM.js → directory-live-DgjzYeC_.js} +2 -2
- package/dist/{doctor-CENc9ks0.js → doctor-D3wfD2UP.js} +17 -3
- package/dist/{draft-stream-r49dgIZc.js → draft-stream-DQN43iqS.js} +1 -1
- package/dist/{encryption-guidance-CU-OAPMg.js → encryption-guidance-aEUzD940.js} +1 -1
- package/dist/helper-api.js +2 -2
- package/dist/index.js +2 -2
- package/dist/{legacy-crypto-restore-BgW3I87R.js → legacy-crypto-restore--9Wu5rsx.js} +1 -1
- package/dist/{logging-yEwXx4Hm.js → logging-C7wjdKK5.js} +1 -1
- package/dist/{matrix-migration.runtime-CZOep_JX.js → matrix-migration.runtime-RzIEp7RP.js} +3 -3
- package/dist/{media-text-C4IBQI5B.js → media-text-C8b9cJiE.js} +1 -1
- package/dist/{messages-CMx2qIs1.js → messages-DyU_49Ws.js} +3 -3
- package/dist/{monitor-COOR-Ksj.js → monitor-C-w1IkPI.js} +133 -104
- package/dist/plugin-entry.handlers.runtime.js +1 -1
- package/dist/probe.runtime-BegszwhP.js +3 -0
- package/dist/{profile-update-Cl7wAFCq.js → profile-update-DON3UoVK.js} +2 -2
- package/dist/{reaction-events-D3jtYqTp.js → reaction-events-Cf-zAwa6.js} +1 -1
- package/dist/{recovery-key-store-DfQ_9s6u.js → recovery-key-store-BRnvY8XS.js} +1 -1
- package/dist/{resolve-targets-D-K3tTPe.js → resolve-targets-CLuzv_Jl.js} +1 -1
- package/dist/{resolver.runtime-BRG9o8iL.js → resolver.runtime-VywXDAZv.js} +1 -1
- package/dist/runtime-api.js +3 -3
- package/dist/runtime-heavy-api.js +1 -1
- package/dist/{sdk-ymjYByhr.js → sdk-C2iC7PJZ.js} +6 -6
- package/dist/{send-peVVVL75.js → send-CAmsWgZ2.js} +3 -3
- package/dist/{setup-bootstrap-CiX7Pd07.js → setup-bootstrap-5ki8dOiM.js} +2 -2
- package/dist/{setup-core-DOhHYRrZ.js → setup-core-X-qaIzVT.js} +4 -4
- package/dist/setup-plugin-api.js +3 -3
- package/dist/{setup-surface-CrUp7oeN.js → setup-surface-D6gS45Pz.js} +6 -6
- package/dist/{shared-CmsjJY4i.js → shared-DjJds8e0.js} +6 -6
- package/dist/startup-verification-DdSXlCLn.js +233 -0
- package/dist/{storage-onzulLbU.js → storage-Ds-2Iur5.js} +18 -6
- package/dist/subagent-hooks-api.js +18 -2
- package/dist/{subagent-hooks-api-bedE4GYl.js → subagent-hooks-dkPAF6Et.js} +3 -30
- package/dist/{thread-bindings-DAg6grT8.js → thread-bindings-yt8HTZo0.js} +141 -39
- package/dist/{tool-actions.runtime-DwbLBrRr.js → tool-actions.runtime-DOh3pfFu.js} +7 -7
- package/dist/{verification-BM7g0BeT.js → verification-BkvujZrn.js} +2 -2
- package/npm-shrinkwrap.json +3 -3
- package/package.json +4 -4
- package/dist/probe.runtime-DgSABMiF.js +0 -3
- package/dist/startup-verification-BmTEngvU.js +0 -132
- package/dist/{account-selection-C3arLOhC.js → account-selection-DEMtY2cn.js} +1 -1
- package/dist/{runtime-api-CsF7Kokd.js → runtime-api-CsBoesCU.js} +2 -2
- 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-
|
|
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 {
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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 {
|
|
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
|
-
|
|
2
|
-
|
|
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
|
-
|
|
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 {
|
|
3
|
-
import { a as sendMessageMatrix } from "./send-
|
|
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
|
|
6
|
+
import os from "node:os";
|
|
6
7
|
import path from "node:path";
|
|
7
|
-
import {
|
|
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
|
-
|
|
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
|
|
28
|
-
|
|
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
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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(
|
|
57
|
-
|
|
58
|
-
|
|
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
|
|
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.
|
|
173
|
+
if (existingEntry.storageKey === storageKey) return existingEntry.manager;
|
|
106
174
|
existingEntry.manager.stop();
|
|
107
175
|
}
|
|
108
|
-
const
|
|
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(
|
|
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
|
-
|
|
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 };
|