@kodelyth/matrix 2026.5.39 → 2026.6.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 (117) hide show
  1. package/dist/account-selection-Y50DNJ2l.js +158 -0
  2. package/dist/active-client-CmFdvPdO.js +20 -0
  3. package/dist/api.js +12 -0
  4. package/dist/approval-handler.runtime-BIi4fL0R.js +377 -0
  5. package/dist/approval-ids-BGHK7PnZ.js +7 -0
  6. package/dist/approval-reaction-auth-CL0-nCNV.js +27 -0
  7. package/dist/approval-reactions-nDm2x-K5.js +162 -0
  8. package/dist/async-lock-SsmtFXtt.js +19 -0
  9. package/dist/auth-presence.js +26 -0
  10. package/dist/backup-health-3BHbHxyd.js +60 -0
  11. package/dist/channel-C0kCyTNB.js +1380 -0
  12. package/dist/channel-plugin-api.js +2 -0
  13. package/dist/channel.runtime-CdrdEN-0.js +250 -0
  14. package/dist/cli-FtY6Nuzw.js +1338 -0
  15. package/dist/cli-metadata-Dkwua7CB.js +22 -0
  16. package/dist/cli-metadata.js +2 -0
  17. package/dist/client-BnohYygh.js +25 -0
  18. package/dist/client-PhrTwuC4.js +30 -0
  19. package/dist/client-bootstrap-Mcj8ChJ5.js +114 -0
  20. package/dist/config-paths-DVvt6vM3.js +114 -0
  21. package/dist/config-schema-BMGOlhdI.js +308 -0
  22. package/dist/config-secret-input.runtime-Dv_4Br_f.js +2 -0
  23. package/dist/contract-api.js +8 -0
  24. package/dist/create-client-J0htTaRj.js +64 -0
  25. package/dist/credentials-B7GsBbgQ.js +56 -0
  26. package/dist/credentials-read-8fE4qoWs.js +112 -0
  27. package/dist/credentials-write.runtime-BibplB4Y.js +17 -0
  28. package/dist/crypto-node.runtime-D9qxgRPa.js +12 -0
  29. package/dist/crypto-runtime-1pKW4O2F.js +1214 -0
  30. package/dist/deps-DVpDS81G.js +208 -0
  31. package/dist/device-health-Ct2wDSPG.js +16 -0
  32. package/dist/directory-live-i3T8uORc.js +150 -0
  33. package/dist/doctor-contract-BLzYHl_9.js +246 -0
  34. package/dist/doctor-contract-api.js +2 -0
  35. package/dist/doctor-diR5gE7D.js +153 -0
  36. package/dist/draft-stream-HpPJ_VJt.js +143 -0
  37. package/dist/encryption-guidance-BNEgckrZ.js +15 -0
  38. package/dist/env-auth-UFiTGkDM.js +63 -0
  39. package/dist/env-vars-EQKQv-FE.js +63 -0
  40. package/dist/errors-BETj3zr9.js +17 -0
  41. package/dist/exec-approval-resolver-BxPorU_t.js +15 -0
  42. package/dist/helper-api.js +4 -0
  43. package/dist/http-client-DoQgbQsU.js +331 -0
  44. package/dist/index.js +46 -0
  45. package/dist/legacy-crypto-inspector-zK0hDCbt.js +41 -0
  46. package/dist/legacy-crypto-restore-DSFIXuDo.js +85 -0
  47. package/dist/logging-Df7aPD1z.js +99 -0
  48. package/dist/matrix-migration.runtime-BNoT1Prt.js +525 -0
  49. package/dist/media-text-ZhGA8Pcs.js +146 -0
  50. package/dist/messages-CRA9WGg0.js +140 -0
  51. package/dist/migration-snapshot-backup-BR-xD7Ew.js +69 -0
  52. package/dist/migration-snapshot.runtime-BLcy_Nvw.js +2 -0
  53. package/dist/monitor-DQm7_13y.js +4331 -0
  54. package/dist/plugin-entry.handlers.runtime.js +51 -0
  55. package/dist/probe.runtime-CjJS53Kz.js +3 -0
  56. package/dist/profile-update-DqkPgZ1P.js +68 -0
  57. package/dist/reaction-common-CmVLzP-u.js +71 -0
  58. package/dist/reaction-events-D0nUJuZV.js +121 -0
  59. package/dist/record-shared-DGvSFn5M.js +2 -0
  60. package/dist/resolve-targets-ChECUzD2.js +140 -0
  61. package/dist/resolver.runtime-hdY3n0GO.js +5 -0
  62. package/dist/rolldown-runtime-DUslC3ob.js +14 -0
  63. package/dist/route-xRKj_ESW.js +161 -0
  64. package/dist/runtime-B-Fyrmxo.js +8 -0
  65. package/dist/runtime-api-BYXXkxq2.js +24 -0
  66. package/dist/runtime-api.js +25 -0
  67. package/dist/runtime-heavy-api.js +3 -0
  68. package/dist/runtime-lwTSy9Yt.js +6 -0
  69. package/dist/runtime-setter-api.js +2 -0
  70. package/dist/sdk-Jhq7mLtD.js +1704 -0
  71. package/dist/secret-contract-DEMcDsjl.js +120 -0
  72. package/dist/secret-contract-api.js +2 -0
  73. package/dist/send-CJunc6QM.js +1517 -0
  74. package/dist/setup-bootstrap-rJ0qZWPe.js +62 -0
  75. package/dist/setup-core-BEYoXF3J.js +677 -0
  76. package/dist/setup-entry.js +19 -0
  77. package/dist/setup-plugin-api.js +43 -0
  78. package/dist/setup-surface-c28ON6jq.js +537 -0
  79. package/dist/shared-D6MFMnpG.js +642 -0
  80. package/dist/startup-abort-B2J3MU_h.js +109 -0
  81. package/dist/startup-verification-CkD4Cwce.js +132 -0
  82. package/dist/storage-nyO0DOFE.js +281 -0
  83. package/dist/storage-paths-BTAketfg.js +52 -0
  84. package/dist/subagent-hooks-api-Dr_xnMRG.js +170 -0
  85. package/dist/subagent-hooks-api.js +2 -0
  86. package/dist/sync-state-Bx0gPaGA.js +12 -0
  87. package/dist/target-ids-Bsazo8si.js +77 -0
  88. package/dist/test-api.js +4 -0
  89. package/dist/thread-binding-api-IGU0-L70.js +17 -0
  90. package/dist/thread-binding-api.js +2 -0
  91. package/dist/thread-bindings-FjAZmDUP.js +352 -0
  92. package/dist/thread-bindings-runtime.js +2 -0
  93. package/dist/thread-bindings-shared-fvfP7jVs.js +97 -0
  94. package/dist/timeout-abort-signal-DpSHDHhR.js +2 -0
  95. package/dist/tool-actions.runtime-Cbo7YcYZ.js +532 -0
  96. package/dist/url-validation-DlrXNjAE.js +36 -0
  97. package/dist/verification-7tDPRpJU.js +345 -0
  98. package/package.json +19 -7
  99. package/api.js +0 -7
  100. package/auth-presence.js +0 -7
  101. package/channel-plugin-api.js +0 -7
  102. package/cli-metadata.js +0 -7
  103. package/contract-api.js +0 -7
  104. package/doctor-contract-api.js +0 -7
  105. package/helper-api.js +0 -7
  106. package/index.js +0 -7
  107. package/plugin-entry.handlers.runtime.js +0 -7
  108. package/runtime-api.js +0 -7
  109. package/runtime-heavy-api.js +0 -7
  110. package/runtime-setter-api.js +0 -7
  111. package/secret-contract-api.js +0 -7
  112. package/setup-entry.js +0 -7
  113. package/setup-plugin-api.js +0 -7
  114. package/subagent-hooks-api.js +0 -7
  115. package/test-api.js +0 -7
  116. package/thread-binding-api.js +0 -7
  117. package/thread-bindings-runtime.js +0 -7
