@xmanrui/dsh-im 2.3.0 → 2.5.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 (57) hide show
  1. package/README.en.md +9 -4
  2. package/README.md +9 -4
  3. package/lib/client.js +411 -156
  4. package/lib/index.js +218 -210
  5. package/package.json +1 -1
  6. package/plugin-src/client/channel-card-meta.js +36 -1
  7. package/plugin-src/client/channels/dingtalk/api.js +2 -0
  8. package/plugin-src/client/channels/dingtalk/index.js +9 -1
  9. package/plugin-src/client/channels/feishu/api.js +3 -0
  10. package/plugin-src/client/channels/feishu/index.js +46 -28
  11. package/plugin-src/client/channels/feishu/styles.js +26 -1
  12. package/plugin-src/client/channels/qq/api.js +2 -0
  13. package/plugin-src/client/channels/qq/index.js +9 -1
  14. package/plugin-src/client/channels/shared/token-api.js +2 -0
  15. package/plugin-src/client/channels/shared/token-channel.js +9 -1
  16. package/plugin-src/client/channels/wecom/api.js +2 -0
  17. package/plugin-src/client/channels/wecom/index.js +9 -1
  18. package/plugin-src/client/channels/weixin/api.js +2 -10
  19. package/plugin-src/client/channels/weixin/index.js +9 -5
  20. package/plugin-src/client/channels/whatsapp/api.js +2 -0
  21. package/plugin-src/client/channels/whatsapp/index.js +9 -1
  22. package/plugin-src/client/i18n.js +31 -25
  23. package/plugin-src/client/index.js +16 -2
  24. package/plugin-src/client/last-message-error.js +17 -0
  25. package/plugin-src/client/styles.js +5 -1
  26. package/plugin-src/host/channels/feishu/rpc.mjs +3 -0
  27. package/src/channels/dingtalk/dingtalk-api.mjs +1 -1
  28. package/src/channels/dingtalk/dingtalk-bridge.mjs +50 -16
  29. package/src/channels/dingtalk/dingtalk-card-stream.mjs +2 -2
  30. package/src/channels/dingtalk/dingtalk-controller.mjs +2 -0
  31. package/src/channels/feishu/bridge.mjs +148 -70
  32. package/src/channels/feishu/feishu-cards.mjs +10 -6
  33. package/src/channels/feishu/feishu-runtime.mjs +0 -1
  34. package/src/channels/feishu/message-utils.mjs +1 -1
  35. package/src/channels/feishu/multi-bot-controller.mjs +3 -17
  36. package/src/channels/feishu/repair-manager.mjs +7 -2
  37. package/src/channels/qq/qq-bridge.mjs +84 -28
  38. package/src/channels/qq/qq-controller.mjs +2 -0
  39. package/src/channels/shared/control-command.mjs +11 -1
  40. package/src/channels/shared/harness-client.mjs +40 -4
  41. package/src/channels/shared/i18n-en/feishu.mjs +27 -25
  42. package/src/channels/shared/i18n-en/shared-a.mjs +78 -0
  43. package/src/channels/shared/i18n-en/shared-b.mjs +1 -0
  44. package/src/channels/shared/i18n-en/telegram.mjs +1 -0
  45. package/src/channels/shared/message-failure.mjs +244 -0
  46. package/src/channels/shared/semantic/artifact-delivery.mjs +9 -2
  47. package/src/channels/shared/text-harness-bridge.mjs +66 -60
  48. package/src/channels/shared/token-bot-controller.mjs +2 -0
  49. package/src/channels/slack/slack-controller.mjs +2 -0
  50. package/src/channels/telegram/telegram-runtime.mjs +1 -0
  51. package/src/channels/wecom/wecom-bridge.mjs +50 -15
  52. package/src/channels/wecom/wecom-controller.mjs +2 -0
  53. package/src/channels/weixin/weixin-api.mjs +47 -0
  54. package/src/channels/weixin/weixin-bridge.mjs +262 -43
  55. package/src/channels/weixin/weixin-controller.mjs +2 -15
  56. package/src/channels/weixin/weixin-runtime.mjs +1 -0
  57. package/src/channels/whatsapp/whatsapp-controller.mjs +2 -0
package/lib/client.js CHANGED
@@ -35,6 +35,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
35
35
  var index_exports = {};
