@xmanrui/dsh-im 4.24.1 → 4.25.0

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 (40) hide show
  1. package/README.en.md +6 -2
  2. package/README.md +6 -2
  3. package/THIRD_PARTY_NOTICES.md +2 -0
  4. package/lib/client.js +564 -279
  5. package/lib/index.js +298 -289
  6. package/package.json +4 -2
  7. package/plugin-src/client/channel-logos.js +11 -0
  8. package/plugin-src/client/channels/matrix/api.js +11 -0
  9. package/plugin-src/client/channels/matrix/index.js +151 -0
  10. package/plugin-src/client/channels/matrix/styles.js +36 -0
  11. package/plugin-src/client/i18n.js +16 -0
  12. package/plugin-src/client/index.js +20 -0
  13. package/plugin-src/client/session-channel-logos.js +2 -1
  14. package/plugin-src/client/styles.js +5 -3
  15. package/plugin-src/client/update-panel.js +25 -11
  16. package/plugin-src/host/channels/matrix/index.mjs +31 -0
  17. package/plugin-src/host/channels/matrix/production.mjs +227 -0
  18. package/plugin-src/host/channels/matrix/rpc.mjs +228 -0
  19. package/plugin-src/host/channels/shared/access-policy-production.mjs +1 -1
  20. package/plugin-src/host/channels/shared/startup-error.mjs +2 -1
  21. package/plugin-src/host/delivery-adapter.mjs +18 -0
  22. package/plugin-src/host/delivery-suggestions.mjs +13 -0
  23. package/plugin-src/host/index.mjs +3 -0
  24. package/scripts/verify-lan-management.mjs +1 -1
  25. package/scripts/verify-package.mjs +5 -1
  26. package/src/channels/matrix/matrix-api.mjs +696 -0
  27. package/src/channels/matrix/matrix-bridge.mjs +20 -0
  28. package/src/channels/matrix/matrix-config-store.mjs +356 -0
  29. package/src/channels/matrix/matrix-controller.mjs +404 -0
  30. package/src/channels/matrix/matrix-crypto-store.mjs +279 -0
  31. package/src/channels/matrix/matrix-crypto.mjs +1014 -0
  32. package/src/channels/matrix/matrix-harness-client.mjs +11 -0
  33. package/src/channels/matrix/matrix-normalize.mjs +357 -0
  34. package/src/channels/matrix/matrix-rich-text.mjs +313 -0
  35. package/src/channels/matrix/matrix-runtime.mjs +900 -0
  36. package/src/channels/shared/command-catalog.mjs +1 -1
  37. package/src/channels/shared/i18n-en/matrix.mjs +75 -0
  38. package/src/channels/shared/i18n-en.mjs +2 -0
  39. package/src/channels/shared/session-channel-labels.mjs +1 -0
  40. package/src/channels/shared/text-harness-bridge.mjs +3 -0