@@ -0,0 +1,97 @@
1
+ import { resolveThreadBindingLifecycle } from "klaw/plugin-sdk/thread-bindings-session-runtime";
2
+ //#region extensions/matrix/src/matrix/thread-bindings-shared.ts
3
+ const MANAGERS_BY_ACCOUNT_ID = /* @__PURE__ */ new Map();
4
+ const BINDINGS_BY_ACCOUNT_CONVERSATION = /* @__PURE__ */ new Map();
5
+ function resolveBindingKey(params) {
6
+ return `${params.accountId}:${params.parentConversationId?.trim() || "-"}:${params.conversationId}`;
7
+ }
8
+ function toSessionBindingTargetKind(raw) {
9
+ return raw === "subagent" ? "subagent" : "session";
10
+ }
11
+ function toMatrixBindingTargetKind(raw) {
12
+ return raw === "subagent" ? "subagent" : "acp";
13
+ }
14
+ function resolveEffectiveBindingExpiry(params) {
15
+ return resolveThreadBindingLifecycle(params);
16
+ }
17
+ function toSessionBindingRecord(record, defaults) {
18
+ const lifecycle = resolveEffectiveBindingExpiry({
19
+ record,
20
+ defaultIdleTimeoutMs: defaults.idleTimeoutMs,
21
+ defaultMaxAgeMs: defaults.maxAgeMs
22
+ });
23
+ const idleTimeoutMs = typeof record.idleTimeoutMs === "number" ? record.idleTimeoutMs : defaults.idleTimeoutMs;
24
+ const maxAgeMs = typeof record.maxAgeMs === "number" ? record.maxAgeMs : defaults.maxAgeMs;
25
+ return {
26
+ bindingId: resolveBindingKey(record),
27
+ targetSessionKey: record.targetSessionKey,
28
+ targetKind: toSessionBindingTargetKind(record.targetKind),
29
+ conversation: {
30
+ channel: "matrix",
31
+ accountId: record.accountId,
32
+ conversationId: record.conversationId,
33
+ parentConversationId: record.parentConversationId
34
+ },
35
+ status: "active",
36
+ boundAt: record.boundAt,
37
+ expiresAt: lifecycle.expiresAt,
38
+ metadata: {
39
+ agentId: record.agentId,
40
+ label: record.label,
41
+ boundBy: record.boundBy,
42
+ lastActivityAt: record.lastActivityAt,
43
+ idleTimeoutMs,
44
+ maxAgeMs
45
+ }
46
+ };
47
+ }
48
+ function setBindingRecord(record) {
49
+ BINDINGS_BY_ACCOUNT_CONVERSATION.set(resolveBindingKey(record), record);
50
+ }
51
+ function removeBindingRecord(record) {
52
+ const key = resolveBindingKey(record);
53
+ const removed = BINDINGS_BY_ACCOUNT_CONVERSATION.get(key) ?? null;
54
+ if (removed) BINDINGS_BY_ACCOUNT_CONVERSATION.delete(key);
55
+ return removed;
56
+ }
57
+ function listBindingsForAccount(accountId) {
58
+ return [...BINDINGS_BY_ACCOUNT_CONVERSATION.values()].filter((entry) => entry.accountId === accountId);
59
+ }
60
+ function listAllBindings() {
61
+ return [...BINDINGS_BY_ACCOUNT_CONVERSATION.values()];
62
+ }
63
+ function getMatrixThreadBindingManagerEntry(accountId) {
64
+ return MANAGERS_BY_ACCOUNT_ID.get(accountId) ?? null;
65
+ }
66
+ function setMatrixThreadBindingManagerEntry(accountId, entry) {
67
+ MANAGERS_BY_ACCOUNT_ID.set(accountId, entry);
68
+ }
69
+ function deleteMatrixThreadBindingManagerEntry(accountId) {
70
+ MANAGERS_BY_ACCOUNT_ID.delete(accountId);
71
+ }
72
+ function getMatrixThreadBindingManager(accountId) {
73
+ return MANAGERS_BY_ACCOUNT_ID.get(accountId)?.manager ?? null;
74
+ }
75
+ function setMatrixThreadBindingIdleTimeoutBySessionKey(params) {
76
+ const manager = MANAGERS_BY_ACCOUNT_ID.get(params.accountId)?.manager;
77
+ if (!manager) return [];
78
+ return manager.setIdleTimeoutBySessionKey(params).map((record) => toSessionBindingRecord(record, {
79
+ idleTimeoutMs: manager.getIdleTimeoutMs(),
80
+ maxAgeMs: manager.getMaxAgeMs()
81
+ }));
82
+ }
83
+ function setMatrixThreadBindingMaxAgeBySessionKey(params) {
84
+ const manager = MANAGERS_BY_ACCOUNT_ID.get(params.accountId)?.manager;
85
+ if (!manager) return [];
86
+ return manager.setMaxAgeBySessionKey(params).map((record) => toSessionBindingRecord(record, {
87
+ idleTimeoutMs: manager.getIdleTimeoutMs(),
88
+ maxAgeMs: manager.getMaxAgeMs()
89
+ }));
90
+ }
91
+ function resetMatrixThreadBindingsForTests() {
92
+ for (const { manager } of MANAGERS_BY_ACCOUNT_ID.values()) manager.stop();
93
+ MANAGERS_BY_ACCOUNT_ID.clear();
94
+ BINDINGS_BY_ACCOUNT_CONVERSATION.clear();
95
+ }
96
+ //#endregion
97
+ export { listBindingsForAccount as a, resolveBindingKey as c, setMatrixThreadBindingIdleTimeoutBySessionKey as d, setMatrixThreadBindingManagerEntry as f, toSessionBindingRecord as h, listAllBindings as i, resolveEffectiveBindingExpiry as l, toMatrixBindingTargetKind as m, getMatrixThreadBindingManager as n, removeBindingRecord as o, setMatrixThreadBindingMaxAgeBySessionKey as p, getMatrixThreadBindingManagerEntry as r, resetMatrixThreadBindingsForTests as s, deleteMatrixThreadBindingManagerEntry as t, setBindingRecord as u };
@@ -0,0 +1,2 @@
1
+ import { buildTimeoutAbortSignal } from "klaw/plugin-sdk/extension-shared";
2
+ export { buildTimeoutAbortSignal as t };
@@ -0,0 +1,532 @@
1
+ import { c as resolveMatrixAccountConfig } from "./config-paths-DVvt6vM3.js";
2
+ import "./setup-core-BEYoXF3J.js";
3
+ import { E as parsePollStart, T as isPollStartType, b as buildPollResponseContent, i as reactMatrixMessage, u as resolveMatrixRoomId } from "./send-CJunc6QM.js";
4
+ import { i as buildMatrixReactionRelationsPath, o as selectOwnMatrixReactionEventIds, s as summarizeMatrixReactionEvents } from "./reaction-common-CmVLzP-u.js";
5
+ import { n as withResolvedActionClient, r as withResolvedRoomAction } from "./client-BnohYygh.js";
6
+ import { a as fetchEventSummary, c as resolveMatrixActionLimit, i as sendMatrixMessage, n as editMatrixMessage, o as readPinnedEvents, r as readMatrixMessages, s as EventType, t as deleteMatrixMessage } from "./messages-CRA9WGg0.js";
7
+ import { a as jsonResult, c as readStringArrayParam, l as readStringParam, o as readNumberParam, r as createActionGate, s as readReactionParams } from "./runtime-api-BYXXkxq2.js";
8
+ import { t as applyMatrixProfileUpdate } from "./profile-update-DqkPgZ1P.js";
9
+ import { _ as scanMatrixVerificationQr, a as confirmMatrixVerificationSas, b as verifyMatrixRecoveryKey, c as getMatrixRoomKeyBackupStatus, d as listMatrixVerifications, f as mismatchMatrixVerificationSas, h as restoreMatrixRoomKeyBackup, i as confirmMatrixVerificationReciprocateQr, l as getMatrixVerificationSas, n as bootstrapMatrixVerification, o as generateMatrixVerificationQr, p as requestMatrixVerification, r as cancelMatrixVerification, s as getMatrixEncryptionStatus, t as acceptMatrixVerification, u as getMatrixVerificationStatus, v as startMatrixVerification } from "./verification-7tDPRpJU.js";
10
+ import { normalizeOptionalLowercaseString } from "klaw/plugin-sdk/string-coerce-runtime";
11
+ //#region extensions/matrix/src/matrix/actions/polls.ts
12
+ function normalizeOptionIndexes(indexes) {
13
+ const normalized = indexes.map((index) => Math.trunc(index)).filter((index) => Number.isFinite(index) && index > 0);
14
+ return Array.from(new Set(normalized));
15
+ }
16
+ function normalizeOptionIds(optionIds) {
17
+ return Array.from(new Set(optionIds.map((optionId) => optionId.trim()).filter((optionId) => optionId.length > 0)));
18
+ }
19
+ function resolveSelectedAnswerIds(params) {
20
+ const parsed = parsePollStart(params.pollContent);
21
+ if (!parsed) throw new Error("Matrix poll vote requires a valid poll start event.");
22
+ const selectedById = normalizeOptionIds(params.optionIds ?? []);
23
+ const selectedByIndex = normalizeOptionIndexes(params.optionIndexes ?? []).map((index) => {
24
+ const answer = parsed.answers[index - 1];
25
+ if (!answer) throw new Error(`Matrix poll option index ${index} is out of range for a poll with ${parsed.answers.length} options.`);
26
+ return answer.id;
27
+ });
28
+ const answerIds = normalizeOptionIds([...selectedById, ...selectedByIndex]);
29
+ if (answerIds.length === 0) throw new Error("Matrix poll vote requires at least one poll option id or index.");
30
+ if (answerIds.length > parsed.maxSelections) throw new Error(`Matrix poll allows at most ${parsed.maxSelections} selection${parsed.maxSelections === 1 ? "" : "s"}.`);
31
+ const answerMap = new Map(parsed.answers.map((answer) => [answer.id, answer.text]));
32
+ return {
33
+ answerIds,
34
+ labels: answerIds.map((answerId) => {
35
+ const label = answerMap.get(answerId);
36
+ if (!label) throw new Error(`Matrix poll option id "${answerId}" is not valid for poll ${parsed.question}.`);
37
+ return label;
38
+ }),
39
+ maxSelections: parsed.maxSelections
40
+ };
41
+ }
42
+ async function voteMatrixPoll(roomId, pollId, opts = {}) {
43
+ return await withResolvedRoomAction(roomId, opts, async (client, resolvedRoom) => {
44
+ const pollEvent = await client.getEvent(resolvedRoom, pollId);
45
+ if (!isPollStartType(typeof pollEvent.type === "string" ? pollEvent.type : "")) throw new Error(`Event ${pollId} is not a Matrix poll start event.`);
46
+ const { answerIds, labels, maxSelections } = resolveSelectedAnswerIds({
47
+ optionIds: [...opts.optionIds ?? [], ...opts.optionId ? [opts.optionId] : []],
48
+ optionIndexes: [...opts.optionIndexes ?? [], ...opts.optionIndex !== void 0 ? [opts.optionIndex] : []],
49
+ pollContent: pollEvent.content
50
+ });
51
+ const content = buildPollResponseContent(pollId, answerIds);
52
+ return {
53
+ eventId: await client.sendEvent(resolvedRoom, "m.poll.response", content) ?? null,
54
+ roomId: resolvedRoom,
55
+ pollId,
56
+ answerIds,
57
+ labels,
58
+ maxSelections
59
+ };
60
+ });
61
+ }
62
+ //#endregion
63
+ //#region extensions/matrix/src/matrix/actions/reactions.ts
64
+ async function listMatrixReactionEvents(client, roomId, messageId, limit) {
65
+ const res = await client.doRequest("GET", buildMatrixReactionRelationsPath(roomId, messageId), {
66
+ dir: "b",
67
+ limit
68
+ });
69
+ return Array.isArray(res.chunk) ? res.chunk : [];
70
+ }
71
+ async function listMatrixReactions(roomId, messageId, opts = {}) {
72
+ return await withResolvedRoomAction(roomId, opts, async (client, resolvedRoom) => {
73
+ return summarizeMatrixReactionEvents(await listMatrixReactionEvents(client, resolvedRoom, messageId, resolveMatrixActionLimit(opts.limit, 100)));
74
+ });
75
+ }
76
+ async function removeMatrixReactions(roomId, messageId, opts = {}) {
77
+ return await withResolvedRoomAction(roomId, opts, async (client, resolvedRoom) => {
78
+ const chunk = await listMatrixReactionEvents(client, resolvedRoom, messageId, 200);
79
+ const userId = await client.getUserId();
80
+ if (!userId) return { removed: 0 };
81
+ const toRemove = selectOwnMatrixReactionEventIds(chunk, userId, opts.emoji);
82
+ if (toRemove.length === 0) return { removed: 0 };
83
+ await Promise.all(toRemove.map((id) => client.redactEvent(resolvedRoom, id)));
84
+ return { removed: toRemove.length };
85
+ });
86
+ }
87
+ //#endregion
88
+ //#region extensions/matrix/src/matrix/actions/pins.ts
89
+ async function updateMatrixPins(roomId, opts, update) {
90
+ return await withResolvedRoomAction(roomId, opts, async (client, resolvedRoom) => {
91
+ const next = update(await readPinnedEvents(client, resolvedRoom));
92
+ const payload = { pinned: next };
93
+ await client.sendStateEvent(resolvedRoom, EventType.RoomPinnedEvents, "", payload);
94
+ return { pinned: next };
95
+ });
96
+ }
97
+ async function pinMatrixMessage(roomId, messageId, opts = {}) {
98
+ return await updateMatrixPins(roomId, opts, (current) => current.includes(messageId) ? current : [...current, messageId]);
99
+ }
100
+ async function unpinMatrixMessage(roomId, messageId, opts = {}) {
101
+ return await updateMatrixPins(roomId, opts, (current) => current.filter((id) => id !== messageId));
102
+ }
103
+ async function listMatrixPins(roomId, opts = {}) {
104
+ return await withResolvedRoomAction(roomId, opts, async (client, resolvedRoom) => {
105
+ const pinned = await readPinnedEvents(client, resolvedRoom);
106
+ return {
107
+ pinned,
108
+ events: (await Promise.all(pinned.map(async (eventId) => {
109
+ try {
110
+ return await fetchEventSummary(client, resolvedRoom, eventId);
111
+ } catch {
112
+ return null;
113
+ }
114
+ }))).filter((event) => Boolean(event))
115
+ };
116
+ });
117
+ }
118
+ //#endregion
119
+ //#region extensions/matrix/src/matrix/actions/room.ts
120
+ async function getMatrixMemberInfo(userId, opts = {}) {
121
+ return await withResolvedActionClient(opts, async (client) => {
122
+ const roomId = opts.roomId ? await resolveMatrixRoomId(client, opts.roomId) : void 0;
123
+ const profile = await client.getUserProfile(userId);
124
+ return {
125
+ userId,
126
+ profile: {
127
+ displayName: profile?.displayname ?? null,
128
+ avatarUrl: profile?.avatar_url ?? null
129
+ },
130
+ membership: null,
131
+ powerLevel: null,
132
+ displayName: profile?.displayname ?? null,
133
+ roomId: roomId ?? null
134
+ };
135
+ });
136
+ }
137
+ async function getMatrixRoomInfo(roomId, opts = {}) {
138
+ return await withResolvedRoomAction(roomId, opts, async (client, resolvedRoom) => {
139
+ let name = null;
140
+ let topic = null;
141
+ let canonicalAlias = null;
142
+ let memberCount = null;
143
+ try {
144
+ const nameState = await client.getRoomStateEvent(resolvedRoom, "m.room.name", "");
145
+ name = typeof nameState?.name === "string" ? nameState.name : null;
146
+ } catch {}
147
+ try {
148
+ const topicState = await client.getRoomStateEvent(resolvedRoom, EventType.RoomTopic, "");
149
+ topic = typeof topicState?.topic === "string" ? topicState.topic : null;
150
+ } catch {}
151
+ try {
152
+ const aliasState = await client.getRoomStateEvent(resolvedRoom, "m.room.canonical_alias", "");
153
+ canonicalAlias = typeof aliasState?.alias === "string" ? aliasState.alias : null;
154
+ } catch {}
155
+ try {
156
+ memberCount = (await client.getJoinedRoomMembers(resolvedRoom)).length;
157
+ } catch {}
158
+ return {
159
+ roomId: resolvedRoom,
160
+ name,
161
+ topic,
162
+ canonicalAlias,
163
+ altAliases: [],
164
+ memberCount
165
+ };
166
+ });
167
+ }
168
+ //#endregion
169
+ //#region extensions/matrix/src/tool-actions.ts
170
+ const messageActions = new Set([
171
+ "sendMessage",
172
+ "editMessage",
173
+ "deleteMessage",
174
+ "readMessages"
175
+ ]);
176
+ const reactionActions = new Set(["react", "reactions"]);
177
+ const pinActions = new Set([
178
+ "pinMessage",
179
+ "unpinMessage",
180
+ "listPins"
181
+ ]);
182
+ const pollActions = new Set(["pollVote"]);
183
+ const profileActions = new Set(["setProfile"]);
184
+ const verificationActions = new Set([
185
+ "encryptionStatus",
186
+ "verificationList",
187
+ "verificationRequest",
188
+ "verificationAccept",
189
+ "verificationCancel",
190
+ "verificationStart",
191
+ "verificationGenerateQr",
192
+ "verificationScanQr",
193
+ "verificationSas",
194
+ "verificationConfirm",
195
+ "verificationMismatch",
196
+ "verificationConfirmQr",
197
+ "verificationStatus",
198
+ "verificationBootstrap",
199
+ "verificationRecoveryKey",
200
+ "verificationBackupStatus",
201
+ "verificationBackupRestore"
202
+ ]);
203
+ function readRoomId(params, required = true) {
204
+ const direct = readStringParam(params, "roomId") ?? readStringParam(params, "channelId");
205
+ if (direct) return direct;
206
+ if (!required) return readStringParam(params, "to") ?? "";
207
+ return readStringParam(params, "to", { required: true });
208
+ }
209
+ function toSnakeCaseKey(key) {
210
+ return normalizeOptionalLowercaseString(key.replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2").replace(/([a-z0-9])([A-Z])/g, "$1_$2"));
211
+ }
212
+ function readRawParam(params, key) {
213
+ if (Object.hasOwn(params, key)) return params[key];
214
+ const snakeKey = toSnakeCaseKey(key);
215
+ if (snakeKey !== key && Object.hasOwn(params, snakeKey)) return params[snakeKey];
216
+ }
217
+ function readStringAliasParam(params, keys, options = {}) {
218
+ for (const key of keys) {
219
+ const raw = readRawParam(params, key);
220
+ if (typeof raw !== "string") continue;
221
+ const trimmed = raw.trim();
222
+ if (trimmed) return trimmed;
223
+ }
224
+ if (options.required) throw new Error(`${keys[0]} required`);
225
+ }
226
+ function readNumericArrayParam(params, key, options = {}) {
227
+ const { integer = false } = options;
228
+ const raw = readRawParam(params, key);
229
+ if (raw === void 0) return [];
230
+ return (Array.isArray(raw) ? raw : [raw]).map((value) => {
231
+ if (typeof value === "number" && Number.isFinite(value)) return value;
232
+ if (typeof value === "string") {
233
+ const trimmed = value.trim();
234
+ if (!trimmed) return null;
235
+ const parsed = Number(trimmed);
236
+ return Number.isFinite(parsed) ? parsed : null;
237
+ }
238
+ return null;
239
+ }).filter((value) => value !== null).map((value) => integer ? Math.trunc(value) : value);
240
+ }
241
+ async function handleMatrixAction(params, cfg, opts = {}) {
242
+ const action = readStringParam(params, "action", { required: true });
243
+ const accountId = readStringParam(params, "accountId") ?? void 0;
244
+ const isActionEnabled = createActionGate(resolveMatrixAccountConfig({
245
+ cfg,
246
+ accountId
247
+ }).actions);
248
+ const clientOpts = {
249
+ cfg,
250
+ ...accountId ? { accountId } : {}
251
+ };
252
+ if (reactionActions.has(action)) {
253
+ if (!isActionEnabled("reactions")) throw new Error("Matrix reactions are disabled.");
254
+ const roomId = readRoomId(params);
255
+ const messageId = readStringParam(params, "messageId", { required: true });
256
+ if (action === "react") {
257
+ const { emoji, remove, isEmpty } = readReactionParams(params, { removeErrorMessage: "Emoji is required to remove a Matrix reaction." });
258
+ if (remove || isEmpty) return jsonResult({
259
+ ok: true,
260
+ removed: (await removeMatrixReactions(roomId, messageId, {
261
+ ...clientOpts,
262
+ emoji: remove ? emoji : void 0
263
+ })).removed
264
+ });
265
+ await reactMatrixMessage(roomId, messageId, emoji, clientOpts);
266
+ return jsonResult({
267
+ ok: true,
268
+ added: emoji
269
+ });
270
+ }
271
+ const limit = readNumberParam(params, "limit", { integer: true });
272
+ return jsonResult({
273
+ ok: true,
274
+ reactions: await listMatrixReactions(roomId, messageId, {
275
+ ...clientOpts,
276
+ limit: limit ?? void 0
277
+ })
278
+ });
279
+ }
280
+ if (pollActions.has(action)) {
281
+ const roomId = readRoomId(params);
282
+ const pollId = readStringAliasParam(params, ["pollId", "messageId"], { required: true });
283
+ if (!pollId) throw new Error("pollId required");
284
+ const optionId = readStringParam(params, "pollOptionId");
285
+ const optionIndex = readNumberParam(params, "pollOptionIndex", { integer: true });
286
+ const optionIds = [...readStringArrayParam(params, "pollOptionIds") ?? [], ...optionId ? [optionId] : []];
287
+ const optionIndexes = [...readNumericArrayParam(params, "pollOptionIndexes", { integer: true }), ...optionIndex !== void 0 ? [optionIndex] : []];
288
+ return jsonResult({
289
+ ok: true,
290
+ result: await voteMatrixPoll(roomId, pollId, {
291
+ ...clientOpts,
292
+ optionIds,
293
+ optionIndexes
294
+ })
295
+ });
296
+ }
297
+ if (messageActions.has(action)) {
298
+ if (!isActionEnabled("messages")) throw new Error("Matrix messages are disabled.");
299
+ switch (action) {
300
+ case "sendMessage": {
301
+ const to = readStringParam(params, "to", { required: true });
302
+ const mediaUrl = readStringParam(params, "mediaUrl", { trim: false }) ?? readStringParam(params, "media", { trim: false }) ?? readStringParam(params, "filePath", { trim: false }) ?? readStringParam(params, "path", { trim: false });
303
+ const content = readStringParam(params, "content", {
304
+ required: !mediaUrl,
305
+ allowEmpty: true
306
+ });
307
+ const replyToId = readStringParam(params, "replyToId") ?? readStringParam(params, "replyTo");
308
+ const threadId = readStringParam(params, "threadId");
309
+ const audioAsVoice = typeof readRawParam(params, "audioAsVoice") === "boolean" ? readRawParam(params, "audioAsVoice") : typeof readRawParam(params, "asVoice") === "boolean" ? readRawParam(params, "asVoice") : void 0;
310
+ return jsonResult({
311
+ ok: true,
312
+ result: await sendMatrixMessage(to, content, {
313
+ mediaUrl: mediaUrl ?? void 0,
314
+ mediaLocalRoots: opts.mediaLocalRoots,
315
+ replyToId: replyToId ?? void 0,
316
+ threadId: threadId ?? void 0,
317
+ audioAsVoice,
318
+ ...clientOpts
319
+ })
320
+ });
321
+ }
322
+ case "editMessage": return jsonResult({
323
+ ok: true,
324
+ result: await editMatrixMessage(readRoomId(params), readStringParam(params, "messageId", { required: true }), readStringParam(params, "content", { required: true }), clientOpts)
325
+ });
326
+ case "deleteMessage":
327
+ await deleteMatrixMessage(readRoomId(params), readStringParam(params, "messageId", { required: true }), {
328
+ reason: readStringParam(params, "reason") ?? void 0,
329
+ ...clientOpts
330
+ });
331
+ return jsonResult({
332
+ ok: true,
333
+ deleted: true
334
+ });
335
+ case "readMessages": {
336
+ const roomId = readRoomId(params);
337
+ const limit = readNumberParam(params, "limit", { integer: true });
338
+ const before = readStringParam(params, "before");
339
+ const after = readStringParam(params, "after");
340
+ return jsonResult({
341
+ ok: true,
342
+ ...await readMatrixMessages(roomId, {
343
+ limit: limit ?? void 0,
344
+ before: before ?? void 0,
345
+ after: after ?? void 0,
346
+ ...clientOpts
347
+ })
348
+ });
349
+ }
350
+ default: break;
351
+ }
352
+ }
353
+ if (pinActions.has(action)) {
354
+ if (!isActionEnabled("pins")) throw new Error("Matrix pins are disabled.");
355
+ const roomId = readRoomId(params);
356
+ if (action === "pinMessage") return jsonResult({
357
+ ok: true,
358
+ pinned: (await pinMatrixMessage(roomId, readStringParam(params, "messageId", { required: true }), clientOpts)).pinned
359
+ });
360
+ if (action === "unpinMessage") return jsonResult({
361
+ ok: true,
362
+ pinned: (await unpinMatrixMessage(roomId, readStringParam(params, "messageId", { required: true }), clientOpts)).pinned
363
+ });
364
+ const result = await listMatrixPins(roomId, clientOpts);
365
+ return jsonResult({
366
+ ok: true,
367
+ pinned: result.pinned,
368
+ events: result.events
369
+ });
370
+ }
371
+ if (profileActions.has(action)) {
372
+ if (!isActionEnabled("profile")) throw new Error("Matrix profile updates are disabled.");
373
+ const avatarPath = readStringParam(params, "avatarPath") ?? readStringParam(params, "path") ?? readStringParam(params, "filePath");
374
+ return jsonResult({
375
+ ok: true,
376
+ ...await applyMatrixProfileUpdate({
377
+ cfg,
378
+ account: accountId,
379
+ displayName: readStringParam(params, "displayName") ?? readStringParam(params, "name"),
380
+ avatarUrl: readStringParam(params, "avatarUrl"),
381
+ avatarPath,
382
+ mediaLocalRoots: opts.mediaLocalRoots
383
+ })
384
+ });
385
+ }
386
+ if (action === "memberInfo") {
387
+ if (!isActionEnabled("memberInfo")) throw new Error("Matrix member info is disabled.");
388
+ return jsonResult({
389
+ ok: true,
390
+ member: await getMatrixMemberInfo(readStringParam(params, "userId", { required: true }), {
391
+ roomId: readStringParam(params, "roomId") ?? readStringParam(params, "channelId") ?? void 0,
392
+ ...clientOpts
393
+ })
394
+ });
395
+ }
396
+ if (action === "channelInfo") {
397
+ if (!isActionEnabled("channelInfo")) throw new Error("Matrix room info is disabled.");
398
+ return jsonResult({
399
+ ok: true,
400
+ room: await getMatrixRoomInfo(readRoomId(params), clientOpts)
401
+ });
402
+ }
403
+ if (verificationActions.has(action)) {
404
+ if (!isActionEnabled("verification")) throw new Error("Matrix verification actions are disabled.");
405
+ const requestId = readStringParam(params, "requestId") ?? readStringParam(params, "verificationId") ?? readStringParam(params, "id");
406
+ if (action === "encryptionStatus") return jsonResult({
407
+ ok: true,
408
+ status: await getMatrixEncryptionStatus({
409
+ includeRecoveryKey: params.includeRecoveryKey === true,
410
+ ...clientOpts
411
+ })
412
+ });
413
+ if (action === "verificationStatus") return jsonResult({
414
+ ok: true,
415
+ status: await getMatrixVerificationStatus({
416
+ includeRecoveryKey: params.includeRecoveryKey === true,
417
+ ...clientOpts
418
+ })
419
+ });
420
+ if (action === "verificationBootstrap") {
421
+ const result = await bootstrapMatrixVerification({
422
+ recoveryKey: readStringParam(params, "recoveryKey", { trim: false }) ?? readStringParam(params, "key", { trim: false }) ?? void 0,
423
+ forceResetCrossSigning: params.forceResetCrossSigning === true,
424
+ ...clientOpts
425
+ });
426
+ return jsonResult({
427
+ ok: result.success,
428
+ result
429
+ });
430
+ }
431
+ if (action === "verificationRecoveryKey") {
432
+ const result = await verifyMatrixRecoveryKey(readStringParam({ recoveryKey: readStringParam(params, "recoveryKey", { trim: false }) ?? readStringParam(params, "key", { trim: false }) }, "recoveryKey", {
433
+ required: true,
434
+ trim: false
435
+ }), clientOpts);
436
+ return jsonResult({
437
+ ok: result.success,
438
+ result
439
+ });
440
+ }
441
+ if (action === "verificationBackupStatus") return jsonResult({
442
+ ok: true,
443
+ status: await getMatrixRoomKeyBackupStatus(clientOpts)
444
+ });
445
+ if (action === "verificationBackupRestore") {
446
+ const result = await restoreMatrixRoomKeyBackup({
447
+ recoveryKey: readStringParam(params, "recoveryKey", { trim: false }) ?? readStringParam(params, "key", { trim: false }) ?? void 0,
448
+ ...clientOpts
449
+ });
450
+ return jsonResult({
451
+ ok: result.success,
452
+ result
453
+ });
454
+ }
455
+ if (action === "verificationList") return jsonResult({
456
+ ok: true,
457
+ verifications: await listMatrixVerifications(clientOpts)
458
+ });
459
+ if (action === "verificationRequest") {
460
+ const userId = readStringParam(params, "userId");
461
+ const deviceId = readStringParam(params, "deviceId");
462
+ const roomId = readStringParam(params, "roomId") ?? readStringParam(params, "channelId");
463
+ return jsonResult({
464
+ ok: true,
465
+ verification: await requestMatrixVerification({
466
+ ownUser: typeof params.ownUser === "boolean" ? params.ownUser : void 0,
467
+ userId: userId ?? void 0,
468
+ deviceId: deviceId ?? void 0,
469
+ roomId: roomId ?? void 0,
470
+ ...clientOpts
471
+ })
472
+ });
473
+ }
474
+ if (action === "verificationAccept") return jsonResult({
475
+ ok: true,
476
+ verification: await acceptMatrixVerification(readStringParam({ requestId }, "requestId", { required: true }), clientOpts)
477
+ });
478
+ if (action === "verificationCancel") {
479
+ const reason = readStringParam(params, "reason");
480
+ const code = readStringParam(params, "code");
481
+ return jsonResult({
482
+ ok: true,
483
+ verification: await cancelMatrixVerification(readStringParam({ requestId }, "requestId", { required: true }), {
484
+ reason: reason ?? void 0,
485
+ code: code ?? void 0,
486
+ ...clientOpts
487
+ })
488
+ });
489
+ }
490
+ if (action === "verificationStart") {
491
+ const method = normalizeOptionalLowercaseString(readStringParam(params, "method"));
492
+ if (method && method !== "sas") throw new Error("Matrix verificationStart only supports method=sas; use verificationGenerateQr/verificationScanQr for QR flows.");
493
+ return jsonResult({
494
+ ok: true,
495
+ verification: await startMatrixVerification(readStringParam({ requestId }, "requestId", { required: true }), {
496
+ method: "sas",
497
+ ...clientOpts
498
+ })
499
+ });
500
+ }
501
+ if (action === "verificationGenerateQr") return jsonResult({
502
+ ok: true,
503
+ ...await generateMatrixVerificationQr(readStringParam({ requestId }, "requestId", { required: true }), clientOpts)
504
+ });
505
+ if (action === "verificationScanQr") {
506
+ const qrDataBase64 = readStringParam(params, "qrDataBase64") ?? readStringParam(params, "qrData") ?? readStringParam(params, "qr");
507
+ return jsonResult({
508
+ ok: true,
509
+ verification: await scanMatrixVerificationQr(readStringParam({ requestId }, "requestId", { required: true }), readStringParam({ qrDataBase64 }, "qrDataBase64", { required: true }), clientOpts)
510
+ });
511
+ }
512
+ if (action === "verificationSas") return jsonResult({
513
+ ok: true,
514
+ sas: await getMatrixVerificationSas(readStringParam({ requestId }, "requestId", { required: true }), clientOpts)
515
+ });
516
+ if (action === "verificationConfirm") return jsonResult({
517
+ ok: true,
518
+ verification: await confirmMatrixVerificationSas(readStringParam({ requestId }, "requestId", { required: true }), clientOpts)
519
+ });
520
+ if (action === "verificationMismatch") return jsonResult({
521
+ ok: true,
522
+ verification: await mismatchMatrixVerificationSas(readStringParam({ requestId }, "requestId", { required: true }), clientOpts)
523
+ });
524
+ if (action === "verificationConfirmQr") return jsonResult({
525
+ ok: true,
526
+ verification: await confirmMatrixVerificationReciprocateQr(readStringParam({ requestId }, "requestId", { required: true }), clientOpts)
527
+ });
528
+ }
529
+ throw new Error(`Unsupported Matrix action: ${action}`);
530
+ }
531
+ //#endregion
532
+ export { handleMatrixAction };
@@ -0,0 +1,36 @@
1
+ import { assertHttpUrlTargetsPrivateNetwork, isPrivateOrLoopbackHost } from "klaw/plugin-sdk/ssrf-runtime";
2
+ //#region extensions/matrix/src/matrix/client/url-validation.ts
3
+ const MATRIX_HTTP_HOMESERVER_ERROR = "Matrix homeserver must use https:// unless it targets a private or loopback host";
4
+ function cleanString(value, requiredMessage) {
5
+ const trimmed = typeof value === "string" ? value.trim() : "";
6
+ if (!trimmed) throw new Error(requiredMessage);
7
+ return trimmed;
8
+ }
9
+ function validateMatrixHomeserverUrl(homeserver, opts) {
10
+ const trimmed = cleanString(homeserver, "Matrix homeserver is required (matrix.homeserver)");
11
+ let parsed;
12
+ try {
13
+ parsed = new URL(trimmed);
14
+ } catch {
15
+ throw new Error("Matrix homeserver must be a valid http(s) URL");
16
+ }
17
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") throw new Error("Matrix homeserver must use http:// or https://");
18
+ if (!parsed.hostname) throw new Error("Matrix homeserver must include a hostname");
19
+ if (parsed.username || parsed.password) throw new Error("Matrix homeserver URL must not include embedded credentials");
20
+ if (parsed.search || parsed.hash) throw new Error("Matrix homeserver URL must not include query strings or fragments");
21
+ if (parsed.protocol === "http:" && opts?.allowPrivateNetwork !== true && !isPrivateOrLoopbackHost(parsed.hostname)) throw new Error(MATRIX_HTTP_HOMESERVER_ERROR);
22
+ return trimmed;
23
+ }
24
+ async function resolveValidatedMatrixHomeserverUrl(homeserver, opts) {
25
+ const allowPrivateNetwork = typeof opts?.dangerouslyAllowPrivateNetwork === "boolean" ? opts.dangerouslyAllowPrivateNetwork : opts?.allowPrivateNetwork;
26
+ const normalized = validateMatrixHomeserverUrl(homeserver, { allowPrivateNetwork });
27
+ await assertHttpUrlTargetsPrivateNetwork(normalized, {
28
+ dangerouslyAllowPrivateNetwork: opts?.dangerouslyAllowPrivateNetwork,
29
+ allowPrivateNetwork,
30
+ lookupFn: opts?.lookupFn,
31
+ errorMessage: MATRIX_HTTP_HOMESERVER_ERROR
32
+ });
33
+ return normalized;
34
+ }
35
+ //#endregion
36
+ export { validateMatrixHomeserverUrl as n, isPrivateOrLoopbackHost as r, resolveValidatedMatrixHomeserverUrl as t };