@openclaw/matrix 2026.9.2 → 2026.9.4

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 (68) hide show
  1. package/dist/{account-selection-DA-jfx22.js → account-selection-Bbtc483D.js} +9 -1
  2. package/dist/{accounts-DR1c4xF_.js → accounts-GwSAk9vY.js} +2 -2
  3. package/dist/api.js +6 -6
  4. package/dist/{approval-handler.runtime-BJCD4dLf.js → approval-handler.runtime-6I3IpyeX.js} +6 -6
  5. package/dist/{approval-ids-Bst7HM_o.js → approval-ids-C4NdeXNz.js} +1 -1
  6. package/dist/{approval-reaction-auth-DhH8QOSe.js → approval-reaction-auth-cbltZAUQ.js} +2 -2
  7. package/dist/{channel-Bs8VLb6q.js → channel-Cg97H4c1.js} +13 -202
  8. package/dist/channel-plugin-api.js +1 -1
  9. package/dist/{channel.runtime-CCJRhdH5.js → channel.runtime-Bhpfa1qc.js} +6 -11
  10. package/dist/{channel.setup-DhmDXwPp.js → channel.setup-DmS7m7aT.js} +3 -3
  11. package/dist/{cli-IvDUuiDH.js → cli-CLexRrQw.js} +9 -9
  12. package/dist/{cli-metadata-BGryAl2e.js → cli-metadata-zRyVmUOL.js} +1 -1
  13. package/dist/cli-metadata.js +1 -1
  14. package/dist/{client-oNOlldJI.js → client-C0nZFCTj.js} +2 -2
  15. package/dist/{client-Dj4mcf-s.js → client-CPcRv6ab.js} +6 -6
  16. package/dist/{client-bootstrap-n1Rqc8Go.js → client-bootstrap-DLN-K8Xb.js} +1 -6
  17. package/dist/contract-api.js +2 -2
  18. package/dist/{credentials-DJj2xs3q.js → credentials-DysXbkv2.js} +2 -2
  19. package/dist/{credentials-read-mexhw-Ur.js → credentials-read-WWpqi88V.js} +1 -1
  20. package/dist/{credentials-write.runtime-DQt-kgJq.js → credentials-write.runtime-D22lPwRO.js} +1 -1
  21. package/dist/{crypto-runtime-m1eplj3b.js → crypto-runtime-DiyH4R3D.js} +3 -25
  22. package/dist/{crypto-snapshot-doctor.runtime-D0v841D_.js → crypto-snapshot-doctor.runtime-DxgUMXUy.js} +2 -2
  23. package/dist/{directory-live-DLUgWBhA.js → directory-live-B8-GAVcc.js} +2 -2
  24. package/dist/doctor-contract-api.js +41 -21
  25. package/dist/{draft-stream-DglwxWzJ.js → draft-stream--NdEtnZ8.js} +16 -5
  26. package/dist/{encryption-guidance-BNcZNQZI.js → encryption-guidance-mDyxJV9U.js} +1 -1
  27. package/dist/{event-helpers-XRfAbOIh.js → event-helpers-CspuhE9k.js} +9 -1
  28. package/dist/helper-api.js +3 -3
  29. package/dist/{http-client-DOmFvKvB.js → http-client-BfPeF4CE.js} +1 -1
  30. package/dist/{idb-persistence-CU7CNLlX.js → idb-persistence-DBdwHSWg.js} +1 -1
  31. package/dist/index.js +1 -1
  32. package/dist/{messages-Czn8lNEh.js → messages-CpZfiQO0.js} +6 -99
  33. package/dist/{monitor-DouG43FJ.js → monitor-BUek91SW.js} +61 -92
  34. package/dist/{outbound-Co_tJyE6.js → outbound-D91JinYa.js} +1 -1
  35. package/dist/plugin-entry.handlers.runtime.js +1 -1
  36. package/dist/probe.runtime-DWdw74_H.js +2 -0
  37. package/dist/{profile-update-CAl8nZNG.js → profile-update-vnhxwjEt.js} +1 -1
  38. package/dist/{reaction-events-C_7G7bvI.js → reaction-events-2WM2nJe_.js} +5 -7
  39. package/dist/{resolve-targets-B64O69Nd.js → resolve-targets-K8D0HWPX.js} +1 -1
  40. package/dist/{resolver.runtime-TRmePJDV.js → resolver.runtime-C88GwQCx.js} +1 -1
  41. package/dist/{room-info-6viLR3NH.js → room-info-BPVJkXnp.js} +7 -4
  42. package/dist/runtime-api.js +2 -2
  43. package/dist/{sdk-C1yfda1L.js → sdk-B4By16Bt.js} +13 -6
  44. package/dist/{send-B5XChnvB.js → send-UWLIQ0bG.js} +211 -135
  45. package/dist/session-binding-contract-api.js +1 -1
  46. package/dist/{setup-bootstrap-S_loyUyM.js → setup-bootstrap-sVqkwtSY.js} +2 -2
  47. package/dist/{setup-core-XkIfQ65J.js → setup-core-8keb-Yre.js} +14 -29
  48. package/dist/setup-plugin-api.js +1 -1
  49. package/dist/{setup-surface-B2yZ8KGc.js → setup-surface-bcluelBI.js} +8 -17
  50. package/dist/{startup-verification-1Ney1mmI.js → startup-verification-BTSf31hS.js} +2 -1
  51. package/dist/storage-CV-pfV_2.js +320 -0
  52. package/dist/{storage-BVf4uucD.js → storage-metadata-DYArLcq1.js} +14 -319
  53. package/dist/{storage-paths-gUmSydsW.js → storage-paths-DVCANXTc.js} +13 -1
  54. package/dist/{sync-cache-state-d-A_OhbU.js → sync-cache-state-C-mhj3xb.js} +9 -3
  55. package/dist/{thread-bindings-BkBnn4te.js → thread-bindings-Bwv87Gve.js} +3 -2
  56. package/dist/{tool-actions.runtime-a5L5xGSP.js → tool-actions.runtime-Bf98Juk6.js} +295 -256
  57. package/dist/types-DzSc7Sqm.js +32 -0
  58. package/dist/{verification-XJtTc5DI.js → verification-BbG-VC9S.js} +2 -2
  59. package/node_modules/@matrix-org/matrix-sdk-crypto-wasm/package.json +1 -1
  60. package/node_modules/@matrix-org/matrix-sdk-crypto-wasm/pkg/matrix_sdk_crypto_wasm.d.ts +69 -4
  61. package/node_modules/@matrix-org/matrix-sdk-crypto-wasm/pkg/matrix_sdk_crypto_wasm_bg.cjs +526 -432
  62. package/node_modules/@matrix-org/matrix-sdk-crypto-wasm/pkg/matrix_sdk_crypto_wasm_bg.js +358 -265
  63. package/node_modules/@matrix-org/matrix-sdk-crypto-wasm/pkg/matrix_sdk_crypto_wasm_bg.wasm +0 -0
  64. package/node_modules/@matrix-org/matrix-sdk-crypto-wasm/pkg/matrix_sdk_crypto_wasm_bg.wasm.d.ts +8 -7
  65. package/openclaw.plugin.json +27 -1
  66. package/package.json +5 -5
  67. package/dist/probe.runtime-B1YPxG9x.js +0 -2
  68. package/dist/runtime-BefyhPWv.js +0 -6
