@openclaw/matrix 2026.3.13 → 2026.5.10-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/account-config-D2W-V1eQ.js +96 -0
- package/dist/account-selection-BWwIruri.js +158 -0
- package/dist/accounts-Bm90Rzvp.js +130 -0
- package/dist/active-client-uhlxdhEy.js +20 -0
- package/dist/allowlist-sTzpCn5d.js +68 -0
- package/dist/api.js +12 -0
- package/dist/approval-handler.runtime-DWTQfd4m.js +370 -0
- package/dist/approval-ids-DoC2z7tR.js +7 -0
- package/dist/approval-reaction-auth-DbcA1gGd.js +27 -0
- package/dist/approval-reactions-o2_tuH8D.js +162 -0
- package/dist/async-lock-uQfhfQIY.js +19 -0
- package/dist/auth-presence.js +26 -0
- package/dist/backup-health-Cabu_WQC.js +60 -0
- package/dist/channel-H_6lMgwf.js +1116 -0
- package/dist/channel-plugin-api.js +2 -0
- package/dist/channel.runtime-BnO9f0pR.js +246 -0
- package/dist/cli-CYZ9yVcB.js +1340 -0
- package/dist/cli-metadata-DPIHnoa6.js +22 -0
- package/dist/cli-metadata.js +2 -0
- package/dist/client-DkcXnm0X.js +25 -0
- package/dist/client-_hckQNGW.js +31 -0
- package/dist/client-bootstrap-Rb8oHvhH.js +114 -0
- package/dist/config--5-S2Akv.js +452 -0
- package/dist/config-paths-nsVaysCu.js +19 -0
- package/dist/config-schema-nPLpEgHl.js +200 -0
- package/dist/config-secret-input.runtime-DiKFehsE.js +2 -0
- package/dist/config-update-wZX-HLMn.js +143 -0
- package/dist/contract-api.js +9 -0
- package/dist/create-client-DCnqDaqd.js +64 -0
- package/dist/credentials-DV6fWXhC.js +56 -0
- package/dist/credentials-read-cmHgousK.js +112 -0
- package/dist/credentials-write.runtime-zniTq-Gr.js +17 -0
- package/dist/crypto-node.runtime-pihzdpY7.js +12 -0
- package/dist/crypto-runtime-ZI0zAtn3.js +1214 -0
- package/dist/deps-C6WqKY7m.js +235 -0
- package/dist/device-health-UVYpbA_W.js +16 -0
- package/dist/direct-management-DMMMgtTB.js +249 -0
- package/dist/direct-room-XkutHjES.js +76 -0
- package/dist/directory-live-DmOtMhyr.js +150 -0
- package/dist/doctor-C4__7c-U.js +153 -0
- package/dist/doctor-contract-D4-64QuJ.js +246 -0
- package/dist/doctor-contract-api.js +2 -0
- package/dist/draft-stream-BE2QevQQ.js +144 -0
- package/dist/encryption-guidance-BPi3A_m3.js +15 -0
- package/dist/env-auth-BJqGI8M6.js +63 -0
- package/dist/env-vars-C7uQCTKn.js +63 -0
- package/dist/errors-CTcpEDq-.js +17 -0
- package/dist/exec-approval-resolver-Bza9Dhlm.js +15 -0
- package/dist/exec-approvals-Crnh543m.js +196 -0
- package/dist/helper-api.js +4 -0
- package/dist/http-client-C7AeVJay.js +319 -0
- package/dist/index.js +46 -0
- package/dist/legacy-crypto-inspector-poDWldgy.js +41 -0
- package/dist/legacy-crypto-restore-Biw-w2ng.js +85 -0
- package/dist/logger-CnZRVrux.js +78 -0
- package/dist/logging-DZHSPP5N.js +99 -0
- package/dist/matrix-migration.runtime-WY6ffcrf.js +525 -0
- package/dist/media-text-DU6nWZuj.js +146 -0
- package/dist/messages-BpihMh82.js +140 -0
- package/dist/migration-snapshot-backup-DaCHTp8C.js +69 -0
- package/dist/migration-snapshot.runtime-CKHE3xF9.js +2 -0
- package/dist/monitor-BaRCKyLd.js +4175 -0
- package/dist/plugin-entry.handlers.runtime.js +51 -0
- package/dist/probe.runtime-BvAzYAIe.js +3 -0
- package/dist/profile-BlHu0wDX.js +111 -0
- package/dist/profile-update-DjeBNgIV.js +69 -0
- package/dist/reaction-common-ejrL19w-.js +71 -0
- package/dist/reaction-events-CiARZfjk.js +121 -0
- package/dist/record-shared-CHWJCTWf.js +2 -0
- package/dist/recovery-key-store-BTJ6jz5v.js +294 -0
- package/dist/resolve-targets-YtJnw1Tb.js +140 -0
- package/dist/resolver.runtime-D9piiGEl.js +5 -0
- package/dist/rolldown-runtime-DUslC3ob.js +14 -0
- package/dist/route-D6rg-iXN.js +161 -0
- package/dist/runtime-C6X4h_SJ.js +6 -0
- package/dist/runtime-Dog86njy.js +8 -0
- package/dist/runtime-api-DTKcXOhp.js +24 -0
- package/dist/runtime-api.js +25 -0
- package/dist/runtime-heavy-api.js +3 -0
- package/dist/runtime-setter-api.js +2 -0
- package/dist/sdk-B2vZA27-.js +1416 -0
- package/dist/secret-contract-DcrJWCQI.js +120 -0
- package/dist/secret-contract-api.js +2 -0
- package/dist/send-Bo0DU1ca.js +1200 -0
- package/dist/session-store-metadata-DQXjgNLt.js +77 -0
- package/dist/setup-bootstrap-ImenBsMt.js +62 -0
- package/dist/setup-core-CfZy05oW.js +116 -0
- package/dist/setup-dm-policy-2-r1FrQh.js +194 -0
- package/dist/setup-entry.js +19 -0
- package/dist/setup-plugin-api.js +44 -0
- package/dist/setup-surface-CqT_o61M.js +540 -0
- package/dist/shared-CpMoYKm1.js +195 -0
- package/dist/startup-abort-56edvmbM.js +32 -0
- package/dist/startup-verification-Demyp0bP.js +132 -0
- package/dist/storage-paths-BJLdnCjV.js +52 -0
- package/dist/storage-tC3ujLiW.js +281 -0
- package/dist/subagent-hooks-DQbyqq9V.js +149 -0
- package/dist/subagent-hooks-api.js +23 -0
- package/dist/sync-state-C_beeevA.js +12 -0
- package/dist/target-ids-80nQ2gql.js +77 -0
- package/dist/test-api.js +4 -0
- package/dist/thread-binding-api-Cq_E-E1K.js +17 -0
- package/dist/thread-binding-api.js +2 -0
- package/dist/thread-bindings-B9mesxXk.js +352 -0
- package/dist/thread-bindings-runtime.js +2 -0
- package/dist/thread-bindings-shared-DK-d-oYX.js +97 -0
- package/dist/timeout-abort-signal-CtaIaP1v.js +2 -0
- package/dist/tool-actions.runtime-ThYhfHtZ.js +532 -0
- package/dist/url-validation-DiK9j7jz.js +36 -0
- package/dist/verification-CZ2rDeHL.js +345 -0
- package/openclaw.plugin.json +796 -1
- package/package.json +82 -16
- package/CHANGELOG.md +0 -104
- package/index.ts +0 -22
- package/src/actions.ts +0 -195
- package/src/channel.directory.test.ts +0 -135
- package/src/channel.ts +0 -461
- package/src/config-schema.test.ts +0 -26
- package/src/config-schema.ts +0 -62
- package/src/directory-live.test.ts +0 -85
- package/src/directory-live.ts +0 -209
- package/src/group-mentions.ts +0 -52
- package/src/matrix/accounts.test.ts +0 -131
- package/src/matrix/accounts.ts +0 -114
- package/src/matrix/actions/client.ts +0 -47
- package/src/matrix/actions/limits.test.ts +0 -15
- package/src/matrix/actions/limits.ts +0 -6
- package/src/matrix/actions/messages.ts +0 -126
- package/src/matrix/actions/pins.test.ts +0 -74
- package/src/matrix/actions/pins.ts +0 -84
- package/src/matrix/actions/reactions.test.ts +0 -109
- package/src/matrix/actions/reactions.ts +0 -102
- package/src/matrix/actions/room.ts +0 -85
- package/src/matrix/actions/summary.ts +0 -75
- package/src/matrix/actions/types.ts +0 -85
- package/src/matrix/actions.ts +0 -15
- package/src/matrix/active-client.ts +0 -32
- package/src/matrix/client/config.ts +0 -245
- package/src/matrix/client/create-client.ts +0 -125
- package/src/matrix/client/logging.ts +0 -46
- package/src/matrix/client/runtime.ts +0 -4
- package/src/matrix/client/shared.test.ts +0 -85
- package/src/matrix/client/shared.ts +0 -210
- package/src/matrix/client/startup.test.ts +0 -49
- package/src/matrix/client/startup.ts +0 -29
- package/src/matrix/client/storage.ts +0 -131
- package/src/matrix/client/types.ts +0 -34
- package/src/matrix/client-bootstrap.ts +0 -47
- package/src/matrix/client.test.ts +0 -56
- package/src/matrix/client.ts +0 -14
- package/src/matrix/credentials.ts +0 -125
- package/src/matrix/deps.test.ts +0 -74
- package/src/matrix/deps.ts +0 -126
- package/src/matrix/format.test.ts +0 -33
- package/src/matrix/format.ts +0 -22
- package/src/matrix/index.ts +0 -11
- package/src/matrix/monitor/access-policy.ts +0 -126
- package/src/matrix/monitor/allowlist.test.ts +0 -45
- package/src/matrix/monitor/allowlist.ts +0 -94
- package/src/matrix/monitor/auto-join.ts +0 -72
- package/src/matrix/monitor/direct.test.ts +0 -396
- package/src/matrix/monitor/direct.ts +0 -152
- package/src/matrix/monitor/events.test.ts +0 -186
- package/src/matrix/monitor/events.ts +0 -168
- package/src/matrix/monitor/handler.body-for-agent.test.ts +0 -196
- package/src/matrix/monitor/handler.ts +0 -768
- package/src/matrix/monitor/inbound-body.test.ts +0 -73
- package/src/matrix/monitor/inbound-body.ts +0 -28
- package/src/matrix/monitor/index.test.ts +0 -18
- package/src/matrix/monitor/index.ts +0 -414
- package/src/matrix/monitor/location.ts +0 -100
- package/src/matrix/monitor/media.test.ts +0 -86
- package/src/matrix/monitor/media.ts +0 -118
- package/src/matrix/monitor/mentions.test.ts +0 -154
- package/src/matrix/monitor/mentions.ts +0 -62
- package/src/matrix/monitor/replies.test.ts +0 -184
- package/src/matrix/monitor/replies.ts +0 -124
- package/src/matrix/monitor/room-info.ts +0 -55
- package/src/matrix/monitor/rooms.test.ts +0 -124
- package/src/matrix/monitor/rooms.ts +0 -47
- package/src/matrix/monitor/threads.ts +0 -68
- package/src/matrix/monitor/types.ts +0 -39
- package/src/matrix/poll-types.test.ts +0 -21
- package/src/matrix/poll-types.ts +0 -167
- package/src/matrix/probe.ts +0 -69
- package/src/matrix/sdk-runtime.ts +0 -18
- package/src/matrix/send/client.ts +0 -99
- package/src/matrix/send/formatting.ts +0 -93
- package/src/matrix/send/media.ts +0 -230
- package/src/matrix/send/targets.test.ts +0 -98
- package/src/matrix/send/targets.ts +0 -150
- package/src/matrix/send/types.ts +0 -110
- package/src/matrix/send-queue.test.ts +0 -145
- package/src/matrix/send-queue.ts +0 -28
- package/src/matrix/send.test.ts +0 -319
- package/src/matrix/send.ts +0 -267
- package/src/onboarding.ts +0 -462
- package/src/outbound.test.ts +0 -159
- package/src/outbound.ts +0 -58
- package/src/resolve-targets.test.ts +0 -68
- package/src/resolve-targets.ts +0 -125
- package/src/runtime.ts +0 -6
- package/src/secret-input.ts +0 -13
- package/src/test-mocks.ts +0 -53
- package/src/tool-actions.ts +0 -164
- package/src/types.ts +0 -118
|
@@ -1,245 +0,0 @@
|
|
|
1
|
-
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
|
|
2
|
-
import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/matrix";
|
|
3
|
-
import { getMatrixRuntime } from "../../runtime.js";
|
|
4
|
-
import {
|
|
5
|
-
normalizeResolvedSecretInputString,
|
|
6
|
-
normalizeSecretInputString,
|
|
7
|
-
} from "../../secret-input.js";
|
|
8
|
-
import type { CoreConfig } from "../../types.js";
|
|
9
|
-
import { loadMatrixSdk } from "../sdk-runtime.js";
|
|
10
|
-
import { ensureMatrixSdkLoggingConfigured } from "./logging.js";
|
|
11
|
-
import type { MatrixAuth, MatrixResolvedConfig } from "./types.js";
|
|
12
|
-
|
|
13
|
-
function clean(value: unknown, path: string): string {
|
|
14
|
-
return normalizeResolvedSecretInputString({ value, path }) ?? "";
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/** Shallow-merge known nested config sub-objects so partial overrides inherit base values. */
|
|
18
|
-
function deepMergeConfig<T extends Record<string, unknown>>(base: T, override: Partial<T>): T {
|
|
19
|
-
const merged = { ...base, ...override } as Record<string, unknown>;
|
|
20
|
-
// Merge known nested objects (dm, actions) so partial overrides keep base fields
|
|
21
|
-
for (const key of ["dm", "actions"] as const) {
|
|
22
|
-
const b = base[key];
|
|
23
|
-
const o = override[key];
|
|
24
|
-
if (typeof b === "object" && b !== null && typeof o === "object" && o !== null) {
|
|
25
|
-
merged[key] = { ...(b as Record<string, unknown>), ...(o as Record<string, unknown>) };
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return merged as T;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Resolve Matrix config for a specific account, with fallback to top-level config.
|
|
33
|
-
* This supports both multi-account (channels.matrix.accounts.*) and
|
|
34
|
-
* single-account (channels.matrix.*) configurations.
|
|
35
|
-
*/
|
|
36
|
-
export function resolveMatrixConfigForAccount(
|
|
37
|
-
cfg: CoreConfig = getMatrixRuntime().config.loadConfig() as CoreConfig,
|
|
38
|
-
accountId?: string | null,
|
|
39
|
-
env: NodeJS.ProcessEnv = process.env,
|
|
40
|
-
): MatrixResolvedConfig {
|
|
41
|
-
const normalizedAccountId = normalizeAccountId(accountId);
|
|
42
|
-
const matrixBase = cfg.channels?.matrix ?? {};
|
|
43
|
-
const accounts = cfg.channels?.matrix?.accounts;
|
|
44
|
-
|
|
45
|
-
// Try to get account-specific config first (direct lookup, then case-insensitive fallback)
|
|
46
|
-
let accountConfig = accounts?.[normalizedAccountId];
|
|
47
|
-
if (!accountConfig && accounts) {
|
|
48
|
-
for (const key of Object.keys(accounts)) {
|
|
49
|
-
if (normalizeAccountId(key) === normalizedAccountId) {
|
|
50
|
-
accountConfig = accounts[key];
|
|
51
|
-
break;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Deep merge: account-specific values override top-level values, preserving
|
|
57
|
-
// nested object inheritance (dm, actions, groups) so partial overrides work.
|
|
58
|
-
const matrix = accountConfig ? deepMergeConfig(matrixBase, accountConfig) : matrixBase;
|
|
59
|
-
|
|
60
|
-
const homeserver =
|
|
61
|
-
clean(matrix.homeserver, "channels.matrix.homeserver") ||
|
|
62
|
-
clean(env.MATRIX_HOMESERVER, "MATRIX_HOMESERVER");
|
|
63
|
-
const userId =
|
|
64
|
-
clean(matrix.userId, "channels.matrix.userId") || clean(env.MATRIX_USER_ID, "MATRIX_USER_ID");
|
|
65
|
-
const accessToken =
|
|
66
|
-
clean(matrix.accessToken, "channels.matrix.accessToken") ||
|
|
67
|
-
clean(env.MATRIX_ACCESS_TOKEN, "MATRIX_ACCESS_TOKEN") ||
|
|
68
|
-
undefined;
|
|
69
|
-
const password =
|
|
70
|
-
clean(matrix.password, "channels.matrix.password") ||
|
|
71
|
-
clean(env.MATRIX_PASSWORD, "MATRIX_PASSWORD") ||
|
|
72
|
-
undefined;
|
|
73
|
-
const deviceName =
|
|
74
|
-
clean(matrix.deviceName, "channels.matrix.deviceName") ||
|
|
75
|
-
clean(env.MATRIX_DEVICE_NAME, "MATRIX_DEVICE_NAME") ||
|
|
76
|
-
undefined;
|
|
77
|
-
const initialSyncLimit =
|
|
78
|
-
typeof matrix.initialSyncLimit === "number"
|
|
79
|
-
? Math.max(0, Math.floor(matrix.initialSyncLimit))
|
|
80
|
-
: undefined;
|
|
81
|
-
const encryption = matrix.encryption ?? false;
|
|
82
|
-
return {
|
|
83
|
-
homeserver,
|
|
84
|
-
userId,
|
|
85
|
-
accessToken,
|
|
86
|
-
password,
|
|
87
|
-
deviceName,
|
|
88
|
-
initialSyncLimit,
|
|
89
|
-
encryption,
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Single-account function for backward compatibility - resolves default account config.
|
|
95
|
-
*/
|
|
96
|
-
export function resolveMatrixConfig(
|
|
97
|
-
cfg: CoreConfig = getMatrixRuntime().config.loadConfig() as CoreConfig,
|
|
98
|
-
env: NodeJS.ProcessEnv = process.env,
|
|
99
|
-
): MatrixResolvedConfig {
|
|
100
|
-
return resolveMatrixConfigForAccount(cfg, DEFAULT_ACCOUNT_ID, env);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export async function resolveMatrixAuth(params?: {
|
|
104
|
-
cfg?: CoreConfig;
|
|
105
|
-
env?: NodeJS.ProcessEnv;
|
|
106
|
-
accountId?: string | null;
|
|
107
|
-
}): Promise<MatrixAuth> {
|
|
108
|
-
const cfg = params?.cfg ?? (getMatrixRuntime().config.loadConfig() as CoreConfig);
|
|
109
|
-
const env = params?.env ?? process.env;
|
|
110
|
-
const resolved = resolveMatrixConfigForAccount(cfg, params?.accountId, env);
|
|
111
|
-
if (!resolved.homeserver) {
|
|
112
|
-
throw new Error("Matrix homeserver is required (matrix.homeserver)");
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const {
|
|
116
|
-
loadMatrixCredentials,
|
|
117
|
-
saveMatrixCredentials,
|
|
118
|
-
credentialsMatchConfig,
|
|
119
|
-
touchMatrixCredentials,
|
|
120
|
-
} = await import("../credentials.js");
|
|
121
|
-
|
|
122
|
-
const accountId = params?.accountId;
|
|
123
|
-
const cached = loadMatrixCredentials(env, accountId);
|
|
124
|
-
const cachedCredentials =
|
|
125
|
-
cached &&
|
|
126
|
-
credentialsMatchConfig(cached, {
|
|
127
|
-
homeserver: resolved.homeserver,
|
|
128
|
-
userId: resolved.userId || "",
|
|
129
|
-
})
|
|
130
|
-
? cached
|
|
131
|
-
: null;
|
|
132
|
-
|
|
133
|
-
// If we have an access token, we can fetch userId via whoami if not provided
|
|
134
|
-
if (resolved.accessToken) {
|
|
135
|
-
let userId = resolved.userId;
|
|
136
|
-
if (!userId) {
|
|
137
|
-
// Fetch userId from access token via whoami
|
|
138
|
-
ensureMatrixSdkLoggingConfigured();
|
|
139
|
-
const { MatrixClient } = loadMatrixSdk();
|
|
140
|
-
const tempClient = new MatrixClient(resolved.homeserver, resolved.accessToken);
|
|
141
|
-
const whoami = await tempClient.getUserId();
|
|
142
|
-
userId = whoami;
|
|
143
|
-
// Save the credentials with the fetched userId
|
|
144
|
-
saveMatrixCredentials(
|
|
145
|
-
{
|
|
146
|
-
homeserver: resolved.homeserver,
|
|
147
|
-
userId,
|
|
148
|
-
accessToken: resolved.accessToken,
|
|
149
|
-
},
|
|
150
|
-
env,
|
|
151
|
-
accountId,
|
|
152
|
-
);
|
|
153
|
-
} else if (cachedCredentials && cachedCredentials.accessToken === resolved.accessToken) {
|
|
154
|
-
touchMatrixCredentials(env, accountId);
|
|
155
|
-
}
|
|
156
|
-
return {
|
|
157
|
-
homeserver: resolved.homeserver,
|
|
158
|
-
userId,
|
|
159
|
-
accessToken: resolved.accessToken,
|
|
160
|
-
deviceName: resolved.deviceName,
|
|
161
|
-
initialSyncLimit: resolved.initialSyncLimit,
|
|
162
|
-
encryption: resolved.encryption,
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
if (cachedCredentials) {
|
|
167
|
-
touchMatrixCredentials(env, accountId);
|
|
168
|
-
return {
|
|
169
|
-
homeserver: cachedCredentials.homeserver,
|
|
170
|
-
userId: cachedCredentials.userId,
|
|
171
|
-
accessToken: cachedCredentials.accessToken,
|
|
172
|
-
deviceName: resolved.deviceName,
|
|
173
|
-
initialSyncLimit: resolved.initialSyncLimit,
|
|
174
|
-
encryption: resolved.encryption,
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (!resolved.userId) {
|
|
179
|
-
throw new Error("Matrix userId is required when no access token is configured (matrix.userId)");
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
if (!resolved.password) {
|
|
183
|
-
throw new Error(
|
|
184
|
-
"Matrix password is required when no access token is configured (matrix.password)",
|
|
185
|
-
);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// Login with password using HTTP API.
|
|
189
|
-
const { response: loginResponse, release: releaseLoginResponse } = await fetchWithSsrFGuard({
|
|
190
|
-
url: `${resolved.homeserver}/_matrix/client/v3/login`,
|
|
191
|
-
init: {
|
|
192
|
-
method: "POST",
|
|
193
|
-
headers: { "Content-Type": "application/json" },
|
|
194
|
-
body: JSON.stringify({
|
|
195
|
-
type: "m.login.password",
|
|
196
|
-
identifier: { type: "m.id.user", user: resolved.userId },
|
|
197
|
-
password: resolved.password,
|
|
198
|
-
initial_device_display_name: resolved.deviceName ?? "OpenClaw Gateway",
|
|
199
|
-
}),
|
|
200
|
-
},
|
|
201
|
-
auditContext: "matrix.login",
|
|
202
|
-
});
|
|
203
|
-
const login = await (async () => {
|
|
204
|
-
try {
|
|
205
|
-
if (!loginResponse.ok) {
|
|
206
|
-
const errorText = await loginResponse.text();
|
|
207
|
-
throw new Error(`Matrix login failed: ${errorText}`);
|
|
208
|
-
}
|
|
209
|
-
return (await loginResponse.json()) as {
|
|
210
|
-
access_token?: string;
|
|
211
|
-
user_id?: string;
|
|
212
|
-
device_id?: string;
|
|
213
|
-
};
|
|
214
|
-
} finally {
|
|
215
|
-
await releaseLoginResponse();
|
|
216
|
-
}
|
|
217
|
-
})();
|
|
218
|
-
|
|
219
|
-
const accessToken = login.access_token?.trim();
|
|
220
|
-
if (!accessToken) {
|
|
221
|
-
throw new Error("Matrix login did not return an access token");
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
const auth: MatrixAuth = {
|
|
225
|
-
homeserver: resolved.homeserver,
|
|
226
|
-
userId: login.user_id ?? resolved.userId,
|
|
227
|
-
accessToken,
|
|
228
|
-
deviceName: resolved.deviceName,
|
|
229
|
-
initialSyncLimit: resolved.initialSyncLimit,
|
|
230
|
-
encryption: resolved.encryption,
|
|
231
|
-
};
|
|
232
|
-
|
|
233
|
-
saveMatrixCredentials(
|
|
234
|
-
{
|
|
235
|
-
homeserver: auth.homeserver,
|
|
236
|
-
userId: auth.userId,
|
|
237
|
-
accessToken: auth.accessToken,
|
|
238
|
-
deviceId: login.device_id,
|
|
239
|
-
},
|
|
240
|
-
env,
|
|
241
|
-
accountId,
|
|
242
|
-
);
|
|
243
|
-
|
|
244
|
-
return auth;
|
|
245
|
-
}
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import type {
|
|
3
|
-
IStorageProvider,
|
|
4
|
-
ICryptoStorageProvider,
|
|
5
|
-
MatrixClient,
|
|
6
|
-
} from "@vector-im/matrix-bot-sdk";
|
|
7
|
-
import { loadMatrixSdk } from "../sdk-runtime.js";
|
|
8
|
-
import { ensureMatrixSdkLoggingConfigured } from "./logging.js";
|
|
9
|
-
import {
|
|
10
|
-
maybeMigrateLegacyStorage,
|
|
11
|
-
resolveMatrixStoragePaths,
|
|
12
|
-
writeStorageMeta,
|
|
13
|
-
} from "./storage.js";
|
|
14
|
-
|
|
15
|
-
function sanitizeUserIdList(input: unknown, label: string): string[] {
|
|
16
|
-
const LogService = loadMatrixSdk().LogService;
|
|
17
|
-
if (input == null) {
|
|
18
|
-
return [];
|
|
19
|
-
}
|
|
20
|
-
if (!Array.isArray(input)) {
|
|
21
|
-
LogService.warn(
|
|
22
|
-
"MatrixClientLite",
|
|
23
|
-
`Expected ${label} list to be an array, got ${typeof input}`,
|
|
24
|
-
);
|
|
25
|
-
return [];
|
|
26
|
-
}
|
|
27
|
-
const filtered = input.filter(
|
|
28
|
-
(entry): entry is string => typeof entry === "string" && entry.trim().length > 0,
|
|
29
|
-
);
|
|
30
|
-
if (filtered.length !== input.length) {
|
|
31
|
-
LogService.warn(
|
|
32
|
-
"MatrixClientLite",
|
|
33
|
-
`Dropping ${input.length - filtered.length} invalid ${label} entries from sync payload`,
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
return filtered;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export async function createMatrixClient(params: {
|
|
40
|
-
homeserver: string;
|
|
41
|
-
userId: string;
|
|
42
|
-
accessToken: string;
|
|
43
|
-
encryption?: boolean;
|
|
44
|
-
localTimeoutMs?: number;
|
|
45
|
-
accountId?: string | null;
|
|
46
|
-
}): Promise<MatrixClient> {
|
|
47
|
-
const { MatrixClient, SimpleFsStorageProvider, RustSdkCryptoStorageProvider, LogService } =
|
|
48
|
-
loadMatrixSdk();
|
|
49
|
-
ensureMatrixSdkLoggingConfigured();
|
|
50
|
-
const env = process.env;
|
|
51
|
-
|
|
52
|
-
// Create storage provider
|
|
53
|
-
const storagePaths = resolveMatrixStoragePaths({
|
|
54
|
-
homeserver: params.homeserver,
|
|
55
|
-
userId: params.userId,
|
|
56
|
-
accessToken: params.accessToken,
|
|
57
|
-
accountId: params.accountId,
|
|
58
|
-
env,
|
|
59
|
-
});
|
|
60
|
-
maybeMigrateLegacyStorage({ storagePaths, env });
|
|
61
|
-
fs.mkdirSync(storagePaths.rootDir, { recursive: true });
|
|
62
|
-
const storage: IStorageProvider = new SimpleFsStorageProvider(storagePaths.storagePath);
|
|
63
|
-
|
|
64
|
-
// Create crypto storage if encryption is enabled
|
|
65
|
-
let cryptoStorage: ICryptoStorageProvider | undefined;
|
|
66
|
-
if (params.encryption) {
|
|
67
|
-
fs.mkdirSync(storagePaths.cryptoPath, { recursive: true });
|
|
68
|
-
|
|
69
|
-
try {
|
|
70
|
-
const { StoreType } = await import("@matrix-org/matrix-sdk-crypto-nodejs");
|
|
71
|
-
cryptoStorage = new RustSdkCryptoStorageProvider(storagePaths.cryptoPath, StoreType.Sqlite);
|
|
72
|
-
} catch (err) {
|
|
73
|
-
LogService.warn(
|
|
74
|
-
"MatrixClientLite",
|
|
75
|
-
"Failed to initialize crypto storage, E2EE disabled:",
|
|
76
|
-
err,
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
writeStorageMeta({
|
|
82
|
-
storagePaths,
|
|
83
|
-
homeserver: params.homeserver,
|
|
84
|
-
userId: params.userId,
|
|
85
|
-
accountId: params.accountId,
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
const client = new MatrixClient(params.homeserver, params.accessToken, storage, cryptoStorage);
|
|
89
|
-
|
|
90
|
-
if (client.crypto) {
|
|
91
|
-
const originalUpdateSyncData = client.crypto.updateSyncData.bind(client.crypto);
|
|
92
|
-
client.crypto.updateSyncData = async (
|
|
93
|
-
toDeviceMessages,
|
|
94
|
-
otkCounts,
|
|
95
|
-
unusedFallbackKeyAlgs,
|
|
96
|
-
changedDeviceLists,
|
|
97
|
-
leftDeviceLists,
|
|
98
|
-
) => {
|
|
99
|
-
const safeChanged = sanitizeUserIdList(changedDeviceLists, "changed device list");
|
|
100
|
-
const safeLeft = sanitizeUserIdList(leftDeviceLists, "left device list");
|
|
101
|
-
try {
|
|
102
|
-
return await originalUpdateSyncData(
|
|
103
|
-
toDeviceMessages,
|
|
104
|
-
otkCounts,
|
|
105
|
-
unusedFallbackKeyAlgs,
|
|
106
|
-
safeChanged,
|
|
107
|
-
safeLeft,
|
|
108
|
-
);
|
|
109
|
-
} catch (err) {
|
|
110
|
-
const message = typeof err === "string" ? err : err instanceof Error ? err.message : "";
|
|
111
|
-
if (message.includes("Expect value to be String")) {
|
|
112
|
-
LogService.warn(
|
|
113
|
-
"MatrixClientLite",
|
|
114
|
-
"Ignoring malformed device list entries during crypto sync",
|
|
115
|
-
message,
|
|
116
|
-
);
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
throw err;
|
|
120
|
-
}
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return client;
|
|
125
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { loadMatrixSdk } from "../sdk-runtime.js";
|
|
2
|
-
|
|
3
|
-
let matrixSdkLoggingConfigured = false;
|
|
4
|
-
let matrixSdkBaseLogger:
|
|
5
|
-
| {
|
|
6
|
-
trace: (module: string, ...messageOrObject: unknown[]) => void;
|
|
7
|
-
debug: (module: string, ...messageOrObject: unknown[]) => void;
|
|
8
|
-
info: (module: string, ...messageOrObject: unknown[]) => void;
|
|
9
|
-
warn: (module: string, ...messageOrObject: unknown[]) => void;
|
|
10
|
-
error: (module: string, ...messageOrObject: unknown[]) => void;
|
|
11
|
-
}
|
|
12
|
-
| undefined;
|
|
13
|
-
|
|
14
|
-
function shouldSuppressMatrixHttpNotFound(module: string, messageOrObject: unknown[]): boolean {
|
|
15
|
-
if (module !== "MatrixHttpClient") {
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
return messageOrObject.some((entry) => {
|
|
19
|
-
if (!entry || typeof entry !== "object") {
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
return (entry as { errcode?: string }).errcode === "M_NOT_FOUND";
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function ensureMatrixSdkLoggingConfigured(): void {
|
|
27
|
-
if (matrixSdkLoggingConfigured) {
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
const { ConsoleLogger, LogService } = loadMatrixSdk();
|
|
31
|
-
matrixSdkBaseLogger = new ConsoleLogger();
|
|
32
|
-
matrixSdkLoggingConfigured = true;
|
|
33
|
-
|
|
34
|
-
LogService.setLogger({
|
|
35
|
-
trace: (module, ...messageOrObject) => matrixSdkBaseLogger?.trace(module, ...messageOrObject),
|
|
36
|
-
debug: (module, ...messageOrObject) => matrixSdkBaseLogger?.debug(module, ...messageOrObject),
|
|
37
|
-
info: (module, ...messageOrObject) => matrixSdkBaseLogger?.info(module, ...messageOrObject),
|
|
38
|
-
warn: (module, ...messageOrObject) => matrixSdkBaseLogger?.warn(module, ...messageOrObject),
|
|
39
|
-
error: (module, ...messageOrObject) => {
|
|
40
|
-
if (shouldSuppressMatrixHttpNotFound(module, messageOrObject)) {
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
matrixSdkBaseLogger?.error(module, ...messageOrObject);
|
|
44
|
-
},
|
|
45
|
-
});
|
|
46
|
-
}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import type { MatrixClient } from "@vector-im/matrix-bot-sdk";
|
|
2
|
-
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
3
|
-
import { resolveSharedMatrixClient, stopSharedClient } from "./shared.js";
|
|
4
|
-
import type { MatrixAuth } from "./types.js";
|
|
5
|
-
|
|
6
|
-
const createMatrixClientMock = vi.hoisted(() => vi.fn());
|
|
7
|
-
|
|
8
|
-
vi.mock("./create-client.js", () => ({
|
|
9
|
-
createMatrixClient: (...args: unknown[]) => createMatrixClientMock(...args),
|
|
10
|
-
}));
|
|
11
|
-
|
|
12
|
-
function makeAuth(suffix: string): MatrixAuth {
|
|
13
|
-
return {
|
|
14
|
-
homeserver: "https://matrix.example.org",
|
|
15
|
-
userId: `@bot-${suffix}:example.org`,
|
|
16
|
-
accessToken: `token-${suffix}`,
|
|
17
|
-
encryption: false,
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function createMockClient(startImpl: () => Promise<void>): MatrixClient {
|
|
22
|
-
return {
|
|
23
|
-
start: vi.fn(startImpl),
|
|
24
|
-
stop: vi.fn(),
|
|
25
|
-
getJoinedRooms: vi.fn().mockResolvedValue([]),
|
|
26
|
-
crypto: undefined,
|
|
27
|
-
} as unknown as MatrixClient;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
describe("resolveSharedMatrixClient startup behavior", () => {
|
|
31
|
-
afterEach(() => {
|
|
32
|
-
stopSharedClient();
|
|
33
|
-
createMatrixClientMock.mockReset();
|
|
34
|
-
vi.useRealTimers();
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it("propagates the original start error during initialization", async () => {
|
|
38
|
-
vi.useFakeTimers();
|
|
39
|
-
const startError = new Error("bad token");
|
|
40
|
-
const client = createMockClient(
|
|
41
|
-
() =>
|
|
42
|
-
new Promise<void>((_resolve, reject) => {
|
|
43
|
-
setTimeout(() => reject(startError), 1);
|
|
44
|
-
}),
|
|
45
|
-
);
|
|
46
|
-
createMatrixClientMock.mockResolvedValue(client);
|
|
47
|
-
|
|
48
|
-
const startPromise = resolveSharedMatrixClient({
|
|
49
|
-
auth: makeAuth("start-error"),
|
|
50
|
-
});
|
|
51
|
-
const startExpectation = expect(startPromise).rejects.toBe(startError);
|
|
52
|
-
|
|
53
|
-
await vi.advanceTimersByTimeAsync(2001);
|
|
54
|
-
await startExpectation;
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it("retries start after a late start-loop failure", async () => {
|
|
58
|
-
vi.useFakeTimers();
|
|
59
|
-
let rejectFirstStart: ((err: unknown) => void) | undefined;
|
|
60
|
-
const firstStart = new Promise<void>((_resolve, reject) => {
|
|
61
|
-
rejectFirstStart = reject;
|
|
62
|
-
});
|
|
63
|
-
const secondStart = new Promise<void>(() => {});
|
|
64
|
-
const startMock = vi.fn().mockReturnValueOnce(firstStart).mockReturnValueOnce(secondStart);
|
|
65
|
-
const client = createMockClient(startMock);
|
|
66
|
-
createMatrixClientMock.mockResolvedValue(client);
|
|
67
|
-
|
|
68
|
-
const firstResolve = resolveSharedMatrixClient({
|
|
69
|
-
auth: makeAuth("late-failure"),
|
|
70
|
-
});
|
|
71
|
-
await vi.advanceTimersByTimeAsync(2000);
|
|
72
|
-
await expect(firstResolve).resolves.toBe(client);
|
|
73
|
-
expect(startMock).toHaveBeenCalledTimes(1);
|
|
74
|
-
|
|
75
|
-
rejectFirstStart?.(new Error("late failure"));
|
|
76
|
-
await Promise.resolve();
|
|
77
|
-
|
|
78
|
-
const secondResolve = resolveSharedMatrixClient({
|
|
79
|
-
auth: makeAuth("late-failure"),
|
|
80
|
-
});
|
|
81
|
-
await vi.advanceTimersByTimeAsync(2000);
|
|
82
|
-
await expect(secondResolve).resolves.toBe(client);
|
|
83
|
-
expect(startMock).toHaveBeenCalledTimes(2);
|
|
84
|
-
});
|
|
85
|
-
});
|