@kodelyth/matrix 2026.5.42 → 2026.6.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.
Files changed (205) hide show
  1. package/klaw.plugin.json +891 -3
  2. package/package.json +18 -6
  3. package/CHANGELOG.md +0 -321
  4. package/SPEC-SUPPORT.md +0 -116
  5. package/api.ts +0 -38
  6. package/auth-presence.ts +0 -56
  7. package/channel-plugin-api.ts +0 -3
  8. package/cli-metadata.ts +0 -11
  9. package/contract-api.ts +0 -17
  10. package/doctor-contract-api.ts +0 -1
  11. package/helper-api.ts +0 -3
  12. package/index.ts +0 -55
  13. package/plugin-entry.handlers.runtime.ts +0 -1
  14. package/runtime-api.ts +0 -72
  15. package/runtime-heavy-api.ts +0 -1
  16. package/runtime-setter-api.ts +0 -3
  17. package/secret-contract-api.ts +0 -5
  18. package/setup-entry.ts +0 -17
  19. package/setup-plugin-api.ts +0 -3
  20. package/src/account-selection.ts +0 -223
  21. package/src/actions.ts +0 -346
  22. package/src/approval-auth.ts +0 -25
  23. package/src/approval-handler.runtime.ts +0 -592
  24. package/src/approval-ids.ts +0 -6
  25. package/src/approval-native.ts +0 -345
  26. package/src/approval-reaction-auth.ts +0 -45
  27. package/src/approval-reactions.ts +0 -313
  28. package/src/auth-precedence.ts +0 -61
  29. package/src/channel-account-paths.ts +0 -97
  30. package/src/channel.runtime.ts +0 -17
  31. package/src/channel.setup.ts +0 -48
  32. package/src/channel.ts +0 -667
  33. package/src/cli-metadata.ts +0 -19
  34. package/src/cli.ts +0 -2298
  35. package/src/config-adapter.ts +0 -41
  36. package/src/config-schema.ts +0 -159
  37. package/src/config-ui-hints.ts +0 -56
  38. package/src/directory-live.ts +0 -238
  39. package/src/doctor-contract.ts +0 -287
  40. package/src/doctor.ts +0 -262
  41. package/src/env-vars.ts +0 -92
  42. package/src/exec-approval-resolver.ts +0 -23
  43. package/src/exec-approvals.ts +0 -287
  44. package/src/group-mentions.ts +0 -41
  45. package/src/legacy-crypto-inspector-availability.ts +0 -60
  46. package/src/legacy-crypto.ts +0 -531
  47. package/src/legacy-state.ts +0 -156
  48. package/src/matrix/account-config.ts +0 -175
  49. package/src/matrix/accounts.ts +0 -194
  50. package/src/matrix/actions/client.ts +0 -31
  51. package/src/matrix/actions/devices.ts +0 -34
  52. package/src/matrix/actions/limits.ts +0 -6
  53. package/src/matrix/actions/messages.ts +0 -129
  54. package/src/matrix/actions/pins.ts +0 -63
  55. package/src/matrix/actions/polls.ts +0 -109
  56. package/src/matrix/actions/profile.ts +0 -37
  57. package/src/matrix/actions/reactions.ts +0 -59
  58. package/src/matrix/actions/room.ts +0 -71
  59. package/src/matrix/actions/summary.ts +0 -88
  60. package/src/matrix/actions/types.ts +0 -63
  61. package/src/matrix/actions/verification.ts +0 -589
  62. package/src/matrix/actions.ts +0 -37
  63. package/src/matrix/active-client.ts +0 -26
  64. package/src/matrix/async-lock.ts +0 -18
  65. package/src/matrix/backup-health.ts +0 -124
  66. package/src/matrix/client/config-runtime-api.ts +0 -9
  67. package/src/matrix/client/config-secret-input.runtime.ts +0 -1
  68. package/src/matrix/client/config.ts +0 -853
  69. package/src/matrix/client/create-client.ts +0 -105
  70. package/src/matrix/client/env-auth.ts +0 -95
  71. package/src/matrix/client/file-sync-store.ts +0 -289
  72. package/src/matrix/client/logging.ts +0 -140
  73. package/src/matrix/client/migration-snapshot.runtime.ts +0 -1
  74. package/src/matrix/client/private-network-host.ts +0 -1
  75. package/src/matrix/client/runtime.ts +0 -4
  76. package/src/matrix/client/shared.ts +0 -316
  77. package/src/matrix/client/storage.ts +0 -543
  78. package/src/matrix/client/types.ts +0 -50
  79. package/src/matrix/client/url-validation.ts +0 -73
  80. package/src/matrix/client-bootstrap.ts +0 -173
  81. package/src/matrix/client.ts +0 -23
  82. package/src/matrix/config-paths.ts +0 -31
  83. package/src/matrix/config-update.ts +0 -292
  84. package/src/matrix/credentials-read.ts +0 -208
  85. package/src/matrix/credentials-write.runtime.ts +0 -35
  86. package/src/matrix/credentials.ts +0 -95
  87. package/src/matrix/deps.ts +0 -309
  88. package/src/matrix/device-health.ts +0 -29
  89. package/src/matrix/direct-management.ts +0 -349
  90. package/src/matrix/direct-room.ts +0 -128
  91. package/src/matrix/draft-stream.ts +0 -225
  92. package/src/matrix/encryption-guidance.ts +0 -24
  93. package/src/matrix/errors.ts +0 -21
  94. package/src/matrix/format.ts +0 -426
  95. package/src/matrix/legacy-crypto-inspector.ts +0 -95
  96. package/src/matrix/media-errors.ts +0 -20
  97. package/src/matrix/media-text.ts +0 -162
  98. package/src/matrix/monitor/access-state.ts +0 -145
  99. package/src/matrix/monitor/ack-config.ts +0 -27
  100. package/src/matrix/monitor/allowlist.ts +0 -89
  101. package/src/matrix/monitor/auto-join.ts +0 -86
  102. package/src/matrix/monitor/config.ts +0 -569
  103. package/src/matrix/monitor/context-summary.ts +0 -43
  104. package/src/matrix/monitor/direct.ts +0 -296
  105. package/src/matrix/monitor/events.ts +0 -397
  106. package/src/matrix/monitor/handler.ts +0 -2266
  107. package/src/matrix/monitor/inbound-dedupe.ts +0 -267
  108. package/src/matrix/monitor/index.ts +0 -540
  109. package/src/matrix/monitor/legacy-crypto-restore.ts +0 -139
  110. package/src/matrix/monitor/location.ts +0 -108
  111. package/src/matrix/monitor/media.ts +0 -119
  112. package/src/matrix/monitor/mentions.ts +0 -256
  113. package/src/matrix/monitor/reaction-events.ts +0 -197
  114. package/src/matrix/monitor/recent-invite.ts +0 -30
  115. package/src/matrix/monitor/replies.ts +0 -136
  116. package/src/matrix/monitor/reply-context.ts +0 -92
  117. package/src/matrix/monitor/room-history.ts +0 -301
  118. package/src/matrix/monitor/room-info.ts +0 -126
  119. package/src/matrix/monitor/rooms.ts +0 -52
  120. package/src/matrix/monitor/route.ts +0 -179
  121. package/src/matrix/monitor/runtime-api.ts +0 -28
  122. package/src/matrix/monitor/startup-verification.ts +0 -237
  123. package/src/matrix/monitor/startup.ts +0 -218
  124. package/src/matrix/monitor/status.ts +0 -120
  125. package/src/matrix/monitor/sync-lifecycle.ts +0 -91
  126. package/src/matrix/monitor/task-runner.ts +0 -38
  127. package/src/matrix/monitor/test-events.ts +0 -21
  128. package/src/matrix/monitor/thread-context.ts +0 -108
  129. package/src/matrix/monitor/threads.ts +0 -85
  130. package/src/matrix/monitor/types.ts +0 -30
  131. package/src/matrix/monitor/verification-events.ts +0 -643
  132. package/src/matrix/monitor/verification-utils.ts +0 -46
  133. package/src/matrix/outbound-media-runtime.ts +0 -1
  134. package/src/matrix/poll-summary.ts +0 -110
  135. package/src/matrix/poll-types.ts +0 -429
  136. package/src/matrix/probe.runtime.ts +0 -4
  137. package/src/matrix/probe.ts +0 -97
  138. package/src/matrix/profile.ts +0 -184
  139. package/src/matrix/reaction-common.ts +0 -147
  140. package/src/matrix/sdk/crypto-bootstrap.ts +0 -438
  141. package/src/matrix/sdk/crypto-facade.ts +0 -242
  142. package/src/matrix/sdk/crypto-node.runtime.ts +0 -17
  143. package/src/matrix/sdk/crypto-runtime.ts +0 -14
  144. package/src/matrix/sdk/decrypt-bridge.ts +0 -410
  145. package/src/matrix/sdk/event-helpers.ts +0 -83
  146. package/src/matrix/sdk/http-client.ts +0 -87
  147. package/src/matrix/sdk/idb-persistence-lock.ts +0 -51
  148. package/src/matrix/sdk/idb-persistence.ts +0 -288
  149. package/src/matrix/sdk/logger.ts +0 -108
  150. package/src/matrix/sdk/read-response-with-limit.ts +0 -19
  151. package/src/matrix/sdk/recovery-key-store.ts +0 -453
  152. package/src/matrix/sdk/timeout-abort-signal.ts +0 -1
  153. package/src/matrix/sdk/transport-runtime-api.ts +0 -18
  154. package/src/matrix/sdk/transport.ts +0 -352
  155. package/src/matrix/sdk/types.ts +0 -245
  156. package/src/matrix/sdk/verification-manager.ts +0 -795
  157. package/src/matrix/sdk/verification-status.ts +0 -23
  158. package/src/matrix/sdk.ts +0 -2152
  159. package/src/matrix/send/client.ts +0 -93
  160. package/src/matrix/send/formatting.ts +0 -189
  161. package/src/matrix/send/media.ts +0 -244
  162. package/src/matrix/send/targets.ts +0 -104
  163. package/src/matrix/send/types.ts +0 -131
  164. package/src/matrix/send.ts +0 -660
  165. package/src/matrix/session-store-metadata.ts +0 -108
  166. package/src/matrix/startup-abort.ts +0 -44
  167. package/src/matrix/subagent-hooks.ts +0 -308
  168. package/src/matrix/sync-state.ts +0 -27
  169. package/src/matrix/target-ids.ts +0 -79
  170. package/src/matrix/thread-bindings-shared.ts +0 -206
  171. package/src/matrix/thread-bindings.ts +0 -580
  172. package/src/matrix-migration.runtime.ts +0 -9
  173. package/src/migration-config.ts +0 -243
  174. package/src/migration-snapshot-backup.ts +0 -116
  175. package/src/migration-snapshot.ts +0 -53
  176. package/src/onboarding.ts +0 -775
  177. package/src/outbound.ts +0 -248
  178. package/src/plugin-entry.runtime.js +0 -115
  179. package/src/plugin-entry.runtime.ts +0 -70
  180. package/src/profile-update.ts +0 -71
  181. package/src/record-shared.ts +0 -3
  182. package/src/resolve-targets.ts +0 -175
  183. package/src/resolver.runtime.ts +0 -5
  184. package/src/resolver.ts +0 -21
  185. package/src/runtime-api.ts +0 -106
  186. package/src/runtime.ts +0 -13
  187. package/src/secret-contract.ts +0 -174
  188. package/src/session-route.ts +0 -126
  189. package/src/setup-bootstrap.ts +0 -102
  190. package/src/setup-config.ts +0 -222
  191. package/src/setup-contract.ts +0 -90
  192. package/src/setup-core.ts +0 -146
  193. package/src/setup-dm-policy.ts +0 -15
  194. package/src/setup-surface.ts +0 -4
  195. package/src/startup-maintenance.ts +0 -114
  196. package/src/storage-paths.ts +0 -92
  197. package/src/thread-binding-api.ts +0 -23
  198. package/src/tool-actions.runtime.ts +0 -1
  199. package/src/tool-actions.ts +0 -498
  200. package/src/types.ts +0 -257
  201. package/subagent-hooks-api.ts +0 -31
  202. package/test-api.ts +0 -21
  203. package/thread-binding-api.ts +0 -4
  204. package/thread-bindings-runtime.ts +0 -4
  205. package/tsconfig.json +0 -16