@@ -2,24 +2,28 @@ import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
2
  import { a as resolveMatrixAccountConfig } from "./account-config-CRsKoMqJ.js";
3
3
  import { t as getMatrixRuntime } from "./runtime-6S3DNFNv.js";
4
4
  import { i as normalizeMatrixResolvableTarget, t as isMatrixQualifiedUserId } from "./target-ids-Nwx7cMVE.js";
5
- import { n as MATRIX_REACTION_EVENT_TYPE, r as buildMatrixReactionContent, t as MATRIX_ANNOTATION_RELATION_TYPE } from "./reaction-common-DkrQdBSZ.js";
6
5
  import { a as isStrictDirectRoom, r as inspectMatrixDirectRoomEvidence } from "./direct-room-RinHjtqX.js";
6
+ import { r as buildMatrixReactionContent } from "./reaction-common-DkrQdBSZ.js";
7
+ import { a as RelationType, i as MsgType, r as MSC4357_LIVE_KEY, t as EventType } from "./types-DzSc7Sqm.js";
8
+ import { n as getMatrixEventProjection } from "./event-helpers-CspuhE9k.js";
7
9
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
8
10
  import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
9
- import { isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeOptionalStringifiedId } from "openclaw/plugin-sdk/string-coerce-runtime";
11
+ import { asNullableObjectRecord, asNullableRecord, asOptionalRecord, isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeOptionalStringifiedId } from "openclaw/plugin-sdk/string-coerce-runtime";
10
12
  import { FormatCapabilityProfile, convertMarkdownTables, findCodeRegions, isInsideCode, markdownToIR, renderMarkdownWithMarkers, tokenizeHtmlTags } from "openclaw/plugin-sdk/text-chunking";
11
13
  import { createHash } from "node:crypto";
14
+ import path from "node:path";
12
15
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
13
16
  import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
14
17
  import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
15
18
  import { loadOutboundMediaFromUrl } from "openclaw/plugin-sdk/outbound-media";
19
+ import { M_POLL_KIND_DISCLOSED } from "matrix-js-sdk/lib/@types/polls.js";
16
20
  import { normalizePollInput } from "openclaw/plugin-sdk/poll-runtime";
17
21
  import MarkdownIt from "markdown-it";
18
22
  import { isAutoLinkedFileRef } from "openclaw/plugin-sdk/text-autolink-runtime";
19
23
  import { isVoiceMessageCompatibleAudio } from "openclaw/plugin-sdk/media-runtime";
20
24
  import { parseBuffer } from "music-metadata";
21
25
  //#region extensions/matrix/src/matrix/send/client.ts
