@xmanrui/dsh-im 4.19.2 → 4.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.en.md +78 -0
  2. package/README.md +78 -0
  3. package/lib/client.js +594 -217
  4. package/lib/index.js +279 -276
  5. package/package.json +9 -1
  6. package/plugin-src/client/channels/weixin/api.js +35 -17
  7. package/plugin-src/client/channels/weixin/connection-error.js +68 -0
  8. package/plugin-src/client/channels/weixin/index.js +36 -12
  9. package/plugin-src/client/i18n.js +2 -0
  10. package/plugin-src/host/channels/shared/startup.mjs +7 -4
  11. package/plugin-src/host/channels/weixin/connection-supervisor.mjs +13 -1
  12. package/plugin-src/host/channels/weixin/index.mjs +12 -3
  13. package/plugin-src/host/channels/weixin/production.mjs +53 -3
  14. package/plugin-src/host/channels/weixin/rpc.mjs +22 -17
  15. package/src/channels/dingtalk/dingtalk-bridge.mjs +4 -1
  16. package/src/channels/dingtalk/dingtalk-menu.mjs +8 -4
  17. package/src/channels/feishu/bridge.mjs +44 -13
  18. package/src/channels/qq/qq-bridge.mjs +12 -4
  19. package/src/channels/qq/qq-menu.mjs +11 -8
  20. package/src/channels/shared/bot-workspace-store.mjs +532 -40
  21. package/src/channels/shared/command-catalog.mjs +5 -0
  22. package/src/channels/shared/compact-command.mjs +14 -4
  23. package/src/channels/shared/control-command.mjs +1 -1
  24. package/src/channels/shared/deferred-delivery-coordinator.mjs +1 -1
  25. package/src/channels/shared/history-command.mjs +1 -1
  26. package/src/channels/shared/i18n-en/shared-a.mjs +41 -0
  27. package/src/channels/shared/i18n-en/weixin.mjs +2 -0
  28. package/src/channels/shared/model-command.mjs +5 -3
  29. package/src/channels/shared/workspace-command.mjs +114 -9
  30. package/src/channels/shared/workspace-session.mjs +55 -5
  31. package/src/channels/telegram/telegram-runtime.mjs +1 -1
  32. package/src/channels/wecom/wecom-bridge.mjs +2 -2
  33. package/src/channels/weixin/connection-error.en.mjs +116 -0
  34. package/src/channels/weixin/connection-error.mjs +204 -0
  35. package/src/channels/weixin/diagnostic-details.mjs +40 -0
  36. package/src/channels/weixin/state-store.mjs +4 -3
  37. package/src/channels/weixin/weixin-api.mjs +20 -8
  38. package/src/channels/weixin/weixin-bridge.mjs +3 -2
  39. package/src/channels/weixin/weixin-controller.mjs +133 -104
  40. package/src/channels/weixin/weixin-runtime.mjs +35 -24
package/lib/client.js CHANGED
@@ -577,12 +577,12 @@ function callManagementRpc(connection, channel5, method, payload, signal) {
577
577
  }
578
578
 
579
579
  // plugin-src/client/index.js
580
- var React30 = __toESM(require("react"), 1);
580
+ var React31 = __toESM(require("react"), 1);
581
581
 
582
582
  // package.json
