@openclaw/matrix 2026.7.2-beta.7 → 2026.8.1-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{account-selection-kqquRzCf.js → account-selection-CWuhuFn1.js} +7 -8
- package/dist/{accounts-DfngqebB.js → accounts-BCzyubQt.js} +3 -3
- package/dist/api.js +7 -10
- package/dist/{approval-handler.runtime-DSeaIsGa.js → approval-handler.runtime-CJXCUdRg.js} +5 -5
- package/dist/{approval-ids-BdJGPAJT.js → approval-ids-7rf7etWE.js} +1 -1
- package/dist/{approval-reaction-auth-BjOpELxu.js → approval-reaction-auth-wBwbEDpZ.js} +2 -2
- package/dist/{approval-reactions-D-BxBK_L.js → approval-reactions-tXh9KYrW.js} +2 -8
- package/dist/auth-presence.js +2 -2
- package/dist/{channel-vj788dNZ.js → channel-VSrHgTON.js} +156 -136
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-CLoF2S9T.js → channel.runtime-pOOL0uT_.js} +70 -56
- package/dist/{config-schema-Djxw3C6b.js → channel.setup-PpxRP9Du.js} +50 -3
- package/dist/{cli-DMqfDE-q.js → cli-CkTfKC_c.js} +16 -16
- package/dist/{cli-metadata-C7D53SND.js → cli-metadata-B1d1aGM5.js} +1 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/client-CeGw0G5S.js +784 -0
- package/dist/{client-bootstrap-XsIkHNt0.js → client-bootstrap-BFwT_2VT.js} +25 -61
- package/dist/{client-6eRENr7k.js → client-sJesKQmp.js} +4 -4
- package/dist/client-support-DLj4vDeu.js +93 -0
- package/dist/config-update-Bor_Pjsv.js +150 -0
- package/dist/contract-api.js +2 -2
- package/dist/{credentials-W2EmwRhu.js → credentials-BdAaWuiR.js} +2 -1
- package/dist/credentials-read-B37cQknZ.js +51 -0
- package/dist/credentials-state-B3cuUFwZ.js +27 -0
- package/dist/{credentials-write.runtime-Be9zNSUw.js → credentials-write.runtime-nAV2-5uR.js} +1 -1
- package/dist/{crypto-runtime-D9_6J5tZ.js → crypto-runtime-Bnz3zEcS.js} +55 -32
- package/dist/direct-room-RinHjtqX.js +71 -0
- package/dist/{directory-live-C8dVBiCc.js → directory-live-Bvg2wAnR.js} +1 -2
- package/dist/{doctor-CM8ijNpW.js → doctor-EWf9CDso.js} +2 -2
- package/dist/{doctor-contract-BMSJkkAE.js → doctor-contract-DEt4O4Zt.js} +2 -3
- package/dist/doctor-contract-api.js +202 -90
- package/dist/{draft-stream-CtvOXq0Z.js → draft-stream-BRi7PRRS.js} +20 -23
- package/dist/{encryption-guidance-CbEFe38F.js → encryption-guidance-DmLY8NiO.js} +1 -1
- package/dist/{env-auth-CQsYbz-p.js → env-auth-MVS-Vv41.js} +4 -3
- package/dist/{env-vars-B0NxQnPk.js → env-vars-dGqak9dN.js} +1 -1
- package/dist/{errors-C47hvAF8.js → errors-DKVS3_DO.js} +2 -5
- package/dist/{file-sync-store-DiiFsayX.js → file-sync-store-DjskBX2o.js} +24 -3
- package/dist/helper-api.js +2 -2
- package/dist/{idb-persistence-B6x7dMsF.js → idb-persistence-BM0P27Zg.js} +3 -2
- package/dist/{inbound-dedupe-CaBLblef.js → inbound-dedupe-RvSLqdsz.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/{logger-D0GCSDQq.js → logger-B_71hN6W.js} +1 -1
- package/dist/{logging-DV-p52N0.js → logging-DRjvUOIh.js} +1 -1
- package/dist/{media-text-BTwzADS_.js → media-text-JudlYOSc.js} +1 -1
- package/dist/{messages-DxQJkhxs.js → messages-BW0s-6Y9.js} +7 -7
- package/dist/{monitor-VyWlSLwo.js → monitor-Ddfc-vjX.js} +394 -384
- package/dist/plugin-entry.handlers.runtime.js +3 -3
- package/dist/probe.runtime-Dr91B_X3.js +2 -0
- package/dist/profile-D-Wubo0A.js +108 -0
- package/dist/{profile-update-CffmyW_4.js → profile-update-BkgWYDIp.js} +3 -2
- package/dist/{reaction-events-B00WSi98.js → reaction-events-nfUbFLdV.js} +9 -6
- package/dist/{recovery-key-store-BNnHvXdk.js → recovery-key-store-CognuDys.js} +5 -4
- package/dist/{resolve-targets-nm2L48sh.js → resolve-targets-BJAPY4Vb.js} +1 -1
- package/dist/{resolver.runtime-DS6uPaEe.js → resolver.runtime-LWJELYq5.js} +1 -1
- package/dist/{room-info-CAFZ3Z9J.js → room-info-BXQA7y10.js} +12 -3
- package/dist/runtime-api.js +6 -3
- package/dist/{sdk-bUytQHx7.js → sdk-DjaQFCHc.js} +229 -120
- package/dist/{secret-contract-M3hRmGO-.js → secret-contract-CufozuyJ.js} +1 -1
- package/dist/secret-contract-api.js +1 -1
- package/dist/{send-BldGYG8g.js → send-ZDLU4JTk.js} +1462 -1196
- package/dist/session-binding-contract-api.js +1 -1
- package/dist/{setup-bootstrap-Deleiibz.js → setup-bootstrap-BaXkhgJg.js} +4 -4
- package/dist/{setup-core-BVfBv2ai.js → setup-core-DQn6b5vi.js} +17 -266
- package/dist/setup-plugin-api.js +1 -44
- package/dist/{setup-surface-BBq3WeqX.js → setup-surface-DlhJdrNI.js} +9 -11
- package/dist/{startup-verification-wm3_i88s.js → startup-verification-Cs08ca8u.js} +3 -3
- package/dist/{storage-BvAkgzvT.js → storage-BsGuHngK.js} +3 -3
- package/dist/{thread-bindings-DGbl3vDW.js → thread-bindings-CcHZP3w2.js} +7 -4
- package/dist/{tool-actions.runtime-uu9blSqO.js → tool-actions.runtime-DmdRL0bN.js} +35 -18
- package/dist/{verification-DYMQ1QpI.js → verification-C7ig-bQE.js} +2 -2
- package/openclaw.plugin.json +54 -1
- package/package.json +4 -4
- package/dist/active-client-DXvz2gCo.js +0 -20
- package/dist/client-Dbso3-0V.js +0 -30
- package/dist/create-client-BmSU-q-D.js +0 -61
- package/dist/credentials-read-DVmFCm7X.js +0 -77
- package/dist/exec-approval-resolver-BCgqRtZS.js +0 -16
- package/dist/preflight-audio.runtime-BZxxQsxY.js +0 -11
- package/dist/probe.runtime-BuieqmS3.js +0 -3
- package/dist/record-shared-CWWx6fvI.js +0 -2
- package/dist/shared-CUMWxcMz.js +0 -673
- package/dist/sync-state-CWbp0QSY.js +0 -12
- package/dist/{runtime-api-D1xI_cvh.js → runtime-api-BGO16Fu8.js} +3 -3
|
@@ -0,0 +1,784 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
|
|
2
|
+
import { a as resolveMatrixDefaultOrOnlyAccountId, n as requiresExplicitMatrixDefaultAccount, o as resolveMatrixAccountStringValues } from "./account-selection-CWuhuFn1.js";
|
|
3
|
+
import { t as getMatrixScopedEnvVarNames } from "./env-vars-dGqak9dN.js";
|
|
4
|
+
import { o as resolveMatrixBaseConfig, r as listNormalizedMatrixAccountIds, t as findMatrixAccountConfig } from "./account-config-BZWN9tGS.js";
|
|
5
|
+
import { r as resolveScopedMatrixEnvConfig, t as resolveGlobalMatrixEnvConfig } from "./env-auth-MVS-Vv41.js";
|
|
6
|
+
import { t as resolveMatrixConfigFieldPath } from "./config-paths-CnREYb1Y.js";
|
|
7
|
+
import { t as resolveValidatedMatrixHomeserverUrl } from "./url-validation-GRHde6lq.js";
|
|
8
|
+
import { d as writeStorageMeta, l as resolveMatrixStoragePaths, r as maybeMigrateLegacyStorage, s as repairCurrentTokenStorageMetaDeviceId } from "./storage-BsGuHngK.js";
|
|
9
|
+
import { n as LogService } from "./logger-B_71hN6W.js";
|
|
10
|
+
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
11
|
+
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
12
|
+
import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, normalizeAccountId as normalizeAccountId$1, normalizeOptionalAccountId, normalizeOptionalAccountId as normalizeOptionalAccountId$1 } from "openclaw/plugin-sdk/account-id";
|
|
13
|
+
import { coerceSecretRef, normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input-runtime";
|
|
14
|
+
import { formatErrorMessage, toErrorObject, toStringifiedError } from "openclaw/plugin-sdk/error-runtime";
|
|
15
|
+
import { resolveOptionalIntegerOption } from "openclaw/plugin-sdk/number-runtime";
|
|
16
|
+
import { isPrivateNetworkOptInEnabled, ssrfPolicyFromDangerouslyAllowPrivateNetwork, ssrfPolicyFromDangerouslyAllowPrivateNetwork as ssrfPolicyFromDangerouslyAllowPrivateNetwork$1 } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
17
|
+
import fs from "node:fs";
|
|
18
|
+
import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
19
|
+
import { retryAsync } from "openclaw/plugin-sdk/retry-runtime";
|
|
20
|
+
import { sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
|
|
21
|
+
import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
|
|
22
|
+
//#region extensions/matrix/src/matrix/client/config.ts
|
|
23
|
+
const loadMatrixAuthClientDeps = createLazyRuntimeModule(() => Promise.all([import("./sdk-DjaQFCHc.js"), import("./logging-DRjvUOIh.js").then((n) => n.n)]).then(([sdkModule, loggingModule]) => ({
|
|
24
|
+
MatrixClient: sdkModule.MatrixClient,
|
|
25
|
+
ensureMatrixSdkLoggingConfigured: loggingModule.ensureMatrixSdkLoggingConfigured
|
|
26
|
+
})));
|
|
27
|
+
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;
|
|
28
|
+
const loadMatrixCredentialsReadDeps = createLazyRuntimeModule(() => import("./credentials-read-B37cQknZ.js").then((n) => n.r));
|
|
29
|
+
const loadMatrixCredentialsWriteRuntime = createLazyRuntimeModule(() => import("./credentials-write.runtime-nAV2-5uR.js"));
|
|
30
|
+
const loadMatrixSecretInputDeps = createLazyRuntimeModule(() => import("./config-secret-input.runtime-CwsP3--c.js"));
|
|
31
|
+
function shouldRetryMatrixAuthRequest(err) {
|
|
32
|
+
return MATRIX_AUTH_REQUEST_RETRY_RE.test(formatErrorMessage(err));
|
|
33
|
+
}
|
|
34
|
+
function isAbortSignalTriggered(signal) {
|
|
35
|
+
return signal?.aborted === true;
|
|
36
|
+
}
|
|
37
|
+
function credentialsMatchBackfillAuthLineage(params) {
|
|
38
|
+
if (!params.stored) return true;
|
|
39
|
+
return params.stored.homeserver === params.auth.homeserver && params.stored.userId === params.auth.userId && params.stored.accessToken === params.auth.accessToken;
|
|
40
|
+
}
|
|
41
|
+
async function retryMatrixAuthRequest(label, run, signal) {
|
|
42
|
+
return await retryAsync(run, {
|
|
43
|
+
attempts: 3,
|
|
44
|
+
minDelayMs: 250,
|
|
45
|
+
maxDelayMs: 1500,
|
|
46
|
+
jitter: .1,
|
|
47
|
+
label,
|
|
48
|
+
shouldRetry: (err) => shouldRetryMatrixAuthRequest(err),
|
|
49
|
+
sleep: (ms) => sleepWithAbort(ms, signal)
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
async function fetchMatrixWhoamiIdentity(params) {
|
|
53
|
+
const { MatrixClient, ensureMatrixSdkLoggingConfigured } = await loadMatrixAuthClientDeps();
|
|
54
|
+
ensureMatrixSdkLoggingConfigured();
|
|
55
|
+
const tempClient = new MatrixClient(params.homeserver, params.accessToken, {
|
|
56
|
+
userId: params.userId,
|
|
57
|
+
ssrfPolicy: params.ssrfPolicy,
|
|
58
|
+
dispatcherPolicy: params.dispatcherPolicy
|
|
59
|
+
});
|
|
60
|
+
return await retryMatrixAuthRequest("matrix auth whoami", async () => await tempClient.doRequest("GET", "/_matrix/client/v3/account/whoami"), params.signal);
|
|
61
|
+
}
|
|
62
|
+
const MATRIX_CONFIG_STRING_FIELDS = [
|
|
63
|
+
"homeserver",
|
|
64
|
+
"userId",
|
|
65
|
+
"accessToken",
|
|
66
|
+
"password",
|
|
67
|
+
"deviceId",
|
|
68
|
+
"deviceName"
|
|
69
|
+
];
|
|
70
|
+
const MATRIX_AUTH_SECRET_FIELDS = ["accessToken", "password"];
|
|
71
|
+
function readMatrixEnvSecretRef(params) {
|
|
72
|
+
const provider = params.cfg.secrets?.providers?.[params.ref.provider];
|
|
73
|
+
if (provider) {
|
|
74
|
+
if (provider.source !== "env") throw new Error(`Secret provider "${params.ref.provider}" has source "${provider.source}" but ref requests "env".`);
|
|
75
|
+
if (provider.allowlist && !provider.allowlist.includes(params.ref.id)) throw new Error(`Environment variable "${params.ref.id}" is not allowlisted in secrets.providers.${params.ref.provider}.allowlist.`);
|
|
76
|
+
} else if (params.ref.provider !== (params.cfg.secrets?.defaults?.env?.trim() || "default")) throw new Error(`Secret provider "${params.ref.provider}" is not configured (ref: env:${params.ref.provider}:${params.ref.id}).`);
|
|
77
|
+
return params.env[params.ref.id]?.trim() || void 0;
|
|
78
|
+
}
|
|
79
|
+
function readMatrixConfigString(params) {
|
|
80
|
+
const ref = coerceSecretRef(params.value, params.cfg.secrets?.defaults);
|
|
81
|
+
if (params.suppressSecretRef && ref) return "";
|
|
82
|
+
return normalizeResolvedSecretInputString({
|
|
83
|
+
value: params.allowEnvSecretRef ? ref?.source === "env" ? readMatrixEnvSecretRef({
|
|
84
|
+
ref,
|
|
85
|
+
cfg: params.cfg,
|
|
86
|
+
env: params.env
|
|
87
|
+
}) ?? params.value : ref ? "" : params.value : params.value,
|
|
88
|
+
path: params.path,
|
|
89
|
+
defaults: params.cfg.secrets?.defaults
|
|
90
|
+
}) ?? "";
|
|
91
|
+
}
|
|
92
|
+
function resolveMatrixBaseConfigFieldPath(field) {
|
|
93
|
+
return `channels.matrix.${field}`;
|
|
94
|
+
}
|
|
95
|
+
function hasConfiguredMatrixSecret(value, cfg) {
|
|
96
|
+
return typeof value === "string" && value.trim().length > 0 || Boolean(coerceSecretRef(value, cfg.secrets?.defaults));
|
|
97
|
+
}
|
|
98
|
+
async function resolveConfiguredMatrixAuthSecretInput(params) {
|
|
99
|
+
const configured = params.configured;
|
|
100
|
+
if (!configured) return;
|
|
101
|
+
if (!coerceSecretRef(configured.value, params.cfg.secrets?.defaults)) return normalizeResolvedSecretInputString({
|
|
102
|
+
value: configured.value,
|
|
103
|
+
path: configured.path,
|
|
104
|
+
defaults: params.cfg.secrets?.defaults
|
|
105
|
+
});
|
|
106
|
+
const { resolveConfiguredSecretInputString } = await loadMatrixSecretInputDeps();
|
|
107
|
+
const resolved = await resolveConfiguredSecretInputString({
|
|
108
|
+
config: params.cfg,
|
|
109
|
+
env: params.env,
|
|
110
|
+
value: configured.value,
|
|
111
|
+
path: configured.path,
|
|
112
|
+
unresolvedReasonStyle: "detailed"
|
|
113
|
+
});
|
|
114
|
+
if (resolved.value !== void 0) return resolved.value;
|
|
115
|
+
throw new Error(resolved.unresolvedRefReason ?? `${configured.path} SecretRef could not be resolved.`);
|
|
116
|
+
}
|
|
117
|
+
function clampMatrixInitialSyncLimit(value) {
|
|
118
|
+
return resolveOptionalIntegerOption(value, { min: 0 });
|
|
119
|
+
}
|
|
120
|
+
function buildMatrixNetworkFields(params) {
|
|
121
|
+
const dispatcherPolicy = params.dispatcherPolicy ?? (params.proxy ? {
|
|
122
|
+
mode: "explicit-proxy",
|
|
123
|
+
proxyUrl: params.proxy
|
|
124
|
+
} : void 0);
|
|
125
|
+
if (!params.allowPrivateNetwork && !dispatcherPolicy) return {};
|
|
126
|
+
return {
|
|
127
|
+
...params.allowPrivateNetwork ? {
|
|
128
|
+
allowPrivateNetwork: true,
|
|
129
|
+
ssrfPolicy: ssrfPolicyFromDangerouslyAllowPrivateNetwork$1(true)
|
|
130
|
+
} : {},
|
|
131
|
+
...dispatcherPolicy ? { dispatcherPolicy } : {}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function buildResolvedMatrixAuth(resolved, auth) {
|
|
135
|
+
return {
|
|
136
|
+
...auth,
|
|
137
|
+
deviceName: resolved.deviceName,
|
|
138
|
+
initialSyncLimit: resolved.initialSyncLimit,
|
|
139
|
+
encryption: resolved.encryption,
|
|
140
|
+
...buildMatrixNetworkFields({
|
|
141
|
+
allowPrivateNetwork: resolved.allowPrivateNetwork,
|
|
142
|
+
dispatcherPolicy: resolved.dispatcherPolicy
|
|
143
|
+
})
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
function hasScopedMatrixEnvConfig(accountId, env) {
|
|
147
|
+
const scoped = resolveScopedMatrixEnvConfig(accountId, env);
|
|
148
|
+
return Boolean(scoped.homeserver || scoped.userId || scoped.accessToken || scoped.password || scoped.deviceId || scoped.deviceName);
|
|
149
|
+
}
|
|
150
|
+
function readMatrixConfigStrings(params) {
|
|
151
|
+
return Object.fromEntries(MATRIX_CONFIG_STRING_FIELDS.map((field) => [field, readMatrixConfigString({
|
|
152
|
+
value: params.values[field],
|
|
153
|
+
path: params.path(field),
|
|
154
|
+
cfg: params.cfg,
|
|
155
|
+
env: params.env,
|
|
156
|
+
allowEnvSecretRef: MATRIX_AUTH_SECRET_FIELDS.includes(field),
|
|
157
|
+
suppressSecretRef: field === "password" && params.suppressPasswordSecretRef
|
|
158
|
+
})]));
|
|
159
|
+
}
|
|
160
|
+
function resolveMatrixAccountConfigSnapshot(cfg, accountId, env) {
|
|
161
|
+
const normalizedAccountId = normalizeAccountId$1(accountId);
|
|
162
|
+
const matrix = resolveMatrixBaseConfig(cfg);
|
|
163
|
+
const account = findMatrixAccountConfig(cfg, normalizedAccountId) ?? {};
|
|
164
|
+
const scopedKeys = getMatrixScopedEnvVarNames(normalizedAccountId);
|
|
165
|
+
const scopedEnv = resolveScopedMatrixEnvConfig(normalizedAccountId, env);
|
|
166
|
+
const globalEnv = resolveGlobalMatrixEnvConfig(env);
|
|
167
|
+
const authCandidates = (field) => [
|
|
168
|
+
{
|
|
169
|
+
value: account[field],
|
|
170
|
+
path: resolveMatrixConfigFieldPath(cfg, accountId, field)
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
value: scopedEnv[field],
|
|
174
|
+
path: scopedKeys[field]
|
|
175
|
+
},
|
|
176
|
+
...normalizedAccountId === DEFAULT_ACCOUNT_ID$1 ? [{
|
|
177
|
+
value: matrix[field],
|
|
178
|
+
path: resolveMatrixBaseConfigFieldPath(field)
|
|
179
|
+
}, {
|
|
180
|
+
value: globalEnv[field],
|
|
181
|
+
path: field === "accessToken" ? "MATRIX_ACCESS_TOKEN" : "MATRIX_PASSWORD"
|
|
182
|
+
}] : []
|
|
183
|
+
];
|
|
184
|
+
const accessTokenCandidates = authCandidates("accessToken");
|
|
185
|
+
const passwordCandidates = authCandidates("password");
|
|
186
|
+
const suppressPasswordSecretRef = accessTokenCandidates.some((source) => hasConfiguredMatrixSecret(source.value, cfg));
|
|
187
|
+
const resolvedStrings = resolveMatrixAccountStringValues({
|
|
188
|
+
accountId: normalizedAccountId,
|
|
189
|
+
account: readMatrixConfigStrings({
|
|
190
|
+
cfg,
|
|
191
|
+
env,
|
|
192
|
+
values: account,
|
|
193
|
+
path: (field) => resolveMatrixConfigFieldPath(cfg, normalizedAccountId, field),
|
|
194
|
+
suppressPasswordSecretRef
|
|
195
|
+
}),
|
|
196
|
+
scopedEnv,
|
|
197
|
+
channel: readMatrixConfigStrings({
|
|
198
|
+
cfg,
|
|
199
|
+
env,
|
|
200
|
+
values: matrix,
|
|
201
|
+
path: resolveMatrixBaseConfigFieldPath,
|
|
202
|
+
suppressPasswordSecretRef
|
|
203
|
+
}),
|
|
204
|
+
globalEnv
|
|
205
|
+
});
|
|
206
|
+
const accountInitialSyncLimit = clampMatrixInitialSyncLimit(account.initialSyncLimit);
|
|
207
|
+
const allowPrivateNetwork = isPrivateNetworkOptInEnabled(account) || isPrivateNetworkOptInEnabled(matrix) ? true : void 0;
|
|
208
|
+
return {
|
|
209
|
+
resolved: {
|
|
210
|
+
homeserver: resolvedStrings.homeserver,
|
|
211
|
+
userId: resolvedStrings.userId,
|
|
212
|
+
accessToken: resolvedStrings.accessToken || void 0,
|
|
213
|
+
password: resolvedStrings.password || void 0,
|
|
214
|
+
deviceId: resolvedStrings.deviceId || void 0,
|
|
215
|
+
deviceName: resolvedStrings.deviceName || void 0,
|
|
216
|
+
initialSyncLimit: accountInitialSyncLimit ?? clampMatrixInitialSyncLimit(matrix.initialSyncLimit),
|
|
217
|
+
encryption: typeof account.encryption === "boolean" ? account.encryption : matrix.encryption ?? false,
|
|
218
|
+
...buildMatrixNetworkFields({
|
|
219
|
+
allowPrivateNetwork,
|
|
220
|
+
proxy: account.proxy ?? matrix.proxy
|
|
221
|
+
})
|
|
222
|
+
},
|
|
223
|
+
authInputs: {
|
|
224
|
+
accessToken: accessTokenCandidates.find((source) => source.value !== void 0),
|
|
225
|
+
password: passwordCandidates.find((source) => source.value !== void 0)
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
function resolveImplicitMatrixAccountId(cfg, env = process.env) {
|
|
230
|
+
if (requiresExplicitMatrixDefaultAccount(cfg, env)) return null;
|
|
231
|
+
return normalizeAccountId$1(resolveMatrixDefaultOrOnlyAccountId(cfg, env));
|
|
232
|
+
}
|
|
233
|
+
function resolveMatrixAuthState(params) {
|
|
234
|
+
const cfg = requireRuntimeConfig(params.cfg, "Matrix auth context");
|
|
235
|
+
const env = params?.env ?? process.env;
|
|
236
|
+
const requestedAccountId = params?.accountId?.trim();
|
|
237
|
+
const explicitAccountId = normalizeOptionalAccountId$1(params?.accountId);
|
|
238
|
+
if (requestedAccountId && !explicitAccountId) throw new Error(`Matrix account id "${requestedAccountId}" is invalid.`);
|
|
239
|
+
const effectiveAccountId = explicitAccountId ?? resolveImplicitMatrixAccountId(cfg, env);
|
|
240
|
+
if (!effectiveAccountId) throw new Error("Multiple Matrix accounts are configured and channels.matrix.defaultAccount is not set. Set \"channels.matrix.defaultAccount\" to the intended account or pass --account <id>.");
|
|
241
|
+
if (explicitAccountId && explicitAccountId !== DEFAULT_ACCOUNT_ID$1 && !listNormalizedMatrixAccountIds(cfg).includes(explicitAccountId) && !hasScopedMatrixEnvConfig(explicitAccountId, env)) throw new Error(`Matrix account "${explicitAccountId}" is not configured. Add channels.matrix.accounts.${explicitAccountId} or define scoped ${getMatrixScopedEnvVarNames(explicitAccountId).accessToken.replace(/_ACCESS_TOKEN$/, "")}_* variables.`);
|
|
242
|
+
const matrix = resolveMatrixBaseConfig(cfg);
|
|
243
|
+
const account = findMatrixAccountConfig(cfg, effectiveAccountId);
|
|
244
|
+
if (matrix.enabled === false || account?.enabled === false) throw new Error(`Matrix account "${effectiveAccountId}" is disabled.`);
|
|
245
|
+
const snapshot = resolveMatrixAccountConfigSnapshot(cfg, effectiveAccountId, env);
|
|
246
|
+
return {
|
|
247
|
+
context: {
|
|
248
|
+
cfg,
|
|
249
|
+
env,
|
|
250
|
+
accountId: effectiveAccountId,
|
|
251
|
+
resolved: snapshot.resolved
|
|
252
|
+
},
|
|
253
|
+
authInputs: snapshot.authInputs
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
function resolveMatrixAuthContext(params) {
|
|
257
|
+
return resolveMatrixAuthState(params).context;
|
|
258
|
+
}
|
|
259
|
+
async function resolveMatrixAuth(params) {
|
|
260
|
+
if (!params?.cfg) throw new Error("Matrix auth requires a resolved runtime config. Load and resolve config at the command or gateway boundary, then pass cfg through the runtime path.");
|
|
261
|
+
const { context, authInputs } = resolveMatrixAuthState({
|
|
262
|
+
cfg: params.cfg,
|
|
263
|
+
env: params.env,
|
|
264
|
+
accountId: params.accountId
|
|
265
|
+
});
|
|
266
|
+
const { cfg, env, accountId, resolved } = context;
|
|
267
|
+
const accessToken = await resolveConfiguredMatrixAuthSecretInput({
|
|
268
|
+
cfg,
|
|
269
|
+
env,
|
|
270
|
+
configured: authInputs.accessToken
|
|
271
|
+
}) ?? resolved.accessToken;
|
|
272
|
+
const tokenAuthPassword = resolved.password;
|
|
273
|
+
const homeserver = await resolveValidatedMatrixHomeserverUrl(resolved.homeserver, { dangerouslyAllowPrivateNetwork: resolved.allowPrivateNetwork });
|
|
274
|
+
const { loadMatrixCredentials, credentialsMatchConfig } = await loadMatrixCredentialsReadDeps();
|
|
275
|
+
const cached = loadMatrixCredentials(env, accountId);
|
|
276
|
+
const cachedCredentials = cached && credentialsMatchConfig(cached, {
|
|
277
|
+
homeserver,
|
|
278
|
+
userId: resolved.userId || "",
|
|
279
|
+
accessToken
|
|
280
|
+
}) ? cached : null;
|
|
281
|
+
if (accessToken) {
|
|
282
|
+
let userId = resolved.userId;
|
|
283
|
+
const hasMatchingCachedToken = cachedCredentials?.accessToken === accessToken;
|
|
284
|
+
let knownDeviceId = hasMatchingCachedToken ? cachedCredentials?.deviceId || resolved.deviceId : resolved.deviceId;
|
|
285
|
+
if (!userId) {
|
|
286
|
+
const whoami = await fetchMatrixWhoamiIdentity({
|
|
287
|
+
homeserver,
|
|
288
|
+
accessToken,
|
|
289
|
+
userId,
|
|
290
|
+
ssrfPolicy: resolved.ssrfPolicy,
|
|
291
|
+
dispatcherPolicy: resolved.dispatcherPolicy
|
|
292
|
+
});
|
|
293
|
+
const fetchedUserId = whoami.user_id?.trim();
|
|
294
|
+
if (!fetchedUserId) throw new Error("Matrix whoami did not return user_id");
|
|
295
|
+
userId = fetchedUserId;
|
|
296
|
+
knownDeviceId = knownDeviceId || whoami.device_id?.trim() || resolved.deviceId;
|
|
297
|
+
}
|
|
298
|
+
if (!cachedCredentials || !hasMatchingCachedToken || cachedCredentials.userId !== userId || (cachedCredentials.deviceId || void 0) !== knownDeviceId) {
|
|
299
|
+
const { saveMatrixCredentials } = await loadMatrixCredentialsWriteRuntime();
|
|
300
|
+
await saveMatrixCredentials({
|
|
301
|
+
homeserver,
|
|
302
|
+
userId,
|
|
303
|
+
accessToken,
|
|
304
|
+
deviceId: knownDeviceId
|
|
305
|
+
}, env, accountId);
|
|
306
|
+
} else if (hasMatchingCachedToken) {
|
|
307
|
+
const { touchMatrixCredentials } = await loadMatrixCredentialsWriteRuntime();
|
|
308
|
+
await touchMatrixCredentials(env, accountId);
|
|
309
|
+
}
|
|
310
|
+
return buildResolvedMatrixAuth(resolved, {
|
|
311
|
+
accountId,
|
|
312
|
+
homeserver,
|
|
313
|
+
userId,
|
|
314
|
+
accessToken,
|
|
315
|
+
password: tokenAuthPassword,
|
|
316
|
+
deviceId: knownDeviceId
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
if (cachedCredentials) {
|
|
320
|
+
const { touchMatrixCredentials } = await loadMatrixCredentialsWriteRuntime();
|
|
321
|
+
await touchMatrixCredentials(env, accountId);
|
|
322
|
+
return buildResolvedMatrixAuth(resolved, {
|
|
323
|
+
accountId,
|
|
324
|
+
homeserver: cachedCredentials.homeserver,
|
|
325
|
+
userId: cachedCredentials.userId,
|
|
326
|
+
accessToken: cachedCredentials.accessToken,
|
|
327
|
+
password: tokenAuthPassword,
|
|
328
|
+
deviceId: cachedCredentials.deviceId || resolved.deviceId
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
if (!resolved.userId) throw new Error("Matrix userId is required when no access token is configured (matrix.userId)");
|
|
332
|
+
const password = await resolveConfiguredMatrixAuthSecretInput({
|
|
333
|
+
cfg,
|
|
334
|
+
env,
|
|
335
|
+
configured: authInputs.password
|
|
336
|
+
}) ?? resolved.password;
|
|
337
|
+
if (!password) throw new Error("Matrix password is required when no access token is configured (matrix.password)");
|
|
338
|
+
const { MatrixClient, ensureMatrixSdkLoggingConfigured } = await loadMatrixAuthClientDeps();
|
|
339
|
+
ensureMatrixSdkLoggingConfigured();
|
|
340
|
+
const loginClient = new MatrixClient(homeserver, "", {
|
|
341
|
+
ssrfPolicy: resolved.ssrfPolicy,
|
|
342
|
+
dispatcherPolicy: resolved.dispatcherPolicy
|
|
343
|
+
});
|
|
344
|
+
const login = await retryMatrixAuthRequest("matrix auth login", async () => await loginClient.doRequest("POST", "/_matrix/client/v3/login", void 0, {
|
|
345
|
+
type: "m.login.password",
|
|
346
|
+
identifier: {
|
|
347
|
+
type: "m.id.user",
|
|
348
|
+
user: resolved.userId
|
|
349
|
+
},
|
|
350
|
+
password,
|
|
351
|
+
device_id: resolved.deviceId,
|
|
352
|
+
initial_device_display_name: resolved.deviceName ?? "OpenClaw Gateway"
|
|
353
|
+
}));
|
|
354
|
+
const loginAccessToken = login.access_token?.trim();
|
|
355
|
+
if (!loginAccessToken) throw new Error("Matrix login did not return an access token");
|
|
356
|
+
const auth = buildResolvedMatrixAuth(resolved, {
|
|
357
|
+
accountId,
|
|
358
|
+
homeserver,
|
|
359
|
+
userId: login.user_id ?? resolved.userId,
|
|
360
|
+
accessToken: loginAccessToken,
|
|
361
|
+
password,
|
|
362
|
+
deviceId: login.device_id ?? resolved.deviceId
|
|
363
|
+
});
|
|
364
|
+
const { saveMatrixCredentials } = await loadMatrixCredentialsWriteRuntime();
|
|
365
|
+
await saveMatrixCredentials({
|
|
366
|
+
homeserver: auth.homeserver,
|
|
367
|
+
userId: auth.userId,
|
|
368
|
+
accessToken: auth.accessToken,
|
|
369
|
+
deviceId: auth.deviceId
|
|
370
|
+
}, env, accountId);
|
|
371
|
+
return auth;
|
|
372
|
+
}
|
|
373
|
+
async function backfillMatrixAuthDeviceIdAfterStartup(params) {
|
|
374
|
+
const knownDeviceId = params.auth.deviceId?.trim();
|
|
375
|
+
if (knownDeviceId) return knownDeviceId;
|
|
376
|
+
if (isAbortSignalTriggered(params.abortSignal)) return;
|
|
377
|
+
let whoami;
|
|
378
|
+
try {
|
|
379
|
+
whoami = await fetchMatrixWhoamiIdentity({
|
|
380
|
+
homeserver: params.auth.homeserver,
|
|
381
|
+
accessToken: params.auth.accessToken,
|
|
382
|
+
userId: params.auth.userId,
|
|
383
|
+
ssrfPolicy: params.auth.ssrfPolicy,
|
|
384
|
+
dispatcherPolicy: params.auth.dispatcherPolicy,
|
|
385
|
+
signal: params.abortSignal
|
|
386
|
+
});
|
|
387
|
+
} catch (err) {
|
|
388
|
+
if (isAbortSignalTriggered(params.abortSignal)) return;
|
|
389
|
+
throw err;
|
|
390
|
+
}
|
|
391
|
+
const deviceId = whoami.device_id?.trim();
|
|
392
|
+
if (!deviceId) return;
|
|
393
|
+
if (isAbortSignalTriggered(params.abortSignal)) return;
|
|
394
|
+
const env = params.env ?? process.env;
|
|
395
|
+
const { loadMatrixCredentials } = await loadMatrixCredentialsReadDeps();
|
|
396
|
+
if (!credentialsMatchBackfillAuthLineage({
|
|
397
|
+
stored: loadMatrixCredentials(env, params.auth.accountId),
|
|
398
|
+
auth: params.auth
|
|
399
|
+
})) return;
|
|
400
|
+
if (!repairCurrentTokenStorageMetaDeviceId({
|
|
401
|
+
homeserver: params.auth.homeserver,
|
|
402
|
+
userId: params.auth.userId,
|
|
403
|
+
accessToken: params.auth.accessToken,
|
|
404
|
+
accountId: params.auth.accountId,
|
|
405
|
+
deviceId,
|
|
406
|
+
env: params.env
|
|
407
|
+
})) throw new Error("Matrix deviceId backfill failed to repair current-token storage metadata");
|
|
408
|
+
if (isAbortSignalTriggered(params.abortSignal)) return;
|
|
409
|
+
return await (await loadMatrixCredentialsWriteRuntime()).saveBackfilledMatrixDeviceId({
|
|
410
|
+
homeserver: params.auth.homeserver,
|
|
411
|
+
userId: params.auth.userId,
|
|
412
|
+
accessToken: params.auth.accessToken,
|
|
413
|
+
deviceId
|
|
414
|
+
}, env, params.auth.accountId) === "saved" ? deviceId : void 0;
|
|
415
|
+
}
|
|
416
|
+
//#endregion
|
|
417
|
+
//#region extensions/matrix/src/matrix/client/create-client.ts
|
|
418
|
+
var create_client_exports = /* @__PURE__ */ __exportAll({ createMatrixClient: () => createMatrixClient });
|
|
419
|
+
const loadMatrixCreateClientRuntimeDeps = createLazyRuntimeModule(() => Promise.all([import("./sdk-DjaQFCHc.js"), import("./logging-DRjvUOIh.js").then((n) => n.n)]).then(([sdkModule, loggingModule]) => ({
|
|
420
|
+
MatrixClient: sdkModule.MatrixClient,
|
|
421
|
+
ensureMatrixSdkLoggingConfigured: loggingModule.ensureMatrixSdkLoggingConfigured
|
|
422
|
+
})));
|
|
423
|
+
async function createMatrixClient(params) {
|
|
424
|
+
const { MatrixClient, ensureMatrixSdkLoggingConfigured } = await loadMatrixCreateClientRuntimeDeps();
|
|
425
|
+
ensureMatrixSdkLoggingConfigured();
|
|
426
|
+
const homeserver = await resolveValidatedMatrixHomeserverUrl(params.homeserver, { dangerouslyAllowPrivateNetwork: params.allowPrivateNetwork });
|
|
427
|
+
const matrixClientUserId = normalizeOptionalString(params.userId);
|
|
428
|
+
const userId = matrixClientUserId ?? "unknown";
|
|
429
|
+
const storagePaths = params.persistStorage !== false ? resolveMatrixStoragePaths({
|
|
430
|
+
homeserver,
|
|
431
|
+
userId,
|
|
432
|
+
accessToken: params.accessToken,
|
|
433
|
+
accountId: params.accountId,
|
|
434
|
+
deviceId: params.deviceId,
|
|
435
|
+
env: process.env
|
|
436
|
+
}) : null;
|
|
437
|
+
if (storagePaths) {
|
|
438
|
+
await maybeMigrateLegacyStorage({
|
|
439
|
+
storagePaths,
|
|
440
|
+
env: process.env
|
|
441
|
+
});
|
|
442
|
+
fs.mkdirSync(storagePaths.rootDir, { recursive: true });
|
|
443
|
+
writeStorageMeta({
|
|
444
|
+
storagePaths,
|
|
445
|
+
homeserver,
|
|
446
|
+
userId,
|
|
447
|
+
accountId: params.accountId,
|
|
448
|
+
deviceId: params.deviceId
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
const cryptoDatabasePrefix = storagePaths ? `openclaw-matrix-${storagePaths.accountKey}-${storagePaths.tokenHash}` : void 0;
|
|
452
|
+
return new MatrixClient(homeserver, params.accessToken, {
|
|
453
|
+
userId: matrixClientUserId,
|
|
454
|
+
password: params.password,
|
|
455
|
+
deviceId: params.deviceId,
|
|
456
|
+
encryption: params.encryption,
|
|
457
|
+
localTimeoutMs: params.localTimeoutMs,
|
|
458
|
+
initialSyncLimit: params.initialSyncLimit,
|
|
459
|
+
storageRootDir: storagePaths?.rootDir,
|
|
460
|
+
recoveryKeyPath: storagePaths?.recoveryKeyPath,
|
|
461
|
+
idbSnapshotPath: storagePaths?.idbSnapshotPath,
|
|
462
|
+
cryptoDatabasePrefix,
|
|
463
|
+
autoBootstrapCrypto: params.autoBootstrapCrypto,
|
|
464
|
+
ssrfPolicy: params.ssrfPolicy ?? ssrfPolicyFromDangerouslyAllowPrivateNetwork(params.allowPrivateNetwork),
|
|
465
|
+
dispatcherPolicy: params.dispatcherPolicy
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
//#endregion
|
|
469
|
+
//#region extensions/matrix/src/matrix/startup-abort.ts
|
|
470
|
+
function createMatrixStartupAbortError() {
|
|
471
|
+
const error = /* @__PURE__ */ new Error("Matrix startup aborted");
|
|
472
|
+
error.name = "AbortError";
|
|
473
|
+
return error;
|
|
474
|
+
}
|
|
475
|
+
function throwIfMatrixStartupAborted(abortSignal) {
|
|
476
|
+
if (abortSignal?.aborted === true) throw createMatrixStartupAbortError();
|
|
477
|
+
}
|
|
478
|
+
function isMatrixStartupAbortError(error) {
|
|
479
|
+
return error instanceof Error && error.name === "AbortError";
|
|
480
|
+
}
|
|
481
|
+
async function awaitMatrixStartupWithAbort(promise, abortSignal) {
|
|
482
|
+
if (!abortSignal) return await promise;
|
|
483
|
+
if (abortSignal.aborted) throw createMatrixStartupAbortError();
|
|
484
|
+
return await new Promise((resolve, reject) => {
|
|
485
|
+
const onAbort = () => {
|
|
486
|
+
abortSignal.removeEventListener("abort", onAbort);
|
|
487
|
+
reject(createMatrixStartupAbortError());
|
|
488
|
+
};
|
|
489
|
+
abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
490
|
+
promise.then((value) => {
|
|
491
|
+
abortSignal.removeEventListener("abort", onAbort);
|
|
492
|
+
resolve(value);
|
|
493
|
+
}, (error) => {
|
|
494
|
+
abortSignal.removeEventListener("abort", onAbort);
|
|
495
|
+
reject(toErrorObject(error, "Non-Error rejection"));
|
|
496
|
+
});
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
//#endregion
|
|
500
|
+
//#region extensions/matrix/src/matrix/client/shared.ts
|
|
501
|
+
const loadMatrixCreateClientDeps = createLazyRuntimeModule(() => Promise.resolve().then(() => create_client_exports).then((runtime) => ({ createMatrixClient: runtime.createMatrixClient })));
|
|
502
|
+
const MATRIX_TRANSIENT_LEASE_DRAIN_TIMEOUT_MS = 5e3;
|
|
503
|
+
const sharedClientStates = /* @__PURE__ */ new Map();
|
|
504
|
+
const sharedClientPromises = /* @__PURE__ */ new Map();
|
|
505
|
+
function buildSharedClientKey(auth) {
|
|
506
|
+
return JSON.stringify([
|
|
507
|
+
auth.homeserver,
|
|
508
|
+
auth.userId,
|
|
509
|
+
auth.accessToken,
|
|
510
|
+
auth.encryption ? "e2ee" : "plain",
|
|
511
|
+
auth.allowPrivateNetwork ? "private-net" : "strict-net",
|
|
512
|
+
auth.dispatcherPolicy ?? null,
|
|
513
|
+
auth.accountId
|
|
514
|
+
]);
|
|
515
|
+
}
|
|
516
|
+
async function createSharedMatrixClient(params) {
|
|
517
|
+
const { createMatrixClient } = await loadMatrixCreateClientDeps();
|
|
518
|
+
const client = await createMatrixClient({
|
|
519
|
+
homeserver: params.auth.homeserver,
|
|
520
|
+
userId: params.auth.userId,
|
|
521
|
+
accessToken: params.auth.accessToken,
|
|
522
|
+
password: params.auth.password,
|
|
523
|
+
deviceId: params.auth.deviceId,
|
|
524
|
+
encryption: params.auth.encryption,
|
|
525
|
+
localTimeoutMs: params.timeoutMs,
|
|
526
|
+
initialSyncLimit: params.auth.initialSyncLimit,
|
|
527
|
+
accountId: params.auth.accountId,
|
|
528
|
+
allowPrivateNetwork: params.auth.allowPrivateNetwork,
|
|
529
|
+
ssrfPolicy: params.auth.ssrfPolicy,
|
|
530
|
+
dispatcherPolicy: params.auth.dispatcherPolicy
|
|
531
|
+
});
|
|
532
|
+
return {
|
|
533
|
+
auth: params.auth,
|
|
534
|
+
client,
|
|
535
|
+
key: buildSharedClientKey(params.auth),
|
|
536
|
+
started: false,
|
|
537
|
+
cryptoReady: false,
|
|
538
|
+
startPromise: null,
|
|
539
|
+
phase: "open",
|
|
540
|
+
leases: /* @__PURE__ */ new Set(),
|
|
541
|
+
monitorRetirementPromises: /* @__PURE__ */ new Set(),
|
|
542
|
+
noLeases: createDeferred(),
|
|
543
|
+
retirementPromise: null,
|
|
544
|
+
poisonError: null,
|
|
545
|
+
releaseMode: "discard"
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
function deleteSharedClientState(state) {
|
|
549
|
+
if (sharedClientStates.get(state.key) === state) sharedClientStates.delete(state.key);
|
|
550
|
+
sharedClientPromises.delete(state.key);
|
|
551
|
+
}
|
|
552
|
+
async function ensureSharedClientStarted(state, abortSignal) {
|
|
553
|
+
if (state.started) return;
|
|
554
|
+
if (state.startPromise) {
|
|
555
|
+
await awaitMatrixStartupWithAbort(state.startPromise, abortSignal);
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
const guardedStart = (async () => {
|
|
559
|
+
if (state.auth.encryption && !state.cryptoReady) try {
|
|
560
|
+
const joinedRooms = await state.client.getJoinedRooms();
|
|
561
|
+
if (state.client.crypto) {
|
|
562
|
+
await state.client.crypto.prepare(joinedRooms);
|
|
563
|
+
state.cryptoReady = true;
|
|
564
|
+
}
|
|
565
|
+
} catch (err) {
|
|
566
|
+
LogService.warn("MatrixClientLite", "Failed to prepare crypto:", err);
|
|
567
|
+
}
|
|
568
|
+
await awaitMatrixStartupWithAbort(state.client.start({ abortSignal }), abortSignal);
|
|
569
|
+
state.started = true;
|
|
570
|
+
})().finally(() => {
|
|
571
|
+
if (state.startPromise === guardedStart) state.startPromise = null;
|
|
572
|
+
});
|
|
573
|
+
state.startPromise = guardedStart;
|
|
574
|
+
await awaitMatrixStartupWithAbort(guardedStart, abortSignal);
|
|
575
|
+
}
|
|
576
|
+
async function resolveSharedMatrixAuth(params) {
|
|
577
|
+
const requestedAccountId = normalizeOptionalAccountId(params.accountId);
|
|
578
|
+
if (params.auth && requestedAccountId && requestedAccountId !== params.auth.accountId) throw new Error(`Matrix shared client account mismatch: requested ${requestedAccountId}, auth resolved ${params.auth.accountId}`);
|
|
579
|
+
if (params.auth) return params.auth;
|
|
580
|
+
if (!params.cfg) throw new Error("Matrix shared client requires a resolved runtime config. Load and resolve config at the command or gateway boundary, then pass cfg through the runtime path.");
|
|
581
|
+
const authContext = resolveMatrixAuthContext({
|
|
582
|
+
cfg: params.cfg,
|
|
583
|
+
env: params.env,
|
|
584
|
+
accountId: params.accountId
|
|
585
|
+
});
|
|
586
|
+
return await resolveMatrixAuth({
|
|
587
|
+
cfg: authContext.cfg,
|
|
588
|
+
env: authContext.env,
|
|
589
|
+
accountId: authContext.accountId
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
async function resolveOpenSharedMatrixClientState(params) {
|
|
593
|
+
const auth = await resolveSharedMatrixAuth(params);
|
|
594
|
+
const key = buildSharedClientKey(auth);
|
|
595
|
+
while (true) {
|
|
596
|
+
const existing = sharedClientStates.get(key);
|
|
597
|
+
if (existing?.poisonError) throw existing.poisonError;
|
|
598
|
+
if (existing?.phase === "open") return existing;
|
|
599
|
+
if (existing?.retirementPromise) {
|
|
600
|
+
await awaitMatrixStartupWithAbort(existing.retirementPromise, params.abortSignal);
|
|
601
|
+
continue;
|
|
602
|
+
}
|
|
603
|
+
const pending = sharedClientPromises.get(key);
|
|
604
|
+
if (pending) {
|
|
605
|
+
await awaitMatrixStartupWithAbort(pending, params.abortSignal);
|
|
606
|
+
continue;
|
|
607
|
+
}
|
|
608
|
+
const creationPromise = createSharedMatrixClient({
|
|
609
|
+
auth,
|
|
610
|
+
timeoutMs: params.timeoutMs
|
|
611
|
+
});
|
|
612
|
+
sharedClientPromises.set(key, creationPromise);
|
|
613
|
+
try {
|
|
614
|
+
const created = await creationPromise;
|
|
615
|
+
sharedClientStates.set(key, created);
|
|
616
|
+
return created;
|
|
617
|
+
} finally {
|
|
618
|
+
sharedClientPromises.delete(key);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
async function runMonitorRetirement(retirement) {
|
|
623
|
+
if (!retirement) return;
|
|
624
|
+
retirement.closeTaskAdmission();
|
|
625
|
+
retirement.detachListeners();
|
|
626
|
+
await retirement.waitForTasks();
|
|
627
|
+
await retirement.cleanup();
|
|
628
|
+
}
|
|
629
|
+
function retireMonitorLease(state, lease) {
|
|
630
|
+
if (lease.monitorRetirementPromise) return lease.monitorRetirementPromise;
|
|
631
|
+
lease.monitorRetirementPromise = runMonitorRetirement(lease.monitorRetirement ?? void 0);
|
|
632
|
+
state.monitorRetirementPromises.add(lease.monitorRetirementPromise);
|
|
633
|
+
return lease.monitorRetirementPromise;
|
|
634
|
+
}
|
|
635
|
+
async function retireMonitorLeases(state, leases) {
|
|
636
|
+
for (const lease of leases) retireMonitorLease(state, lease);
|
|
637
|
+
const failure = (await Promise.allSettled(state.monitorRetirementPromises)).find((result) => result.status === "rejected");
|
|
638
|
+
if (failure?.status === "rejected") throw failure.reason;
|
|
639
|
+
}
|
|
640
|
+
function mergeReleaseMode(current, requested) {
|
|
641
|
+
if (current === "persist" || requested === "persist") return "persist";
|
|
642
|
+
if (current === "stop" || requested === "stop") return "stop";
|
|
643
|
+
return "discard";
|
|
644
|
+
}
|
|
645
|
+
function abortTransientLeases(state) {
|
|
646
|
+
for (const lease of state.leases) if (lease.role === "transient") lease.abortController.abort();
|
|
647
|
+
}
|
|
648
|
+
function forceReleaseLeases(state, releasePromise = Promise.resolve()) {
|
|
649
|
+
for (const lease of state.leases) {
|
|
650
|
+
lease.abortController.abort();
|
|
651
|
+
lease.releasePromise ??= releasePromise;
|
|
652
|
+
}
|
|
653
|
+
state.leases.clear();
|
|
654
|
+
state.noLeases.resolve();
|
|
655
|
+
}
|
|
656
|
+
async function waitForLeaseDrain(state) {
|
|
657
|
+
if (state.leases.size === 0) return;
|
|
658
|
+
let deadline;
|
|
659
|
+
try {
|
|
660
|
+
await Promise.race([state.noLeases.promise, new Promise((_, reject) => {
|
|
661
|
+
deadline = setTimeout(() => {
|
|
662
|
+
reject(/* @__PURE__ */ new Error(`Matrix transient leases did not drain within ${MATRIX_TRANSIENT_LEASE_DRAIN_TIMEOUT_MS}ms`));
|
|
663
|
+
}, MATRIX_TRANSIENT_LEASE_DRAIN_TIMEOUT_MS);
|
|
664
|
+
deadline.unref?.();
|
|
665
|
+
})]);
|
|
666
|
+
} finally {
|
|
667
|
+
if (deadline) clearTimeout(deadline);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
function beginGenerationRetirement(params) {
|
|
671
|
+
const { state } = params;
|
|
672
|
+
if (state.retirementPromise) return state.retirementPromise;
|
|
673
|
+
state.phase = "quiescing";
|
|
674
|
+
state.retirementPromise = Promise.resolve().then(async () => {
|
|
675
|
+
try {
|
|
676
|
+
await state.client.quiesceSync();
|
|
677
|
+
state.started = false;
|
|
678
|
+
await state.client.drainPendingDecryptions("matrix monitor sync quiesce");
|
|
679
|
+
} catch (error) {
|
|
680
|
+
state.poisonError = toStringifiedError(error);
|
|
681
|
+
}
|
|
682
|
+
try {
|
|
683
|
+
await retireMonitorLeases(state, params.monitorLeases ?? []);
|
|
684
|
+
} catch (error) {
|
|
685
|
+
state.poisonError ??= toStringifiedError(error);
|
|
686
|
+
}
|
|
687
|
+
state.phase = "closing";
|
|
688
|
+
try {
|
|
689
|
+
await waitForLeaseDrain(state);
|
|
690
|
+
} catch (error) {
|
|
691
|
+
state.poisonError ??= toStringifiedError(error);
|
|
692
|
+
forceReleaseLeases(state);
|
|
693
|
+
}
|
|
694
|
+
if (state.poisonError) {
|
|
695
|
+
await state.client.drainPendingDecryptions("matrix poisoned client shutdown").catch(() => void 0);
|
|
696
|
+
state.client.stopWithoutPersist();
|
|
697
|
+
throw state.poisonError;
|
|
698
|
+
}
|
|
699
|
+
try {
|
|
700
|
+
await state.client.drainPendingDecryptions("matrix shared client final shutdown");
|
|
701
|
+
} catch (error) {
|
|
702
|
+
state.poisonError = toStringifiedError(error);
|
|
703
|
+
try {
|
|
704
|
+
state.client.stopWithoutPersist();
|
|
705
|
+
} finally {
|
|
706
|
+
deleteSharedClientState(state);
|
|
707
|
+
}
|
|
708
|
+
throw state.poisonError;
|
|
709
|
+
}
|
|
710
|
+
try {
|
|
711
|
+
if (state.releaseMode === "persist") await state.client.stopAndPersist();
|
|
712
|
+
else if (state.releaseMode === "discard") state.client.stopWithoutPersist();
|
|
713
|
+
else await state.client.stopAndPersist().catch(() => state.client.stopWithoutPersist());
|
|
714
|
+
} finally {
|
|
715
|
+
deleteSharedClientState(state);
|
|
716
|
+
}
|
|
717
|
+
});
|
|
718
|
+
abortTransientLeases(state);
|
|
719
|
+
return state.retirementPromise;
|
|
720
|
+
}
|
|
721
|
+
function createSharedMatrixClientLease(state, role) {
|
|
722
|
+
const leaseState = {
|
|
723
|
+
abortController: new AbortController(),
|
|
724
|
+
monitorRetirement: null,
|
|
725
|
+
monitorRetirementPromise: null,
|
|
726
|
+
role,
|
|
727
|
+
releasePromise: null
|
|
728
|
+
};
|
|
729
|
+
state.leases.add(leaseState);
|
|
730
|
+
return {
|
|
731
|
+
abortSignal: leaseState.abortController.signal,
|
|
732
|
+
client: state.client,
|
|
733
|
+
role,
|
|
734
|
+
registerMonitorRetirement: (retirement) => {
|
|
735
|
+
if (role !== "monitor") throw new Error("Matrix transient leases cannot register monitor retirement");
|
|
736
|
+
if (leaseState.releasePromise || state.phase !== "open") throw new Error("Matrix monitor lease is already retiring");
|
|
737
|
+
if (leaseState.monitorRetirement && leaseState.monitorRetirement !== retirement) throw new Error("Matrix monitor retirement is already registered");
|
|
738
|
+
leaseState.monitorRetirement = retirement;
|
|
739
|
+
},
|
|
740
|
+
start: async (abortSignal) => {
|
|
741
|
+
if (leaseState.releasePromise) throw new Error("Matrix client lease has already been released");
|
|
742
|
+
if (state.phase !== "open") throw new Error("Matrix client generation is retiring");
|
|
743
|
+
await ensureSharedClientStarted(state, abortSignal ? AbortSignal.any([abortSignal, leaseState.abortController.signal]) : leaseState.abortController.signal);
|
|
744
|
+
},
|
|
745
|
+
release: (releaseParams = {}) => {
|
|
746
|
+
if (leaseState.releasePromise) return leaseState.releasePromise;
|
|
747
|
+
state.releaseMode = mergeReleaseMode(state.releaseMode, releaseParams.mode ?? "stop");
|
|
748
|
+
state.leases.delete(leaseState);
|
|
749
|
+
if (state.leases.size === 0) state.noLeases.resolve();
|
|
750
|
+
const finalMonitor = role === "monitor" && !Array.from(state.leases).some((lease) => lease.role === "monitor");
|
|
751
|
+
if (role === "monitor" && !finalMonitor) {
|
|
752
|
+
leaseState.releasePromise = retireMonitorLease(state, leaseState);
|
|
753
|
+
return leaseState.releasePromise;
|
|
754
|
+
}
|
|
755
|
+
if (!(finalMonitor || state.leases.size === 0)) {
|
|
756
|
+
leaseState.releasePromise = Promise.resolve();
|
|
757
|
+
return leaseState.releasePromise;
|
|
758
|
+
}
|
|
759
|
+
leaseState.releasePromise = beginGenerationRetirement({
|
|
760
|
+
state,
|
|
761
|
+
monitorLeases: role === "monitor" ? [leaseState] : void 0
|
|
762
|
+
});
|
|
763
|
+
return leaseState.releasePromise;
|
|
764
|
+
}
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
async function acquireSharedMatrixClient(params = {}) {
|
|
768
|
+
const lease = createSharedMatrixClientLease(await resolveOpenSharedMatrixClientState(params), params.role ?? "transient");
|
|
769
|
+
if (params.startClient !== false) try {
|
|
770
|
+
await lease.start(params.abortSignal);
|
|
771
|
+
} catch (error) {
|
|
772
|
+
await lease.release({ mode: "stop" }).catch(() => void 0);
|
|
773
|
+
throw error;
|
|
774
|
+
}
|
|
775
|
+
return lease;
|
|
776
|
+
}
|
|
777
|
+
//#endregion
|
|
778
|
+
//#region extensions/matrix/src/matrix/client.ts
|
|
779
|
+
var client_exports = /* @__PURE__ */ __exportAll({
|
|
780
|
+
acquireSharedMatrixClient: () => acquireSharedMatrixClient,
|
|
781
|
+
resolveMatrixAuthContext: () => resolveMatrixAuthContext
|
|
782
|
+
});
|
|
783
|
+
//#endregion
|
|
784
|
+
export { throwIfMatrixStartupAborted as a, resolveMatrixAuth as c, isMatrixStartupAbortError as i, resolveMatrixAuthContext as l, acquireSharedMatrixClient as n, createMatrixClient as o, createMatrixStartupAbortError as r, backfillMatrixAuthDeviceIdAfterStartup as s, client_exports as t };
|