22
- const loadMatrixSendClientRuntime = createLazyRuntimeModule(() => import("./client-bootstrap-n1Rqc8Go.js").then((n) => n.t));
26
+ const loadMatrixSendClientRuntime = createLazyRuntimeModule(() => import("./client-bootstrap-DLN-K8Xb.js").then((n) => n.t));
23
27
  function resolveMediaMaxBytes(accountId, cfg) {
24
28
  if (!cfg) throw new Error("Matrix media limits requires a resolved runtime config. Load and resolve config at the command or gateway boundary, then pass cfg through the runtime path.");
25
29
  const resolvedCfg = requireRuntimeConfig(cfg, "Matrix media limits");
@@ -47,36 +51,6 @@ async function withResolvedMatrixClient(opts, run, shutdownBehavior) {
47
51
  return await withResolvedRuntimeMatrixClient(opts, run, shutdownBehavior);
48
52
  }
49
53
  //#endregion
50
- //#region extensions/matrix/src/matrix/send/types.ts
51
- const MsgType = {
52
- Text: "m.text",
53
- Image: "m.image",
54
- Audio: "m.audio",
55
- Video: "m.video",
56
- File: "m.file",
57
- Notice: "m.notice"
58
- };
59
- const RelationType = {
60
- Annotation: MATRIX_ANNOTATION_RELATION_TYPE,
61
- Replace: "m.replace",
62
- Thread: "m.thread"
63
- };
64
- const EventType = {
65
- Direct: "m.direct",
66
- Reaction: MATRIX_REACTION_EVENT_TYPE,
67
- RoomMessage: "m.room.message"
68
- };
69
- const MATRIX_OPENCLAW_FINALIZED_PREVIEW_KEY = "com.openclaw.finalized_preview";
70
- /**
71
- * MSC4357 live marker key.
72
- * When present on event content, signals that the message is still being
73
- * streamed (e.g. an LLM generating a response). Supporting clients render
74
- * the message with a streaming animation until an edit without this marker
75
- * arrives, indicating the stream is complete.
76
- * @see https://github.com/matrix-org/matrix-spec-proposals/pull/4357
77
- */
78
- const MSC4357_LIVE_KEY = "org.matrix.msc4357.live";
79
- //#endregion
80
54
  //#region extensions/matrix/src/matrix/direct-management.ts
81
55
  var direct_management_exports = /* @__PURE__ */ __exportAll({
82
56
  inspectMatrixDirectRooms: () => inspectMatrixDirectRooms,
@@ -659,7 +633,7 @@ function parsePollStart(content) {
659
633
  return {
660
634
  question,
661
635
  answers,
662
- kind: poll.kind ?? "m.poll.disclosed",
636
+ kind: M_POLL_KIND_DISCLOSED.matches(poll.kind ?? "m.poll.disclosed") ? "m.poll.disclosed" : "m.poll.undisclosed",
663
637
  maxSelections: Math.min(Math.max(maxSelections, 1), answers.length)
664
638
  };
665
639
  }
@@ -816,6 +790,34 @@ function buildPollResponseContent(pollEventId, answerIds) {
816
790
  };
817
791
  }
818
792
  //#endregion
793
+ //#region extensions/matrix/src/matrix/relations.ts
794
+ function relatedReplyEventId(relation) {
795
+ const reply = asOptionalRecord(relation?.["m.in_reply_to"]);
796
+ return typeof reply?.event_id === "string" ? reply.event_id : void 0;
797
+ }
798
+ function buildMatrixMessageRelation(params) {
799
+ const threadId = params.threadId?.trim();
800
+ const replyToId = params.replyToId?.trim();
801
+ const relatedId = replyToId || (threadId ? params.fallbackReplyToId?.trim() : void 0);
802
+ const reply = relatedId ? { "m.in_reply_to": { event_id: relatedId } } : void 0;
803
+ if (!threadId) return reply;
804
+ return {
805
+ rel_type: RelationType.Thread,
806
+ event_id: threadId,
807
+ ...reply,
808
+ ...relatedId && !replyToId ? { is_falling_back: true } : {}
809
+ };
810
+ }
811
+ function resolveMatrixReplyToEventId(content) {
812
+ const relation = asOptionalRecord(content["m.relates_to"]);
813
+ return relation?.rel_type === RelationType.Thread && relation.is_falling_back === true ? void 0 : relatedReplyEventId(relation);
814
+ }
815
+ function resolveMatrixThreadRootId(content) {
816
+ const relation = asOptionalRecord(content["m.relates_to"]);
817
+ if (relation?.rel_type !== RelationType.Thread) return;
818
+ return typeof relation.event_id === "string" ? relation.event_id : relatedReplyEventId(relation);
819
+ }
820
+ //#endregion
819
821
  //#region extensions/matrix/src/matrix/format-profile.ts
820
822
  function createMatrixPrivateMarkers(markdown, exhaustedMessage) {
821
823
  const used = new Set(Array.from(markdown, (character) => character.charCodeAt(0)));
@@ -854,15 +856,7 @@ function isMarkdownEscaped(markdown, index) {
854
856
  return slashCount % 2 === 1;
855
857
  }
856
858
  function projectMatrixMarkdown(markdown) {
857
- const normalized = (markdown ?? "").replace(/\r\n?/gu, "\n");
858
- return renderMarkdownWithMarkers({
859
- text: normalized,
860
- styles: [],
861
- links: []
862
- }, {
863
- styleMarkers: {},
864
- escapeText: (text) => text
865
- }, MATRIX_FORMAT_PROFILE);
859
+ return (markdown ?? "").replace(/\r\n?/gu, "\n");
866
860
  }
867
861
  function renderMatrixMarkdownTables(markdown, mode) {
868
862
  return MATRIX_FORMAT_PROFILE.constructs.table === "native" && (mode === "off" || mode === "block") ? markdown : convertMarkdownTables(markdown, mode);
@@ -1010,6 +1004,7 @@ function findMatrixMarkdownMetadataRanges(markdown) {
1010
1004
  }
1011
1005
  function findMatrixSpoilerDelimiterOffsets(markdown) {
1012
1006
  const projected = projectMatrixMarkdown(markdown);
1007
+ if (!projected.includes("||")) return [];
1013
1008
  const tokens = spoilerParser.parse(projected, {});
1014
1009
  const lineStarts = [0];
1015
1010
  for (let index = 0; index < projected.length; index += 1) if (projected[index] === "\n") lineStarts.push(index + 1);
@@ -1042,6 +1037,7 @@ function findMatrixSpoilerDelimiterOffsets(markdown) {
1042
1037
  }
1043
1038
  function hasMatrixSpoilerMetadataCollision(markdown) {
1044
1039
  const projected = projectMatrixMarkdown(markdown);
1040
+ if (!projected.includes("||")) return false;
1045
1041
  const ordinary = new Set(findMatrixSpoilerDelimiterOffsets(projected));
1046
1042
  const underlineTags = [...tokenizeHtmlTags(projected)].filter((tag) => (tag.name === "u" || tag.name === "ins") && !isMarkdownEscaped(projected, tag.start));
1047
1043
  const literalRanges = [...findMatrixTableSourceRanges(projected), ...findCodeRegions(projected).filter((code) => !underlineTags.some((tag) => code.start > tag.start && code.start < tag.end))];
@@ -1112,48 +1108,21 @@ md.renderer.rules.image = (tokens, idx, options, env, self) => {
1112
1108
  md.renderer.rules.html_block = (tokens, idx) => escapeHtml(tokens[idx]?.content ?? "");
1113
1109
  md.renderer.rules.html_inline = (tokens, idx) => escapeHtml(tokens[idx]?.content ?? "");
1114
1110
  md.renderer.rules.text_special = (tokens, idx) => escapeHtml(tokens[idx]?.content ?? "");
1111
+ md.renderer.rules.matrix_escaped_mention = () => "@";
1112
+ md.core.ruler.before("text_join", "matrix_escaped_mentions", (state) => {
1113
+ preserveEscapedMentionTokens(state.tokens);
1114
+ });
1115
1115
  md.renderer.rules.link_open = (tokens, idx, _options, _env, self) => shouldSuppressAutoLink(tokens, idx) ? "" : self.renderToken(tokens, idx, _options);
1116
1116
  md.renderer.rules.link_close = (tokens, idx, _options, _env, self) => {
1117
1117
  const openIdx = idx - 2;
1118
1118
  if (openIdx >= 0 && shouldSuppressAutoLink(tokens, openIdx)) return "";
1119
1119
  return self.renderToken(tokens, idx, _options);
1120
1120
  };
1121
- function maskEscapedMentions(markdown) {
1122
- let masked = "";
1123
- let idx = 0;
1124
- let codeFenceLength = 0;
1125
- let marker;
1126
- const metadataRanges = markdown.includes("\\@") ? findMatrixMarkdownMetadataRanges(markdown) : [];
1127
- while (idx < markdown.length) {
1128
- if (markdown[idx] === "`" && !isMarkdownEscaped(markdown, idx)) {
1129
- let runLength = 1;
1130
- while (markdown[idx + runLength] === "`") runLength += 1;
1131
- if (codeFenceLength === 0) codeFenceLength = runLength;
1132
- else if (runLength === codeFenceLength) codeFenceLength = 0;
1133
- masked += markdown.slice(idx, idx + runLength);
1134
- idx += runLength;
1135
- continue;
1136
- }
1137
- if (codeFenceLength === 0 && markdown[idx] === "\\" && markdown[idx + 1] === "@" && !metadataRanges.some((range) => idx >= range.start && idx < range.end)) {
1138
- marker ??= createMatrixPrivateMarkers(markdown, "Matrix mention formatting exhausted its private marker pool").open;
1139
- masked += marker;
1140
- idx += 2;
1141
- continue;
1142
- }
1143
- masked += markdown[idx] ?? "";
1144
- idx += 1;
1121
+ function preserveEscapedMentionTokens(tokens) {
1122
+ for (const token of tokens) {
1123
+ if (token.type === "text_special" && token.info === "escape" && token.content === "@") token.type = "matrix_escaped_mention";
1124
+ if (token.children) preserveEscapedMentionTokens(token.children);
1145
1125
  }
1146
- return {
1147
- markdown: masked,
1148
- ...marker ? { marker } : {}
1149
- };
1150
- }
1151
- function restoreEscapedMentions(text, marker, inCode = false) {
1152
- return marker ? text.replaceAll(marker, inCode ? "\\@" : "@") : text;
1153
- }
1154
- function restoreEscapedMentionsInBlockTokens(tokens, marker) {
1155
- if (!marker) return;
1156
- for (const token of tokens) if ((token.type === "fence" || token.type === "code_block") && token.content) token.content = restoreEscapedMentions(token.content, marker, true);
1157
1126
  }
1158
1127
  function isMentionStartBoundary(charBefore) {
1159
1128
  return !charBefore || !/[A-Za-z0-9_]/.test(charBefore);
@@ -1296,7 +1265,6 @@ async function resolveMatrixSelfUserId(client) {
1296
1265
  }
1297
1266
  function mutateInlineTokensWithMentions(params) {
1298
1267
  const nextChildren = [];
1299
- const restoreMention = (text) => restoreEscapedMentions(text, params.escapedMentionMarker);
1300
1268
  let roomMentioned = false;
1301
1269
  let insideLinkDepth = 0;
1302
1270
  for (const child of params.children) {
@@ -1311,23 +1279,21 @@ function mutateInlineTokensWithMentions(params) {
1311
1279
  continue;
1312
1280
  }
1313
1281
  if (child.type !== "text" || !child.content) {
1314
- for (const nested of child.children ?? []) nested.content = restoreMention(nested.content);
1315
1282
  nextChildren.push(child);
1316
1283
  continue;
1317
1284
  }
1318
- const visibleContent = restoreMention(child.content);
1319
1285
  if (insideLinkDepth > 0) {
1320
- nextChildren.push(createTextToken(child, visibleContent));
1286
+ nextChildren.push(child);
1321
1287
  continue;
1322
1288
  }
1323
1289
  const matches = collectMentionCandidates(child.content);
1324
1290
  if (matches.length === 0) {
1325
- nextChildren.push(createTextToken(child, visibleContent));
1291
+ nextChildren.push(child);
1326
1292
  continue;
1327
1293
  }
1328
1294
  let cursor = 0;
1329
1295
  for (const match of matches) {
1330
- if (match.start > cursor) nextChildren.push(createTextToken(child, restoreMention(child.content.slice(cursor, match.start))));
1296
+ if (match.start > cursor) nextChildren.push(createTextToken(child, child.content.slice(cursor, match.start)));
1331
1297
  cursor = match.end;
1332
1298
  if (match.kind === "room") {
1333
1299
  roomMentioned = true;
@@ -1349,7 +1315,7 @@ function mutateInlineTokensWithMentions(params) {
1349
1315
  label: match.raw
1350
1316
  }));
1351
1317
  }
1352
- if (cursor < child.content.length) nextChildren.push(createTextToken(child, restoreMention(child.content.slice(cursor))));
1318
+ if (cursor < child.content.length) nextChildren.push(createTextToken(child, child.content.slice(cursor)));
1353
1319
  }
1354
1320
  return {
1355
1321
  children: nextChildren,
@@ -1441,9 +1407,7 @@ function renderMatrixFallbackHtml(markdown) {
1441
1407
  return `<p>${escapeHtml(markdownToMatrixBody(markdown)).replaceAll("\n", "<br>\n")}</p>`;
1442
1408
  }
1443
1409
  async function resolveMarkdownMentionState(params) {
1444
- const { markdown, marker } = maskEscapedMentions(projectMatrixMarkdown(params.markdown));
1445
- const tokens = parseMatrixMarkdown(markdown, params.tableMode);
1446
- restoreEscapedMentionsInBlockTokens(tokens, marker);
1410
+ const tokens = parseMatrixMarkdown(projectMatrixMarkdown(params.markdown), params.tableMode);
1447
1411
  const selfUserId = await resolveMatrixSelfUserId(params.client);
1448
1412
  const userIds = [];
1449
1413
  const seenUserIds = /* @__PURE__ */ new Set();
@@ -1454,8 +1418,7 @@ async function resolveMarkdownMentionState(params) {
1454
1418
  children: token.children,
1455
1419
  userIds,
1456
1420
  seenUserIds,
1457
- selfUserId,
1458
- escapedMentionMarker: marker
1421
+ selfUserId
1459
1422
  });
1460
1423
  token.children = mutated.children;
1461
1424
  roomMentioned ||= mutated.roomMentioned;
@@ -1656,6 +1619,145 @@ function chunkMatrixText(text, opts) {
1656
1619
  };
1657
1620
  }
1658
1621
  //#endregion
1622
+ //#region extensions/matrix/src/matrix/media-text.ts
1623
+ const MATRIX_MEDIA_KINDS = {
1624
+ "m.audio": "audio",
1625
+ "m.file": "file",
1626
+ "m.image": "image",
1627
+ "m.sticker": "sticker",
1628
+ "m.video": "video"
1629
+ };
1630
+ function resolveMatrixMediaKind(msgtype) {
1631
+ const key = msgtype ?? "";
1632
+ return Object.hasOwn(MATRIX_MEDIA_KINDS, key) ? MATRIX_MEDIA_KINDS[key] : void 0;
1633
+ }
1634
+ function resolveMatrixMediaLabel(kind, fallback = "media") {
1635
+ return `${kind ?? fallback} attachment`;
1636
+ }
1637
+ function formatMatrixAttachmentMarker(params) {
1638
+ const label = resolveMatrixMediaLabel(params.kind);
1639
+ if (params.tooLarge) return `[matrix ${label} too large]`;
1640
+ return params.unavailable ? `[matrix ${label} unavailable]` : `[matrix ${label}]`;
1641
+ }
1642
+ function isLikelyBareFilename(text) {
1643
+ const trimmed = text.trim();
1644
+ if (!trimmed || trimmed.includes("\n") || /\s/.test(trimmed)) return false;
1645
+ if (path.basename(trimmed) !== trimmed) return false;
1646
+ return path.extname(trimmed).length > 1;
1647
+ }
1648
+ function resolveCaptionOrFilename(params) {
1649
+ const body = params.body?.trim() ?? "";
1650
+ const filename = params.filename?.trim() ?? "";
1651
+ if (filename) {
1652
+ if (!body || body === filename) return { filename };
1653
+ return {
1654
+ caption: body,
1655
+ filename
1656
+ };
1657
+ }
1658
+ if (!body) return {};
1659
+ if (isLikelyBareFilename(body)) return { filename: body };
1660
+ return { caption: body };
1661
+ }
1662
+ function resolveMatrixReplacementContent(event, replacementEvent = event.unsigned?.["m.relations"]?.["m.replace"]) {
1663
+ return resolveMatrixReplacement(event, replacementEvent)?.content;
1664
+ }
1665
+ function resolveMatrixReplacement(event, replacementEvent = event.unsigned?.["m.relations"]?.["m.replace"]) {
1666
+ const replacement = asNullableObjectRecord(replacementEvent);
1667
+ if (!replacement || event.state_key !== void 0 || event.unsigned?.redacted_because) return;
1668
+ const content = asNullableObjectRecord(replacement.content);
1669
+ const relation = asNullableObjectRecord(content?.["m.relates_to"]);
1670
+ const unreadable = getMatrixEventProjection(replacement)?.decryptionFailure === true || replacement.type === "m.room.encrypted";
1671
+ if (replacement.sender !== event.sender || !unreadable && replacement.type !== event.type || replacement.state_key !== void 0 || asNullableObjectRecord(replacement.unsigned)?.redacted_because || !relation || relation.rel_type !== "m.replace" || relation.event_id !== event.event_id) return;
1672
+ if (unreadable) return { kind: "unreadable" };
1673
+ const newContent = asNullableRecord(content?.["m.new_content"]);
1674
+ return newContent ? {
1675
+ kind: "content",
1676
+ content: newContent
1677
+ } : void 0;
1678
+ }
1679
+ function resolveMatrixMessageAttachment(params) {
1680
+ const kind = resolveMatrixMediaKind(params.msgtype);
1681
+ if (!kind) return;
1682
+ const resolved = resolveCaptionOrFilename(params);
1683
+ return {
1684
+ kind,
1685
+ caption: resolved.caption,
1686
+ filename: resolved.filename
1687
+ };
1688
+ }
1689
+ function formatMatrixAttachmentText(params) {
1690
+ if (!params.attachment) return;
1691
+ return formatMatrixAttachmentMarker({
1692
+ kind: params.attachment.kind,
1693
+ tooLarge: params.tooLarge,
1694
+ unavailable: params.unavailable
1695
+ });
1696
+ }
1697
+ function formatMatrixMessageText(params) {
1698
+ const attachment = resolveMatrixMessageAttachment(params);
1699
+ const body = attachment ? attachment.caption ?? "" : params.body?.trim() ?? "";
1700
+ const marker = formatMatrixAttachmentText({
1701
+ attachment,
1702
+ tooLarge: params.tooLarge,
1703
+ unavailable: params.unavailable
1704
+ });
1705
+ if (!marker) return body || void 0;
1706
+ if (!body) return marker;
1707
+ return `${body}\n\n${marker}`;
1708
+ }
1709
+ function formatMatrixMediaUnavailableText(params) {
1710
+ return formatMatrixMessageText({
1711
+ ...params,
1712
+ unavailable: true
1713
+ }) ?? "";
1714
+ }
1715
+ function formatMatrixMediaTooLargeText(params) {
1716
+ return formatMatrixMessageText({
1717
+ ...params,
1718
+ tooLarge: true
1719
+ }) ?? "";
1720
+ }
1721
+ //#endregion
1722
+ //#region extensions/matrix/src/matrix/send/edit-content.ts
1723
+ const MAX_EDIT_RELATION_PAGES = 100;
1724
+ const EDIT_RELATION_PAGE_SIZE = 100;
1725
+ const EDIT_DECRYPTION_ERROR = "Matrix edit history is not fully decrypted; restore encryption keys before editing.";
1726
+ async function resolveMatrixEditContent(params) {
1727
+ const { client, roomId, event } = params;
1728
+ if (!event || event.unsigned?.redacted_because || event.state_key !== void 0) return event?.content;
1729
+ const projection = getMatrixEventProjection(event);
1730
+ if (projection?.decryptionFailure || event.type === "m.room.encrypted") throw new Error(EDIT_DECRYPTION_ERROR);
1731
+ const originalContent = projection?.originalContent ?? event.content;
1732
+ const embedded = resolveMatrixReplacementContent(event) ?? asNullableObjectRecord(originalContent?.["m.new_content"]);
1733
+ if (embedded) return embedded;
1734
+ let latest;
1735
+ let latestReplacement;
1736
+ let from;
1737
+ const seenCursors = /* @__PURE__ */ new Set();
1738
+ for (let pageIndex = 0; pageIndex < MAX_EDIT_RELATION_PAGES; pageIndex++) {
1739
+ const page = await client.getRelations(roomId, event.event_id, "m.replace", void 0, {
1740
+ from,
1741
+ limit: EDIT_RELATION_PAGE_SIZE
1742
+ });
1743
+ for (const replacement of page.events) {
1744
+ const replacementContent = resolveMatrixReplacement(event, replacement);
1745
+ if (replacementContent && (!latest || replacement.origin_server_ts > latest.origin_server_ts || replacement.origin_server_ts === latest.origin_server_ts && replacement.event_id > latest.event_id)) {
1746
+ latest = replacement;
1747
+ latestReplacement = replacementContent;
1748
+ }
1749
+ }
1750
+ from = page.nextBatch ?? void 0;
1751
+ if (!from) {
1752
+ if (latestReplacement?.kind === "unreadable") throw new Error(EDIT_DECRYPTION_ERROR);
1753
+ return latestReplacement?.content ?? originalContent;
1754
+ }
1755
+ if (seenCursors.has(from)) break;
1756
+ seenCursors.add(from);
1757
+ }
1758
+ throw new Error("Matrix edit history could not be fully read; send a new message instead.");
1759
+ }
1760
+ //#endregion
1659
1761
  //#region extensions/matrix/src/matrix/send/formatting.ts
1660
1762
  async function renderMatrixFormattedContent(params) {
1661
1763
  const markdown = params.markdown ?? "";
@@ -1732,24 +1834,6 @@ function diffMatrixMentions(current, previous) {
1732
1834
  if (current.room && !previous.room) delta.room = true;
1733
1835
  return delta;
1734
1836
  }
1735
- function buildReplyRelation(replyToId) {
1736
- const trimmed = replyToId?.trim();
1737
- if (!trimmed) return;
1738
- return { "m.in_reply_to": { event_id: trimmed } };
1739
- }
1740
- function buildThreadRelation(threadId, replyToId) {
1741
- const trimmed = threadId.trim();
1742
- const relation = {
1743
- rel_type: RelationType.Thread,
1744
- event_id: trimmed
1745
- };
1746
- const fallbackReplyToId = replyToId?.trim();
1747
- if (fallbackReplyToId) {
1748
- relation.is_falling_back = true;
1749
- relation["m.in_reply_to"] = { event_id: fallbackReplyToId };
1750
- }
1751
- return relation;
1752
- }
1753
1837
  function resolveMatrixMsgType(contentType, _fileName) {
1754
1838
  switch (getMatrixRuntime().media.mediaKindFromMime(contentType ?? "")) {
1755
1839
  case "image": return MsgType.Image;
@@ -1961,14 +2045,6 @@ function normalizeMatrixClientResolveOpts(opts) {
1961
2045
  accountId: opts.accountId
1962
2046
  };
1963
2047
  }
1964
- function resolvePreviousEditContent(previousEvent) {
1965
- if (!previousEvent || typeof previousEvent !== "object") return;
1966
- const eventRecord = previousEvent;
1967
- if (!eventRecord.content || typeof eventRecord.content !== "object") return;
1968
- const content = eventRecord.content;
1969
- const newContent = content["m.new_content"];
1970
- return newContent && typeof newContent === "object" ? newContent : content;
1971
- }
1972
2048
  function resolvePreviousThreadId(previousEvent) {
1973
2049
  if (!previousEvent || typeof previousEvent !== "object") return;
1974
2050
  const content = previousEvent.content;
@@ -1979,9 +2055,6 @@ function resolvePreviousThreadId(previousEvent) {
1979
2055
  if (relationRecord.rel_type !== RelationType.Thread || typeof relationRecord.event_id !== "string") return;
1980
2056
  return normalizeThreadId(relationRecord.event_id) ?? void 0;
1981
2057
  }
1982
- function hasMatrixMentionsMetadata(content) {
1983
- return Boolean(content && Object.hasOwn(content, "m.mentions"));
1984
- }
1985
2058
  function withMatrixExtraContentFields(content, extraContent) {
1986
2059
  if (!extraContent) return content;
1987
2060
  return {
@@ -1990,8 +2063,9 @@ function withMatrixExtraContentFields(content, extraContent) {
1990
2063
  };
1991
2064
  }
1992
2065
  async function resolvePreviousEditMentions(params) {
1993
- if (hasMatrixMentionsMetadata(params.content)) return extractMatrixMentions(params.content);
1994
- const body = typeof params.content?.body === "string" ? params.content.body : "";
2066
+ const content = await resolveMatrixEditContent(params);
2067
+ if (content && Object.hasOwn(content, "m.mentions")) return extractMatrixMentions(content);
2068
+ const body = typeof content?.body === "string" ? content.body : "";
1995
2069
  if (!body) return {};
1996
2070
  return await resolveMatrixMentionsForBody({
1997
2071
  client: params.client,
@@ -2031,7 +2105,10 @@ async function sendMessageMatrix(to, message, opts) {
2031
2105
  preserveWhitespace: true
2032
2106
  });
2033
2107
  const singleEventBody = fitsInSingleEvent ? preparedBody : void 0;
2034
- const relation = threadId ? buildThreadRelation(threadId, opts.replyToId) : buildReplyRelation(opts.replyToId);
2108
+ const relation = buildMatrixMessageRelation({
2109
+ ...opts,
2110
+ threadId
2111
+ });
2035
2112
  let pendingExtraContent = opts.extraContent;
2036
2113
  const events = [];
2037
2114
  const prepareContent = (content, receiptKind) => {
@@ -2157,7 +2234,7 @@ async function sendMessageMatrix(to, message, opts) {
2157
2234
  } : void 0);
2158
2235
  lastMessageId = eventId || lastMessageId;
2159
2236
  if (!eventId) continue;
2160
- const eventReplyToId = planned.content["m.relates_to"]?.["m.in_reply_to"]?.event_id;
2237
+ const eventReplyToId = resolveMatrixReplyToEventId(planned.content);
2161
2238
  const acceptedEvent = {
2162
2239
  messageId: eventId,
2163
2240
  kind: planned.receiptKind,
@@ -2209,7 +2286,7 @@ async function sendPollMatrix(to, poll, opts) {
2209
2286
  const threadId = normalizeThreadId(opts.threadId);
2210
2287
  const pollPayload = threadId ? {
2211
2288
  ...pollContent,
2212
- "m.relates_to": buildThreadRelation(threadId)
2289
+ "m.relates_to": buildMatrixMessageRelation({ threadId })
2213
2290
  } : { ...pollContent };
2214
2291
  pollPayload["m.mentions"] = mentions;
2215
2292
  return {
@@ -2259,7 +2336,10 @@ async function sendSingleTextMessageMatrix(roomId, text, opts) {
2259
2336
  }, async (client) => {
2260
2337
  const resolvedRoom = await resolveMatrixRoomId(client, roomId);
2261
2338
  const normalizedThreadId = normalizeThreadId(opts.threadId);
2262
- const relation = normalizedThreadId ? buildThreadRelation(normalizedThreadId, opts.replyToId) : buildReplyRelation(opts.replyToId);
2339
+ const relation = buildMatrixMessageRelation({
2340
+ ...opts,
2341
+ threadId: normalizedThreadId
2342
+ });
2263
2343
  const content = withMatrixExtraContentFields(buildTextContent(convertedText, relation, { msgtype: opts.msgtype }), opts.extraContent);
2264
2344
  await enrichMatrixFormattedContent({
2265
2345
  client,
@@ -2271,7 +2351,7 @@ async function sendSingleTextMessageMatrix(roomId, text, opts) {
2271
2351
  });
2272
2352
  if (opts.live) content[MSC4357_LIVE_KEY] = {};
2273
2353
  const eventId = await client.sendMessage(resolvedRoom, content);
2274
- const replyToId = content["m.relates_to"]?.["m.in_reply_to"]?.event_id;
2354
+ const replyToId = resolveMatrixReplyToEventId(content);
2275
2355
  return {
2276
2356
  messageId: eventId ?? "unknown",
2277
2357
  roomId: resolvedRoom,
@@ -2289,11 +2369,6 @@ async function sendSingleTextMessageMatrix(roomId, text, opts) {
2289
2369
  };
2290
2370
  });
2291
2371
  }
2292
- async function getPreviousMatrixEvent(client, roomId, eventId) {
2293
- const getEvent = client.getEvent;
2294
- if (typeof getEvent !== "function") return null;
2295
- return await Promise.resolve(getEvent.call(client, roomId, eventId)).catch(() => null);
2296
- }
2297
2372
  async function editMessageMatrix(roomId, originalEventId, newText, opts) {
2298
2373
  return await withResolvedMatrixSendClient({
2299
2374
  client: opts.client,
@@ -2316,16 +2391,17 @@ async function editMessageMatrix(roomId, originalEventId, newText, opts) {
2316
2391
  includeMentions: opts.includeMentions,
2317
2392
  tableMode
2318
2393
  });
2319
- const previousEvent = await getPreviousMatrixEvent(client, resolvedRoom, originalEventId);
2394
+ const threadId = normalizeThreadId(opts.threadId);
2395
+ const previousEvent = opts.includeMentions !== false || threadId ? await client.getEvent(resolvedRoom, originalEventId) : null;
2320
2396
  const replaceMentions = opts.includeMentions === false ? void 0 : diffMatrixMentions(extractMatrixMentions(newContent), await resolvePreviousEditMentions({
2321
2397
  client,
2322
- content: resolvePreviousEditContent(previousEvent)
2398
+ roomId: resolvedRoom,
2399
+ event: previousEvent
2323
2400
  }));
2324
2401
  const replaceRelation = {
2325
2402
  rel_type: RelationType.Replace,
2326
2403
  event_id: originalEventId
2327
2404
  };
2328
- const threadId = normalizeThreadId(opts.threadId);
2329
2405
  if (threadId) {
2330
2406
  if (resolvePreviousThreadId(previousEvent) !== threadId) throw new Error("Matrix edit cannot add or change the original event thread relation.");
2331
2407
  }
@@ -2358,4 +2434,4 @@ async function reactMatrixMessage(roomId, messageId, emoji, opts) {
2358
2434
  });
2359
2435
  }
2360
2436
  //#endregion
2361
- export { repairMatrixDirectRooms as C, promoteMatrixDirectRoomCandidate as S, MsgType as T, resolvePollReferenceEventId as _, sendSingleTextMessageMatrix as a, resolveMatrixRoomId as b, prepareMatrixSingleText as c, formatPollAsText as d, formatPollResultsAsText as f, parsePollStartContent as g, parsePollStart as h, sendPollMatrix as i, buildPollResponseContent as l, isPollStartType as m, reactMatrixMessage as n, sendTypingMatrix as o, isPollEventType as p, sendMessageMatrix as r, send_exports as s, editMessageMatrix as t, buildPollResultsSummary as u, cleanupMatrixDeliveryPlans as v, MATRIX_OPENCLAW_FINALIZED_PREVIEW_KEY as w, direct_management_exports as x, reconcileMatrixUnknownSend as y };
2437
+ export { promoteMatrixDirectRoomCandidate as A, parsePollStart as C, reconcileMatrixUnknownSend as D, cleanupMatrixDeliveryPlans as E, resolveMatrixRoomId as O, isPollStartType as S, resolvePollReferenceEventId as T, buildPollResponseContent as _, sendSingleTextMessageMatrix as a, formatPollResultsAsText as b, formatMatrixMediaTooLargeText as c, isLikelyBareFilename as d, resolveMatrixMessageAttachment as f, resolveMatrixThreadRootId as g, resolveMatrixReplyToEventId as h, sendPollMatrix as i, repairMatrixDirectRooms as j, direct_management_exports as k, formatMatrixMediaUnavailableText as l, prepareMatrixSingleText as m, reactMatrixMessage as n, sendTypingMatrix as o, resolveMatrixReplacementContent as p, sendMessageMatrix as r, send_exports as s, editMessageMatrix as t, formatMatrixMessageText as u, buildPollResultsSummary as v, parsePollStartContent as w, isPollEventType as x, formatPollAsText as y };
@@ -1,3 +1,3 @@
1
1
  import { r as setMatrixRuntime } from "./runtime-6S3DNFNv.js";
2
- import { t as createMatrixThreadBindingManager } from "./thread-bindings-BkBnn4te.js";
2
+ import { t as createMatrixThreadBindingManager } from "./thread-bindings-Bwv87Gve.js";
3
3
  export { createMatrixThreadBindingManager, setMatrixRuntime };
@@ -1,6 +1,6 @@
1
1
  import { a as resolveMatrixAccountConfig, n as hasExplicitMatrixAccountConfig } from "./account-config-CRsKoMqJ.js";
2
- import "./accounts-DR1c4xF_.js";
3
- import { n as bootstrapMatrixVerification } from "./verification-XJtTc5DI.js";
2
+ import "./accounts-GwSAk9vY.js";
3
+ import { n as bootstrapMatrixVerification } from "./verification-BbG-VC9S.js";
4
4
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
5
5
  //#region extensions/matrix/src/setup-bootstrap.ts
6
6
  async function maybeBootstrapNewEncryptedMatrixAccount(params) {
@@ -1,12 +1,12 @@
1
- import { s as resolveMatrixEnvAuthReadiness } from "./account-selection-DA-jfx22.js";
1
+ import { c as resolveMatrixEnvAuthReadiness } from "./account-selection-Bbtc483D.js";
2
2
  import { a as resolveMatrixAccountConfig } from "./account-config-CRsKoMqJ.js";
3
- import { r as resolveDefaultMatrixAccountId } from "./accounts-DR1c4xF_.js";
3
+ import { r as resolveDefaultMatrixAccountId } from "./accounts-GwSAk9vY.js";
4
4
  import { t as resolveMatrixConfigFieldPath } from "./config-paths-CnREYb1Y.js";
5
5
  import { r as updateMatrixAccountConfig } from "./config-update-BnX26jCO.js";
6
6
  import { t as isSupportedMatrixAvatarSource } from "./profile-vmjsmhh4.js";
7
7
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
8
8
  import { defineChannelSetupContract } from "openclaw/plugin-sdk/channel-setup";
9
- import { DEFAULT_ACCOUNT_ID, addWildcardAllowFrom, applyAccountNameToChannelSection, normalizeAccountId, normalizeAllowFromEntries, normalizeSecretInputString, prepareScopedSetupConfig } from "openclaw/plugin-sdk/setup";
9
+ import { DEFAULT_ACCOUNT_ID, addWildcardAllowFrom, applyAccountNameToChannelSection, normalizeAccountId, normalizeAllowFromEntries, normalizeSecretInputString, patchTopLevelChannelConfigSection, prepareScopedSetupConfig, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup";
10
10
  import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, normalizeAccountId as normalizeAccountId$1 } from "openclaw/plugin-sdk/routing";
11
11
  import { createChannelDmPolicy } from "openclaw/plugin-sdk/channel-dm-policy";
12
12
  //#region extensions/matrix/src/setup-contract.ts
@@ -126,21 +126,15 @@ function moveSingleMatrixAccountConfigToNamedAccount(cfg) {
126
126
  const resolvedTargetAccountId = resolveExistingMatrixAccountKey(accounts, resolveSingleAccountPromotionTarget({ channel: base }));
127
127
  const nextAccount = { ...accounts[resolvedTargetAccountId] };
128
128
  for (const key of keysToMove) nextAccount[key] = cloneIfObject(base[key]);
129
- const nextChannel = { ...base };
130
- for (const key of keysToMove) delete nextChannel[key];
131
- return {
132
- ...cfg,
133
- channels: {
134
- ...cfg.channels,
135
- [channel$1]: {
136
- ...nextChannel,
137
- accounts: {
138
- ...accounts,
139
- [resolvedTargetAccountId]: nextAccount
140
- }
141
- }
142
- }
143
- };
129
+ return patchTopLevelChannelConfigSection({
130
+ cfg,
131
+ channel: channel$1,
132
+ clearFields: keysToMove,
133
+ patch: { accounts: {
134
+ ...accounts,
135
+ [resolvedTargetAccountId]: nextAccount
136
+ } }
137
+ });
144
138
  }
145
139
  function validateMatrixSetupInput(params) {
146
140
  const input = params.input;
@@ -271,16 +265,7 @@ function createMatrixSetupWizardProxy(loadWizardModule) {
271
265
  const promptAllowFrom = (await loadWizard()).dmPolicy?.promptAllowFrom;
272
266
  return promptAllowFrom ? await promptAllowFrom(params) : params.cfg;
273
267
  }),
274
- disable: (cfg) => ({
275
- ...cfg,
276
- channels: {
277
- ...cfg.channels,
278
- matrix: {
279
- ...cfg.channels?.matrix,
280
- enabled: false
281
- }
282
- }
283
- })
268
+ disable: (cfg) => setSetupChannelEnabled(cfg, channel, false)
284
269
  };
285
270
  }
286
271
  const matrixSetupAdapter = {
@@ -311,7 +296,7 @@ const matrixSetupAdapter = {
311
296
  input
312
297
  }),
313
298
  afterAccountConfigWritten: async ({ previousCfg, cfg, accountId, runtime }) => {
314
- const { runMatrixSetupBootstrapAfterConfigWrite } = await import("./setup-bootstrap-S_loyUyM.js");
299
+ const { runMatrixSetupBootstrapAfterConfigWrite } = await import("./setup-bootstrap-sVqkwtSY.js");
315
300
  await runMatrixSetupBootstrapAfterConfigWrite({
316
301
  previousCfg,
317
302
  cfg,
@@ -1,2 +1,2 @@
1
- import { n as matrixSetupPlugin } from "./channel.setup-DhmDXwPp.js";
1
+ import { n as matrixSetupPlugin } from "./channel.setup-DmS7m7aT.js";
2
2
  export { matrixSetupPlugin };