package/lib/client.js CHANGED
@@ -568,13 +568,13 @@ __export(index_exports, {
568
568
  module.exports = __toCommonJS(index_exports);
569
569
 
570
570
  // plugin-src/management-rpc.mjs
571
- function rpcEndpoint(channel6) {
572
- if (!/^\/[A-Za-z0-9._~-]+$/.test(channel6)) throw new TypeError("Invalid IM RPC channel");
573
- return `dsh-im${channel6}`;
571
+ function rpcEndpoint(channel7) {
572
+ if (!/^\/[A-Za-z0-9._~-]+$/.test(channel7)) throw new TypeError("Invalid IM RPC channel");
573
+ return `dsh-im${channel7}`;
574
574
  }
575
- async function callManagementRpc(connection, channel6, method, payload, signal) {
575
+ async function callManagementRpc(connection, channel7, method, payload, signal) {
576
576
  try {
577
- return await connection.rpc.call("/api", rpcEndpoint(channel6), { method, payload }, signal);
577
+ return await connection.rpc.call("/api", rpcEndpoint(channel7), { method, payload }, signal);
578
578
  } catch (cause) {
579
579
  if (signal?.aborted || cause?.name === "AbortError") throw cause;
580
580
  const error = new Error("\u65E0\u6CD5\u8BBF\u95EE DSH \u7BA1\u7406\u63A5\u53E3\uFF0C\u8BF7\u68C0\u67E5 DSH \u8FDE\u63A5\u6216\u91CD\u65B0\u767B\u5F55\u540E\u91CD\u8BD5\u3002", { cause });
@@ -590,13 +590,13 @@ async function callManagementRpc(connection, channel6, method, payload, signal)
590
590
  }
591
591
 
592
592
  // plugin-src/client/index.js
593
- var React33 = __toESM(require("react"), 1);
593
+ var React34 = __toESM(require("react"), 1);
594
594
 
595
595
  // package.json
596
596
  var package_default = {
597
597
  name: "@xmanrui/dsh-im",
598
- version: "4.24.1",
599
- description: "\u628A\u5341\u4E00\u79CD IM \u6E20\u9053\u548C\u516C\u7F51 AI Office \u63A5\u5165\u672C\u673A DeepSeek Harness\u3002 Connect eleven IM channels and a public AI Office to a local DeepSeek Harness.",
598
+ version: "4.25.0",
599
+ description: "\u628A\u5341\u4E8C\u79CD IM \u6E20\u9053\u548C\u516C\u7F51 AI Office \u63A5\u5165\u672C\u673A DeepSeek Harness\u3002 Connect twelve IM channels and a public AI Office to a local DeepSeek Harness.",
600
600
  keywords: [
601
601
  "deepseek-harness",
602
602
  "dsh",
@@ -616,6 +616,7 @@ var package_default = {
616
616
  "discord",
617
617
  "whatsapp",
618
618
  "imessage",
619
+ "matrix",
619
620
  "ai-office"
620
621
  ],
621
622
  author: "xmanrui (https://github.com/xmanrui)",
@@ -761,6 +762,7 @@ var package_default = {
761
762
  node: ">=22.19"
762
763
  },
763
764
  dependencies: {
765
+ "@matrix-org/olm": "3.2.15",
764
766
  "@tencent-connect/qqbot-connector": "1.2.0",
765
767
  "@tencent-connect/qqbot-nodejs": "1.0.4",
766
768
  "@wecom/aibot-node-sdk": "1.0.7",
@@ -950,6 +952,19 @@ function IMessageLogoGlyph({ size } = {}) {
950
952
  d: "M12 2.5C5.65 2.5.5 6.66.5 11.8c0 2.76 1.49 5.24 3.85 6.94.28 1.34-.35 2.76-1.6 4.01 2.1-.2 3.87-.86 5.26-1.85 1.25.4 2.6.62 3.99.62 6.35 0 11.5-4.35 11.5-9.72S18.35 2.5 12 2.5Z"
951
953
  }));
952
954
  }
955
+ function MatrixLogoGlyph({ size } = {}) {
956
+ return h("svg", {
957
+ ...dimensions(size),
958
+ viewBox: "0 0 24 24",
959
+ focusable: "false",
960
+ "aria-hidden": "true",
961
+ "data-im-channel-logo": "matrix"
962
+ }, h("path", {
963
+ fill: "currentColor",
964
+ "fill-rule": "evenodd",
965
+ d: "M4 4h16a2.4 2.4 0 0 1 2.4 2.4v8.2A2.4 2.4 0 0 1 20 17h-7.55l-4.2 3.3a.6.6 0 0 1-.98-.47V17H4A2.4 2.4 0 0 1 1.6 14.6V6.4A2.4 2.4 0 0 1 4 4Zm3 4.1a1.45 1.45 0 1 0 0 2.9 1.45 1.45 0 0 0 0-2.9Zm5.6 0a1.45 1.45 0 1 0 0 2.9 1.45 1.45 0 0 0 0-2.9Zm5.6 0a1.45 1.45 0 1 0 0 2.9 1.45 1.45 0 0 0 0-2.9Z"
966
+ }));
967
+ }
953
968
  function OfficeLogoGlyph({ size } = {}) {
954
969
  return h(
955
970
  "svg",
@@ -1860,6 +1875,19 @@ var EN = Object.freeze({
1860
1875
  "Gateway \u957F\u8FDE\u63A5": "Gateway persistent connection",
1861
1876
  " Socket Mode \u957F\u8FDE\u63A5": " Socket Mode persistent connection",
1862
1877
  "Socket Mode \u957F\u8FDE\u63A5": "Socket Mode persistent connection",
1878
+ " CS API \u957F\u8F6E\u8BE2": " CS API long polling",
1879
+ "CS API \u957F\u8F6E\u8BE2": "CS API long polling",
1880
+ "\u63A5\u5165 Matrix \u673A\u5668\u4EBA": "Connect a Matrix bot",
1881
+ "\u8FDE\u63A5\u4F60\u7684 Matrix homeserver": "Connect your Matrix homeserver",
1882
+ "\u586B\u5199 homeserver \u5730\u5740\uFF0C\u5E76\u63D0\u4F9B\u8BBF\u95EE\u4EE4\u724C\uFF0C\u6216\u8005\u7528\u6237 ID \u4E0E\u5BC6\u7801\u7684\u7EC4\u5408\u3002\u673A\u5668\u4EBA\u53EA\u8BBF\u95EE\u8BE5 homeserver\uFF0C\u4E0D\u8FDE\u63A5\u7B2C\u4E09\u65B9\u670D\u52A1\u5668\u3002": "Enter the homeserver URL plus an access token, or a user id with a password. The bot only talks to that homeserver and never to third-party servers.",
1883
+ "Homeserver \u5730\u5740": "Homeserver URL",
1884
+ "\u8BBF\u95EE\u4EE4\u724C\uFF08\u4E0E\u7528\u6237 ID\u3001\u5BC6\u7801\u4E8C\u9009\u4E00\uFF09": "Access token (or user id + password)",
1885
+ "\u7528\u6237 ID\uFF08\u53EF\u9009\uFF09": "User id (optional)",
1886
+ "\u5BC6\u7801\uFF08\u53EF\u9009\uFF09": "Password (optional)",
1887
+ "\u8BBF\u95EE\u4EE4\u724C\u6765\u81EA Element \u8BBE\u7F6E \u2192 \u5E2E\u52A9 \u2192 \u7F16\u8F91\u8BBE\u7F6E\uFF0C\u6216 homeserver \u7684\u767B\u5F55\u63A5\u53E3\uFF1B\u7528\u6237 ID \u4E0E\u5BC6\u7801\u65B9\u5F0F\u4F1A\u4E3A\u672C\u5B89\u88C5\u6D3E\u751F\u7A33\u5B9A\u8BBE\u5907\u4F1A\u8BDD\u3002": "The access token comes from Element settings \u2192 Help \u2192 Advanced settings, or from the homeserver login API; the user id and password flow derives a stable device session for this installation.",
1888
+ "\u586B\u5199 homeserver \u5730\u5740\u4E0E\u8BBF\u95EE\u4EE4\u724C\uFF0C\u6216\u8005\u7528\u6237 ID \u4E0E\u5BC6\u7801\uFF0C\u5373\u53EF\u8BA9\u673A\u5668\u4EBA\u4EE5 CS API \u957F\u8F6E\u8BE2\u63A5\u6536\u6D88\u606F\u5E76\u4EE5\u5BCC\u6587\u672C\u56DE\u590D\u3002": "Enter the homeserver URL with an access token, or a user id with a password, and the bot receives messages over the CS API long poll and replies with rich text.",
1889
+ "\u4F7F\u7528 homeserver \u4E0E\u51ED\u636E\u63A5\u5165 Matrix \u673A\u5668\u4EBA": "Connect a Matrix bot with the homeserver and credentials",
1890
+ "\u8BBF\u95EE\u4EE4\u724C\u6216\u7528\u6237 ID \u4E0E\u5BC6\u7801": "access token or user id with password",
1863
1891
  "\u63A5\u5165 Telegram \u673A\u5668\u4EBA": "Connect a Telegram bot",
1864
1892
  "\u5148\u901A\u8FC7 @BotFather \u83B7\u53D6 Bot Token\uFF0C\u518D\u5728\u8FD9\u91CC\u5B8C\u6210\u63A5\u5165\u3002": "Get a Bot Token from @BotFather, then connect it here.",
1865
1893
  "\u586B\u5199 @BotFather \u751F\u6210\u7684 Bot Token": "Enter the Bot Token from @BotFather",
@@ -4033,7 +4061,7 @@ function CredentialActionIcon() {
4033
4061
  );
4034
4062
  }
4035
4063
  function CredentialBindingPanel({
4036
- channel: channel6,
4064
+ channel: channel7,
4037
4065
  identityLabel,
4038
4066
  identityPlaceholder,
4039
4067
  secretLabel,
@@ -4061,7 +4089,7 @@ function CredentialBindingPanel({
4061
4089
  className: "ddt-card dim-surfaceCard dim-credentialPanel",
4062
4090
  "aria-labelledby": headingId
4063
4091
  },
4064
- h2("h3", { id: headingId, className: "dim-credentialTitle" }, `\u624B\u52A8\u63A5\u5165${channel6}\u673A\u5668\u4EBA`),
4092
+ h2("h3", { id: headingId, className: "dim-credentialTitle" }, `\u624B\u52A8\u63A5\u5165${channel7}\u673A\u5668\u4EBA`),
4065
4093
  children,
4066
4094
  h2(
4067
4095
  "form",
@@ -4153,7 +4181,7 @@ function SettingsGlyph() {
4153
4181
  );
4154
4182
  }
4155
4183
  function BotSettingsButton({
4156
- channel: channel6,
4184
+ channel: channel7,
4157
4185
  botId,
4158
4186
  botName,
4159
4187
  connected,
@@ -4169,11 +4197,11 @@ function BotSettingsButton({
4169
4197
  {
4170
4198
  type: "button",
4171
4199
  className: "dim-botSettingsButton",
4172
- "data-delivery-channel": channel6,
4200
+ "data-delivery-channel": channel7,
4173
4201
  "aria-label": "\u66F4\u591A\u673A\u5668\u4EBA\u8BBE\u7F6E",
4174
4202
  onClick: () => openBotSettings?.({
4175
4203
  ...channelSettings && typeof channelSettings === "object" ? channelSettings : {},
4176
- channel: channel6,
4204
+ channel: channel7,
4177
4205
  botId,
4178
4206
  botName,
4179
4207
  connected: Boolean(connected),
@@ -6478,16 +6506,16 @@ var TOKEN_BOT_ENDPOINTS = Object.freeze({
6478
6506
  setAlias: "bot.alias.set",
6479
6507
  setThinkingTraces: "bot.thinking-traces.set"
6480
6508
  });
6481
- function createTokenChannelApi(channel6, connectionSummary, {
6509
+ function createTokenChannelApi(channel7, connectionSummary, {
6482
6510
  normalizeBotExtension = () => ({})
6483
6511
  } = {}) {
6484
- const unwrapRpcResult16 = (result) => {
6512
+ const unwrapRpcResult17 = (result) => {
6485
6513
  if (!isRecord2(result) || typeof result.ok !== "boolean") {
6486
- throw new Error(`${channel6} \u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94`);
6514
+ throw new Error(`${channel7} \u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94`);
6487
6515
  }
6488
6516
  if (!result.ok) {
6489
- const error = new Error(text2(result.error?.message, `${channel6} \u64CD\u4F5C\u5931\u8D25`));
6490
- error.code = text2(result.error?.code, `${channel6.toUpperCase()}_RPC_ERROR`, 80);
6517
+ const error = new Error(text2(result.error?.message, `${channel7} \u64CD\u4F5C\u5931\u8D25`));
6518
+ error.code = text2(result.error?.code, `${channel7.toUpperCase()}_RPC_ERROR`, 80);
6491
6519
  Object.assign(error, diagnosticFields(result.error));
6492
6520
  throw error;
6493
6521
  }
@@ -6511,30 +6539,30 @@ function createTokenChannelApi(channel6, connectionSummary, {
6511
6539
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
6512
6540
  bot: {
6513
6541
  ...normalizeBotAlias(value.bot),
6514
- name: text2(value.bot?.name, `${channel6}\u673A\u5668\u4EBA`, 100),
6542
+ name: text2(value.bot?.name, `${channel7}\u673A\u5668\u4EBA`, 100),
6515
6543
  username: text2(value.bot?.username, "", 100),
6516
6544
  idMasked: text2(value.bot?.idMasked, "\u673A\u5668\u4EBA\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58", 140)
6517
6545
  },
6518
6546
  health: {
6519
6547
  summary: text2(
6520
6548
  value.health?.summary,
6521
- connected ? `${channel6}${connectionSummary}\u8FD0\u884C\u6B63\u5E38` : `${channel6}\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA`
6549
+ connected ? `${channel7}${connectionSummary}\u8FD0\u884C\u6B63\u5E38` : `${channel7}\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA`
6522
6550
  ),
6523
6551
  lastCheckedAt: timestamp2(value.health?.lastCheckedAt)
6524
6552
  },
6525
6553
  lastMessageError: normalizeLastMessageError(value.lastMessageError),
6526
6554
  error: isRecord2(value.error) ? {
6527
6555
  ...diagnosticFields(value.error),
6528
- code: text2(value.error.code, `${channel6.toUpperCase()}_ACCOUNT_ERROR`, 80),
6529
- message: text2(value.error.message, `${channel6}\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA`)
6556
+ code: text2(value.error.code, `${channel7.toUpperCase()}_ACCOUNT_ERROR`, 80),
6557
+ message: text2(value.error.message, `${channel7}\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA`)
6530
6558
  } : null,
6531
6559
  ...isRecord2(extension) ? extension : {}
6532
6560
  };
6533
6561
  };
6534
- const normalizeSnapshot12 = (value) => {
6562
+ const normalizeSnapshot13 = (value) => {
6535
6563
  const source = isRecord2(value?.snapshot) ? value.snapshot : value;
6536
6564
  if (!isRecord2(source) || !Array.isArray(source.bots)) {
6537
- throw new Error(`${channel6} \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868`);
6565
+ throw new Error(`${channel7} \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868`);
6538
6566
  }
6539
6567
  const bots = source.bots.map(normalizeBot8).filter(Boolean);
6540
6568
  return {
@@ -6546,12 +6574,12 @@ function createTokenChannelApi(channel6, connectionSummary, {
6546
6574
  ...isRecord2(source.permissions) ? { permissions: source.permissions } : {}
6547
6575
  };
6548
6576
  };
6549
- const presentError16 = (error) => ({
6577
+ const presentError17 = (error) => ({
6550
6578
  ...diagnosticFields(error),
6551
- code: text2(error?.code, `${channel6.toUpperCase()}_ERROR`, 80),
6552
- message: text2(error?.message, `${channel6}\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5`)
6579
+ code: text2(error?.code, `${channel7.toUpperCase()}_ERROR`, 80),
6580
+ message: text2(error?.message, `${channel7}\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5`)
6553
6581
  });
6554
- return Object.freeze({ unwrapRpcResult: unwrapRpcResult16, normalizeSnapshot: normalizeSnapshot12, presentError: presentError16 });
6582
+ return Object.freeze({ unwrapRpcResult: unwrapRpcResult17, normalizeSnapshot: normalizeSnapshot13, presentError: presentError17 });
6555
6583
  }
6556
6584
 
6557
6585
  // plugin-src/client/channels/discord/api.js
@@ -6594,9 +6622,9 @@ function connectionTestNotice(value) {
6594
6622
  }
6595
6623
  function createTokenChannelSettings(definition) {
6596
6624
  const {
6597
- channel: channel6,
6625
+ channel: channel7,
6598
6626
  endpoints,
6599
- api: api6,
6627
+ api: api7,
6600
6628
  LogoGlyph,
6601
6629
  installStyles,
6602
6630
  pageClass,
@@ -6608,7 +6636,7 @@ function createTokenChannelSettings(definition) {
6608
6636
  platformLabel,
6609
6637
  CredentialPanel = null,
6610
6638
  credentialPayload = ({ secret }) => ({ token: secret }),
6611
- credentialAriaLabel = `\u4F7F\u7528 Bot Token \u63A5\u5165 ${channel6} \u673A\u5668\u4EBA`,
6639
+ credentialAriaLabel = `\u4F7F\u7528 Bot Token \u63A5\u5165 ${channel7} \u673A\u5668\u4EBA`,
6612
6640
  credentialOpenLabel = "\u624B\u52A8\u63A5\u5165",
6613
6641
  credentialCloseLabel = "\u6536\u8D77\u51ED\u636E",
6614
6642
  credentialNoun = "Bot Token",
@@ -6632,7 +6660,7 @@ function createTokenChannelSettings(definition) {
6632
6660
  CollapsibleAccountSection,
6633
6661
  {
6634
6662
  settings: h2(BotSettingsButton, {
6635
- channel: channel6.toLowerCase(),
6663
+ channel: channel7.toLowerCase(),
6636
6664
  botId: account.botId,
6637
6665
  botName: account.bot.name,
6638
6666
  connected: account.connected,
@@ -6794,11 +6822,11 @@ function createTokenChannelSettings(definition) {
6794
6822
  };
6795
6823
  }, []);
6796
6824
  const invoke = React15.useCallback(async (endpoint, payload = {}, signal) => {
6797
- if (typeof rpcCall !== "function") throw new TypeError(`${channel6} \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5`);
6825
+ if (typeof rpcCall !== "function") throw new TypeError(`${channel7} \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5`);
6798
6826
  const operation = !["connection.status", "provision.poll", "provision.begin", "provision.cancel"].includes(endpoint);
6799
6827
  if (operation && mounted.current) setOperationError(null);
6800
6828
  try {
6801
- const value = api6.unwrapRpcResult(await rpcCall(endpoint, payload, signal));
6829
+ const value = api7.unwrapRpcResult(await rpcCall(endpoint, payload, signal));
6802
6830
  if (operation && mounted.current) setOperationError(value?.testMessage?.error ?? value?.warnings?.[0] ?? null);
6803
6831
  return value;
6804
6832
  } catch (error) {
@@ -6811,7 +6839,7 @@ function createTokenChannelSettings(definition) {
6811
6839
  if (workspaceVersion === null) return;
6812
6840
  if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
6813
6841
  try {
6814
- const snapshot = api6.normalizeSnapshot(await invoke(endpoints.status, {}, signal));
6842
+ const snapshot = api7.normalizeSnapshot(await invoke(endpoints.status, {}, signal));
6815
6843
  if (!mounted.current || signal?.aborted || !workspaceFence.canCommitStatus(workspaceVersion)) return;
6816
6844
  setModel({
6817
6845
  phase: "ready",
@@ -6827,7 +6855,7 @@ function createTokenChannelSettings(definition) {
6827
6855
  setModel((current) => ({
6828
6856
  ...current,
6829
6857
  phase: silent ? current.phase : "error",
6830
- error: api6.presentError(error)
6858
+ error: api7.presentError(error)
6831
6859
  }));
6832
6860
  }
6833
6861
  }
@@ -6854,7 +6882,7 @@ function createTokenChannelSettings(definition) {
6854
6882
  setBusy(true);
6855
6883
  setCredentialError(null);
6856
6884
  try {
6857
- const snapshot = api6.normalizeSnapshot(await invoke(
6885
+ const snapshot = api7.normalizeSnapshot(await invoke(
6858
6886
  endpoints.bindCredentials,
6859
6887
  credentialPayload(values)
6860
6888
  ));
@@ -6872,7 +6900,7 @@ function createTokenChannelSettings(definition) {
6872
6900
  }
6873
6901
  setCredentialOpen(false);
6874
6902
  } catch (error) {
6875
- if (mounted.current) setCredentialError(api6.presentError(error));
6903
+ if (mounted.current) setCredentialError(api7.presentError(error));
6876
6904
  } finally {
6877
6905
  const shouldRefresh = workspaceFence.endMutation();
6878
6906
  if (shouldRefresh && mounted.current) void loadStatus({ silent: true });
@@ -6884,7 +6912,7 @@ function createTokenChannelSettings(definition) {
6884
6912
  setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
6885
6913
  try {
6886
6914
  const value = await invoke(endpoint, payload);
6887
- const snapshot = api6.normalizeSnapshot(value);
6915
+ const snapshot = api7.normalizeSnapshot(value);
6888
6916
  if (mounted.current && workspaceFence.canCommitMutation(snapshotVersion)) {
6889
6917
  setModel({
6890
6918
  phase: "ready",
@@ -6924,7 +6952,7 @@ function createTokenChannelSettings(definition) {
6924
6952
  { className: "dim-listSection" },
6925
6953
  h2(ChannelListHeading, {
6926
6954
  className: "ddt-listHeading",
6927
- title: `\u5DF2\u63A5\u5165\u7684 ${channel6} \u673A\u5668\u4EBA`,
6955
+ title: `\u5DF2\u63A5\u5165\u7684 ${channel7} \u673A\u5668\u4EBA`,
6928
6956
  connectionLabel
6929
6957
  }),
6930
6958
  h2("ul", { className: "ddt-list dim-botList" }, model.bots.map((account) => h2("li", { key: account.botId }, h2(AccountCard6, {
@@ -6995,7 +7023,7 @@ function createTokenChannelSettings(definition) {
6995
7023
  "section",
6996
7024
  {
6997
7025
  className: `ddt-page ${pageClass} dim-channelPage`,
6998
- "aria-label": `${channel6} \u8BBE\u7F6E`
7026
+ "aria-label": `${channel7} \u8BBE\u7F6E`
6999
7027
  },
7000
7028
  operationError ? h2(ConnectionError, { error: operationError }) : null,
7001
7029
  h2(
@@ -7029,13 +7057,13 @@ function createTokenChannelSettings(definition) {
7029
7057
  model.phase === "loading" ? h2("div", {
7030
7058
  className: "ddt-card ddt-loading dim-surfaceCard dim-loadingView",
7031
7059
  "aria-busy": "true"
7032
- }, h2("div", { className: "ddt-spinner dim-spinner" }), `\u6B63\u5728\u8BFB\u53D6 ${channel6} \u673A\u5668\u4EBA\u72B6\u6001\u2026`) : model.phase === "error" ? h2(
7060
+ }, h2("div", { className: "ddt-spinner dim-spinner" }), `\u6B63\u5728\u8BFB\u53D6 ${channel7} \u673A\u5668\u4EBA\u72B6\u6001\u2026`) : model.phase === "error" ? h2(
7033
7061
  "div",
7034
7062
  { className: "ddt-card dim-surfaceCard" },
7035
7063
  h2(
7036
7064
  "div",
7037
7065
  { className: "ddt-inlineError dim-inlineError" },
7038
- h2("h3", null, `\u65E0\u6CD5\u8BFB\u53D6 ${channel6} \u673A\u5668\u4EBA\u72B6\u6001`),
7066
+ h2("h3", null, `\u65E0\u6CD5\u8BFB\u53D6 ${channel7} \u673A\u5668\u4EBA\u72B6\u6001`),
7039
7067
  h2(ConnectionError, { error: model.error }),
7040
7068
  h2(Button3, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
7041
7069
  )
@@ -7043,7 +7071,7 @@ function createTokenChannelSettings(definition) {
7043
7071
  React15.Fragment,
7044
7072
  null,
7045
7073
  credentialOpen ? CredentialPanel ? h2(CredentialPanel, {
7046
- channel: channel6,
7074
+ channel: channel7,
7047
7075
  permissions: model.permissions,
7048
7076
  busy,
7049
7077
  error: credentialError,
@@ -7058,7 +7086,7 @@ function createTokenChannelSettings(definition) {
7058
7086
  endpoints,
7059
7087
  onAuthorized: bindCredentials
7060
7088
  }) : h2(CredentialBindingPanel, {
7061
- channel: channel6,
7089
+ channel: channel7,
7062
7090
  secretLabel: "Bot Token",
7063
7091
  secretPlaceholder: tokenPlaceholder,
7064
7092
  busy,
@@ -7082,7 +7110,7 @@ function createTokenChannelSettings(definition) {
7082
7110
  "div",
7083
7111
  { className: "ddt-stateLabel dim-stateLabel" },
7084
7112
  h2("span", { className: "ddt-dot dim-stateDot" }),
7085
- h2("span", null, `\u5C1A\u672A\u63A5\u5165 ${channel6} \u673A\u5668\u4EBA`)
7113
+ h2("span", null, `\u5C1A\u672A\u63A5\u5165 ${channel7} \u673A\u5668\u4EBA`)
7086
7114
  ),
7087
7115
  h2("h3", null, emptyTitle),
7088
7116
  h2("p", null, emptyDescription),
@@ -15770,6 +15798,217 @@ function useEmailChannelEnabled(rpcCall) {
15770
15798
  return enabled === true;
15771
15799
  }
15772
15800
 
15801
+ // plugin-src/client/channels/matrix/api.js
15802
+ var MATRIX_RPC_CHANNEL = "/matrix";
15803
+ var MATRIX_ENDPOINTS = TOKEN_BOT_ENDPOINTS;
15804
+ var api6 = createTokenChannelApi("Matrix", " CS API \u957F\u8F6E\u8BE2");
15805
+ var unwrapRpcResult13 = api6.unwrapRpcResult;
15806
+ var normalizeSnapshot12 = api6.normalizeSnapshot;
15807
+ var presentError13 = api6.presentError;
15808
+
15809
+ // plugin-src/client/channels/matrix/index.js
15810
+ var React27 = __toESM(require("react"), 1);
15811
+
15812
+ // plugin-src/client/channels/matrix/styles.js
15813
+ var MATRIX_STYLE_ID = "xmanrui-dsh-im-matrix-settings";
15814
+ var CSS14 = String.raw`
15815
+ .dmt-page { --ddt-accent: #1a8f6f; --ddt-accent-deep: #12654f; --ddt-accent-wash: #eef8f4; }
15816
+ .dmt-avatar { background: linear-gradient(145deg, #fff, #f6faf8); border: 1px solid #e2eae7; }
15817
+ .dmt-avatar svg { display: block; }
15818
+ .dim-logoMatrix { color: white; background: #0dbd8b; }
15819
+ .dim-logoMatrix svg { width: 22px; height: 22px; }
15820
+ .dmt-setup { display: grid; gap: 18px; }
15821
+ .dmt-guide { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start; gap: 18px; padding: 16px; border: 1px solid color-mix(in srgb, #1a8f6f 18%, var(--dsw-alias-border-l2, #e5e6eb)); border-radius: 11px; background: color-mix(in srgb, #1a8f6f 4%, var(--dsw-alias-bg-layer-1, #fff)); }
15822
+ .dmt-guideCopy { min-width: 0; }
15823
+ .dmt-guideCopy strong { display: block; margin-bottom: 5px; color: var(--dsw-alias-label-primary, #1f2329); font-size: 13px; }
15824
+ .dmt-guideCopy p { margin: 0; color: var(--dsw-alias-label-secondary, #646a73); font-size: 12px; line-height: 1.6; }
15825
+ .dmt-guideActions { display: flex; align-items: center; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
15826
+ .dmt-guideActions .ddt-button { white-space: nowrap; }
15827
+ .dmt-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
15828
+ .dmt-fields .dmt-fieldWide { grid-column: 1 / -1; }
15829
+ .dmt-tokenHint { grid-column: 1 / -1; margin: -4px 0 0; color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 11px; line-height: 1.55; }
15830
+ @container (max-width: 680px) {
15831
+ .dmt-guide { grid-template-columns: minmax(0, 1fr); }
15832
+ .dmt-guideActions { justify-content: flex-start; }
15833
+ .dmt-fields { grid-template-columns: minmax(0, 1fr); }
15834
+ }
15835
+ `;
15836
+ function installMatrixStyles() {
15837
+ if (typeof document === "undefined") return () => {
15838
+ };
15839
+ const existing = document.querySelector(`style[data-plugin-css="${MATRIX_STYLE_ID}"]`);
15840
+ if (existing) return () => {
15841
+ };
15842
+ const style = document.createElement("style");
15843
+ style.dataset.plugin = "@xmanrui/dsh-im";
15844
+ style.dataset.pluginCss = MATRIX_STYLE_ID;
15845
+ style.textContent = CSS14;
15846
+ document.head.appendChild(style);
15847
+ return () => style.remove();
15848
+ }
15849
+
15850
+ // plugin-src/client/channels/matrix/index.js
15851
+ var MATRIX_USER_ID_PATTERN = /^@[^:@\s]+:[^:@\s]+(?::\d{1,5})?$/u;
15852
+ function validHomeserver(value) {
15853
+ if (!value || value.length > 2048) return false;
15854
+ try {
15855
+ const url = new URL(value);
15856
+ return (url.protocol === "https:" || url.protocol === "http:") && !url.username && !url.password && !url.hash;
15857
+ } catch {
15858
+ return false;
15859
+ }
15860
+ }
15861
+ function MatrixCredentialPanel({ busy, error, onSubmit, onCancel }) {
15862
+ const [homeserver, setHomeserver] = React27.useState("");
15863
+ const [accessToken, setAccessToken] = React27.useState("");
15864
+ const [userId, setUserId] = React27.useState("");
15865
+ const [password, setPassword] = React27.useState("");
15866
+ const headingId = React27.useId();
15867
+ const normalizedHomeserver = homeserver.trim();
15868
+ const normalizedUserId = userId.trim();
15869
+ const tokenMode = Boolean(accessToken.trim());
15870
+ const loginMode = Boolean(normalizedUserId) && Boolean(password);
15871
+ const canSubmit = validHomeserver(normalizedHomeserver) && (tokenMode ? !normalizedUserId && !password && accessToken.trim().length >= 8 : !accessToken.trim() && MATRIX_USER_ID_PATTERN.test(normalizedUserId) && password.length >= 1);
15872
+ const submit = (event) => {
15873
+ event.preventDefault();
15874
+ if (!canSubmit || busy) return;
15875
+ void onSubmit?.(tokenMode ? { homeserver: normalizedHomeserver, accessToken: accessToken.trim() } : {
15876
+ homeserver: normalizedHomeserver,
15877
+ userId: normalizedUserId,
15878
+ password
15879
+ });
15880
+ };
15881
+ return h2(
15882
+ "section",
15883
+ {
15884
+ className: "ddt-card dim-surfaceCard dim-credentialPanel dmt-setup",
15885
+ "aria-labelledby": headingId
15886
+ },
15887
+ h2("h3", { id: headingId, className: "dim-credentialTitle" }, "\u63A5\u5165 Matrix \u673A\u5668\u4EBA"),
15888
+ h2(
15889
+ "div",
15890
+ { className: "dmt-guide" },
15891
+ h2(
15892
+ "div",
15893
+ { className: "dmt-guideCopy" },
15894
+ h2("strong", null, "\u8FDE\u63A5\u4F60\u7684 Matrix homeserver"),
15895
+ h2("p", null, "\u586B\u5199 homeserver \u5730\u5740\uFF0C\u5E76\u63D0\u4F9B\u8BBF\u95EE\u4EE4\u724C\uFF0C\u6216\u8005\u7528\u6237 ID \u4E0E\u5BC6\u7801\u7684\u7EC4\u5408\u3002\u673A\u5668\u4EBA\u53EA\u8BBF\u95EE\u8BE5 homeserver\uFF0C\u4E0D\u8FDE\u63A5\u7B2C\u4E09\u65B9\u670D\u52A1\u5668\u3002")
15896
+ )
15897
+ ),
15898
+ h2(
15899
+ "form",
15900
+ { className: "dim-credentialForm dim-credentialFormSingle", onSubmit: submit },
15901
+ h2(
15902
+ "div",
15903
+ { className: "dmt-fields" },
15904
+ h2(
15905
+ "label",
15906
+ { className: "dim-credentialField dmt-fieldWide" },
15907
+ h2("span", null, "Homeserver \u5730\u5740"),
15908
+ h2("input", {
15909
+ type: "url",
15910
+ value: homeserver,
15911
+ onChange: (event) => setHomeserver(event.target.value),
15912
+ placeholder: "https://matrix.example.org",
15913
+ maxLength: 2048,
15914
+ autoCapitalize: "none",
15915
+ autoCorrect: "off",
15916
+ spellCheck: false,
15917
+ disabled: busy,
15918
+ required: true
15919
+ })
15920
+ ),
15921
+ h2(
15922
+ "label",
15923
+ { className: "dim-credentialField dmt-fieldWide" },
15924
+ h2("span", null, "\u8BBF\u95EE\u4EE4\u724C\uFF08\u4E0E\u7528\u6237 ID\u3001\u5BC6\u7801\u4E8C\u9009\u4E00\uFF09"),
15925
+ h2("input", {
15926
+ type: "password",
15927
+ value: accessToken,
15928
+ onChange: (event) => setAccessToken(event.target.value),
15929
+ placeholder: "syt_\u2026",
15930
+ maxLength: 4096,
15931
+ autoCapitalize: "none",
15932
+ autoCorrect: "off",
15933
+ spellCheck: false,
15934
+ autoComplete: "new-password",
15935
+ disabled: busy
15936
+ })
15937
+ ),
15938
+ h2(
15939
+ "label",
15940
+ { className: "dim-credentialField" },
15941
+ h2("span", null, "\u7528\u6237 ID\uFF08\u53EF\u9009\uFF09"),
15942
+ h2("input", {
15943
+ type: "text",
15944
+ value: userId,
15945
+ onChange: (event) => setUserId(event.target.value),
15946
+ placeholder: "@bot:example.org",
15947
+ maxLength: 512,
15948
+ autoCapitalize: "none",
15949
+ autoCorrect: "off",
15950
+ spellCheck: false,
15951
+ disabled: busy
15952
+ })
15953
+ ),
15954
+ h2(
15955
+ "label",
15956
+ { className: "dim-credentialField" },
15957
+ h2("span", null, "\u5BC6\u7801\uFF08\u53EF\u9009\uFF09"),
15958
+ h2("input", {
15959
+ type: "password",
15960
+ value: password,
15961
+ onChange: (event) => setPassword(event.target.value),
15962
+ maxLength: 1024,
15963
+ autoComplete: "new-password",
15964
+ disabled: busy
15965
+ })
15966
+ ),
15967
+ h2("p", { className: "dmt-tokenHint" }, "\u8BBF\u95EE\u4EE4\u724C\u6765\u81EA Element \u8BBE\u7F6E \u2192 \u5E2E\u52A9 \u2192 \u7F16\u8F91\u8BBE\u7F6E\uFF0C\u6216 homeserver \u7684\u767B\u5F55\u63A5\u53E3\uFF1B\u7528\u6237 ID \u4E0E\u5BC6\u7801\u65B9\u5F0F\u4F1A\u4E3A\u672C\u5B89\u88C5\u6D3E\u751F\u7A33\u5B9A\u8BBE\u5907\u4F1A\u8BDD\u3002")
15968
+ ),
15969
+ error ? h2("p", { className: "dim-credentialError", role: "alert" }, error.message ?? String(error)) : null,
15970
+ h2(
15971
+ "div",
15972
+ { className: "ddt-actions dim-viewActions dim-credentialActions" },
15973
+ h2("button", {
15974
+ type: "submit",
15975
+ className: "ddt-button",
15976
+ "data-kind": "primary",
15977
+ disabled: busy || !canSubmit
15978
+ }, busy ? "\u6B63\u5728\u9A8C\u8BC1\u5E76\u8FDE\u63A5\u2026" : "\u9A8C\u8BC1\u5E76\u8FDE\u63A5"),
15979
+ h2("button", {
15980
+ type: "button",
15981
+ className: "ddt-button",
15982
+ onClick: onCancel,
15983
+ disabled: busy
15984
+ }, "\u53D6\u6D88")
15985
+ )
15986
+ )
15987
+ );
15988
+ }
15989
+ var channel6 = createTokenChannelSettings({
15990
+ channel: "Matrix",
15991
+ endpoints: MATRIX_ENDPOINTS,
15992
+ api: api6,
15993
+ LogoGlyph: MatrixLogoGlyph,
15994
+ installStyles: installMatrixStyles,
15995
+ pageClass: "dmt-page",
15996
+ avatarClass: "dmt-avatar",
15997
+ connectionLabel: "CS API \u957F\u8F6E\u8BE2",
15998
+ emptyTitle: "\u63A5\u5165 Matrix \u673A\u5668\u4EBA",
15999
+ emptyDescription: "\u586B\u5199 homeserver \u5730\u5740\u4E0E\u8BBF\u95EE\u4EE4\u724C\uFF0C\u6216\u8005\u7528\u6237 ID \u4E0E\u5BC6\u7801\uFF0C\u5373\u53EF\u8BA9\u673A\u5668\u4EBA\u4EE5 CS API \u957F\u8F6E\u8BE2\u63A5\u6536\u6D88\u606F\u5E76\u4EE5\u5BCC\u6587\u672C\u56DE\u590D\u3002",
16000
+ platformLabel: "Matrix homeserver",
16001
+ CredentialPanel: MatrixCredentialPanel,
16002
+ credentialPayload: ({ homeserver, accessToken, userId, password }) => ({ homeserver, accessToken, userId, password }),
16003
+ credentialAriaLabel: "\u4F7F\u7528 homeserver \u4E0E\u51ED\u636E\u63A5\u5165 Matrix \u673A\u5668\u4EBA",
16004
+ credentialOpenLabel: "\u63A5\u5165\u673A\u5668\u4EBA",
16005
+ credentialCloseLabel: "\u6536\u8D77\u63A5\u5165",
16006
+ credentialNoun: "\u8BBF\u95EE\u4EE4\u724C\u6216\u7528\u6237 ID \u4E0E\u5BC6\u7801",
16007
+ emptyActionLabel: "\u5F00\u59CB\u63A5\u5165"
16008
+ });
16009
+ var MatrixSettingsTab = channel6.SettingsTab;
16010
+ var MatrixAccountCard = channel6.AccountCard;
16011
+
15773
16012
  // src/channels/shared/interface-language.mjs
15774
16013
  var LANGUAGE_TAG = /^[A-Za-z]{2,8}(?:-[A-Za-z0-9]{1,8})*$/u;
15775
16014
  var HOST_LANGUAGE_SOURCES = Object.freeze(["config", "settings", "mirror"]);
@@ -15833,10 +16072,10 @@ function installInterfaceLanguageMirror(ctx, {
15833
16072
  }
15834
16073
 
15835
16074
  // plugin-src/client/delivery-settings.js
15836
- var React29 = __toESM(require("react"), 1);
16075
+ var React30 = __toESM(require("react"), 1);
15837
16076
 
15838
16077
  // plugin-src/client/access-policy-settings.js
15839
- var React27 = __toESM(require("react"), 1);
16078
+ var React28 = __toESM(require("react"), 1);
15840
16079
  var ACCESS_POLICY_ENDPOINT = "bot.access-policy.set";
15841
16080
  var ACCESS_CHANNEL_DEFINITIONS = Object.freeze({
15842
16081
  weixin: Object.freeze({
@@ -15922,7 +16161,7 @@ function clonePolicy(policy) {
15922
16161
  group: cloneScope(policy.group)
15923
16162
  };
15924
16163
  }
15925
- function unwrapRpcResult13(result) {
16164
+ function unwrapRpcResult14(result) {
15926
16165
  if (result?.ok === true) return result.value;
15927
16166
  if (result?.ok === false) {
15928
16167
  const error = new Error(result.error?.message || "\u8BBF\u95EE\u8BBE\u7F6E\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
@@ -15949,8 +16188,8 @@ function ScenePolicyEditor({
15949
16188
  unsupported = false,
15950
16189
  onChange
15951
16190
  }) {
15952
- const ownerHelpId = React27.useId();
15953
- const emptyAllowlistHelpId = React27.useId();
16191
+ const ownerHelpId = React28.useId();
16192
+ const emptyAllowlistHelpId = React28.useId();
15954
16193
  const allowlist = policy.mode === "allowlist";
15955
16194
  const collectionKey = allowlist ? "users" : "commandPermissionOverrides";
15956
16195
  const branchKey = allowlist ? "allowlist" : "open";
@@ -16002,7 +16241,7 @@ function ScenePolicyEditor({
16002
16241
  h2("strong", null, "\u5F53\u524D\u6E20\u9053\u4E0D\u652F\u6301\u7FA4\u804A"),
16003
16242
  h2("p", null, "\u6B64\u533A\u57DF\u65E0\u9700\u914D\u7F6E\uFF0C\u4FDD\u5B58\u79C1\u804A\u8BBE\u7F6E\u65F6\u4F1A\u4FDD\u7559\u73B0\u6709\u7FA4\u804A\u7B56\u7565\u3002")
16004
16243
  ) : h2(
16005
- React27.Fragment,
16244
+ React28.Fragment,
16006
16245
  null,
16007
16246
  h2(
16008
16247
  "div",
@@ -16139,20 +16378,20 @@ function ScenePolicyEditor({
16139
16378
  )
16140
16379
  );
16141
16380
  }
16142
- function AccessPolicySettingsPage({ channel: channel6, account, rpcCall, onSaved }) {
16143
- const definition = ACCESS_CHANNEL_DEFINITIONS[channel6];
16381
+ function AccessPolicySettingsPage({ channel: channel7, account, rpcCall, onSaved }) {
16382
+ const definition = ACCESS_CHANNEL_DEFINITIONS[channel7];
16144
16383
  const initialPolicy = normalizeAccessPolicy(account?.accessPolicy);
16145
16384
  const initialKey = JSON.stringify(initialPolicy);
16146
- const [draft, setDraft] = React27.useState(() => clonePolicy(
16385
+ const [draft, setDraft] = React28.useState(() => clonePolicy(
16147
16386
  initialPolicy ?? DEFAULT_ACCESS_POLICY
16148
16387
  ));
16149
- const [saving, setSaving] = React27.useState(false);
16150
- const [feedback, setFeedback] = React27.useState(null);
16151
- React27.useEffect(() => {
16388
+ const [saving, setSaving] = React28.useState(false);
16389
+ const [feedback, setFeedback] = React28.useState(null);
16390
+ React28.useEffect(() => {
16152
16391
  const next = normalizeAccessPolicy(account?.accessPolicy);
16153
16392
  setDraft(clonePolicy(next ?? DEFAULT_ACCESS_POLICY));
16154
16393
  }, [account?.botId, initialKey]);
16155
- React27.useEffect(() => {
16394
+ React28.useEffect(() => {
16156
16395
  setFeedback(null);
16157
16396
  }, [account?.botId]);
16158
16397
  if (!definition) {
@@ -16169,7 +16408,7 @@ function AccessPolicySettingsPage({ channel: channel6, account, rpcCall, onSaved
16169
16408
  try {
16170
16409
  const policy = validateAccessPolicy(draft);
16171
16410
  if (typeof rpcCall !== "function") throw new Error("\u8BBF\u95EE\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
16172
- const value = unwrapRpcResult13(await rpcCall(ACCESS_POLICY_ENDPOINT, {
16411
+ const value = unwrapRpcResult14(await rpcCall(ACCESS_POLICY_ENDPOINT, {
16173
16412
  botId: account.botId,
16174
16413
  policy
16175
16414
  }));
@@ -16243,7 +16482,7 @@ function AccessPolicySettingsPage({ channel: channel6, account, rpcCall, onSaved
16243
16482
  }
16244
16483
 
16245
16484
  // plugin-src/client/channels/feishu/group-settings.js
16246
- var React28 = __toESM(require("react"), 1);
16485
+ var React29 = __toESM(require("react"), 1);
16247
16486
  var GROUP_MESSAGE_PERMISSION_OPERATION2 = FEISHU_REGISTRATION_OPERATIONS.GROUP_MESSAGE_PERMISSION;
16248
16487
  function SettingsButton({ children, kind = "secondary", className = "", ...props }) {
16249
16488
  return h2("button", {
@@ -16304,9 +16543,9 @@ function GroupResponseModeEditor({
16304
16543
  onAuthorize
16305
16544
  }) {
16306
16545
  const current = normalizeGroupResponseMode(value);
16307
- const [saving, setSaving] = React28.useState(false);
16308
- const [authorizing, setAuthorizing] = React28.useState(false);
16309
- const [error, setError] = React28.useState(null);
16546
+ const [saving, setSaving] = React29.useState(false);
16547
+ const [authorizing, setAuthorizing] = React29.useState(false);
16548
+ const [error, setError] = React29.useState(null);
16310
16549
  const change = async (event) => {
16311
16550
  const next = normalizeGroupResponseMode(event.target.value);
16312
16551
  if (next === current || saving || disabled) return;
@@ -16387,8 +16626,8 @@ function GroupResponseModeEditor({
16387
16626
  }
16388
16627
  function GroupTopicReplyEditor({ value = false, disabled = false, onSave }) {
16389
16628
  const current = value === true ? "on" : "off";
16390
- const [saving, setSaving] = React28.useState(false);
16391
- const [error, setError] = React28.useState(null);
16629
+ const [saving, setSaving] = React29.useState(false);
16630
+ const [error, setError] = React29.useState(null);
16392
16631
  const change = async (event) => {
16393
16632
  const next = event.target.value === "on";
16394
16633
  if ((next ? "on" : "off") === current || saving || disabled) return;
@@ -16575,14 +16814,14 @@ function PermissionFlow({ provision, now, busy, botName, onRetry, onCancel, onCl
16575
16814
  );
16576
16815
  }
16577
16816
  function FeishuGroupSettingsPage({ account, rpcCall }) {
16578
- const [settings, setSettings] = React28.useState(() => groupSettingsFrom(account));
16579
- const [refreshing, setRefreshing] = React28.useState(false);
16580
- const [refreshError, setRefreshError] = React28.useState(null);
16581
- const [provision, setProvision] = React28.useState(null);
16582
- const [provisionBusy, setProvisionBusy] = React28.useState(false);
16583
- const [now, setNow] = React28.useState(() => Date.now());
16584
- const mounted = React28.useRef(true);
16585
- React28.useEffect(() => {
16817
+ const [settings, setSettings] = React29.useState(() => groupSettingsFrom(account));
16818
+ const [refreshing, setRefreshing] = React29.useState(false);
16819
+ const [refreshError, setRefreshError] = React29.useState(null);
16820
+ const [provision, setProvision] = React29.useState(null);
16821
+ const [provisionBusy, setProvisionBusy] = React29.useState(false);
16822
+ const [now, setNow] = React29.useState(() => Date.now());
16823
+ const mounted = React29.useRef(true);
16824
+ React29.useEffect(() => {
16586
16825
  setSettings(groupSettingsFrom(account));
16587
16826
  }, [
16588
16827
  account.botId,
@@ -16590,22 +16829,22 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
16590
16829
  account.groupTopicReply,
16591
16830
  account.groupMessagePermissionGranted
16592
16831
  ]);
16593
- React28.useEffect(() => {
16832
+ React29.useEffect(() => {
16594
16833
  mounted.current = true;
16595
16834
  return () => {
16596
16835
  mounted.current = false;
16597
16836
  };
16598
16837
  }, []);
16599
- const invoke = React28.useCallback(async (endpoint, payload = {}, signal) => {
16838
+ const invoke = React29.useCallback(async (endpoint, payload = {}, signal) => {
16600
16839
  if (typeof rpcCall !== "function") throw new Error("\u98DE\u4E66\u7FA4\u804A\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
16601
16840
  return unwrapRpcResult3(await rpcCall(endpoint, payload, signal));
16602
16841
  }, [rpcCall]);
16603
- const applySnapshot = React28.useCallback((value) => {
16842
+ const applySnapshot = React29.useCallback((value) => {
16604
16843
  const result = targetBotFromSnapshot(value, account.botId);
16605
16844
  if (mounted.current) setSettings(groupSettingsFrom(result.bot));
16606
16845
  return result;
16607
16846
  }, [account.botId]);
16608
- const loadSettings = React28.useCallback(async ({ signal, restoreProvisioning = false } = {}) => {
16847
+ const loadSettings = React29.useCallback(async ({ signal, restoreProvisioning = false } = {}) => {
16609
16848
  setRefreshing(true);
16610
16849
  setRefreshError(null);
16611
16850
  try {
@@ -16634,16 +16873,16 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
16634
16873
  if (!signal?.aborted && mounted.current) setRefreshing(false);
16635
16874
  }
16636
16875
  }, [account.botId, applySnapshot, invoke]);
16637
- React28.useEffect(() => {
16876
+ React29.useEffect(() => {
16638
16877
  const controller = new AbortController();
16639
16878
  void loadSettings({ signal: controller.signal, restoreProvisioning: true });
16640
16879
  return () => controller.abort();
16641
16880
  }, [loadSettings]);
16642
- const saveSetting = React28.useCallback(async (endpoint, payload) => {
16881
+ const saveSetting = React29.useCallback(async (endpoint, payload) => {
16643
16882
  const value = await invoke(endpoint, { botId: account.botId, ...payload });
16644
16883
  applySnapshot(value);
16645
16884
  }, [account.botId, applySnapshot, invoke]);
16646
- const startAuthorization = React28.useCallback(async ({ replace = false } = {}) => {
16885
+ const startAuthorization = React29.useCallback(async ({ replace = false } = {}) => {
16647
16886
  if (provisionBusy) return;
16648
16887
  const previousAttemptId = provision?.attemptId;
16649
16888
  setProvisionBusy(true);
@@ -16684,13 +16923,13 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
16684
16923
  if (mounted.current) setProvisionBusy(false);
16685
16924
  }
16686
16925
  }, [account.botId, invoke, provision?.attemptId, provisionBusy]);
16687
- const finishAuthorization = React28.useCallback(async (signal) => {
16926
+ const finishAuthorization = React29.useCallback(async (signal) => {
16688
16927
  const bot = await loadSettings({ signal, restoreProvisioning: false });
16689
16928
  if (signal?.aborted || !mounted.current) return;
16690
16929
  if (!bot) throw new Error("\u7FA4\u6D88\u606F\u6743\u9650\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001");
16691
16930
  setProvision(null);
16692
16931
  }, [loadSettings]);
16693
- React28.useEffect(() => {
16932
+ React29.useEffect(() => {
16694
16933
  if (!provision?.attemptId || !["qr", "connecting"].includes(provision.phase) || provision.expired) return void 0;
16695
16934
  const timerHost = globalThis.window ?? globalThis;
16696
16935
  const controller = new AbortController();
@@ -16734,7 +16973,7 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
16734
16973
  timerHost.clearTimeout(timer);
16735
16974
  };
16736
16975
  }, [account.botId, finishAuthorization, invoke, provision]);
16737
- React28.useEffect(() => {
16976
+ React29.useEffect(() => {
16738
16977
  if (!provision?.attemptId || provision.phase !== "qr" || provision.expired) return void 0;
16739
16978
  const timerHost = globalThis.window ?? globalThis;
16740
16979
  const tick = () => {
@@ -16748,7 +16987,7 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
16748
16987
  const timer = timerHost.setInterval(tick, 1e3);
16749
16988
  return () => timerHost.clearInterval(timer);
16750
16989
  }, [provision?.attemptId, provision?.expired, provision?.expiresAt, provision?.phase]);
16751
- const cancelAuthorization = React28.useCallback(async () => {
16990
+ const cancelAuthorization = React29.useCallback(async () => {
16752
16991
  if (!provision?.attemptId || provisionBusy) {
16753
16992
  setProvision(null);
16754
16993
  return;
@@ -16859,8 +17098,8 @@ var FEISHU_BOT_SETTINGS_TABS = Object.freeze([
16859
17098
  ...BOT_SETTINGS_TABS,
16860
17099
  Object.freeze({ id: "group", label: "\u7FA4\u804A" })
16861
17100
  ]);
16862
- function botSettingsTabsForChannel(channel6) {
16863
- return channel6 === "feishu" ? FEISHU_BOT_SETTINGS_TABS : BOT_SETTINGS_TABS;
17101
+ function botSettingsTabsForChannel(channel7) {
17102
+ return channel7 === "feishu" ? FEISHU_BOT_SETTINGS_TABS : BOT_SETTINGS_TABS;
16864
17103
  }
16865
17104
  var CHANNEL_DEFINITIONS = Object.freeze({
16866
17105
  weixin: {
@@ -16948,10 +17187,10 @@ var CHANNEL_DEFINITIONS = Object.freeze({
16948
17187
  fields: { user: [{ key: "chatGuid", label: "Chat GUID", placeholder: "iMessage;+;chat123" }] }
16949
17188
  }
16950
17189
  });
16951
- function presentError13(error, fallback) {
17190
+ function presentError14(error, fallback) {
16952
17191
  return error?.message || fallback;
16953
17192
  }
16954
- function unwrapRpcResult14(result) {
17193
+ function unwrapRpcResult15(result) {
16955
17194
  if (result?.ok === true) return result.value;
16956
17195
  if (result?.ok === false) {
16957
17196
  const error = new Error(result.error?.message || "\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
@@ -17069,13 +17308,13 @@ function TargetForm({
17069
17308
  }) {
17070
17309
  const editing = mode === "edit";
17071
17310
  const initialKind = initialValue?.kind && definition.fields[initialValue.kind] ? initialValue.kind : definition.kinds[0].value;
17072
- const [targetId, setTargetId] = React29.useState(initialValue?.targetId ?? "");
17073
- const [name2, setName] = React29.useState(initialValue?.name ?? "");
17074
- const [kind, setKind] = React29.useState(initialKind);
17075
- const [route, setRoute] = React29.useState(initialValue?.route ?? {});
17076
- const [error, setError] = React29.useState(null);
17077
- const [testing, setTesting] = React29.useState(false);
17078
- const [testState, setTestState] = React29.useState(null);
17311
+ const [targetId, setTargetId] = React30.useState(initialValue?.targetId ?? "");
17312
+ const [name2, setName] = React30.useState(initialValue?.name ?? "");
17313
+ const [kind, setKind] = React30.useState(initialKind);
17314
+ const [route, setRoute] = React30.useState(initialValue?.route ?? {});
17315
+ const [error, setError] = React30.useState(null);
17316
+ const [testing, setTesting] = React30.useState(false);
17317
+ const [testState, setTestState] = React30.useState(null);
17079
17318
  const currentTarget = () => {
17080
17319
  const normalizedRoute = Object.fromEntries(fieldsFor(definition, kind).map((field2) => {
17081
17320
  const raw = String(route[field2.key] ?? "").trim();
@@ -17096,7 +17335,7 @@ function TargetForm({
17096
17335
  ...currentTarget()
17097
17336
  });
17098
17337
  } catch (caught) {
17099
- setError(presentError13(caught, "\u76EE\u6807\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u540E\u91CD\u8BD5\u3002"));
17338
+ setError(presentError14(caught, "\u76EE\u6807\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u540E\u91CD\u8BD5\u3002"));
17100
17339
  }
17101
17340
  };
17102
17341
  const testTarget = async () => {
@@ -17108,7 +17347,7 @@ function TargetForm({
17108
17347
  await onTest({ kind: target.kind, route: target.route });
17109
17348
  setTestState({ tone: "success", message: "\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u8BF7\u5230\u76EE\u6807\u4F1A\u8BDD\u786E\u8BA4\u3002" });
17110
17349
  } catch (caught) {
17111
- setTestState({ tone: "error", message: presentError13(caught, "\u6D4B\u8BD5\u53D1\u9001\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002") });
17350
+ setTestState({ tone: "error", message: presentError14(caught, "\u6D4B\u8BD5\u53D1\u9001\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002") });
17112
17351
  } finally {
17113
17352
  setTesting(false);
17114
17353
  }
@@ -17292,7 +17531,7 @@ function TargetSuggestionPicker({
17292
17531
  suggestions.map((suggestion, index) => {
17293
17532
  const identity = routeIdentity(definition, suggestion);
17294
17533
  const added = configured.has(identity);
17295
- return React29.createElement("option", {
17534
+ return React30.createElement("option", {
17296
17535
  key: suggestion.id ?? suggestion.suggestionId ?? `${identity}:${index}`,
17297
17536
  value: String(index),
17298
17537
  disabled: added
@@ -17309,11 +17548,11 @@ function TargetSuggestionPicker({
17309
17548
  );
17310
17549
  }
17311
17550
  function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, onEdit }) {
17312
- const [action, setAction] = React29.useState(null);
17313
- const [testState, setTestState] = React29.useState(null);
17314
- const [syncFeedback, setSyncFeedback] = React29.useState(null);
17315
- const [copyState, setCopyState] = React29.useState(null);
17316
- const [confirmDelete, setConfirmDelete] = React29.useState(false);
17551
+ const [action, setAction] = React30.useState(null);
17552
+ const [testState, setTestState] = React30.useState(null);
17553
+ const [syncFeedback, setSyncFeedback] = React30.useState(null);
17554
+ const [copyState, setCopyState] = React30.useState(null);
17555
+ const [confirmDelete, setConfirmDelete] = React30.useState(false);
17317
17556
  const sessionSync = target.sessionSync ?? { enabled: false, state: "unavailable" };
17318
17557
  const syncDescription = sessionSync.state === "active" ? "\u81EA\u52A8\u8DDF\u968F\u8BE5\u79C1\u804A\u7684\u5F53\u524D\u4F1A\u8BDD" : sessionSync.state === "waiting" ? "\u7B49\u5F85\u8BE5\u79C1\u804A\u5EFA\u7ACB\u65B0\u4F1A\u8BDD" : sessionSync.state === "unavailable" ? "\u4EC5\u652F\u6301\u5DF2\u7ECF\u804A\u8FC7\u3001\u5DF2\u5EFA\u7ACB\u5F53\u524D\u4F1A\u8BDD\u4E14\u4F7F\u7528\u5F53\u524D Host Harness \u7684\u79C1\u804A\u76EE\u6807" : "\u5173\u95ED\u65F6\u4E0D\u53D1\u9001 DSH \u4F1A\u8BDD\u6D88\u606F";
17319
17558
  const testTarget = async () => {
@@ -17323,7 +17562,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
17323
17562
  await rpcCall(DELIVERY_ENDPOINTS.test, { botId, targetId: target.targetId });
17324
17563
  setTestState({ tone: "success", message: "\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u8BF7\u5230\u76EE\u6807\u4F1A\u8BDD\u786E\u8BA4\u3002" });
17325
17564
  } catch (error) {
17326
- setTestState({ tone: "error", message: presentError13(error, "\u6D4B\u8BD5\u53D1\u9001\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002") });
17565
+ setTestState({ tone: "error", message: presentError14(error, "\u6D4B\u8BD5\u53D1\u9001\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002") });
17327
17566
  } finally {
17328
17567
  setAction(null);
17329
17568
  }
@@ -17334,7 +17573,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
17334
17573
  await copyText(JSON.stringify({ botId, targetId: target.targetId }));
17335
17574
  setCopyState("\u5DF2\u590D\u5236\u8C03\u7528\u53C2\u6570");
17336
17575
  } catch (error) {
17337
- setCopyState(presentError13(error, "\u590D\u5236\u5931\u8D25\u3002"));
17576
+ setCopyState(presentError14(error, "\u590D\u5236\u5931\u8D25\u3002"));
17338
17577
  }
17339
17578
  };
17340
17579
  const deleteTarget = async () => {
@@ -17343,7 +17582,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
17343
17582
  await rpcCall(DELIVERY_ENDPOINTS.delete, { botId, targetId: target.targetId });
17344
17583
  await onChanged();
17345
17584
  } catch (error) {
17346
- setTestState({ tone: "error", message: presentError13(error, "\u5220\u9664\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002") });
17585
+ setTestState({ tone: "error", message: presentError14(error, "\u5220\u9664\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002") });
17347
17586
  setAction(null);
17348
17587
  setConfirmDelete(false);
17349
17588
  }
@@ -17361,7 +17600,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
17361
17600
  } catch (error) {
17362
17601
  setSyncFeedback({
17363
17602
  tone: "error",
17364
- message: error?.code === "session-sync-unavailable" ? "\u4F1A\u8BDD\u540C\u6B65\u4EC5\u652F\u6301\u5DF2\u7ECF\u804A\u8FC7\u3001\u5DF2\u5EFA\u7ACB\u5F53\u524D\u4F1A\u8BDD\u4E14\u4F7F\u7528\u5F53\u524D Host Harness \u7684\u79C1\u804A\u76EE\u6807\u3002" : presentError13(error, "\u4F1A\u8BDD\u540C\u6B65\u8BBE\u7F6E\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")
17603
+ message: error?.code === "session-sync-unavailable" ? "\u4F1A\u8BDD\u540C\u6B65\u4EC5\u652F\u6301\u5DF2\u7ECF\u804A\u8FC7\u3001\u5DF2\u5EFA\u7ACB\u5F53\u524D\u4F1A\u8BDD\u4E14\u4F7F\u7528\u5F53\u524D Host Harness \u7684\u79C1\u804A\u76EE\u6807\u3002" : presentError14(error, "\u4F1A\u8BDD\u540C\u6B65\u8BBE\u7F6E\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")
17365
17604
  });
17366
17605
  } finally {
17367
17606
  setAction(null);
@@ -17376,7 +17615,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
17376
17615
  h2(
17377
17616
  "div",
17378
17617
  { className: "dim-targetTitle" },
17379
- React29.createElement("strong", null, target.name || target.targetId),
17618
+ React30.createElement("strong", null, target.name || target.targetId),
17380
17619
  h2("span", null, kindLabel(definition, target.kind))
17381
17620
  ),
17382
17621
  h2("code", null, `targetId: ${target.targetId}`)
@@ -17455,33 +17694,33 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
17455
17694
  );
17456
17695
  }
17457
17696
  function DeliveryTargetSettingsPage({
17458
- channel: channel6,
17697
+ channel: channel7,
17459
17698
  account,
17460
17699
  rpcCall,
17461
17700
  accessRpcCall,
17462
17701
  onBack
17463
17702
  }) {
17464
- const definition = CHANNEL_DEFINITIONS[channel6];
17465
- const [activeTabId, setActiveTabId] = React29.useState(BOT_SETTINGS_TABS[0].id);
17466
- const [phase, setPhase] = React29.useState("loading");
17467
- const [targets, setTargets] = React29.useState([]);
17468
- const [suggestionPhase, setSuggestionPhase] = React29.useState("idle");
17469
- const [suggestions, setSuggestions] = React29.useState([]);
17470
- const [suggestionError, setSuggestionError] = React29.useState(null);
17471
- const [error, setError] = React29.useState(null);
17472
- const [editor, setEditor] = React29.useState(null);
17473
- const [saving, setSaving] = React29.useState(false);
17474
- const [botCopyState, setBotCopyState] = React29.useState(null);
17475
- const [accessPolicy, setAccessPolicy] = React29.useState(account.accessPolicy);
17476
- const mounted = React29.useRef(true);
17477
- React29.useEffect(() => {
17703
+ const definition = CHANNEL_DEFINITIONS[channel7];
17704
+ const [activeTabId, setActiveTabId] = React30.useState(BOT_SETTINGS_TABS[0].id);
17705
+ const [phase, setPhase] = React30.useState("loading");
17706
+ const [targets, setTargets] = React30.useState([]);
17707
+ const [suggestionPhase, setSuggestionPhase] = React30.useState("idle");
17708
+ const [suggestions, setSuggestions] = React30.useState([]);
17709
+ const [suggestionError, setSuggestionError] = React30.useState(null);
17710
+ const [error, setError] = React30.useState(null);
17711
+ const [editor, setEditor] = React30.useState(null);
17712
+ const [saving, setSaving] = React30.useState(false);
17713
+ const [botCopyState, setBotCopyState] = React30.useState(null);
17714
+ const [accessPolicy, setAccessPolicy] = React30.useState(account.accessPolicy);
17715
+ const mounted = React30.useRef(true);
17716
+ React30.useEffect(() => {
17478
17717
  setAccessPolicy(account.accessPolicy);
17479
17718
  }, [account.botId, account.accessPolicy]);
17480
- const invoke = React29.useCallback(async (endpoint, payload = {}, signal) => {
17719
+ const invoke = React30.useCallback(async (endpoint, payload = {}, signal) => {
17481
17720
  if (typeof rpcCall !== "function") throw new Error("\u6295\u9012\u76EE\u6807\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
17482
- return unwrapRpcResult14(await rpcCall(endpoint, payload, signal));
17721
+ return unwrapRpcResult15(await rpcCall(endpoint, payload, signal));
17483
17722
  }, [rpcCall]);
17484
- const loadTargets = React29.useCallback(async ({ signal, silent = false } = {}) => {
17723
+ const loadTargets = React30.useCallback(async ({ signal, silent = false } = {}) => {
17485
17724
  if (!silent) setPhase("loading");
17486
17725
  setError(null);
17487
17726
  try {
@@ -17491,11 +17730,11 @@ function DeliveryTargetSettingsPage({
17491
17730
  setPhase("ready");
17492
17731
  } catch (caught) {
17493
17732
  if (signal?.aborted || caught?.name === "AbortError" || !mounted.current) return;
17494
- setError(presentError13(caught, "\u65E0\u6CD5\u8BFB\u53D6\u6295\u9012\u76EE\u6807\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
17733
+ setError(presentError14(caught, "\u65E0\u6CD5\u8BFB\u53D6\u6295\u9012\u76EE\u6807\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
17495
17734
  setPhase("error");
17496
17735
  }
17497
17736
  }, [account.botId, invoke]);
17498
- const loadSuggestions = React29.useCallback(async () => {
17737
+ const loadSuggestions = React30.useCallback(async () => {
17499
17738
  setSuggestionPhase("loading");
17500
17739
  setSuggestionError(null);
17501
17740
  try {
@@ -17505,11 +17744,11 @@ function DeliveryTargetSettingsPage({
17505
17744
  setSuggestionPhase("ready");
17506
17745
  } catch (caught) {
17507
17746
  if (caught?.name === "AbortError" || !mounted.current) return;
17508
- setSuggestionError(presentError13(caught, "\u65E0\u6CD5\u8BFB\u53D6\u5DF2\u804A\u4F1A\u8BDD\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
17747
+ setSuggestionError(presentError14(caught, "\u65E0\u6CD5\u8BFB\u53D6\u5DF2\u804A\u4F1A\u8BDD\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
17509
17748
  setSuggestionPhase("error");
17510
17749
  }
17511
17750
  }, [account.botId, definition, invoke]);
17512
- React29.useEffect(() => {
17751
+ React30.useEffect(() => {
17513
17752
  mounted.current = true;
17514
17753
  const controller = new AbortController();
17515
17754
  void loadTargets({ signal: controller.signal });
@@ -17577,10 +17816,10 @@ function DeliveryTargetSettingsPage({
17577
17816
  await copyText(account.botId);
17578
17817
  setBotCopyState("\u5DF2\u590D\u5236 Bot ID");
17579
17818
  } catch (caught) {
17580
- setBotCopyState(presentError13(caught, "\u590D\u5236\u5931\u8D25\u3002"));
17819
+ setBotCopyState(presentError14(caught, "\u590D\u5236\u5931\u8D25\u3002"));
17581
17820
  }
17582
17821
  };
17583
- const settingsTabs = botSettingsTabsForChannel(channel6);
17822
+ const settingsTabs = botSettingsTabsForChannel(channel7);
17584
17823
  const activeTab = settingsTabs.find((tab) => tab.id === activeTabId) ?? settingsTabs[0];
17585
17824
  const activeTabDomId = `dim-bot-settings-${activeTab.id}-tab`;
17586
17825
  const activePanelId = `dim-bot-settings-${activeTab.id}-panel`;
@@ -17623,15 +17862,15 @@ function DeliveryTargetSettingsPage({
17623
17862
  "aria-labelledby": activeTabDomId
17624
17863
  },
17625
17864
  activeTab.id === "access" ? h2(AccessPolicySettingsPage, {
17626
- channel: channel6,
17865
+ channel: channel7,
17627
17866
  account: { ...account, accessPolicy },
17628
17867
  rpcCall: accessRpcCall,
17629
17868
  onSaved: setAccessPolicy
17630
- }) : activeTab.id === "group" && channel6 === "feishu" ? h2(FeishuGroupSettingsPage, {
17869
+ }) : activeTab.id === "group" && channel7 === "feishu" ? h2(FeishuGroupSettingsPage, {
17631
17870
  account,
17632
17871
  rpcCall: accessRpcCall
17633
17872
  }) : h2(
17634
- React29.Fragment,
17873
+ React30.Fragment,
17635
17874
  null,
17636
17875
  h2(
17637
17876
  "section",
@@ -17742,7 +17981,7 @@ function DeliveryTargetSettingsPage({
17742
17981
  }
17743
17982
 
17744
17983
  // plugin-src/client/global-settings.js
17745
- var React30 = __toESM(require("react"), 1);
17984
+ var React31 = __toESM(require("react"), 1);
17746
17985
 
17747
17986
  // src/channels/shared/inbound-ttl.mjs
17748
17987
  var DEFAULT_INBOUND_TTL_HOURS = 168;
@@ -17794,10 +18033,10 @@ var GLOBAL_SETTINGS_ENDPOINTS = Object.freeze({
17794
18033
  getImages: "settings.image-input.get",
17795
18034
  setImages: "settings.image-input.set"
17796
18035
  });
17797
- function presentError14(error, fallback) {
18036
+ function presentError15(error, fallback) {
17798
18037
  return error?.message || fallback;
17799
18038
  }
17800
- function unwrapRpcResult15(result) {
18039
+ function unwrapRpcResult16(result) {
17801
18040
  if (result?.ok === true) return result.value;
17802
18041
  if (result?.ok === false) {
17803
18042
  const error = new Error(result.error?.message || "\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
@@ -17827,18 +18066,18 @@ function GlobalButton({ children, kind = "secondary", className = "", ...props }
17827
18066
  }, children);
17828
18067
  }
17829
18068
  function ImageInputSettings({ rpcCall }) {
17830
- const [values, setValues] = React30.useState(DEFAULT_IMAGE_INPUT_SETTINGS);
17831
- const [phase, setPhase] = React30.useState("loading");
17832
- const [error, setError] = React30.useState(null);
17833
- const [saved, setSaved] = React30.useState(false);
17834
- const mounted = React30.useRef(false);
17835
- const saving = React30.useRef(false);
17836
- const id6 = React30.useId();
17837
- const load = React30.useCallback(async (signal) => {
18069
+ const [values, setValues] = React31.useState(DEFAULT_IMAGE_INPUT_SETTINGS);
18070
+ const [phase, setPhase] = React31.useState("loading");
18071
+ const [error, setError] = React31.useState(null);
18072
+ const [saved, setSaved] = React31.useState(false);
18073
+ const mounted = React31.useRef(false);
18074
+ const saving = React31.useRef(false);
18075
+ const id6 = React31.useId();
18076
+ const load = React31.useCallback(async (signal) => {
17838
18077
  setPhase("loading");
17839
18078
  setError(null);
17840
18079
  try {
17841
- const result = unwrapRpcResult15(await rpcCall(GLOBAL_SETTINGS_ENDPOINTS.getImages, {}, signal));
18080
+ const result = unwrapRpcResult16(await rpcCall(GLOBAL_SETTINGS_ENDPOINTS.getImages, {}, signal));
17842
18081
  if (signal?.aborted || !mounted.current) return;
17843
18082
  const settings = normalizeImageInputSettings(result);
17844
18083
  if (!settings) throw new Error("\u901A\u7528\u8BBE\u7F6E\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94\u3002");
@@ -17846,11 +18085,11 @@ function ImageInputSettings({ rpcCall }) {
17846
18085
  setPhase("ready");
17847
18086
  } catch (caught) {
17848
18087
  if (signal?.aborted || !mounted.current) return;
17849
- setError(presentError14(caught, "\u65E0\u6CD5\u8BFB\u53D6\u6216\u4FDD\u5B58\u56FE\u7247\u8BBE\u7F6E\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
18088
+ setError(presentError15(caught, "\u65E0\u6CD5\u8BFB\u53D6\u6216\u4FDD\u5B58\u56FE\u7247\u8BBE\u7F6E\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
17850
18089
  setPhase("error");
17851
18090
  }
17852
18091
  }, [rpcCall]);
17853
- React30.useEffect(() => {
18092
+ React31.useEffect(() => {
17854
18093
  mounted.current = true;
17855
18094
  const controller = new AbortController();
17856
18095
  void load(controller.signal);
@@ -17872,14 +18111,14 @@ function ImageInputSettings({ rpcCall }) {
17872
18111
  setPhase("saving");
17873
18112
  setError(null);
17874
18113
  try {
17875
- const result = unwrapRpcResult15(await rpcCall(GLOBAL_SETTINGS_ENDPOINTS.setImages, settings));
18114
+ const result = unwrapRpcResult16(await rpcCall(GLOBAL_SETTINGS_ENDPOINTS.setImages, settings));
17876
18115
  if (!normalizeImageInputSettings(result)) throw new Error("\u901A\u7528\u8BBE\u7F6E\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94\u3002");
17877
18116
  if (mounted.current) {
17878
18117
  setValues(result);
17879
18118
  setSaved(true);
17880
18119
  }
17881
18120
  } catch (caught) {
17882
- if (mounted.current) setError(presentError14(caught, "\u65E0\u6CD5\u8BFB\u53D6\u6216\u4FDD\u5B58\u56FE\u7247\u8BBE\u7F6E\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
18121
+ if (mounted.current) setError(presentError15(caught, "\u65E0\u6CD5\u8BFB\u53D6\u6216\u4FDD\u5B58\u56FE\u7247\u8BBE\u7F6E\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
17883
18122
  } finally {
17884
18123
  saving.current = false;
17885
18124
  if (mounted.current) setPhase("ready");
@@ -17927,29 +18166,29 @@ function ImageInputSettings({ rpcCall }) {
17927
18166
  );
17928
18167
  }
17929
18168
  function GlobalSettingsPanel({ rpcCall }) {
17930
- const [phase, setPhase] = React30.useState("loading");
17931
- const [loadError, setLoadError] = React30.useState(null);
17932
- const [ttlInput, setTtlInput] = React30.useState("");
17933
- const [savedTtl, setSavedTtl] = React30.useState(null);
17934
- const [ttlError, setTtlError] = React30.useState(false);
17935
- const [saveError, setSaveError] = React30.useState(null);
17936
- const [saveSucceeded, setSaveSucceeded] = React30.useState(false);
17937
- const [isSaving, setIsSaving] = React30.useState(false);
17938
- const [sweepConfirming, setSweepConfirming] = React30.useState(false);
17939
- const [sweeping, setSweeping] = React30.useState(false);
17940
- const ttlErrorId = React30.useId();
17941
- const ttlHintsId = React30.useId();
17942
- const sweepTriggerId = React30.useId();
17943
- const sweepConfirmId = React30.useId();
17944
- const sweepConfirmTextId = React30.useId();
17945
- const sweepConfirmButtonId = React30.useId();
17946
- const mounted = React30.useRef(true);
17947
- const saving = React30.useRef(false);
17948
- const invoke = React30.useCallback(async (endpoint, payload = {}, signal) => {
18169
+ const [phase, setPhase] = React31.useState("loading");
18170
+ const [loadError, setLoadError] = React31.useState(null);
18171
+ const [ttlInput, setTtlInput] = React31.useState("");
18172
+ const [savedTtl, setSavedTtl] = React31.useState(null);
18173
+ const [ttlError, setTtlError] = React31.useState(false);
18174
+ const [saveError, setSaveError] = React31.useState(null);
18175
+ const [saveSucceeded, setSaveSucceeded] = React31.useState(false);
18176
+ const [isSaving, setIsSaving] = React31.useState(false);
18177
+ const [sweepConfirming, setSweepConfirming] = React31.useState(false);
18178
+ const [sweeping, setSweeping] = React31.useState(false);
18179
+ const ttlErrorId = React31.useId();
18180
+ const ttlHintsId = React31.useId();
18181
+ const sweepTriggerId = React31.useId();
18182
+ const sweepConfirmId = React31.useId();
18183
+ const sweepConfirmTextId = React31.useId();
18184
+ const sweepConfirmButtonId = React31.useId();
18185
+ const mounted = React31.useRef(true);
18186
+ const saving = React31.useRef(false);
18187
+ const invoke = React31.useCallback(async (endpoint, payload = {}, signal) => {
17949
18188
  if (typeof rpcCall !== "function") throw new Error("\u901A\u7528\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
17950
- return unwrapRpcResult15(await rpcCall(endpoint, payload, signal));
18189
+ return unwrapRpcResult16(await rpcCall(endpoint, payload, signal));
17951
18190
  }, [rpcCall]);
17952
- const loadSettings = React30.useCallback(async ({ signal } = {}) => {
18191
+ const loadSettings = React31.useCallback(async ({ signal } = {}) => {
17953
18192
  setPhase("loading");
17954
18193
  setLoadError(null);
17955
18194
  try {
@@ -17969,11 +18208,11 @@ function GlobalSettingsPanel({ rpcCall }) {
17969
18208
  setPhase("ready");
17970
18209
  } catch (caught) {
17971
18210
  if (signal?.aborted || caught?.name === "AbortError" || !mounted.current) return;
17972
- setLoadError(presentError14(caught, "\u65E0\u6CD5\u8BFB\u53D6\u901A\u7528\u8BBE\u7F6E\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
18211
+ setLoadError(presentError15(caught, "\u65E0\u6CD5\u8BFB\u53D6\u901A\u7528\u8BBE\u7F6E\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
17973
18212
  setPhase("error");
17974
18213
  }
17975
18214
  }, [invoke]);
17976
- React30.useEffect(() => {
18215
+ React31.useEffect(() => {
17977
18216
  mounted.current = true;
17978
18217
  const controller = new AbortController();
17979
18218
  void loadSettings({ signal: controller.signal });
@@ -17982,7 +18221,7 @@ function GlobalSettingsPanel({ rpcCall }) {
17982
18221
  controller.abort();
17983
18222
  };
17984
18223
  }, [loadSettings]);
17985
- React30.useEffect(() => {
18224
+ React31.useEffect(() => {
17986
18225
  if (!sweepConfirming) return;
17987
18226
  globalThis.document?.getElementById(sweepConfirmButtonId)?.focus();
17988
18227
  }, [sweepConfirmButtonId, sweepConfirming]);
@@ -18013,7 +18252,7 @@ function GlobalSettingsPanel({ rpcCall }) {
18013
18252
  setPhase("ready");
18014
18253
  } catch (caught) {
18015
18254
  if (mounted.current) {
18016
- setSaveError(presentError14(caught, "\u8BBE\u7F6E\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
18255
+ setSaveError(presentError15(caught, "\u8BBE\u7F6E\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
18017
18256
  }
18018
18257
  } finally {
18019
18258
  saving.current = false;
@@ -18290,7 +18529,7 @@ function replacePageLocation(url, location = globalThis.location) {
18290
18529
 
18291
18530
  // plugin-src/client/styles.js
18292
18531
  var IM_STYLE_ID = "xmanrui-dsh-im-settings";
18293
- var CSS14 = String.raw`
18532
+ var CSS15 = String.raw`
18294
18533
  .dim-connectionDiagnostic { min-width: 0; width: 100%; color: var(--dsw-alias-label-secondary, #646a73); overflow-wrap: anywhere; font-size: 13px; line-height: 1.6; }
18295
18534
  .dim-connectionDiagnostic[data-warning="true"] { color: var(--dsw-alias-state-warn-primary, #d97706); }
18296
18535
  .dim-connectionDiagnostic p { margin: 4px 0; }
@@ -18350,7 +18589,9 @@ var CSS14 = String.raw`
18350
18589
  .dim-updateButton:hover:not(:disabled) { border-color: #aeb3bb; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-interactive-bg-hover, #f7f8fa); }
18351
18590
  .dim-updateButton:focus-visible { outline: 2px solid var(--dsw-alias-state-business-primary, #3370ff); outline-offset: 2px; }
18352
18591
  .dim-updateButton:disabled { opacity: .55; cursor: default; }
18353
- .dim-updateTrigger { white-space: nowrap; }
18592
+ .dim-updateAction { position: relative; display: inline-flex; flex: none; }
18593
+ .dim-updateTrigger { width: 30px; height: 30px; flex: none; padding: 0; }
18594
+ .dim-updateTrigger svg { display: block; }
18354
18595
  .dim-updateBackdrop { position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center; padding: 24px; background: rgb(15 17 21 / 42%); }
18355
18596
  .dim-updateBackdrop, .dim-updateBackdrop * { box-sizing: border-box; }
18356
18597
  .dim-updateDialog { width: min(480px, 100%); max-height: calc(100vh - 48px); overflow-y: auto; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 16px; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-bg-layer-3, #fff); box-shadow: 0 20px 70px rgb(0 0 0 / 20%); text-align: left; }
@@ -18387,8 +18628,8 @@ var CSS14 = String.raw`
18387
18628
  .dim-githubLink svg { display: block; }
18388
18629
  .dim-githubLink:hover { border-color: #aeb3bb; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-interactive-bg-hover, #f7f8fa); }
18389
18630
  .dim-githubLink:focus-visible { outline: 2px solid color-mix(in srgb, var(--dim-blue) 70%, white); outline-offset: 2px; }
18390
- .dim-githubTooltip { position: absolute; top: calc(100% + 8px); right: 0; z-index: 20; width: max-content; max-width: min(220px, 80vw); padding: 6px 9px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 7px; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-bg-layer-3, #fff); box-shadow: 0 8px 24px rgb(31 35 41 / 14%); font-size: 11px; line-height: 16px; font-weight: 500; white-space: nowrap; opacity: 0; visibility: hidden; transform: translateY(-3px); pointer-events: none; transition: opacity .15s ease, transform .15s ease, visibility .15s ease; }
18391
- .dim-githubAction:hover .dim-githubTooltip, .dim-githubAction:focus-within .dim-githubTooltip { opacity: 1; visibility: visible; transform: translateY(0); }
18631
+ .dim-updateTooltip, .dim-githubTooltip { position: absolute; top: calc(100% + 8px); right: 0; z-index: 20; width: max-content; max-width: min(220px, 80vw); padding: 6px 9px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 7px; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-bg-layer-3, #fff); box-shadow: 0 8px 24px rgb(31 35 41 / 14%); font-size: 11px; line-height: 16px; font-weight: 500; white-space: nowrap; opacity: 0; visibility: hidden; transform: translateY(-3px); pointer-events: none; transition: opacity .15s ease, transform .15s ease, visibility .15s ease; }
18632
+ .dim-updateAction:hover .dim-updateTooltip, .dim-updateTrigger:focus-visible + .dim-updateTooltip, .dim-githubAction:hover .dim-githubTooltip, .dim-githubAction:focus-within .dim-githubTooltip { opacity: 1; visibility: visible; transform: translateY(0); }
18392
18633
  .dim-generalSettingsAction { position: relative; display: inline-flex; flex: none; }
18393
18634
  .dim-generalSettingsButton { width: 30px; height: 30px; display: grid; place-items: center; flex: none; padding: 0; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 8px; color: var(--dsw-alias-label-secondary, #646a73); background: var(--dsw-alias-bg-layer-1, #fff); cursor: pointer; transition: border-color .15s ease, color .15s ease, background .15s ease, box-shadow .15s ease; }
18394
18635
  .dim-generalSettingsButton svg { display: block; }
@@ -19010,7 +19251,7 @@ function installImStyles() {
19010
19251
  const style = document.createElement("style");
19011
19252
  style.dataset.plugin = "@xmanrui/dsh-im";
19012
19253
  style.dataset.pluginCss = IM_STYLE_ID;
19013
- style.textContent = CSS14;
19254
+ style.textContent = CSS15;
19014
19255
  document.head.appendChild(style);
19015
19256
  return () => style.remove();
19016
19257
  }
@@ -19027,15 +19268,16 @@ var SESSION_CHANNEL_LABELS = Object.freeze(Object.fromEntries(Object.entries({
19027
19268
  discord: ["Discord", "Discord"],
19028
19269
  whatsapp: ["WhatsApp", "WhatsApp"],
19029
19270
  imessage: ["iMessage", "iMessage"],
19271
+ matrix: ["Matrix", "Matrix"],
19030
19272
  office: ["AI Office", "AI Office"]
19031
- }).map(([channel6, labels]) => [channel6, Object.freeze(labels)])));
19273
+ }).map(([channel7, labels]) => [channel7, Object.freeze(labels)])));
19032
19274
  function parseSessionChannelTitle(title) {
19033
19275
  if (typeof title !== "string") return null;
19034
- for (const [channel6, labels] of Object.entries(SESSION_CHANNEL_LABELS)) {
19276
+ for (const [channel7, labels] of Object.entries(SESSION_CHANNEL_LABELS)) {
19035
19277
  for (const label of labels) {
19036
19278
  const prefix = `${label} \xB7 `;
19037
19279
  if (title.startsWith(prefix) && title.slice(prefix.length).trim()) {
19038
- return { channel: channel6, title: title.slice(prefix.length) };
19280
+ return { channel: channel7, title: title.slice(prefix.length) };
19039
19281
  }
19040
19282
  }
19041
19283
  }
@@ -19054,6 +19296,7 @@ var GLYPHS = Object.freeze({
19054
19296
  discord: [DiscordLogoGlyph, "#5865f2"],
19055
19297
  whatsapp: [WhatsappLogoGlyph, "#25d366"],
19056
19298
  imessage: [IMessageLogoGlyph, "#3478f6"],
19299
+ matrix: [MatrixLogoGlyph, "#1a8f6f"],
19057
19300
  office: [OfficeLogoGlyph, "#f97316"]
19058
19301
  });
19059
19302
  var CHANNEL_ATTR = "data-dsh-im-session-channel";
@@ -19076,8 +19319,8 @@ function titleOf(row) {
19076
19319
  }
19077
19320
  return title?.childNodes.length === 1 && title.firstChild.nodeType === 3 ? title : null;
19078
19321
  }
19079
- function logoUri(document2, channel6) {
19080
- const [Glyph, color] = GLYPHS[channel6];
19322
+ function logoUri(document2, channel7) {
19323
+ const [Glyph, color] = GLYPHS[channel7];
19081
19324
  const render = (node) => {
19082
19325
  if (!["svg", "path"].includes(node.type)) throw new Error("Unsupported channel logo element");
19083
19326
  const element = document2.createElementNS(SVG_NS, node.type);
@@ -19104,7 +19347,7 @@ function createInstallation(document2) {
19104
19347
  let scheduled = false;
19105
19348
  const style = document2.createElement("style");
19106
19349
  style.dataset.pluginCss = "dsh-im-session-channel-logos";
19107
- const uris = Object.fromEntries(Object.keys(GLYPHS).map((channel6) => [channel6, logoUri(document2, channel6)]));
19350
+ const uris = Object.fromEntries(Object.keys(GLYPHS).map((channel7) => [channel7, logoUri(document2, channel7)]));
19108
19351
  style.textContent = `
19109
19352
  ${MARKED}[${TITLE_ATTR}] {
19110
19353
  position: relative;
@@ -19136,7 +19379,7 @@ ${MARKED}[${TITLE_ATTR}]::after {
19136
19379
  text-overflow: ellipsis;
19137
19380
  pointer-events: none;
19138
19381
  }
19139
- ${Object.entries(uris).map(([channel6, uri]) => `[${CHANNEL_ATTR}="${channel6}"] { --dsh-im-session-logo: url("${uri}"); }`).join("\n")}
19382
+ ${Object.entries(uris).map(([channel7, uri]) => `[${CHANNEL_ATTR}="${channel7}"] { --dsh-im-session-logo: url("${uri}"); }`).join("\n")}
19140
19383
  `;
19141
19384
  document2.head.appendChild(style);
19142
19385
  const restore = (title) => {
@@ -19219,12 +19462,12 @@ ${Object.entries(uris).map(([channel6, uri]) => `[${CHANNEL_ATTR}="${channel6}"]
19219
19462
  attributes: true,
19220
19463
  attributeFilter: ["class", "role", "aria-selected", "contenteditable"]
19221
19464
  });
19222
- for (const [channel6, uri] of Object.entries(uris)) {
19465
+ for (const [channel7, uri] of Object.entries(uris)) {
19223
19466
  const image = new view.Image();
19224
19467
  images.push(image);
19225
19468
  image.onload = () => {
19226
19469
  if (closed) return;
19227
- ready.add(channel6);
19470
+ ready.add(channel7);
19228
19471
  collect(document2.body, true);
19229
19472
  };
19230
19473
  image.src = uri;
@@ -19265,7 +19508,7 @@ function installSessionChannelLogos(document2 = globalThis.document) {
19265
19508
  }
19266
19509
 
19267
19510
  // plugin-src/client/update-panel.js
19268
- var React31 = __toESM(require("react"), 1);
19511
+ var React32 = __toESM(require("react"), 1);
19269
19512
  var import_react_dom4 = require("react-dom");
19270
19513
  var import_valid = __toESM(require_valid(), 1);
19271
19514
  var import_rcompare = __toESM(require_rcompare(), 1);
@@ -19312,7 +19555,7 @@ function unwrapSnapshot(result) {
19312
19555
  }
19313
19556
  return value;
19314
19557
  }
19315
- function presentError15(error) {
19558
+ function presentError16(error) {
19316
19559
  const code = error?.rpcError?.code ?? error?.code ?? "";
19317
19560
  const message = error?.rpcError?.message ?? error?.message ?? "";
19318
19561
  if (code === "update-unavailable" || /(?:not[-_ ]found|unimplemented|unknown[-_ ](?:endpoint|channel)|no[-_ ]handler)/i.test(code) || /(?:not found|unknown (?:endpoint|channel)|not registered|no .*handler|HTTP 404)/i.test(message)) {
@@ -19358,11 +19601,11 @@ function manualUpdateCommand(snapshot) {
19358
19601
  return `dsh plugin --profile ${profileArgument} add -w @xmanrui/dsh-im@${version}`;
19359
19602
  }
19360
19603
  function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
19361
- const [copyState, setCopyState] = React31.useState("idle");
19362
- const commandRef = React31.useRef(null);
19363
- const mounted = React31.useRef(false);
19364
- const copying = React31.useRef(false);
19365
- React31.useEffect(() => {
19604
+ const [copyState, setCopyState] = React32.useState("idle");
19605
+ const commandRef = React32.useRef(null);
19606
+ const mounted = React32.useRef(false);
19607
+ const copying = React32.useRef(false);
19608
+ React32.useEffect(() => {
19366
19609
  mounted.current = true;
19367
19610
  return () => {
19368
19611
  mounted.current = false;
@@ -19394,7 +19637,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
19394
19637
  { className: "dim-updateManual", "aria-label": "\u624B\u5DE5\u66F4\u65B0" },
19395
19638
  h2("h4", { className: "dim-updateManualHeading" }, "\u624B\u5DE5\u66F4\u65B0"),
19396
19639
  command ? h2(
19397
- React31.Fragment,
19640
+ React32.Fragment,
19398
19641
  null,
19399
19642
  h2("p", { className: "dim-updateManualHint" }, "\u81EA\u52A8\u66F4\u65B0\u5931\u8D25\u53EF\u4EE5\u4F7F\u7528\u547D\u4EE4\u66F4\u65B0\uFF1A"),
19400
19643
  h2(
@@ -19430,7 +19673,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
19430
19673
  "aria-hidden": "true",
19431
19674
  focusable: "false"
19432
19675
  }, copyState === "copied" ? h2("path", { d: "m4 10 4 4 8-8" }) : h2(
19433
- React31.Fragment,
19676
+ React32.Fragment,
19434
19677
  null,
19435
19678
  h2("rect", { x: 7, y: 7, width: 10, height: 11, rx: 1.5 }),
19436
19679
  h2("path", { d: "M5 13H3.5A1.5 1.5 0 0 1 2 11.5v-8A1.5 1.5 0 0 1 3.5 2h8A1.5 1.5 0 0 1 13 3.5V5" })
@@ -19455,10 +19698,10 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
19455
19698
  );
19456
19699
  }
19457
19700
  function UpdateDialog({ children, onClose }) {
19458
- const dialogRef = React31.useRef(null);
19459
- const titleId = React31.useId();
19460
- const descriptionId = React31.useId();
19461
- React31.useEffect(() => {
19701
+ const dialogRef = React32.useRef(null);
19702
+ const titleId = React32.useId();
19703
+ const descriptionId = React32.useId();
19704
+ React32.useEffect(() => {
19462
19705
  const previous = globalThis.document?.activeElement;
19463
19706
  dialogRef.current?.focus?.();
19464
19707
  return () => {
@@ -19516,19 +19759,20 @@ function UpdateDialog({ children, onClose }) {
19516
19759
  return typeof document !== "undefined" && document.body ? (0, import_react_dom4.createPortal)(content, document.body) : content;
19517
19760
  }
19518
19761
  function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
19519
- const [snapshot, setSnapshot] = React31.useState(null);
19520
- const [action, setAction] = React31.useState("status");
19521
- const [error, setError] = React31.useState(null);
19522
- const [open, setOpen] = React31.useState(false);
19523
- const [uncertainInstall, setUncertainInstall] = React31.useState(false);
19524
- const mounted = React31.useRef(false);
19525
- const busy = React31.useRef(false);
19526
- const readController = React31.useRef(null);
19527
- const pollReadController = React31.useRef(null);
19528
- const installRequest = React31.useRef(null);
19529
- const onStatusRef = React31.useRef(onStatus);
19762
+ const tooltipId = React32.useId();
19763
+ const [snapshot, setSnapshot] = React32.useState(null);
19764
+ const [action, setAction] = React32.useState("status");
19765
+ const [error, setError] = React32.useState(null);
19766
+ const [open, setOpen] = React32.useState(false);
19767
+ const [uncertainInstall, setUncertainInstall] = React32.useState(false);
19768
+ const mounted = React32.useRef(false);
19769
+ const busy = React32.useRef(false);
19770
+ const readController = React32.useRef(null);
19771
+ const pollReadController = React32.useRef(null);
19772
+ const installRequest = React32.useRef(null);
19773
+ const onStatusRef = React32.useRef(onStatus);
19530
19774
  onStatusRef.current = onStatus;
19531
- const accept = React31.useCallback((next) => {
19775
+ const accept = React32.useCallback((next) => {
19532
19776
  setSnapshot(next);
19533
19777
  onStatusRef.current?.(next);
19534
19778
  }, []);
@@ -19537,7 +19781,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
19537
19781
  setUncertainInstall(false);
19538
19782
  accept(next);
19539
19783
  };
19540
- const invoke = React31.useCallback(async (endpoint, payload = {}, signal) => {
19784
+ const invoke = React32.useCallback(async (endpoint, payload = {}, signal) => {
19541
19785
  if (typeof rpcCall !== "function") {
19542
19786
  const unavailable = new Error("\u5F53\u524D Host \u4E0D\u652F\u6301\u66F4\u65B0\u63A5\u53E3\uFF0C\u8BF7\u5148\u624B\u52A8\u66F4\u65B0\u63D2\u4EF6\u5E76\u91CD\u542F\u3002");
19543
19787
  unavailable.code = "update-unavailable";
@@ -19545,14 +19789,14 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
19545
19789
  }
19546
19790
  return unwrapSnapshot(await rpcCall(endpoint, payload, signal));
19547
19791
  }, [rpcCall]);
19548
- React31.useEffect(() => {
19792
+ React32.useEffect(() => {
19549
19793
  mounted.current = true;
19550
19794
  busy.current = true;
19551
19795
  const controller = new AbortController();
19552
19796
  void invoke("update.status", {}, controller.signal).then((next) => {
19553
19797
  if (!controller.signal.aborted) accept(next);
19554
19798
  }).catch((cause) => {
19555
- if (!controller.signal.aborted) setError(presentError15(cause));
19799
+ if (!controller.signal.aborted) setError(presentError16(cause));
19556
19800
  }).finally(() => {
19557
19801
  if (!controller.signal.aborted) {
19558
19802
  busy.current = false;
@@ -19568,7 +19812,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
19568
19812
  const activeJob = ACTIVE_STATES4.has(snapshot?.job?.state);
19569
19813
  const restartRequired = snapshot?.job?.state === "restart-required" || snapshot?.blockedReason === "pending-restart";
19570
19814
  const shouldPoll = activeJob || uncertainInstall;
19571
- React31.useEffect(() => {
19815
+ React32.useEffect(() => {
19572
19816
  if (!shouldPoll) return void 0;
19573
19817
  let controller;
19574
19818
  const scheduler = createPollScheduler({
@@ -19589,7 +19833,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
19589
19833
  keepPolling = ACTIVE_STATES4.has(next.job?.state);
19590
19834
  }
19591
19835
  } catch (cause) {
19592
- if (!pendingController.signal.aborted) setError(presentError15(cause));
19836
+ if (!pendingController.signal.aborted) setError(presentError16(cause));
19593
19837
  } finally {
19594
19838
  if (pollReadController.current === pendingController) pollReadController.current = null;
19595
19839
  }
@@ -19620,7 +19864,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
19620
19864
  else acceptAuthoritative(next);
19621
19865
  }
19622
19866
  } catch (cause) {
19623
- if (!controller.signal.aborted && mounted.current) setError(presentError15(cause));
19867
+ if (!controller.signal.aborted && mounted.current) setError(presentError16(cause));
19624
19868
  } finally {
19625
19869
  if (!controller.signal.aborted && mounted.current) {
19626
19870
  busy.current = false;
@@ -19646,7 +19890,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
19646
19890
  if (mounted.current) acceptAuthoritative(next);
19647
19891
  } catch (cause) {
19648
19892
  if (mounted.current) {
19649
- setError(presentError15(cause));
19893
+ setError(presentError16(cause));
19650
19894
  setUncertainInstall(true);
19651
19895
  }
19652
19896
  } finally {
@@ -19667,20 +19911,46 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
19667
19911
  const latestVersion = !activeJob && !restartRequired && !error && snapshot?.checkedAt ? snapshot.latestVersion : null;
19668
19912
  const manualCommand = manualUpdateCommand(snapshot);
19669
19913
  const buttonLabel = action === "checking" ? "\u68C0\u67E5\u4E2D\u2026" : action === "starting" || activeJob ? "\u6B63\u5728\u66F4\u65B0\u2026" : restartRequired ? "\u5F85\u624B\u52A8\u91CD\u542F" : snapshot?.canInstall ? "\u66F4\u65B0\u81F3" : "\u68C0\u67E5\u66F4\u65B0";
19914
+ const buttonDescription = localizeText(buttonLabel) + (buttonLabel === "\u66F4\u65B0\u81F3" ? ` v${snapshot.latestVersion}` : "");
19670
19915
  return h2(
19671
- React31.Fragment,
19916
+ React32.Fragment,
19672
19917
  null,
19673
- h2("button", {
19674
- type: "button",
19675
- className: "dim-updateButton dim-updateTrigger",
19676
- disabled: busyAction,
19677
- "aria-haspopup": "dialog",
19678
- onClick: () => {
19679
- setOpen(true);
19680
- if (restartRequired) void refreshStatus();
19681
- else if (!snapshot?.canInstall && !activeJob && !uncertainInstall) void check();
19682
- }
19683
- }, buttonLabel, buttonLabel === "\u66F4\u65B0\u81F3" ? ` v${snapshot.latestVersion}` : null),
19918
+ h2(
19919
+ "span",
19920
+ { className: "dim-updateAction" },
19921
+ h2("button", {
19922
+ type: "button",
19923
+ className: "dim-updateButton dim-updateTrigger",
19924
+ disabled: busyAction,
19925
+ "aria-label": buttonDescription,
19926
+ "aria-describedby": tooltipId,
19927
+ "aria-haspopup": "dialog",
19928
+ onClick: () => {
19929
+ setOpen(true);
19930
+ if (restartRequired) void refreshStatus();
19931
+ else if (!snapshot?.canInstall && !activeJob && !uncertainInstall) void check();
19932
+ }
19933
+ }, h2(
19934
+ "svg",
19935
+ {
19936
+ width: 18,
19937
+ height: 18,
19938
+ viewBox: "0 0 24 24",
19939
+ fill: "none",
19940
+ stroke: "currentColor",
19941
+ strokeWidth: 2.3,
19942
+ strokeLinecap: "round",
19943
+ strokeLinejoin: "round",
19944
+ focusable: "false",
19945
+ "aria-hidden": "true"
19946
+ },
19947
+ h2("path", { d: "M3 12a9 9 0 0 1 15.36-6.36L21 8" }),
19948
+ h2("path", { d: "M21 3v5h-5" }),
19949
+ h2("path", { d: "M21 12a9 9 0 0 1-15.36 6.36L3 16" }),
19950
+ h2("path", { d: "M8 16H3v5" })
19951
+ )),
19952
+ h2("span", { id: tooltipId, className: "dim-updateTooltip", role: "tooltip" }, buttonDescription)
19953
+ ),
19684
19954
  open ? h2(
19685
19955
  UpdateDialog,
19686
19956
  { onClose: () => setOpen(false) },
@@ -19693,25 +19963,25 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
19693
19963
  h2("dt", null, "\u8FD0\u884C\u7248\u672C"),
19694
19964
  h2("dd", null, `v${snapshot?.runningVersion ?? clientVersion}`),
19695
19965
  snapshot?.installedVersion && snapshot.installedVersion !== snapshot.runningVersion ? h2(
19696
- React31.Fragment,
19966
+ React32.Fragment,
19697
19967
  null,
19698
19968
  h2("dt", null, "\u5DF2\u5B89\u88C5\u7248\u672C"),
19699
19969
  h2("dd", null, `v${snapshot.installedVersion}`)
19700
19970
  ) : null,
19701
19971
  targetVersion ? h2(
19702
- React31.Fragment,
19972
+ React32.Fragment,
19703
19973
  null,
19704
19974
  h2("dt", null, "\u76EE\u6807\u7248\u672C"),
19705
19975
  h2("dd", null, `v${targetVersion}`)
19706
19976
  ) : null,
19707
19977
  latestVersion ? h2(
19708
- React31.Fragment,
19978
+ React32.Fragment,
19709
19979
  null,
19710
19980
  h2("dt", null, "\u6700\u65B0\u7248\u672C"),
19711
19981
  h2("dd", null, `v${latestVersion}`)
19712
19982
  ) : null,
19713
19983
  historicalTargetVersion ? h2(
19714
- React31.Fragment,
19984
+ React32.Fragment,
19715
19985
  null,
19716
19986
  h2("dt", null, "\u4E0A\u6B21\u66F4\u65B0\u76EE\u6807"),
19717
19987
  h2("dd", null, `v${historicalTargetVersion}`)
@@ -19780,8 +20050,8 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
19780
20050
  }
19781
20051
 
19782
20052
  // plugin-src/client/panel-error-boundary.js
19783
- var React32 = __toESM(require("react"), 1);
19784
- var IMPanelErrorBoundary = class extends React32.Component {
20053
+ var React33 = __toESM(require("react"), 1);
20054
+ var IMPanelErrorBoundary = class extends React33.Component {
19785
20055
  state = { failed: false };
19786
20056
  static getDerivedStateFromError() {
19787
20057
  return { failed: true };
@@ -19825,6 +20095,7 @@ var CHANNELS = Object.freeze([
19825
20095
  { id: "wecomApp", label: "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528", note: "\uFF08\u5B9E\u9A8C\u529F\u80FD\uFF09" },
19826
20096
  { id: "imessage", label: "iMessage", note: "\uFF08\u5B9E\u9A8C\u529F\u80FD\uFF09" },
19827
20097
  { id: "email", label: "\u90AE\u7BB1", note: "\uFF08\u5B9E\u9A8C\u529F\u80FD\uFF09" },
20098
+ { id: "matrix", label: "Matrix", note: "\uFF08\u5B9E\u9A8C\u529F\u80FD\uFF09" },
19828
20099
  { id: "office", label: "AI Office", note: "\uFF08\u5B9E\u9A8C\u529F\u80FD\uFF09" }
19829
20100
  ]);
19830
20101
  function WeixinLogo() {
@@ -19899,6 +20170,13 @@ function EmailLogo() {
19899
20170
  h2(EmailLogoGlyph)
19900
20171
  );
19901
20172
  }
20173
+ function MatrixLogo() {
20174
+ return h2(
20175
+ "span",
20176
+ { className: "dim-logo dim-logoMatrix", "aria-hidden": "true" },
20177
+ h2(MatrixLogoGlyph)
20178
+ );
20179
+ }
19902
20180
  function OfficeLogo() {
19903
20181
  return h2(
19904
20182
  "span",
@@ -19906,19 +20184,20 @@ function OfficeLogo() {
19906
20184
  h2(OfficeLogoGlyph)
19907
20185
  );
19908
20186
  }
19909
- function ChannelLogo({ channel: channel6 }) {
19910
- if (channel6 === "weixin") return h2(WeixinLogo);
19911
- if (channel6 === "feishu") return h2(FeishuLogo);
19912
- if (channel6 === "dingtalk") return h2(DingtalkLogo);
19913
- if (channel6 === "wecom") return h2(WecomLogo);
19914
- if (channel6 === "wecomApp") return h2(WecomAppLogo);
19915
- if (channel6 === "qq") return h2(QqLogo);
19916
- if (channel6 === "slack") return h2(SlackLogo);
19917
- if (channel6 === "telegram") return h2(TelegramLogo);
19918
- if (channel6 === "discord") return h2(DiscordLogo);
19919
- if (channel6 === "whatsapp") return h2(WhatsappLogo);
19920
- if (channel6 === "imessage") return h2(IMessageLogo);
19921
- if (channel6 === "email") return h2(EmailLogo);
20187
+ function ChannelLogo({ channel: channel7 }) {
20188
+ if (channel7 === "weixin") return h2(WeixinLogo);
20189
+ if (channel7 === "feishu") return h2(FeishuLogo);
20190
+ if (channel7 === "dingtalk") return h2(DingtalkLogo);
20191
+ if (channel7 === "wecom") return h2(WecomLogo);
20192
+ if (channel7 === "wecomApp") return h2(WecomAppLogo);
20193
+ if (channel7 === "qq") return h2(QqLogo);
20194
+ if (channel7 === "slack") return h2(SlackLogo);
20195
+ if (channel7 === "telegram") return h2(TelegramLogo);
20196
+ if (channel7 === "discord") return h2(DiscordLogo);
20197
+ if (channel7 === "whatsapp") return h2(WhatsappLogo);
20198
+ if (channel7 === "imessage") return h2(IMessageLogo);
20199
+ if (channel7 === "email") return h2(EmailLogo);
20200
+ if (channel7 === "matrix") return h2(MatrixLogo);
19922
20201
  return h2(OfficeLogo);
19923
20202
  }
19924
20203
  function LoopbackRecoveryNotice({ recovery, onNavigate = replacePageLocation }) {
@@ -19948,6 +20227,7 @@ function IMSettingsTab({
19948
20227
  feishuRpcCall,
19949
20228
  imessageRpcCall,
19950
20229
  emailRpcCall,
20230
+ matrixRpcCall,
19951
20231
  qqRpcCall,
19952
20232
  slackRpcCall,
19953
20233
  telegramRpcCall,
@@ -19964,28 +20244,28 @@ function IMSettingsTab({
19964
20244
  browserLocation = globalThis.location,
19965
20245
  navigateToRecoveryUrl = replacePageLocation
19966
20246
  }) {
19967
- const [selected, setSelected] = React33.useState(() => preferredSectionId === GLOBAL_SETTINGS_TAB_ID || CHANNELS.some((channel6) => channel6.id === preferredSectionId) ? preferredSectionId : "weixin");
19968
- const [loopbackRecovery, setLoopbackRecovery] = React33.useState(null);
19969
- const [runningVersion, setRunningVersion] = React33.useState(IM_PLUGIN_VERSION);
19970
- const [deliverySettings, setDeliverySettings] = React33.useState(null);
20247
+ const [selected, setSelected] = React34.useState(() => preferredSectionId === GLOBAL_SETTINGS_TAB_ID || CHANNELS.some((channel7) => channel7.id === preferredSectionId) ? preferredSectionId : "weixin");
20248
+ const [loopbackRecovery, setLoopbackRecovery] = React34.useState(null);
20249
+ const [runningVersion, setRunningVersion] = React34.useState(IM_PLUGIN_VERSION);
20250
+ const [deliverySettings, setDeliverySettings] = React34.useState(null);
19971
20251
  const emailEnabled = useEmailChannelEnabled(emailRpcCall);
19972
- const visibleChannels = React33.useMemo(
19973
- () => CHANNELS.filter((channel6) => channel6.id !== "email" || emailEnabled),
20252
+ const visibleChannels = React34.useMemo(
20253
+ () => CHANNELS.filter((channel7) => channel7.id !== "email" || emailEnabled),
19974
20254
  [emailEnabled]
19975
20255
  );
19976
- const githubTooltipId = React33.useId();
19977
- const generalSettingsTooltipId = React33.useId();
20256
+ const githubTooltipId = React34.useId();
20257
+ const generalSettingsTooltipId = React34.useId();
19978
20258
  const globalSettingsSelected = selected === GLOBAL_SETTINGS_TAB_ID;
19979
- const active = visibleChannels.find((channel6) => channel6.id === selected) ?? visibleChannels[0];
20259
+ const active = visibleChannels.find((channel7) => channel7.id === selected) ?? visibleChannels[0];
19980
20260
  const activeTabId = globalSettingsSelected ? "dim-general-settings-trigger" : `dim-tab-${active.id}`;
19981
20261
  const activePanelId = globalSettingsSelected ? `dim-panel-${GLOBAL_SETTINGS_TAB_ID}` : `dim-panel-${active.id}`;
19982
- const reportLoopbackRecovery = React33.useCallback((recovery) => {
20262
+ const reportLoopbackRecovery = React34.useCallback((recovery) => {
19983
20263
  setLoopbackRecovery((current) => current?.url === recovery.url ? current : recovery);
19984
20264
  }, []);
19985
- const reportUpdateStatus = React33.useCallback((snapshot) => {
20265
+ const reportUpdateStatus = React34.useCallback((snapshot) => {
19986
20266
  setRunningVersion(snapshot.runningVersion);
19987
20267
  }, []);
19988
- const rpcCalls = React33.useMemo(() => createLoopbackAwareRpcCalls({
20268
+ const rpcCalls = React34.useMemo(() => createLoopbackAwareRpcCalls({
19989
20269
  dingtalkRpcCall,
19990
20270
  discordRpcCall,
19991
20271
  feishuRpcCall,
@@ -20001,7 +20281,8 @@ function IMSettingsTab({
20001
20281
  deliveryRpcCall,
20002
20282
  globalSettingsRpcCall,
20003
20283
  imessageRpcCall,
20004
- emailRpcCall
20284
+ emailRpcCall,
20285
+ matrixRpcCall
20005
20286
  }, {
20006
20287
  location: browserLocation,
20007
20288
  onRecovery: reportLoopbackRecovery
@@ -20014,6 +20295,7 @@ function IMSettingsTab({
20014
20295
  globalSettingsRpcCall,
20015
20296
  imessageRpcCall,
20016
20297
  emailRpcCall,
20298
+ matrixRpcCall,
20017
20299
  officeRpcCall,
20018
20300
  qqRpcCall,
20019
20301
  reportLoopbackRecovery,
@@ -20025,7 +20307,7 @@ function IMSettingsTab({
20025
20307
  weixinRpcCall,
20026
20308
  whatsappRpcCall
20027
20309
  ]);
20028
- const botSettingsContext = React33.useMemo(() => Object.freeze({
20310
+ const botSettingsContext = React34.useMemo(() => Object.freeze({
20029
20311
  openBotSettings: setDeliverySettings
20030
20312
  }), []);
20031
20313
  return h2(
@@ -20116,27 +20398,27 @@ function IMSettingsTab({
20116
20398
  h2(
20117
20399
  "nav",
20118
20400
  { className: "dim-rail", role: "tablist", "aria-label": "IM \u8BBE\u7F6E\u5BFC\u822A" },
20119
- visibleChannels.map((channel6) => h2(
20401
+ visibleChannels.map((channel7) => h2(
20120
20402
  "button",
20121
20403
  {
20122
- key: channel6.id,
20404
+ key: channel7.id,
20123
20405
  type: "button",
20124
20406
  role: "tab",
20125
- id: `dim-tab-${channel6.id}`,
20407
+ id: `dim-tab-${channel7.id}`,
20126
20408
  className: "dim-channel",
20127
- "aria-selected": !globalSettingsSelected && channel6.id === active.id,
20128
- "aria-controls": `dim-panel-${channel6.id}`,
20409
+ "aria-selected": !globalSettingsSelected && channel7.id === active.id,
20410
+ "aria-controls": `dim-panel-${channel7.id}`,
20129
20411
  onClick: () => {
20130
- setSelected(channel6.id);
20412
+ setSelected(channel7.id);
20131
20413
  setDeliverySettings(null);
20132
20414
  }
20133
20415
  },
20134
- h2(ChannelLogo, { channel: channel6.id }),
20416
+ h2(ChannelLogo, { channel: channel7.id }),
20135
20417
  h2(
20136
20418
  "span",
20137
20419
  { className: "dim-channelCopy" },
20138
- h2("strong", null, channel6.label),
20139
- channel6.note ? h2("small", { className: "dim-channelNote" }, channel6.note) : null
20420
+ h2("strong", null, channel7.label),
20421
+ channel7.note ? h2("small", { className: "dim-channelNote" }, channel7.note) : null
20140
20422
  )
20141
20423
  ))
20142
20424
  ),
@@ -20162,7 +20444,7 @@ function IMSettingsTab({
20162
20444
  rpcCall: rpcCalls.deliveryRpcCall,
20163
20445
  accessRpcCall: rpcCalls[`${active.id}RpcCall`],
20164
20446
  onBack: () => setDeliverySettings(null)
20165
- }) : active.id === "weixin" ? h2(WeixinSettingsTab, { rpcCall: rpcCalls.weixinRpcCall }) : active.id === "feishu" ? h2(FeishuSettingsTab, { rpcCall: rpcCalls.feishuRpcCall }) : active.id === "dingtalk" ? h2(DingtalkSettingsTab, { rpcCall: rpcCalls.dingtalkRpcCall }) : active.id === "wecom" ? h2(WecomSettingsTab, { rpcCall: rpcCalls.wecomRpcCall }) : active.id === "wecomApp" ? h2(WecomAppSettingsTab, { rpcCall: rpcCalls.wecomAppRpcCall }) : active.id === "qq" ? h2(QqSettingsTab, { rpcCall: rpcCalls.qqRpcCall }) : active.id === "slack" ? h2(SlackSettingsTab, { rpcCall: rpcCalls.slackRpcCall }) : active.id === "telegram" ? h2(TelegramSettingsTab, { rpcCall: rpcCalls.telegramRpcCall }) : active.id === "discord" ? h2(DiscordSettingsTab, { rpcCall: rpcCalls.discordRpcCall }) : active.id === "whatsapp" ? h2(WhatsappSettingsTab, { rpcCall: rpcCalls.whatsappRpcCall }) : active.id === "imessage" ? h2(IMessageSettingsTab, { rpcCall: rpcCalls.imessageRpcCall }) : active.id === "email" ? h2(EmailSettingsTab, { rpcCall: rpcCalls.emailRpcCall }) : h2(OfficeSettingsTab, { rpcCall: rpcCalls.officeRpcCall })
20447
+ }) : active.id === "weixin" ? h2(WeixinSettingsTab, { rpcCall: rpcCalls.weixinRpcCall }) : active.id === "feishu" ? h2(FeishuSettingsTab, { rpcCall: rpcCalls.feishuRpcCall }) : active.id === "dingtalk" ? h2(DingtalkSettingsTab, { rpcCall: rpcCalls.dingtalkRpcCall }) : active.id === "wecom" ? h2(WecomSettingsTab, { rpcCall: rpcCalls.wecomRpcCall }) : active.id === "wecomApp" ? h2(WecomAppSettingsTab, { rpcCall: rpcCalls.wecomAppRpcCall }) : active.id === "qq" ? h2(QqSettingsTab, { rpcCall: rpcCalls.qqRpcCall }) : active.id === "slack" ? h2(SlackSettingsTab, { rpcCall: rpcCalls.slackRpcCall }) : active.id === "telegram" ? h2(TelegramSettingsTab, { rpcCall: rpcCalls.telegramRpcCall }) : active.id === "discord" ? h2(DiscordSettingsTab, { rpcCall: rpcCalls.discordRpcCall }) : active.id === "whatsapp" ? h2(WhatsappSettingsTab, { rpcCall: rpcCalls.whatsappRpcCall }) : active.id === "imessage" ? h2(IMessageSettingsTab, { rpcCall: rpcCalls.imessageRpcCall }) : active.id === "email" ? h2(EmailSettingsTab, { rpcCall: rpcCalls.emailRpcCall }) : active.id === "matrix" ? h2(MatrixSettingsTab, { rpcCall: rpcCalls.matrixRpcCall }) : h2(OfficeSettingsTab, { rpcCall: rpcCalls.officeRpcCall })
20166
20448
  )
20167
20449
  )
20168
20450
  )
@@ -20196,6 +20478,7 @@ function apply(ctx) {
20196
20478
  installWhatsappStyles(),
20197
20479
  installIMessageStyles(),
20198
20480
  installEmailStyles(),
20481
+ installMatrixStyles(),
20199
20482
  installOfficeStyles(),
20200
20483
  installImStyles()
20201
20484
  ];
@@ -20214,6 +20497,7 @@ function apply(ctx) {
20214
20497
  const whatsappRpcCall = (endpoint, payload, signal) => callManagementRpc(ctx.connection, WHATSAPP_RPC_CHANNEL, endpoint, payload, signal);
20215
20498
  const imessageRpcCall = (endpoint, payload, signal) => callManagementRpc(ctx.connection, IMESSAGE_RPC_CHANNEL, endpoint, payload, signal);
20216
20499
  const emailRpcCall = (endpoint, payload, signal) => callManagementRpc(ctx.connection, EMAIL_RPC_CHANNEL, endpoint, payload, signal);
20500
+ const matrixRpcCall = (endpoint, payload, signal) => callManagementRpc(ctx.connection, MATRIX_RPC_CHANNEL, endpoint, payload, signal);
20217
20501
  const slackRpcCall = (endpoint, payload, signal) => callManagementRpc(ctx.connection, SLACK_RPC_CHANNEL, endpoint, payload, signal);
20218
20502
  const officeRpcCall = (endpoint, payload, signal) => callManagementRpc(ctx.connection, OFFICE_RPC_CHANNEL, endpoint, payload, signal);
20219
20503
  const updateRpcCall = (endpoint, payload, signal) => callManagementRpc(ctx.connection, UPDATE_RPC_CHANNEL, endpoint, payload, signal);
@@ -20237,6 +20521,7 @@ function apply(ctx) {
20237
20521
  imessageRpcCall,
20238
20522
  officeRpcCall,
20239
20523
  emailRpcCall,
20524
+ matrixRpcCall,
20240
20525
  updateRpcCall,
20241
20526
  deliveryRpcCall,
20242
20527
  globalSettingsRpcCall,
@@ -20246,7 +20531,7 @@ function apply(ctx) {
20246
20531
  };
20247
20532
  const localeSnapshot = () => ctx.locale.getLocale?.()?.active ?? "";
20248
20533
  function IMPanel({ preferredSectionId }) {
20249
- React33.useSyncExternalStore(subscribeLocale, localeSnapshot, localeSnapshot);
20534
+ React34.useSyncExternalStore(subscribeLocale, localeSnapshot, localeSnapshot);
20250
20535
  return h2(
20251
20536
  IMPanelErrorBoundary,
20252
20537
  null,