36
36
  __export(index_exports, {
37
37
  IMSettingsTab: () => IMSettingsTab,
38
+ IM_PLUGIN_VERSION: () => IM_PLUGIN_VERSION,
38
39
  LoopbackRecoveryNotice: () => LoopbackRecoveryNotice,
39
40
  apply: () => apply,
40
41
  inject: () => inject,
@@ -43,6 +44,115 @@ __export(index_exports, {
43
44
  module.exports = __toCommonJS(index_exports);
44
45
  var React20 = __toESM(require("react"), 1);
45
46
 
47
+ // package.json
48
+ var package_default = {
49
+ name: "@xmanrui/dsh-im",
50
+ version: "2.5.0",
51
+ description: "\u628A\u4E5D\u79CD IM \u673A\u5668\u4EBA\u548C\u516C\u7F51 AI Office \u63A5\u5165\u672C\u673A DeepSeek Harness\u3002 Connect nine IM channels and a public AI Office to a local DeepSeek Harness.",
52
+ keywords: [
53
+ "deepseek-harness",
54
+ "dsh",
55
+ "dsh-plugin",
56
+ "ai-agent",
57
+ "im",
58
+ "instant-messaging",
59
+ "chatbot",
60
+ "feishu",
61
+ "lark",
62
+ "wechat",
63
+ "wecom",
64
+ "dingtalk",
65
+ "qq",
66
+ "slack",
67
+ "telegram",
68
+ "discord",
69
+ "whatsapp",
70
+ "ai-office"
71
+ ],
72
+ author: {
73
+ name: "xmanrui",
74
+ url: "https://github.com/xmanrui"
75
+ },
76
+ contributors: [
77
+ {
78
+ name: "C3H3-AI",
79
+ url: "https://github.com/C3H3-AI"
80
+ }
81
+ ],
82
+ license: "MIT",
83
+ type: "module",
84
+ repository: {
85
+ type: "git",
86
+ url: "git+https://github.com/xmanrui/dsh-im.git"
87
+ },
88
+ homepage: "https://github.com/xmanrui/dsh-im#readme",
89
+ bugs: "https://github.com/xmanrui/dsh-im/issues",
90
+ publishConfig: {
91
+ access: "public"
92
+ },
93
+ bin: {
94
+ "dsh-im": "bin/dsh-im.mjs"
95
+ },
96
+ main: "./lib/index.js",
97
+ exports: {
98
+ ".": "./lib/index.js",
99
+ "./client": "./lib/client.js",
100
+ "./package.json": "./package.json"
101
+ },
102
+ files: [
103
+ "assets",
104
+ "bin",
105
+ "cordis.patch.yml",
106
+ "lib",
107
+ "plugin-src",
108
+ "scripts",
109
+ "src",
110
+ "LICENSE",
111
+ "README.md",
112
+ "README.en.md",
113
+ "THIRD_PARTY_NOTICES.md"
114
+ ],
115
+ dsh: {
116
+ bundle: {
117
+ patch: "./cordis.patch.yml"
118
+ },
119
+ client: {
120
+ inject: [
121
+ "@deepseek-ai/dsh-client-connection",
122
+ "@deepseek-ai/dsh-client-runtime",
123
+ "@deepseek-ai/dsh-client-ui-settings",
124
+ "@deepseek-ai/dsh-client-ui-slots",
125
+ "@deepseek-ai/dsh-client-locale"
126
+ ],
127
+ platform: "web"
128
+ }
129
+ },
130
+ scripts: {
131
+ build: "node plugin-src/client/build.mjs && node plugin-src/host/build.mjs",
132
+ test: "node --test test/*.test.mjs test/channels/*/*.test.mjs",
133
+ check: "npm test && npm run build && node scripts/verify-package.mjs"
134
+ },
135
+ engines: {
136
+ node: ">=22.19"
137
+ },
138
+ dependencies: {
139
+ "@tencent-connect/qqbot-connector": "1.2.0",
140
+ "@tencent-connect/qqbot-nodejs": "1.0.4",
141
+ "@wecom/aibot-node-sdk": "1.0.7",
142
+ "dingtalk-stream": "2.1.4",
143
+ qrcode: "1.5.4"
144
+ },
145
+ devDependencies: {
146
+ "@larksuiteoapi/node-sdk": "1.73.0",
147
+ "@whiskeysockets/baileys": "7.0.0-rc14",
148
+ esbuild: "0.25.9",
149
+ "https-proxy-agent": "5.0.1",
150
+ react: "18.3.1",
151
+ "react-dom": "18.3.1",
152
+ "react-test-renderer": "18.3.1"
153
+ }
154
+ };
155
+
46
156
  // plugin-src/client/channel-logos.js
47
157
  var React = __toESM(require("react"), 1);
48
158
  var h = React.createElement;
@@ -199,6 +309,7 @@ var EN = Object.freeze({
199
309
  "IM\u673A\u5668\u4EBA\u8BBE\u7F6E": "IM bot settings",
200
310
  "IM \u6E20\u9053": "IM channels",
201
311
  "\u8BA9 DeepSeek Harness \u89E6\u624B\u53EF\u53CA": "DeepSeek Harness, always within reach",
312
+ "\u5F53\u524D\u7248\u672C": "Current version",
202
313
  "AI Office": "AI Office",
203
314
  "\uFF08\u5B9E\u9A8C\u529F\u80FD\uFF09": "(Experimental)",
204
315
  "AI Office \u8BBE\u7F6E": "AI Office settings",
@@ -304,6 +415,9 @@ var EN = Object.freeze({
304
415
  "\u6D88\u606F\u901A\u9053": "Message channel",
305
416
  "\u67E5\u770B\u6D88\u606F\u901A\u9053\u8BF4\u660E": "View message channel details",
306
417
  "\u6700\u8FD1\u68C0\u67E5": "Last checked",
418
+ "\u6700\u8FD1\u4E00\u6761\u6D88\u606F\u5904\u7406\u5931\u8D25": "Latest message failed",
419
+ "\u9519\u8BEF\u7801": "Code",
420
+ "\u53C2\u8003\u53F7": "Reference",
307
421
  "\u5F53\u524D\u5DE5\u4F5C\u533A": "Current workspace",
308
422
  "\u9009\u62E9\u76EE\u5F55": "Choose folder",
309
423
  "\u9009\u62E9\u673A\u5668\u4EBA\u5DE5\u4F5C\u533A\u76EE\u5F55": "Select bot workspace folder",
@@ -422,7 +536,7 @@ var EN = Object.freeze({
422
536
  "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u65B0\u673A\u5668\u4EBA\u7684\u957F\u8FDE\u63A5\u5C31\u7EEA": "Keep this page open until the bot connection is ready",
423
537
  "\u5728\u98DE\u4E66\u4E2D\u6253\u5F00": "Open in Feishu",
424
538
  "\u53D6\u6D88\u6DFB\u52A0": "Cancel",
425
- "\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u4FEE\u590D\u5361\u7247\u6309\u94AE": "Scan with Feishu to repair card buttons",
539
+ "\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u8865\u5168\u6743\u9650": "Scan with Feishu to complete permissions",
426
540
  "\u4F7F\u7528\u98DE\u4E66\u786E\u8BA4\u7FA4\u6D88\u606F\u6743\u9650": "Confirm group-message permission with Feishu",
427
541
  "\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u53EA\u589E\u91CF\u5F00\u901A\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u540E\u4F1A\u81EA\u52A8\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002": "Scanning updates the existing Feishu app with only the \u201CRead all messages in associated group chat\u201D scope. It does not create a new app. After confirmation, \u201CRespond to all group messages\u201D is enabled automatically; other bots are unaffected.",
428
542
  "\u6838\u5BF9\u73B0\u6709\u5E94\u7528\uFF0C\u5E76\u786E\u8BA4\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650": "Review the existing app and confirm the \u201CRead all messages in associated group chat\u201D permission",
@@ -433,18 +547,20 @@ var EN = Object.freeze({
433
547
  "\u6743\u9650\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u542F\u7528\u5168\u90E8\u6D88\u606F\u6A21\u5F0F\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002": "The permission update was submitted. Enabling all-message mode and reconnecting this bot. This stage cannot be cancelled; other bots will not be interrupted.",
434
548
  "\u6B63\u5728\u4E3A\u73B0\u6709\u98DE\u4E66\u5E94\u7528\u7533\u8BF7\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002": "Requesting a group-message permission QR code for the existing Feishu app\u2026",
435
549
  "\u7FA4\u6D88\u606F\u6743\u9650\u6CA1\u6709\u5F00\u901A\u5B8C\u6210": "Group-message permission was not granted",
436
- "\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u53EA\u589E\u91CF\u8865\u5145\u5361\u7247\u6309\u94AE\u56DE\u8C03\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u540E\u6B64\u673A\u5668\u4EBA\u4F1A\u77ED\u6682\u91CD\u8FDE\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002": "Scanning updates the existing Feishu app with only the card-button callback. It does not create a new app. This bot reconnects briefly after confirmation; other bots are not affected.",
437
- "\u6838\u5BF9\u73B0\u6709\u5E94\u7528\u540D\u79F0\uFF0C\u5E76\u786E\u8BA4\u53EA\u65B0\u589E\u5361\u7247\u56DE\u8C03": "Review the existing app name and confirm that only the card callback is added",
438
- "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u5361\u7247\u6309\u94AE\u4FEE\u590D\u5B8C\u6210": "Keep this page open until card-button repair finishes",
439
- "\u53D6\u6D88\u4FEE\u590D": "Cancel repair",
440
- "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u5B8C\u6210\u5361\u7247\u6309\u94AE\u4FEE\u590D": "Confirmed. Finishing card-button repair",
441
- "\u6B63\u5728\u51C6\u5907\u4FEE\u590D\u4E8C\u7EF4\u7801": "Preparing the repair QR code",
442
- "\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u9A8C\u8BC1\u5361\u7247\u6309\u94AE\u56DE\u8C03\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002": "The update was submitted. Verifying the card callback and reconnecting this bot. This stage cannot be cancelled; other bots will not be interrupted.",
550
+ "\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u6700\u591A\u589E\u91CF\u8865\u5145\u5361\u7247\u6309\u94AE\u56DE\u8C03\u3001\u8BFB\u53D6\u7528\u6237\u6D88\u606F\u5185\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:message:readonly\uFF08\u98DE\u4E66\u663E\u793A\u4E3A\u201C\u83B7\u53D6\u5355\u804A\u3001\u7FA4\u7EC4\u6D88\u606F\u201D\uFF09\uFF0C\u4EE5\u53CA\u4E0A\u4F20\u673A\u5668\u4EBA\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:resource\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u9875\u53EA\u663E\u793A\u5F53\u524D\u7F3A\u5C11\u9879\uFF0C\u5B8C\u6210\u540E\u6B64\u673A\u5668\u4EBA\u4F1A\u77ED\u6682\u91CD\u8FDE\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002": "Scanning updates the existing Feishu app with up to three missing items: the card-button callback, im:message:readonly for reading images or files in user messages (shown by Feishu as \u201CRead direct and group messages\u201D), and im:resource for uploading images or files sent by the bot. It does not create a new app. The confirmation page shows only missing items; this bot reconnects briefly afterward, while other bots are unaffected.",
551
+ "\u6838\u5BF9\u73B0\u6709\u5E94\u7528\u540D\u79F0\uFF0C\u5E76\u786E\u8BA4\u53EA\u65B0\u589E\u5F53\u524D\u7F3A\u5C11\u7684\u4E0A\u8FF0\u914D\u7F6E": "Review the existing app name and confirm that only the missing items described above are added",
552
+ "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u6743\u9650\u4E0E\u56DE\u8C03\u8865\u5168\u5B8C\u6210": "Keep this page open until permissions and the callback are complete",
553
+ "\u53D6\u6D88\u8865\u5168": "Cancel setup",
554
+ "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u5B8C\u6210\u6743\u9650\u4E0E\u56DE\u8C03\u914D\u7F6E": "Confirmed. Completing permissions and callback setup",
555
+ "\u6B63\u5728\u51C6\u5907\u6743\u9650\u8865\u5168\u4E8C\u7EF4\u7801": "Preparing the permission-completion QR code",
556
+ "\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u4FDD\u5B58\u6743\u9650\u3001\u9A8C\u8BC1\u5361\u7247\u56DE\u8C03\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002": "The update was submitted. Saving permissions, verifying the card callback, and reconnecting this bot. This stage cannot be cancelled; other bots will not be interrupted.",
443
557
  "\u6B63\u5728\u4E3A\u73B0\u6709\u98DE\u4E66\u5E94\u7528\u7533\u8BF7\u4E00\u6B21\u6027\u66F4\u65B0\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002": "Requesting a one-time update QR code for the existing Feishu app\u2026",
444
- "\u5361\u7247\u6309\u94AE\u6CA1\u6709\u4FEE\u590D\u5B8C\u6210": "Card-button repair did not finish",
445
- "\u4FEE\u590D\u5361\u7247\u6309\u94AE": "Repair card buttons",
558
+ "\u6743\u9650\u4E0E\u56DE\u8C03\u6CA1\u6709\u8865\u5168\u5B8C\u6210": "Permissions and callback setup did not finish",
559
+ "\u8865\u5168\u6743\u9650": "Complete permissions",
560
+ "\u8865\u5168\u8303\u56F4": "Completion scope",
561
+ "\u6700\u591A\u589E\u91CF\u6DFB\u52A0\u5361\u7247\u56DE\u8C03 card.action.trigger\u3001\u8BFB\u53D6\u6D88\u606F\u5185\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:message:readonly\uFF08\u98DE\u4E66\u663E\u793A\u4E3A\u201C\u83B7\u53D6\u5355\u804A\u3001\u7FA4\u7EC4\u6D88\u606F\u201D\uFF09\uFF0C\u4EE5\u53CA\u4E0A\u4F20\u673A\u5668\u4EBA\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:resource\uFF1B\u786E\u8BA4\u9875\u53EA\u663E\u793A\u5F53\u524D\u7F3A\u5C11\u9879\uFF0C\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002": "Adds up to the missing card callback card.action.trigger, im:message:readonly for reading images or files in messages (shown by Feishu as \u201CRead direct and group messages\u201D), and im:resource for uploading images or files sent by the bot. The confirmation page shows only missing items; no new app is created.",
446
562
  "\u7B49\u5F85\u626B\u7801\u2026": "Waiting for scan\u2026",
447
- "\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u5361\u7247\u4FEE\u590D\u4E8C\u7EF4\u7801": "Feishu returned a repair QR code for a different bot",
563
+ "\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u6743\u9650\u8865\u5168\u4E8C\u7EF4\u7801": "Feishu returned a permission-completion QR code for a different bot",
448
564
  "\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801": "Feishu returned a group-message permission QR code for a different bot",
449
565
  "\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u7684\u4FEE\u590D\u4FE1\u606F\u7F3A\u5C11 botId": "Feishu repair status is missing the bot ID",
450
566
  "\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u7684\u5E94\u7528\u66F4\u65B0\u4FE1\u606F\u7F3A\u5C11 botId": "Feishu app-update status is missing the bot ID",
@@ -452,16 +568,16 @@ var EN = Object.freeze({
452
568
  "\u6B64\u673A\u5668\u4EBA": "this bot",
453
569
  "\u7528\u4E8E\u4E3A${botName}\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801": "One-time QR code for granting group-message permission to ${botName}",
454
570
  "\u6B63\u5728\u4E3A\u300C${botName}\u300D\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650": "Granting group-message permission to \u201C${botName}\u201D",
455
- '${botName ?? "\u673A\u5668\u4EBA"}\u7684\u4FEE\u590D\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002': 'Repair QR code generated for ${botName ?? "bot"}. Scan it with Feishu.',
571
+ '${botName ?? "\u673A\u5668\u4EBA"}\u7684\u6743\u9650\u8865\u5168\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002': 'Permission-completion QR code generated for ${botName ?? "bot"}. Scan it with Feishu.',
456
572
  '${botName ?? "\u673A\u5668\u4EBA"}\u7684\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u786E\u8BA4\u3002': 'Group-message permission QR code generated for ${botName ?? "bot"}. Confirm it with Feishu.',
457
573
  "${targetBotName}\u5DF2\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\uFF0C\u5E76\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\u3002": "${targetBotName} now has group-message permission and \u201CRespond to all group messages\u201D is enabled.",
458
574
  "${targetBot.bot.name}\u5DF2\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\uFF0C\u5E76\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\u3002": "${targetBot.bot.name} now has group-message permission and \u201CRespond to all group messages\u201D is enabled.",
459
575
  "${targetBot.bot.name}\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5728\u98DE\u4E66\u4E2D\u5F00\u59CB\u804A\u5929\u3002": "${targetBot.bot.name} is connected and ready to chat in Feishu.",
460
- "\u5DF2\u53D6\u6D88\u5361\u7247\u6309\u94AE\u4FEE\u590D\u3002": "Card-button repair was cancelled.",
576
+ "\u5DF2\u53D6\u6D88\u8865\u5168\u6743\u9650\u4E0E\u56DE\u8C03\u3002": "Completing permissions and the callback was cancelled.",
461
577
  "\u5DF2\u53D6\u6D88\u7FA4\u6D88\u606F\u6743\u9650\u6388\u6743\u3002": "Group-message permission authorization was cancelled.",
462
- "\u5361\u7247\u6309\u94AE\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001": "The card callback was updated, but the bot connection could not be confirmed yet",
578
+ "\u6743\u9650\u4E0E\u56DE\u8C03\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001": "Permissions and the callback were updated, but the bot connection could not be confirmed yet",
463
579
  "\u7FA4\u6D88\u606F\u6743\u9650\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001": "The group-message permission was updated, but the bot connection could not be confirmed yet",
464
- "\u98DE\u4E66\u5361\u7247\u6309\u94AE\u4FEE\u590D\u5931\u8D25": "Could not repair the Feishu card buttons",
580
+ "\u98DE\u4E66\u6743\u9650\u4E0E\u56DE\u8C03\u8865\u5168\u5931\u8D25": "Could not complete Feishu permissions and callback setup",
465
581
  "\u98DE\u4E66\u7FA4\u6D88\u606F\u6743\u9650\u5F00\u901A\u5931\u8D25": "Could not grant the Feishu group-message permission",
466
582
  "\u8BF7\u5148\u5B8C\u6210\u5F53\u524D\u98DE\u4E66\u6388\u6743\u64CD\u4F5C\uFF0C\u518D\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\u3002": "Finish the current Feishu authorization before granting group-message permission.",
467
583
  "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u8FDE\u63A5\u65B0\u673A\u5668\u4EBA": "Confirmed. Connecting the new bot",
@@ -760,72 +876,72 @@ function isEnglish() {
760
876
  function channelName(value) {
761
877
  return localizeText(value);
762
878
  }
763
- function translateDynamic(text5) {
764
- let match = /^(\d+) \/ (\d+) 在线$/.exec(text5);
879
+ function translateDynamic(text6) {
880
+ let match = /^(\d+) \/ (\d+) 在线$/.exec(text6);
765
881
  if (match) return `${match[1]}/${match[2]} online`;
766
- match = /^已接入 (\d+) 个机器人,其中 (\d+) 个在线$/.exec(text5);
882
+ match = /^已接入 (\d+) 个机器人,其中 (\d+) 个在线$/.exec(text6);
767
883
  if (match) return `${match[2]} of ${match[1]} bots online`;
768
- match = /^正在读取\s*(.+?)\s*机器人状态…$/.exec(text5);
884
+ match = /^正在读取\s*(.+?)\s*机器人状态…$/.exec(text6);
769
885
  if (match) return `Loading ${channelName(match[1])} bot status\u2026`;
770
- match = /^无法读取\s*(.+?)\s*机器人状态$/.exec(text5);
886
+ match = /^无法读取\s*(.+?)\s*机器人状态$/.exec(text6);
771
887
  if (match) return `Could not load ${channelName(match[1])} bot status`;
772
- match = /^尚未接入\s*(.+?)\s*机器人$/.exec(text5);
888
+ match = /^尚未接入\s*(.+?)\s*机器人$/.exec(text6);
773
889
  if (match) return `No ${channelName(match[1])} bot connected yet`;
774
- match = /^已接入的\s*(.+?)\s*机器人$/.exec(text5);
890
+ match = /^已接入的\s*(.+?)\s*机器人$/.exec(text6);
775
891
  if (match) return `Connected ${channelName(match[1])} bots`;
776
- match = /^手动接入(.+)机器人$/.exec(text5);
892
+ match = /^手动接入(.+)机器人$/.exec(text6);
777
893
  if (match) return `Connect ${channelName(match[1])} bot manually`;
778
- match = /^(.+) 设置$/.exec(text5);
894
+ match = /^(.+) 设置$/.exec(text6);
779
895
  if (match) return `${channelName(match[1])} settings`;
780
- match = /^从 DeepSeek Harness 移除“(.+)”?$/.exec(text5);
896
+ match = /^从 DeepSeek Harness 移除“(.+)”?$/.exec(text6);
781
897
  if (match) return `Remove \u201C${match[1]}\u201D from DeepSeek Harness?`;
782
- match = /^从 DeepSeek Harness 移除(.+)$/.exec(text5);
898
+ match = /^从 DeepSeek Harness 移除(.+)$/.exec(text6);
783
899
  if (match) return `Remove ${match[1]} from DeepSeek Harness`;
784
- match = /^(.+)的飞书授权流程$/.exec(text5);
900
+ match = /^(.+)的飞书授权流程$/.exec(text6);
785
901
  if (match) return `Feishu authorization flow for ${match[1]}`;
786
- match = /^用于修复(.+)卡片按钮的一次性授权二维码$/.exec(text5);
787
- if (match) return `One-time QR code for repairing card buttons for ${match[1]}`;
788
- match = /^用于为(.+)开通群消息权限的一次性授权二维码$/.exec(text5);
902
+ match = /^用于为(.+)补全权限与回调的一次性授权二维码$/.exec(text6);
903
+ if (match) return `One-time QR code for completing permissions and the callback for ${match[1]}`;
904
+ match = /^用于为(.+)开通群消息权限的一次性授权二维码$/.exec(text6);
789
905
  if (match) return `One-time QR code for granting group-message permission to ${match[1]}`;
790
- match = /^正在修复「(.+)」$/.exec(text5);
791
- if (match) return `Repairing \u201C${match[1]}\u201D`;
792
- match = /^正在为「(.+)」开通群消息权限$/.exec(text5);
906
+ match = /^正在为「(.+)」补全权限与回调$/.exec(text6);
907
+ if (match) return `Completing permissions and the callback for \u201C${match[1]}\u201D`;
908
+ match = /^正在为「(.+)」开通群消息权限$/.exec(text6);
793
909
  if (match) return `Granting group-message permission to \u201C${match[1]}\u201D`;
794
- match = /^修复(.+)的卡片按钮$/.exec(text5);
795
- if (match) return `Repair card buttons for ${match[1]}`;
796
- match = /^(.+)的修复二维码已生成,请使用飞书扫码。$/.exec(text5);
797
- if (match) return `Repair QR code generated for ${match[1]}. Scan it with Feishu.`;
798
- match = /^(.+)的群消息权限二维码已生成,请使用飞书确认。$/.exec(text5);
910
+ match = /^为(.+)补全权限与回调$/.exec(text6);
911
+ if (match) return `Complete permissions and the callback for ${match[1]}`;
912
+ match = /^(.+)的权限补全二维码已生成,请使用飞书扫码。$/.exec(text6);
913
+ if (match) return `Permission-completion QR code generated for ${match[1]}. Scan it with Feishu.`;
914
+ match = /^(.+)的群消息权限二维码已生成,请使用飞书确认。$/.exec(text6);
799
915
  if (match) return `Group-message permission QR code generated for ${match[1]}. Confirm it with Feishu.`;
800
- match = /^(.+)的卡片按钮已修复。$/.exec(text5);
801
- if (match) return `Card buttons repaired for ${match[1]}.`;
802
- match = /^(.+)已开通群消息权限,并启用“响应所有群消息”。$/.exec(text5);
916
+ match = /^(.+)的权限与回调已补全。$/.exec(text6);
917
+ if (match) return `Permissions and the callback completed for ${match[1]}.`;
918
+ match = /^(.+)已开通群消息权限,并启用“响应所有群消息”。$/.exec(text6);
803
919
  if (match) return `${match[1]} now has group-message permission and \u201CRespond to all group messages\u201D is enabled.`;
804
- match = /^(检查连接|重试连接)(.+)$/.exec(text5);
920
+ match = /^(检查连接|重试连接)(.+)$/.exec(text6);
805
921
  if (match) return `${localizeText(match[1])} ${match[2]}`;
806
- match = /^移除(.+)$/.exec(text5);
922
+ match = /^移除(.+)$/.exec(text6);
807
923
  if (match) return `Remove ${match[1]}`;
808
- match = /^这会停止消息连接,并删除本机保存的 (.+)、机器人配置及会话映射。(.+)中的机器人不会被自动删除。$/.exec(text5);
924
+ match = /^这会停止消息连接,并删除本机保存的 (.+)、机器人配置及会话映射。(.+)中的机器人不会被自动删除。$/.exec(text6);
809
925
  if (match) {
810
926
  return `This stops the message connection and removes the locally stored ${localizeText(match[1])}, bot configuration, and session mappings. The bot in ${localizeText(match[2])} is not deleted.`;
811
927
  }
812
- match = /^二维码剩余 (.+)$/.exec(text5);
928
+ match = /^二维码剩余 (.+)$/.exec(text6);
813
929
  if (match) return `QR code expires in ${match[1]}`;
814
- match = /^最近一条消息处理失败:(.+)$/.exec(text5);
930
+ match = /^最近一条消息处理失败:(.+)$/.exec(text6);
815
931
  if (match) return `Latest message failed: ${localizeText(match[1])}`;
816
- match = /^图片下载失败(HTTP (.+)),请重新发送后再试。$/.exec(text5);
932
+ match = /^图片下载失败(HTTP (.+)),请重新发送后再试。$/.exec(text6);
817
933
  if (match) return `The image download failed (HTTP ${match[1]}). Send it again.`;
818
- match = /^一次最多只能处理 (\d+) 张图片。$/.exec(text5);
934
+ match = /^一次最多只能处理 (\d+) 张图片。$/.exec(text6);
819
935
  if (match) return `A message can contain at most ${match[1]} images.`;
820
- match = /^状态刷新失败:(.+)$/.exec(text5);
936
+ match = /^状态刷新失败:(.+)$/.exec(text6);
821
937
  if (match) return `Status refresh failed: ${match[1]}`;
822
- match = /^状态自动刷新失败:(.+)$/.exec(text5);
938
+ match = /^状态自动刷新失败:(.+)$/.exec(text6);
823
939
  if (match) return `Automatic status refresh failed: ${match[1]}`;
824
- match = /^操作失败:(.+)$/.exec(text5);
940
+ match = /^操作失败:(.+)$/.exec(text6);
825
941
  if (match) return `Operation failed: ${match[1]}`;
826
- match = /^连接检查失败:(.+)$/.exec(text5);
942
+ match = /^连接检查失败:(.+)$/.exec(text6);
827
943
  if (match) return `Connection check failed: ${match[1]}`;
828
- match = /^移除失败:(.+)$/.exec(text5);
944
+ match = /^移除失败:(.+)$/.exec(text6);
829
945
  if (match) return `Removal failed: ${match[1]}`;
830
946
  const phrases = [
831
947
  ["\u4F01\u4E1A\u5FAE\u4FE1", "WeCom"],
@@ -862,7 +978,7 @@ function translateDynamic(text5) {
862
978
  ["\u8FDE\u63A5\u72B6\u6001", "connection status"],
863
979
  ["\u4E8C\u7EF4\u7801", "QR code"]
864
980
  ];
865
- let output = text5;
981
+ let output = text6;
866
982
  for (const [source, target] of phrases) output = output.replaceAll(source, target);
867
983
  return output;
868
984
  }
@@ -1010,6 +1126,22 @@ function AgentPresetEditor({ agentPreset = "", disabled = false, onSave }) {
1010
1126
  );
1011
1127
  }
1012
1128
 
1129
+ // plugin-src/client/last-message-error.js
1130
+ function text(value, maxLength) {
1131
+ if (typeof value !== "string") return null;
1132
+ const trimmed = value.trim();
1133
+ return trimmed ? trimmed.slice(0, maxLength) : null;
1134
+ }
1135
+ function normalizeLastMessageError(value) {
1136
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
1137
+ const code = text(value.code, 64);
1138
+ const reason = text(value.reason, 64);
1139
+ const message = text(value.message, 500);
1140
+ const referenceId = text(value.referenceId, 40);
1141
+ const at = Number.isFinite(value.at) ? value.at : null;
1142
+ return code && reason && message && referenceId && at !== null ? { code, reason, message, referenceId, at } : null;
1143
+ }
1144
+
1013
1145
  // plugin-src/client/channels/dingtalk/api.js
1014
1146
  var DINGTALK_RPC_CHANNEL = "/dingtalk";
1015
1147
  var DINGTALK_ENDPOINTS = Object.freeze({
@@ -1164,6 +1296,7 @@ function normalizeBot(value) {
1164
1296
  messagesReceived: nonNegativeInteger(stats.messagesReceived),
1165
1297
  messagesReplied: nonNegativeInteger(stats.messagesReplied)
1166
1298
  },
1299
+ lastMessageError: normalizeLastMessageError(value.lastMessageError),
1167
1300
  error: normalizeError(value.error, "DINGTALK_ACCOUNT_ERROR", "\u9489\u9489\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA") ?? null
1168
1301
  };
1169
1302
  }
@@ -1709,6 +1842,19 @@ function useWorkspaceSnapshotFence() {
1709
1842
 
1710
1843
  // plugin-src/client/channel-card-meta.js
1711
1844
  var React8 = __toESM(require("react"), 1);
1845
+ function messageErrorTime(value) {
1846
+ try {
1847
+ return new Intl.DateTimeFormat(isEnglish() ? "en-US" : "zh-CN", {
1848
+ year: "numeric",
1849
+ month: "2-digit",
1850
+ day: "2-digit",
1851
+ hour: "2-digit",
1852
+ minute: "2-digit"
1853
+ }).format(new Date(value));
1854
+ } catch {
1855
+ return null;
1856
+ }
1857
+ }
1712
1858
  function ChannelListHeading({ className = "", id: id5, title, connectionLabel }) {
1713
1859
  const helpId = React8.useId();
1714
1860
  return h2(
@@ -1773,6 +1919,32 @@ function BotStatusMeta({
1773
1919
  )
1774
1920
  );
1775
1921
  }
1922
+ function LastMessageErrorSummary({ className = "", error }) {
1923
+ if (!error) return null;
1924
+ const occurredAt = messageErrorTime(error.at);
1925
+ return h2(
1926
+ "div",
1927
+ {
1928
+ className: `${className} dim-cardSummary`.trim(),
1929
+ role: "status"
1930
+ },
1931
+ h2("strong", null, "\u6700\u8FD1\u4E00\u6761\u6D88\u606F\u5904\u7406\u5931\u8D25"),
1932
+ "\uFF1A",
1933
+ h2("span", null, error.message),
1934
+ "\uFF08",
1935
+ h2("span", null, "\u9519\u8BEF\u7801"),
1936
+ ` ${error.code} \xB7 `,
1937
+ h2("span", null, "\u53C2\u8003\u53F7"),
1938
+ ` ${error.referenceId}`,
1939
+ occurredAt ? h2(
1940
+ React8.Fragment,
1941
+ null,
1942
+ " \xB7 ",
1943
+ h2("time", { dateTime: new Date(error.at).toISOString() }, occurredAt)
1944
+ ) : null,
1945
+ "\uFF09"
1946
+ );
1947
+ }
1776
1948
 
1777
1949
  // plugin-src/client/channels/dingtalk/styles.js
1778
1950
  var DINGTALK_STYLE_ID = "xmanrui-dsh-dingtalk-settings";
@@ -2247,6 +2419,10 @@ function AccountCard({
2247
2419
  )
2248
2420
  ),
2249
2421
  summary ? h2("div", { className: "ddt-summary dim-cardSummary" }, summary) : null,
2422
+ account.lastMessageError ? h2(LastMessageErrorSummary, {
2423
+ className: "ddt-summary",
2424
+ error: account.lastMessageError
2425
+ }) : null,
2250
2426
  feedback ? h2("div", {
2251
2427
  className: "ddt-summary dim-cardFeedback",
2252
2428
  role: "status"
@@ -2827,11 +3003,11 @@ var ACCOUNT_STATES2 = /* @__PURE__ */ new Set(["connected", "connecting", "offli
2827
3003
  function isRecord2(value) {
2828
3004
  return value !== null && typeof value === "object" && !Array.isArray(value);
2829
3005
  }
2830
- function text(value, fallback, max = 240) {
3006
+ function text2(value, fallback, max = 240) {
2831
3007
  return typeof value === "string" && value.trim() ? value.trim().slice(0, max) : fallback;
2832
3008
  }
2833
3009
  function id(value) {
2834
- const result = text(value, "", 128);
3010
+ const result = text2(value, "", 128);
2835
3011
  return /^[a-z\d_-]+$/i.test(result) ? result : void 0;
2836
3012
  }
2837
3013
  function timestamp2(value) {
@@ -2855,8 +3031,8 @@ function createTokenChannelApi(channel4, connectionSummary, {
2855
3031
  throw new Error(`${channel4} \u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94`);
2856
3032
  }
2857
3033
  if (!result.ok) {
2858
- const error = new Error(text(result.error?.message, `${channel4} \u64CD\u4F5C\u5931\u8D25`));
2859
- error.code = text(result.error?.code, `${channel4.toUpperCase()}_RPC_ERROR`, 80);
3034
+ const error = new Error(text2(result.error?.message, `${channel4} \u64CD\u4F5C\u5931\u8D25`));
3035
+ error.code = text2(result.error?.code, `${channel4.toUpperCase()}_RPC_ERROR`, 80);
2860
3036
  throw error;
2861
3037
  }
2862
3038
  return result.value;
@@ -2870,23 +3046,24 @@ function createTokenChannelApi(channel4, connectionSummary, {
2870
3046
  botId: id(value.botId),
2871
3047
  connected,
2872
3048
  state: connected ? "connected" : state,
2873
- workspace: text(value.workspace, "", 4096),
3049
+ workspace: text2(value.workspace, "", 4096),
2874
3050
  agentPreset: normalizeAgentPresetId(value.agentPreset),
2875
3051
  bot: {
2876
- name: text(value.bot?.name, `${channel4}\u673A\u5668\u4EBA`, 100),
2877
- username: text(value.bot?.username, "", 100),
2878
- idMasked: text(value.bot?.idMasked, "\u673A\u5668\u4EBA\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58", 140)
3052
+ name: text2(value.bot?.name, `${channel4}\u673A\u5668\u4EBA`, 100),
3053
+ username: text2(value.bot?.username, "", 100),
3054
+ idMasked: text2(value.bot?.idMasked, "\u673A\u5668\u4EBA\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58", 140)
2879
3055
  },
2880
3056
  health: {
2881
- summary: text(
3057
+ summary: text2(
2882
3058
  value.health?.summary,
2883
3059
  connected ? `${channel4}${connectionSummary}\u8FD0\u884C\u6B63\u5E38` : `${channel4}\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA`
2884
3060
  ),
2885
3061
  lastCheckedAt: timestamp2(value.health?.lastCheckedAt)
2886
3062
  },
3063
+ lastMessageError: normalizeLastMessageError(value.lastMessageError),
2887
3064
  error: isRecord2(value.error) ? {
2888
- code: text(value.error.code, `${channel4.toUpperCase()}_ACCOUNT_ERROR`, 80),
2889
- message: text(value.error.message, `${channel4}\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA`)
3065
+ code: text2(value.error.code, `${channel4.toUpperCase()}_ACCOUNT_ERROR`, 80),
3066
+ message: text2(value.error.message, `${channel4}\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA`)
2890
3067
  } : null,
2891
3068
  ...isRecord2(extension) ? extension : {}
2892
3069
  };
@@ -2905,8 +3082,8 @@ function createTokenChannelApi(channel4, connectionSummary, {
2905
3082
  };
2906
3083
  };
2907
3084
  const presentError10 = (error) => ({
2908
- code: text(error?.code, `${channel4.toUpperCase()}_ERROR`, 80),
2909
- message: text(error?.message, `${channel4}\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5`)
3085
+ code: text2(error?.code, `${channel4.toUpperCase()}_ERROR`, 80),
3086
+ message: text2(error?.message, `${channel4}\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5`)
2910
3087
  });
2911
3088
  return Object.freeze({ unwrapRpcResult: unwrapRpcResult10, normalizeSnapshot: normalizeSnapshot9, presentError: presentError10 });
2912
3089
  }
@@ -3049,6 +3226,10 @@ function createTokenChannelSettings(definition) {
3049
3226
  }, "\u79FB\u9664\u63A5\u5165")
3050
3227
  ),
3051
3228
  summary ? h2("div", { className: "ddt-summary dim-cardSummary" }, summary) : null,
3229
+ account.lastMessageError ? h2(LastMessageErrorSummary, {
3230
+ className: "ddt-summary",
3231
+ error: account.lastMessageError
3232
+ }) : null,
3052
3233
  testNotice ? h2("div", {
3053
3234
  className: "ddt-summary dim-cardFeedback",
3054
3235
  role: "status"
@@ -3580,6 +3761,7 @@ function normalizeBotConnection(value, fallbackBotId) {
3580
3761
  groupMessagePermissionGranted: value.groupMessagePermissionGranted === true,
3581
3762
  bot: normalizeBot2(value.bot),
3582
3763
  health: normalizeHealth(value.health, connected),
3764
+ lastMessageError: normalizeLastMessageError(value.lastMessageError),
3583
3765
  error: normalizeError2(value.error)
3584
3766
  };
3585
3767
  }
@@ -3594,6 +3776,7 @@ function normalizeBotsSnapshot(value) {
3594
3776
  configured: true,
3595
3777
  bot: value.bot,
3596
3778
  health: value.health,
3779
+ lastMessageError: value.lastMessageError,
3597
3780
  error: value.error
3598
3781
  }];
3599
3782
  }
@@ -4201,10 +4384,35 @@ var CSS3 = String.raw`
4201
4384
  .bxf-connectedFooter { display: flex; align-items: center; justify-content: space-between; gap: 15px; margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--dsw-alias-border-l1, #eef0f3); }
4202
4385
  .bxf-healthSummary { min-width: 0; color: var(--dsw-alias-label-secondary, #646a73); font-size: 12px; line-height: 18px; }
4203
4386
  .bxf-healthSummary[data-error="true"] { color: var(--bxf-error); }
4204
- .bxf-botActions { flex: none; width: 100%; flex-wrap: wrap; gap: 8px; margin-top: 0; justify-content: flex-end; }
4387
+ .bxf-botActions { position: relative; flex: none; width: 100%; flex-wrap: wrap; gap: 8px; margin-top: 0; justify-content: flex-end; }
4205
4388
  .bxf-botActions .bxf-button { flex: none; white-space: nowrap; }
4206
4389
  .bxf-botActions .bxf-repairButton { color: var(--bxf-accent); border-color: color-mix(in srgb, var(--bxf-accent) 35%, var(--dsw-alias-border-l2, #dee0e3)); }
4207
4390
  .bxf-botActions .bxf-repairButton:hover:not(:disabled) { background: color-mix(in srgb, var(--bxf-accent) 7%, transparent); }
4391
+ .bxf-repairAction { display: inline-flex; }
4392
+ .bxf-repairTooltip {
4393
+ position: absolute;
4394
+ right: 0;
4395
+ bottom: calc(100% + 8px);
4396
+ z-index: 40;
4397
+ width: min(330px, 100%);
4398
+ display: grid;
4399
+ gap: 3px;
4400
+ padding: 9px 10px;
4401
+ border: 1px solid var(--dsw-alias-border-l2, #dfe1e5);
4402
+ border-radius: 8px;
4403
+ color: var(--dsw-alias-label-primary, #1f2329);
4404
+ background: var(--dsw-alias-bg-layer-3, #fff);
4405
+ box-shadow: 0 10px 28px rgb(31 35 41 / 16%);
4406
+ opacity: 0;
4407
+ visibility: hidden;
4408
+ transform: translateY(3px);
4409
+ pointer-events: none;
4410
+ transition: opacity .15s ease, transform .15s ease, visibility .15s ease;
4411
+ }
4412
+ .bxf-repairTooltip strong { font-size: 12px; line-height: 17px; font-weight: 650; }
4413
+ .bxf-repairTooltip > span { color: var(--dsw-alias-label-secondary, #646a73); font-size: 11px; line-height: 17px; font-weight: 400; overflow-wrap: anywhere; }
4414
+ .bxf-repairAction:hover .bxf-repairTooltip,
4415
+ .bxf-repairAction:focus-within .bxf-repairTooltip { opacity: 1; visibility: visible; transform: translateY(0); }
4208
4416
 
4209
4417
  .bxf-confirm {
4210
4418
  border-top: 1px solid var(--dsw-alias-border-l2, #dee0e3);
@@ -4506,7 +4714,7 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
4506
4714
  { className: "bxf-qrFrame dim-qrFrame" },
4507
4715
  qrSource && !imageFailed ? h2("img", {
4508
4716
  src: qrSource,
4509
- alt: repairing ? `\u7528\u4E8E\u4FEE\u590D${botName}\u5361\u7247\u6309\u94AE\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801` : grantingGroupMessages ? `\u7528\u4E8E\u4E3A${botName}\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801` : "\u7528\u4E8E\u65B0\u589E DeepSeek Harness \u98DE\u4E66\u673A\u5668\u4EBA\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801",
4717
+ alt: repairing ? `\u7528\u4E8E\u4E3A${botName}\u8865\u5168\u6743\u9650\u4E0E\u56DE\u8C03\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801` : grantingGroupMessages ? `\u7528\u4E8E\u4E3A${botName}\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801` : "\u7528\u4E8E\u65B0\u589E DeepSeek Harness \u98DE\u4E66\u673A\u5668\u4EBA\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801",
4510
4718
  onError: () => setImageFailed(true)
4511
4719
  }) : h2(
4512
4720
  "div",
@@ -4545,16 +4753,16 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
4545
4753
  "div",
4546
4754
  { className: "bxf-stateLabel dim-stateLabel" },
4547
4755
  h2("span", { className: "bxf-dot dim-stateDot", "data-tone": "warning" }),
4548
- h2("span", null, repairing ? `\u6B63\u5728\u4FEE\u590D\u300C${botName}\u300D` : grantingGroupMessages ? `\u6B63\u5728\u4E3A\u300C${botName}\u300D\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650` : "\u6B63\u5728\u6DFB\u52A0\u65B0\u673A\u5668\u4EBA")
4756
+ h2("span", null, repairing ? `\u6B63\u5728\u4E3A\u300C${botName}\u300D\u8865\u5168\u6743\u9650\u4E0E\u56DE\u8C03` : grantingGroupMessages ? `\u6B63\u5728\u4E3A\u300C${botName}\u300D\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650` : "\u6B63\u5728\u6DFB\u52A0\u65B0\u673A\u5668\u4EBA")
4549
4757
  ),
4550
- h2("h3", null, expired ? "\u5237\u65B0\u4E8C\u7EF4\u7801\u540E\u7EE7\u7EED" : repairing ? "\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u4FEE\u590D\u5361\u7247\u6309\u94AE" : grantingGroupMessages ? "\u4F7F\u7528\u98DE\u4E66\u786E\u8BA4\u7FA4\u6D88\u606F\u6743\u9650" : "\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u521B\u5EFA\u673A\u5668\u4EBA"),
4551
- h2("p", null, repairing ? "\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u53EA\u589E\u91CF\u8865\u5145\u5361\u7247\u6309\u94AE\u56DE\u8C03\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u540E\u6B64\u673A\u5668\u4EBA\u4F1A\u77ED\u6682\u91CD\u8FDE\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002" : grantingGroupMessages ? "\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u53EA\u589E\u91CF\u5F00\u901A\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u540E\u4F1A\u81EA\u52A8\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002" : "\u626B\u7801\u53EA\u4F1A\u65B0\u589E\u4E00\u4E2A\u673A\u5668\u4EBA\uFF0C\u5DF2\u63A5\u5165\u7684\u673A\u5668\u4EBA\u4F1A\u7EE7\u7EED\u6B63\u5E38\u6536\u53D1\u6D88\u606F\u3002"),
4758
+ h2("h3", null, expired ? "\u5237\u65B0\u4E8C\u7EF4\u7801\u540E\u7EE7\u7EED" : repairing ? "\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u8865\u5168\u6743\u9650" : grantingGroupMessages ? "\u4F7F\u7528\u98DE\u4E66\u786E\u8BA4\u7FA4\u6D88\u606F\u6743\u9650" : "\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u521B\u5EFA\u673A\u5668\u4EBA"),
4759
+ h2("p", null, repairing ? "\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u6700\u591A\u589E\u91CF\u8865\u5145\u5361\u7247\u6309\u94AE\u56DE\u8C03\u3001\u8BFB\u53D6\u7528\u6237\u6D88\u606F\u5185\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:message:readonly\uFF08\u98DE\u4E66\u663E\u793A\u4E3A\u201C\u83B7\u53D6\u5355\u804A\u3001\u7FA4\u7EC4\u6D88\u606F\u201D\uFF09\uFF0C\u4EE5\u53CA\u4E0A\u4F20\u673A\u5668\u4EBA\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:resource\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u9875\u53EA\u663E\u793A\u5F53\u524D\u7F3A\u5C11\u9879\uFF0C\u5B8C\u6210\u540E\u6B64\u673A\u5668\u4EBA\u4F1A\u77ED\u6682\u91CD\u8FDE\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002" : grantingGroupMessages ? "\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u53EA\u589E\u91CF\u5F00\u901A\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u540E\u4F1A\u81EA\u52A8\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002" : "\u626B\u7801\u53EA\u4F1A\u65B0\u589E\u4E00\u4E2A\u673A\u5668\u4EBA\uFF0C\u5DF2\u63A5\u5165\u7684\u673A\u5668\u4EBA\u4F1A\u7EE7\u7EED\u6B63\u5E38\u6536\u53D1\u6D88\u606F\u3002"),
4552
4760
  h2(
4553
4761
  "ol",
4554
4762
  { className: "bxf-steps dim-steps" },
4555
4763
  h2("li", null, "\u6253\u5F00\u98DE\u4E66\u79FB\u52A8\u7AEF\uFF0C\u4F7F\u7528\u626B\u4E00\u626B\u8BFB\u53D6\u4E8C\u7EF4\u7801"),
4556
- h2("li", null, repairing ? "\u6838\u5BF9\u73B0\u6709\u5E94\u7528\u540D\u79F0\uFF0C\u5E76\u786E\u8BA4\u53EA\u65B0\u589E\u5361\u7247\u56DE\u8C03" : grantingGroupMessages ? "\u6838\u5BF9\u73B0\u6709\u5E94\u7528\uFF0C\u5E76\u786E\u8BA4\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650" : "\u6838\u5BF9\u5E94\u7528\u540D\u79F0\u4E0E\u6743\u9650\u8303\u56F4\uFF0C\u5E76\u786E\u8BA4\u521B\u5EFA"),
4557
- h2("li", null, repairing ? "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u5361\u7247\u6309\u94AE\u4FEE\u590D\u5B8C\u6210" : grantingGroupMessages ? "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u6743\u9650\u751F\u6548\u5E76\u81EA\u52A8\u5207\u6362\u54CD\u5E94\u65B9\u5F0F" : "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u65B0\u673A\u5668\u4EBA\u7684\u957F\u8FDE\u63A5\u5C31\u7EEA")
4764
+ h2("li", null, repairing ? "\u6838\u5BF9\u73B0\u6709\u5E94\u7528\u540D\u79F0\uFF0C\u5E76\u786E\u8BA4\u53EA\u65B0\u589E\u5F53\u524D\u7F3A\u5C11\u7684\u4E0A\u8FF0\u914D\u7F6E" : grantingGroupMessages ? "\u6838\u5BF9\u73B0\u6709\u5E94\u7528\uFF0C\u5E76\u786E\u8BA4\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650" : "\u6838\u5BF9\u5E94\u7528\u540D\u79F0\u4E0E\u6743\u9650\u8303\u56F4\uFF0C\u5E76\u786E\u8BA4\u521B\u5EFA"),
4765
+ h2("li", null, repairing ? "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u6743\u9650\u4E0E\u56DE\u8C03\u8865\u5168\u5B8C\u6210" : grantingGroupMessages ? "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u6743\u9650\u751F\u6548\u5E76\u81EA\u52A8\u5207\u6362\u54CD\u5E94\u65B9\u5F0F" : "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u65B0\u673A\u5668\u4EBA\u7684\u957F\u8FDE\u63A5\u5C31\u7EEA")
4558
4766
  ),
4559
4767
  h2(
4560
4768
  "div",
@@ -4571,7 +4779,7 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
4571
4779
  rel: "noopener noreferrer"
4572
4780
  }, h2("span", null, "\u5728\u98DE\u4E66\u4E2D\u6253\u5F00")) : null,
4573
4781
  !expired ? h2(Button5, { onClick: onRefresh, disabled: busy }, "\u6362\u4E00\u4E2A\u4E8C\u7EF4\u7801") : null,
4574
- h2(Button5, { onClick: onCancel, disabled: busy }, repairing ? "\u53D6\u6D88\u4FEE\u590D" : grantingGroupMessages ? "\u53D6\u6D88\u6388\u6743" : "\u53D6\u6D88\u6DFB\u52A0")
4782
+ h2(Button5, { onClick: onCancel, disabled: busy }, repairing ? "\u53D6\u6D88\u8865\u5168" : grantingGroupMessages ? "\u53D6\u6D88\u6388\u6743" : "\u53D6\u6D88\u6DFB\u52A0")
4575
4783
  )
4576
4784
  )
4577
4785
  )
@@ -4588,12 +4796,12 @@ function ProvisionProgress({ phase, provision, onCancel, busy }) {
4588
4796
  "aria-busy": "true"
4589
4797
  },
4590
4798
  h2("div", { className: "dim-spinner", "aria-hidden": "true" }),
4591
- h2("h3", null, connecting ? repairing ? "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u5B8C\u6210\u5361\u7247\u6309\u94AE\u4FEE\u590D" : grantingGroupMessages ? "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u542F\u7528\u5168\u90E8\u6D88\u606F\u6A21\u5F0F" : "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u8FDE\u63A5\u65B0\u673A\u5668\u4EBA" : repairing ? "\u6B63\u5728\u51C6\u5907\u4FEE\u590D\u4E8C\u7EF4\u7801" : grantingGroupMessages ? "\u6B63\u5728\u51C6\u5907\u6743\u9650\u6388\u6743\u4E8C\u7EF4\u7801" : "\u6B63\u5728\u51C6\u5907\u6388\u6743\u4E8C\u7EF4\u7801"),
4592
- h2("p", null, connecting ? repairing ? "\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u9A8C\u8BC1\u5361\u7247\u6309\u94AE\u56DE\u8C03\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002" : grantingGroupMessages ? "\u6743\u9650\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u4FDD\u5B58\u8BBE\u7F6E\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002" : "\u6B63\u5728\u5B89\u5168\u4FDD\u5B58\u51ED\u636E\u5E76\u68C0\u67E5\u65B0\u673A\u5668\u4EBA\u7684\u6D88\u606F\u901A\u9053\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002" : repairing ? "\u6B63\u5728\u4E3A\u73B0\u6709\u98DE\u4E66\u5E94\u7528\u7533\u8BF7\u4E00\u6B21\u6027\u66F4\u65B0\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002" : grantingGroupMessages ? "\u6B63\u5728\u4E3A\u73B0\u6709\u98DE\u4E66\u5E94\u7528\u7533\u8BF7\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002" : "\u6B63\u5728\u5411\u98DE\u4E66\u7533\u8BF7\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002"),
4799
+ h2("h3", null, connecting ? repairing ? "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u5B8C\u6210\u6743\u9650\u4E0E\u56DE\u8C03\u914D\u7F6E" : grantingGroupMessages ? "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u542F\u7528\u5168\u90E8\u6D88\u606F\u6A21\u5F0F" : "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u8FDE\u63A5\u65B0\u673A\u5668\u4EBA" : repairing ? "\u6B63\u5728\u51C6\u5907\u6743\u9650\u8865\u5168\u4E8C\u7EF4\u7801" : grantingGroupMessages ? "\u6B63\u5728\u51C6\u5907\u6743\u9650\u6388\u6743\u4E8C\u7EF4\u7801" : "\u6B63\u5728\u51C6\u5907\u6388\u6743\u4E8C\u7EF4\u7801"),
4800
+ h2("p", null, connecting ? repairing ? "\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u4FDD\u5B58\u6743\u9650\u3001\u9A8C\u8BC1\u5361\u7247\u56DE\u8C03\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002" : grantingGroupMessages ? "\u6743\u9650\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u4FDD\u5B58\u8BBE\u7F6E\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002" : "\u6B63\u5728\u5B89\u5168\u4FDD\u5B58\u51ED\u636E\u5E76\u68C0\u67E5\u65B0\u673A\u5668\u4EBA\u7684\u6D88\u606F\u901A\u9053\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002" : repairing ? "\u6B63\u5728\u4E3A\u73B0\u6709\u98DE\u4E66\u5E94\u7528\u7533\u8BF7\u4E00\u6B21\u6027\u66F4\u65B0\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002" : grantingGroupMessages ? "\u6B63\u5728\u4E3A\u73B0\u6709\u98DE\u4E66\u5E94\u7528\u7533\u8BF7\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002" : "\u6B63\u5728\u5411\u98DE\u4E66\u7533\u8BF7\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002"),
4593
4801
  connecting && onCancel ? h2(
4594
4802
  "div",
4595
4803
  { className: "bxf-actions dim-viewActions", style: { justifyContent: "center" } },
4596
- h2(Button5, { onClick: onCancel, disabled: busy }, repairing ? "\u53D6\u6D88\u4FEE\u590D" : grantingGroupMessages ? "\u53D6\u6D88\u6388\u6743" : "\u53D6\u6D88\u6DFB\u52A0")
4804
+ h2(Button5, { onClick: onCancel, disabled: busy }, repairing ? "\u53D6\u6D88\u8865\u5168" : grantingGroupMessages ? "\u53D6\u6D88\u6388\u6743" : "\u53D6\u6D88\u6DFB\u52A0")
4597
4805
  ) : null
4598
4806
  );
4599
4807
  }
@@ -4609,7 +4817,7 @@ function ProvisionError2({ error, provision, onRetry, onCancel, busy }) {
4609
4817
  h2(
4610
4818
  "div",
4611
4819
  null,
4612
- h2("h3", null, repairing ? "\u5361\u7247\u6309\u94AE\u6CA1\u6709\u4FEE\u590D\u5B8C\u6210" : grantingGroupMessages ? "\u7FA4\u6D88\u606F\u6743\u9650\u6CA1\u6709\u5F00\u901A\u5B8C\u6210" : "\u65B0\u673A\u5668\u4EBA\u6CA1\u6709\u6DFB\u52A0\u5B8C\u6210"),
4820
+ h2("h3", null, repairing ? "\u6743\u9650\u4E0E\u56DE\u8C03\u6CA1\u6709\u8865\u5168\u5B8C\u6210" : grantingGroupMessages ? "\u7FA4\u6D88\u606F\u6743\u9650\u6CA1\u6709\u5F00\u901A\u5B8C\u6210" : "\u65B0\u673A\u5668\u4EBA\u6CA1\u6709\u6DFB\u52A0\u5B8C\u6210"),
4613
4821
  h2("p", null, error.message),
4614
4822
  error.code ? h2("span", { className: "bxf-errorCode" }, error.code) : null,
4615
4823
  h2(
@@ -4802,6 +5010,7 @@ function BotCard({
4802
5010
  removeButtonRef
4803
5011
  }) {
4804
5012
  const { bot, health, state, connected } = connection;
5013
+ const repairTooltipId = React12.useId();
4805
5014
  const stateForDisplay = busy === "reconnect" ? "connecting" : state;
4806
5015
  const tone = stateForDisplay === "connected" ? "success" : stateForDisplay === "connecting" ? "warning" : "error";
4807
5016
  const summary = actionError?.message ?? connection.error?.message ?? (connected ? null : health.summary);
@@ -4887,13 +5096,28 @@ function BotCard({
4887
5096
  "aria-busy": busy === "reconnect" ? "true" : void 0,
4888
5097
  "aria-label": `${connected ? "\u68C0\u67E5\u8FDE\u63A5" : "\u91CD\u8BD5\u8FDE\u63A5"}${bot.name}`
4889
5098
  }, busy === "reconnect" ? connected ? "\u68C0\u67E5\u4E2D\u2026" : "\u6B63\u5728\u8FDE\u63A5\u2026" : connected ? "\u68C0\u67E5\u8FDE\u63A5" : "\u91CD\u8BD5\u8FDE\u63A5"),
4890
- h2(Button5, {
4891
- className: "bxf-repairButton dim-cardAction",
4892
- onClick: onRepairCallback,
4893
- disabled: Boolean(busy) || repairDisabled,
4894
- "aria-busy": busy === "callback-repair" ? "true" : void 0,
4895
- "aria-label": `\u4FEE\u590D${bot.name}\u7684\u5361\u7247\u6309\u94AE`
4896
- }, busy === "callback-repair" ? "\u7B49\u5F85\u626B\u7801\u2026" : "\u4FEE\u590D\u5361\u7247\u6309\u94AE"),
5099
+ h2(
5100
+ "span",
5101
+ { className: "bxf-repairAction" },
5102
+ h2(Button5, {
5103
+ className: "bxf-repairButton dim-cardAction",
5104
+ onClick: onRepairCallback,
5105
+ disabled: Boolean(busy) || repairDisabled,
5106
+ "aria-busy": busy === "callback-repair" ? "true" : void 0,
5107
+ "aria-label": `\u4E3A${bot.name}\u8865\u5168\u6743\u9650\u4E0E\u56DE\u8C03`,
5108
+ "aria-describedby": repairTooltipId
5109
+ }, busy === "callback-repair" ? "\u7B49\u5F85\u626B\u7801\u2026" : "\u8865\u5168\u6743\u9650"),
5110
+ h2(
5111
+ "span",
5112
+ {
5113
+ id: repairTooltipId,
5114
+ className: "bxf-repairTooltip",
5115
+ role: "tooltip"
5116
+ },
5117
+ h2("strong", null, "\u8865\u5168\u8303\u56F4"),
5118
+ h2("span", null, "\u6700\u591A\u589E\u91CF\u6DFB\u52A0\u5361\u7247\u56DE\u8C03 card.action.trigger\u3001\u8BFB\u53D6\u6D88\u606F\u5185\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:message:readonly\uFF08\u98DE\u4E66\u663E\u793A\u4E3A\u201C\u83B7\u53D6\u5355\u804A\u3001\u7FA4\u7EC4\u6D88\u606F\u201D\uFF09\uFF0C\u4EE5\u53CA\u4E0A\u4F20\u673A\u5668\u4EBA\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:resource\uFF1B\u786E\u8BA4\u9875\u53EA\u663E\u793A\u5F53\u524D\u7F3A\u5C11\u9879\uFF0C\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002")
5119
+ )
5120
+ ),
4897
5121
  h2(Button5, {
4898
5122
  className: "dim-cardAction",
4899
5123
  kind: "danger",
@@ -4908,6 +5132,10 @@ function BotCard({
4908
5132
  { className: "bxf-healthSummary dim-cardSummary", "data-error": actionError || connection.error ? "true" : void 0 },
4909
5133
  summary
4910
5134
  ) : null,
5135
+ connection.lastMessageError ? h2(LastMessageErrorSummary, {
5136
+ className: "bxf-healthSummary",
5137
+ error: connection.lastMessageError
5138
+ }) : null,
4911
5139
  testNotice ? h2("div", {
4912
5140
  className: "bxf-healthSummary dim-cardFeedback",
4913
5141
  role: "status"
@@ -5167,7 +5395,7 @@ function FeishuSettingsTab({ rpcCall }) {
5167
5395
  targetedUpdate ? { botId } : { locale: "zh-CN" }
5168
5396
  ));
5169
5397
  if (targetedUpdate && (provision2.operation !== operation || provision2.botId !== botId)) {
5170
- throw new Error(grantingGroupMessages ? "\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801" : "\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u5361\u7247\u4FEE\u590D\u4E8C\u7EF4\u7801");
5398
+ throw new Error(grantingGroupMessages ? "\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801" : "\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u6743\u9650\u8865\u5168\u4E8C\u7EF4\u7801");
5171
5399
  }
5172
5400
  const timestamp7 = Date.now();
5173
5401
  setNow(timestamp7);
@@ -5181,7 +5409,7 @@ function FeishuSettingsTab({ rpcCall }) {
5181
5409
  expired: false
5182
5410
  }
5183
5411
  }));
5184
- announce(repairing ? `${botName ?? "\u673A\u5668\u4EBA"}\u7684\u4FEE\u590D\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002` : grantingGroupMessages ? `${botName ?? "\u673A\u5668\u4EBA"}\u7684\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u786E\u8BA4\u3002` : "\u6388\u6743\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002");
5412
+ announce(repairing ? `${botName ?? "\u673A\u5668\u4EBA"}\u7684\u6743\u9650\u8865\u5168\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002` : grantingGroupMessages ? `${botName ?? "\u673A\u5668\u4EBA"}\u7684\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u786E\u8BA4\u3002` : "\u6388\u6743\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002");
5185
5413
  } catch (error) {
5186
5414
  setModel((current) => ({
5187
5415
  ...current,
@@ -5251,20 +5479,20 @@ function FeishuSettingsTab({ rpcCall }) {
5251
5479
  expired: false
5252
5480
  }
5253
5481
  } : current);
5254
- announce(grantingGroupMessages ? "\u6743\u9650\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u542F\u7528\u5168\u90E8\u6D88\u606F\u6A21\u5F0F\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002" : "\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u9A8C\u8BC1\u5361\u7247\u6309\u94AE\u56DE\u8C03\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002");
5482
+ announce(grantingGroupMessages ? "\u6743\u9650\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u542F\u7528\u5168\u90E8\u6D88\u606F\u6A21\u5F0F\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002" : "\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u4FDD\u5B58\u6743\u9650\u3001\u9A8C\u8BC1\u5361\u7247\u56DE\u8C03\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002");
5255
5483
  return;
5256
5484
  }
5257
5485
  if (result.status === "connected") {
5258
5486
  const targetBotName = targetBot?.bot.name ?? activeProvision.botName ?? "\u673A\u5668\u4EBA";
5259
5487
  setModel((current) => ({ ...current, provisioning: null }));
5260
- announce(grantingGroupMessages ? `${targetBotName}\u5DF2\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\uFF0C\u5E76\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\u3002` : `${targetBotName}\u7684\u5361\u7247\u6309\u94AE\u5DF2\u4FEE\u590D\u3002`);
5488
+ announce(grantingGroupMessages ? `${targetBotName}\u5DF2\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\uFF0C\u5E76\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\u3002` : `${targetBotName}\u7684\u6743\u9650\u4E0E\u56DE\u8C03\u5DF2\u8865\u5168\u3002`);
5261
5489
  if (activeProvision.botId) setFocusBotId(activeProvision.botId);
5262
5490
  await loadStatus({ silent: true, restoreProvisioning: false });
5263
5491
  return;
5264
5492
  }
5265
5493
  }
5266
5494
  setModel((current) => ({ ...current, provisioning: null }));
5267
- announce(repairing ? "\u5DF2\u53D6\u6D88\u5361\u7247\u6309\u94AE\u4FEE\u590D\u3002" : grantingGroupMessages ? "\u5DF2\u53D6\u6D88\u7FA4\u6D88\u606F\u6743\u9650\u6388\u6743\u3002" : "\u5DF2\u53D6\u6D88\u6DFB\u52A0\u673A\u5668\u4EBA\u3002");
5495
+ announce(repairing ? "\u5DF2\u53D6\u6D88\u8865\u5168\u6743\u9650\u4E0E\u56DE\u8C03\u3002" : grantingGroupMessages ? "\u5DF2\u53D6\u6D88\u7FA4\u6D88\u606F\u6743\u9650\u6388\u6743\u3002" : "\u5DF2\u53D6\u6D88\u6DFB\u52A0\u673A\u5668\u4EBA\u3002");
5268
5496
  await loadStatus({ silent: true, restoreProvisioning: false });
5269
5497
  scheduleAnimationFrame(() => {
5270
5498
  if (targetedUpdate && activeProvision.botId) {
@@ -5322,19 +5550,19 @@ function FeishuSettingsTab({ rpcCall }) {
5322
5550
  const snapshot = await loadStatus({ signal: controller.signal, silent: true, restoreProvisioning: false });
5323
5551
  const targetBot = snapshot?.bots.find((bot) => bot.botId === result.botId);
5324
5552
  if (!snapshot) {
5325
- throw new Error(isCallbackRepair(provision2) ? "\u5361\u7247\u6309\u94AE\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001" : isGroupMessagePermission(provision2) ? "\u7FA4\u6D88\u606F\u6743\u9650\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001" : "\u673A\u5668\u4EBA\u5DF2\u7ECF\u521B\u5EFA\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u8FDE\u63A5\u72B6\u6001");
5553
+ throw new Error(isCallbackRepair(provision2) ? "\u6743\u9650\u4E0E\u56DE\u8C03\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001" : isGroupMessagePermission(provision2) ? "\u7FA4\u6D88\u606F\u6743\u9650\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001" : "\u673A\u5668\u4EBA\u5DF2\u7ECF\u521B\u5EFA\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u8FDE\u63A5\u72B6\u6001");
5326
5554
  }
5327
5555
  if (!targetBot?.connected) {
5328
5556
  setModel((current) => current.provisioning?.attemptId === provision2.attemptId ? { ...current, provisioning: { ...current.provisioning, phase: "connecting" } } : current);
5329
5557
  return;
5330
5558
  }
5331
5559
  setModel((current) => ({ ...current, provisioning: null }));
5332
- announce(isCallbackRepair(provision2) ? `${targetBot.bot.name}\u7684\u5361\u7247\u6309\u94AE\u5DF2\u4FEE\u590D\u3002` : isGroupMessagePermission(provision2) ? `${targetBot.bot.name}\u5DF2\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\uFF0C\u5E76\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\u3002` : targetBot ? `${targetBot.bot.name}\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5728\u98DE\u4E66\u4E2D\u5F00\u59CB\u804A\u5929\u3002` : "\u65B0\u98DE\u4E66\u673A\u5668\u4EBA\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5F00\u59CB\u804A\u5929\u3002");
5560
+ announce(isCallbackRepair(provision2) ? `${targetBot.bot.name}\u7684\u6743\u9650\u4E0E\u56DE\u8C03\u5DF2\u8865\u5168\u3002` : isGroupMessagePermission(provision2) ? `${targetBot.bot.name}\u5DF2\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\uFF0C\u5E76\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\u3002` : targetBot ? `${targetBot.bot.name}\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5728\u98DE\u4E66\u4E2D\u5F00\u59CB\u804A\u5929\u3002` : "\u65B0\u98DE\u4E66\u673A\u5668\u4EBA\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5F00\u59CB\u804A\u5929\u3002");
5333
5561
  if (result.botId) setFocusBotId(result.botId);
5334
5562
  return;
5335
5563
  }
5336
5564
  if (result.status === "failed") {
5337
- const error = new Error(result.message ?? (isCallbackRepair(provision2) ? "\u98DE\u4E66\u5361\u7247\u6309\u94AE\u4FEE\u590D\u5931\u8D25" : isGroupMessagePermission(provision2) ? "\u98DE\u4E66\u7FA4\u6D88\u606F\u6743\u9650\u5F00\u901A\u5931\u8D25" : "\u98DE\u4E66\u5E94\u7528\u521B\u5EFA\u5931\u8D25"));
5565
+ const error = new Error(result.message ?? (isCallbackRepair(provision2) ? "\u98DE\u4E66\u6743\u9650\u4E0E\u56DE\u8C03\u8865\u5168\u5931\u8D25" : isGroupMessagePermission(provision2) ? "\u98DE\u4E66\u7FA4\u6D88\u606F\u6743\u9650\u5F00\u901A\u5931\u8D25" : "\u98DE\u4E66\u5E94\u7528\u521B\u5EFA\u5931\u8D25"));
5338
5566
  error.code = "FEISHU_PROVISION_FAILED";
5339
5567
  throw error;
5340
5568
  }
@@ -5715,11 +5943,11 @@ var QR_DATA_URL2 = /^data:image\/(?:png|webp);base64,[a-z\d+/]+={0,2}$/i;
5715
5943
  function isRecord4(value) {
5716
5944
  return value !== null && typeof value === "object" && !Array.isArray(value);
5717
5945
  }
5718
- function text2(value, fallback, max = 240) {
5946
+ function text3(value, fallback, max = 240) {
5719
5947
  return typeof value === "string" && value.trim() ? value.trim().slice(0, max) : fallback;
5720
5948
  }
5721
5949
  function id2(value) {
5722
- const result = text2(value, "", 128);
5950
+ const result = text3(value, "", 128);
5723
5951
  return /^[a-z\d_-]+$/i.test(result) ? result : void 0;
5724
5952
  }
5725
5953
  function timestamp3(value) {
@@ -5730,8 +5958,8 @@ function timestamp3(value) {
5730
5958
  function unwrapRpcResult4(result) {
5731
5959
  if (!isRecord4(result) || typeof result.ok !== "boolean") throw new Error("QQ \u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94");
5732
5960
  if (!result.ok) {
5733
- const error = new Error(text2(result.error?.message, "QQ \u64CD\u4F5C\u5931\u8D25"));
5734
- error.code = text2(result.error?.code, "QQ_RPC_ERROR", 80);
5961
+ const error = new Error(text3(result.error?.message, "QQ \u64CD\u4F5C\u5931\u8D25"));
5962
+ error.code = text3(result.error?.code, "QQ_RPC_ERROR", 80);
5735
5963
  throw error;
5736
5964
  }
5737
5965
  return result.value;
@@ -5744,7 +5972,7 @@ function normalizeProvisioning3(value, now = Date.now()) {
5744
5972
  if (!isRecord4(source)) throw new Error("QQ \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u626B\u7801\u7ED1\u5B9A\u8FDB\u5EA6");
5745
5973
  const attemptId = id2(source.attemptId);
5746
5974
  if (!attemptId) throw new Error("QQ \u626B\u7801\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u7ED1\u5B9A\u4EFB\u52A1");
5747
- const reported = text2(source.status, "failed", 32);
5975
+ const reported = text3(source.status, "failed", 32);
5748
5976
  const result = {
5749
5977
  attemptId,
5750
5978
  status: PROVISION_STATES2.has(reported) ? reported : "failed",
@@ -5756,8 +5984,8 @@ function normalizeProvisioning3(value, now = Date.now()) {
5756
5984
  if (qrCodeDataUrl) result.qrCodeDataUrl = qrCodeDataUrl;
5757
5985
  if (id2(source.botId)) result.botId = id2(source.botId);
5758
5986
  if (isRecord4(source.error)) result.error = {
5759
- code: text2(source.error.code, "QQ_PROVISION_FAILED", 80),
5760
- message: text2(source.error.message, "QQ \u673A\u5668\u4EBA\u6CA1\u6709\u63A5\u5165\u5B8C\u6210")
5987
+ code: text3(source.error.code, "QQ_PROVISION_FAILED", 80),
5988
+ message: text3(source.error.message, "QQ \u673A\u5668\u4EBA\u6CA1\u6709\u63A5\u5165\u5B8C\u6210")
5761
5989
  };
5762
5990
  return result;
5763
5991
  }
@@ -5769,26 +5997,27 @@ function normalizeBot3(value) {
5769
5997
  botId: id2(value.botId),
5770
5998
  connected,
5771
5999
  state: connected ? "connected" : state,
5772
- workspace: text2(value.workspace, "", 4096),
6000
+ workspace: text3(value.workspace, "", 4096),
5773
6001
  agentPreset: normalizeAgentPresetId(value.agentPreset),
5774
6002
  bot: {
5775
- name: text2(value.bot?.name, "QQ\u673A\u5668\u4EBA", 100),
5776
- appIdMasked: text2(value.bot?.appIdMasked, "\u5E94\u7528\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58", 140)
6003
+ name: text3(value.bot?.name, "QQ\u673A\u5668\u4EBA", 100),
6004
+ appIdMasked: text3(value.bot?.appIdMasked, "\u5E94\u7528\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58", 140)
5777
6005
  },
5778
6006
  health: {
5779
- summary: text2(value.health?.summary, connected ? "QQ WebSocket \u957F\u8FDE\u63A5\u8FD0\u884C\u6B63\u5E38" : "QQ \u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA"),
6007
+ summary: text3(value.health?.summary, connected ? "QQ WebSocket \u957F\u8FDE\u63A5\u8FD0\u884C\u6B63\u5E38" : "QQ \u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA"),
5780
6008
  lastCheckedAt: timestamp3(value.health?.lastCheckedAt)
5781
6009
  },
6010
+ lastMessageError: normalizeLastMessageError(value.lastMessageError),
5782
6011
  error: isRecord4(value.error) ? {
5783
- code: text2(value.error.code, "QQ_ACCOUNT_ERROR", 80),
5784
- message: text2(value.error.message, "QQ \u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA")
6012
+ code: text3(value.error.code, "QQ_ACCOUNT_ERROR", 80),
6013
+ message: text3(value.error.message, "QQ \u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA")
5785
6014
  } : null
5786
6015
  };
5787
6016
  }
5788
6017
  function normalizeTestMessage2(value) {
5789
6018
  if (!isRecord4(value) || typeof value.sent !== "boolean") return void 0;
5790
6019
  if (value.sent) return { sent: true };
5791
- const code = text2(value.code, "test-message-failed", 80);
6020
+ const code = text3(value.code, "test-message-failed", 80);
5792
6021
  return {
5793
6022
  sent: false,
5794
6023
  code: TEST_MESSAGE_CODES.has(code) ? code : "test-message-failed"
@@ -5817,8 +6046,8 @@ function connectionTestFeedback2(result) {
5817
6046
  }
5818
6047
  function presentError4(error) {
5819
6048
  return {
5820
- code: text2(error?.code, "QQ_ERROR", 80),
5821
- message: text2(error?.message, "QQ \u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5")
6049
+ code: text3(error?.code, "QQ_ERROR", 80),
6050
+ message: text3(error?.message, "QQ \u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5")
5822
6051
  };
5823
6052
  }
5824
6053
  function formatRemaining3(milliseconds) {
@@ -6126,6 +6355,10 @@ function AccountCard2({
6126
6355
  h2(Button7, { className: "dim-cardAction", kind: "danger", onClick: onRequestRemove, disabled: Boolean(busy) }, "\u79FB\u9664\u63A5\u5165")
6127
6356
  ),
6128
6357
  summary ? h2("div", { className: "ddt-summary dim-cardSummary" }, summary) : null,
6358
+ account.lastMessageError ? h2(LastMessageErrorSummary, {
6359
+ className: "ddt-summary",
6360
+ error: account.lastMessageError
6361
+ }) : null,
6129
6362
  feedback ? h2("div", {
6130
6363
  className: "ddt-summary dim-cardFeedback",
6131
6364
  role: "status",
@@ -7265,11 +7498,11 @@ var QR_DATA_URL3 = /^data:image\/(?:png|webp);base64,[a-z\d+/]+={0,2}$/i;
7265
7498
  function isRecord5(value) {
7266
7499
  return value !== null && typeof value === "object" && !Array.isArray(value);
7267
7500
  }
7268
- function text3(value, fallback, max = 240) {
7501
+ function text4(value, fallback, max = 240) {
7269
7502
  return typeof value === "string" && value.trim() ? value.trim().slice(0, max) : fallback;
7270
7503
  }
7271
7504
  function id3(value) {
7272
- const result = text3(value, "", 128);
7505
+ const result = text4(value, "", 128);
7273
7506
  return /^[a-z\d_-]+$/i.test(result) ? result : void 0;
7274
7507
  }
7275
7508
  function timestamp4(value) {
@@ -7287,8 +7520,8 @@ function normalizeTestMessage3(value) {
7287
7520
  function unwrapRpcResult7(result) {
7288
7521
  if (!isRecord5(result) || typeof result.ok !== "boolean") throw new Error("\u4F01\u4E1A\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94");
7289
7522
  if (!result.ok) {
7290
- const error = new Error(text3(result.error?.message, "\u4F01\u4E1A\u5FAE\u4FE1\u64CD\u4F5C\u5931\u8D25"));
7291
- error.code = text3(result.error?.code, "WECOM_RPC_ERROR", 80);
7523
+ const error = new Error(text4(result.error?.message, "\u4F01\u4E1A\u5FAE\u4FE1\u64CD\u4F5C\u5931\u8D25"));
7524
+ error.code = text4(result.error?.code, "WECOM_RPC_ERROR", 80);
7292
7525
  throw error;
7293
7526
  }
7294
7527
  return result.value;
@@ -7301,7 +7534,7 @@ function normalizeProvisioning4(value, now = Date.now()) {
7301
7534
  if (!isRecord5(source)) throw new Error("\u4F01\u4E1A\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u626B\u7801\u7ED1\u5B9A\u8FDB\u5EA6");
7302
7535
  const attemptId = id3(source.attemptId);
7303
7536
  if (!attemptId) throw new Error("\u4F01\u4E1A\u5FAE\u4FE1\u626B\u7801\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u7ED1\u5B9A\u4EFB\u52A1");
7304
- const reported = text3(source.status, "failed", 32);
7537
+ const reported = text4(source.status, "failed", 32);
7305
7538
  const result = {
7306
7539
  attemptId,
7307
7540
  status: PROVISION_STATES3.has(reported) ? reported : "failed",
@@ -7313,8 +7546,8 @@ function normalizeProvisioning4(value, now = Date.now()) {
7313
7546
  if (qrCodeDataUrl) result.qrCodeDataUrl = qrCodeDataUrl;
7314
7547
  if (id3(source.botId)) result.botId = id3(source.botId);
7315
7548
  if (isRecord5(source.error)) result.error = {
7316
- code: text3(source.error.code, "WECOM_PROVISION_FAILED", 80),
7317
- message: text3(source.error.message, "\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u6CA1\u6709\u63A5\u5165\u5B8C\u6210")
7549
+ code: text4(source.error.code, "WECOM_PROVISION_FAILED", 80),
7550
+ message: text4(source.error.message, "\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u6CA1\u6709\u63A5\u5165\u5B8C\u6210")
7318
7551
  };
7319
7552
  return result;
7320
7553
  }
@@ -7326,19 +7559,20 @@ function normalizeBot4(value) {
7326
7559
  botId: id3(value.botId),
7327
7560
  connected,
7328
7561
  state: connected ? "connected" : state,
7329
- workspace: text3(value.workspace, "", 4096),
7562
+ workspace: text4(value.workspace, "", 4096),
7330
7563
  agentPreset: normalizeAgentPresetId(value.agentPreset),
7331
7564
  bot: {
7332
- name: text3(value.bot?.name, "\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA", 100),
7333
- appIdMasked: text3(value.bot?.appIdMasked, "\u5E94\u7528\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58", 140)
7565
+ name: text4(value.bot?.name, "\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA", 100),
7566
+ appIdMasked: text4(value.bot?.appIdMasked, "\u5E94\u7528\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58", 140)
7334
7567
  },
7335
7568
  health: {
7336
- summary: text3(value.health?.summary, connected ? "\u4F01\u4E1A\u5FAE\u4FE1 WebSocket \u957F\u8FDE\u63A5\u8FD0\u884C\u6B63\u5E38" : "\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA"),
7569
+ summary: text4(value.health?.summary, connected ? "\u4F01\u4E1A\u5FAE\u4FE1 WebSocket \u957F\u8FDE\u63A5\u8FD0\u884C\u6B63\u5E38" : "\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA"),
7337
7570
  lastCheckedAt: timestamp4(value.health?.lastCheckedAt)
7338
7571
  },
7572
+ lastMessageError: normalizeLastMessageError(value.lastMessageError),
7339
7573
  error: isRecord5(value.error) ? {
7340
- code: text3(value.error.code, "WECOM_ACCOUNT_ERROR", 80),
7341
- message: text3(value.error.message, "\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA")
7574
+ code: text4(value.error.code, "WECOM_ACCOUNT_ERROR", 80),
7575
+ message: text4(value.error.message, "\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA")
7342
7576
  } : null
7343
7577
  };
7344
7578
  }
@@ -7357,8 +7591,8 @@ function normalizeSnapshot6(value) {
7357
7591
  }
7358
7592
  function presentError7(error) {
7359
7593
  return {
7360
- code: text3(error?.code, "WECOM_ERROR", 80),
7361
- message: text3(error?.message, "\u4F01\u4E1A\u5FAE\u4FE1\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5")
7594
+ code: text4(error?.code, "WECOM_ERROR", 80),
7595
+ message: text4(error?.message, "\u4F01\u4E1A\u5FAE\u4FE1\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5")
7362
7596
  };
7363
7597
  }
7364
7598
  function formatRemaining4(milliseconds) {
@@ -7666,6 +7900,10 @@ function AccountCard3({
7666
7900
  h2(Button10, { className: "dim-cardAction", kind: "danger", onClick: onRequestRemove, disabled: Boolean(busy) }, "\u79FB\u9664\u63A5\u5165")
7667
7901
  ),
7668
7902
  summary ? h2("div", { className: "ddt-summary dim-cardSummary" }, summary) : null,
7903
+ account.lastMessageError ? h2(LastMessageErrorSummary, {
7904
+ className: "ddt-summary",
7905
+ error: account.lastMessageError
7906
+ }) : null,
7669
7907
  feedback ? h2("div", {
7670
7908
  className: "ddt-summary dim-cardFeedback",
7671
7909
  role: "status",
@@ -8067,14 +8305,6 @@ function normalizeTestMessage4(value) {
8067
8305
  const code = value.code === "test-target-unavailable" ? "test-target-unavailable" : "test-message-failed";
8068
8306
  return { sent: false, code };
8069
8307
  }
8070
- function normalizeMessageError(value) {
8071
- if (!isRecord6(value)) return null;
8072
- const code = string(value.code).slice(0, 64);
8073
- const reason = string(value.reason).slice(0, 128);
8074
- const message = string(value.message).slice(0, 500);
8075
- const at = timestamp5(value.at);
8076
- return code && reason && message && at !== null ? { code, reason, message, at } : null;
8077
- }
8078
8308
  function unwrapRpcResult8(result) {
8079
8309
  if (!isRecord6(result) || typeof result.ok !== "boolean") {
8080
8310
  throw new Error("\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94");
@@ -8149,7 +8379,7 @@ function normalizeBot5(value) {
8149
8379
  messagesReceived: Math.max(0, Number(value.stats?.messagesReceived) || 0),
8150
8380
  messagesReplied: Math.max(0, Number(value.stats?.messagesReplied) || 0)
8151
8381
  },
8152
- lastMessageError: normalizeMessageError(value.lastMessageError),
8382
+ lastMessageError: normalizeLastMessageError(value.lastMessageError),
8153
8383
  error: isRecord6(value.error) ? {
8154
8384
  code: string(value.error.code, "WEIXIN_ACCOUNT_ERROR"),
8155
8385
  message: string(value.error.message, "\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA")
@@ -8610,10 +8840,10 @@ function AccountCard4({
8610
8840
  h2(Button12, { className: "dim-cardAction", kind: "danger", onClick: onRequestRemove, disabled: Boolean(busy) }, "\u79FB\u9664\u63A5\u5165")
8611
8841
  ),
8612
8842
  summary ? h2("div", { className: "dxw-summary dim-cardSummary" }, summary) : null,
8613
- account.lastMessageError ? h2("div", {
8614
- className: "dxw-summary dim-cardSummary",
8615
- role: "status"
8616
- }, `\u6700\u8FD1\u4E00\u6761\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF1A${account.lastMessageError.message}`) : null,
8843
+ account.lastMessageError ? h2(LastMessageErrorSummary, {
8844
+ className: "dxw-summary",
8845
+ error: account.lastMessageError
8846
+ }) : null,
8617
8847
  feedback ? h2("div", {
8618
8848
  className: "dxw-summary dim-cardFeedback",
8619
8849
  role: "status",
@@ -9108,11 +9338,11 @@ var QR_DATA_URL4 = /^data:image\/(?:png|webp);base64,[a-z\d+/]+={0,2}$/i;
9108
9338
  function isRecord7(value) {
9109
9339
  return value !== null && typeof value === "object" && !Array.isArray(value);
9110
9340
  }
9111
- function text4(value, fallback, max = 240) {
9341
+ function text5(value, fallback, max = 240) {
9112
9342
  return typeof value === "string" && value.trim() ? value.trim().slice(0, max) : fallback;
9113
9343
  }
9114
9344
  function id4(value) {
9115
- const result = text4(value, "", 128);
9345
+ const result = text5(value, "", 128);
9116
9346
  return /^[a-z\d_-]+$/i.test(result) ? result : void 0;
9117
9347
  }
9118
9348
  function timestamp6(value) {
@@ -9125,8 +9355,8 @@ function unwrapRpcResult9(result) {
9125
9355
  throw new Error("WhatsApp \u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94");
9126
9356
  }
9127
9357
  if (!result.ok) {
9128
- const error = new Error(text4(result.error?.message, "WhatsApp \u64CD\u4F5C\u5931\u8D25"));
9129
- error.code = text4(result.error?.code, "WHATSAPP_RPC_ERROR", 80);
9358
+ const error = new Error(text5(result.error?.message, "WhatsApp \u64CD\u4F5C\u5931\u8D25"));
9359
+ error.code = text5(result.error?.code, "WHATSAPP_RPC_ERROR", 80);
9130
9360
  throw error;
9131
9361
  }
9132
9362
  return result.value;
@@ -9139,7 +9369,7 @@ function normalizeProvisioning6(value, now = Date.now()) {
9139
9369
  if (!isRecord7(source)) throw new Error("WhatsApp \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u626B\u7801\u8FDB\u5EA6");
9140
9370
  const attemptId = id4(source.attemptId);
9141
9371
  if (!attemptId) throw new Error("WhatsApp \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u626B\u7801\u4EFB\u52A1");
9142
- const reported = text4(source.status, "failed", 32);
9372
+ const reported = text5(source.status, "failed", 32);
9143
9373
  const result = {
9144
9374
  attemptId,
9145
9375
  status: PROVISION_STATES5.has(reported) ? reported : "failed",
@@ -9151,8 +9381,8 @@ function normalizeProvisioning6(value, now = Date.now()) {
9151
9381
  if (qrCodeDataUrl) result.qrCodeDataUrl = qrCodeDataUrl;
9152
9382
  if (id4(source.botId)) result.botId = id4(source.botId);
9153
9383
  if (isRecord7(source.error)) result.error = {
9154
- code: text4(source.error.code, "WHATSAPP_PROVISION_FAILED", 80),
9155
- message: text4(source.error.message, "WhatsApp \u6CA1\u6709\u63A5\u5165\u5B8C\u6210")
9384
+ code: text5(source.error.code, "WHATSAPP_PROVISION_FAILED", 80),
9385
+ message: text5(source.error.message, "WhatsApp \u6CA1\u6709\u63A5\u5165\u5B8C\u6210")
9156
9386
  };
9157
9387
  return result;
9158
9388
  }
@@ -9164,7 +9394,7 @@ function normalizeBot6(value) {
9164
9394
  botId: id4(value.botId),
9165
9395
  connected,
9166
9396
  state: connected ? "connected" : state,
9167
- workspace: text4(value.workspace, "", 4096),
9397
+ workspace: text5(value.workspace, "", 4096),
9168
9398
  agentPreset: normalizeAgentPresetId(value.agentPreset),
9169
9399
  accessPolicy: {
9170
9400
  accessMode: ["self-only", "private-allowlist", "open"].includes(
@@ -9173,16 +9403,17 @@ function normalizeBot6(value) {
9173
9403
  allowedNumbers: Array.isArray(value.accessPolicy?.allowedNumbers) ? [...new Set(value.accessPolicy.allowedNumbers.filter((entry) => typeof entry === "string" && /^[1-9]\d{4,14}$/.test(entry)))] : []
9174
9404
  },
9175
9405
  bot: {
9176
- name: text4(value.bot?.name, "WhatsApp\u673A\u5668\u4EBA", 100),
9177
- idMasked: text4(value.bot?.idMasked, "WhatsApp\u8D26\u53F7", 140)
9406
+ name: text5(value.bot?.name, "WhatsApp\u673A\u5668\u4EBA", 100),
9407
+ idMasked: text5(value.bot?.idMasked, "WhatsApp\u8D26\u53F7", 140)
9178
9408
  },
9179
9409
  health: {
9180
- summary: text4(value.health?.summary, connected ? "WhatsApp Web \u5173\u8054\u8BBE\u5907\u8FD0\u884C\u6B63\u5E38" : "WhatsApp \u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA"),
9410
+ summary: text5(value.health?.summary, connected ? "WhatsApp Web \u5173\u8054\u8BBE\u5907\u8FD0\u884C\u6B63\u5E38" : "WhatsApp \u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA"),
9181
9411
  lastCheckedAt: timestamp6(value.health?.lastCheckedAt)
9182
9412
  },
9413
+ lastMessageError: normalizeLastMessageError(value.lastMessageError),
9183
9414
  error: isRecord7(value.error) ? {
9184
- code: text4(value.error.code, "WHATSAPP_ACCOUNT_ERROR", 80),
9185
- message: text4(value.error.message, "WhatsApp \u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA")
9415
+ code: text5(value.error.code, "WHATSAPP_ACCOUNT_ERROR", 80),
9416
+ message: text5(value.error.message, "WhatsApp \u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA")
9186
9417
  } : null
9187
9418
  };
9188
9419
  }
@@ -9202,8 +9433,8 @@ function normalizeSnapshot8(value) {
9202
9433
  }
9203
9434
  function presentError9(error) {
9204
9435
  return {
9205
- code: text4(error?.code, "WHATSAPP_ERROR", 80),
9206
- message: text4(error?.message, "WhatsApp \u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5")
9436
+ code: text5(error?.code, "WHATSAPP_ERROR", 80),
9437
+ message: text5(error?.message, "WhatsApp \u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5")
9207
9438
  };
9208
9439
  }
9209
9440
  function formatRemaining6(milliseconds) {
@@ -9713,6 +9944,10 @@ function WhatsappAccountCard({
9713
9944
  }, "\u79FB\u9664\u63A5\u5165")
9714
9945
  ),
9715
9946
  summary ? h2("div", { className: "ddt-summary dim-cardSummary" }, summary) : null,
9947
+ account.lastMessageError ? h2(LastMessageErrorSummary, {
9948
+ className: "ddt-summary",
9949
+ error: account.lastMessageError
9950
+ }) : null,
9716
9951
  testNotice ? h2("div", {
9717
9952
  className: "ddt-summary dim-cardFeedback",
9718
9953
  role: "status"
@@ -10088,9 +10323,13 @@ var CSS11 = String.raw`
10088
10323
  }
10089
10324
  .dim-page *, .dim-page *::before, .dim-page *::after { box-sizing: border-box; }
10090
10325
  .dim-title { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin: 0 0 18px; }
10091
- .dim-brand { min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 1px; }
10326
+ .dim-brand { position: relative; min-width: 0; width: max-content; max-width: 100%; display: flex; flex-direction: column; align-items: flex-start; gap: 1px; margin: -2px -6px; padding: 2px 6px; border-radius: 8px; cursor: help; }
10327
+ .dim-brand:focus-visible { outline: 2px solid color-mix(in srgb, var(--dim-blue) 70%, white); outline-offset: 2px; }
10092
10328
  .dim-brandName { color: var(--dsw-alias-label-primary, #1f2329); font-size: 20px; line-height: 24px; font-weight: 800; letter-spacing: .04em; }
10093
10329
  .dim-title p { margin: 0; color: var(--dsw-alias-label-secondary, #646a73); font-size: 12px; line-height: 18px; font-weight: 500; white-space: nowrap; }
10330
+ .dim-versionTooltip { position: absolute; left: 0; bottom: calc(100% + 8px); z-index: 20; width: max-content; max-width: min(220px, 80vw); display: inline-flex; align-items: center; gap: 6px; padding: 6px 9px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 7px; color: var(--dsw-alias-label-secondary, #646a73); background: var(--dsw-alias-bg-layer-3, #fff); box-shadow: 0 8px 24px rgb(31 35 41 / 14%); font-size: 11px; line-height: 16px; font-weight: 500; white-space: nowrap; opacity: 0; visibility: hidden; transform: translateY(3px); pointer-events: none; transition: opacity .15s ease, transform .15s ease, visibility .15s ease; }
10331
+ .dim-versionTooltip strong { color: var(--dsw-alias-label-primary, #1f2329); font: 600 11px/16px ui-monospace, SFMono-Regular, Menlo, monospace; }
10332
+ .dim-brand:hover .dim-versionTooltip, .dim-brand:focus .dim-versionTooltip { opacity: 1; visibility: visible; transform: translateY(0); }
10094
10333
  .dim-githubAction { position: relative; display: inline-flex; flex: none; }
10095
10334
  .dim-githubLink { min-height: 30px; display: inline-flex; align-items: center; gap: 5px; flex: none; padding: 0 10px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 8px; color: var(--dsw-alias-label-secondary, #646a73); background: var(--dsw-alias-bg-layer-1, #fff); font-size: 12px; line-height: normal; font-weight: 560; text-decoration: none; transition: border-color .15s ease, color .15s ease, background .15s ease; }
10096
10335
  .dim-githubLink:hover { border-color: #aeb3bb; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-interactive-bg-hover, #f7f8fa); }
@@ -10382,6 +10621,7 @@ function installImStyles() {
10382
10621
  // plugin-src/client/index.js
10383
10622
  var name = "im-settings";
10384
10623
  var inject = ["slots", "connection", "locale", "workspaces"];
10624
+ var IM_PLUGIN_VERSION = package_default.version;
10385
10625
  var CHANNELS = Object.freeze([
10386
10626
  { id: "weixin", label: "\u5FAE\u4FE1" },
10387
10627
  { id: "feishu", label: "\u98DE\u4E66" },
@@ -10506,6 +10746,7 @@ function IMSettingsTab({
10506
10746
  }) {
10507
10747
  const [selected, setSelected] = React20.useState("weixin");
10508
10748
  const [loopbackRecovery, setLoopbackRecovery] = React20.useState(null);
10749
+ const versionTooltipId = React20.useId();
10509
10750
  const githubTooltipId = React20.useId();
10510
10751
  const active = CHANNELS.find((channel4) => channel4.id === selected) ?? CHANNELS[0];
10511
10752
  const reportLoopbackRecovery = React20.useCallback((recovery) => {
@@ -10550,9 +10791,23 @@ function IMSettingsTab({
10550
10791
  { className: "dim-title" },
10551
10792
  h2(
10552
10793
  "div",
10553
- { className: "dim-brand" },
10794
+ {
10795
+ className: "dim-brand",
10796
+ tabIndex: 0,
10797
+ "aria-describedby": versionTooltipId
10798
+ },
10554
10799
  h2("strong", { className: "dim-brandName" }, "DSH-IM"),
10555
- h2("p", null, "\u8BA9 DeepSeek Harness \u89E6\u624B\u53EF\u53CA")
10800
+ h2("p", null, "\u8BA9 DeepSeek Harness \u89E6\u624B\u53EF\u53CA"),
10801
+ h2(
10802
+ "span",
10803
+ {
10804
+ id: versionTooltipId,
10805
+ className: "dim-versionTooltip",
10806
+ role: "tooltip"
10807
+ },
10808
+ h2("span", null, "\u5F53\u524D\u7248\u672C"),
10809
+ h2("strong", null, `v${IM_PLUGIN_VERSION}`)
10810
+ )
10556
10811
  ),
10557
10812
  h2(
10558
10813
  "span",