@xmanrui/dsh-im 4.17.0 → 4.18.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 (50) hide show
  1. package/README.en.md +20 -14
  2. package/README.md +19 -16
  3. package/lib/client.js +447 -257
  4. package/lib/index.js +285 -263
  5. package/package.json +10 -4
  6. package/plugin-src/client/access-policy-settings.js +5 -0
  7. package/plugin-src/client/channel-logos.js +10 -0
  8. package/plugin-src/client/channels/imessage/api.js +12 -0
  9. package/plugin-src/client/channels/imessage/index.js +45 -0
  10. package/plugin-src/client/channels/imessage/styles.js +19 -0
  11. package/plugin-src/client/channels/shared/token-api.js +1 -0
  12. package/plugin-src/client/channels/shared/token-channel.js +5 -1
  13. package/plugin-src/client/delivery-settings.js +5 -0
  14. package/plugin-src/client/i18n.js +23 -1
  15. package/plugin-src/client/index.js +35 -14
  16. package/plugin-src/client/session-channel-logos.js +2 -0
  17. package/plugin-src/client/styles.js +1 -0
  18. package/plugin-src/host/channels/dingtalk/rpc.mjs +2 -4
  19. package/plugin-src/host/channels/feishu/rpc.mjs +2 -4
  20. package/plugin-src/host/channels/imessage/index.mjs +21 -0
  21. package/plugin-src/host/channels/imessage/production.mjs +13 -0
  22. package/plugin-src/host/channels/imessage/rpc.mjs +70 -0
  23. package/plugin-src/host/channels/office/rpc.mjs +2 -1
  24. package/plugin-src/host/channels/qq/rpc.mjs +2 -4
  25. package/plugin-src/host/channels/shared/access-policy-production.mjs +1 -1
  26. package/plugin-src/host/channels/shared/rpc.mjs +2 -4
  27. package/plugin-src/host/channels/shared/startup.mjs +2 -4
  28. package/plugin-src/host/channels/slack/rpc.mjs +2 -4
  29. package/plugin-src/host/channels/telegram/rpc.mjs +2 -4
  30. package/plugin-src/host/channels/wecom/rpc.mjs +2 -4
  31. package/plugin-src/host/channels/wecom-app/rpc.mjs +2 -4
  32. package/plugin-src/host/channels/weixin/rpc.mjs +2 -4
  33. package/plugin-src/host/channels/whatsapp/rpc.mjs +2 -4
  34. package/plugin-src/host/delivery-adapter.mjs +4 -0
  35. package/plugin-src/host/delivery-rpc.mjs +2 -4
  36. package/plugin-src/host/inbound-ttl-rpc.mjs +2 -4
  37. package/plugin-src/host/index.mjs +4 -1
  38. package/plugin-src/host/modern-harness-api.mjs +1 -1
  39. package/plugin-src/host/update-rpc.mjs +2 -1
  40. package/plugin-src/management-rpc.mjs +77 -0
  41. package/src/channels/imessage/config-store.mjs +24 -0
  42. package/src/channels/imessage/controller.mjs +37 -0
  43. package/src/channels/imessage/harness-client.mjs +7 -0
  44. package/src/channels/imessage/imessage-api.mjs +194 -0
  45. package/src/channels/imessage/imessage-bridge.mjs +16 -0
  46. package/src/channels/imessage/runtime.mjs +98 -0
  47. package/src/channels/imessage/state-store.mjs +3 -0
  48. package/src/channels/shared/i18n-en/shared-a.mjs +2 -2
  49. package/src/channels/shared/message-failure.mjs +5 -5
  50. package/src/channels/shared/session-channel-labels.mjs +1 -0
package/lib/client.js CHANGED
@@ -566,13 +566,24 @@ __export(index_exports, {
566
566
  name: () => name
567
567
  });
568
568
  module.exports = __toCommonJS(index_exports);
569
- var React28 = __toESM(require("react"), 1);
569
+
570
+ // plugin-src/management-rpc.mjs
571
+ function rpcEndpoint(channel5) {
572
+ if (!/^\/[A-Za-z0-9._~-]+$/.test(channel5)) throw new TypeError("Invalid IM RPC channel");
573
+ return `dsh-im${channel5}`;
574
+ }
575
+ function callManagementRpc(connection, channel5, method, payload, signal) {
576
+ return connection.rpc.call("/api", rpcEndpoint(channel5), { method, payload }, signal);
577
+ }
578
+
579
+ // plugin-src/client/index.js
580
+ var React29 = __toESM(require("react"), 1);
570
581
 
571
582
  // package.json