package/src/onboarding.ts DELETED
@@ -1,775 +0,0 @@
1
- import { DEFAULT_ACCOUNT_ID } from "klaw/plugin-sdk/account-id";
2
- import type { DmPolicy } from "klaw/plugin-sdk/config-contracts";
3
- import {
4
- type ChannelSetupDmPolicy,
5
- type ChannelSetupWizardAdapter,
6
- formatDocsLink,
7
- hasConfiguredSecretInput,
8
- mergeAllowFromEntries,
9
- normalizeAccountId,
10
- promptAccountId,
11
- promptChannelAccessConfig,
12
- splitSetupEntries,
13
- } from "klaw/plugin-sdk/setup";
14
- import { isPrivateNetworkOptInEnabled } from "klaw/plugin-sdk/ssrf-policy";
15
- import {
16
- normalizeLowercaseStringOrEmpty,
17
- normalizeOptionalString,
18
- normalizeStringifiedOptionalString,
19
- } from "klaw/plugin-sdk/string-coerce-runtime";
20
- import { requiresExplicitMatrixDefaultAccount } from "./account-selection.js";
21
- import {
22
- listMatrixAccountIds,
23
- resolveDefaultMatrixAccountId,
24
- resolveMatrixAccount,
25
- resolveMatrixAccountConfig,
26
- } from "./matrix/accounts.js";
27
- import { resolveMatrixEnvAuthReadiness } from "./matrix/client/env-auth.js";
28
- import { isPrivateOrLoopbackHost } from "./matrix/client/private-network-host.js";
29
- import {
30
- resolveValidatedMatrixHomeserverUrl,
31
- validateMatrixHomeserverUrl,
32
- } from "./matrix/client/url-validation.js";
33
- import { resolveMatrixConfigFieldPath, updateMatrixAccountConfig } from "./matrix/config-update.js";
34
- import { ensureMatrixSdkInstalled, isMatrixSdkAvailable } from "./matrix/deps.js";
35
- import type { RuntimeEnv, WizardPrompter } from "./runtime-api.js";
36
- import { moveSingleMatrixAccountConfigToNamedAccount } from "./setup-config.js";
37
- import { resolveMatrixSetupDmAllowFrom } from "./setup-dm-policy.js";
38
- import type { CoreConfig, MatrixConfig } from "./types.js";
39
-
40
- const channel = "matrix" as const;
41
- type MatrixInviteAutoJoinPolicy = NonNullable<MatrixConfig["autoJoin"]>;
42
-
43
- const matrixInviteAutoJoinOptions: Array<{
44
- value: MatrixInviteAutoJoinPolicy;
45
- label: string;
46
- }> = [
47
- { value: "allowlist", label: "Allowlist (recommended)" },
48
- { value: "always", label: "Always (join every invite)" },
49
- { value: "off", label: "Off (do not auto-join invites)" },
50
- ];
51
-
52
- function isMatrixInviteAutoJoinPolicy(value: string): value is MatrixInviteAutoJoinPolicy {
53
- return value === "allowlist" || value === "always" || value === "off";
54
- }
55
-
56
- function isMatrixInviteAutoJoinTarget(entry: string): boolean {
57
- return (
58
- entry === "*" ||
59
- (entry.startsWith("!") && entry.includes(":")) ||
60
- (entry.startsWith("#") && entry.includes(":"))
61
- );
62
- }
63
-
64
- function normalizeMatrixInviteAutoJoinTargets(entries: string[]): string[] {
65
- return [
66
- ...new Set(
67
- entries
68
- .map((entry) => normalizeOptionalString(entry))
69
- .filter((entry): entry is string => Boolean(entry)),
70
- ),
71
- ];
72
- }
73
-
74
- function resolveMatrixOnboardingAccountId(cfg: CoreConfig, accountId?: string): string {
75
- return normalizeAccountId(
76
- normalizeOptionalString(accountId) || resolveDefaultMatrixAccountId(cfg) || DEFAULT_ACCOUNT_ID,
77
- );
78
- }
79
-
80
- function setMatrixDmPolicy(cfg: CoreConfig, policy: DmPolicy, accountId?: string) {
81
- const resolvedAccountId = resolveMatrixOnboardingAccountId(cfg, accountId);
82
- const existing = resolveMatrixAccountConfig({
83
- cfg,
84
- accountId: resolvedAccountId,
85
- });
86
- const allowFrom = resolveMatrixSetupDmAllowFrom(policy, existing.dm?.allowFrom);
87
- return updateMatrixAccountConfig(cfg, resolvedAccountId, {
88
- dm: {
89
- ...existing.dm,
90
- policy,
91
- allowFrom,
92
- },
93
- });
94
- }
95
-
96
- async function noteMatrixAuthHelp(prompter: WizardPrompter): Promise<void> {
97
- await prompter.note(
98
- [
99
- "Matrix requires a homeserver URL.",
100
- "Use an access token (recommended) or password login to an existing account.",
101
- "With access token: user ID is fetched automatically.",
102
- "Env vars supported: MATRIX_HOMESERVER, MATRIX_USER_ID, MATRIX_ACCESS_TOKEN, MATRIX_PASSWORD, MATRIX_DEVICE_ID, MATRIX_DEVICE_NAME.",
103
- "Per-account env vars: MATRIX_<ACCOUNT_ID>_HOMESERVER, MATRIX_<ACCOUNT_ID>_USER_ID, MATRIX_<ACCOUNT_ID>_ACCESS_TOKEN, MATRIX_<ACCOUNT_ID>_PASSWORD, MATRIX_<ACCOUNT_ID>_DEVICE_ID, MATRIX_<ACCOUNT_ID>_DEVICE_NAME.",
104
- `Docs: ${formatDocsLink("/channels/matrix", "channels/matrix")}`,
105
- ].join("\n"),
106
- "Matrix setup",
107
- );
108
- }
109
-
110
- function requiresMatrixPrivateNetworkOptIn(homeserver: string): boolean {
111
- try {
112
- const parsed = new URL(homeserver);
113
- return parsed.protocol === "http:" && !isPrivateOrLoopbackHost(parsed.hostname);
114
- } catch {
115
- return false;
116
- }
117
- }
118
-
119
- async function promptMatrixAllowFrom(params: {
120
- cfg: CoreConfig;
121
- prompter: WizardPrompter;
122
- accountId?: string;
123
- }): Promise<CoreConfig> {
124
- const { cfg, prompter } = params;
125
- const accountId = resolveMatrixOnboardingAccountId(cfg, params.accountId);
126
- const existingConfig = resolveMatrixAccountConfig({ cfg, accountId });
127
- const existingAllowFrom = existingConfig.dm?.allowFrom ?? [];
128
- const account = resolveMatrixAccount({ cfg, accountId });
129
- const canResolve = account.configured;
130
-
131
- const isFullUserId = (value: string) => value.startsWith("@") && value.includes(":");
132
-
133
- while (true) {
134
- const entry = await prompter.text({
135
- message: "Matrix allowFrom (full @user:server; display name only if unique)",
136
- placeholder: "@user:server",
137
- initialValue: existingAllowFrom[0] ? String(existingAllowFrom[0]) : undefined,
138
- validate: (value) => (normalizeOptionalString(value) ? undefined : "Required"),
139
- });
140
- const parts = splitSetupEntries(entry);
141
- const resolvedIds: string[] = [];
142
- const pending: string[] = [];
143
- const unresolved: string[] = [];
144
- const unresolvedNotes: string[] = [];
145
-
146
- for (const part of parts) {
147
- if (isFullUserId(part)) {
148
- resolvedIds.push(part);
149
- continue;
150
- }
151
- if (!canResolve) {
152
- unresolved.push(part);
153
- continue;
154
- }
155
- pending.push(part);
156
- }
157
-
158
- if (pending.length > 0) {
159
- const { resolveMatrixTargets } = await import("./resolve-targets.js");
160
- const results = await resolveMatrixTargets({
161
- cfg,
162
- accountId,
163
- inputs: pending,
164
- kind: "user",
165
- }).catch(() => []);
166
- for (const result of results) {
167
- if (result?.resolved && result.id) {
168
- resolvedIds.push(result.id);
169
- continue;
170
- }
171
- if (result?.input) {
172
- unresolved.push(result.input);
173
- if (result.note) {
174
- unresolvedNotes.push(`${result.input}: ${result.note}`);
175
- }
176
- }
177
- }
178
- }
179
-
180
- if (unresolved.length > 0) {
181
- const details = unresolvedNotes.length > 0 ? unresolvedNotes : unresolved;
182
- await prompter.note(
183
- `Could not resolve:\n${details.join("\n")}\nUse full @user:server IDs.`,
184
- "Matrix allowlist",
185
- );
186
- continue;
187
- }
188
-
189
- const unique = mergeAllowFromEntries(existingAllowFrom, resolvedIds);
190
- return updateMatrixAccountConfig(cfg, accountId, {
191
- dm: {
192
- ...existingConfig.dm,
193
- policy: "allowlist",
194
- allowFrom: unique,
195
- },
196
- });
197
- }
198
- }
199
-
200
- function setMatrixGroupPolicy(
201
- cfg: CoreConfig,
202
- groupPolicy: "open" | "allowlist" | "disabled",
203
- accountId?: string,
204
- ) {
205
- return updateMatrixAccountConfig(cfg, resolveMatrixOnboardingAccountId(cfg, accountId), {
206
- groupPolicy,
207
- });
208
- }
209
-
210
- function setMatrixGroupRooms(cfg: CoreConfig, roomKeys: string[], accountId?: string) {
211
- const groups = Object.fromEntries(roomKeys.map((key) => [key, { enabled: true }]));
212
- return updateMatrixAccountConfig(cfg, resolveMatrixOnboardingAccountId(cfg, accountId), {
213
- groups,
214
- rooms: null,
215
- });
216
- }
217
-
218
- function setMatrixAutoJoin(
219
- cfg: CoreConfig,
220
- autoJoin: MatrixInviteAutoJoinPolicy,
221
- autoJoinAllowlist: string[],
222
- accountId?: string,
223
- ) {
224
- return updateMatrixAccountConfig(cfg, resolveMatrixOnboardingAccountId(cfg, accountId), {
225
- autoJoin,
226
- autoJoinAllowlist: autoJoin === "allowlist" ? autoJoinAllowlist : null,
227
- });
228
- }
229
-
230
- async function configureMatrixInviteAutoJoin(params: {
231
- cfg: CoreConfig;
232
- prompter: WizardPrompter;
233
- accountId?: string;
234
- }): Promise<CoreConfig> {
235
- const accountId = resolveMatrixOnboardingAccountId(params.cfg, params.accountId);
236
- const existingConfig = resolveMatrixAccountConfig({ cfg: params.cfg, accountId });
237
- const currentPolicy = existingConfig.autoJoin ?? "off";
238
- const currentAllowlist = (existingConfig.autoJoinAllowlist ?? []).map((entry) => String(entry));
239
- const hasExistingConfig = existingConfig.autoJoin !== undefined || currentAllowlist.length > 0;
240
-
241
- await params.prompter.note(
242
- [
243
- "WARNING: Matrix invite auto-join defaults to off.",
244
- "Klaw agents will not join invited rooms or fresh DM-style invites unless you set autoJoin.",
245
- 'Choose "allowlist" to restrict joins or "always" to join every invite.',
246
- ].join("\n"),
247
- "Matrix invite auto-join",
248
- );
249
-
250
- const wants = await params.prompter.confirm({
251
- message: hasExistingConfig
252
- ? "Update Matrix invite auto-join?"
253
- : "Configure Matrix invite auto-join?",
254
- initialValue: hasExistingConfig ? currentPolicy !== "off" : true,
255
- });
256
- if (!wants) {
257
- return params.cfg;
258
- }
259
-
260
- const selectedPolicy = await params.prompter.select({
261
- message: "Matrix invite auto-join",
262
- options: matrixInviteAutoJoinOptions,
263
- initialValue: currentPolicy,
264
- });
265
- if (!isMatrixInviteAutoJoinPolicy(selectedPolicy)) {
266
- throw new Error(`Unsupported Matrix invite auto-join policy: ${String(selectedPolicy)}`);
267
- }
268
- const policy = selectedPolicy;
269
-
270
- if (policy === "off") {
271
- await params.prompter.note(
272
- [
273
- "Matrix invite auto-join remains off.",
274
- "Agents will not join invited rooms or fresh DM-style invites until you change autoJoin.",
275
- ].join("\n"),
276
- "Matrix invite auto-join",
277
- );
278
- return setMatrixAutoJoin(params.cfg, policy, [], accountId);
279
- }
280
-
281
- if (policy === "always") {
282
- return setMatrixAutoJoin(params.cfg, policy, [], accountId);
283
- }
284
-
285
- while (true) {
286
- const rawAllowlist = await params.prompter.text({
287
- message: "Matrix invite auto-join allowlist (comma-separated)",
288
- placeholder: "!roomId:server, #alias:server, *",
289
- initialValue: currentAllowlist[0] ? currentAllowlist.join(", ") : undefined,
290
- validate: (value) => {
291
- const entries = splitSetupEntries(value);
292
- return entries.length > 0 ? undefined : "Required";
293
- },
294
- });
295
- const allowlist = normalizeMatrixInviteAutoJoinTargets(splitSetupEntries(rawAllowlist));
296
- const invalidEntries = allowlist.filter((entry) => !isMatrixInviteAutoJoinTarget(entry));
297
- if (allowlist.length === 0 || invalidEntries.length > 0) {
298
- await params.prompter.note(
299
- [
300
- "Use only stable Matrix invite targets for auto-join: !roomId:server, #alias:server, or *.",
301
- invalidEntries.length > 0 ? `Invalid: ${invalidEntries.join(", ")}` : undefined,
302
- ]
303
- .filter(Boolean)
304
- .join("\n"),
305
- "Matrix invite auto-join",
306
- );
307
- continue;
308
- }
309
- return setMatrixAutoJoin(params.cfg, "allowlist", allowlist, accountId);
310
- }
311
- }
312
-
313
- async function configureMatrixAccessPrompts(params: {
314
- cfg: CoreConfig;
315
- prompter: WizardPrompter;
316
- forceAllowFrom: boolean;
317
- accountId: string;
318
- }): Promise<CoreConfig> {
319
- let next = params.cfg;
320
-
321
- if (params.forceAllowFrom) {
322
- next = await promptMatrixAllowFrom({
323
- cfg: next,
324
- prompter: params.prompter,
325
- accountId: params.accountId,
326
- });
327
- }
328
-
329
- const existingAccountConfig = resolveMatrixAccountConfig({
330
- cfg: next,
331
- accountId: params.accountId,
332
- });
333
- const existingGroups = existingAccountConfig.groups ?? existingAccountConfig.rooms;
334
- const accessConfig = await promptChannelAccessConfig({
335
- prompter: params.prompter,
336
- label: "Matrix rooms",
337
- currentPolicy: existingAccountConfig.groupPolicy ?? "allowlist",
338
- currentEntries: Object.keys(existingGroups ?? {}),
339
- placeholder: "!roomId:server, #alias:server, Project Room",
340
- updatePrompt: Boolean(existingGroups),
341
- });
342
- if (accessConfig) {
343
- if (accessConfig.policy !== "allowlist") {
344
- next = setMatrixGroupPolicy(next, accessConfig.policy, params.accountId);
345
- } else {
346
- let roomKeys = accessConfig.entries;
347
- if (accessConfig.entries.length > 0) {
348
- try {
349
- const resolvedIds: string[] = [];
350
- const unresolved: string[] = [];
351
- for (const entry of accessConfig.entries) {
352
- const trimmed = normalizeOptionalString(entry) ?? "";
353
- if (!trimmed) {
354
- continue;
355
- }
356
- const cleaned = trimmed.replace(/^(room|channel):/i, "").trim();
357
- if (cleaned.startsWith("!") && cleaned.includes(":")) {
358
- resolvedIds.push(cleaned);
359
- continue;
360
- }
361
- const { listMatrixDirectoryGroupsLive } = await import("./directory-live.js");
362
- const matches = await listMatrixDirectoryGroupsLive({
363
- cfg: next,
364
- accountId: params.accountId,
365
- query: trimmed,
366
- limit: 10,
367
- });
368
- const exact = matches.find(
369
- (match) =>
370
- normalizeLowercaseStringOrEmpty(match.name) ===
371
- normalizeLowercaseStringOrEmpty(trimmed),
372
- );
373
- const best = exact ?? matches[0];
374
- if (best?.id) {
375
- resolvedIds.push(best.id);
376
- } else {
377
- unresolved.push(entry);
378
- }
379
- }
380
- roomKeys = [
381
- ...resolvedIds,
382
- ...unresolved
383
- .map((entry) => normalizeOptionalString(entry))
384
- .filter((entry): entry is string => Boolean(entry)),
385
- ];
386
- if (resolvedIds.length > 0 || unresolved.length > 0) {
387
- await params.prompter.note(
388
- [
389
- resolvedIds.length > 0 ? `Resolved: ${resolvedIds.join(", ")}` : undefined,
390
- unresolved.length > 0
391
- ? `Unresolved (kept as typed): ${unresolved.join(", ")}`
392
- : undefined,
393
- ]
394
- .filter(Boolean)
395
- .join("\n"),
396
- "Matrix rooms",
397
- );
398
- }
399
- } catch (err) {
400
- await params.prompter.note(
401
- `Room lookup failed; keeping entries as typed. ${String(err)}`,
402
- "Matrix rooms",
403
- );
404
- }
405
- }
406
- next = setMatrixGroupPolicy(next, "allowlist", params.accountId);
407
- next = setMatrixGroupRooms(next, roomKeys, params.accountId);
408
- }
409
- }
410
-
411
- return await configureMatrixInviteAutoJoin({
412
- cfg: next,
413
- prompter: params.prompter,
414
- accountId: params.accountId,
415
- });
416
- }
417
-
418
- const dmPolicy: ChannelSetupDmPolicy = {
419
- label: "Matrix",
420
- channel,
421
- policyKey: "channels.matrix.dm.policy",
422
- allowFromKey: "channels.matrix.dm.allowFrom",
423
- resolveConfigKeys: (cfg, accountId) => {
424
- const effectiveAccountId = resolveMatrixOnboardingAccountId(cfg as CoreConfig, accountId);
425
- return {
426
- policyKey: resolveMatrixConfigFieldPath(cfg as CoreConfig, effectiveAccountId, "dm.policy"),
427
- allowFromKey: resolveMatrixConfigFieldPath(
428
- cfg as CoreConfig,
429
- effectiveAccountId,
430
- "dm.allowFrom",
431
- ),
432
- };
433
- },
434
- getCurrent: (cfg, accountId) =>
435
- resolveMatrixAccountConfig({
436
- cfg: cfg as CoreConfig,
437
- accountId: resolveMatrixOnboardingAccountId(cfg as CoreConfig, accountId),
438
- }).dm?.policy ?? "pairing",
439
- setPolicy: (cfg, policy, accountId) => setMatrixDmPolicy(cfg as CoreConfig, policy, accountId),
440
- promptAllowFrom: promptMatrixAllowFrom,
441
- };
442
-
443
- type MatrixConfigureIntent = "update" | "add-account";
444
-
445
- async function runMatrixConfigure(params: {
446
- cfg: CoreConfig;
447
- runtime: RuntimeEnv;
448
- prompter: WizardPrompter;
449
- forceAllowFrom: boolean;
450
- accountOverrides?: Partial<Record<string, string>>;
451
- shouldPromptAccountIds?: boolean;
452
- intent: MatrixConfigureIntent;
453
- }): Promise<{ cfg: CoreConfig; accountId: string }> {
454
- let next = params.cfg;
455
- await ensureMatrixSdkInstalled({
456
- runtime: params.runtime,
457
- confirm: async (message) =>
458
- await params.prompter.confirm({
459
- message,
460
- initialValue: true,
461
- }),
462
- });
463
- const defaultAccountId = resolveDefaultMatrixAccountId(next);
464
- let accountId = defaultAccountId || DEFAULT_ACCOUNT_ID;
465
- if (params.intent === "add-account") {
466
- const enteredName =
467
- normalizeStringifiedOptionalString(
468
- await params.prompter.text({
469
- message: "Matrix account name",
470
- validate: (value) => (normalizeOptionalString(value) ? undefined : "Required"),
471
- }),
472
- ) ?? "";
473
- accountId = normalizeAccountId(enteredName);
474
- if (enteredName !== accountId) {
475
- await params.prompter.note(`Account id will be "${accountId}".`, "Matrix account");
476
- }
477
- if (accountId !== DEFAULT_ACCOUNT_ID) {
478
- next = moveSingleMatrixAccountConfigToNamedAccount(next);
479
- }
480
- next = updateMatrixAccountConfig(next, accountId, { name: enteredName, enabled: true });
481
- } else {
482
- const override = normalizeOptionalString(params.accountOverrides?.[channel]);
483
- if (override) {
484
- accountId = normalizeAccountId(override);
485
- } else if (params.shouldPromptAccountIds) {
486
- accountId = await promptAccountId({
487
- cfg: next,
488
- prompter: params.prompter,
489
- label: "Matrix",
490
- currentId: accountId,
491
- listAccountIds: (inputCfg) => listMatrixAccountIds(inputCfg as CoreConfig),
492
- defaultAccountId,
493
- });
494
- }
495
- }
496
-
497
- const existing = resolveMatrixAccountConfig({ cfg: next, accountId });
498
- const account = resolveMatrixAccount({ cfg: next, accountId });
499
- if (!account.configured) {
500
- await noteMatrixAuthHelp(params.prompter);
501
- }
502
-
503
- const envReadiness = resolveMatrixEnvAuthReadiness(accountId, process.env);
504
- const envReady = envReadiness.ready;
505
- const envHomeserver = envReadiness.homeserver;
506
- const envUserId = envReadiness.userId;
507
-
508
- if (
509
- envReady &&
510
- !existing.homeserver &&
511
- !existing.userId &&
512
- !existing.accessToken &&
513
- !existing.password
514
- ) {
515
- const useEnv = await params.prompter.confirm({
516
- message: `Matrix env vars detected (${envReadiness.sourceHint}). Use env values?`,
517
- initialValue: true,
518
- });
519
- if (useEnv) {
520
- next = updateMatrixAccountConfig(next, accountId, { enabled: true });
521
- next = await configureMatrixAccessPrompts({
522
- cfg: next,
523
- prompter: params.prompter,
524
- forceAllowFrom: params.forceAllowFrom,
525
- accountId,
526
- });
527
- return { cfg: next, accountId };
528
- }
529
- }
530
-
531
- const homeserver =
532
- normalizeStringifiedOptionalString(
533
- await params.prompter.text({
534
- message: "Matrix homeserver URL",
535
- initialValue: existing.homeserver ?? envHomeserver,
536
- validate: (value) => {
537
- try {
538
- validateMatrixHomeserverUrl(value, {
539
- allowPrivateNetwork: true,
540
- });
541
- return undefined;
542
- } catch (error) {
543
- return error instanceof Error ? error.message : "Invalid Matrix homeserver URL";
544
- }
545
- },
546
- }),
547
- ) ?? "";
548
- const requiresAllowPrivateNetwork = requiresMatrixPrivateNetworkOptIn(homeserver);
549
- const shouldPromptAllowPrivateNetwork =
550
- requiresAllowPrivateNetwork || isPrivateNetworkOptInEnabled(existing);
551
- const allowPrivateNetwork = shouldPromptAllowPrivateNetwork
552
- ? await params.prompter.confirm({
553
- message: "Allow private/internal Matrix homeserver traffic for this account?",
554
- initialValue: isPrivateNetworkOptInEnabled(existing) || requiresAllowPrivateNetwork,
555
- })
556
- : false;
557
- if (requiresAllowPrivateNetwork && !allowPrivateNetwork) {
558
- throw new Error("Matrix homeserver requires explicit private-network opt-in");
559
- }
560
- await resolveValidatedMatrixHomeserverUrl(homeserver, {
561
- dangerouslyAllowPrivateNetwork: allowPrivateNetwork,
562
- });
563
-
564
- let accessToken = existing.accessToken;
565
- let password = existing.password;
566
- let userId = existing.userId ?? "";
567
-
568
- if (hasConfiguredSecretInput(accessToken) || hasConfiguredSecretInput(password)) {
569
- const keep = await params.prompter.confirm({
570
- message: "Matrix credentials already configured. Keep them?",
571
- initialValue: true,
572
- });
573
- if (!keep) {
574
- accessToken = undefined;
575
- password = undefined;
576
- userId = "";
577
- }
578
- }
579
-
580
- if (!hasConfiguredSecretInput(accessToken) && !hasConfiguredSecretInput(password)) {
581
- const authMode = await params.prompter.select({
582
- message: "Matrix auth method",
583
- options: [
584
- { value: "token", label: "Access token (user ID fetched automatically)" },
585
- { value: "password", label: "Password (requires user ID)" },
586
- ],
587
- });
588
-
589
- if (authMode === "token") {
590
- accessToken =
591
- normalizeStringifiedOptionalString(
592
- await params.prompter.text({
593
- message: "Matrix access token",
594
- validate: (value) => (normalizeOptionalString(value) ? undefined : "Required"),
595
- }),
596
- ) ?? "";
597
- password = undefined;
598
- userId = "";
599
- } else {
600
- userId =
601
- normalizeStringifiedOptionalString(
602
- await params.prompter.text({
603
- message: "Matrix user ID",
604
- initialValue: existing.userId ?? envUserId,
605
- validate: (value) => {
606
- const raw = normalizeOptionalString(value) ?? "";
607
- if (!raw) {
608
- return "Required";
609
- }
610
- if (!raw.startsWith("@")) {
611
- return "Matrix user IDs should start with @";
612
- }
613
- if (!raw.includes(":")) {
614
- return "Matrix user IDs should include a server (:server)";
615
- }
616
- return undefined;
617
- },
618
- }),
619
- ) ?? "";
620
- password =
621
- normalizeStringifiedOptionalString(
622
- await params.prompter.text({
623
- message: "Matrix password",
624
- validate: (value) => (normalizeOptionalString(value) ? undefined : "Required"),
625
- }),
626
- ) ?? "";
627
- accessToken = undefined;
628
- }
629
- }
630
-
631
- const deviceName =
632
- normalizeStringifiedOptionalString(
633
- await params.prompter.text({
634
- message: "Matrix device name (optional)",
635
- initialValue: existing.deviceName ?? "Klaw Gateway",
636
- }),
637
- ) ?? "";
638
-
639
- const enableEncryption = await params.prompter.confirm({
640
- message: "Enable end-to-end encryption (E2EE)?",
641
- initialValue: existing.encryption ?? false,
642
- });
643
-
644
- next = updateMatrixAccountConfig(next, accountId, {
645
- enabled: true,
646
- homeserver,
647
- ...(shouldPromptAllowPrivateNetwork
648
- ? { allowPrivateNetwork: allowPrivateNetwork ? true : null }
649
- : {}),
650
- userId: userId || null,
651
- accessToken: accessToken ?? null,
652
- password: password ?? null,
653
- deviceName: deviceName || null,
654
- encryption: enableEncryption,
655
- });
656
-
657
- next = await configureMatrixAccessPrompts({
658
- cfg: next,
659
- prompter: params.prompter,
660
- forceAllowFrom: params.forceAllowFrom,
661
- accountId,
662
- });
663
-
664
- return { cfg: next, accountId };
665
- }
666
-
667
- export const matrixOnboardingAdapter: ChannelSetupWizardAdapter = {
668
- channel,
669
- getStatus: async ({ cfg, accountOverrides }) => {
670
- const resolvedCfg = cfg as CoreConfig;
671
- const sdkReady = isMatrixSdkAvailable();
672
- if (!accountOverrides[channel] && requiresExplicitMatrixDefaultAccount(resolvedCfg)) {
673
- return {
674
- channel,
675
- configured: false,
676
- statusLines: ['Matrix: set "channels.matrix.defaultAccount" to select a named account'],
677
- selectionHint: !sdkReady ? "install Matrix deps" : "set defaultAccount",
678
- };
679
- }
680
- const account = resolveMatrixAccount({
681
- cfg: resolvedCfg,
682
- accountId: resolveMatrixOnboardingAccountId(resolvedCfg, accountOverrides[channel]),
683
- });
684
- const configured = account.configured;
685
- return {
686
- channel,
687
- configured,
688
- statusLines: [
689
- `Matrix: ${configured ? "configured" : "needs homeserver + access token or password"}`,
690
- ],
691
- selectionHint: !sdkReady ? "install Matrix deps" : configured ? "configured" : "needs auth",
692
- };
693
- },
694
- configure: async ({
695
- cfg,
696
- runtime,
697
- prompter,
698
- forceAllowFrom,
699
- accountOverrides,
700
- shouldPromptAccountIds,
701
- }) =>
702
- await runMatrixConfigure({
703
- cfg: cfg as CoreConfig,
704
- runtime,
705
- prompter,
706
- forceAllowFrom,
707
- accountOverrides,
708
- shouldPromptAccountIds,
709
- intent: "update",
710
- }),
711
- configureInteractive: async ({
712
- cfg,
713
- runtime,
714
- prompter,
715
- forceAllowFrom,
716
- accountOverrides,
717
- shouldPromptAccountIds,
718
- configured,
719
- }) => {
720
- if (!configured) {
721
- return await runMatrixConfigure({
722
- cfg: cfg as CoreConfig,
723
- runtime,
724
- prompter,
725
- forceAllowFrom,
726
- accountOverrides,
727
- shouldPromptAccountIds,
728
- intent: "update",
729
- });
730
- }
731
- const action = await prompter.select({
732
- message: "Matrix already configured. What do you want to do?",
733
- options: [
734
- { value: "update", label: "Modify settings" },
735
- { value: "add-account", label: "Add account" },
736
- { value: "skip", label: "Skip (leave as-is)" },
737
- ],
738
- initialValue: "update",
739
- });
740
- if (action === "skip") {
741
- return "skip";
742
- }
743
- return await runMatrixConfigure({
744
- cfg: cfg as CoreConfig,
745
- runtime,
746
- prompter,
747
- forceAllowFrom,
748
- accountOverrides,
749
- shouldPromptAccountIds,
750
- intent: action === "add-account" ? "add-account" : "update",
751
- });
752
- },
753
- afterConfigWritten: async ({ previousCfg, cfg, accountId, runtime }) => {
754
- const { runMatrixSetupBootstrapAfterConfigWrite } = await import("./setup-bootstrap.js");
755
- await runMatrixSetupBootstrapAfterConfigWrite({
756
- previousCfg: previousCfg as CoreConfig,
757
- cfg: cfg as CoreConfig,
758
- accountId,
759
- runtime,
760
- });
761
- },
762
- dmPolicy,
763
- disable: (cfg) => ({
764
- ...(cfg as CoreConfig),
765
- channels: {
766
- ...(cfg as CoreConfig).channels,
767
- matrix: { ...(cfg as CoreConfig).channels?.["matrix"], enabled: false },
768
- },
769
- }),
770
- };
771
-
772
- export const testing = {
773
- promptMatrixAllowFrom,
774
- };
775
- export { testing as __testing };