@openclaw/matrix 2026.8.1-beta.2 → 2026.8.1-beta.3

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 (51) hide show
  1. package/dist/api.js +6 -6
  2. package/dist/{approval-handler.runtime-CJXCUdRg.js → approval-handler.runtime-CSvueU9P.js} +5 -4
  3. package/dist/{approval-ids-7rf7etWE.js → approval-ids-CEcf-EiM.js} +1 -1
  4. package/dist/{approval-reaction-auth-wBwbEDpZ.js → approval-reaction-auth-CziKXatm.js} +1 -1
  5. package/dist/{channel-VSrHgTON.js → channel-CzQw5OZN.js} +228 -20
  6. package/dist/channel-plugin-api.js +1 -1
  7. package/dist/{channel.runtime-pOOL0uT_.js → channel.runtime-I9pBRQb3.js} +24 -14
  8. package/dist/{channel.setup-PpxRP9Du.js → channel.setup-aNaa3Uyn.js} +3 -9
  9. package/dist/{cli-CkTfKC_c.js → cli-iR6QJ5U0.js} +8 -8
  10. package/dist/{cli-metadata-B1d1aGM5.js → cli-metadata-BmUYWjuM.js} +1 -1
  11. package/dist/cli-metadata.js +1 -1
  12. package/dist/{client-CeGw0G5S.js → client-BBQdBG7t.js} +34 -19
  13. package/dist/{client-sJesKQmp.js → client-D8XghqmX.js} +2 -2
  14. package/dist/{client-bootstrap-BFwT_2VT.js → client-bootstrap-Co3RlItb.js} +1 -1
  15. package/dist/contract-api.js +2 -2
  16. package/dist/{directory-live-Bvg2wAnR.js → directory-live-DLQzel12.js} +2 -2
  17. package/dist/doctor-contract-api.js +7 -1
  18. package/dist/{draft-stream-BRi7PRRS.js → draft-stream-DQ7QNC-l.js} +1 -1
  19. package/dist/index.js +1 -1
  20. package/dist/{media-text-JudlYOSc.js → media-text-Dh-DpTc3.js} +4 -1
  21. package/dist/{messages-BW0s-6Y9.js → messages-DEqg7HVy.js} +27 -7
  22. package/dist/{monitor-Ddfc-vjX.js → monitor-FNrfkuWL.js} +33 -35
  23. package/dist/plugin-entry.handlers.runtime.js +1 -1
  24. package/dist/probe.runtime-NIJZYqc2.js +2 -0
  25. package/dist/{profile-update-BkgWYDIp.js → profile-update-BQlE5s2J.js} +1 -1
  26. package/dist/{reaction-events-nfUbFLdV.js → reaction-events-BKOLlnCo.js} +3 -3
  27. package/dist/{resolve-targets-BJAPY4Vb.js → resolve-targets-e7AI0P75.js} +2 -2
  28. package/dist/{resolver.runtime-LWJELYq5.js → resolver.runtime-V8u0pHEb.js} +1 -1
  29. package/dist/runtime-api.js +1 -1
  30. package/dist/{sdk-DjaQFCHc.js → sdk-NxK3vzMa.js} +17 -3
  31. package/dist/{send-ZDLU4JTk.js → send-ClHgDZLT.js} +11 -10
  32. package/dist/session-binding-contract-api.js +2 -3
  33. package/dist/{setup-bootstrap-BaXkhgJg.js → setup-bootstrap-BGPjbA5N.js} +1 -1
  34. package/dist/{setup-core-DQn6b5vi.js → setup-core-DigrLebY.js} +1 -1
  35. package/dist/setup-plugin-api.js +1 -1
  36. package/dist/{setup-surface-DlhJdrNI.js → setup-surface-Dtn8sAWs.js} +10 -9
  37. package/dist/subagent-hooks-CMoZaARG.js +48 -0
  38. package/dist/subagent-hooks-api.js +1 -1
  39. package/dist/{target-ids-B-5aQxwn.js → target-ids-Nwx7cMVE.js} +11 -1
  40. package/dist/{thread-binding-api-DRbBZlhS.js → thread-binding-api-CzkeLZCU.js} +1 -1
  41. package/dist/thread-binding-api.js +1 -1
  42. package/dist/{thread-bindings-CcHZP3w2.js → thread-bindings-BYEGfw3h.js} +11 -7
  43. package/dist/thread-bindings-runtime.js +1 -1
  44. package/dist/{thread-bindings-shared-CKnY4LSd.js → thread-bindings-shared-oNPiyMWY.js} +1 -6
  45. package/dist/{tool-actions.runtime-DmdRL0bN.js → tool-actions.runtime-ck6IJyP0.js} +8 -8
  46. package/dist/{verification-C7ig-bQE.js → verification-CabtBTtB.js} +1 -1
  47. package/openclaw.plugin.json +7 -0
  48. package/package.json +4 -4
  49. package/dist/probe.runtime-Dr91B_X3.js +0 -2
  50. package/dist/route-DY6at4qJ.js +0 -161
  51. package/dist/subagent-hooks-dkPAF6Et.js +0 -143