583
583
  var package_default = {
584
584
  name: "@xmanrui/dsh-im",
585
- version: "4.19.2",
585
+ version: "4.20.0",
586
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.",
587
587
  keywords: [
588
588
  "deepseek-harness",
@@ -638,6 +638,14 @@ var package_default = {
638
638
  {
639
639
  name: "grloper",
640
640
  url: "https://github.com/grloper"
641
+ },
642
+ {
643
+ name: "baijian",
644
+ url: "https://github.com/baijian"
645
+ },
646
+ {
647
+ name: "lyzhu86",
648
+ url: "https://github.com/lyzhu86"
641
649
  }
642
650
  ],
643
651
  license: "MIT",
@@ -915,10 +923,128 @@ function normalizeBotAlias(bot) {
915
923
  // plugin-src/client/agent-preset.js
916
924
  var React3 = __toESM(require("react"), 1);
917
925
 
926
+ // src/channels/weixin/connection-error.en.mjs
927
+ var connection_error_en_default = {
928
+ "\u63D2\u4EF6\u7248\u672C": "Plugin version",
929
+ "DSH \u5FAE\u4FE1\u7BA1\u7406\u63A5\u53E3\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94\uFF0C\u8BF7\u91CD\u65B0\u8BFB\u53D6\u72B6\u6001\u3002": "The DSH WeChat management endpoint returned an invalid response. Refresh the status.",
930
+ "\u65E0\u6CD5\u8BFB\u53D6\u73B0\u6709\u767B\u5F55\u51ED\u636E\u3002\u8BF7\u68C0\u67E5 DSH \u51ED\u636E\u5B58\u50A8\u3002": "Could not read the saved login credential. Check the DSH credential store.",
931
+ "\u767B\u5F55\u51ED\u636E\u65E0\u6CD5\u5199\u5165 DSH \u51ED\u636E\u5B58\u50A8\u3002\u8BF7\u68C0\u67E5\u51ED\u636E\u5B58\u50A8\u662F\u5426\u53EF\u5199\u3002": "Could not save the login credential to DSH. Check whether the credential store is writable.",
932
+ "\u8D26\u53F7\u914D\u7F6E\u65E0\u6CD5\u5199\u5165\u672C\u673A\u3002\u8BF7\u68C0\u67E5 DSH_HOME \u76EE\u5F55\u6743\u9650\u3002": "Could not save the account configuration. Check permissions on DSH_HOME.",
933
+ "\u65E0\u6CD5\u521D\u59CB\u5316\u8D26\u53F7\u72B6\u6001\u6216\u5DE5\u4F5C\u533A\u3002\u8BF7\u68C0\u67E5 DSH_HOME \u548C\u5DE5\u4F5C\u533A\u76EE\u5F55\u3002": "Could not prepare the account state or workspace. Check DSH_HOME and the workspace directory.",
934
+ "\u63D2\u4EF6\u65E0\u6CD5\u8FDE\u63A5\u5F53\u524D Harness\uFF0C\u8BF7\u68C0\u67E5\u5BBF\u4E3B\u662F\u5426\u5DF2\u5C31\u7EEA\u3002": "The plugin could not connect to this Harness. Check whether the host is ready.",
935
+ "Harness \u5065\u5EB7\u68C0\u67E5\u8D85\u65F6\u3002\u8BF7\u786E\u8BA4 dsh web \u672A\u963B\u585E\u3002": "The Harness health check timed out. Check whether the host is responsive.",
936
+ "Harness \u5065\u5EB7\u68C0\u67E5\u9700\u8981\u8EAB\u4EFD\u8BA4\u8BC1\u3002\u8BF7\u68C0\u67E5\u4EE3\u7406\u3001\u7F51\u5173\u6216\u81EA\u5B9A\u4E49\u9274\u6743\u914D\u7F6E\u3002": "The Harness health check requires authentication. Check proxy, gateway or custom authentication settings.",
937
+ "\u672C\u673A Harness \u8BF7\u6C42\u88AB\u4EE3\u7406\u8981\u6C42\u8BA4\u8BC1\u3002\u8BF7\u8BA9\u56DE\u73AF\u5730\u5740\u7ED5\u8FC7\u4EE3\u7406\uFF0C\u5E76\u68C0\u67E5 NO_PROXY \u914D\u7F6E\u3002": "The proxy requires authentication for the local Harness request. Bypass the proxy for loopback addresses and check NO_PROXY.",
938
+ "Harness \u5F02\u5E38\u62D2\u7EDD\u4E86\u56DE\u73AF\u5730\u5740\u7684\u5065\u5EB7\u68C0\u67E5\u3002\u8BF7\u68C0\u67E5 HTTP \u4EE3\u7406\u3001Harness \u6E90\u7801\u7248\u672C\u548C\u6784\u5EFA\u4EA7\u7269\u3002": "Harness rejected a loopback health check. Check the HTTP proxy and the running Harness build.",
939
+ "Harness \u7684 Host \u4FE1\u4EFB\u68C0\u67E5\u62D2\u7EDD\u4E86\u975E\u56DE\u73AF\u5730\u5740\u8BF7\u6C42\u3002\u8BF7\u68C0\u67E5 harnessBaseUrl \u4E0E trustedHosts \u914D\u7F6E\u3002": "Harness rejected the non-loopback Host. Check harnessBaseUrl and trustedHosts.",
940
+ "\u5065\u5EB7\u68C0\u67E5\u6536\u5230\u4E86\u975E Harness \u6807\u51C6\u7684 403 \u62D2\u7EDD\u54CD\u5E94\u3002\u8BF7\u68C0\u67E5\u4EE3\u7406\u6216\u7F51\u5173\u914D\u7F6E\u3002": "The health check received a non-standard HTTP 403 response. Check proxy or gateway settings.",
941
+ "\u627E\u4E0D\u5230 Harness \u5065\u5EB7\u68C0\u67E5\u63A5\u53E3\u3002\u8BF7\u786E\u8BA4 Harness \u4E0E\u63D2\u4EF6\u7248\u672C\u517C\u5BB9\u3002": "The Harness health check endpoint was not found. Check Harness and plugin compatibility.",
942
+ "Harness \u5065\u5EB7\u68C0\u67E5\u8FD4\u56DE\u670D\u52A1\u9519\u8BEF\u3002\u8BF7\u67E5\u770B DSH \u65E5\u5FD7\u3002": "The Harness health check returned a service error. Check the DSH logs.",
943
+ "Harness \u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94\u3002\u8BF7\u786E\u8BA4 Harness \u4E0E\u63D2\u4EF6\u7248\u672C\u517C\u5BB9\u3002": "Harness returned an unrecognized response. Check Harness and plugin compatibility.",
944
+ "Harness \u62D2\u7EDD\u4E86\u5065\u5EB7\u68C0\u67E5\u8BF7\u6C42\u3002\u8BF7\u67E5\u770B DSH \u65E5\u5FD7\u3002": "Harness rejected the health check. Check the DSH logs.",
945
+ "Harness \u5065\u5EB7\u68C0\u67E5\u53D1\u751F\u672A\u77E5\u9519\u8BEF\u3002\u8BF7\u67E5\u770B DSH \u65E5\u5FD7\u3002": "The Harness health check failed with an unknown error. Check the DSH logs.",
946
+ "\u6D88\u606F\u8FDE\u63A5\u521D\u59CB\u5316\u5931\u8D25\u3002\u8BF7\u67E5\u770B DSH \u65E5\u5FD7\u540E\u91CD\u8BD5\u3002": "The message connection could not start. Check the DSH logs and retry.",
947
+ "\u6682\u65F6\u65E0\u6CD5\u8BBF\u95EE\u5FAE\u4FE1\u670D\u52A1\u3002": "The WeChat service is temporarily unreachable.",
948
+ "\u5FAE\u4FE1\u670D\u52A1\u8BF7\u6C42\u8D85\u65F6\u3002": "The WeChat service request timed out.",
949
+ "\u5FAE\u4FE1\u670D\u52A1\u8BF7\u6C42\u5931\u8D25\uFF08HTTP {status}\uFF09\u3002": "The WeChat service request failed (HTTP {status}).",
950
+ "\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u89E3\u6790\u7684\u54CD\u5E94\u3002": "The WeChat service returned an unparseable response.",
951
+ "\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u4E8C\u7EF4\u7801\u3002": "The WeChat service did not return a valid QR code.",
952
+ "\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u53D7\u4FE1\u4EFB\u7684\u626B\u7801\u5730\u5740\u3002": "The WeChat service returned an untrusted QR-code URL.",
953
+ "\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6548\u7684\u8FDE\u63A5\u5730\u5740\u3002": "The WeChat service returned an invalid connection URL.",
954
+ "\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u53D7\u4FE1\u4EFB\u7684\u8FDE\u63A5\u5730\u5740\u3002": "The WeChat service returned an untrusted connection URL.",
955
+ "\u62D2\u7EDD\u8BBF\u95EE\u4E0D\u53D7\u4FE1\u4EFB\u7684\u5FAE\u4FE1\u670D\u52A1\u5730\u5740\u3002": "Refusing to access an untrusted WeChat service URL.",
956
+ "\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u626B\u7801\u72B6\u6001\u3002": "The WeChat service returned an unrecognized QR-code status.",
957
+ "\u5FAE\u4FE1\u6388\u6743\u6210\u529F\uFF0C\u4F46\u8FD4\u56DE\u7684\u8D26\u53F7\u51ED\u636E\u4E0D\u5B8C\u6574\u3002": "WeChat authorized the account but returned incomplete credentials.",
958
+ "\u5FAE\u4FE1\u670D\u52A1\u62D2\u7EDD\u4E86\u4E8C\u7EF4\u7801\u7533\u8BF7\u3002": "The WeChat service rejected the QR-code request.",
959
+ "\u5DF2\u53D6\u5F97\u626B\u7801\u5730\u5740\uFF0C\u4F46\u672C\u673A\u4E8C\u7EF4\u7801\u56FE\u7247\u751F\u6210\u5931\u8D25\u3002": "The login URL was obtained, but the QR-code image could not be generated locally.",
960
+ "\u65E0\u6CD5\u751F\u6210\u5FAE\u4FE1\u4E8C\u7EF4\u7801\u3002": "Could not generate a WeChat QR code.",
961
+ "\u8FD9\u6B21\u5FAE\u4FE1\u7ED1\u5B9A\u4EFB\u52A1\u5DF2\u4E0D\u5B58\u5728\uFF0C\u8BF7\u91CD\u65B0\u8BFB\u53D6\u72B6\u6001\u6216\u751F\u6210\u4E8C\u7EF4\u7801\u3002": "This WeChat setup attempt no longer exists. Refresh the status or generate a new QR code.",
962
+ "\u8FD9\u6B21\u5FAE\u4FE1\u7ED1\u5B9A\u4EFB\u52A1\u5F53\u524D\u4E0D\u80FD\u63D0\u4EA4\u914D\u5BF9\u7801\uFF0C\u8BF7\u91CD\u65B0\u8BFB\u53D6\u72B6\u6001\u3002": "This setup attempt is not waiting for a pairing code. Refresh the status.",
963
+ "\u767B\u5F55\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u79FB\u9664\u8D26\u53F7\u540E\u91CD\u65B0\u626B\u7801\u3002": "The login credential is missing. Remove the account and scan a new QR code.",
964
+ "\u5FAE\u4FE1\u767B\u5F55\u51ED\u636E\u5DF2\u5931\u6548\uFF0C\u8BF7\u79FB\u9664\u8D26\u53F7\u540E\u91CD\u65B0\u626B\u7801\u3002": "The WeChat login credential has expired. Remove the account and scan a new QR code.",
965
+ "\u65E0\u6CD5\u4ECE DSH \u51ED\u636E\u5B58\u50A8\u79FB\u9664\u5FAE\u4FE1\u767B\u5F55\u51ED\u636E\u3002": "Could not remove the WeChat login credential from the DSH credential store.",
966
+ "\u5FAE\u4FE1\u8D26\u53F7\u914D\u7F6E\u79FB\u9664\u5931\u8D25\u3002": "Could not remove the WeChat account configuration.",
967
+ "\u65E0\u6CD5\u8BFB\u53D6\u5FAE\u4FE1\u8D26\u53F7\u72B6\u6001\u6587\u4EF6\u3002": "Could not read the WeChat account state file.",
968
+ "\u65E0\u6CD5\u4FDD\u5B58\u5FAE\u4FE1\u8D26\u53F7\u72B6\u6001\u6587\u4EF6\u3002": "Could not save the WeChat account state file.",
969
+ "\u5FAE\u4FE1\u8D26\u53F7\u5DF2\u79FB\u9664\uFF0C\u4F46\u672C\u673A\u72B6\u6001\u6587\u4EF6\u6E05\u7406\u5931\u8D25\u3002": "The WeChat account was removed, but its local state file could not be cleaned up.",
970
+ "\u65E0\u6CD5\u4FDD\u5B58\u5FAE\u4FE1\u5DE5\u4F5C\u533A\u8BBE\u7F6E\u3002": "Could not save the WeChat workspace settings.",
971
+ "\u5FAE\u4FE1\u8D26\u53F7\u5DF2\u79FB\u9664\uFF0C\u4F46\u5DE5\u4F5C\u533A\u8BBE\u7F6E\u6E05\u7406\u5931\u8D25\u3002": "The WeChat account was removed, but its workspace settings could not be cleaned up.",
972
+ "\u5FAE\u4FE1\u8D26\u53F7\u8FDE\u63A5\u542F\u52A8\u5931\u8D25\u3002": "The WeChat account connection could not start.",
973
+ "\u5FAE\u4FE1\u6D88\u606F\u540C\u6B65\u8BF7\u6C42\u88AB\u62D2\u7EDD\u3002": "WeChat rejected the message sync request.",
974
+ "\u5FAE\u4FE1\u670D\u52A1\u672A\u786E\u8BA4\u505C\u6B62\u901A\u77E5\u3002": "WeChat did not confirm the stop notification.",
975
+ "\u5FAE\u4FE1\u6D88\u606F\u8FDE\u63A5\u505C\u6B62\u65F6\u53D1\u751F\u9519\u8BEF\u3002": "An error occurred while stopping the WeChat connection.",
976
+ "\u65E0\u6CD5\u8BFB\u53D6\u5FAE\u4FE1\u8FDE\u63A5\u72B6\u6001\uFF0C\u8BF7\u91CD\u65B0\u8BFB\u53D6\uFF1B\u4E4B\u524D\u7684\u64CD\u4F5C\u53EF\u80FD\u5DF2\u5B8C\u6210\u3002": "Could not read the WeChat connection status. Refresh it; the previous operation may have completed.",
977
+ "\u5FAE\u4FE1\u6FC0\u6D3B\u8FC7\u7A0B\u4E2D\u53D1\u751F\u672A\u77E5\u9519\u8BEF\u3002": "An unknown error occurred while activating the WeChat account.",
978
+ "\u5FAE\u4FE1\u64CD\u4F5C\u53D1\u751F\u672A\u77E5\u9519\u8BEF\u3002": "The WeChat operation failed with an unknown error.",
979
+ "\u5FAE\u4FE1\u914D\u7F6E\u683C\u5F0F\u9519\u8BEF\uFF0C\u8BF7\u68C0\u67E5 config.json \u548C workspaces.json \u540E\u91CD\u542F DSH\u3002": "The WeChat configuration is invalid. Check config.json and workspaces.json, then restart DSH.",
980
+ "\u5FAE\u4FE1\u914D\u7F6E\u8BBF\u95EE\u6743\u9650\u4E0D\u8DB3\uFF0C\u8BF7\u68C0\u67E5\u6570\u636E\u76EE\u5F55\u6743\u9650\u540E\u91CD\u542F DSH\u3002": "The WeChat configuration could not be accessed. Check the data directory permissions and restart DSH.",
981
+ "\u5FAE\u4FE1\u521D\u59CB\u5316\u5931\u8D25\uFF0C\u8BF7\u67E5\u770B DSH \u542F\u52A8\u65E5\u5FD7\u3002": "WeChat initialization failed. Check the DSH startup logs.",
982
+ "\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA\u3002": "The WeChat connection is not ready.",
983
+ "\u5FAE\u4FE1\u64CD\u4F5C\u5931\u8D25\u540E\uFF0C\u539F\u8D26\u53F7\u72B6\u6001\u6062\u590D\u5931\u8D25\u3002": "The previous account state could not be restored after the failed WeChat operation.",
984
+ "\u539F\u8D26\u53F7\u72B6\u6001\u5C1A\u672A\u786E\u8BA4\uFF0C\u8BF7\u91CD\u65B0\u8BFB\u53D6\u72B6\u6001\uFF0C\u5E76\u53CD\u9988\u8BCA\u65AD\u4FE1\u606F\u3002": "The previous account state has not been confirmed. Refresh the status and share the diagnostic information.",
985
+ "\u64CD\u4F5C\u672A\u5B8C\u6210\uFF0C\u5DF2\u6062\u590D\u4E4B\u524D\u7684\u672C\u673A\u72B6\u6001\u3002\u8BF7\u5904\u7406\u4E0A\u8FF0\u95EE\u9898\u540E\u91CD\u8BD5\u3002": "The operation did not complete. The previous local state was restored. Resolve the problem above before retrying.",
986
+ "\u51ED\u636E\u7531\u53EA\u8BFB\u6765\u6E90\u63D0\u4F9B\uFF0C\u8BF7\u5728\u542F\u52A8 DSH \u7684\u914D\u7F6E\u4E2D\u68C0\u67E5\u8BE5\u6765\u6E90\u3002": "The credential comes from a read-only source. Check that source in the configuration used to launch DSH.",
987
+ "\u5FAE\u4FE1\u670D\u52A1\u57DF\u540D\u89E3\u6790\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u8FD0\u884C DSH \u7684\u673A\u5668\u7684\u7F51\u7EDC\u548C DNS \u8BBE\u7F6E\u540E\u91CD\u8BD5\u3002": "The WeChat service domain could not be resolved. Check the network and DNS settings on the machine running DSH and retry.",
988
+ "\u8BF7\u68C0\u67E5 DSH \u6570\u636E\u76EE\u5F55\u548C\u5BF9\u5E94\u6587\u4EF6\u7684\u8BFB\u5199\u6743\u9650\u3002": "Check read and write permissions on the DSH data directory and the affected file.",
989
+ "\u78C1\u76D8\u7A7A\u95F4\u4E0D\u8DB3\uFF0C\u8BF7\u91CA\u653E\u7A7A\u95F4\u540E\u91CD\u8BD5\u3002": "The disk is full. Free up space and retry.",
990
+ "\u672C\u673A\u6587\u4EF6\u683C\u5F0F\u65E0\u6548\uFF0C\u8BF7\u68C0\u67E5\u5BF9\u5E94\u914D\u7F6E\u6216\u72B6\u6001\u6587\u4EF6\uFF1B\u4E0D\u8981\u6E05\u7A7A\u767B\u5F55\u51ED\u636E\u3002": "The local file format is invalid. Check the affected configuration or state file; do not clear login credentials.",
991
+ "\u8BF7\u68C0\u67E5\u8FD0\u884C DSH \u7684\u673A\u5668\u7684\u7CFB\u7EDF\u65F6\u95F4\u3001\u8BC1\u4E66\u548C\u7F51\u7EDC\u8BBE\u7F6E\u3002": "Check the system time, certificates and network settings on the machine running DSH.",
992
+ "\u8BF7\u79FB\u9664\u5931\u6548\u63A5\u5165\u5E76\u91CD\u65B0\u626B\u7801\u7ED1\u5B9A\u3002": "Remove the invalid connection and scan a new QR code to connect.",
993
+ "\u8BF7\u786E\u8BA4\u5F53\u524D DSH \u5BBF\u4E3B\u5DF2\u5C31\u7EEA\uFF0C\u5E76\u68C0\u67E5 Harness \u4E0E\u63D2\u4EF6\u5B9E\u9645\u8FD0\u884C\u7248\u672C\u53CA\u5BBF\u4E3B\u65E5\u5FD7\u3002": "Check that this DSH host is ready, and check the running Harness and plugin versions and the host logs.",
994
+ "\u5FAE\u4FE1\u670D\u52A1\u9650\u6D41\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002": "The WeChat service is rate-limiting requests. Try again later.",
995
+ "\u8BBF\u95EE\u88AB\u62D2\u7EDD\uFF0C\u8BF7\u68C0\u67E5\u670D\u52A1\u8BBF\u95EE\u9650\u5236\uFF1BHTTP \u72B6\u6001\u672C\u8EAB\u4E0D\u80FD\u786E\u8BA4\u767B\u5F55\u51ED\u636E\u5DF2\u5931\u6548\u3002": "Access was denied. Check service access restrictions; the HTTP status alone does not establish that the login credential expired.",
996
+ "\u8BF7\u68C0\u67E5\u8FD0\u884C DSH \u7684\u673A\u5668\u80FD\u5426\u8BBF\u95EE\u5FAE\u4FE1\u670D\u52A1\uFF0C\u7136\u540E\u91CD\u8BD5\u3002": "Check whether the machine running DSH can access the WeChat service, then retry.",
997
+ "\u8BF7\u6309\u53C2\u8003\u53F7\u67E5\u770B DSH \u65E5\u5FD7\uFF0C\u5E76\u590D\u5236\u8BCA\u65AD\u4FE1\u606F\u53CD\u9988\u3002": "Find this reference in the DSH logs and copy the diagnostic information when reporting the issue.",
998
+ "\u65E0\u6CD5\u5B8C\u6210\u5FAE\u4FE1\u7BA1\u7406\u8BF7\u6C42\uFF0C\u8BF7\u68C0\u67E5 DSH \u8FDE\u63A5\u540E\u91CD\u65B0\u8BFB\u53D6\u72B6\u6001\u3002": "The WeChat management request could not be completed. Check the DSH connection and refresh the status.",
999
+ "\u67E5\u8BE2\u5FAE\u4FE1\u626B\u7801\u72B6\u6001\u5931\u8D25": "Could not query WeChat QR-code status",
1000
+ "\u65E0\u6CD5\u5B8C\u6210\u5FAE\u4FE1\u7BA1\u7406\u8BF7\u6C42": "Could not complete the WeChat management request",
1001
+ "\u65E0\u6CD5\u751F\u6210\u5FAE\u4FE1\u4E8C\u7EF4\u7801": "Could not generate a WeChat QR code",
1002
+ "\u72B6\u6001\u8BFB\u53D6\u5931\u8D25\uFF0C\u4EE5\u4E0B\u662F\u4E0A\u6B21\u8BFB\u53D6\u7684\u72B6\u6001\u3002": "Status refresh failed. The last known status is shown below.",
1003
+ "\u8BCA\u65AD\u8BE6\u60C5": "Diagnostic details",
1004
+ "\u8BCA\u65AD\u4FE1\u606F": "Diagnostic information",
1005
+ "\u590D\u5236\u8BCA\u65AD\u4FE1\u606F": "Copy diagnostic information",
1006
+ "\u8BCA\u65AD\u4FE1\u606F\u5DF2\u590D\u5236": "Diagnostic information copied",
1007
+ "\u672A\u53D6\u5F97 Host \u8BCA\u65AD\u53C2\u8003\u53F7\u3002": "No diagnostic reference was received from the host.",
1008
+ "\u65E0\u6CD5\u8BBF\u95EE\u526A\u8D34\u677F\uFF0C\u8BF7\u9009\u62E9\u5E76\u590D\u5236\u4EE5\u4E0B\u8BCA\u65AD\u4FE1\u606F\u3002": "Clipboard access is unavailable. Select and copy the diagnostic information below.",
1009
+ "\u9519\u8BEF\u7801": "Error code",
1010
+ "\u5931\u8D25\u9636\u6BB5": "Failed step",
1011
+ "\u5E95\u5C42\u539F\u56E0": "Underlying cause",
1012
+ "HTTP \u72B6\u6001": "HTTP status",
1013
+ "\u5FAE\u4FE1\u8FD4\u56DE\u7801": "WeChat return code",
1014
+ "\u53C2\u8003\u53F7": "Reference",
1015
+ "\u53D1\u751F\u65F6\u95F4": "Time",
1016
+ "\u52A0\u8F7D\u5FAE\u4FE1\u914D\u7F6E": "Load WeChat configuration",
1017
+ "\u7533\u8BF7\u4E8C\u7EF4\u7801": "Request QR code",
1018
+ "\u751F\u6210\u4E8C\u7EF4\u7801\u56FE\u7247": "Generate QR-code image",
1019
+ "\u67E5\u8BE2\u626B\u7801\u72B6\u6001": "Query QR-code status",
1020
+ "\u63D0\u4EA4\u914D\u5BF9\u7801": "Submit pairing code",
1021
+ "\u53D6\u6D88\u7ED1\u5B9A": "Cancel setup",
1022
+ "\u8BFB\u53D6\u767B\u5F55\u51ED\u636E": "Read login credential",
1023
+ "\u4FDD\u5B58\u767B\u5F55\u51ED\u636E": "Save login credential",
1024
+ "\u79FB\u9664\u767B\u5F55\u51ED\u636E": "Remove login credential",
1025
+ "\u4FDD\u5B58\u8D26\u53F7\u914D\u7F6E": "Save account configuration",
1026
+ "\u79FB\u9664\u8D26\u53F7\u914D\u7F6E": "Remove account configuration",
1027
+ "\u8BFB\u53D6\u8D26\u53F7\u72B6\u6001": "Read account state",
1028
+ "\u4FDD\u5B58\u8D26\u53F7\u72B6\u6001": "Save account state",
1029
+ "\u6E05\u7406\u8D26\u53F7\u72B6\u6001": "Clean up account state",
1030
+ "\u4FDD\u5B58\u5DE5\u4F5C\u533A\u8BBE\u7F6E": "Save workspace settings",
1031
+ "\u6E05\u7406\u5DE5\u4F5C\u533A\u8BBE\u7F6E": "Clean up workspace settings",
1032
+ "\u51C6\u5907\u6D88\u606F\u8FDE\u63A5": "Prepare message connection",
1033
+ "\u6FC0\u6D3B\u5FAE\u4FE1\u8D26\u53F7": "Activate WeChat account",
1034
+ "\u68C0\u67E5 DSH \u5BBF\u4E3B": "Check DSH host",
1035
+ "\u542F\u52A8\u5FAE\u4FE1\u8FDE\u63A5": "Start WeChat connection",
1036
+ "\u540C\u6B65\u5FAE\u4FE1\u6D88\u606F": "Sync WeChat messages",
1037
+ "\u505C\u6B62\u5FAE\u4FE1\u8FDE\u63A5": "Stop WeChat connection",
1038
+ "\u8BFB\u53D6\u8FDE\u63A5\u72B6\u6001": "Read connection status",
1039
+ "\u6062\u590D\u539F\u8D26\u53F7\u72B6\u6001": "Restore previous account state",
1040
+ "\u8BBF\u95EE DSH \u7BA1\u7406\u63A5\u53E3": "Access DSH management API"
1041
+ };
1042
+
918
1043
  // plugin-src/client/i18n.js
919
1044
  var React2 = __toESM(require("react"), 1);
920
1045
  var IM_LOCALE_NAMESPACE = "dsh-im";
921
1046
  var EN = Object.freeze({
1047
+ ...connection_error_en_default,
922
1048
  "$locale": "en",
923
1049
  "\u4FEE\u6539\u522B\u540D": "Edit alias",
924
1050
  "\u5173\u95ED\u4FEE\u6539\u522B\u540D": "Close alias editor",
@@ -11885,9 +12011,111 @@ function WecomAppSettingsTab({ rpcCall }) {
11885
12011
  )));
11886
12012
  }
11887
12013
 
11888
- // plugin-src/client/channels/weixin/index.js
12014
+ // plugin-src/client/channels/weixin/connection-error.js
11889
12015
  var React22 = __toESM(require("react"), 1);
11890
12016
 
12017
+ // src/channels/weixin/diagnostic-details.mjs
12018
+ var OPERATIONS = /* @__PURE__ */ new Set([
12019
+ "startup",
12020
+ "connection.restore",
12021
+ "connection.monitor",
12022
+ "connection.close",
12023
+ "connection.status",
12024
+ "provision.begin",
12025
+ "provision.poll",
12026
+ "provision.verify",
12027
+ "provision.cancel",
12028
+ "bot.reconnect",
12029
+ "bot.delete",
12030
+ "bot.workspace.set",
12031
+ "bot.model.set",
12032
+ "bot.agent-preset.set",
12033
+ "bot.context-enhancement.set",
12034
+ "bot.access-policy.set",
12035
+ "bot.alias.set"
12036
+ ]);
12037
+ var STAGES = /* @__PURE__ */ new Set([
12038
+ "startup.load",
12039
+ "qr.begin",
12040
+ "qr.encode",
12041
+ "qr.poll",
12042
+ "qr.verify",
12043
+ "qr.cancel",
12044
+ "credential.read",
12045
+ "credential.save",
12046
+ "credential.remove",
12047
+ "account.save",
12048
+ "account.remove",
12049
+ "state.load",
12050
+ "state.write",
12051
+ "state.cleanup",
12052
+ "workspace.write",
12053
+ "workspace.cleanup",
12054
+ "runtime.prepare",
12055
+ "activation",
12056
+ "harness.check",
12057
+ "connection.start",
12058
+ "connection.poll",
12059
+ "connection.stop",
12060
+ "status.read",
12061
+ "rollback",
12062
+ "management.request"
12063
+ ]);
12064
+ var REASONS = /* @__PURE__ */ new Set([
12065
+ "ENOTFOUND",
12066
+ "EAI_AGAIN",
12067
+ "ECONNREFUSED",
12068
+ "ECONNRESET",
12069
+ "EHOSTUNREACH",
12070
+ "ENETUNREACH",
12071
+ "ETIMEDOUT",
12072
+ "EPIPE",
12073
+ "UND_ERR_CONNECT_TIMEOUT",
12074
+ "UND_ERR_HEADERS_TIMEOUT",
12075
+ "UND_ERR_BODY_TIMEOUT",
12076
+ "UND_ERR_SOCKET",
12077
+ "CERT_HAS_EXPIRED",
12078
+ "CERT_NOT_YET_VALID",
12079
+ "DEPTH_ZERO_SELF_SIGNED_CERT",
12080
+ "SELF_SIGNED_CERT_IN_CHAIN",
12081
+ "UNABLE_TO_VERIFY_LEAF_SIGNATURE",
12082
+ "UNABLE_TO_GET_ISSUER_CERT_LOCALLY",
12083
+ "ERR_TLS_CERT_ALTNAME_INVALID",
12084
+ "ERR_SSL_WRONG_VERSION_NUMBER",
12085
+ "ENOENT",
12086
+ "EACCES",
12087
+ "EPERM",
12088
+ "ENOSPC",
12089
+ "EROFS",
12090
+ "ENOTDIR",
12091
+ "EISDIR",
12092
+ "EBUSY",
12093
+ "EIO",
12094
+ "EXDEV",
12095
+ "EMFILE",
12096
+ "ENFILE",
12097
+ "EEXIST",
12098
+ "invalid-json",
12099
+ "read-only"
12100
+ ]);
12101
+ var RESOURCES = /* @__PURE__ */ new Set(["credential-store", "account-config", "account-state", "workspace-config", "workspace-directory"]);
12102
+ function normalizeWeixinDiagnosticDetails(value) {
12103
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
12104
+ const result = {};
12105
+ for (const [field, allowed] of [["operation", OPERATIONS], ["stage", STAGES], ["reason", REASONS], ["resource", RESOURCES]]) {
12106
+ if (allowed.has(value[field])) result[field] = value[field];
12107
+ }
12108
+ if (/^WX-CONN-[A-F0-9]{8}$/.test(value.referenceId ?? "")) result.referenceId = value.referenceId;
12109
+ if (typeof value.occurredAt === "string" && /^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d\.\d{3}Z$/.test(value.occurredAt) && Number.isFinite(Date.parse(value.occurredAt))) result.occurredAt = value.occurredAt;
12110
+ if (Number.isInteger(value.httpStatus) && value.httpStatus >= 100 && value.httpStatus <= 599) result.httpStatus = value.httpStatus;
12111
+ const provider = typeof value.providerCode === "number" && Number.isSafeInteger(value.providerCode) ? String(value.providerCode) : value.providerCode;
12112
+ if (typeof provider === "string" && /^-?\d{1,12}$/.test(provider)) result.providerCode = provider;
12113
+ if (typeof value.pluginVersion === "string" && /^\d+\.\d+\.\d+(?:-[A-Za-z0-9.-]+)?$/.test(value.pluginVersion) && value.pluginVersion.length <= 64) result.pluginVersion = value.pluginVersion;
12114
+ if (["succeeded", "failed", "not-attempted", "unknown"].includes(value.rollback)) result.rollback = value.rollback;
12115
+ if (typeof value.hint === "string" && value.hint.trim()) result.hint = value.hint.trim().slice(0, 500);
12116
+ return result;
12117
+ }
12118
+
11891
12119
  // plugin-src/client/channels/weixin/api.js
11892
12120
  var WEIXIN_RPC_CHANNEL = "/weixin";
11893
12121
  var WEIXIN_ENDPOINTS = Object.freeze({
@@ -11933,13 +12161,35 @@ function normalizeTestMessage5(value) {
11933
12161
  const code = value.code === "test-target-unavailable" ? "test-target-unavailable" : "test-message-failed";
11934
12162
  return { sent: false, code };
11935
12163
  }
12164
+ function normalizeConnectionError(value, fallbackCode = "WEIXIN_ERROR", fallbackMessage = "\u5FAE\u4FE1\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5") {
12165
+ const details = normalizeWeixinDiagnosticDetails(value?.details);
12166
+ return {
12167
+ code: string(value?.code, fallbackCode).slice(0, 100),
12168
+ message: string(value?.message, fallbackMessage).slice(0, 500),
12169
+ ...Object.keys(details).length ? { details } : {}
12170
+ };
12171
+ }
12172
+ function managementRequestError(cause, operation) {
12173
+ if (cause?.name === "AbortError") return cause;
12174
+ const error = new Error("\u65E0\u6CD5\u5B8C\u6210\u5FAE\u4FE1\u7BA1\u7406\u8BF7\u6C42\uFF0C\u8BF7\u68C0\u67E5 DSH \u8FDE\u63A5\u540E\u91CD\u65B0\u8BFB\u53D6\u72B6\u6001\u3002");
12175
+ error.code = "weixin-management-unreachable";
12176
+ error.details = normalizeWeixinDiagnosticDetails({ operation, stage: "management.request", occurredAt: (/* @__PURE__ */ new Date()).toISOString() });
12177
+ return error;
12178
+ }
12179
+ function invalidResponse() {
12180
+ const error = new Error("DSH \u5FAE\u4FE1\u7BA1\u7406\u63A5\u53E3\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94\uFF0C\u8BF7\u91CD\u65B0\u8BFB\u53D6\u72B6\u6001\u3002");
12181
+ error.code = "weixin-management-invalid-response";
12182
+ error.details = { stage: "management.request", occurredAt: (/* @__PURE__ */ new Date()).toISOString() };
12183
+ return error;
12184
+ }
11936
12185
  function unwrapRpcResult9(result) {
11937
12186
  if (!isRecord7(result) || typeof result.ok !== "boolean") {
11938
- throw new Error("\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94");
12187
+ throw invalidResponse();
11939
12188
  }
11940
12189
  if (!result.ok) {
11941
- const error = new Error(string(result.error?.message, "\u5FAE\u4FE1\u64CD\u4F5C\u5931\u8D25"));
11942
- error.code = string(result.error?.code, "WEIXIN_RPC_ERROR");
12190
+ if (!isRecord7(result.error)) throw invalidResponse();
12191
+ const visible = normalizeConnectionError(result.error, "WEIXIN_RPC_ERROR", "\u5FAE\u4FE1\u64CD\u4F5C\u5931\u8D25");
12192
+ const error = Object.assign(new Error(visible.message), visible);
11943
12193
  throw error;
11944
12194
  }
11945
12195
  return result.value;
@@ -11959,7 +12209,7 @@ function safeVerificationUrl(value) {
11959
12209
  }
11960
12210
  function normalizeProvisioning5(value) {
11961
12211
  if (!isRecord7(value) || !string(value.attemptId)) {
11962
- throw new Error("\u5FAE\u4FE1\u626B\u7801\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u7ED1\u5B9A\u4EFB\u52A1");
12212
+ throw invalidResponse();
11963
12213
  }
11964
12214
  const status = PROVISION_STATES4.has(value.status) ? value.status : "failed";
11965
12215
  const result = {
@@ -11976,10 +12226,7 @@ function normalizeProvisioning5(value) {
11976
12226
  if (string(value.botId)) result.botId = string(value.botId);
11977
12227
  if (value.alreadyConnected === true) result.alreadyConnected = true;
11978
12228
  if (isRecord7(value.error)) {
11979
- result.error = {
11980
- code: string(value.error.code, "WEIXIN_PROVISION_FAILED"),
11981
- message: string(value.error.message, "\u5FAE\u4FE1\u7ED1\u5B9A\u6CA1\u6709\u5B8C\u6210")
11982
- };
12229
+ result.error = normalizeConnectionError(value.error, "WEIXIN_PROVISION_FAILED", "\u5FAE\u4FE1\u7ED1\u5B9A\u6CA1\u6709\u5B8C\u6210");
11983
12230
  }
11984
12231
  return result;
11985
12232
  }
@@ -12012,15 +12259,12 @@ function normalizeBot6(value) {
12012
12259
  messagesReplied: Math.max(0, Number(value.stats?.messagesReplied) || 0)
12013
12260
  },
12014
12261
  lastMessageError: normalizeLastMessageError(value.lastMessageError),
12015
- error: isRecord7(value.error) ? {
12016
- code: string(value.error.code, "WEIXIN_ACCOUNT_ERROR"),
12017
- message: string(value.error.message, "\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA")
12018
- } : null
12262
+ error: isRecord7(value.error) ? normalizeConnectionError(value.error, "WEIXIN_ACCOUNT_ERROR", "\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA") : null
12019
12263
  };
12020
12264
  }
12021
12265
  function normalizeSnapshot8(value) {
12022
12266
  if (!isRecord7(value) || !Array.isArray(value.bots)) {
12023
- throw new Error("\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u8D26\u53F7\u5217\u8868");
12267
+ throw invalidResponse();
12024
12268
  }
12025
12269
  const bots = value.bots.map(normalizeBot6).filter(Boolean);
12026
12270
  return {
@@ -12034,23 +12278,130 @@ function normalizeSnapshot8(value) {
12034
12278
  },
12035
12279
  provisioning: value.provisioning ? normalizeProvisioning5(value.provisioning) : null,
12036
12280
  testMessage: normalizeTestMessage5(value.testMessage),
12281
+ warnings: Array.isArray(value.warnings) ? value.warnings.filter(isRecord7).slice(0, 8).map((error) => normalizeConnectionError(error)) : [],
12037
12282
  agentPresetCatalog: normalizeAgentPresetCatalog(value.agentPresetCatalog),
12038
12283
  modelCatalog: normalizeModelCatalog(value.modelCatalog)
12039
12284
  };
12040
12285
  }
12041
12286
  function presentError9(error) {
12042
- return {
12043
- code: string(error?.code, "WEIXIN_ERROR"),
12044
- message: string(error?.message, "\u5FAE\u4FE1\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5")
12045
- };
12287
+ return normalizeConnectionError(error);
12046
12288
  }
12047
12289
  function formatRemaining5(milliseconds) {
12048
12290
  const seconds = Math.max(0, Math.ceil(milliseconds / 1e3));
12049
12291
  return `${Math.floor(seconds / 60)}:${String(seconds % 60).padStart(2, "0")}`;
12050
12292
  }
12051
12293
 
12294
+ // plugin-src/client/channels/weixin/connection-error.js
12295
+ var STAGE_LABELS = {
12296
+ "startup.load": "\u52A0\u8F7D\u5FAE\u4FE1\u914D\u7F6E",
12297
+ "qr.begin": "\u7533\u8BF7\u4E8C\u7EF4\u7801",
12298
+ "qr.encode": "\u751F\u6210\u4E8C\u7EF4\u7801\u56FE\u7247",
12299
+ "qr.poll": "\u67E5\u8BE2\u626B\u7801\u72B6\u6001",
12300
+ "qr.verify": "\u63D0\u4EA4\u914D\u5BF9\u7801",
12301
+ "qr.cancel": "\u53D6\u6D88\u7ED1\u5B9A",
12302
+ "credential.read": "\u8BFB\u53D6\u767B\u5F55\u51ED\u636E",
12303
+ "credential.save": "\u4FDD\u5B58\u767B\u5F55\u51ED\u636E",
12304
+ "credential.remove": "\u79FB\u9664\u767B\u5F55\u51ED\u636E",
12305
+ "account.save": "\u4FDD\u5B58\u8D26\u53F7\u914D\u7F6E",
12306
+ "account.remove": "\u79FB\u9664\u8D26\u53F7\u914D\u7F6E",
12307
+ "state.load": "\u8BFB\u53D6\u8D26\u53F7\u72B6\u6001",
12308
+ "state.write": "\u4FDD\u5B58\u8D26\u53F7\u72B6\u6001",
12309
+ "state.cleanup": "\u6E05\u7406\u8D26\u53F7\u72B6\u6001",
12310
+ "workspace.write": "\u4FDD\u5B58\u5DE5\u4F5C\u533A\u8BBE\u7F6E",
12311
+ "workspace.cleanup": "\u6E05\u7406\u5DE5\u4F5C\u533A\u8BBE\u7F6E",
12312
+ "runtime.prepare": "\u51C6\u5907\u6D88\u606F\u8FDE\u63A5",
12313
+ activation: "\u6FC0\u6D3B\u5FAE\u4FE1\u8D26\u53F7",
12314
+ "harness.check": "\u68C0\u67E5 DSH \u5BBF\u4E3B",
12315
+ "connection.start": "\u542F\u52A8\u5FAE\u4FE1\u8FDE\u63A5",
12316
+ "connection.poll": "\u540C\u6B65\u5FAE\u4FE1\u6D88\u606F",
12317
+ "connection.stop": "\u505C\u6B62\u5FAE\u4FE1\u8FDE\u63A5",
12318
+ "status.read": "\u8BFB\u53D6\u8FDE\u63A5\u72B6\u6001",
12319
+ rollback: "\u6062\u590D\u539F\u8D26\u53F7\u72B6\u6001",
12320
+ "management.request": "\u8BBF\u95EE DSH \u7BA1\u7406\u63A5\u53E3"
12321
+ };
12322
+ function provisioningErrorTitle(error) {
12323
+ const stage = error?.details?.stage;
12324
+ if (stage === "qr.begin" || stage === "qr.encode") return "\u65E0\u6CD5\u751F\u6210\u5FAE\u4FE1\u4E8C\u7EF4\u7801";
12325
+ if (stage === "qr.poll") return "\u67E5\u8BE2\u5FAE\u4FE1\u626B\u7801\u72B6\u6001\u5931\u8D25";
12326
+ if (stage === "management.request") return "\u65E0\u6CD5\u5B8C\u6210\u5FAE\u4FE1\u7BA1\u7406\u8BF7\u6C42";
12327
+ return "\u5FAE\u4FE1\u6CA1\u6709\u7ED1\u5B9A\u5B8C\u6210";
12328
+ }
12329
+ function formatWeixinDiagnostic(value) {
12330
+ const error = normalizeConnectionError(value);
12331
+ const details = error.details ?? {};
12332
+ return [
12333
+ localizeText(error.message),
12334
+ details.hint ? localizeText(details.hint) : null,
12335
+ localizeText("\u9519\u8BEF\u7801") + ": " + error.code,
12336
+ ...["operation", "stage", "reason", "httpStatus", "providerCode", "resource", "referenceId", "occurredAt", "rollback", "pluginVersion"].filter((field) => details[field] !== void 0).map((field) => `${field}: ${details[field]}`)
12337
+ ].filter(Boolean).join("\n");
12338
+ }
12339
+ function WeixinConnectionError({ error: value, warning = false }) {
12340
+ const error = normalizeConnectionError(value);
12341
+ const details = error.details ?? {};
12342
+ const [copyState, setCopyState] = React22.useState(null);
12343
+ React22.useEffect(() => setCopyState(null), [details.referenceId, error.code, error.message]);
12344
+ const copy = async () => {
12345
+ try {
12346
+ if (typeof globalThis.navigator?.clipboard?.writeText !== "function") throw new Error("clipboard unavailable");
12347
+ await globalThis.navigator.clipboard.writeText(formatWeixinDiagnostic(error));
12348
+ setCopyState("copied");
12349
+ } catch {
12350
+ setCopyState("manual");
12351
+ }
12352
+ };
12353
+ const fields = [
12354
+ ["\u9519\u8BEF\u7801", error.code],
12355
+ ["\u5931\u8D25\u9636\u6BB5", localizeText(STAGE_LABELS[details.stage] ?? details.stage ?? "")],
12356
+ ["\u5E95\u5C42\u539F\u56E0", details.reason],
12357
+ ["HTTP \u72B6\u6001", details.httpStatus],
12358
+ ["\u5FAE\u4FE1\u8FD4\u56DE\u7801", details.providerCode],
12359
+ ["\u53C2\u8003\u53F7", details.referenceId],
12360
+ ["\u53D1\u751F\u65F6\u95F4", details.occurredAt],
12361
+ ["\u63D2\u4EF6\u7248\u672C", details.pluginVersion]
12362
+ ].filter(([, text7]) => text7 !== void 0 && text7 !== "");
12363
+ return h2(
12364
+ "div",
12365
+ { className: "dxw-summary dim-cardSummary", "data-weixin-diagnostic": true, role: warning ? "status" : void 0 },
12366
+ h2("p", null, error.message),
12367
+ details.hint ? h2("p", null, details.hint) : null,
12368
+ h2(
12369
+ "details",
12370
+ { style: { marginTop: 8 } },
12371
+ h2("summary", { style: { cursor: "pointer" } }, "\u8BCA\u65AD\u8BE6\u60C5"),
12372
+ h2(
12373
+ "dl",
12374
+ { style: { display: "grid", gridTemplateColumns: "auto minmax(0, 1fr)", gap: "4px 12px", margin: "10px 0" } },
12375
+ ...fields.flatMap(([label, text7]) => [
12376
+ h2("dt", { key: `${label}-label` }, label),
12377
+ React22.createElement("dd", { key: label, style: { margin: 0, overflowWrap: "anywhere" } }, String(text7))
12378
+ ])
12379
+ ),
12380
+ !details.referenceId ? h2("p", null, "\u672A\u53D6\u5F97 Host \u8BCA\u65AD\u53C2\u8003\u53F7\u3002") : null,
12381
+ h2(
12382
+ "div",
12383
+ { className: "dim-viewActions" },
12384
+ h2("button", { type: "button", className: "dxw-button", onClick: copy }, copyState === "copied" ? "\u8BCA\u65AD\u4FE1\u606F\u5DF2\u590D\u5236" : "\u590D\u5236\u8BCA\u65AD\u4FE1\u606F")
12385
+ ),
12386
+ copyState === "manual" ? h2(
12387
+ "div",
12388
+ null,
12389
+ h2("p", null, "\u65E0\u6CD5\u8BBF\u95EE\u526A\u8D34\u677F\uFF0C\u8BF7\u9009\u62E9\u5E76\u590D\u5236\u4EE5\u4E0B\u8BCA\u65AD\u4FE1\u606F\u3002"),
12390
+ React22.createElement("textarea", {
12391
+ readOnly: true,
12392
+ value: formatWeixinDiagnostic(error),
12393
+ rows: 7,
12394
+ "aria-label": localizeText("\u8BCA\u65AD\u4FE1\u606F"),
12395
+ style: { width: "100%", boxSizing: "border-box", marginTop: 8 }
12396
+ })
12397
+ ) : null
12398
+ )
12399
+ );
12400
+ }
12401
+
12052
12402
  // plugin-src/client/channels/weixin/index.js
12053
- var Button14 = React22.forwardRef(function Button15({ children, kind = "secondary", className = "", ...props }, ref) {
12403
+ var React23 = __toESM(require("react"), 1);
12404
+ var Button14 = React23.forwardRef(function Button15({ children, kind = "secondary", className = "", ...props }, ref) {
12054
12405
  return h2("button", {
12055
12406
  ...props,
12056
12407
  ref,
@@ -12123,14 +12474,14 @@ function EmptyView6({ onStart, busy }) {
12123
12474
  );
12124
12475
  }
12125
12476
  function QrPanel4({ provision, now, busy, onRefresh, onCancel }) {
12126
- const [imageFailed, setImageFailed] = React22.useState(false);
12477
+ const [imageFailed, setImageFailed] = React23.useState(false);
12127
12478
  const source = safeQrSource5(provision.qrCodeDataUrl);
12128
12479
  const href = safeVerificationUrl(provision.verificationUrl);
12129
12480
  const remaining = Math.max(0, provision.expiresAt - now);
12130
12481
  const expired = remaining === 0 || provision.status === "expired";
12131
12482
  const duration = Math.max(1, provision.durationMs ?? 5 * 6e4);
12132
12483
  const progress = Math.round(Math.min(1, remaining / duration) * 100);
12133
- React22.useEffect(() => setImageFailed(false), [source]);
12484
+ React23.useEffect(() => setImageFailed(false), [source]);
12134
12485
  return h2(
12135
12486
  "div",
12136
12487
  { className: "dxw-card dim-surfaceCard" },
@@ -12197,9 +12548,9 @@ function QrPanel4({ provision, now, busy, onRefresh, onCancel }) {
12197
12548
  );
12198
12549
  }
12199
12550
  function VerificationPanel({ provision, busy, onSubmit, onCancel }) {
12200
- const [code, setCode] = React22.useState("");
12551
+ const [code, setCode] = React23.useState("");
12201
12552
  const valid = /^\d{4,8}$/.test(code);
12202
- React22.useEffect(() => setCode(""), [provision.attemptId]);
12553
+ React23.useEffect(() => setCode(""), [provision.attemptId]);
12203
12554
  return h2(
12204
12555
  "div",
12205
12556
  { className: "dxw-card dim-surfaceCard" },
@@ -12266,9 +12617,8 @@ function ProvisionError3({ provision, busy, onRetry, onClose }) {
12266
12617
  h2(
12267
12618
  "div",
12268
12619
  { className: "dxw-error dim-inlineError", role: "alert" },
12269
- h2("h3", null, provision.status === "expired" ? "\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F" : "\u5FAE\u4FE1\u6CA1\u6709\u7ED1\u5B9A\u5B8C\u6210"),
12270
- h2("p", null, error.message),
12271
- h2("span", { className: "dxw-errorCode" }, error.code),
12620
+ h2("h3", null, provision.status === "expired" ? "\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F" : provisioningErrorTitle(error)),
12621
+ h2(WeixinConnectionError, { error }),
12272
12622
  h2(
12273
12623
  "div",
12274
12624
  { className: "dxw-actions dim-viewActions" },
@@ -12394,7 +12744,7 @@ function AccountCard5({
12394
12744
  ),
12395
12745
  h2(Button14, { className: "dim-cardAction", kind: "danger", onClick: onRequestRemove, disabled: Boolean(busy) }, "\u79FB\u9664\u63A5\u5165")
12396
12746
  ),
12397
- summary2 ? h2("div", { className: "dxw-summary dim-cardSummary" }, summary2) : null,
12747
+ account.error ? h2(WeixinConnectionError, { error: account.error }) : summary2 ? h2("div", { className: "dxw-summary dim-cardSummary" }, summary2) : null,
12398
12748
  account.lastMessageError ? h2(LastMessageErrorSummary, {
12399
12749
  className: "dxw-summary",
12400
12750
  error: account.lastMessageError
@@ -12403,7 +12753,7 @@ function AccountCard5({
12403
12753
  className: "dxw-summary dim-cardFeedback",
12404
12754
  role: "status",
12405
12755
  "aria-live": "polite"
12406
- }, feedback) : null
12756
+ }, typeof feedback === "string" ? feedback : h2(WeixinConnectionError, { error: feedback })) : null
12407
12757
  )
12408
12758
  )
12409
12759
  )
@@ -12467,7 +12817,7 @@ function mergeWeixinProvisioningSnapshot(current, incoming, { restoreProvisionin
12467
12817
  };
12468
12818
  }
12469
12819
  function WeixinSettingsTab({ rpcCall }) {
12470
- const [model, setModel] = React22.useState({
12820
+ const [model, setModel] = React23.useState({
12471
12821
  phase: "loading",
12472
12822
  bots: [],
12473
12823
  totals: EMPTY_TOTALS3,
@@ -12476,33 +12826,41 @@ function WeixinSettingsTab({ rpcCall }) {
12476
12826
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
12477
12827
  modelCatalog: EMPTY_MODEL_CATALOG
12478
12828
  });
12479
- const [provision, setProvision] = React22.useState(null);
12480
- const [busy, setBusy] = React22.useState(false);
12481
- const [busyByBot, setBusyByBot] = React22.useState({});
12482
- const [feedbackByBot, setFeedbackByBot] = React22.useState({});
12483
- const [removeTarget, setRemoveTarget] = React22.useState(null);
12484
- const [notice, setNotice] = React22.useState("");
12485
- const [now, setNow] = React22.useState(() => Date.now());
12486
- const addButtonRef = React22.useRef(null);
12487
- const mountedRef = React22.useRef(true);
12829
+ const [provision, setProvision] = React23.useState(null);
12830
+ const [busy, setBusy] = React23.useState(false);
12831
+ const [busyByBot, setBusyByBot] = React23.useState({});
12832
+ const [feedbackByBot, setFeedbackByBot] = React23.useState({});
12833
+ const [removeTarget, setRemoveTarget] = React23.useState(null);
12834
+ const [notice, setNotice] = React23.useState("");
12835
+ const [operationWarnings, setOperationWarnings] = React23.useState([]);
12836
+ const [now, setNow] = React23.useState(() => Date.now());
12837
+ const addButtonRef = React23.useRef(null);
12838
+ const mountedRef = React23.useRef(true);
12488
12839
  const workspaceFence = useWorkspaceSnapshotFence();
12489
12840
  const scheduleAnimationFrame = useAnimationFrameScheduler();
12490
- React22.useEffect(() => {
12841
+ React23.useEffect(() => {
12491
12842
  mountedRef.current = true;
12492
12843
  return () => {
12493
12844
  mountedRef.current = false;
12494
12845
  };
12495
12846
  }, []);
12496
- const announce = React22.useCallback((value) => {
12847
+ const announce = React23.useCallback((value) => {
12497
12848
  setNotice("");
12498
12849
  scheduleAnimationFrame(() => {
12499
12850
  if (value) setNotice(value);
12500
12851
  }, "announcement");
12501
12852
  }, [scheduleAnimationFrame]);
12502
- const invoke = React22.useCallback(async (endpoint, payload = {}, signal) => {
12503
- return unwrapRpcResult9(await rpcCall(endpoint, payload, signal));
12853
+ const invoke = React23.useCallback(async (endpoint, payload = {}, signal) => {
12854
+ let result;
12855
+ try {
12856
+ result = await rpcCall(endpoint, payload, signal);
12857
+ } catch (error) {
12858
+ if (signal?.aborted) throw error;
12859
+ throw managementRequestError(error, endpoint);
12860
+ }
12861
+ return unwrapRpcResult9(result);
12504
12862
  }, [rpcCall]);
12505
- const loadStatus = React22.useCallback(async ({
12863
+ const loadStatus = React23.useCallback(async ({
12506
12864
  signal,
12507
12865
  silent = false,
12508
12866
  restoreProvisioning = false
@@ -12540,12 +12898,12 @@ function WeixinSettingsTab({ rpcCall }) {
12540
12898
  return void 0;
12541
12899
  }
12542
12900
  }, [invoke, workspaceFence]);
12543
- React22.useEffect(() => {
12901
+ React23.useEffect(() => {
12544
12902
  const controller = new AbortController();
12545
12903
  void loadStatus({ signal: controller.signal, restoreProvisioning: true });
12546
12904
  return () => controller.abort();
12547
12905
  }, [loadStatus]);
12548
- React22.useEffect(() => {
12906
+ React23.useEffect(() => {
12549
12907
  if (model.phase !== "ready") return void 0;
12550
12908
  const controller = new AbortController();
12551
12909
  let running = false;
@@ -12564,12 +12922,12 @@ function WeixinSettingsTab({ rpcCall }) {
12564
12922
  window.clearInterval(timer);
12565
12923
  };
12566
12924
  }, [loadStatus, model.phase]);
12567
- React22.useEffect(() => {
12925
+ React23.useEffect(() => {
12568
12926
  if (!provision || !["pending", "scanned"].includes(provision.status)) return void 0;
12569
12927
  const timer = window.setInterval(() => setNow(Date.now()), 1e3);
12570
12928
  return () => window.clearInterval(timer);
12571
12929
  }, [provision?.attemptId, provision?.status]);
12572
- const startProvisioning = React22.useCallback(async ({ replace = false } = {}) => {
12930
+ const startProvisioning = React23.useCallback(async ({ replace = false } = {}) => {
12573
12931
  setBusy(true);
12574
12932
  try {
12575
12933
  if (replace && provision?.attemptId) {
@@ -12590,7 +12948,7 @@ function WeixinSettingsTab({ rpcCall }) {
12590
12948
  setBusy(false);
12591
12949
  }
12592
12950
  }, [announce, invoke, provision?.attemptId]);
12593
- const cancelProvisioning = React22.useCallback(async () => {
12951
+ const cancelProvisioning = React23.useCallback(async () => {
12594
12952
  setBusy(true);
12595
12953
  try {
12596
12954
  if (provision?.attemptId && !["failed", "expired", "cancelled"].includes(provision.status)) {
@@ -12605,7 +12963,7 @@ function WeixinSettingsTab({ rpcCall }) {
12605
12963
  setBusy(false);
12606
12964
  }
12607
12965
  }, [announce, invoke, provision?.attemptId, provision?.status, scheduleAnimationFrame]);
12608
- const submitVerification = React22.useCallback(async (verifyCode) => {
12966
+ const submitVerification = React23.useCallback(async (verifyCode) => {
12609
12967
  if (!provision?.attemptId) return;
12610
12968
  setBusy(true);
12611
12969
  try {
@@ -12621,7 +12979,7 @@ function WeixinSettingsTab({ rpcCall }) {
12621
12979
  setBusy(false);
12622
12980
  }
12623
12981
  }, [announce, invoke, provision?.attemptId]);
12624
- React22.useEffect(() => {
12982
+ React23.useEffect(() => {
12625
12983
  const attemptId = provision?.attemptId;
12626
12984
  if (!attemptId || !["pending", "scanned", "connecting"].includes(provision.status)) return void 0;
12627
12985
  const controller = new AbortController();
@@ -12669,7 +13027,7 @@ function WeixinSettingsTab({ rpcCall }) {
12669
13027
  controller.abort();
12670
13028
  };
12671
13029
  }, [announce, invoke, loadStatus, provision?.attemptId, provision?.status, provision?.pollIntervalMs]);
12672
- const setBotBusy = React22.useCallback((botId, value) => {
13030
+ const setBotBusy = React23.useCallback((botId, value) => {
12673
13031
  setBusyByBot((current) => {
12674
13032
  const next = { ...current };
12675
13033
  if (value) next[botId] = value;
@@ -12677,7 +13035,7 @@ function WeixinSettingsTab({ rpcCall }) {
12677
13035
  return next;
12678
13036
  });
12679
13037
  }, []);
12680
- const reconnect = React22.useCallback(async (account) => {
13038
+ const reconnect = React23.useCallback(async (account) => {
12681
13039
  const snapshotVersion = workspaceFence.beginMutation();
12682
13040
  setBotBusy(account.botId, "reconnect");
12683
13041
  setFeedbackByBot((current) => {
@@ -12717,21 +13075,22 @@ function WeixinSettingsTab({ rpcCall }) {
12717
13075
  setFeedbackByBot((current) => ({ ...current, [account.botId]: feedback }));
12718
13076
  }
12719
13077
  announce(feedback);
12720
- } catch {
12721
- const feedback = "\u8FDE\u63A5\u68C0\u67E5\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002";
13078
+ } catch (error) {
13079
+ const feedback = presentError9(error);
12722
13080
  if (mountedRef.current) {
12723
13081
  setFeedbackByBot((current) => ({ ...current, [account.botId]: feedback }));
12724
13082
  }
12725
- announce(feedback);
13083
+ announce(feedback.message);
12726
13084
  } finally {
12727
13085
  const shouldRefresh = workspaceFence.endMutation();
12728
13086
  if (shouldRefresh && mountedRef.current) void loadStatus({ silent: true });
12729
13087
  setBotBusy(account.botId, null);
12730
13088
  }
12731
13089
  }, [announce, invoke, loadStatus, setBotBusy, workspaceFence]);
12732
- const saveWorkspace = React22.useCallback(async (account, workspace) => {
13090
+ const saveWorkspace = React23.useCallback(async (account, workspace) => {
12733
13091
  const workspaceVersion = workspaceFence.beginMutation();
12734
13092
  setBotBusy(account.botId, "workspace");
13093
+ setFeedbackByBot((current) => ({ ...current, [account.botId]: null }));
12735
13094
  try {
12736
13095
  const snapshot = normalizeSnapshot8(await invoke(
12737
13096
  WEIXIN_ENDPOINTS.setWorkspace,
@@ -12748,15 +13107,19 @@ function WeixinSettingsTab({ rpcCall }) {
12748
13107
  modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG
12749
13108
  });
12750
13109
  }
13110
+ } catch (error) {
13111
+ if (mountedRef.current) setFeedbackByBot((current) => ({ ...current, [account.botId]: presentError9(error) }));
13112
+ throw error;
12751
13113
  } finally {
12752
13114
  const shouldRefresh = workspaceFence.endMutation();
12753
13115
  if (shouldRefresh && mountedRef.current) void loadStatus({ silent: true });
12754
13116
  if (mountedRef.current) setBotBusy(account.botId, null);
12755
13117
  }
12756
13118
  }, [invoke, loadStatus, setBotBusy, workspaceFence]);
12757
- const saveBotSetting = React22.useCallback(async (account, operation, endpoint, payload) => {
13119
+ const saveBotSetting = React23.useCallback(async (account, operation, endpoint, payload) => {
12758
13120
  const snapshotVersion = workspaceFence.beginMutation();
12759
13121
  setBotBusy(account.botId, operation);
13122
+ setFeedbackByBot((current) => ({ ...current, [account.botId]: null }));
12760
13123
  try {
12761
13124
  const snapshot = normalizeSnapshot8(await invoke(
12762
13125
  endpoint,
@@ -12773,15 +13136,20 @@ function WeixinSettingsTab({ rpcCall }) {
12773
13136
  modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG
12774
13137
  });
12775
13138
  }
13139
+ } catch (error) {
13140
+ if (mountedRef.current) setFeedbackByBot((current) => ({ ...current, [account.botId]: presentError9(error) }));
13141
+ throw error;
12776
13142
  } finally {
12777
13143
  const shouldRefresh = workspaceFence.endMutation();
12778
13144
  if (shouldRefresh && mountedRef.current) void loadStatus({ silent: true });
12779
13145
  if (mountedRef.current) setBotBusy(account.botId, null);
12780
13146
  }
12781
13147
  }, [invoke, loadStatus, setBotBusy, workspaceFence]);
12782
- const remove = React22.useCallback(async (account) => {
13148
+ const remove = React23.useCallback(async (account) => {
12783
13149
  const snapshotVersion = workspaceFence.beginMutation();
12784
13150
  setBotBusy(account.botId, "delete");
13151
+ setOperationWarnings([]);
13152
+ setFeedbackByBot((current) => ({ ...current, [account.botId]: null }));
12785
13153
  try {
12786
13154
  const snapshot = normalizeSnapshot8(await invoke(WEIXIN_ENDPOINTS.deleteBot, {
12787
13155
  botId: account.botId,
@@ -12797,10 +13165,13 @@ function WeixinSettingsTab({ rpcCall }) {
12797
13165
  modelCatalog: snapshot.modelCatalog ?? current.modelCatalog
12798
13166
  }));
12799
13167
  }
13168
+ setOperationWarnings(snapshot.warnings);
12800
13169
  setRemoveTarget(null);
12801
13170
  announce("\u5FAE\u4FE1\u8D26\u53F7\u53CA\u672C\u673A\u51ED\u636E\u5DF2\u79FB\u9664\u3002");
12802
13171
  } catch (error) {
12803
- announce(`\u79FB\u9664\u5931\u8D25\uFF1A${presentError9(error).message}`);
13172
+ const failure = presentError9(error);
13173
+ if (mountedRef.current) setFeedbackByBot((current) => ({ ...current, [account.botId]: failure }));
13174
+ announce(failure.message);
12804
13175
  } finally {
12805
13176
  const shouldRefresh = workspaceFence.endMutation();
12806
13177
  if (shouldRefresh && mountedRef.current) void loadStatus({ silent: true });
@@ -12854,7 +13225,13 @@ function WeixinSettingsTab({ rpcCall }) {
12854
13225
  addButtonRef
12855
13226
  }),
12856
13227
  h2("div", { className: "dxw-visuallyHidden", role: "status", "aria-live": "polite" }, notice),
12857
- model.error && model.phase === "ready" ? h2("div", { className: "dxw-statusNotice dim-statusNotice" }, `\u72B6\u6001\u5237\u65B0\u5931\u8D25\uFF1A${model.error.message}`) : null,
13228
+ ...operationWarnings.map((error, index) => h2(WeixinConnectionError, { key: error.details?.referenceId ?? index, error, warning: true })),
13229
+ model.error && model.phase === "ready" ? h2(
13230
+ "div",
13231
+ { className: "dxw-statusNotice dim-statusNotice" },
13232
+ h2("p", null, "\u72B6\u6001\u8BFB\u53D6\u5931\u8D25\uFF0C\u4EE5\u4E0B\u662F\u4E0A\u6B21\u8BFB\u53D6\u7684\u72B6\u6001\u3002"),
13233
+ h2(WeixinConnectionError, { error: model.error })
13234
+ ) : null,
12858
13235
  model.phase === "loading" ? h2(LoadingView6) : model.phase === "error" ? h2(
12859
13236
  "div",
12860
13237
  { className: "dxw-card dim-surfaceCard" },
@@ -12862,11 +13239,11 @@ function WeixinSettingsTab({ rpcCall }) {
12862
13239
  "div",
12863
13240
  { className: "dxw-error dim-inlineError" },
12864
13241
  h2("h3", null, "\u65E0\u6CD5\u8BFB\u53D6\u5FAE\u4FE1\u72B6\u6001"),
12865
- h2("p", null, model.error?.message ?? "\u8BF7\u7A0D\u540E\u91CD\u8BD5"),
13242
+ h2(WeixinConnectionError, { error: model.error }),
12866
13243
  h2(Button14, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
12867
13244
  )
12868
13245
  ) : h2(
12869
- React22.Fragment,
13246
+ React23.Fragment,
12870
13247
  null,
12871
13248
  provisionView,
12872
13249
  model.bots.length === 0 && !provision ? h2(EmptyView6, { onStart: () => void startProvisioning(), busy }) : null,
@@ -13152,7 +13529,7 @@ function formatRemaining6(milliseconds) {
13152
13529
  }
13153
13530
 
13154
13531
  // plugin-src/client/channels/whatsapp/index.js
13155
- var React23 = __toESM(require("react"), 1);
13532
+ var React24 = __toESM(require("react"), 1);
13156
13533
 
13157
13534
  // plugin-src/client/channels/whatsapp/styles.js
13158
13535
  var WHATSAPP_STYLE_ID = "xmanrui-dsh-im-whatsapp-settings";
@@ -13177,7 +13554,7 @@ function installWhatsappStyles() {
13177
13554
 
13178
13555
  // plugin-src/client/channels/whatsapp/index.js
13179
13556
  var ACTIVE_STATES3 = /* @__PURE__ */ new Set(["pending", "connecting"]);
13180
- var Button16 = React23.forwardRef(function Button17({ children, kind = "secondary", className = "", ...props }, ref) {
13557
+ var Button16 = React24.forwardRef(function Button17({ children, kind = "secondary", className = "", ...props }, ref) {
13181
13558
  return h2("button", {
13182
13559
  ...props,
13183
13560
  ref,
@@ -13531,7 +13908,7 @@ function WhatsappAccountCard({
13531
13908
  );
13532
13909
  }
13533
13910
  function WhatsappSettingsTab({ rpcCall }) {
13534
- const [model, setModel] = React23.useState({
13911
+ const [model, setModel] = React24.useState({
13535
13912
  phase: "loading",
13536
13913
  bots: [],
13537
13914
  totals: { configured: 0, connected: 0 },
@@ -13539,16 +13916,16 @@ function WhatsappSettingsTab({ rpcCall }) {
13539
13916
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
13540
13917
  modelCatalog: EMPTY_MODEL_CATALOG
13541
13918
  });
13542
- const [provision, setProvision] = React23.useState(null);
13543
- const [busy, setBusy] = React23.useState(false);
13544
- const [busyByBot, setBusyByBot] = React23.useState({});
13545
- const [testNoticeByBot, setTestNoticeByBot] = React23.useState({});
13546
- const [removeTarget, setRemoveTarget] = React23.useState(null);
13547
- const [now, setNow] = React23.useState(Date.now());
13548
- const mounted = React23.useRef(true);
13919
+ const [provision, setProvision] = React24.useState(null);
13920
+ const [busy, setBusy] = React24.useState(false);
13921
+ const [busyByBot, setBusyByBot] = React24.useState({});
13922
+ const [testNoticeByBot, setTestNoticeByBot] = React24.useState({});
13923
+ const [removeTarget, setRemoveTarget] = React24.useState(null);
13924
+ const [now, setNow] = React24.useState(Date.now());
13925
+ const mounted = React24.useRef(true);
13549
13926
  const workspaceFence = useWorkspaceSnapshotFence();
13550
- const addButtonRef = React23.useRef(null);
13551
- React23.useEffect(() => {
13927
+ const addButtonRef = React24.useRef(null);
13928
+ React24.useEffect(() => {
13552
13929
  const disposeDingtalk = installDingtalkStyles();
13553
13930
  const disposeWhatsapp = installWhatsappStyles();
13554
13931
  mounted.current = true;
@@ -13558,11 +13935,11 @@ function WhatsappSettingsTab({ rpcCall }) {
13558
13935
  disposeDingtalk();
13559
13936
  };
13560
13937
  }, []);
13561
- const invoke = React23.useCallback(async (endpoint, payload = {}, signal) => {
13938
+ const invoke = React24.useCallback(async (endpoint, payload = {}, signal) => {
13562
13939
  if (typeof rpcCall !== "function") throw new TypeError("WhatsApp \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
13563
13940
  return unwrapRpcResult10(await rpcCall(endpoint, payload, signal));
13564
13941
  }, [rpcCall]);
13565
- const loadStatus = React23.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
13942
+ const loadStatus = React24.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
13566
13943
  const workspaceVersion = workspaceFence.beginStatus();
13567
13944
  if (workspaceVersion === null) return void 0;
13568
13945
  if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
@@ -13593,12 +13970,12 @@ function WhatsappSettingsTab({ rpcCall }) {
13593
13970
  return void 0;
13594
13971
  }
13595
13972
  }, [invoke, workspaceFence]);
13596
- React23.useEffect(() => {
13973
+ React24.useEffect(() => {
13597
13974
  const controller = new AbortController();
13598
13975
  void loadStatus({ signal: controller.signal, restore: true });
13599
13976
  return () => controller.abort();
13600
13977
  }, [loadStatus]);
13601
- React23.useEffect(() => {
13978
+ React24.useEffect(() => {
13602
13979
  if (model.phase !== "ready") return void 0;
13603
13980
  const controller = new AbortController();
13604
13981
  const timer = window.setInterval(
@@ -13610,12 +13987,12 @@ function WhatsappSettingsTab({ rpcCall }) {
13610
13987
  window.clearInterval(timer);
13611
13988
  };
13612
13989
  }, [loadStatus, model.phase]);
13613
- React23.useEffect(() => {
13990
+ React24.useEffect(() => {
13614
13991
  if (!provision || !ACTIVE_STATES3.has(provision.status)) return void 0;
13615
13992
  const timer = window.setInterval(() => mounted.current && setNow(Date.now()), 1e3);
13616
13993
  return () => window.clearInterval(timer);
13617
13994
  }, [provision?.attemptId, provision?.status]);
13618
- const startProvisioning = React23.useCallback(async (replace = false) => {
13995
+ const startProvisioning = React24.useCallback(async (replace = false) => {
13619
13996
  setBusy(true);
13620
13997
  try {
13621
13998
  if (replace && provision?.attemptId) {
@@ -13633,7 +14010,7 @@ function WhatsappSettingsTab({ rpcCall }) {
13633
14010
  if (mounted.current) setBusy(false);
13634
14011
  }
13635
14012
  }, [invoke, provision?.attemptId]);
13636
- const closeProvision = React23.useCallback(async () => {
14013
+ const closeProvision = React24.useCallback(async () => {
13637
14014
  setBusy(true);
13638
14015
  try {
13639
14016
  if (provision?.attemptId && ACTIVE_STATES3.has(provision.status)) {
@@ -13644,7 +14021,7 @@ function WhatsappSettingsTab({ rpcCall }) {
13644
14021
  if (mounted.current) setBusy(false);
13645
14022
  }
13646
14023
  }, [invoke, provision?.attemptId, provision?.status]);
13647
- React23.useEffect(() => {
14024
+ React24.useEffect(() => {
13648
14025
  const attemptId = provision?.attemptId;
13649
14026
  if (!attemptId || !ACTIVE_STATES3.has(provision.status)) return void 0;
13650
14027
  const controller = new AbortController();
@@ -13685,7 +14062,7 @@ function WhatsappSettingsTab({ rpcCall }) {
13685
14062
  if (timer) window.clearTimeout(timer);
13686
14063
  };
13687
14064
  }, [invoke, loadStatus, provision?.attemptId, provision?.status]);
13688
- const botAction = React23.useCallback(async (account, operation, endpoint, payload) => {
14065
+ const botAction = React24.useCallback(async (account, operation, endpoint, payload) => {
13689
14066
  const snapshotVersion = workspaceFence.beginMutation();
13690
14067
  setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
13691
14068
  if (operation === "reconnect") {
@@ -13819,7 +14196,7 @@ function WhatsappSettingsTab({ rpcCall }) {
13819
14196
  h2(Button16, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
13820
14197
  )
13821
14198
  ) : h2(
13822
- React23.Fragment,
14199
+ React24.Fragment,
13823
14200
  null,
13824
14201
  provision?.status === "pending" ? h2(QrPanel5, {
13825
14202
  provision,
@@ -13850,7 +14227,7 @@ var normalizeSnapshot10 = api4.normalizeSnapshot;
13850
14227
  var presentError11 = api4.presentError;
13851
14228
 
13852
14229
  // plugin-src/client/channels/imessage/index.js
13853
- var React24 = __toESM(require("react"), 1);
14230
+ var React25 = __toESM(require("react"), 1);
13854
14231
 
13855
14232
  // plugin-src/client/channels/imessage/styles.js
13856
14233
  var IMESSAGE_STYLE_ID = "xmanrui-dsh-im-imessage-settings";
@@ -14005,10 +14382,10 @@ function installInterfaceLanguageMirror(ctx, {
14005
14382
  }
14006
14383
 
14007
14384
  // plugin-src/client/delivery-settings.js
14008
- var React27 = __toESM(require("react"), 1);
14385
+ var React28 = __toESM(require("react"), 1);
14009
14386
 
14010
14387
  // plugin-src/client/access-policy-settings.js
14011
- var React25 = __toESM(require("react"), 1);
14388
+ var React26 = __toESM(require("react"), 1);
14012
14389
  var ACCESS_POLICY_ENDPOINT = "bot.access-policy.set";
14013
14390
  var ACCESS_CHANNEL_DEFINITIONS = Object.freeze({
14014
14391
  weixin: Object.freeze({
@@ -14121,8 +14498,8 @@ function ScenePolicyEditor({
14121
14498
  unsupported = false,
14122
14499
  onChange
14123
14500
  }) {
14124
- const ownerHelpId = React25.useId();
14125
- const emptyAllowlistHelpId = React25.useId();
14501
+ const ownerHelpId = React26.useId();
14502
+ const emptyAllowlistHelpId = React26.useId();
14126
14503
  const allowlist = policy.mode === "allowlist";
14127
14504
  const collectionKey = allowlist ? "users" : "commandPermissionOverrides";
14128
14505
  const branchKey = allowlist ? "allowlist" : "open";
@@ -14174,7 +14551,7 @@ function ScenePolicyEditor({
14174
14551
  h2("strong", null, "\u5F53\u524D\u6E20\u9053\u4E0D\u652F\u6301\u7FA4\u804A"),
14175
14552
  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")
14176
14553
  ) : h2(
14177
- React25.Fragment,
14554
+ React26.Fragment,
14178
14555
  null,
14179
14556
  h2(
14180
14557
  "div",
@@ -14315,16 +14692,16 @@ function AccessPolicySettingsPage({ channel: channel5, account, rpcCall, onSaved
14315
14692
  const definition = ACCESS_CHANNEL_DEFINITIONS[channel5];
14316
14693
  const initialPolicy = normalizeAccessPolicy(account?.accessPolicy);
14317
14694
  const initialKey = JSON.stringify(initialPolicy);
14318
- const [draft, setDraft] = React25.useState(() => clonePolicy(
14695
+ const [draft, setDraft] = React26.useState(() => clonePolicy(
14319
14696
  initialPolicy ?? DEFAULT_ACCESS_POLICY
14320
14697
  ));
14321
- const [saving, setSaving] = React25.useState(false);
14322
- const [feedback, setFeedback] = React25.useState(null);
14323
- React25.useEffect(() => {
14698
+ const [saving, setSaving] = React26.useState(false);
14699
+ const [feedback, setFeedback] = React26.useState(null);
14700
+ React26.useEffect(() => {
14324
14701
  const next = normalizeAccessPolicy(account?.accessPolicy);
14325
14702
  setDraft(clonePolicy(next ?? DEFAULT_ACCESS_POLICY));
14326
14703
  }, [account?.botId, initialKey]);
14327
- React25.useEffect(() => {
14704
+ React26.useEffect(() => {
14328
14705
  setFeedback(null);
14329
14706
  }, [account?.botId]);
14330
14707
  if (!definition) {
@@ -14415,7 +14792,7 @@ function AccessPolicySettingsPage({ channel: channel5, account, rpcCall, onSaved
14415
14792
  }
14416
14793
 
14417
14794
  // plugin-src/client/channels/feishu/group-settings.js
14418
- var React26 = __toESM(require("react"), 1);
14795
+ var React27 = __toESM(require("react"), 1);
14419
14796
  var GROUP_MESSAGE_PERMISSION_OPERATION2 = FEISHU_REGISTRATION_OPERATIONS.GROUP_MESSAGE_PERMISSION;
14420
14797
  function SettingsButton({ children, kind = "secondary", className = "", ...props }) {
14421
14798
  return h2("button", {
@@ -14476,9 +14853,9 @@ function GroupResponseModeEditor({
14476
14853
  onAuthorize
14477
14854
  }) {
14478
14855
  const current = normalizeGroupResponseMode(value);
14479
- const [saving, setSaving] = React26.useState(false);
14480
- const [authorizing, setAuthorizing] = React26.useState(false);
14481
- const [error, setError] = React26.useState(null);
14856
+ const [saving, setSaving] = React27.useState(false);
14857
+ const [authorizing, setAuthorizing] = React27.useState(false);
14858
+ const [error, setError] = React27.useState(null);
14482
14859
  const change = async (event) => {
14483
14860
  const next = normalizeGroupResponseMode(event.target.value);
14484
14861
  if (next === current || saving || disabled) return;
@@ -14559,8 +14936,8 @@ function GroupResponseModeEditor({
14559
14936
  }
14560
14937
  function GroupTopicReplyEditor({ value = false, disabled = false, onSave }) {
14561
14938
  const current = value === true ? "on" : "off";
14562
- const [saving, setSaving] = React26.useState(false);
14563
- const [error, setError] = React26.useState(null);
14939
+ const [saving, setSaving] = React27.useState(false);
14940
+ const [error, setError] = React27.useState(null);
14564
14941
  const change = async (event) => {
14565
14942
  const next = event.target.value === "on";
14566
14943
  if ((next ? "on" : "off") === current || saving || disabled) return;
@@ -14747,14 +15124,14 @@ function PermissionFlow({ provision, now, busy, botName, onRetry, onCancel, onCl
14747
15124
  );
14748
15125
  }
14749
15126
  function FeishuGroupSettingsPage({ account, rpcCall }) {
14750
- const [settings, setSettings] = React26.useState(() => groupSettingsFrom(account));
14751
- const [refreshing, setRefreshing] = React26.useState(false);
14752
- const [refreshError, setRefreshError] = React26.useState(null);
14753
- const [provision, setProvision] = React26.useState(null);
14754
- const [provisionBusy, setProvisionBusy] = React26.useState(false);
14755
- const [now, setNow] = React26.useState(() => Date.now());
14756
- const mounted = React26.useRef(true);
14757
- React26.useEffect(() => {
15127
+ const [settings, setSettings] = React27.useState(() => groupSettingsFrom(account));
15128
+ const [refreshing, setRefreshing] = React27.useState(false);
15129
+ const [refreshError, setRefreshError] = React27.useState(null);
15130
+ const [provision, setProvision] = React27.useState(null);
15131
+ const [provisionBusy, setProvisionBusy] = React27.useState(false);
15132
+ const [now, setNow] = React27.useState(() => Date.now());
15133
+ const mounted = React27.useRef(true);
15134
+ React27.useEffect(() => {
14758
15135
  setSettings(groupSettingsFrom(account));
14759
15136
  }, [
14760
15137
  account.botId,
@@ -14762,22 +15139,22 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14762
15139
  account.groupTopicReply,
14763
15140
  account.groupMessagePermissionGranted
14764
15141
  ]);
14765
- React26.useEffect(() => {
15142
+ React27.useEffect(() => {
14766
15143
  mounted.current = true;
14767
15144
  return () => {
14768
15145
  mounted.current = false;
14769
15146
  };
14770
15147
  }, []);
14771
- const invoke = React26.useCallback(async (endpoint, payload = {}, signal) => {
15148
+ const invoke = React27.useCallback(async (endpoint, payload = {}, signal) => {
14772
15149
  if (typeof rpcCall !== "function") throw new Error("\u98DE\u4E66\u7FA4\u804A\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
14773
15150
  return unwrapRpcResult3(await rpcCall(endpoint, payload, signal));
14774
15151
  }, [rpcCall]);
14775
- const applySnapshot = React26.useCallback((value) => {
15152
+ const applySnapshot = React27.useCallback((value) => {
14776
15153
  const result = targetBotFromSnapshot(value, account.botId);
14777
15154
  if (mounted.current) setSettings(groupSettingsFrom(result.bot));
14778
15155
  return result;
14779
15156
  }, [account.botId]);
14780
- const loadSettings = React26.useCallback(async ({ signal, restoreProvisioning = false } = {}) => {
15157
+ const loadSettings = React27.useCallback(async ({ signal, restoreProvisioning = false } = {}) => {
14781
15158
  setRefreshing(true);
14782
15159
  setRefreshError(null);
14783
15160
  try {
@@ -14806,16 +15183,16 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14806
15183
  if (!signal?.aborted && mounted.current) setRefreshing(false);
14807
15184
  }
14808
15185
  }, [account.botId, applySnapshot, invoke]);
14809
- React26.useEffect(() => {
15186
+ React27.useEffect(() => {
14810
15187
  const controller = new AbortController();
14811
15188
  void loadSettings({ signal: controller.signal, restoreProvisioning: true });
14812
15189
  return () => controller.abort();
14813
15190
  }, [loadSettings]);
14814
- const saveSetting = React26.useCallback(async (endpoint, payload) => {
15191
+ const saveSetting = React27.useCallback(async (endpoint, payload) => {
14815
15192
  const value = await invoke(endpoint, { botId: account.botId, ...payload });
14816
15193
  applySnapshot(value);
14817
15194
  }, [account.botId, applySnapshot, invoke]);
14818
- const startAuthorization = React26.useCallback(async ({ replace = false } = {}) => {
15195
+ const startAuthorization = React27.useCallback(async ({ replace = false } = {}) => {
14819
15196
  if (provisionBusy) return;
14820
15197
  const previousAttemptId = provision?.attemptId;
14821
15198
  setProvisionBusy(true);
@@ -14856,13 +15233,13 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14856
15233
  if (mounted.current) setProvisionBusy(false);
14857
15234
  }
14858
15235
  }, [account.botId, invoke, provision?.attemptId, provisionBusy]);
14859
- const finishAuthorization = React26.useCallback(async (signal) => {
15236
+ const finishAuthorization = React27.useCallback(async (signal) => {
14860
15237
  const bot = await loadSettings({ signal, restoreProvisioning: false });
14861
15238
  if (signal?.aborted || !mounted.current) return;
14862
15239
  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");
14863
15240
  setProvision(null);
14864
15241
  }, [loadSettings]);
14865
- React26.useEffect(() => {
15242
+ React27.useEffect(() => {
14866
15243
  if (!provision?.attemptId || !["qr", "connecting"].includes(provision.phase) || provision.expired) return void 0;
14867
15244
  const timerHost = globalThis.window ?? globalThis;
14868
15245
  const controller = new AbortController();
@@ -14906,7 +15283,7 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14906
15283
  timerHost.clearTimeout(timer);
14907
15284
  };
14908
15285
  }, [account.botId, finishAuthorization, invoke, provision]);
14909
- React26.useEffect(() => {
15286
+ React27.useEffect(() => {
14910
15287
  if (!provision?.attemptId || provision.phase !== "qr" || provision.expired) return void 0;
14911
15288
  const timerHost = globalThis.window ?? globalThis;
14912
15289
  const tick = () => {
@@ -14920,7 +15297,7 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14920
15297
  const timer = timerHost.setInterval(tick, 1e3);
14921
15298
  return () => timerHost.clearInterval(timer);
14922
15299
  }, [provision?.attemptId, provision?.expired, provision?.expiresAt, provision?.phase]);
14923
- const cancelAuthorization = React26.useCallback(async () => {
15300
+ const cancelAuthorization = React27.useCallback(async () => {
14924
15301
  if (!provision?.attemptId || provisionBusy) {
14925
15302
  setProvision(null);
14926
15303
  return;
@@ -15241,13 +15618,13 @@ function TargetForm({
15241
15618
  }) {
15242
15619
  const editing = mode === "edit";
15243
15620
  const initialKind = initialValue?.kind && definition.fields[initialValue.kind] ? initialValue.kind : definition.kinds[0].value;
15244
- const [targetId, setTargetId] = React27.useState(initialValue?.targetId ?? "");
15245
- const [name2, setName] = React27.useState(initialValue?.name ?? "");
15246
- const [kind, setKind] = React27.useState(initialKind);
15247
- const [route, setRoute] = React27.useState(initialValue?.route ?? {});
15248
- const [error, setError] = React27.useState(null);
15249
- const [testing, setTesting] = React27.useState(false);
15250
- const [testState, setTestState] = React27.useState(null);
15621
+ const [targetId, setTargetId] = React28.useState(initialValue?.targetId ?? "");
15622
+ const [name2, setName] = React28.useState(initialValue?.name ?? "");
15623
+ const [kind, setKind] = React28.useState(initialKind);
15624
+ const [route, setRoute] = React28.useState(initialValue?.route ?? {});
15625
+ const [error, setError] = React28.useState(null);
15626
+ const [testing, setTesting] = React28.useState(false);
15627
+ const [testState, setTestState] = React28.useState(null);
15251
15628
  const currentTarget = () => {
15252
15629
  const normalizedRoute = Object.fromEntries(fieldsFor(definition, kind).map((field) => {
15253
15630
  const raw = String(route[field.key] ?? "").trim();
@@ -15464,7 +15841,7 @@ function TargetSuggestionPicker({
15464
15841
  suggestions.map((suggestion, index) => {
15465
15842
  const identity = routeIdentity(definition, suggestion);
15466
15843
  const added = configured.has(identity);
15467
- return React27.createElement("option", {
15844
+ return React28.createElement("option", {
15468
15845
  key: suggestion.id ?? suggestion.suggestionId ?? `${identity}:${index}`,
15469
15846
  value: String(index),
15470
15847
  disabled: added
@@ -15481,11 +15858,11 @@ function TargetSuggestionPicker({
15481
15858
  );
15482
15859
  }
15483
15860
  function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, onEdit }) {
15484
- const [action, setAction] = React27.useState(null);
15485
- const [testState, setTestState] = React27.useState(null);
15486
- const [syncFeedback, setSyncFeedback] = React27.useState(null);
15487
- const [copyState, setCopyState] = React27.useState(null);
15488
- const [confirmDelete, setConfirmDelete] = React27.useState(false);
15861
+ const [action, setAction] = React28.useState(null);
15862
+ const [testState, setTestState] = React28.useState(null);
15863
+ const [syncFeedback, setSyncFeedback] = React28.useState(null);
15864
+ const [copyState, setCopyState] = React28.useState(null);
15865
+ const [confirmDelete, setConfirmDelete] = React28.useState(false);
15489
15866
  const sessionSync = target.sessionSync ?? { enabled: false, state: "unavailable" };
15490
15867
  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";
15491
15868
  const testTarget = async () => {
@@ -15548,7 +15925,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
15548
15925
  h2(
15549
15926
  "div",
15550
15927
  { className: "dim-targetTitle" },
15551
- React27.createElement("strong", null, target.name || target.targetId),
15928
+ React28.createElement("strong", null, target.name || target.targetId),
15552
15929
  h2("span", null, kindLabel(definition, target.kind))
15553
15930
  ),
15554
15931
  h2("code", null, `targetId: ${target.targetId}`)
@@ -15634,26 +16011,26 @@ function DeliveryTargetSettingsPage({
15634
16011
  onBack
15635
16012
  }) {
15636
16013
  const definition = CHANNEL_DEFINITIONS[channel5];
15637
- const [activeTabId, setActiveTabId] = React27.useState(BOT_SETTINGS_TABS[0].id);
15638
- const [phase, setPhase] = React27.useState("loading");
15639
- const [targets, setTargets] = React27.useState([]);
15640
- const [suggestionPhase, setSuggestionPhase] = React27.useState("idle");
15641
- const [suggestions, setSuggestions] = React27.useState([]);
15642
- const [suggestionError, setSuggestionError] = React27.useState(null);
15643
- const [error, setError] = React27.useState(null);
15644
- const [editor, setEditor] = React27.useState(null);
15645
- const [saving, setSaving] = React27.useState(false);
15646
- const [botCopyState, setBotCopyState] = React27.useState(null);
15647
- const [accessPolicy, setAccessPolicy] = React27.useState(account.accessPolicy);
15648
- const mounted = React27.useRef(true);
15649
- React27.useEffect(() => {
16014
+ const [activeTabId, setActiveTabId] = React28.useState(BOT_SETTINGS_TABS[0].id);
16015
+ const [phase, setPhase] = React28.useState("loading");
16016
+ const [targets, setTargets] = React28.useState([]);
16017
+ const [suggestionPhase, setSuggestionPhase] = React28.useState("idle");
16018
+ const [suggestions, setSuggestions] = React28.useState([]);
16019
+ const [suggestionError, setSuggestionError] = React28.useState(null);
16020
+ const [error, setError] = React28.useState(null);
16021
+ const [editor, setEditor] = React28.useState(null);
16022
+ const [saving, setSaving] = React28.useState(false);
16023
+ const [botCopyState, setBotCopyState] = React28.useState(null);
16024
+ const [accessPolicy, setAccessPolicy] = React28.useState(account.accessPolicy);
16025
+ const mounted = React28.useRef(true);
16026
+ React28.useEffect(() => {
15650
16027
  setAccessPolicy(account.accessPolicy);
15651
16028
  }, [account.botId, account.accessPolicy]);
15652
- const invoke = React27.useCallback(async (endpoint, payload = {}, signal) => {
16029
+ const invoke = React28.useCallback(async (endpoint, payload = {}, signal) => {
15653
16030
  if (typeof rpcCall !== "function") throw new Error("\u6295\u9012\u76EE\u6807\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
15654
16031
  return unwrapRpcResult13(await rpcCall(endpoint, payload, signal));
15655
16032
  }, [rpcCall]);
15656
- const loadTargets = React27.useCallback(async ({ signal, silent = false } = {}) => {
16033
+ const loadTargets = React28.useCallback(async ({ signal, silent = false } = {}) => {
15657
16034
  if (!silent) setPhase("loading");
15658
16035
  setError(null);
15659
16036
  try {
@@ -15667,7 +16044,7 @@ function DeliveryTargetSettingsPage({
15667
16044
  setPhase("error");
15668
16045
  }
15669
16046
  }, [account.botId, invoke]);
15670
- const loadSuggestions = React27.useCallback(async () => {
16047
+ const loadSuggestions = React28.useCallback(async () => {
15671
16048
  setSuggestionPhase("loading");
15672
16049
  setSuggestionError(null);
15673
16050
  try {
@@ -15681,7 +16058,7 @@ function DeliveryTargetSettingsPage({
15681
16058
  setSuggestionPhase("error");
15682
16059
  }
15683
16060
  }, [account.botId, definition, invoke]);
15684
- React27.useEffect(() => {
16061
+ React28.useEffect(() => {
15685
16062
  mounted.current = true;
15686
16063
  const controller = new AbortController();
15687
16064
  void loadTargets({ signal: controller.signal });
@@ -15803,7 +16180,7 @@ function DeliveryTargetSettingsPage({
15803
16180
  account,
15804
16181
  rpcCall: accessRpcCall
15805
16182
  }) : h2(
15806
- React27.Fragment,
16183
+ React28.Fragment,
15807
16184
  null,
15808
16185
  h2(
15809
16186
  "section",
@@ -15914,7 +16291,7 @@ function DeliveryTargetSettingsPage({
15914
16291
  }
15915
16292
 
15916
16293
  // plugin-src/client/global-settings.js
15917
- var React28 = __toESM(require("react"), 1);
16294
+ var React29 = __toESM(require("react"), 1);
15918
16295
 
15919
16296
  // src/channels/shared/inbound-ttl.mjs
15920
16297
  var DEFAULT_INBOUND_TTL_HOURS = 168;
@@ -15976,29 +16353,29 @@ function GlobalButton({ children, kind = "secondary", className = "", ...props }
15976
16353
  }, children);
15977
16354
  }
15978
16355
  function GlobalSettingsPanel({ rpcCall }) {
15979
- const [phase, setPhase] = React28.useState("loading");
15980
- const [loadError, setLoadError] = React28.useState(null);
15981
- const [ttlInput, setTtlInput] = React28.useState("");
15982
- const [savedTtl, setSavedTtl] = React28.useState(null);
15983
- const [ttlError, setTtlError] = React28.useState(false);
15984
- const [saveError, setSaveError] = React28.useState(null);
15985
- const [saveSucceeded, setSaveSucceeded] = React28.useState(false);
15986
- const [isSaving, setIsSaving] = React28.useState(false);
15987
- const [sweepConfirming, setSweepConfirming] = React28.useState(false);
15988
- const [sweeping, setSweeping] = React28.useState(false);
15989
- const ttlErrorId = React28.useId();
15990
- const ttlHintsId = React28.useId();
15991
- const sweepTriggerId = React28.useId();
15992
- const sweepConfirmId = React28.useId();
15993
- const sweepConfirmTextId = React28.useId();
15994
- const sweepConfirmButtonId = React28.useId();
15995
- const mounted = React28.useRef(true);
15996
- const saving = React28.useRef(false);
15997
- const invoke = React28.useCallback(async (endpoint, payload = {}, signal) => {
16356
+ const [phase, setPhase] = React29.useState("loading");
16357
+ const [loadError, setLoadError] = React29.useState(null);
16358
+ const [ttlInput, setTtlInput] = React29.useState("");
16359
+ const [savedTtl, setSavedTtl] = React29.useState(null);
16360
+ const [ttlError, setTtlError] = React29.useState(false);
16361
+ const [saveError, setSaveError] = React29.useState(null);
16362
+ const [saveSucceeded, setSaveSucceeded] = React29.useState(false);
16363
+ const [isSaving, setIsSaving] = React29.useState(false);
16364
+ const [sweepConfirming, setSweepConfirming] = React29.useState(false);
16365
+ const [sweeping, setSweeping] = React29.useState(false);
16366
+ const ttlErrorId = React29.useId();
16367
+ const ttlHintsId = React29.useId();
16368
+ const sweepTriggerId = React29.useId();
16369
+ const sweepConfirmId = React29.useId();
16370
+ const sweepConfirmTextId = React29.useId();
16371
+ const sweepConfirmButtonId = React29.useId();
16372
+ const mounted = React29.useRef(true);
16373
+ const saving = React29.useRef(false);
16374
+ const invoke = React29.useCallback(async (endpoint, payload = {}, signal) => {
15998
16375
  if (typeof rpcCall !== "function") throw new Error("\u901A\u7528\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
15999
16376
  return unwrapRpcResult14(await rpcCall(endpoint, payload, signal));
16000
16377
  }, [rpcCall]);
16001
- const loadSettings = React28.useCallback(async ({ signal } = {}) => {
16378
+ const loadSettings = React29.useCallback(async ({ signal } = {}) => {
16002
16379
  setPhase("loading");
16003
16380
  setLoadError(null);
16004
16381
  try {
@@ -16022,7 +16399,7 @@ function GlobalSettingsPanel({ rpcCall }) {
16022
16399
  setPhase("error");
16023
16400
  }
16024
16401
  }, [invoke]);
16025
- React28.useEffect(() => {
16402
+ React29.useEffect(() => {
16026
16403
  mounted.current = true;
16027
16404
  const controller = new AbortController();
16028
16405
  void loadSettings({ signal: controller.signal });
@@ -16031,7 +16408,7 @@ function GlobalSettingsPanel({ rpcCall }) {
16031
16408
  controller.abort();
16032
16409
  };
16033
16410
  }, [loadSettings]);
16034
- React28.useEffect(() => {
16411
+ React29.useEffect(() => {
16035
16412
  if (!sweepConfirming) return;
16036
16413
  globalThis.document?.getElementById(sweepConfirmButtonId)?.focus();
16037
16414
  }, [sweepConfirmButtonId, sweepConfirming]);
@@ -17303,7 +17680,7 @@ function installSessionChannelLogos(document2 = globalThis.document) {
17303
17680
  }
17304
17681
 
17305
17682
  // plugin-src/client/update-panel.js
17306
- var React29 = __toESM(require("react"), 1);
17683
+ var React30 = __toESM(require("react"), 1);
17307
17684
  var import_react_dom4 = require("react-dom");
17308
17685
  var import_valid = __toESM(require_valid(), 1);
17309
17686
  var import_rcompare = __toESM(require_rcompare(), 1);
@@ -17393,11 +17770,11 @@ function manualUpdateCommand(snapshot) {
17393
17770
  return `dsh plugin --profile ${profileArgument} add -w @xmanrui/dsh-im@${version}`;
17394
17771
  }
17395
17772
  function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
17396
- const [copyState, setCopyState] = React29.useState("idle");
17397
- const commandRef = React29.useRef(null);
17398
- const mounted = React29.useRef(false);
17399
- const copying = React29.useRef(false);
17400
- React29.useEffect(() => {
17773
+ const [copyState, setCopyState] = React30.useState("idle");
17774
+ const commandRef = React30.useRef(null);
17775
+ const mounted = React30.useRef(false);
17776
+ const copying = React30.useRef(false);
17777
+ React30.useEffect(() => {
17401
17778
  mounted.current = true;
17402
17779
  return () => {
17403
17780
  mounted.current = false;
@@ -17429,7 +17806,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
17429
17806
  { className: "dim-updateManual", "aria-label": "\u624B\u5DE5\u66F4\u65B0" },
17430
17807
  h2("h4", { className: "dim-updateManualHeading" }, "\u624B\u5DE5\u66F4\u65B0"),
17431
17808
  command ? h2(
17432
- React29.Fragment,
17809
+ React30.Fragment,
17433
17810
  null,
17434
17811
  h2("p", { className: "dim-updateManualHint" }, "\u81EA\u52A8\u66F4\u65B0\u5931\u8D25\u53EF\u4EE5\u4F7F\u7528\u547D\u4EE4\u66F4\u65B0\uFF1A"),
17435
17812
  h2(
@@ -17465,7 +17842,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
17465
17842
  "aria-hidden": "true",
17466
17843
  focusable: "false"
17467
17844
  }, copyState === "copied" ? h2("path", { d: "m4 10 4 4 8-8" }) : h2(
17468
- React29.Fragment,
17845
+ React30.Fragment,
17469
17846
  null,
17470
17847
  h2("rect", { x: 7, y: 7, width: 10, height: 11, rx: 1.5 }),
17471
17848
  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" })
@@ -17490,10 +17867,10 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
17490
17867
  );
17491
17868
  }
17492
17869
  function UpdateDialog({ children, onClose }) {
17493
- const dialogRef = React29.useRef(null);
17494
- const titleId = React29.useId();
17495
- const descriptionId = React29.useId();
17496
- React29.useEffect(() => {
17870
+ const dialogRef = React30.useRef(null);
17871
+ const titleId = React30.useId();
17872
+ const descriptionId = React30.useId();
17873
+ React30.useEffect(() => {
17497
17874
  const previous = globalThis.document?.activeElement;
17498
17875
  dialogRef.current?.focus?.();
17499
17876
  return () => {
@@ -17551,19 +17928,19 @@ function UpdateDialog({ children, onClose }) {
17551
17928
  return typeof document !== "undefined" && document.body ? (0, import_react_dom4.createPortal)(content, document.body) : content;
17552
17929
  }
17553
17930
  function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17554
- const [snapshot, setSnapshot] = React29.useState(null);
17555
- const [action, setAction] = React29.useState("status");
17556
- const [error, setError] = React29.useState(null);
17557
- const [open, setOpen] = React29.useState(false);
17558
- const [uncertainInstall, setUncertainInstall] = React29.useState(false);
17559
- const mounted = React29.useRef(false);
17560
- const busy = React29.useRef(false);
17561
- const readController = React29.useRef(null);
17562
- const pollReadController = React29.useRef(null);
17563
- const installRequest = React29.useRef(null);
17564
- const onStatusRef = React29.useRef(onStatus);
17931
+ const [snapshot, setSnapshot] = React30.useState(null);
17932
+ const [action, setAction] = React30.useState("status");
17933
+ const [error, setError] = React30.useState(null);
17934
+ const [open, setOpen] = React30.useState(false);
17935
+ const [uncertainInstall, setUncertainInstall] = React30.useState(false);
17936
+ const mounted = React30.useRef(false);
17937
+ const busy = React30.useRef(false);
17938
+ const readController = React30.useRef(null);
17939
+ const pollReadController = React30.useRef(null);
17940
+ const installRequest = React30.useRef(null);
17941
+ const onStatusRef = React30.useRef(onStatus);
17565
17942
  onStatusRef.current = onStatus;
17566
- const accept = React29.useCallback((next) => {
17943
+ const accept = React30.useCallback((next) => {
17567
17944
  setSnapshot(next);
17568
17945
  onStatusRef.current?.(next);
17569
17946
  }, []);
@@ -17572,7 +17949,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17572
17949
  setUncertainInstall(false);
17573
17950
  accept(next);
17574
17951
  };
17575
- const invoke = React29.useCallback(async (endpoint, payload = {}, signal) => {
17952
+ const invoke = React30.useCallback(async (endpoint, payload = {}, signal) => {
17576
17953
  if (typeof rpcCall !== "function") {
17577
17954
  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");
17578
17955
  unavailable.code = "update-unavailable";
@@ -17580,7 +17957,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17580
17957
  }
17581
17958
  return unwrapSnapshot(await rpcCall(endpoint, payload, signal));
17582
17959
  }, [rpcCall]);
17583
- React29.useEffect(() => {
17960
+ React30.useEffect(() => {
17584
17961
  mounted.current = true;
17585
17962
  busy.current = true;
17586
17963
  const controller = new AbortController();
@@ -17603,7 +17980,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17603
17980
  const activeJob = ACTIVE_STATES4.has(snapshot?.job?.state);
17604
17981
  const restartRequired = snapshot?.job?.state === "restart-required" || snapshot?.blockedReason === "pending-restart";
17605
17982
  const shouldPoll = activeJob || uncertainInstall;
17606
- React29.useEffect(() => {
17983
+ React30.useEffect(() => {
17607
17984
  if (!shouldPoll) return void 0;
17608
17985
  let controller;
17609
17986
  const scheduler = createPollScheduler({
@@ -17701,7 +18078,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17701
18078
  const manualCommand = manualUpdateCommand(snapshot);
17702
18079
  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";
17703
18080
  return h2(
17704
- React29.Fragment,
18081
+ React30.Fragment,
17705
18082
  null,
17706
18083
  h2("button", {
17707
18084
  type: "button",
@@ -17726,13 +18103,13 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17726
18103
  h2("dt", null, "\u8FD0\u884C\u7248\u672C"),
17727
18104
  h2("dd", null, `v${snapshot?.runningVersion ?? clientVersion}`),
17728
18105
  snapshot?.installedVersion && snapshot.installedVersion !== snapshot.runningVersion ? h2(
17729
- React29.Fragment,
18106
+ React30.Fragment,
17730
18107
  null,
17731
18108
  h2("dt", null, "\u5DF2\u5B89\u88C5\u7248\u672C"),
17732
18109
  h2("dd", null, `v${snapshot.installedVersion}`)
17733
18110
  ) : null,
17734
18111
  targetVersion ? h2(
17735
- React29.Fragment,
18112
+ React30.Fragment,
17736
18113
  null,
17737
18114
  h2("dt", null, "\u76EE\u6807\u7248\u672C"),
17738
18115
  h2("dd", null, `v${targetVersion}`)
@@ -17953,23 +18330,23 @@ function IMSettingsTab({
17953
18330
  browserLocation = globalThis.location,
17954
18331
  navigateToRecoveryUrl = replacePageLocation
17955
18332
  }) {
17956
- const [selected, setSelected] = React30.useState("weixin");
17957
- const [loopbackRecovery, setLoopbackRecovery] = React30.useState(null);
17958
- const [runningVersion, setRunningVersion] = React30.useState(IM_PLUGIN_VERSION);
17959
- const [deliverySettings, setDeliverySettings] = React30.useState(null);
17960
- const githubTooltipId = React30.useId();
17961
- const generalSettingsTooltipId = React30.useId();
18333
+ const [selected, setSelected] = React31.useState("weixin");
18334
+ const [loopbackRecovery, setLoopbackRecovery] = React31.useState(null);
18335
+ const [runningVersion, setRunningVersion] = React31.useState(IM_PLUGIN_VERSION);
18336
+ const [deliverySettings, setDeliverySettings] = React31.useState(null);
18337
+ const githubTooltipId = React31.useId();
18338
+ const generalSettingsTooltipId = React31.useId();
17962
18339
  const globalSettingsSelected = selected === GLOBAL_SETTINGS_TAB_ID;
17963
18340
  const active = CHANNELS.find((channel5) => channel5.id === selected) ?? CHANNELS[0];
17964
18341
  const activeTabId = globalSettingsSelected ? "dim-general-settings-trigger" : `dim-tab-${active.id}`;
17965
18342
  const activePanelId = globalSettingsSelected ? `dim-panel-${GLOBAL_SETTINGS_TAB_ID}` : `dim-panel-${active.id}`;
17966
- const reportLoopbackRecovery = React30.useCallback((recovery) => {
18343
+ const reportLoopbackRecovery = React31.useCallback((recovery) => {
17967
18344
  setLoopbackRecovery((current) => current?.url === recovery.url ? current : recovery);
17968
18345
  }, []);
17969
- const reportUpdateStatus = React30.useCallback((snapshot) => {
18346
+ const reportUpdateStatus = React31.useCallback((snapshot) => {
17970
18347
  setRunningVersion(snapshot.runningVersion);
17971
18348
  }, []);
17972
- const rpcCalls = React30.useMemo(() => createLoopbackAwareRpcCalls({
18349
+ const rpcCalls = React31.useMemo(() => createLoopbackAwareRpcCalls({
17973
18350
  dingtalkRpcCall,
17974
18351
  discordRpcCall,
17975
18352
  feishuRpcCall,
@@ -18007,7 +18384,7 @@ function IMSettingsTab({
18007
18384
  weixinRpcCall,
18008
18385
  whatsappRpcCall
18009
18386
  ]);
18010
- const botSettingsContext = React30.useMemo(() => Object.freeze({
18387
+ const botSettingsContext = React31.useMemo(() => Object.freeze({
18011
18388
  openBotSettings: setDeliverySettings
18012
18389
  }), []);
18013
18390
  return h2(