572
583
  var package_default = {
573
584
  name: "@xmanrui/dsh-im",
574
- version: "4.17.0",
575
- description: "\u628A\u5341\u79CD IM \u673A\u5668\u4EBA\u548C\u516C\u7F51 AI Office \u63A5\u5165\u672C\u673A DeepSeek Harness\u3002 Connect ten IM channels and a public AI Office to a local DeepSeek Harness.",
585
+ version: "4.18.0",
586
+ 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.",
576
587
  keywords: [
577
588
  "deepseek-harness",
578
589
  "dsh",
@@ -591,6 +602,7 @@ var package_default = {
591
602
  "telegram",
592
603
  "discord",
593
604
  "whatsapp",
605
+ "imessage",
594
606
  "ai-office"
595
607
  ],
596
608
  author: "xmanrui (https://github.com/xmanrui)",
@@ -614,6 +626,10 @@ var package_default = {
614
626
  {
615
627
  name: "masucc",
616
628
  url: "https://github.com/masucc"
629
+ },
630
+ {
631
+ name: "cherryFloris",
632
+ url: "https://github.com/cherryFloris"
617
633
  }
618
634
  ],
619
635
  license: "MIT",
@@ -668,12 +684,13 @@ var package_default = {
668
684
  platform: "web"
669
685
  },
670
686
  compatibility: {
671
- dsh: "0.1.2-alpha.4 || 0.1.2-alpha.5 || 0.1.2-rc.1 || 0.1.3-alpha.1",
687
+ dsh: "0.1.2-alpha.4 || 0.1.2-alpha.5 || 0.1.2-rc.1 || 0.1.3-alpha.1 || 0.1.5-alpha.1",
672
688
  dshReleases: {
673
689
  "0.1.2-alpha.4": "compatible",
674
690
  "0.1.2-alpha.5": "compatible",
675
691
  "0.1.2-rc.1": "compatible",
676
- "0.1.3-alpha.1": "compatible"
692
+ "0.1.3-alpha.1": "compatible",
693
+ "0.1.5-alpha.1": "compatible"
677
694
  },
678
695
  profiles: [
679
696
  "web"
@@ -843,6 +860,18 @@ function WhatsappLogoGlyph({ size } = {}) {
843
860
  d: "M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.074-.297-.149-1.255-.462-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.521.149-.173.198-.297.298-.495.099-.198.05-.372-.025-.521-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51a12.8 12.8 0 0 0-.57-.01c-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479s1.065 2.875 1.213 3.074c.149.198 2.095 3.2 5.077 4.487.709.306 1.262.489 1.694.626.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.29.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 0 1-5.031-1.378l-.361-.214-3.741.981.999-3.648-.235-.374a9.86 9.86 0 0 1-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.83 9.83 0 0 1 2.893 6.991c-.003 5.45-4.437 9.884-9.886 9.884m8.413-18.297A11.8 11.8 0 0 0 12.055 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.9 11.9 0 0 0 5.688 1.448h.005c6.557 0 11.892-5.335 11.895-11.893a11.82 11.82 0 0 0-3.486-8.413"
844
861
  }));
845
862
  }
863
+ function IMessageLogoGlyph({ size } = {}) {
864
+ return h("svg", {
865
+ ...dimensions(size),
866
+ viewBox: "0 0 24 24",
867
+ focusable: "false",
868
+ "aria-hidden": "true",
869
+ "data-im-channel-logo": "imessage"
870
+ }, h("path", {
871
+ fill: "currentColor",
872
+ d: "M12 2.2c-5.52 0-10 3.75-10 8.38 0 2.63 1.52 4.98 3.9 6.52l-.92 3.43a.5.5 0 0 0 .72.56l3.54-1.96c.87.23 1.8.35 2.76.35 5.52 0 10-3.75 10-8.9S17.52 2.2 12 2.2Zm-3.4 8.2a1.2 1.2 0 1 1 0 2.4 1.2 1.2 0 0 1 0-2.4Zm3.4 0a1.2 1.2 0 1 1 0 2.4 1.2 1.2 0 0 1 0-2.4Zm3.4 0a1.2 1.2 0 1 1 0 2.4 1.2 1.2 0 0 1 0-2.4Z"
873
+ }));
874
+ }
846
875
  function OfficeLogoGlyph({ size } = {}) {
847
876
  return h(
848
877
  "svg",
@@ -866,6 +895,27 @@ var React2 = __toESM(require("react"), 1);
866
895
  var IM_LOCALE_NAMESPACE = "dsh-im";
867
896
  var EN = Object.freeze({
868
897
  "$locale": "en",
898
+ " macOS Messages \u8FDE\u63A5": " macOS Messages connection",
899
+ "\u63A5\u5165 iMessage": "Connect iMessage",
900
+ "\u5148\u5728 macOS \u7CFB\u7EDF\u8BBE\u7F6E\u4E2D\u6388\u4E88 Messages \u6743\u9650\u3002": "Grant Messages permissions in macOS System Settings first.",
901
+ "\u914D\u7F6E macOS Messages \u6743\u9650": "Configure macOS Messages permissions",
902
+ "\u914D\u7F6E\u672C\u673A\u6743\u9650": "Configure local permissions",
903
+ "\u542F\u7528 macOS \u539F\u751F iMessage": "Enable native macOS iMessage",
904
+ "\u652F\u6301\u540C\u8D26\u53F7\u81EA\u804A\uFF1A\u5728 iPhone \u6216 Mac \u4E0A\u7ED9\u81EA\u5DF1\u5DF2\u767B\u5F55\u7684 iMessage \u90AE\u7BB1\u6216\u53F7\u7801\u53D1\u6307\u4EE4\u3002AI \u56DE\u590D\u4EE5 \u{1F916} DSH \u5F00\u5934\uFF0C\u4E0D\u4F1A\u518D\u6B21\u89E6\u53D1\u673A\u5668\u4EBA\u3002": "Self-chat is supported: send instructions from your iPhone or Mac to your signed-in iMessage email or phone number. AI replies start with \u{1F916} DSH and do not trigger the bot again.",
905
+ "\u68C0\u67E5\u6743\u9650\u5E76\u542F\u7528": "Check permissions and enable",
906
+ "DeepSeek Harness \u901A\u8FC7 macOS Messages.app \u6536\u53D1\u6587\u672C\u6D88\u606F\u3002\u9996\u6B21\u4F7F\u7528\u9700\u8981\u6388\u4E88\u4EE5\u4E0B\u6743\u9650\uFF1A": "DeepSeek Harness sends and receives messages through macOS Messages.app. The following permissions are required the first time:",
907
+ "\u2713 \u5B8C\u5168\u78C1\u76D8\u8BBF\u95EE\u6743\u9650\u5DF2\u6388\u4E88": "\u2713 Full Disk Access granted",
908
+ "1. \u6388\u4E88\u5B8C\u5168\u78C1\u76D8\u8BBF\u95EE\u6743\u9650": "1. Grant Full Disk Access",
909
+ "\u5728\u201C\u7CFB\u7EDF\u8BBE\u7F6E \u2192 \u9690\u79C1\u4E0E\u5B89\u5168\u6027 \u2192 \u5B8C\u5168\u78C1\u76D8\u8BBF\u95EE\u6743\u9650\u201D\u4E2D\uFF0C\u6253\u5F00\u8FD0\u884C DeepSeek Harness \u7684\u7EC8\u7AEF\u6216\u5E94\u7528\u3002": "In System Settings \u2192 Privacy & Security \u2192 Full Disk Access, enable the terminal or app running DeepSeek Harness.",
910
+ "\u6253\u5F00\u5B8C\u5168\u78C1\u76D8\u8BBF\u95EE\u6743\u9650\u8BBE\u7F6E": "Open Full Disk Access settings",
911
+ "\u2713 Messages \u81EA\u52A8\u5316\u6743\u9650\u5DF2\u6388\u4E88": "\u2713 Messages automation granted",
912
+ "2. \u5141\u8BB8\u81EA\u52A8\u5316\u63A7\u5236 Messages": "2. Allow automation control of Messages",
913
+ "\u5728\u201C\u7CFB\u7EDF\u8BBE\u7F6E \u2192 \u9690\u79C1\u4E0E\u5B89\u5168\u6027 \u2192 \u81EA\u52A8\u5316\u201D\u4E2D\uFF0C\u5141\u8BB8\u8FD0\u884C DeepSeek Harness \u7684\u5E94\u7528\u63A7\u5236 Messages\u3002": "In System Settings \u2192 Privacy & Security \u2192 Automation, allow the app running DeepSeek Harness to control Messages.",
914
+ "\u6253\u5F00\u81EA\u52A8\u5316\u8BBE\u7F6E": "Open Automation settings",
915
+ "\u6B63\u5728\u68C0\u67E5\u2026": "Checking\u2026",
916
+ "\u63A5\u5165 macOS \u539F\u751F iMessage": "Connect native macOS iMessage",
917
+ "\u65E0\u9700\u5B89\u88C5\u7B2C\u4E09\u65B9\u670D\u52A1\uFF1B\u8BF7\u6309\u6307\u5F15\u6388\u4E88 macOS Messages \u8BBF\u95EE\u6743\u9650\u3002": "No third-party service is required; follow the guide to grant macOS Messages access.",
918
+ "macOS Messages \u6743\u9650": "macOS Messages permissions",
869
919
  "IM\u673A\u5668\u4EBA": "IM bots",
870
920
  "IM\u673A\u5668\u4EBA\u8BBE\u7F6E": "IM bot settings",
871
921
  "\u66F4\u591A\u673A\u5668\u4EBA\u8BBE\u7F6E": "More bot settings",
@@ -1917,6 +1967,8 @@ function translateDynamic(text7) {
1917
1967
  ["\u4F01\u4E1A\u5FAE\u4FE1", "WeCom"],
1918
1968
  ["DeepSeek Harness", "DeepSeek Harness"],
1919
1969
  ["WhatsApp", "WhatsApp"],
1970
+ ["iMessage", "iMessage"],
1971
+ ["macOS Messages", "macOS Messages"],
1920
1972
  ["Telegram", "Telegram"],
1921
1973
  ["Discord", "Discord"],
1922
1974
  ["Slack", "Slack"],
@@ -2956,7 +3008,7 @@ function CredentialActionIcon() {
2956
3008
  );
2957
3009
  }
2958
3010
  function CredentialBindingPanel({
2959
- channel: channel4,
3011
+ channel: channel5,
2960
3012
  identityLabel,
2961
3013
  identityPlaceholder,
2962
3014
  secretLabel,
@@ -2983,7 +3035,7 @@ function CredentialBindingPanel({
2983
3035
  className: "ddt-card dim-surfaceCard dim-credentialPanel",
2984
3036
  "aria-labelledby": headingId
2985
3037
  },
2986
- h2("h3", { id: headingId, className: "dim-credentialTitle" }, `\u624B\u52A8\u63A5\u5165${channel4}\u673A\u5668\u4EBA`),
3038
+ h2("h3", { id: headingId, className: "dim-credentialTitle" }, `\u624B\u52A8\u63A5\u5165${channel5}\u673A\u5668\u4EBA`),
2987
3039
  h2(
2988
3040
  "form",
2989
3041
  {
@@ -4043,7 +4095,7 @@ function SettingsGlyph() {
4043
4095
  );
4044
4096
  }
4045
4097
  function BotSettingsButton({
4046
- channel: channel4,
4098
+ channel: channel5,
4047
4099
  botId,
4048
4100
  botName,
4049
4101
  connected,
@@ -4058,12 +4110,12 @@ function BotSettingsButton({
4058
4110
  h2("button", {
4059
4111
  type: "button",
4060
4112
  className: "dim-botSettingsButton",
4061
- "data-delivery-channel": channel4,
4113
+ "data-delivery-channel": channel5,
4062
4114
  "aria-label": "\u66F4\u591A\u673A\u5668\u4EBA\u8BBE\u7F6E",
4063
4115
  "aria-describedby": tooltipId,
4064
4116
  onClick: () => openBotSettings?.({
4065
4117
  ...channelSettings && typeof channelSettings === "object" ? channelSettings : {},
4066
- channel: channel4,
4118
+ channel: channel5,
4067
4119
  botId,
4068
4120
  botName,
4069
4121
  connected: Boolean(connected),
@@ -5354,16 +5406,16 @@ var TOKEN_BOT_ENDPOINTS = Object.freeze({
5354
5406
  setContextEnhancement: "bot.context-enhancement.set",
5355
5407
  setAccessPolicy: "bot.access-policy.set"
5356
5408
  });
5357
- function createTokenChannelApi(channel4, connectionSummary, {
5409
+ function createTokenChannelApi(channel5, connectionSummary, {
5358
5410
  normalizeBotExtension = () => ({})
5359
5411
  } = {}) {
5360
- const unwrapRpcResult14 = (result) => {
5412
+ const unwrapRpcResult15 = (result) => {
5361
5413
  if (!isRecord2(result) || typeof result.ok !== "boolean") {
5362
- throw new Error(`${channel4} \u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94`);
5414
+ throw new Error(`${channel5} \u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94`);
5363
5415
  }
5364
5416
  if (!result.ok) {
5365
- const error = new Error(text2(result.error?.message, `${channel4} \u64CD\u4F5C\u5931\u8D25`));
5366
- error.code = text2(result.error?.code, `${channel4.toUpperCase()}_RPC_ERROR`, 80);
5417
+ const error = new Error(text2(result.error?.message, `${channel5} \u64CD\u4F5C\u5931\u8D25`));
5418
+ error.code = text2(result.error?.code, `${channel5.toUpperCase()}_RPC_ERROR`, 80);
5367
5419
  throw error;
5368
5420
  }
5369
5421
  return result.value;
@@ -5383,29 +5435,29 @@ function createTokenChannelApi(channel4, connectionSummary, {
5383
5435
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
5384
5436
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
5385
5437
  bot: {
5386
- name: text2(value.bot?.name, `${channel4}\u673A\u5668\u4EBA`, 100),
5438
+ name: text2(value.bot?.name, `${channel5}\u673A\u5668\u4EBA`, 100),
5387
5439
  username: text2(value.bot?.username, "", 100),
5388
5440
  idMasked: text2(value.bot?.idMasked, "\u673A\u5668\u4EBA\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58", 140)
5389
5441
  },
5390
5442
  health: {
5391
5443
  summary: text2(
5392
5444
  value.health?.summary,
5393
- connected ? `${channel4}${connectionSummary}\u8FD0\u884C\u6B63\u5E38` : `${channel4}\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA`
5445
+ connected ? `${channel5}${connectionSummary}\u8FD0\u884C\u6B63\u5E38` : `${channel5}\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA`
5394
5446
  ),
5395
5447
  lastCheckedAt: timestamp2(value.health?.lastCheckedAt)
5396
5448
  },
5397
5449
  lastMessageError: normalizeLastMessageError(value.lastMessageError),
5398
5450
  error: isRecord2(value.error) ? {
5399
- code: text2(value.error.code, `${channel4.toUpperCase()}_ACCOUNT_ERROR`, 80),
5400
- message: text2(value.error.message, `${channel4}\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA`)
5451
+ code: text2(value.error.code, `${channel5.toUpperCase()}_ACCOUNT_ERROR`, 80),
5452
+ message: text2(value.error.message, `${channel5}\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA`)
5401
5453
  } : null,
5402
5454
  ...isRecord2(extension) ? extension : {}
5403
5455
  };
5404
5456
  };
5405
- const normalizeSnapshot10 = (value) => {
5457
+ const normalizeSnapshot11 = (value) => {
5406
5458
  const source = isRecord2(value?.snapshot) ? value.snapshot : value;
5407
5459
  if (!isRecord2(source) || !Array.isArray(source.bots)) {
5408
- throw new Error(`${channel4} \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868`);
5460
+ throw new Error(`${channel5} \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868`);
5409
5461
  }
5410
5462
  const bots = source.bots.map(normalizeBot8).filter(Boolean);
5411
5463
  return {
@@ -5413,14 +5465,15 @@ function createTokenChannelApi(channel4, connectionSummary, {
5413
5465
  bots,
5414
5466
  totals: { configured: bots.length, connected: bots.filter((bot) => bot.connected).length },
5415
5467
  agentPresetCatalog: normalizeAgentPresetCatalog(source.agentPresetCatalog),
5416
- modelCatalog: normalizeModelCatalog(source.modelCatalog)
5468
+ modelCatalog: normalizeModelCatalog(source.modelCatalog),
5469
+ ...isRecord2(source.permissions) ? { permissions: source.permissions } : {}
5417
5470
  };
5418
5471
  };
5419
- const presentError14 = (error) => ({
5420
- code: text2(error?.code, `${channel4.toUpperCase()}_ERROR`, 80),
5421
- message: text2(error?.message, `${channel4}\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5`)
5472
+ const presentError15 = (error) => ({
5473
+ code: text2(error?.code, `${channel5.toUpperCase()}_ERROR`, 80),
5474
+ message: text2(error?.message, `${channel5}\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5`)
5422
5475
  });
5423
- return Object.freeze({ unwrapRpcResult: unwrapRpcResult14, normalizeSnapshot: normalizeSnapshot10, presentError: presentError14 });
5476
+ return Object.freeze({ unwrapRpcResult: unwrapRpcResult15, normalizeSnapshot: normalizeSnapshot11, presentError: presentError15 });
5424
5477
  }
5425
5478
 
5426
5479
  // plugin-src/client/channels/discord/api.js
@@ -5463,9 +5516,9 @@ function connectionTestNotice(value) {
5463
5516
  }
5464
5517
  function createTokenChannelSettings(definition) {
5465
5518
  const {
5466
- channel: channel4,
5519
+ channel: channel5,
5467
5520
  endpoints,
5468
- api: api4,
5521
+ api: api5,
5469
5522
  LogoGlyph,
5470
5523
  installStyles,
5471
5524
  pageClass,
@@ -5477,7 +5530,7 @@ function createTokenChannelSettings(definition) {
5477
5530
  platformLabel,
5478
5531
  CredentialPanel = null,
5479
5532
  credentialPayload = ({ secret }) => ({ token: secret }),
5480
- credentialAriaLabel = `\u4F7F\u7528 Bot Token \u63A5\u5165 ${channel4} \u673A\u5668\u4EBA`,
5533
+ credentialAriaLabel = `\u4F7F\u7528 Bot Token \u63A5\u5165 ${channel5} \u673A\u5668\u4EBA`,
5481
5534
  credentialOpenLabel = "\u624B\u52A8\u63A5\u5165",
5482
5535
  credentialCloseLabel = "\u6536\u8D77\u51ED\u636E",
5483
5536
  credentialNoun = "Bot Token",
@@ -5540,7 +5593,7 @@ function createTokenChannelSettings(definition) {
5540
5593
  formatCheckedTime: checkedTime2
5541
5594
  }),
5542
5595
  h2(BotSettingsButton, {
5543
- channel: channel4.toLowerCase(),
5596
+ channel: channel5.toLowerCase(),
5544
5597
  botId: account.botId,
5545
5598
  botName: account.bot.name,
5546
5599
  connected: account.connected,
@@ -5633,7 +5686,8 @@ function createTokenChannelSettings(definition) {
5633
5686
  totals: { configured: 0, connected: 0 },
5634
5687
  error: null,
5635
5688
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
5636
- modelCatalog: EMPTY_MODEL_CATALOG
5689
+ modelCatalog: EMPTY_MODEL_CATALOG,
5690
+ permissions: null
5637
5691
  });
5638
5692
  const [credentialOpen, setCredentialOpen] = React13.useState(false);
5639
5693
  const [credentialError, setCredentialError] = React13.useState(null);
@@ -5654,15 +5708,15 @@ function createTokenChannelSettings(definition) {
5654
5708
  };
5655
5709
  }, []);
5656
5710
  const invoke = React13.useCallback(async (endpoint, payload = {}, signal) => {
5657
- if (typeof rpcCall !== "function") throw new TypeError(`${channel4} \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5`);
5658
- return api4.unwrapRpcResult(await rpcCall(endpoint, payload, signal));
5711
+ if (typeof rpcCall !== "function") throw new TypeError(`${channel5} \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5`);
5712
+ return api5.unwrapRpcResult(await rpcCall(endpoint, payload, signal));
5659
5713
  }, [rpcCall]);
5660
5714
  const loadStatus = React13.useCallback(async ({ signal, silent = false } = {}) => {
5661
5715
  const workspaceVersion = workspaceFence.beginStatus();
5662
5716
  if (workspaceVersion === null) return;
5663
5717
  if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
5664
5718
  try {
5665
- const snapshot = api4.normalizeSnapshot(await invoke(endpoints.status, {}, signal));
5719
+ const snapshot = api5.normalizeSnapshot(await invoke(endpoints.status, {}, signal));
5666
5720
  if (!mounted.current || signal?.aborted || !workspaceFence.canCommitStatus(workspaceVersion)) return;
5667
5721
  setModel({
5668
5722
  phase: "ready",
@@ -5670,14 +5724,15 @@ function createTokenChannelSettings(definition) {
5670
5724
  totals: snapshot.totals,
5671
5725
  error: null,
5672
5726
  agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
5673
- modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG
5727
+ modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG,
5728
+ permissions: snapshot.permissions ?? null
5674
5729
  });
5675
5730
  } catch (error) {
5676
5731
  if (error?.name !== "AbortError" && mounted.current && !signal?.aborted && workspaceFence.canCommitStatus(workspaceVersion)) {
5677
5732
  setModel((current) => ({
5678
5733
  ...current,
5679
5734
  phase: silent ? current.phase : "error",
5680
- error: api4.presentError(error)
5735
+ error: api5.presentError(error)
5681
5736
  }));
5682
5737
  }
5683
5738
  }
@@ -5704,7 +5759,7 @@ function createTokenChannelSettings(definition) {
5704
5759
  setBusy(true);
5705
5760
  setCredentialError(null);
5706
5761
  try {
5707
- const snapshot = api4.normalizeSnapshot(await invoke(
5762
+ const snapshot = api5.normalizeSnapshot(await invoke(
5708
5763
  endpoints.bindCredentials,
5709
5764
  credentialPayload(values)
5710
5765
  ));
@@ -5716,12 +5771,13 @@ function createTokenChannelSettings(definition) {
5716
5771
  totals: snapshot.totals,
5717
5772
  error: null,
5718
5773
  agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
5719
- modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG
5774
+ modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG,
5775
+ permissions: snapshot.permissions ?? null
5720
5776
  });
5721
5777
  }
5722
5778
  setCredentialOpen(false);
5723
5779
  } catch (error) {
5724
- if (mounted.current) setCredentialError(api4.presentError(error));
5780
+ if (mounted.current) setCredentialError(api5.presentError(error));
5725
5781
  } finally {
5726
5782
  const shouldRefresh = workspaceFence.endMutation();
5727
5783
  if (shouldRefresh && mounted.current) void loadStatus({ silent: true });
@@ -5733,7 +5789,7 @@ function createTokenChannelSettings(definition) {
5733
5789
  setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
5734
5790
  try {
5735
5791
  const value = await invoke(endpoint, payload);
5736
- const snapshot = api4.normalizeSnapshot(value);
5792
+ const snapshot = api5.normalizeSnapshot(value);
5737
5793
  if (mounted.current && workspaceFence.canCommitMutation(snapshotVersion)) {
5738
5794
  setModel({
5739
5795
  phase: "ready",
@@ -5773,7 +5829,7 @@ function createTokenChannelSettings(definition) {
5773
5829
  { className: "dim-listSection" },
5774
5830
  h2(ChannelListHeading, {
5775
5831
  className: "ddt-listHeading",
5776
- title: `\u5DF2\u63A5\u5165\u7684 ${channel4} \u673A\u5668\u4EBA`,
5832
+ title: `\u5DF2\u63A5\u5165\u7684 ${channel5} \u673A\u5668\u4EBA`,
5777
5833
  connectionLabel
5778
5834
  }),
5779
5835
  h2("ul", { className: "ddt-list dim-botList" }, model.bots.map((account) => h2("li", { key: account.botId }, h2(AccountCard6, {
@@ -5836,7 +5892,7 @@ function createTokenChannelSettings(definition) {
5836
5892
  "section",
5837
5893
  {
5838
5894
  className: `ddt-page ${pageClass} dim-channelPage`,
5839
- "aria-label": `${channel4} \u8BBE\u7F6E`
5895
+ "aria-label": `${channel5} \u8BBE\u7F6E`
5840
5896
  },
5841
5897
  h2(
5842
5898
  "div",
@@ -5869,13 +5925,13 @@ function createTokenChannelSettings(definition) {
5869
5925
  model.phase === "loading" ? h2("div", {
5870
5926
  className: "ddt-card ddt-loading dim-surfaceCard dim-loadingView",
5871
5927
  "aria-busy": "true"
5872
- }, h2("div", { className: "ddt-spinner dim-spinner" }), `\u6B63\u5728\u8BFB\u53D6 ${channel4} \u673A\u5668\u4EBA\u72B6\u6001\u2026`) : model.phase === "error" ? h2(
5928
+ }, h2("div", { className: "ddt-spinner dim-spinner" }), `\u6B63\u5728\u8BFB\u53D6 ${channel5} \u673A\u5668\u4EBA\u72B6\u6001\u2026`) : model.phase === "error" ? h2(
5873
5929
  "div",
5874
5930
  { className: "ddt-card dim-surfaceCard" },
5875
5931
  h2(
5876
5932
  "div",
5877
5933
  { className: "ddt-inlineError dim-inlineError" },
5878
- h2("h3", null, `\u65E0\u6CD5\u8BFB\u53D6 ${channel4} \u673A\u5668\u4EBA\u72B6\u6001`),
5934
+ h2("h3", null, `\u65E0\u6CD5\u8BFB\u53D6 ${channel5} \u673A\u5668\u4EBA\u72B6\u6001`),
5879
5935
  h2("p", null, model.error?.message),
5880
5936
  h2(Button3, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
5881
5937
  )
@@ -5883,6 +5939,8 @@ function createTokenChannelSettings(definition) {
5883
5939
  React13.Fragment,
5884
5940
  null,
5885
5941
  credentialOpen ? CredentialPanel ? h2(CredentialPanel, {
5942
+ channel: channel5,
5943
+ permissions: model.permissions,
5886
5944
  busy,
5887
5945
  error: credentialError,
5888
5946
  onSubmit: bindCredentials,
@@ -5891,7 +5949,7 @@ function createTokenChannelSettings(definition) {
5891
5949
  setCredentialError(null);
5892
5950
  }
5893
5951
  }) : h2(CredentialBindingPanel, {
5894
- channel: channel4,
5952
+ channel: channel5,
5895
5953
  secretLabel: "Bot Token",
5896
5954
  secretPlaceholder: tokenPlaceholder,
5897
5955
  busy,
@@ -5915,7 +5973,7 @@ function createTokenChannelSettings(definition) {
5915
5973
  "div",
5916
5974
  { className: "ddt-stateLabel dim-stateLabel" },
5917
5975
  h2("span", { className: "ddt-dot dim-stateDot" }),
5918
- h2("span", null, `\u5C1A\u672A\u63A5\u5165 ${channel4} \u673A\u5668\u4EBA`)
5976
+ h2("span", null, `\u5C1A\u672A\u63A5\u5165 ${channel5} \u673A\u5668\u4EBA`)
5919
5977
  ),
5920
5978
  h2("h3", null, emptyTitle),
5921
5979
  h2("p", null, emptyDescription),
@@ -13411,11 +13469,115 @@ function WhatsappSettingsTab({ rpcCall }) {
13411
13469
  )));
13412
13470
  }
13413
13471
 
13472
+ // plugin-src/client/channels/imessage/api.js
13473
+ var IMESSAGE_RPC_CHANNEL = "/imessage";
13474
+ var IMESSAGE_ENDPOINTS = Object.freeze({
13475
+ ...TOKEN_BOT_ENDPOINTS,
13476
+ bindCredentials: "bot.bind-native"
13477
+ });
13478
+ var api4 = createTokenChannelApi("iMessage", " macOS Messages \u8FDE\u63A5");
13479
+ var unwrapRpcResult11 = api4.unwrapRpcResult;
13480
+ var normalizeSnapshot10 = api4.normalizeSnapshot;
13481
+ var presentError11 = api4.presentError;
13482
+
13483
+ // plugin-src/client/channels/imessage/index.js
13484
+ var React23 = __toESM(require("react"), 1);
13485
+
13486
+ // plugin-src/client/channels/imessage/styles.js
13487
+ var IMESSAGE_STYLE_ID = "xmanrui-dsh-im-imessage-settings";
13488
+ var CSS12 = String.raw`
13489
+ .dim-pageIMessage { --ddt-accent: #32a852; --ddt-accent-deep: #248a40; --ddt-accent-wash: #edf9f0; }
13490
+ .dim-avatarIMessage { color: #fff; background: #32a852; }
13491
+ .dim-avatarIMessage svg { display: block; }
13492
+ .dim-imessagePermissionPanel { padding: 20px; }
13493
+ .dim-imessagePermissionPanel p { color: var(--dsw-alias-label-secondary, #646a73); }
13494
+ .dim-imessagePermissionSteps { margin: 16px 0; padding-left: 22px; }
13495
+ .dim-imessagePermissionSteps li { margin: 12px 0; }
13496
+ .dim-imessagePermissionSteps a { color: var(--ddt-accent-deep); }
13497
+ `;
13498
+ function installIMessageStyles() {
13499
+ if (typeof document === "undefined") return () => {
13500
+ };
13501
+ const existing = document.querySelector(`style[data-plugin-css="${IMESSAGE_STYLE_ID}"]`);
13502
+ if (existing) return () => {
13503
+ };
13504
+ const style = document.createElement("style");
13505
+ style.dataset.plugin = "@xmanrui/dsh-im";
13506
+ style.dataset.pluginCss = IMESSAGE_STYLE_ID;
13507
+ style.textContent = CSS12;
13508
+ document.head.appendChild(style);
13509
+ return () => style.remove();
13510
+ }
13511
+
13512
+ // plugin-src/client/channels/imessage/index.js
13513
+ function PermissionPanel({ permissions, busy, error, onSubmit, onCancel }) {
13514
+ const databaseReady = permissions?.database === "granted";
13515
+ const automationReady = permissions?.automation === "granted";
13516
+ return h2(
13517
+ "section",
13518
+ { className: "ddt-card dim-surfaceCard dim-imessagePermissionPanel" },
13519
+ h2("h3", null, "\u542F\u7528 macOS \u539F\u751F iMessage"),
13520
+ h2("p", null, "\u652F\u6301\u540C\u8D26\u53F7\u81EA\u804A\uFF1A\u5728 iPhone \u6216 Mac \u4E0A\u7ED9\u81EA\u5DF1\u5DF2\u767B\u5F55\u7684 iMessage \u90AE\u7BB1\u6216\u53F7\u7801\u53D1\u6307\u4EE4\u3002AI \u56DE\u590D\u4EE5 \u{1F916} DSH \u5F00\u5934\uFF0C\u4E0D\u4F1A\u518D\u6B21\u89E6\u53D1\u673A\u5668\u4EBA\u3002"),
13521
+ h2("p", null, "DeepSeek Harness \u901A\u8FC7 macOS Messages.app \u6536\u53D1\u6587\u672C\u6D88\u606F\u3002\u9996\u6B21\u4F7F\u7528\u9700\u8981\u6388\u4E88\u4EE5\u4E0B\u6743\u9650\uFF1A"),
13522
+ h2(
13523
+ "ol",
13524
+ { className: "dim-imessagePermissionSteps" },
13525
+ h2(
13526
+ "li",
13527
+ null,
13528
+ h2("strong", null, databaseReady ? "\u2713 \u5B8C\u5168\u78C1\u76D8\u8BBF\u95EE\u6743\u9650\u5DF2\u6388\u4E88" : "1. \u6388\u4E88\u5B8C\u5168\u78C1\u76D8\u8BBF\u95EE\u6743\u9650"),
13529
+ databaseReady ? null : h2("p", null, "\u5728\u201C\u7CFB\u7EDF\u8BBE\u7F6E \u2192 \u9690\u79C1\u4E0E\u5B89\u5168\u6027 \u2192 \u5B8C\u5168\u78C1\u76D8\u8BBF\u95EE\u6743\u9650\u201D\u4E2D\uFF0C\u6253\u5F00\u8FD0\u884C DeepSeek Harness \u7684\u7EC8\u7AEF\u6216\u5E94\u7528\u3002"),
13530
+ databaseReady ? null : h2("a", { href: "x-apple.systempreferences:com.apple.preference.security?Privacy_AllFiles" }, "\u6253\u5F00\u5B8C\u5168\u78C1\u76D8\u8BBF\u95EE\u6743\u9650\u8BBE\u7F6E")
13531
+ ),
13532
+ h2(
13533
+ "li",
13534
+ null,
13535
+ h2("strong", null, automationReady ? "\u2713 Messages \u81EA\u52A8\u5316\u6743\u9650\u5DF2\u6388\u4E88" : "2. \u5141\u8BB8\u81EA\u52A8\u5316\u63A7\u5236 Messages"),
13536
+ automationReady ? null : h2("p", null, "\u5728\u201C\u7CFB\u7EDF\u8BBE\u7F6E \u2192 \u9690\u79C1\u4E0E\u5B89\u5168\u6027 \u2192 \u81EA\u52A8\u5316\u201D\u4E2D\uFF0C\u5141\u8BB8\u8FD0\u884C DeepSeek Harness \u7684\u5E94\u7528\u63A7\u5236 Messages\u3002"),
13537
+ automationReady ? null : h2("a", { href: "x-apple.systempreferences:com.apple.preference.security?Privacy_Automation" }, "\u6253\u5F00\u81EA\u52A8\u5316\u8BBE\u7F6E")
13538
+ )
13539
+ ),
13540
+ error ? h2("p", { className: "dim-inlineError", role: "alert" }, error.message ?? String(error)) : null,
13541
+ h2(
13542
+ "div",
13543
+ { className: "ddt-actions dim-viewActions" },
13544
+ h2("button", { type: "button", className: "ddt-button", onClick: onCancel, disabled: busy }, "\u53D6\u6D88"),
13545
+ h2(
13546
+ "button",
13547
+ { type: "button", className: "ddt-button", "data-kind": "primary", onClick: () => onSubmit({}), disabled: busy },
13548
+ busy ? "\u6B63\u5728\u68C0\u67E5\u2026" : "\u68C0\u67E5\u6743\u9650\u5E76\u542F\u7528"
13549
+ )
13550
+ )
13551
+ );
13552
+ }
13553
+ var channel4 = createTokenChannelSettings({
13554
+ channel: "iMessage",
13555
+ endpoints: IMESSAGE_ENDPOINTS,
13556
+ api: api4,
13557
+ LogoGlyph: IMessageLogoGlyph,
13558
+ installStyles: installIMessageStyles,
13559
+ pageClass: "dim-pageIMessage",
13560
+ avatarClass: "dim-avatarIMessage",
13561
+ connectionLabel: " macOS Messages \u8FDE\u63A5",
13562
+ tokenPlaceholder: "",
13563
+ emptyTitle: "\u63A5\u5165 macOS \u539F\u751F iMessage",
13564
+ emptyDescription: "\u65E0\u9700\u5B89\u88C5\u7B2C\u4E09\u65B9\u670D\u52A1\uFF1B\u8BF7\u6309\u6307\u5F15\u6388\u4E88 macOS Messages \u8BBF\u95EE\u6743\u9650\u3002",
13565
+ platformLabel: "macOS Messages",
13566
+ credentialPayload: () => ({}),
13567
+ CredentialPanel: PermissionPanel,
13568
+ credentialAriaLabel: "\u914D\u7F6E macOS Messages \u6743\u9650",
13569
+ credentialOpenLabel: "\u914D\u7F6E\u672C\u673A\u6743\u9650",
13570
+ credentialNoun: "macOS Messages \u6743\u9650",
13571
+ emptyActionLabel: "\u914D\u7F6E\u672C\u673A\u6743\u9650"
13572
+ });
13573
+ var IMessageSettingsTab = channel4.SettingsTab;
13574
+ var IMessageAccountCard = channel4.AccountCard;
13575
+
13414
13576
  // plugin-src/client/delivery-settings.js
13415
- var React25 = __toESM(require("react"), 1);
13577
+ var React26 = __toESM(require("react"), 1);
13416
13578
 
13417
13579
  // plugin-src/client/access-policy-settings.js
13418
- var React23 = __toESM(require("react"), 1);
13580
+ var React24 = __toESM(require("react"), 1);
13419
13581
  var ACCESS_POLICY_ENDPOINT = "bot.access-policy.set";
13420
13582
  var ACCESS_CHANNEL_DEFINITIONS = Object.freeze({
13421
13583
  weixin: Object.freeze({
@@ -13476,6 +13638,11 @@ var ACCESS_CHANNEL_DEFINITIONS = Object.freeze({
13476
13638
  directPlaceholder: "8613800000000 \u6216\u5B8C\u6574 JID",
13477
13639
  groupUserLabel: "\u7FA4\u6210\u5458\u7535\u8BDD\u53F7\u7801\u6216 JID",
13478
13640
  groupPlaceholder: "8613800000000 \u6216\u5B8C\u6574 JID"
13641
+ }),
13642
+ imessage: Object.freeze({
13643
+ directUserLabel: "iMessage Chat GUID",
13644
+ directPlaceholder: "iMessage;+;chat123",
13645
+ groupSupported: false
13479
13646
  })
13480
13647
  });
13481
13648
  function clonePolicy(policy) {
@@ -13496,7 +13663,7 @@ function clonePolicy(policy) {
13496
13663
  group: cloneScope(policy.group)
13497
13664
  };
13498
13665
  }
13499
- function unwrapRpcResult11(result) {
13666
+ function unwrapRpcResult12(result) {
13500
13667
  if (result?.ok === true) return result.value;
13501
13668
  if (result?.ok === false) {
13502
13669
  const error = new Error(result.error?.message || "\u8BBF\u95EE\u8BBE\u7F6E\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
@@ -13523,8 +13690,8 @@ function ScenePolicyEditor({
13523
13690
  unsupported = false,
13524
13691
  onChange
13525
13692
  }) {
13526
- const ownerHelpId = React23.useId();
13527
- const emptyAllowlistHelpId = React23.useId();
13693
+ const ownerHelpId = React24.useId();
13694
+ const emptyAllowlistHelpId = React24.useId();
13528
13695
  const allowlist = policy.mode === "allowlist";
13529
13696
  const collectionKey = allowlist ? "users" : "commandPermissionOverrides";
13530
13697
  const branchKey = allowlist ? "allowlist" : "open";
@@ -13576,7 +13743,7 @@ function ScenePolicyEditor({
13576
13743
  h2("strong", null, "\u5F53\u524D\u6E20\u9053\u4E0D\u652F\u6301\u7FA4\u804A"),
13577
13744
  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")
13578
13745
  ) : h2(
13579
- React23.Fragment,
13746
+ React24.Fragment,
13580
13747
  null,
13581
13748
  h2(
13582
13749
  "div",
@@ -13713,20 +13880,20 @@ function ScenePolicyEditor({
13713
13880
  )
13714
13881
  );
13715
13882
  }
13716
- function AccessPolicySettingsPage({ channel: channel4, account, rpcCall, onSaved }) {
13717
- const definition = ACCESS_CHANNEL_DEFINITIONS[channel4];
13883
+ function AccessPolicySettingsPage({ channel: channel5, account, rpcCall, onSaved }) {
13884
+ const definition = ACCESS_CHANNEL_DEFINITIONS[channel5];
13718
13885
  const initialPolicy = normalizeAccessPolicy(account?.accessPolicy);
13719
13886
  const initialKey = JSON.stringify(initialPolicy);
13720
- const [draft, setDraft] = React23.useState(() => clonePolicy(
13887
+ const [draft, setDraft] = React24.useState(() => clonePolicy(
13721
13888
  initialPolicy ?? DEFAULT_ACCESS_POLICY
13722
13889
  ));
13723
- const [saving, setSaving] = React23.useState(false);
13724
- const [feedback, setFeedback] = React23.useState(null);
13725
- React23.useEffect(() => {
13890
+ const [saving, setSaving] = React24.useState(false);
13891
+ const [feedback, setFeedback] = React24.useState(null);
13892
+ React24.useEffect(() => {
13726
13893
  const next = normalizeAccessPolicy(account?.accessPolicy);
13727
13894
  setDraft(clonePolicy(next ?? DEFAULT_ACCESS_POLICY));
13728
13895
  }, [account?.botId, initialKey]);
13729
- React23.useEffect(() => {
13896
+ React24.useEffect(() => {
13730
13897
  setFeedback(null);
13731
13898
  }, [account?.botId]);
13732
13899
  if (!definition) {
@@ -13743,7 +13910,7 @@ function AccessPolicySettingsPage({ channel: channel4, account, rpcCall, onSaved
13743
13910
  try {
13744
13911
  const policy = validateAccessPolicy(draft);
13745
13912
  if (typeof rpcCall !== "function") throw new Error("\u8BBF\u95EE\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
13746
- const value = unwrapRpcResult11(await rpcCall(ACCESS_POLICY_ENDPOINT, {
13913
+ const value = unwrapRpcResult12(await rpcCall(ACCESS_POLICY_ENDPOINT, {
13747
13914
  botId: account.botId,
13748
13915
  policy
13749
13916
  }));
@@ -13817,7 +13984,7 @@ function AccessPolicySettingsPage({ channel: channel4, account, rpcCall, onSaved
13817
13984
  }
13818
13985
 
13819
13986
  // plugin-src/client/channels/feishu/group-settings.js
13820
- var React24 = __toESM(require("react"), 1);
13987
+ var React25 = __toESM(require("react"), 1);
13821
13988
  var GROUP_MESSAGE_PERMISSION_OPERATION2 = FEISHU_REGISTRATION_OPERATIONS.GROUP_MESSAGE_PERMISSION;
13822
13989
  function SettingsButton({ children, kind = "secondary", className = "", ...props }) {
13823
13990
  return h2("button", {
@@ -13878,9 +14045,9 @@ function GroupResponseModeEditor({
13878
14045
  onAuthorize
13879
14046
  }) {
13880
14047
  const current = normalizeGroupResponseMode(value);
13881
- const [saving, setSaving] = React24.useState(false);
13882
- const [authorizing, setAuthorizing] = React24.useState(false);
13883
- const [error, setError] = React24.useState(null);
14048
+ const [saving, setSaving] = React25.useState(false);
14049
+ const [authorizing, setAuthorizing] = React25.useState(false);
14050
+ const [error, setError] = React25.useState(null);
13884
14051
  const change = async (event) => {
13885
14052
  const next = normalizeGroupResponseMode(event.target.value);
13886
14053
  if (next === current || saving || disabled) return;
@@ -13961,8 +14128,8 @@ function GroupResponseModeEditor({
13961
14128
  }
13962
14129
  function GroupTopicReplyEditor({ value = false, disabled = false, onSave }) {
13963
14130
  const current = value === true ? "on" : "off";
13964
- const [saving, setSaving] = React24.useState(false);
13965
- const [error, setError] = React24.useState(null);
14131
+ const [saving, setSaving] = React25.useState(false);
14132
+ const [error, setError] = React25.useState(null);
13966
14133
  const change = async (event) => {
13967
14134
  const next = event.target.value === "on";
13968
14135
  if ((next ? "on" : "off") === current || saving || disabled) return;
@@ -14149,14 +14316,14 @@ function PermissionFlow({ provision, now, busy, botName, onRetry, onCancel, onCl
14149
14316
  );
14150
14317
  }
14151
14318
  function FeishuGroupSettingsPage({ account, rpcCall }) {
14152
- const [settings, setSettings] = React24.useState(() => groupSettingsFrom(account));
14153
- const [refreshing, setRefreshing] = React24.useState(false);
14154
- const [refreshError, setRefreshError] = React24.useState(null);
14155
- const [provision, setProvision] = React24.useState(null);
14156
- const [provisionBusy, setProvisionBusy] = React24.useState(false);
14157
- const [now, setNow] = React24.useState(() => Date.now());
14158
- const mounted = React24.useRef(true);
14159
- React24.useEffect(() => {
14319
+ const [settings, setSettings] = React25.useState(() => groupSettingsFrom(account));
14320
+ const [refreshing, setRefreshing] = React25.useState(false);
14321
+ const [refreshError, setRefreshError] = React25.useState(null);
14322
+ const [provision, setProvision] = React25.useState(null);
14323
+ const [provisionBusy, setProvisionBusy] = React25.useState(false);
14324
+ const [now, setNow] = React25.useState(() => Date.now());
14325
+ const mounted = React25.useRef(true);
14326
+ React25.useEffect(() => {
14160
14327
  setSettings(groupSettingsFrom(account));
14161
14328
  }, [
14162
14329
  account.botId,
@@ -14164,22 +14331,22 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14164
14331
  account.groupTopicReply,
14165
14332
  account.groupMessagePermissionGranted
14166
14333
  ]);
14167
- React24.useEffect(() => {
14334
+ React25.useEffect(() => {
14168
14335
  mounted.current = true;
14169
14336
  return () => {
14170
14337
  mounted.current = false;
14171
14338
  };
14172
14339
  }, []);
14173
- const invoke = React24.useCallback(async (endpoint, payload = {}, signal) => {
14340
+ const invoke = React25.useCallback(async (endpoint, payload = {}, signal) => {
14174
14341
  if (typeof rpcCall !== "function") throw new Error("\u98DE\u4E66\u7FA4\u804A\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
14175
14342
  return unwrapRpcResult3(await rpcCall(endpoint, payload, signal));
14176
14343
  }, [rpcCall]);
14177
- const applySnapshot = React24.useCallback((value) => {
14344
+ const applySnapshot = React25.useCallback((value) => {
14178
14345
  const result = targetBotFromSnapshot(value, account.botId);
14179
14346
  if (mounted.current) setSettings(groupSettingsFrom(result.bot));
14180
14347
  return result;
14181
14348
  }, [account.botId]);
14182
- const loadSettings = React24.useCallback(async ({ signal, restoreProvisioning = false } = {}) => {
14349
+ const loadSettings = React25.useCallback(async ({ signal, restoreProvisioning = false } = {}) => {
14183
14350
  setRefreshing(true);
14184
14351
  setRefreshError(null);
14185
14352
  try {
@@ -14208,16 +14375,16 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14208
14375
  if (!signal?.aborted && mounted.current) setRefreshing(false);
14209
14376
  }
14210
14377
  }, [account.botId, applySnapshot, invoke]);
14211
- React24.useEffect(() => {
14378
+ React25.useEffect(() => {
14212
14379
  const controller = new AbortController();
14213
14380
  void loadSettings({ signal: controller.signal, restoreProvisioning: true });
14214
14381
  return () => controller.abort();
14215
14382
  }, [loadSettings]);
14216
- const saveSetting = React24.useCallback(async (endpoint, payload) => {
14383
+ const saveSetting = React25.useCallback(async (endpoint, payload) => {
14217
14384
  const value = await invoke(endpoint, { botId: account.botId, ...payload });
14218
14385
  applySnapshot(value);
14219
14386
  }, [account.botId, applySnapshot, invoke]);
14220
- const startAuthorization = React24.useCallback(async ({ replace = false } = {}) => {
14387
+ const startAuthorization = React25.useCallback(async ({ replace = false } = {}) => {
14221
14388
  if (provisionBusy) return;
14222
14389
  const previousAttemptId = provision?.attemptId;
14223
14390
  setProvisionBusy(true);
@@ -14258,13 +14425,13 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14258
14425
  if (mounted.current) setProvisionBusy(false);
14259
14426
  }
14260
14427
  }, [account.botId, invoke, provision?.attemptId, provisionBusy]);
14261
- const finishAuthorization = React24.useCallback(async (signal) => {
14428
+ const finishAuthorization = React25.useCallback(async (signal) => {
14262
14429
  const bot = await loadSettings({ signal, restoreProvisioning: false });
14263
14430
  if (signal?.aborted || !mounted.current) return;
14264
14431
  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");
14265
14432
  setProvision(null);
14266
14433
  }, [loadSettings]);
14267
- React24.useEffect(() => {
14434
+ React25.useEffect(() => {
14268
14435
  if (!provision?.attemptId || !["qr", "connecting"].includes(provision.phase) || provision.expired) return void 0;
14269
14436
  const timerHost = globalThis.window ?? globalThis;
14270
14437
  const controller = new AbortController();
@@ -14308,7 +14475,7 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14308
14475
  timerHost.clearTimeout(timer);
14309
14476
  };
14310
14477
  }, [account.botId, finishAuthorization, invoke, provision]);
14311
- React24.useEffect(() => {
14478
+ React25.useEffect(() => {
14312
14479
  if (!provision?.attemptId || provision.phase !== "qr" || provision.expired) return void 0;
14313
14480
  const timerHost = globalThis.window ?? globalThis;
14314
14481
  const tick = () => {
@@ -14322,7 +14489,7 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14322
14489
  const timer = timerHost.setInterval(tick, 1e3);
14323
14490
  return () => timerHost.clearInterval(timer);
14324
14491
  }, [provision?.attemptId, provision?.expired, provision?.expiresAt, provision?.phase]);
14325
- const cancelAuthorization = React24.useCallback(async () => {
14492
+ const cancelAuthorization = React25.useCallback(async () => {
14326
14493
  if (!provision?.attemptId || provisionBusy) {
14327
14494
  setProvision(null);
14328
14495
  return;
@@ -14433,8 +14600,8 @@ var FEISHU_BOT_SETTINGS_TABS = Object.freeze([
14433
14600
  ...BOT_SETTINGS_TABS,
14434
14601
  Object.freeze({ id: "group", label: "\u7FA4\u804A" })
14435
14602
  ]);
14436
- function botSettingsTabsForChannel(channel4) {
14437
- return channel4 === "feishu" ? FEISHU_BOT_SETTINGS_TABS : BOT_SETTINGS_TABS;
14603
+ function botSettingsTabsForChannel(channel5) {
14604
+ return channel5 === "feishu" ? FEISHU_BOT_SETTINGS_TABS : BOT_SETTINGS_TABS;
14438
14605
  }
14439
14606
  var CHANNEL_DEFINITIONS = Object.freeze({
14440
14607
  weixin: {
@@ -14515,12 +14682,17 @@ var CHANNEL_DEFINITIONS = Object.freeze({
14515
14682
  user: [{ key: "jid", label: "\u7528\u6237 JID", placeholder: "8613800000000@s.whatsapp.net" }],
14516
14683
  group: [{ key: "jid", label: "\u7FA4 JID", placeholder: "1234567890@g.us" }]
14517
14684
  }
14685
+ },
14686
+ imessage: {
14687
+ label: "iMessage",
14688
+ kinds: [{ value: "user", label: "\u79C1\u804A" }],
14689
+ fields: { user: [{ key: "chatGuid", label: "Chat GUID", placeholder: "iMessage;+;chat123" }] }
14518
14690
  }
14519
14691
  });
14520
- function presentError11(error, fallback) {
14692
+ function presentError12(error, fallback) {
14521
14693
  return error?.message || fallback;
14522
14694
  }
14523
- function unwrapRpcResult12(result) {
14695
+ function unwrapRpcResult13(result) {
14524
14696
  if (result?.ok === true) return result.value;
14525
14697
  if (result?.ok === false) {
14526
14698
  const error = new Error(result.error?.message || "\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
@@ -14638,13 +14810,13 @@ function TargetForm({
14638
14810
  }) {
14639
14811
  const editing = mode === "edit";
14640
14812
  const initialKind = initialValue?.kind && definition.fields[initialValue.kind] ? initialValue.kind : definition.kinds[0].value;
14641
- const [targetId, setTargetId] = React25.useState(initialValue?.targetId ?? "");
14642
- const [name2, setName] = React25.useState(initialValue?.name ?? "");
14643
- const [kind, setKind] = React25.useState(initialKind);
14644
- const [route, setRoute] = React25.useState(initialValue?.route ?? {});
14645
- const [error, setError] = React25.useState(null);
14646
- const [testing, setTesting] = React25.useState(false);
14647
- const [testState, setTestState] = React25.useState(null);
14813
+ const [targetId, setTargetId] = React26.useState(initialValue?.targetId ?? "");
14814
+ const [name2, setName] = React26.useState(initialValue?.name ?? "");
14815
+ const [kind, setKind] = React26.useState(initialKind);
14816
+ const [route, setRoute] = React26.useState(initialValue?.route ?? {});
14817
+ const [error, setError] = React26.useState(null);
14818
+ const [testing, setTesting] = React26.useState(false);
14819
+ const [testState, setTestState] = React26.useState(null);
14648
14820
  const currentTarget = () => {
14649
14821
  const normalizedRoute = Object.fromEntries(fieldsFor(definition, kind).map((field) => {
14650
14822
  const raw = String(route[field.key] ?? "").trim();
@@ -14665,7 +14837,7 @@ function TargetForm({
14665
14837
  ...currentTarget()
14666
14838
  });
14667
14839
  } catch (caught) {
14668
- setError(presentError11(caught, "\u76EE\u6807\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u540E\u91CD\u8BD5\u3002"));
14840
+ setError(presentError12(caught, "\u76EE\u6807\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u540E\u91CD\u8BD5\u3002"));
14669
14841
  }
14670
14842
  };
14671
14843
  const testTarget = async () => {
@@ -14677,7 +14849,7 @@ function TargetForm({
14677
14849
  await onTest({ kind: target.kind, route: target.route });
14678
14850
  setTestState({ tone: "success", message: "\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u8BF7\u5230\u76EE\u6807\u4F1A\u8BDD\u786E\u8BA4\u3002" });
14679
14851
  } catch (caught) {
14680
- setTestState({ tone: "error", message: presentError11(caught, "\u6D4B\u8BD5\u53D1\u9001\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002") });
14852
+ setTestState({ tone: "error", message: presentError12(caught, "\u6D4B\u8BD5\u53D1\u9001\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002") });
14681
14853
  } finally {
14682
14854
  setTesting(false);
14683
14855
  }
@@ -14861,7 +15033,7 @@ function TargetSuggestionPicker({
14861
15033
  suggestions.map((suggestion, index) => {
14862
15034
  const identity = routeIdentity(definition, suggestion);
14863
15035
  const added = configured.has(identity);
14864
- return React25.createElement("option", {
15036
+ return React26.createElement("option", {
14865
15037
  key: suggestion.id ?? suggestion.suggestionId ?? `${identity}:${index}`,
14866
15038
  value: String(index),
14867
15039
  disabled: added
@@ -14878,11 +15050,11 @@ function TargetSuggestionPicker({
14878
15050
  );
14879
15051
  }
14880
15052
  function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, onEdit }) {
14881
- const [action, setAction] = React25.useState(null);
14882
- const [testState, setTestState] = React25.useState(null);
14883
- const [syncFeedback, setSyncFeedback] = React25.useState(null);
14884
- const [copyState, setCopyState] = React25.useState(null);
14885
- const [confirmDelete, setConfirmDelete] = React25.useState(false);
15053
+ const [action, setAction] = React26.useState(null);
15054
+ const [testState, setTestState] = React26.useState(null);
15055
+ const [syncFeedback, setSyncFeedback] = React26.useState(null);
15056
+ const [copyState, setCopyState] = React26.useState(null);
15057
+ const [confirmDelete, setConfirmDelete] = React26.useState(false);
14886
15058
  const sessionSync = target.sessionSync ?? { enabled: false, state: "unavailable" };
14887
15059
  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";
14888
15060
  const testTarget = async () => {
@@ -14892,7 +15064,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
14892
15064
  await rpcCall(DELIVERY_ENDPOINTS.test, { botId, targetId: target.targetId });
14893
15065
  setTestState({ tone: "success", message: "\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u8BF7\u5230\u76EE\u6807\u4F1A\u8BDD\u786E\u8BA4\u3002" });
14894
15066
  } catch (error) {
14895
- setTestState({ tone: "error", message: presentError11(error, "\u6D4B\u8BD5\u53D1\u9001\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002") });
15067
+ setTestState({ tone: "error", message: presentError12(error, "\u6D4B\u8BD5\u53D1\u9001\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002") });
14896
15068
  } finally {
14897
15069
  setAction(null);
14898
15070
  }
@@ -14903,7 +15075,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
14903
15075
  await copyText(JSON.stringify({ botId, targetId: target.targetId }));
14904
15076
  setCopyState("\u5DF2\u590D\u5236\u8C03\u7528\u53C2\u6570");
14905
15077
  } catch (error) {
14906
- setCopyState(presentError11(error, "\u590D\u5236\u5931\u8D25\u3002"));
15078
+ setCopyState(presentError12(error, "\u590D\u5236\u5931\u8D25\u3002"));
14907
15079
  }
14908
15080
  };
14909
15081
  const deleteTarget = async () => {
@@ -14912,7 +15084,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
14912
15084
  await rpcCall(DELIVERY_ENDPOINTS.delete, { botId, targetId: target.targetId });
14913
15085
  await onChanged();
14914
15086
  } catch (error) {
14915
- setTestState({ tone: "error", message: presentError11(error, "\u5220\u9664\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002") });
15087
+ setTestState({ tone: "error", message: presentError12(error, "\u5220\u9664\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002") });
14916
15088
  setAction(null);
14917
15089
  setConfirmDelete(false);
14918
15090
  }
@@ -14930,7 +15102,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
14930
15102
  } catch (error) {
14931
15103
  setSyncFeedback({
14932
15104
  tone: "error",
14933
- 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" : presentError11(error, "\u4F1A\u8BDD\u540C\u6B65\u8BBE\u7F6E\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")
15105
+ 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" : presentError12(error, "\u4F1A\u8BDD\u540C\u6B65\u8BBE\u7F6E\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")
14934
15106
  });
14935
15107
  } finally {
14936
15108
  setAction(null);
@@ -14945,7 +15117,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
14945
15117
  h2(
14946
15118
  "div",
14947
15119
  { className: "dim-targetTitle" },
14948
- React25.createElement("strong", null, target.name || target.targetId),
15120
+ React26.createElement("strong", null, target.name || target.targetId),
14949
15121
  h2("span", null, kindLabel(definition, target.kind))
14950
15122
  ),
14951
15123
  h2("code", null, `targetId: ${target.targetId}`)
@@ -15024,33 +15196,33 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
15024
15196
  );
15025
15197
  }
15026
15198
  function DeliveryTargetSettingsPage({
15027
- channel: channel4,
15199
+ channel: channel5,
15028
15200
  account,
15029
15201
  rpcCall,
15030
15202
  accessRpcCall,
15031
15203
  onBack
15032
15204
  }) {
15033
- const definition = CHANNEL_DEFINITIONS[channel4];
15034
- const [activeTabId, setActiveTabId] = React25.useState(BOT_SETTINGS_TABS[0].id);
15035
- const [phase, setPhase] = React25.useState("loading");
15036
- const [targets, setTargets] = React25.useState([]);
15037
- const [suggestionPhase, setSuggestionPhase] = React25.useState("idle");
15038
- const [suggestions, setSuggestions] = React25.useState([]);
15039
- const [suggestionError, setSuggestionError] = React25.useState(null);
15040
- const [error, setError] = React25.useState(null);
15041
- const [editor, setEditor] = React25.useState(null);
15042
- const [saving, setSaving] = React25.useState(false);
15043
- const [botCopyState, setBotCopyState] = React25.useState(null);
15044
- const [accessPolicy, setAccessPolicy] = React25.useState(account.accessPolicy);
15045
- const mounted = React25.useRef(true);
15046
- React25.useEffect(() => {
15205
+ const definition = CHANNEL_DEFINITIONS[channel5];
15206
+ const [activeTabId, setActiveTabId] = React26.useState(BOT_SETTINGS_TABS[0].id);
15207
+ const [phase, setPhase] = React26.useState("loading");
15208
+ const [targets, setTargets] = React26.useState([]);
15209
+ const [suggestionPhase, setSuggestionPhase] = React26.useState("idle");
15210
+ const [suggestions, setSuggestions] = React26.useState([]);
15211
+ const [suggestionError, setSuggestionError] = React26.useState(null);
15212
+ const [error, setError] = React26.useState(null);
15213
+ const [editor, setEditor] = React26.useState(null);
15214
+ const [saving, setSaving] = React26.useState(false);
15215
+ const [botCopyState, setBotCopyState] = React26.useState(null);
15216
+ const [accessPolicy, setAccessPolicy] = React26.useState(account.accessPolicy);
15217
+ const mounted = React26.useRef(true);
15218
+ React26.useEffect(() => {
15047
15219
  setAccessPolicy(account.accessPolicy);
15048
15220
  }, [account.botId, account.accessPolicy]);
15049
- const invoke = React25.useCallback(async (endpoint, payload = {}, signal) => {
15221
+ const invoke = React26.useCallback(async (endpoint, payload = {}, signal) => {
15050
15222
  if (typeof rpcCall !== "function") throw new Error("\u6295\u9012\u76EE\u6807\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
15051
- return unwrapRpcResult12(await rpcCall(endpoint, payload, signal));
15223
+ return unwrapRpcResult13(await rpcCall(endpoint, payload, signal));
15052
15224
  }, [rpcCall]);
15053
- const loadTargets = React25.useCallback(async ({ signal, silent = false } = {}) => {
15225
+ const loadTargets = React26.useCallback(async ({ signal, silent = false } = {}) => {
15054
15226
  if (!silent) setPhase("loading");
15055
15227
  setError(null);
15056
15228
  try {
@@ -15060,11 +15232,11 @@ function DeliveryTargetSettingsPage({
15060
15232
  setPhase("ready");
15061
15233
  } catch (caught) {
15062
15234
  if (signal?.aborted || caught?.name === "AbortError" || !mounted.current) return;
15063
- setError(presentError11(caught, "\u65E0\u6CD5\u8BFB\u53D6\u6295\u9012\u76EE\u6807\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
15235
+ setError(presentError12(caught, "\u65E0\u6CD5\u8BFB\u53D6\u6295\u9012\u76EE\u6807\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
15064
15236
  setPhase("error");
15065
15237
  }
15066
15238
  }, [account.botId, invoke]);
15067
- const loadSuggestions = React25.useCallback(async () => {
15239
+ const loadSuggestions = React26.useCallback(async () => {
15068
15240
  setSuggestionPhase("loading");
15069
15241
  setSuggestionError(null);
15070
15242
  try {
@@ -15074,11 +15246,11 @@ function DeliveryTargetSettingsPage({
15074
15246
  setSuggestionPhase("ready");
15075
15247
  } catch (caught) {
15076
15248
  if (caught?.name === "AbortError" || !mounted.current) return;
15077
- setSuggestionError(presentError11(caught, "\u65E0\u6CD5\u8BFB\u53D6\u5DF2\u804A\u4F1A\u8BDD\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
15249
+ setSuggestionError(presentError12(caught, "\u65E0\u6CD5\u8BFB\u53D6\u5DF2\u804A\u4F1A\u8BDD\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
15078
15250
  setSuggestionPhase("error");
15079
15251
  }
15080
15252
  }, [account.botId, definition, invoke]);
15081
- React25.useEffect(() => {
15253
+ React26.useEffect(() => {
15082
15254
  mounted.current = true;
15083
15255
  const controller = new AbortController();
15084
15256
  void loadTargets({ signal: controller.signal });
@@ -15146,10 +15318,10 @@ function DeliveryTargetSettingsPage({
15146
15318
  await copyText(account.botId);
15147
15319
  setBotCopyState("\u5DF2\u590D\u5236 Bot ID");
15148
15320
  } catch (caught) {
15149
- setBotCopyState(presentError11(caught, "\u590D\u5236\u5931\u8D25\u3002"));
15321
+ setBotCopyState(presentError12(caught, "\u590D\u5236\u5931\u8D25\u3002"));
15150
15322
  }
15151
15323
  };
15152
- const settingsTabs = botSettingsTabsForChannel(channel4);
15324
+ const settingsTabs = botSettingsTabsForChannel(channel5);
15153
15325
  const activeTab = settingsTabs.find((tab) => tab.id === activeTabId) ?? settingsTabs[0];
15154
15326
  const activeTabDomId = `dim-bot-settings-${activeTab.id}-tab`;
15155
15327
  const activePanelId = `dim-bot-settings-${activeTab.id}-panel`;
@@ -15192,15 +15364,15 @@ function DeliveryTargetSettingsPage({
15192
15364
  "aria-labelledby": activeTabDomId
15193
15365
  },
15194
15366
  activeTab.id === "access" ? h2(AccessPolicySettingsPage, {
15195
- channel: channel4,
15367
+ channel: channel5,
15196
15368
  account: { ...account, accessPolicy },
15197
15369
  rpcCall: accessRpcCall,
15198
15370
  onSaved: setAccessPolicy
15199
- }) : activeTab.id === "group" && channel4 === "feishu" ? h2(FeishuGroupSettingsPage, {
15371
+ }) : activeTab.id === "group" && channel5 === "feishu" ? h2(FeishuGroupSettingsPage, {
15200
15372
  account,
15201
15373
  rpcCall: accessRpcCall
15202
15374
  }) : h2(
15203
- React25.Fragment,
15375
+ React26.Fragment,
15204
15376
  null,
15205
15377
  h2(
15206
15378
  "section",
@@ -15311,7 +15483,7 @@ function DeliveryTargetSettingsPage({
15311
15483
  }
15312
15484
 
15313
15485
  // plugin-src/client/global-settings.js
15314
- var React26 = __toESM(require("react"), 1);
15486
+ var React27 = __toESM(require("react"), 1);
15315
15487
 
15316
15488
  // src/channels/shared/inbound-ttl.mjs
15317
15489
  var DEFAULT_INBOUND_TTL_HOURS = 168;
@@ -15340,10 +15512,10 @@ var GLOBAL_SETTINGS_ENDPOINTS = Object.freeze({
15340
15512
  setTtl: "settings.inbound-ttl.set",
15341
15513
  sweep: "settings.inbound-ttl.sweep"
15342
15514
  });
15343
- function presentError12(error, fallback) {
15515
+ function presentError13(error, fallback) {
15344
15516
  return error?.message || fallback;
15345
15517
  }
15346
- function unwrapRpcResult13(result) {
15518
+ function unwrapRpcResult14(result) {
15347
15519
  if (result?.ok === true) return result.value;
15348
15520
  if (result?.ok === false) {
15349
15521
  const error = new Error(result.error?.message || "\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
@@ -15373,29 +15545,29 @@ function GlobalButton({ children, kind = "secondary", className = "", ...props }
15373
15545
  }, children);
15374
15546
  }
15375
15547
  function GlobalSettingsPanel({ rpcCall }) {
15376
- const [phase, setPhase] = React26.useState("loading");
15377
- const [loadError, setLoadError] = React26.useState(null);
15378
- const [ttlInput, setTtlInput] = React26.useState("");
15379
- const [savedTtl, setSavedTtl] = React26.useState(null);
15380
- const [ttlError, setTtlError] = React26.useState(false);
15381
- const [saveError, setSaveError] = React26.useState(null);
15382
- const [saveSucceeded, setSaveSucceeded] = React26.useState(false);
15383
- const [isSaving, setIsSaving] = React26.useState(false);
15384
- const [sweepConfirming, setSweepConfirming] = React26.useState(false);
15385
- const [sweeping, setSweeping] = React26.useState(false);
15386
- const ttlErrorId = React26.useId();
15387
- const ttlHintsId = React26.useId();
15388
- const sweepTriggerId = React26.useId();
15389
- const sweepConfirmId = React26.useId();
15390
- const sweepConfirmTextId = React26.useId();
15391
- const sweepConfirmButtonId = React26.useId();
15392
- const mounted = React26.useRef(true);
15393
- const saving = React26.useRef(false);
15394
- const invoke = React26.useCallback(async (endpoint, payload = {}, signal) => {
15548
+ const [phase, setPhase] = React27.useState("loading");
15549
+ const [loadError, setLoadError] = React27.useState(null);
15550
+ const [ttlInput, setTtlInput] = React27.useState("");
15551
+ const [savedTtl, setSavedTtl] = React27.useState(null);
15552
+ const [ttlError, setTtlError] = React27.useState(false);
15553
+ const [saveError, setSaveError] = React27.useState(null);
15554
+ const [saveSucceeded, setSaveSucceeded] = React27.useState(false);
15555
+ const [isSaving, setIsSaving] = React27.useState(false);
15556
+ const [sweepConfirming, setSweepConfirming] = React27.useState(false);
15557
+ const [sweeping, setSweeping] = React27.useState(false);
15558
+ const ttlErrorId = React27.useId();
15559
+ const ttlHintsId = React27.useId();
15560
+ const sweepTriggerId = React27.useId();
15561
+ const sweepConfirmId = React27.useId();
15562
+ const sweepConfirmTextId = React27.useId();
15563
+ const sweepConfirmButtonId = React27.useId();
15564
+ const mounted = React27.useRef(true);
15565
+ const saving = React27.useRef(false);
15566
+ const invoke = React27.useCallback(async (endpoint, payload = {}, signal) => {
15395
15567
  if (typeof rpcCall !== "function") throw new Error("\u901A\u7528\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
15396
- return unwrapRpcResult13(await rpcCall(endpoint, payload, signal));
15568
+ return unwrapRpcResult14(await rpcCall(endpoint, payload, signal));
15397
15569
  }, [rpcCall]);
15398
- const loadSettings = React26.useCallback(async ({ signal } = {}) => {
15570
+ const loadSettings = React27.useCallback(async ({ signal } = {}) => {
15399
15571
  setPhase("loading");
15400
15572
  setLoadError(null);
15401
15573
  try {
@@ -15415,11 +15587,11 @@ function GlobalSettingsPanel({ rpcCall }) {
15415
15587
  setPhase("ready");
15416
15588
  } catch (caught) {
15417
15589
  if (signal?.aborted || caught?.name === "AbortError" || !mounted.current) return;
15418
- setLoadError(presentError12(caught, "\u65E0\u6CD5\u8BFB\u53D6\u901A\u7528\u8BBE\u7F6E\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
15590
+ setLoadError(presentError13(caught, "\u65E0\u6CD5\u8BFB\u53D6\u901A\u7528\u8BBE\u7F6E\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
15419
15591
  setPhase("error");
15420
15592
  }
15421
15593
  }, [invoke]);
15422
- React26.useEffect(() => {
15594
+ React27.useEffect(() => {
15423
15595
  mounted.current = true;
15424
15596
  const controller = new AbortController();
15425
15597
  void loadSettings({ signal: controller.signal });
@@ -15428,7 +15600,7 @@ function GlobalSettingsPanel({ rpcCall }) {
15428
15600
  controller.abort();
15429
15601
  };
15430
15602
  }, [loadSettings]);
15431
- React26.useEffect(() => {
15603
+ React27.useEffect(() => {
15432
15604
  if (!sweepConfirming) return;
15433
15605
  globalThis.document?.getElementById(sweepConfirmButtonId)?.focus();
15434
15606
  }, [sweepConfirmButtonId, sweepConfirming]);
@@ -15459,7 +15631,7 @@ function GlobalSettingsPanel({ rpcCall }) {
15459
15631
  setPhase("ready");
15460
15632
  } catch (caught) {
15461
15633
  if (mounted.current) {
15462
- setSaveError(presentError12(caught, "\u8BBE\u7F6E\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
15634
+ setSaveError(presentError13(caught, "\u8BBE\u7F6E\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
15463
15635
  }
15464
15636
  } finally {
15465
15637
  saving.current = false;
@@ -15735,7 +15907,7 @@ function replacePageLocation(url, location = globalThis.location) {
15735
15907
 
15736
15908
  // plugin-src/client/styles.js
15737
15909
  var IM_STYLE_ID = "xmanrui-dsh-im-settings";
15738
- var CSS12 = String.raw`
15910
+ var CSS13 = String.raw`
15739
15911
  .dim-page {
15740
15912
  --dim-blue: var(--dsw-alias-state-business-primary, #3370ff);
15741
15913
  --dim-blue-soft: color-mix(in srgb, var(--dim-blue) 9%, transparent);
@@ -15832,6 +16004,7 @@ var CSS12 = String.raw`
15832
16004
  .dim-logoSlack { color: white; background: #4a154b; }
15833
16005
  .dim-logoSlack svg { width: 21px; height: 21px; }
15834
16006
  .dim-logoWhatsapp { color: white; background: #25d366; }
16007
+ .dim-logoIMessage { color: white; background: #32a852; }
15835
16008
  .dim-logoWhatsapp svg { width: 21px; height: 21px; }
15836
16009
  .dim-channelCopy { min-width: 0; display: grid; }
15837
16010
  .dim-channelCopy strong { overflow: hidden; color: inherit; font-size: 14px; line-height: 20px; font-weight: 680; text-overflow: ellipsis; white-space: nowrap; }
@@ -16408,7 +16581,7 @@ function installImStyles() {
16408
16581
  const style = document.createElement("style");
16409
16582
  style.dataset.plugin = "@xmanrui/dsh-im";
16410
16583
  style.dataset.pluginCss = IM_STYLE_ID;
16411
- style.textContent = CSS12;
16584
+ style.textContent = CSS13;
16412
16585
  document.head.appendChild(style);
16413
16586
  return () => style.remove();
16414
16587
  }
@@ -16424,15 +16597,16 @@ var SESSION_CHANNEL_LABELS = Object.freeze(Object.fromEntries(Object.entries({
16424
16597
  telegram: ["Telegram", "Telegram"],
16425
16598
  discord: ["Discord", "Discord"],
16426
16599
  whatsapp: ["WhatsApp", "WhatsApp"],
16600
+ imessage: ["iMessage", "iMessage"],
16427
16601
  office: ["AI Office", "AI Office"]
16428
- }).map(([channel4, labels]) => [channel4, Object.freeze(labels)])));
16602
+ }).map(([channel5, labels]) => [channel5, Object.freeze(labels)])));
16429
16603
  function parseSessionChannelTitle(title) {
16430
16604
  if (typeof title !== "string") return null;
16431
- for (const [channel4, labels] of Object.entries(SESSION_CHANNEL_LABELS)) {
16605
+ for (const [channel5, labels] of Object.entries(SESSION_CHANNEL_LABELS)) {
16432
16606
  for (const label of labels) {
16433
16607
  const prefix = `${label} \xB7 `;
16434
16608
  if (title.startsWith(prefix) && title.slice(prefix.length).trim()) {
16435
- return { channel: channel4, title: title.slice(prefix.length) };
16609
+ return { channel: channel5, title: title.slice(prefix.length) };
16436
16610
  }
16437
16611
  }
16438
16612
  }
@@ -16450,6 +16624,7 @@ var GLYPHS = Object.freeze({
16450
16624
  telegram: [TelegramLogoGlyph, "#229ed9"],
16451
16625
  discord: [DiscordLogoGlyph, "#5865f2"],
16452
16626
  whatsapp: [WhatsappLogoGlyph, "#25d366"],
16627
+ imessage: [IMessageLogoGlyph, "#3478f6"],
16453
16628
  office: [OfficeLogoGlyph, "#f97316"]
16454
16629
  });
16455
16630
  var CHANNEL_ATTR = "data-dsh-im-session-channel";
@@ -16473,8 +16648,8 @@ function titleOf(row) {
16473
16648
  }
16474
16649
  return title?.childNodes.length === 1 && title.firstChild.nodeType === 3 ? title : null;
16475
16650
  }
16476
- function logoUri(document2, channel4) {
16477
- const [Glyph, color] = GLYPHS[channel4];
16651
+ function logoUri(document2, channel5) {
16652
+ const [Glyph, color] = GLYPHS[channel5];
16478
16653
  const render = (node) => {
16479
16654
  if (!["svg", "path"].includes(node.type)) throw new Error("Unsupported channel logo element");
16480
16655
  const element = document2.createElementNS(SVG_NS, node.type);
@@ -16501,7 +16676,7 @@ function createInstallation(document2) {
16501
16676
  let scheduled = false;
16502
16677
  const style = document2.createElement("style");
16503
16678
  style.dataset.pluginCss = "dsh-im-session-channel-logos";
16504
- const uris = Object.fromEntries(Object.keys(GLYPHS).map((channel4) => [channel4, logoUri(document2, channel4)]));
16679
+ const uris = Object.fromEntries(Object.keys(GLYPHS).map((channel5) => [channel5, logoUri(document2, channel5)]));
16505
16680
  style.textContent = `
16506
16681
  ${MARKED}[${TITLE_ATTR}] {
16507
16682
  position: relative;
@@ -16533,7 +16708,7 @@ ${MARKED}[${TITLE_ATTR}]::after {
16533
16708
  text-overflow: ellipsis;
16534
16709
  pointer-events: none;
16535
16710
  }
16536
- ${Object.entries(uris).map(([channel4, uri]) => `[${CHANNEL_ATTR}="${channel4}"] { --dsh-im-session-logo: url("${uri}"); }`).join("\n")}
16711
+ ${Object.entries(uris).map(([channel5, uri]) => `[${CHANNEL_ATTR}="${channel5}"] { --dsh-im-session-logo: url("${uri}"); }`).join("\n")}
16537
16712
  `;
16538
16713
  document2.head.appendChild(style);
16539
16714
  const restore = (title) => {
@@ -16616,12 +16791,12 @@ ${Object.entries(uris).map(([channel4, uri]) => `[${CHANNEL_ATTR}="${channel4}"]
16616
16791
  attributes: true,
16617
16792
  attributeFilter: ["class", "role", "aria-selected", "contenteditable"]
16618
16793
  });
16619
- for (const [channel4, uri] of Object.entries(uris)) {
16794
+ for (const [channel5, uri] of Object.entries(uris)) {
16620
16795
  const image = new view.Image();
16621
16796
  images.push(image);
16622
16797
  image.onload = () => {
16623
16798
  if (closed) return;
16624
- ready.add(channel4);
16799
+ ready.add(channel5);
16625
16800
  collect(document2.body, true);
16626
16801
  };
16627
16802
  image.src = uri;
@@ -16662,7 +16837,7 @@ function installSessionChannelLogos(document2 = globalThis.document) {
16662
16837
  }
16663
16838
 
16664
16839
  // plugin-src/client/update-panel.js
16665
- var React27 = __toESM(require("react"), 1);
16840
+ var React28 = __toESM(require("react"), 1);
16666
16841
  var import_react_dom3 = require("react-dom");
16667
16842
  var import_valid = __toESM(require_valid(), 1);
16668
16843
  var import_rcompare = __toESM(require_rcompare(), 1);
@@ -16709,7 +16884,7 @@ function unwrapSnapshot(result) {
16709
16884
  }
16710
16885
  return value;
16711
16886
  }
16712
- function presentError13(error) {
16887
+ function presentError14(error) {
16713
16888
  const code = error?.rpcError?.code ?? error?.code ?? "";
16714
16889
  const message = error?.rpcError?.message ?? error?.message ?? "";
16715
16890
  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)) {
@@ -16752,11 +16927,11 @@ function manualUpdateCommand(snapshot) {
16752
16927
  return `dsh plugin --profile ${profileArgument} add -w @xmanrui/dsh-im@${version}`;
16753
16928
  }
16754
16929
  function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
16755
- const [copyState, setCopyState] = React27.useState("idle");
16756
- const commandRef = React27.useRef(null);
16757
- const mounted = React27.useRef(false);
16758
- const copying = React27.useRef(false);
16759
- React27.useEffect(() => {
16930
+ const [copyState, setCopyState] = React28.useState("idle");
16931
+ const commandRef = React28.useRef(null);
16932
+ const mounted = React28.useRef(false);
16933
+ const copying = React28.useRef(false);
16934
+ React28.useEffect(() => {
16760
16935
  mounted.current = true;
16761
16936
  return () => {
16762
16937
  mounted.current = false;
@@ -16788,7 +16963,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
16788
16963
  { className: "dim-updateManual", "aria-label": "\u624B\u5DE5\u66F4\u65B0" },
16789
16964
  h2("h4", { className: "dim-updateManualHeading" }, "\u624B\u5DE5\u66F4\u65B0"),
16790
16965
  command ? h2(
16791
- React27.Fragment,
16966
+ React28.Fragment,
16792
16967
  null,
16793
16968
  h2("p", { className: "dim-updateManualHint" }, "\u81EA\u52A8\u66F4\u65B0\u5931\u8D25\u53EF\u4EE5\u4F7F\u7528\u547D\u4EE4\u66F4\u65B0\uFF1A"),
16794
16969
  h2(
@@ -16824,7 +16999,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
16824
16999
  "aria-hidden": "true",
16825
17000
  focusable: "false"
16826
17001
  }, copyState === "copied" ? h2("path", { d: "m4 10 4 4 8-8" }) : h2(
16827
- React27.Fragment,
17002
+ React28.Fragment,
16828
17003
  null,
16829
17004
  h2("rect", { x: 7, y: 7, width: 10, height: 11, rx: 1.5 }),
16830
17005
  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" })
@@ -16849,10 +17024,10 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
16849
17024
  );
16850
17025
  }
16851
17026
  function UpdateDialog({ children, onClose }) {
16852
- const dialogRef = React27.useRef(null);
16853
- const titleId = React27.useId();
16854
- const descriptionId = React27.useId();
16855
- React27.useEffect(() => {
17027
+ const dialogRef = React28.useRef(null);
17028
+ const titleId = React28.useId();
17029
+ const descriptionId = React28.useId();
17030
+ React28.useEffect(() => {
16856
17031
  const previous = globalThis.document?.activeElement;
16857
17032
  dialogRef.current?.focus?.();
16858
17033
  return () => {
@@ -16910,19 +17085,19 @@ function UpdateDialog({ children, onClose }) {
16910
17085
  return typeof document !== "undefined" && document.body ? (0, import_react_dom3.createPortal)(content, document.body) : content;
16911
17086
  }
16912
17087
  function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
16913
- const [snapshot, setSnapshot] = React27.useState(null);
16914
- const [action, setAction] = React27.useState("status");
16915
- const [error, setError] = React27.useState(null);
16916
- const [open, setOpen] = React27.useState(false);
16917
- const [uncertainInstall, setUncertainInstall] = React27.useState(false);
16918
- const mounted = React27.useRef(false);
16919
- const busy = React27.useRef(false);
16920
- const readController = React27.useRef(null);
16921
- const pollReadController = React27.useRef(null);
16922
- const installRequest = React27.useRef(null);
16923
- const onStatusRef = React27.useRef(onStatus);
17088
+ const [snapshot, setSnapshot] = React28.useState(null);
17089
+ const [action, setAction] = React28.useState("status");
17090
+ const [error, setError] = React28.useState(null);
17091
+ const [open, setOpen] = React28.useState(false);
17092
+ const [uncertainInstall, setUncertainInstall] = React28.useState(false);
17093
+ const mounted = React28.useRef(false);
17094
+ const busy = React28.useRef(false);
17095
+ const readController = React28.useRef(null);
17096
+ const pollReadController = React28.useRef(null);
17097
+ const installRequest = React28.useRef(null);
17098
+ const onStatusRef = React28.useRef(onStatus);
16924
17099
  onStatusRef.current = onStatus;
16925
- const accept = React27.useCallback((next) => {
17100
+ const accept = React28.useCallback((next) => {
16926
17101
  setSnapshot(next);
16927
17102
  onStatusRef.current?.(next);
16928
17103
  }, []);
@@ -16931,7 +17106,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
16931
17106
  setUncertainInstall(false);
16932
17107
  accept(next);
16933
17108
  };
16934
- const invoke = React27.useCallback(async (endpoint, payload = {}, signal) => {
17109
+ const invoke = React28.useCallback(async (endpoint, payload = {}, signal) => {
16935
17110
  if (typeof rpcCall !== "function") {
16936
17111
  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");
16937
17112
  unavailable.code = "update-unavailable";
@@ -16939,14 +17114,14 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
16939
17114
  }
16940
17115
  return unwrapSnapshot(await rpcCall(endpoint, payload, signal));
16941
17116
  }, [rpcCall]);
16942
- React27.useEffect(() => {
17117
+ React28.useEffect(() => {
16943
17118
  mounted.current = true;
16944
17119
  busy.current = true;
16945
17120
  const controller = new AbortController();
16946
17121
  void invoke("update.status", {}, controller.signal).then((next) => {
16947
17122
  if (!controller.signal.aborted) accept(next);
16948
17123
  }).catch((cause) => {
16949
- if (!controller.signal.aborted) setError(presentError13(cause));
17124
+ if (!controller.signal.aborted) setError(presentError14(cause));
16950
17125
  }).finally(() => {
16951
17126
  if (!controller.signal.aborted) {
16952
17127
  busy.current = false;
@@ -16962,7 +17137,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
16962
17137
  const activeJob = ACTIVE_STATES4.has(snapshot?.job?.state);
16963
17138
  const restartRequired = snapshot?.job?.state === "restart-required" || snapshot?.blockedReason === "pending-restart";
16964
17139
  const shouldPoll = activeJob || uncertainInstall;
16965
- React27.useEffect(() => {
17140
+ React28.useEffect(() => {
16966
17141
  if (!shouldPoll) return void 0;
16967
17142
  let controller;
16968
17143
  const scheduler = createPollScheduler({
@@ -16983,7 +17158,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
16983
17158
  keepPolling = ACTIVE_STATES4.has(next.job?.state);
16984
17159
  }
16985
17160
  } catch (cause) {
16986
- if (!pendingController.signal.aborted) setError(presentError13(cause));
17161
+ if (!pendingController.signal.aborted) setError(presentError14(cause));
16987
17162
  } finally {
16988
17163
  if (pollReadController.current === pendingController) pollReadController.current = null;
16989
17164
  }
@@ -17014,7 +17189,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17014
17189
  else acceptAuthoritative(next);
17015
17190
  }
17016
17191
  } catch (cause) {
17017
- if (!controller.signal.aborted && mounted.current) setError(presentError13(cause));
17192
+ if (!controller.signal.aborted && mounted.current) setError(presentError14(cause));
17018
17193
  } finally {
17019
17194
  if (!controller.signal.aborted && mounted.current) {
17020
17195
  busy.current = false;
@@ -17040,7 +17215,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17040
17215
  if (mounted.current) acceptAuthoritative(next);
17041
17216
  } catch (cause) {
17042
17217
  if (mounted.current) {
17043
- setError(presentError13(cause));
17218
+ setError(presentError14(cause));
17044
17219
  setUncertainInstall(true);
17045
17220
  }
17046
17221
  } finally {
@@ -17060,7 +17235,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17060
17235
  const manualCommand = manualUpdateCommand(snapshot);
17061
17236
  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";
17062
17237
  return h2(
17063
- React27.Fragment,
17238
+ React28.Fragment,
17064
17239
  null,
17065
17240
  h2("button", {
17066
17241
  type: "button",
@@ -17085,13 +17260,13 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17085
17260
  h2("dt", null, "\u8FD0\u884C\u7248\u672C"),
17086
17261
  h2("dd", null, `v${snapshot?.runningVersion ?? clientVersion}`),
17087
17262
  snapshot?.installedVersion && snapshot.installedVersion !== snapshot.runningVersion ? h2(
17088
- React27.Fragment,
17263
+ React28.Fragment,
17089
17264
  null,
17090
17265
  h2("dt", null, "\u5DF2\u5B89\u88C5\u7248\u672C"),
17091
17266
  h2("dd", null, `v${snapshot.installedVersion}`)
17092
17267
  ) : null,
17093
17268
  targetVersion ? h2(
17094
- React27.Fragment,
17269
+ React28.Fragment,
17095
17270
  null,
17096
17271
  h2("dt", null, "\u76EE\u6807\u7248\u672C"),
17097
17272
  h2("dd", null, `v${targetVersion}`)
@@ -17182,6 +17357,7 @@ var CHANNELS = Object.freeze([
17182
17357
  { id: "discord", label: "Discord" },
17183
17358
  { id: "whatsapp", label: "WhatsApp" },
17184
17359
  { id: "wecomApp", label: "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528", note: "\uFF08\u5B9E\u9A8C\u529F\u80FD\uFF09" },
17360
+ { id: "imessage", label: "iMessage", note: "\uFF08\u5B9E\u9A8C\u529F\u80FD\uFF09" },
17185
17361
  { id: "office", label: "AI Office", note: "\uFF08\u5B9E\u9A8C\u529F\u80FD\uFF09" }
17186
17362
  ]);
17187
17363
  function WeixinLogo() {
@@ -17242,6 +17418,13 @@ function WhatsappLogo() {
17242
17418
  h2(WhatsappLogoGlyph)
17243
17419
  );
17244
17420
  }
17421
+ function IMessageLogo() {
17422
+ return h2(
17423
+ "span",
17424
+ { className: "dim-logo dim-logoIMessage", "aria-hidden": "true" },
17425
+ h2(IMessageLogoGlyph)
17426
+ );
17427
+ }
17245
17428
  function OfficeLogo() {
17246
17429
  return h2(
17247
17430
  "span",
@@ -17249,17 +17432,18 @@ function OfficeLogo() {
17249
17432
  h2(OfficeLogoGlyph)
17250
17433
  );
17251
17434
  }
17252
- function ChannelLogo({ channel: channel4 }) {
17253
- if (channel4 === "weixin") return h2(WeixinLogo);
17254
- if (channel4 === "feishu") return h2(FeishuLogo);
17255
- if (channel4 === "dingtalk") return h2(DingtalkLogo);
17256
- if (channel4 === "wecom") return h2(WecomLogo);
17257
- if (channel4 === "wecomApp") return h2(WecomAppLogo);
17258
- if (channel4 === "qq") return h2(QqLogo);
17259
- if (channel4 === "slack") return h2(SlackLogo);
17260
- if (channel4 === "telegram") return h2(TelegramLogo);
17261
- if (channel4 === "discord") return h2(DiscordLogo);
17262
- if (channel4 === "whatsapp") return h2(WhatsappLogo);
17435
+ function ChannelLogo({ channel: channel5 }) {
17436
+ if (channel5 === "weixin") return h2(WeixinLogo);
17437
+ if (channel5 === "feishu") return h2(FeishuLogo);
17438
+ if (channel5 === "dingtalk") return h2(DingtalkLogo);
17439
+ if (channel5 === "wecom") return h2(WecomLogo);
17440
+ if (channel5 === "wecomApp") return h2(WecomAppLogo);
17441
+ if (channel5 === "qq") return h2(QqLogo);
17442
+ if (channel5 === "slack") return h2(SlackLogo);
17443
+ if (channel5 === "telegram") return h2(TelegramLogo);
17444
+ if (channel5 === "discord") return h2(DiscordLogo);
17445
+ if (channel5 === "whatsapp") return h2(WhatsappLogo);
17446
+ if (channel5 === "imessage") return h2(IMessageLogo);
17263
17447
  return h2(OfficeLogo);
17264
17448
  }
17265
17449
  function LoopbackRecoveryNotice({ recovery, onNavigate = replacePageLocation }) {
@@ -17287,6 +17471,7 @@ function IMSettingsTab({
17287
17471
  dingtalkRpcCall,
17288
17472
  discordRpcCall,
17289
17473
  feishuRpcCall,
17474
+ imessageRpcCall,
17290
17475
  qqRpcCall,
17291
17476
  slackRpcCall,
17292
17477
  telegramRpcCall,
@@ -17302,23 +17487,23 @@ function IMSettingsTab({
17302
17487
  browserLocation = globalThis.location,
17303
17488
  navigateToRecoveryUrl = replacePageLocation
17304
17489
  }) {
17305
- const [selected, setSelected] = React28.useState("weixin");
17306
- const [loopbackRecovery, setLoopbackRecovery] = React28.useState(null);
17307
- const [runningVersion, setRunningVersion] = React28.useState(IM_PLUGIN_VERSION);
17308
- const [deliverySettings, setDeliverySettings] = React28.useState(null);
17309
- const githubTooltipId = React28.useId();
17310
- const generalSettingsTooltipId = React28.useId();
17490
+ const [selected, setSelected] = React29.useState("weixin");
17491
+ const [loopbackRecovery, setLoopbackRecovery] = React29.useState(null);
17492
+ const [runningVersion, setRunningVersion] = React29.useState(IM_PLUGIN_VERSION);
17493
+ const [deliverySettings, setDeliverySettings] = React29.useState(null);
17494
+ const githubTooltipId = React29.useId();
17495
+ const generalSettingsTooltipId = React29.useId();
17311
17496
  const globalSettingsSelected = selected === GLOBAL_SETTINGS_TAB_ID;
17312
- const active = CHANNELS.find((channel4) => channel4.id === selected) ?? CHANNELS[0];
17497
+ const active = CHANNELS.find((channel5) => channel5.id === selected) ?? CHANNELS[0];
17313
17498
  const activeTabId = globalSettingsSelected ? "dim-general-settings-trigger" : `dim-tab-${active.id}`;
17314
17499
  const activePanelId = globalSettingsSelected ? `dim-panel-${GLOBAL_SETTINGS_TAB_ID}` : `dim-panel-${active.id}`;
17315
- const reportLoopbackRecovery = React28.useCallback((recovery) => {
17500
+ const reportLoopbackRecovery = React29.useCallback((recovery) => {
17316
17501
  setLoopbackRecovery((current) => current?.url === recovery.url ? current : recovery);
17317
17502
  }, []);
17318
- const reportUpdateStatus = React28.useCallback((snapshot) => {
17503
+ const reportUpdateStatus = React29.useCallback((snapshot) => {
17319
17504
  setRunningVersion(snapshot.runningVersion);
17320
17505
  }, []);
17321
- const rpcCalls = React28.useMemo(() => createLoopbackAwareRpcCalls({
17506
+ const rpcCalls = React29.useMemo(() => createLoopbackAwareRpcCalls({
17322
17507
  dingtalkRpcCall,
17323
17508
  discordRpcCall,
17324
17509
  feishuRpcCall,
@@ -17332,7 +17517,8 @@ function IMSettingsTab({
17332
17517
  officeRpcCall,
17333
17518
  updateRpcCall,
17334
17519
  deliveryRpcCall,
17335
- globalSettingsRpcCall
17520
+ globalSettingsRpcCall,
17521
+ imessageRpcCall
17336
17522
  }, {
17337
17523
  location: browserLocation,
17338
17524
  onRecovery: reportLoopbackRecovery
@@ -17343,6 +17529,7 @@ function IMSettingsTab({
17343
17529
  deliveryRpcCall,
17344
17530
  feishuRpcCall,
17345
17531
  globalSettingsRpcCall,
17532
+ imessageRpcCall,
17346
17533
  officeRpcCall,
17347
17534
  qqRpcCall,
17348
17535
  reportLoopbackRecovery,
@@ -17354,7 +17541,7 @@ function IMSettingsTab({
17354
17541
  weixinRpcCall,
17355
17542
  whatsappRpcCall
17356
17543
  ]);
17357
- const botSettingsContext = React28.useMemo(() => Object.freeze({
17544
+ const botSettingsContext = React29.useMemo(() => Object.freeze({
17358
17545
  openBotSettings: setDeliverySettings
17359
17546
  }), []);
17360
17547
  return h2(
@@ -17437,27 +17624,27 @@ function IMSettingsTab({
17437
17624
  h2(
17438
17625
  "nav",
17439
17626
  { className: "dim-rail", role: "tablist", "aria-label": "IM \u8BBE\u7F6E\u5BFC\u822A" },
17440
- CHANNELS.map((channel4) => h2(
17627
+ CHANNELS.map((channel5) => h2(
17441
17628
  "button",
17442
17629
  {
17443
- key: channel4.id,
17630
+ key: channel5.id,
17444
17631
  type: "button",
17445
17632
  role: "tab",
17446
- id: `dim-tab-${channel4.id}`,
17633
+ id: `dim-tab-${channel5.id}`,
17447
17634
  className: "dim-channel",
17448
- "aria-selected": !globalSettingsSelected && channel4.id === active.id,
17449
- "aria-controls": `dim-panel-${channel4.id}`,
17635
+ "aria-selected": !globalSettingsSelected && channel5.id === active.id,
17636
+ "aria-controls": `dim-panel-${channel5.id}`,
17450
17637
  onClick: () => {
17451
- setSelected(channel4.id);
17638
+ setSelected(channel5.id);
17452
17639
  setDeliverySettings(null);
17453
17640
  }
17454
17641
  },
17455
- h2(ChannelLogo, { channel: channel4.id }),
17642
+ h2(ChannelLogo, { channel: channel5.id }),
17456
17643
  h2(
17457
17644
  "span",
17458
17645
  { className: "dim-channelCopy" },
17459
- h2("strong", null, channel4.label),
17460
- channel4.note ? h2("small", { className: "dim-channelNote" }, channel4.note) : null
17646
+ h2("strong", null, channel5.label),
17647
+ channel5.note ? h2("small", { className: "dim-channelNote" }, channel5.note) : null
17461
17648
  )
17462
17649
  ))
17463
17650
  ),
@@ -17483,7 +17670,7 @@ function IMSettingsTab({
17483
17670
  rpcCall: rpcCalls.deliveryRpcCall,
17484
17671
  accessRpcCall: rpcCalls[`${active.id}RpcCall`],
17485
17672
  onBack: () => setDeliverySettings(null)
17486
- }) : 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 }) : h2(OfficeSettingsTab, { rpcCall: rpcCalls.officeRpcCall })
17673
+ }) : 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 }) : h2(OfficeSettingsTab, { rpcCall: rpcCalls.officeRpcCall })
17487
17674
  )
17488
17675
  )
17489
17676
  )
@@ -17509,6 +17696,7 @@ function apply(ctx) {
17509
17696
  installTelegramStyles(),
17510
17697
  installDiscordStyles(),
17511
17698
  installWhatsappStyles(),
17699
+ installIMessageStyles(),
17512
17700
  installOfficeStyles(),
17513
17701
  installImStyles()
17514
17702
  ];
@@ -17516,20 +17704,21 @@ function apply(ctx) {
17516
17704
  for (const dispose of disposers.reverse()) dispose();
17517
17705
  };
17518
17706
  }, "im-settings: install combined channel styles");
17519
- const feishuRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(FEISHU_RPC_CHANNEL, endpoint, payload, signal);
17520
- const weixinRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(WEIXIN_RPC_CHANNEL, endpoint, payload, signal);
17521
- const dingtalkRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(DINGTALK_RPC_CHANNEL, endpoint, payload, signal);
17522
- const qqRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(QQ_RPC_CHANNEL, endpoint, payload, signal);
17523
- const wecomRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(WECOM_RPC_CHANNEL, endpoint, payload, signal);
17524
- const wecomAppRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(WECOM_APP_RPC_CHANNEL, endpoint, payload, signal);
17525
- const telegramRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(TELEGRAM_RPC_CHANNEL, endpoint, payload, signal);
17526
- const discordRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(DISCORD_RPC_CHANNEL, endpoint, payload, signal);
17527
- const whatsappRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(WHATSAPP_RPC_CHANNEL, endpoint, payload, signal);
17528
- const slackRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(SLACK_RPC_CHANNEL, endpoint, payload, signal);
17529
- const officeRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(OFFICE_RPC_CHANNEL, endpoint, payload, signal);
17530
- const updateRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(UPDATE_RPC_CHANNEL, endpoint, payload, signal);
17531
- const deliveryRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(DELIVERY_RPC_CHANNEL, endpoint, payload, signal);
17532
- const globalSettingsRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(GLOBAL_SETTINGS_RPC_CHANNEL, endpoint, payload, signal);
17707
+ const feishuRpcCall = (endpoint, payload, signal) => callManagementRpc(ctx.connection, FEISHU_RPC_CHANNEL, endpoint, payload, signal);
17708
+ const weixinRpcCall = (endpoint, payload, signal) => callManagementRpc(ctx.connection, WEIXIN_RPC_CHANNEL, endpoint, payload, signal);
17709
+ const dingtalkRpcCall = (endpoint, payload, signal) => callManagementRpc(ctx.connection, DINGTALK_RPC_CHANNEL, endpoint, payload, signal);
17710
+ const qqRpcCall = (endpoint, payload, signal) => callManagementRpc(ctx.connection, QQ_RPC_CHANNEL, endpoint, payload, signal);
17711
+ const wecomRpcCall = (endpoint, payload, signal) => callManagementRpc(ctx.connection, WECOM_RPC_CHANNEL, endpoint, payload, signal);
17712
+ const wecomAppRpcCall = (endpoint, payload, signal) => callManagementRpc(ctx.connection, WECOM_APP_RPC_CHANNEL, endpoint, payload, signal);
17713
+ const telegramRpcCall = (endpoint, payload, signal) => callManagementRpc(ctx.connection, TELEGRAM_RPC_CHANNEL, endpoint, payload, signal);
17714
+ const discordRpcCall = (endpoint, payload, signal) => callManagementRpc(ctx.connection, DISCORD_RPC_CHANNEL, endpoint, payload, signal);
17715
+ const whatsappRpcCall = (endpoint, payload, signal) => callManagementRpc(ctx.connection, WHATSAPP_RPC_CHANNEL, endpoint, payload, signal);
17716
+ const imessageRpcCall = (endpoint, payload, signal) => callManagementRpc(ctx.connection, IMESSAGE_RPC_CHANNEL, endpoint, payload, signal);
17717
+ const slackRpcCall = (endpoint, payload, signal) => callManagementRpc(ctx.connection, SLACK_RPC_CHANNEL, endpoint, payload, signal);
17718
+ const officeRpcCall = (endpoint, payload, signal) => callManagementRpc(ctx.connection, OFFICE_RPC_CHANNEL, endpoint, payload, signal);
17719
+ const updateRpcCall = (endpoint, payload, signal) => callManagementRpc(ctx.connection, UPDATE_RPC_CHANNEL, endpoint, payload, signal);
17720
+ const deliveryRpcCall = (endpoint, payload, signal) => callManagementRpc(ctx.connection, DELIVERY_RPC_CHANNEL, endpoint, payload, signal);
17721
+ const globalSettingsRpcCall = (endpoint, payload, signal) => callManagementRpc(ctx.connection, GLOBAL_SETTINGS_RPC_CHANNEL, endpoint, payload, signal);
17533
17722
  const workspaceDirectoryPicker = Object.freeze({
17534
17723
  listDirectory: (path, signal) => callWorkspaceDirectoryApi(ctx, "listDirectory", path, signal),
17535
17724
  pickDirectory: () => callWorkspaceDirectoryApi(ctx, "pickDirectory")
@@ -17551,6 +17740,7 @@ function apply(ctx) {
17551
17740
  wecomAppRpcCall,
17552
17741
  weixinRpcCall,
17553
17742
  whatsappRpcCall,
17743
+ imessageRpcCall,
17554
17744
  officeRpcCall,
17555
17745
  updateRpcCall,
17556
17746
  deliveryRpcCall,