@@ -3,7 +3,7 @@ import { t as SqliteBackedMatrixSyncStore } from "./file-sync-store-DjskBX2o.js"
3
3
  import { n as LogService, r as noop, t as ConsoleLogger } from "./logger-B_71hN6W.js";
4
4
  import { t as MATRIX_IDB_PERSIST_INTERVAL_MS } from "./idb-persistence-lock-DAJ49nZX.js";
5
5
  import { n as isMatrixNotFoundError, t as formatMatrixErrorReason } from "./errors-DKVS3_DO.js";
6
- import { a as throwIfMatrixStartupAborted, r as createMatrixStartupAbortError } from "./client-CeGw0G5S.js";
6
+ import { a as throwIfMatrixStartupAborted, r as createMatrixStartupAbortError } from "./client-BBQdBG7t.js";
7
7
  import { a as matrixEventToRaw, n as createMatrixGuardedFetch, o as parseMxc, t as MatrixAuthedHttpClient } from "./http-client-CycYxU9-.js";
8
8
  import { n as resolveMatrixRoomKeyBackupReadinessError } from "./backup-health-Dm_YMVFT.js";
9
9
  import { t as createMatrixJsSdkClientLogger } from "./logging-DRjvUOIh.js";
@@ -125,6 +125,9 @@ function refreshMatrixDmRoomIds(direct, dmRoomIds) {
125
125
  const MATRIX_SYNC_QUIESCE_TIMEOUT_MS = 5e3;
126
126
  const MATRIX_JS_SDK_SYNC_VERSION = "41.9.0";
127
127
  const matrixJsSdkPackage = createRequire(import.meta.url)("matrix-js-sdk/package.json");
128
+ function requireMatrixClassicSyncInternals(syncApi) {
129
+ return syncApi;
130
+ }
128
131
  function assertMatrixJsSdkSyncVersion() {
129
132
  const version = matrixJsSdkPackage.version;
130
133
  if (version !== MATRIX_JS_SDK_SYNC_VERSION) throw new Error(`Matrix sync quiesce requires matrix-js-sdk ${MATRIX_JS_SDK_SYNC_VERSION}; found ${String(version)}`);
@@ -143,10 +146,14 @@ async function quiesceMatrixClientSync(params) {
143
146
  params.syncStore?.discardPendingSyncCursorPersistence();
144
147
  throw new Error(syncApi === void 0 ? "Matrix sync quiesce requires the classic matrix-js-sdk SyncApi, but none is active" : "Matrix sync quiesce rejected a sliding or unknown matrix-js-sdk sync implementation");
145
148
  }
146
- if (syncApi.getSyncState() === SyncState.Stopped) {
149
+ const syncState = syncApi.getSyncState();
150
+ if (syncState === SyncState.Stopped) {
147
151
  params.markStopped();
148
152
  return;
149
153
  }
154
+ const disconnectedBeforeStop = syncState === SyncState.Error || syncState === SyncState.Reconnecting;
155
+ const syncInternals = requireMatrixClassicSyncInternals(syncApi);
156
+ const keepaliveResolvers = disconnectedBeforeStop ? syncInternals.connectionReturnedResolvers : void 0;
150
157
  await new Promise((resolve, reject) => {
151
158
  let settled = false;
152
159
  const settle = (error) => {
@@ -171,6 +178,11 @@ async function quiesceMatrixClientSync(params) {
171
178
  params.emitter.on("sync.state", onSyncState);
172
179
  try {
173
180
  syncApi.stop();
181
+ if (keepaliveResolvers && syncInternals.connectionReturnedResolvers === keepaliveResolvers) {
182
+ syncInternals.connectionReturnedResolvers = void 0;
183
+ keepaliveResolvers.reject("SyncApi.stop() was called");
184
+ settle();
185
+ }
174
186
  } catch (error) {
175
187
  params.syncStore?.discardPendingSyncCursorPersistence();
176
188
  settle(error instanceof Error ? error : new Error(String(error)));
@@ -208,6 +220,7 @@ var MatrixClientBase = class {
208
220
  this.dmRoomIds = /* @__PURE__ */ new Set();
209
221
  this.cryptoInitialized = false;
210
222
  this.sendQueue = new KeyedAsyncQueue();
223
+ this.syncQuiescePromise = null;
211
224
  this.stopPersistPromise = null;
212
225
  this.verificationSummaryListenerBound = false;
213
226
  this.currentSyncState = null;
@@ -465,7 +478,7 @@ var MatrixClientBase = class {
465
478
  this.started = false;
466
479
  }
467
480
  async quiesceSync() {
468
- await quiesceMatrixClientSync({
481
+ this.syncQuiescePromise ??= quiesceMatrixClientSync({
469
482
  client: this.client,
470
483
  emitter: this.emitter,
471
484
  markStopped: () => {
@@ -474,6 +487,7 @@ var MatrixClientBase = class {
474
487
  started: this.started,
475
488
  syncStore: this.syncStore
476
489
  });
490
+ await this.syncQuiescePromise;
477
491
  }
478
492
  async drainPendingDecryptions(reason = "matrix client shutdown") {
479
493
  await this.decryptBridge?.drainPendingDecryptions(reason);
@@ -1,12 +1,12 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
2
  import { a as resolveMatrixAccountConfig } from "./account-config-BZWN9tGS.js";
3
3
  import { t as getMatrixRuntime } from "./runtime-6S3DNFNv.js";
4
- import { r as normalizeMatrixResolvableTarget, t as isMatrixQualifiedUserId } from "./target-ids-B-5aQxwn.js";
5
- import { a as isStrictDirectRoom, r as inspectMatrixDirectRoomEvidence } from "./direct-room-RinHjtqX.js";
4
+ import { i as normalizeMatrixResolvableTarget, t as isMatrixQualifiedUserId } from "./target-ids-Nwx7cMVE.js";
6
5
  import { n as MATRIX_REACTION_EVENT_TYPE, r as buildMatrixReactionContent, t as MATRIX_ANNOTATION_RELATION_TYPE } from "./reaction-common-DkrQdBSZ.js";
6
+ import { a as isStrictDirectRoom, r as inspectMatrixDirectRoomEvidence } from "./direct-room-RinHjtqX.js";
7
7
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
8
8
  import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
9
- import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeOptionalStringifiedId } from "openclaw/plugin-sdk/string-coerce-runtime";
9
+ import { isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeOptionalStringifiedId } from "openclaw/plugin-sdk/string-coerce-runtime";
10
10
  import { FormatCapabilityProfile, convertMarkdownTables, findCodeRegions, isInsideCode, markdownToIR, renderMarkdownWithMarkers, tokenizeHtmlTags } from "openclaw/plugin-sdk/text-chunking";
11
11
  import { createHash } from "node:crypto";
12
12
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
@@ -19,7 +19,7 @@ import { isAutoLinkedFileRef } from "openclaw/plugin-sdk/text-autolink-runtime";
19
19
  import { isVoiceMessageCompatibleAudio } from "openclaw/plugin-sdk/media-runtime";
20
20
  import { parseBuffer } from "music-metadata";
21
21
  //#region extensions/matrix/src/matrix/send/client.ts
22
- const loadMatrixSendClientRuntime = createLazyRuntimeModule(() => import("./client-bootstrap-BFwT_2VT.js").then((n) => n.t));
22
+ const loadMatrixSendClientRuntime = createLazyRuntimeModule(() => import("./client-bootstrap-Co3RlItb.js").then((n) => n.t));
23
23
  function resolveMediaMaxBytes(accountId, cfg) {
24
24
  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
25
  const mediaMaxMb = resolveMatrixAccountConfig({
@@ -638,17 +638,18 @@ function isPollEventType(eventType) {
638
638
  return POLL_EVENT_TYPES.includes(eventType);
639
639
  }
640
640
  function getTextContent(text) {
641
- if (!text) return "";
642
- return text["m.text"] ?? text["org.matrix.msc1767.text"] ?? text.body ?? "";
641
+ if (!isRecord(text)) return "";
642
+ return normalizeOptionalString(text["m.text"] ?? text["org.matrix.msc1767.text"] ?? text.body) ?? "";
643
643
  }
644
644
  function parsePollStart(content) {
645
645
  const poll = content["m.poll.start"] ?? content[ORG_POLL_START] ?? content["m.poll"];
646
646
  if (!poll) return null;
647
- const question = getTextContent(poll.question).trim();
647
+ const question = getTextContent(poll.question);
648
648
  if (!question) return null;
649
- const answers = poll.answers.map((answer) => ({
650
- id: answer.id,
651
- text: getTextContent(answer).trim()
649
+ const rawAnswers = poll.answers;
650
+ const answers = (Array.isArray(rawAnswers) ? rawAnswers : []).map((answer) => ({
651
+ id: isRecord(answer) && typeof answer.id === "string" ? answer.id : "",
652
+ text: getTextContent(answer)
652
653
  })).filter((answer) => answer.id.trim().length > 0 && answer.text.length > 0);
653
654
  if (answers.length === 0) return null;
654
655
  const maxSelectionsRaw = poll.max_selections;
@@ -1,4 +1,3 @@
1
1
  import { r as setMatrixRuntime } from "./runtime-6S3DNFNv.js";
2
- import { s as resetMatrixThreadBindingsForTests } from "./thread-bindings-shared-CKnY4LSd.js";
3
- import { t as createMatrixThreadBindingManager } from "./thread-bindings-CcHZP3w2.js";
4
- export { createMatrixThreadBindingManager, resetMatrixThreadBindingsForTests, setMatrixRuntime };
2
+ import { t as createMatrixThreadBindingManager } from "./thread-bindings-BYEGfw3h.js";
3
+ export { createMatrixThreadBindingManager, setMatrixRuntime };
@@ -1,6 +1,6 @@
1
1
  import { a as resolveMatrixAccountConfig, n as hasExplicitMatrixAccountConfig } from "./account-config-BZWN9tGS.js";
2
2
  import "./accounts-BCzyubQt.js";
3
- import { n as bootstrapMatrixVerification } from "./verification-C7ig-bQE.js";
3
+ import { n as bootstrapMatrixVerification } from "./verification-CabtBTtB.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) {
@@ -310,7 +310,7 @@ const matrixSetupAdapter = {
310
310
  input
311
311
  }),
312
312
  afterAccountConfigWritten: async ({ previousCfg, cfg, accountId, runtime }) => {
313
- const { runMatrixSetupBootstrapAfterConfigWrite } = await import("./setup-bootstrap-BaXkhgJg.js");
313
+ const { runMatrixSetupBootstrapAfterConfigWrite } = await import("./setup-bootstrap-BGPjbA5N.js");
314
314
  await runMatrixSetupBootstrapAfterConfigWrite({
315
315
  previousCfg,
316
316
  cfg,
@@ -1,2 +1,2 @@
1
- import { n as matrixSetupPlugin } from "./channel.setup-PpxRP9Du.js";
1
+ import { n as matrixSetupPlugin } from "./channel.setup-aNaa3Uyn.js";
2
2
  export { matrixSetupPlugin };
@@ -3,8 +3,9 @@ import { n as requiresExplicitMatrixDefaultAccount } from "./account-selection-C
3
3
  import { a as resolveMatrixAccountConfig } from "./account-config-BZWN9tGS.js";
4
4
  import { n as resolveMatrixEnvAuthReadiness } from "./env-auth-MVS-Vv41.js";
5
5
  import { i as resolveMatrixAccount, r as resolveDefaultMatrixAccountId, t as listMatrixAccountIds } from "./accounts-BCzyubQt.js";
6
+ import { n as isMatrixRoomId } from "./target-ids-Nwx7cMVE.js";
6
7
  import { r as updateMatrixAccountConfig } from "./config-update-Bor_Pjsv.js";
7
- import { a as moveSingleMatrixAccountConfigToNamedAccount, i as createMatrixSetupDmPolicy } from "./setup-core-DQn6b5vi.js";
8
+ import { a as moveSingleMatrixAccountConfigToNamedAccount, i as createMatrixSetupDmPolicy } from "./setup-core-DigrLebY.js";
8
9
  import { n as validateMatrixHomeserverUrl, r as isPrivateOrLoopbackHost, t as resolveValidatedMatrixHomeserverUrl } from "./url-validation-GRHde6lq.js";
9
10
  import { n as ensureMatrixSdkInstalled, r as isMatrixSdkAvailable } from "./deps-CcVJfvRM.js";
10
11
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeStringifiedOptionalString, normalizeUniqueStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
@@ -31,7 +32,7 @@ function isMatrixInviteAutoJoinPolicy(value) {
31
32
  return value === "allowlist" || value === "always" || value === "off";
32
33
  }
33
34
  function isMatrixInviteAutoJoinTarget(entry) {
34
- return entry === "*" || entry.startsWith("!") && entry.includes(":") || entry.startsWith("#") && entry.includes(":");
35
+ return entry === "*" || isMatrixRoomId(entry) || entry.startsWith("#") && entry.includes(":");
35
36
  }
36
37
  function resolveMatrixOnboardingAccountId(cfg, accountId) {
37
38
  return normalizeAccountId$1(normalizeOptionalString(accountId) || resolveDefaultMatrixAccountId(cfg) || DEFAULT_ACCOUNT_ID);
@@ -90,7 +91,7 @@ async function promptMatrixAllowFrom(params) {
90
91
  pending.push(part);
91
92
  }
92
93
  if (pending.length > 0) {
93
- const { resolveMatrixTargets } = await import("./resolve-targets-BJAPY4Vb.js").then((n) => n.n);
94
+ const { resolveMatrixTargets } = await import("./resolve-targets-e7AI0P75.js").then((n) => n.n);
94
95
  const results = await resolveMatrixTargets({
95
96
  cfg,
96
97
  accountId,
@@ -160,7 +161,7 @@ async function configureMatrixInviteAutoJoin(params) {
160
161
  while (true) {
161
162
  const allowlist = normalizeUniqueStringEntries(splitSetupEntries(await params.prompter.text({
162
163
  message: "Matrix invite auto-join allowlist (comma-separated)",
163
- placeholder: "!roomId:server, #alias:server, *",
164
+ placeholder: "!roomId:server, !roomId, #alias:server, *",
164
165
  initialValue: currentAllowlist[0] ? currentAllowlist.join(", ") : void 0,
165
166
  validate: (value) => {
166
167
  return splitSetupEntries(value).length > 0 ? void 0 : "Required";
@@ -168,7 +169,7 @@ async function configureMatrixInviteAutoJoin(params) {
168
169
  })));
169
170
  const invalidEntries = allowlist.filter((entry) => !isMatrixInviteAutoJoinTarget(entry));
170
171
  if (allowlist.length === 0 || invalidEntries.length > 0) {
171
- await params.prompter.note(["Use only stable Matrix invite targets for auto-join: !roomId:server, #alias:server, or *.", invalidEntries.length > 0 ? `Invalid: ${invalidEntries.join(", ")}` : void 0].filter(Boolean).join("\n"), "Matrix invite auto-join");
172
+ await params.prompter.note(["Use only stable Matrix invite targets for auto-join: !roomId:server (or the suffixless !roomId form on room version 12+), #alias:server, or *.", invalidEntries.length > 0 ? `Invalid: ${invalidEntries.join(", ")}` : void 0].filter(Boolean).join("\n"), "Matrix invite auto-join");
172
173
  continue;
173
174
  }
174
175
  return setMatrixAutoJoin(params.cfg, "allowlist", allowlist, accountId);
@@ -191,7 +192,7 @@ async function configureMatrixAccessPrompts(params) {
191
192
  label: "Matrix rooms",
192
193
  currentPolicy: existingAccountConfig.groupPolicy ?? "allowlist",
193
194
  currentEntries: Object.keys(existingGroups ?? {}),
194
- placeholder: "!roomId:server, #alias:server, Project Room",
195
+ placeholder: "!roomId:server, !roomId, #alias:server, Project Room",
195
196
  updatePrompt: Boolean(existingGroups)
196
197
  });
197
198
  if (accessConfig) if (accessConfig.policy !== "allowlist") next = updateMatrixAccountConfig(next, params.accountId, { groupPolicy: accessConfig.policy });
@@ -204,11 +205,11 @@ async function configureMatrixAccessPrompts(params) {
204
205
  const trimmed = normalizeOptionalString(entry) ?? "";
205
206
  if (!trimmed) continue;
206
207
  const cleaned = trimmed.replace(/^(room|channel):/i, "").trim();
207
- if (cleaned.startsWith("!") && cleaned.includes(":")) {
208
+ if (isMatrixRoomId(cleaned)) {
208
209
  resolvedIds.push(cleaned);
209
210
  continue;
210
211
  }
211
- const { listMatrixDirectoryGroupsLive } = await import("./directory-live-Bvg2wAnR.js").then((n) => n.t);
212
+ const { listMatrixDirectoryGroupsLive } = await import("./directory-live-DLQzel12.js").then((n) => n.t);
212
213
  const matches = await listMatrixDirectoryGroupsLive({
213
214
  cfg: next,
214
215
  accountId: params.accountId,
@@ -458,7 +459,7 @@ const matrixOnboardingAdapter = {
458
459
  });
459
460
  },
460
461
  afterConfigWritten: async ({ previousCfg, cfg, accountId, runtime }) => {
461
- const { runMatrixSetupBootstrapAfterConfigWrite } = await import("./setup-bootstrap-BaXkhgJg.js");
462
+ const { runMatrixSetupBootstrapAfterConfigWrite } = await import("./setup-bootstrap-BGPjbA5N.js");
462
463
  await runMatrixSetupBootstrapAfterConfigWrite({
463
464
  previousCfg,
464
465
  cfg,
@@ -0,0 +1,48 @@
1
+ import { a as listBindingsForAccount, i as listAllBindings, n as getMatrixThreadBindingManager, o as removeBindingRecord, s as resolveBindingKey } from "./thread-bindings-shared-oNPiyMWY.js";
2
+ import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
3
+ import { getSessionBindingService } from "openclaw/plugin-sdk/conversation-binding-runtime";
4
+ //#region extensions/matrix/src/matrix/subagent-hooks.ts
5
+ async function handleMatrixSubagentEnded(event) {
6
+ const accountId = normalizeOptionalString(event.accountId) || void 0;
7
+ const matching = (accountId ? listBindingsForAccount(accountId) : listAllBindings()).filter((entry) => entry.targetSessionKey === event.targetSessionKey && entry.targetKind === "subagent");
8
+ const removedBindingKeys = /* @__PURE__ */ new Set();
9
+ if (event.sendFarewell) {
10
+ const bindingService = getSessionBindingService();
11
+ const reason = normalizeOptionalString(event.reason) || "subagent-ended";
12
+ for (const binding of matching) {
13
+ const bindingId = resolveBindingKey(binding);
14
+ if ((await bindingService.unbind({
15
+ bindingId,
16
+ reason
17
+ })).some((entry) => entry.bindingId === bindingId)) removedBindingKeys.add(bindingId);
18
+ }
19
+ }
20
+ const affectedAccountIds = /* @__PURE__ */ new Set();
21
+ for (const binding of matching) {
22
+ if (removedBindingKeys.has(resolveBindingKey(binding))) continue;
23
+ if (removeBindingRecord(binding)) affectedAccountIds.add(binding.accountId);
24
+ }
25
+ for (const acctId of affectedAccountIds) await getMatrixThreadBindingManager(acctId)?.persist();
26
+ }
27
+ function handleMatrixSubagentDeliveryTarget(event) {
28
+ if (!event.expectsCompletionMessage) return;
29
+ if (event.requesterOrigin?.channel?.trim().toLowerCase() !== "matrix") return;
30
+ const requesterAccountId = normalizeOptionalString(event.requesterOrigin?.accountId);
31
+ const requesterThreadId = event.requesterOrigin?.threadId != null && event.requesterOrigin.threadId !== "" ? String(event.requesterOrigin.threadId).trim() : "";
32
+ const bindings = (requesterAccountId ? listBindingsForAccount(requesterAccountId) : listAllBindings()).filter((entry) => entry.targetSessionKey === event.childSessionKey && entry.targetKind === "subagent");
33
+ if (bindings.length === 0) return;
34
+ let binding;
35
+ if (requesterThreadId) binding = bindings.find((entry) => entry.conversationId === requesterThreadId && (!requesterAccountId || entry.accountId === requesterAccountId));
36
+ if (!binding && bindings.length === 1) binding = bindings[0];
37
+ if (!binding) return;
38
+ const roomId = binding.parentConversationId ?? binding.conversationId;
39
+ const threadId = binding.parentConversationId && binding.parentConversationId !== binding.conversationId ? binding.conversationId : void 0;
40
+ return { origin: {
41
+ channel: "matrix",
42
+ accountId: binding.accountId,
43
+ to: `room:${roomId}`,
44
+ ...threadId ? { threadId } : {}
45
+ } };
46
+ }
47
+ //#endregion
48
+ export { handleMatrixSubagentDeliveryTarget, handleMatrixSubagentEnded };
@@ -1,6 +1,6 @@
1
1
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
2
2
  //#region extensions/matrix/subagent-hooks-api.ts
3
- const loadMatrixSubagentHooksModule = createLazyRuntimeModule(() => import("./subagent-hooks-dkPAF6Et.js"));
3
+ const loadMatrixSubagentHooksModule = createLazyRuntimeModule(() => import("./subagent-hooks-CMoZaARG.js"));
4
4
  function registerMatrixSubagentHooks(api) {
5
5
  api.on("subagent_ended", async (event) => {
6
6
  const { handleMatrixSubagentEnded } = await loadMatrixSubagentHooksModule();
@@ -52,6 +52,16 @@ function isMatrixQualifiedUserId(raw) {
52
52
  const trimmed = raw.trim();
53
53
  return trimmed.startsWith("@") && trimmed.includes(":");
54
54
  }
55
+ /**
56
+ * Whether `raw` is already a literal room ID rather than a name/query to resolve.
57
+ * Room version 12 (MSC4291) dropped the trailing ":server" from room IDs — they're
58
+ * now a hash of the create event — so this must not require a colon the way user
59
+ * IDs and aliases still do.
60
+ */
61
+ function isMatrixRoomId(raw) {
62
+ const trimmed = raw.trim();
63
+ return trimmed.startsWith("!") && trimmed.length > 1;
64
+ }
55
65
  function normalizeMatrixResolvableTarget(raw) {
56
66
  return stripKnownPrefixes(raw, [
57
67
  MATRIX_PREFIX,
@@ -74,4 +84,4 @@ function resolveMatrixDirectUserId(params) {
74
84
  return isMatrixQualifiedUserId(userId) ? userId : void 0;
75
85
  }
76
86
  //#endregion
77
- export { resolveMatrixTargetIdentity as a, resolveMatrixDirectUserId as i, normalizeMatrixMessagingTarget as n, normalizeMatrixResolvableTarget as r, isMatrixQualifiedUserId as t };
87
+ export { resolveMatrixDirectUserId as a, normalizeMatrixResolvableTarget as i, isMatrixRoomId as n, resolveMatrixTargetIdentity as o, normalizeMatrixMessagingTarget as r, isMatrixQualifiedUserId as t };
@@ -1,4 +1,4 @@
1
- import { a as resolveMatrixTargetIdentity } from "./target-ids-B-5aQxwn.js";
1
+ import { o as resolveMatrixTargetIdentity } from "./target-ids-Nwx7cMVE.js";
2
2
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
3
3
  //#region extensions/matrix/src/thread-binding-api.ts
4
4
  const defaultTopLevelPlacement = "child";
@@ -1,2 +1,2 @@
1
- import { n as resolveMatrixInboundConversation, t as defaultTopLevelPlacement } from "./thread-binding-api-DRbBZlhS.js";
1
+ import { n as resolveMatrixInboundConversation, t as defaultTopLevelPlacement } from "./thread-binding-api-CzkeLZCU.js";
2
2
  export { defaultTopLevelPlacement, resolveMatrixInboundConversation as resolveInboundConversation };
@@ -1,7 +1,7 @@
1
1
  import { t as getMatrixRuntime } from "./runtime-6S3DNFNv.js";
2
- import { a as listBindingsForAccount, c as resolveBindingKey, f as setMatrixThreadBindingManagerEntry, h as toSessionBindingRecord, l as resolveEffectiveBindingExpiry, m as toMatrixBindingTargetKind, o as removeBindingRecord, r as getMatrixThreadBindingManagerEntry, t as deleteMatrixThreadBindingManagerEntry, u as setBindingRecord } from "./thread-bindings-shared-CKnY4LSd.js";
2
+ import { a as listBindingsForAccount, c as resolveEffectiveBindingExpiry, d as setMatrixThreadBindingManagerEntry, l as setBindingRecord, m as toSessionBindingRecord, o as removeBindingRecord, p as toMatrixBindingTargetKind, r as getMatrixThreadBindingManagerEntry, s as resolveBindingKey, t as deleteMatrixThreadBindingManagerEntry } from "./thread-bindings-shared-oNPiyMWY.js";
3
3
  import { M as resolveMatrixSqliteStateEnv, N as resolveMatrixSqliteStateKey, c as resolveMatrixStateFilePath, t as claimCurrentTokenStorageState } from "./storage-BsGuHngK.js";
4
- import { r as sendMessageMatrix } from "./send-ZDLU4JTk.js";
4
+ import { r as sendMessageMatrix } from "./send-ClHgDZLT.js";
5
5
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
6
6
  import { createHash } from "node:crypto";
7
7
  import path from "node:path";
@@ -153,7 +153,7 @@ async function createMatrixThreadBindingManager(params) {
153
153
  const existingEntry = getMatrixThreadBindingManagerEntry(params.accountId);
154
154
  if (existingEntry) {
155
155
  if (existingEntry.storageKey === storageKey) return existingEntry.manager;
156
- existingEntry.manager.stop();
156
+ await existingEntry.manager.stop();
157
157
  }
158
158
  const pluginLoaded = await loadBindingsFromPluginState({
159
159
  accountId: params.accountId,
@@ -274,20 +274,24 @@ async function createMatrixThreadBindingManager(params) {
274
274
  })
275
275
  });
276
276
  },
277
- stop: () => {
277
+ stop: async () => {
278
278
  if (sweepTimer) clearInterval(sweepTimer);
279
+ let finalPersist = persistQueue;
279
280
  if (persistTimer) {
280
281
  clearTimeout(persistTimer);
281
282
  persistTimer = null;
282
- persistSafely("shutdown-flush");
283
+ finalPersist = enqueuePersist();
283
284
  }
284
285
  unregisterSessionBindingAdapter({
285
286
  channel: "matrix",
286
287
  accountId: params.accountId,
287
288
  adapter: sessionBindingAdapter
288
289
  });
289
- if (getMatrixThreadBindingManagerEntry(params.accountId)?.manager === manager) deleteMatrixThreadBindingManagerEntry(params.accountId);
290
- for (const record of listBindingsForAccount(params.accountId)) removeBindingRecord(record);
290
+ if (getMatrixThreadBindingManagerEntry(params.accountId)?.manager === manager) {
291
+ deleteMatrixThreadBindingManagerEntry(params.accountId);
292
+ for (const record of listBindingsForAccount(params.accountId)) removeBindingRecord(record);
293
+ }
294
+ await finalPersist;
291
295
  }
292
296
  };
293
297
  let sweepTimer = null;
@@ -1,2 +1,2 @@
1
- import { d as setMatrixThreadBindingIdleTimeoutBySessionKey, p as setMatrixThreadBindingMaxAgeBySessionKey } from "./thread-bindings-shared-CKnY4LSd.js";
1
+ import { f as setMatrixThreadBindingMaxAgeBySessionKey, u as setMatrixThreadBindingIdleTimeoutBySessionKey } from "./thread-bindings-shared-oNPiyMWY.js";
2
2
  export { setMatrixThreadBindingIdleTimeoutBySessionKey, setMatrixThreadBindingMaxAgeBySessionKey };
@@ -88,10 +88,5 @@ function setMatrixThreadBindingMaxAgeBySessionKey(params) {
88
88
  maxAgeMs: manager.getMaxAgeMs()
89
89
  }));
90
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
91
  //#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 };
92
+ export { listBindingsForAccount as a, resolveEffectiveBindingExpiry as c, setMatrixThreadBindingManagerEntry as d, setMatrixThreadBindingMaxAgeBySessionKey as f, listAllBindings as i, setBindingRecord as l, toSessionBindingRecord as m, getMatrixThreadBindingManager as n, removeBindingRecord as o, toMatrixBindingTargetKind as p, getMatrixThreadBindingManagerEntry as r, resolveBindingKey as s, deleteMatrixThreadBindingManagerEntry as t, setMatrixThreadBindingIdleTimeoutBySessionKey as u };
@@ -1,15 +1,15 @@
1
1
  import { a as resolveMatrixAccountConfig, o as resolveMatrixBaseConfig } from "./account-config-BZWN9tGS.js";
2
2
  import { i as resolveMatrixAccount } from "./accounts-BCzyubQt.js";
3
- import { r as resolveMatrixRoomConfig } from "./channel-VSrHgTON.js";
4
- import { r as normalizeMatrixResolvableTarget } from "./target-ids-B-5aQxwn.js";
5
- import { g as parsePollStart, h as isPollStartType, n as reactMatrixMessage, u as buildPollResponseContent, x as resolveMatrixRoomId } from "./send-ZDLU4JTk.js";
6
- import { i as isStrictDirectMembership, n as hasDirectMatrixMemberFlag, o as readJoinedMatrixMembers } from "./direct-room-RinHjtqX.js";
3
+ import { l as resolveMatrixRoomConfig } from "./channel-CzQw5OZN.js";
4
+ import { i as normalizeMatrixResolvableTarget } from "./target-ids-Nwx7cMVE.js";
7
5
  import { i as buildMatrixReactionRelationsPath, o as selectOwnMatrixReactionEventIds, s as summarizeMatrixReactionEvents } from "./reaction-common-DkrQdBSZ.js";
8
- import { n as withResolvedActionClient, r as withResolvedRoomAction } from "./client-sJesKQmp.js";
9
- 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-BW0s-6Y9.js";
6
+ import { g as parsePollStart, h as isPollStartType, n as reactMatrixMessage, u as buildPollResponseContent, x as resolveMatrixRoomId } from "./send-ClHgDZLT.js";
7
+ import { i as isStrictDirectMembership, n as hasDirectMatrixMemberFlag, o as readJoinedMatrixMembers } from "./direct-room-RinHjtqX.js";
8
+ import { n as withResolvedActionClient, r as withResolvedRoomAction } from "./client-D8XghqmX.js";
9
+ 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-DEqg7HVy.js";
10
10
  import { c as readReactionParams, d as resolveAllowlistProviderRuntimeGroupPolicy, f as resolveDefaultGroupPolicy, i as createActionGate, l as readStringArrayParam, n as ToolAuthorizationError, o as jsonResult, s as readPositiveIntegerParam, u as readStringParam } from "./runtime-api-BGO16Fu8.js";
11
- import { t as applyMatrixProfileUpdate } from "./profile-update-BkgWYDIp.js";
12
- 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-C7ig-bQE.js";
11
+ import { t as applyMatrixProfileUpdate } from "./profile-update-BQlE5s2J.js";
12
+ 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-CabtBTtB.js";
13
13
  import { t as createMatrixRoomInfoResolver } from "./room-info-BXQA7y10.js";
14
14
  import { normalizeOptionalLowercaseString, uniqueStrings, uniqueValues } from "openclaw/plugin-sdk/string-coerce-runtime";
15
15
  import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
- import { i as withStartedActionClient, n as withResolvedActionClient } from "./client-sJesKQmp.js";
2
+ import { i as withStartedActionClient, n as withResolvedActionClient } from "./client-D8XghqmX.js";
3
3
  import { n as formatMatrixEncryptionUnavailableError } from "./encryption-guidance-DmLY8NiO.js";
4
4
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
5
5
  import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
@@ -6,6 +6,13 @@
6
6
  },
7
7
  "name": "Matrix",
8
8
  "description": "OpenClaw Matrix channel plugin for rooms and direct messages.",
9
+ "cliCommands": [
10
+ {
11
+ "name": "matrix",
12
+ "description": "Manage Matrix accounts, verification, devices, and profile state",
13
+ "hasSubcommands": true
14
+ }
15
+ ],
9
16
  "icon": "https://cdn.simpleicons.org/matrix",
10
17
  "commandAliases": [
11
18
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/matrix",
3
- "version": "2026.8.1-beta.2",
3
+ "version": "2026.8.1-beta.3",
4
4
  "description": "OpenClaw Matrix channel plugin for rooms and direct messages.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -18,7 +18,7 @@
18
18
  "zod": "4.4.3"
19
19
  },
20
20
  "peerDependencies": {
21
- "openclaw": ">=2026.8.1-beta.2"
21
+ "openclaw": ">=2026.8.1-beta.3"
22
22
  },
23
23
  "peerDependenciesMeta": {
24
24
  "openclaw": {
@@ -167,10 +167,10 @@
167
167
  "allowInvalidConfigRecovery": true
168
168
  },
169
169
  "compat": {
170
- "pluginApi": ">=2026.8.1-beta.2"
170
+ "pluginApi": ">=2026.8.1-beta.3"
171
171
  },
172
172
  "build": {
173
- "openclawVersion": "2026.8.1-beta.2"
173
+ "openclawVersion": "2026.8.1-beta.3"
174
174
  },
175
175
  "release": {
176
176
  "publishToClawHub": true,
@@ -1,2 +0,0 @@
1
- import { o as createMatrixClient } from "./client-CeGw0G5S.js";
2
- export { createMatrixClient };