@openclaw/matrix 2026.3.13 → 2026.5.9-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/dist/account-config-D2W-V1eQ.js +96 -0
  2. package/dist/account-selection-BWwIruri.js +158 -0
  3. package/dist/accounts-Bm90Rzvp.js +130 -0
  4. package/dist/active-client-uhlxdhEy.js +20 -0
  5. package/dist/allowlist-sTzpCn5d.js +68 -0
  6. package/dist/api.js +12 -0
  7. package/dist/approval-handler.runtime-DWTQfd4m.js +370 -0
  8. package/dist/approval-ids-DoC2z7tR.js +7 -0
  9. package/dist/approval-reaction-auth-DbcA1gGd.js +27 -0
  10. package/dist/approval-reactions-o2_tuH8D.js +162 -0
  11. package/dist/async-lock-uQfhfQIY.js +19 -0
  12. package/dist/auth-presence.js +26 -0
  13. package/dist/backup-health-Cabu_WQC.js +60 -0
  14. package/dist/channel-DJNir3Rb.js +1116 -0
  15. package/dist/channel-plugin-api.js +2 -0
  16. package/dist/channel.runtime-BQu0hTih.js +246 -0
  17. package/dist/cli-BmfTmg7x.js +1340 -0
  18. package/dist/cli-metadata-B-PCEzrA.js +22 -0
  19. package/dist/cli-metadata.js +2 -0
  20. package/dist/client-DkcXnm0X.js +25 -0
  21. package/dist/client-_hckQNGW.js +31 -0
  22. package/dist/client-bootstrap-Rb8oHvhH.js +114 -0
  23. package/dist/config--5-S2Akv.js +452 -0
  24. package/dist/config-paths-nsVaysCu.js +19 -0
  25. package/dist/config-schema-nPLpEgHl.js +200 -0
  26. package/dist/config-secret-input.runtime-DiKFehsE.js +2 -0
  27. package/dist/config-update-wZX-HLMn.js +143 -0
  28. package/dist/contract-api.js +9 -0
  29. package/dist/create-client-DCnqDaqd.js +64 -0
  30. package/dist/credentials-DV6fWXhC.js +56 -0
  31. package/dist/credentials-read-cmHgousK.js +112 -0
  32. package/dist/credentials-write.runtime-zniTq-Gr.js +17 -0
  33. package/dist/crypto-node.runtime-pihzdpY7.js +12 -0
  34. package/dist/crypto-runtime-ZI0zAtn3.js +1214 -0
  35. package/dist/deps-C6WqKY7m.js +235 -0
  36. package/dist/device-health-UVYpbA_W.js +16 -0
  37. package/dist/direct-management-DMMMgtTB.js +249 -0
  38. package/dist/direct-room-XkutHjES.js +76 -0
  39. package/dist/directory-live-DmOtMhyr.js +150 -0
  40. package/dist/doctor-C4__7c-U.js +153 -0
  41. package/dist/doctor-contract-D4-64QuJ.js +246 -0
  42. package/dist/doctor-contract-api.js +2 -0
  43. package/dist/draft-stream-BE2QevQQ.js +144 -0
  44. package/dist/encryption-guidance-BPi3A_m3.js +15 -0
  45. package/dist/env-auth-BJqGI8M6.js +63 -0
  46. package/dist/env-vars-C7uQCTKn.js +63 -0
  47. package/dist/errors-CTcpEDq-.js +17 -0
  48. package/dist/exec-approval-resolver-Bza9Dhlm.js +15 -0
  49. package/dist/exec-approvals-Crnh543m.js +196 -0
  50. package/dist/helper-api.js +4 -0
  51. package/dist/http-client-C7AeVJay.js +319 -0
  52. package/dist/index.js +46 -0
  53. package/dist/legacy-crypto-inspector-poDWldgy.js +41 -0
  54. package/dist/legacy-crypto-restore-Biw-w2ng.js +85 -0
  55. package/dist/logger-CnZRVrux.js +78 -0
  56. package/dist/logging-DZHSPP5N.js +99 -0
  57. package/dist/matrix-migration.runtime-WY6ffcrf.js +525 -0
  58. package/dist/media-text-DU6nWZuj.js +146 -0
  59. package/dist/messages-BpihMh82.js +140 -0
  60. package/dist/migration-snapshot-backup-DaCHTp8C.js +69 -0
  61. package/dist/migration-snapshot.runtime-CKHE3xF9.js +2 -0
  62. package/dist/monitor-C_81r_Ck.js +4125 -0
  63. package/dist/plugin-entry.handlers.runtime.js +51 -0
  64. package/dist/probe.runtime-BvAzYAIe.js +3 -0
  65. package/dist/profile-BlHu0wDX.js +111 -0
  66. package/dist/profile-update-DjeBNgIV.js +69 -0
  67. package/dist/reaction-common-ejrL19w-.js +71 -0
  68. package/dist/reaction-events-CiARZfjk.js +121 -0
  69. package/dist/record-shared-CHWJCTWf.js +2 -0
  70. package/dist/recovery-key-store-BTJ6jz5v.js +294 -0
  71. package/dist/resolve-targets-YtJnw1Tb.js +140 -0
  72. package/dist/resolver.runtime-D9piiGEl.js +5 -0
  73. package/dist/rolldown-runtime-DUslC3ob.js +14 -0
  74. package/dist/route-D6rg-iXN.js +161 -0
  75. package/dist/runtime-C6X4h_SJ.js +6 -0
  76. package/dist/runtime-Dog86njy.js +8 -0
  77. package/dist/runtime-api-BXWBFIqm.js +25 -0
  78. package/dist/runtime-api.js +25 -0
  79. package/dist/runtime-heavy-api.js +3 -0
  80. package/dist/runtime-setter-api.js +2 -0
  81. package/dist/sdk-B2vZA27-.js +1416 -0
  82. package/dist/secret-contract-DcrJWCQI.js +120 -0
  83. package/dist/secret-contract-api.js +2 -0
  84. package/dist/send-Bo0DU1ca.js +1200 -0
  85. package/dist/session-store-metadata-DI5SCofx.js +77 -0
  86. package/dist/setup-bootstrap-ImenBsMt.js +62 -0
  87. package/dist/setup-core-CfZy05oW.js +116 -0
  88. package/dist/setup-dm-policy-2-r1FrQh.js +194 -0
  89. package/dist/setup-entry.js +19 -0
  90. package/dist/setup-plugin-api.js +44 -0
  91. package/dist/setup-surface-CqT_o61M.js +540 -0
  92. package/dist/shared-CpMoYKm1.js +195 -0
  93. package/dist/startup-abort-56edvmbM.js +32 -0
  94. package/dist/startup-verification-Demyp0bP.js +132 -0
  95. package/dist/storage-paths-BJLdnCjV.js +52 -0
  96. package/dist/storage-tC3ujLiW.js +281 -0
  97. package/dist/subagent-hooks-DQbyqq9V.js +149 -0
  98. package/dist/subagent-hooks-api.js +23 -0
  99. package/dist/sync-state-C_beeevA.js +12 -0
  100. package/dist/target-ids-80nQ2gql.js +77 -0
  101. package/dist/test-api.js +4 -0
  102. package/dist/thread-binding-api-Cq_E-E1K.js +17 -0
  103. package/dist/thread-binding-api.js +2 -0
  104. package/dist/thread-bindings-B9mesxXk.js +352 -0
  105. package/dist/thread-bindings-runtime.js +2 -0
  106. package/dist/thread-bindings-shared-DK-d-oYX.js +97 -0
  107. package/dist/timeout-abort-signal-CtaIaP1v.js +2 -0
  108. package/dist/tool-actions.runtime-BIH49vRr.js +532 -0
  109. package/dist/url-validation-DiK9j7jz.js +36 -0
  110. package/dist/verification-CZ2rDeHL.js +345 -0
  111. package/openclaw.plugin.json +788 -1
  112. package/package.json +82 -16
  113. package/CHANGELOG.md +0 -104
  114. package/index.ts +0 -22
  115. package/src/actions.ts +0 -195
  116. package/src/channel.directory.test.ts +0 -135
  117. package/src/channel.ts +0 -461
  118. package/src/config-schema.test.ts +0 -26
  119. package/src/config-schema.ts +0 -62
  120. package/src/directory-live.test.ts +0 -85
  121. package/src/directory-live.ts +0 -209
  122. package/src/group-mentions.ts +0 -52
  123. package/src/matrix/accounts.test.ts +0 -131
  124. package/src/matrix/accounts.ts +0 -114
  125. package/src/matrix/actions/client.ts +0 -47
  126. package/src/matrix/actions/limits.test.ts +0 -15
  127. package/src/matrix/actions/limits.ts +0 -6
  128. package/src/matrix/actions/messages.ts +0 -126
  129. package/src/matrix/actions/pins.test.ts +0 -74
  130. package/src/matrix/actions/pins.ts +0 -84
  131. package/src/matrix/actions/reactions.test.ts +0 -109
  132. package/src/matrix/actions/reactions.ts +0 -102
  133. package/src/matrix/actions/room.ts +0 -85
  134. package/src/matrix/actions/summary.ts +0 -75
  135. package/src/matrix/actions/types.ts +0 -85
  136. package/src/matrix/actions.ts +0 -15
  137. package/src/matrix/active-client.ts +0 -32
  138. package/src/matrix/client/config.ts +0 -245
  139. package/src/matrix/client/create-client.ts +0 -125
  140. package/src/matrix/client/logging.ts +0 -46
  141. package/src/matrix/client/runtime.ts +0 -4
  142. package/src/matrix/client/shared.test.ts +0 -85
  143. package/src/matrix/client/shared.ts +0 -210
  144. package/src/matrix/client/startup.test.ts +0 -49
  145. package/src/matrix/client/startup.ts +0 -29
  146. package/src/matrix/client/storage.ts +0 -131
  147. package/src/matrix/client/types.ts +0 -34
  148. package/src/matrix/client-bootstrap.ts +0 -47
  149. package/src/matrix/client.test.ts +0 -56
  150. package/src/matrix/client.ts +0 -14
  151. package/src/matrix/credentials.ts +0 -125
  152. package/src/matrix/deps.test.ts +0 -74
  153. package/src/matrix/deps.ts +0 -126
  154. package/src/matrix/format.test.ts +0 -33
  155. package/src/matrix/format.ts +0 -22
  156. package/src/matrix/index.ts +0 -11
  157. package/src/matrix/monitor/access-policy.ts +0 -126
  158. package/src/matrix/monitor/allowlist.test.ts +0 -45
  159. package/src/matrix/monitor/allowlist.ts +0 -94
  160. package/src/matrix/monitor/auto-join.ts +0 -72
  161. package/src/matrix/monitor/direct.test.ts +0 -396
  162. package/src/matrix/monitor/direct.ts +0 -152
  163. package/src/matrix/monitor/events.test.ts +0 -186
  164. package/src/matrix/monitor/events.ts +0 -168
  165. package/src/matrix/monitor/handler.body-for-agent.test.ts +0 -196
  166. package/src/matrix/monitor/handler.ts +0 -768
  167. package/src/matrix/monitor/inbound-body.test.ts +0 -73
  168. package/src/matrix/monitor/inbound-body.ts +0 -28
  169. package/src/matrix/monitor/index.test.ts +0 -18
  170. package/src/matrix/monitor/index.ts +0 -414
  171. package/src/matrix/monitor/location.ts +0 -100
  172. package/src/matrix/monitor/media.test.ts +0 -86
  173. package/src/matrix/monitor/media.ts +0 -118
  174. package/src/matrix/monitor/mentions.test.ts +0 -154
  175. package/src/matrix/monitor/mentions.ts +0 -62
  176. package/src/matrix/monitor/replies.test.ts +0 -184
  177. package/src/matrix/monitor/replies.ts +0 -124
  178. package/src/matrix/monitor/room-info.ts +0 -55
  179. package/src/matrix/monitor/rooms.test.ts +0 -124
  180. package/src/matrix/monitor/rooms.ts +0 -47
  181. package/src/matrix/monitor/threads.ts +0 -68
  182. package/src/matrix/monitor/types.ts +0 -39
  183. package/src/matrix/poll-types.test.ts +0 -21
  184. package/src/matrix/poll-types.ts +0 -167
  185. package/src/matrix/probe.ts +0 -69
  186. package/src/matrix/sdk-runtime.ts +0 -18
  187. package/src/matrix/send/client.ts +0 -99
  188. package/src/matrix/send/formatting.ts +0 -93
  189. package/src/matrix/send/media.ts +0 -230
  190. package/src/matrix/send/targets.test.ts +0 -98
  191. package/src/matrix/send/targets.ts +0 -150
  192. package/src/matrix/send/types.ts +0 -110
  193. package/src/matrix/send-queue.test.ts +0 -145
  194. package/src/matrix/send-queue.ts +0 -28
  195. package/src/matrix/send.test.ts +0 -319
  196. package/src/matrix/send.ts +0 -267
  197. package/src/onboarding.ts +0 -462
  198. package/src/outbound.test.ts +0 -159
  199. package/src/outbound.ts +0 -58
  200. package/src/resolve-targets.test.ts +0 -68
  201. package/src/resolve-targets.ts +0 -125
  202. package/src/runtime.ts +0 -6
  203. package/src/secret-input.ts +0 -13
  204. package/src/test-mocks.ts +0 -53
  205. package/src/tool-actions.ts +0 -164
  206. 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,4 +0,0 @@
1
- export function isBunRuntime(): boolean {
2
- const versions = process.versions as { bun?: string };
3
- return typeof versions.bun === "string";
4
- }
@@ -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
- });