@xmanrui/dsh-im 4.36.1 → 4.38.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 (63) hide show
  1. package/README.en.md +14 -2
  2. package/README.md +13 -1
  3. package/assets/logo-plugin-message-link-gradient.webp +0 -0
  4. package/lib/client.js +417 -189
  5. package/lib/index.js +317 -316
  6. package/package.json +2 -2
  7. package/plugin-src/client/bot-general-settings.js +120 -0
  8. package/plugin-src/client/channels/dingtalk/api.js +3 -1
  9. package/plugin-src/client/channels/feishu/api.js +6 -2
  10. package/plugin-src/client/channels/qq/api.js +3 -1
  11. package/plugin-src/client/channels/shared/token-api.js +3 -1
  12. package/plugin-src/client/channels/wecom/api.js +3 -1
  13. package/plugin-src/client/channels/wecom-app/api.js +3 -1
  14. package/plugin-src/client/channels/weixin/api.js +3 -1
  15. package/plugin-src/client/channels/whatsapp/api.js +3 -1
  16. package/plugin-src/client/delivery-settings.js +5 -1
  17. package/plugin-src/client/i18n.js +14 -0
  18. package/plugin-src/client/styles.js +19 -0
  19. package/plugin-src/host/channels/dingtalk/rpc.mjs +11 -0
  20. package/plugin-src/host/channels/email/rpc.mjs +1 -0
  21. package/plugin-src/host/channels/feishu/production.mjs +1 -0
  22. package/plugin-src/host/channels/feishu/rpc.mjs +31 -0
  23. package/plugin-src/host/channels/imessage/rpc.mjs +1 -0
  24. package/plugin-src/host/channels/matrix/rpc.mjs +10 -0
  25. package/plugin-src/host/channels/qq/rpc.mjs +11 -0
  26. package/plugin-src/host/channels/shared/rpc.mjs +9 -0
  27. package/plugin-src/host/channels/slack/rpc.mjs +10 -0
  28. package/plugin-src/host/channels/wecom/rpc.mjs +11 -0
  29. package/plugin-src/host/channels/wecom-app/rpc.mjs +10 -0
  30. package/plugin-src/host/channels/weixin/rpc.mjs +11 -0
  31. package/plugin-src/host/channels/whatsapp/rpc.mjs +11 -0
  32. package/scripts/verify-package.mjs +11 -6
  33. package/src/channels/dingtalk/dingtalk-bridge.mjs +31 -2
  34. package/src/channels/dingtalk/dingtalk-menu.mjs +1 -1
  35. package/src/channels/dingtalk/dingtalk-runtime.mjs +2 -1
  36. package/src/channels/discord/discord-runtime.mjs +3 -1
  37. package/src/channels/feishu/bridge.mjs +91 -15
  38. package/src/channels/feishu/feishu-cards.mjs +16 -11
  39. package/src/channels/feishu/feishu-runtime.mjs +10 -1
  40. package/src/channels/feishu/multi-bot-controller.mjs +18 -0
  41. package/src/channels/feishu/plugin-config-store.mjs +2 -1
  42. package/src/channels/feishu/slash-command-panel.mjs +1 -0
  43. package/src/channels/feishu/step-push-mode.mjs +21 -0
  44. package/src/channels/matrix/matrix-crypto.mjs +19 -5
  45. package/src/channels/qq/qq-bridge.mjs +40 -2
  46. package/src/channels/qq/qq-menu.mjs +2 -2
  47. package/src/channels/shared/bot-workspace-store.mjs +69 -1
  48. package/src/channels/shared/busy-message-dispatcher.mjs +94 -0
  49. package/src/channels/shared/clear-command.mjs +85 -0
  50. package/src/channels/shared/command-catalog.mjs +3 -0
  51. package/src/channels/shared/command-permission.mjs +2 -0
  52. package/src/channels/shared/control-command.mjs +20 -11
  53. package/src/channels/shared/harness-approval.mjs +102 -2
  54. package/src/channels/shared/i18n-en/feishu.mjs +6 -4
  55. package/src/channels/shared/i18n-en/qq.mjs +2 -1
  56. package/src/channels/shared/i18n-en/shared-b.mjs +27 -0
  57. package/src/channels/shared/i18n-en/shared-c.mjs +4 -0
  58. package/src/channels/shared/message-mode.mjs +19 -0
  59. package/src/channels/shared/text-harness-bridge.mjs +48 -5
  60. package/src/channels/wecom/wecom-bridge.mjs +26 -2
  61. package/src/channels/wecom/wecom-cards.mjs +1 -1
  62. package/src/channels/wecom-app/wecom-app-bridge.mjs +26 -2
  63. package/src/channels/weixin/weixin-bridge.mjs +22 -2
package/lib/client.js CHANGED
@@ -590,12 +590,12 @@ async function callManagementRpc(connection, channel7, method, payload, signal)
590
590
  }
591
591
 
592
592
  // plugin-src/client/index.js
593
- var React39 = __toESM(require("react"), 1);
593
+ var React40 = __toESM(require("react"), 1);
594
594
 
595
595
  // package.json
596
596
  var package_default = {
597
597
  name: "@xmanrui/dsh-im",
598
- version: "4.36.1",
598
+ version: "4.38.0",
599
599
  icon: "./assets/logo-plugin-message-link-gradient.webp",
600
600
  description: "\u628A\u5FAE\u4FE1\u3001\u98DE\u4E66\u3001\u4F01\u5FAE\u3001\u9489\u9489\u3001QQ\u3001Telegram\u3001WhatsApp\u3001Slack\u3001Discord\u3001Matrix\u63A5\u5165DSH\u3002 Connect Telegram, WhatsApp, Slack, Discord, Matrix, WeChat, Feishu, WeCom, DingTalk, and QQ to DSH.",
601
601
  keywords: [
@@ -729,7 +729,7 @@ var package_default = {
729
729
  },
730
730
  optionalDependencies: {
731
731
  "@tencent-qqmail/agently-cli": "^1.0.18",
732
- sharp: "0.35.4"
732
+ sharp: "0.35.5"
733
733
  }
734
734
  };
735
735
 
@@ -931,6 +931,12 @@ function EmailLogoGlyph({ size } = {}) {
931
931
  );
932
932
  }
933
933
 
934
+ // src/channels/shared/message-mode.mjs
935
+ var SET_MESSAGE_MODE_ENDPOINT = "bot.message-mode.set";
936
+ function normalizeBusyMessageMode(value) {
937
+ return value === "steer" ? "steer" : "queue";
938
+ }
939
+
934
940
  // plugin-src/client/connection-error.js
935
941
  var React3 = __toESM(require("react"), 1);
936
942
 
@@ -2168,6 +2174,20 @@ var EN = Object.freeze({
2168
2174
  "\u5C1A\u672A\u914D\u7F6E\u6295\u9012\u76EE\u6807": "No delivery targets yet",
2169
2175
  "\u70B9\u51FB\u201C\u65B0\u5EFA\u76EE\u6807\u201D\u53EF\u4ECE\u5DF2\u804A\u8FC7\u7684\u4F1A\u8BDD\u9009\u62E9\uFF0C\u4E5F\u53EF\u624B\u52A8\u586B\u5199\u3002": "Select New target to choose a conversation or enter the details manually.",
2170
2176
  "\u5168\u5C40\u8BBE\u7F6E": "Global settings",
2177
+ "\u901A\u7528": "General",
2178
+ "\u5904\u7406\u4E2D\u2026": "Processing\u2026",
2179
+ "\u673A\u5668\u4EBA\u901A\u7528\u8BBE\u7F6E": "General bot settings",
2180
+ "\u5C55\u5F00\u601D\u8003\u8FC7\u7A0B": "Expand thinking",
2181
+ "\u5C55\u5F00\u5DE5\u5177\u6458\u8981": "Expand tool summaries",
2182
+ "\u4EC5\u5BF9\u5B9E\u65F6\u8FC7\u7A0B\u5361\u751F\u6548\uFF0C\u4EFB\u52A1\u7ED3\u675F\u540E\u81EA\u52A8\u6536\u8D77\u3002": "Applies to streaming process cards only. Panels collapse when the task ends.",
2183
+ "\u8BF7\u9009\u62E9\u5B9E\u65F6\u8FC7\u7A0B\u5361\u9762\u677F\u7684\u5C55\u5F00\u72B6\u6001\u3002": "Choose whether to expand the streaming process card panels.",
2184
+ "\u6D88\u606F\u5904\u7406\u65B9\u5F0F": "Message handling",
2185
+ "\u6392\u961F": "Queue",
2186
+ "\u63D2\u8BDD": "Steer",
2187
+ "\u5F53\u524D\u4EFB\u52A1\u7ED3\u675F\u540E\u5904\u7406\u65B0\u6D88\u606F": "Process new messages after the current task",
2188
+ "\u5C06\u65B0\u6D88\u606F\u8865\u5145\u5230\u5F53\u524D\u4EFB\u52A1": "Add new messages to the current task",
2189
+ "\u65E0\u6CD5\u8BFB\u53D6\u6D88\u606F\u5904\u7406\u8BBE\u7F6E\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002": "Could not read message handling settings. Try again later.",
2190
+ "\u8BF7\u63D0\u4EA4\u6709\u6548\u7684\u6D88\u606F\u5904\u7406\u65B9\u5F0F\u3002": "Choose a valid message handling mode.",
2171
2191
  "\u901A\u7528\u8BBE\u7F6E": "General settings",
2172
2192
  "\u901A\u7528\u8BBE\u7F6E\u5206\u7C7B": "General settings categories",
2173
2193
  "\u9644\u4EF6": "Attachments",
@@ -3557,6 +3577,7 @@ var DINGTALK_ENDPOINTS = Object.freeze({
3557
3577
  setModel: SET_MODEL_ENDPOINT,
3558
3578
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
3559
3579
  setContextEnhancement: "bot.context-enhancement.set",
3580
+ setBusyMessageMode: "bot.message-mode.set",
3560
3581
  setAccessPolicy: "bot.access-policy.set",
3561
3582
  setAlias: "bot.alias.set"
3562
3583
  });
@@ -3705,6 +3726,7 @@ function normalizeBot(value) {
3705
3726
  workspace: optionalString(value.workspace, 4096) ?? "",
3706
3727
  model: normalizeModelSelection(value.model),
3707
3728
  agentPreset: normalizeAgentPresetId(value.agentPreset),
3729
+ busyMessageMode: normalizeBusyMessageMode(value.busyMessageMode),
3708
3730
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
3709
3731
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
3710
3732
  bot: {
@@ -6533,6 +6555,7 @@ var TOKEN_BOT_ENDPOINTS = Object.freeze({
6533
6555
  setModel: SET_MODEL_ENDPOINT,
6534
6556
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
6535
6557
  setContextEnhancement: "bot.context-enhancement.set",
6558
+ setBusyMessageMode: "bot.message-mode.set",
6536
6559
  setAccessPolicy: "bot.access-policy.set",
6537
6560
  setAlias: "bot.alias.set",
6538
6561
  setThinkingTraces: "bot.thinking-traces.set"
@@ -6564,6 +6587,7 @@ function createTokenChannelApi(channel7, connectionSummary, {
6564
6587
  workspace: text2(value.workspace, "", 4096),
6565
6588
  model: normalizeModelSelection(value.model),
6566
6589
  agentPreset: normalizeAgentPresetId(value.agentPreset),
6590
+ busyMessageMode: normalizeBusyMessageMode(value.busyMessageMode),
6567
6591
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
6568
6592
  // Absent from the backend means ON; only an explicit false opts out.
6569
6593
  thinkingTraces: value.thinkingTraces !== false,
@@ -7216,6 +7240,16 @@ var FEISHU_STEP_PUSH_MODES = Object.freeze({
7216
7240
  LIVE_COT: "live_cot"
7217
7241
  });
7218
7242
  var DEFAULT_FEISHU_STEP_PUSH_MODE = FEISHU_STEP_PUSH_MODES.STREAMING_CARD;
7243
+ var DEFAULT_FEISHU_STEP_CARD_PANELS = Object.freeze({
7244
+ thinkingExpanded: false,
7245
+ toolsExpanded: true
7246
+ });
7247
+ function normalizeFeishuStepCardPanels(value) {
7248
+ return Object.freeze({
7249
+ thinkingExpanded: typeof value?.thinkingExpanded === "boolean" ? value.thinkingExpanded : DEFAULT_FEISHU_STEP_CARD_PANELS.thinkingExpanded,
7250
+ toolsExpanded: typeof value?.toolsExpanded === "boolean" ? value.toolsExpanded : DEFAULT_FEISHU_STEP_CARD_PANELS.toolsExpanded
7251
+ });
7252
+ }
7219
7253
  function normalizeFeishuStepPushMode(value) {
7220
7254
  if (value === FEISHU_STEP_PUSH_MODES.STREAMING_CARD) {
7221
7255
  return FEISHU_STEP_PUSH_MODES.STREAMING_CARD;
@@ -7256,6 +7290,7 @@ var SLASH_COMMAND_MANIFEST = Object.freeze([
7256
7290
  { command: "help", icon: "promptword_outlined", default: "\u67E5\u770B\u5E2E\u52A9", en_us: "Show help" },
7257
7291
  { command: "status", icon: "ai-functions_outlined", default: "\u67E5\u770B\u673A\u5668\u4EBA\u72B6\u6001", en_us: "Show bot status" },
7258
7292
  { command: "compact", icon: "ai-block_outlined", default: "\u538B\u7F29\u5F53\u524D\u4F1A\u8BDD\u4E0A\u4E0B\u6587", en_us: "Compact the current session" },
7293
+ { command: "clear", icon: "clear_outlined", default: "\u6E05\u7A7A\u5F53\u524D\u4F1A\u8BDD\u4E0A\u4E0B\u6587", en_us: "Clear the current session context" },
7259
7294
  { command: "sessionlist", icon: "chat-ai_outlined", default: "\u5217\u51FA\u4F1A\u8BDD", en_us: "List sessions" },
7260
7295
  { command: "workspacelist", icon: "folder_outlined", default: "\u5217\u51FA\u5DE5\u4F5C\u533A", en_us: "List workspaces" },
7261
7296
  { command: "workspaces", icon: "folder_outlined", default: "\u5217\u51FA\u5DE5\u4F5C\u533A", en_us: "List workspaces" },
@@ -7336,12 +7371,14 @@ var FEISHU_ENDPOINTS = Object.freeze({
7336
7371
  setModel: SET_MODEL_ENDPOINT,
7337
7372
  setAgentPreset: "bot.preset.set",
7338
7373
  setContextEnhancement: "bot.context-enhancement.set",
7374
+ setBusyMessageMode: "bot.message-mode.set",
7339
7375
  setAccessPolicy: "bot.access-policy.set",
7340
7376
  setAlias: "bot.alias.set",
7341
7377
  setGroupResponseMode: "bot.group-response-mode.set",
7342
7378
  setMentionTopicReply: "bot.mention-topic-reply.set",
7343
7379
  setStepPush: "bot.step-push.set",
7344
7380
  setStepPushMode: "bot.step-push-mode.set",
7381
+ setStepCardPanels: "bot.step-card-panels.set",
7345
7382
  setVoice: "bot.voice.set",
7346
7383
  setSlashPanel: "bot.slash-panel.set",
7347
7384
  // Kept for rolling upgrades. The multi-bot UI never calls these endpoints.
@@ -7494,12 +7531,14 @@ function normalizeBotConnection(value, fallbackBotId) {
7494
7531
  workspace: optionalString2(value.workspace)?.slice(0, 4096) ?? "",
7495
7532
  model: normalizeModelSelection(value.model),
7496
7533
  agentPreset: normalizeAgentPresetId(value.agentPreset),
7534
+ busyMessageMode: normalizeBusyMessageMode(value.busyMessageMode),
7497
7535
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
7498
7536
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
7499
7537
  groupResponseMode: normalizeGroupResponseMode(value.groupResponseMode),
7500
7538
  mentionTopicReply: value.mentionTopicReply !== false,
7501
7539
  stepPush: value.stepPush === true,
7502
7540
  stepPushMode: normalizeFeishuStepPushMode(value.stepPushMode),
7541
+ stepCardPanels: normalizeFeishuStepCardPanels(value.stepCardPanels),
7503
7542
  voice: normalizeFeishuVoiceConfig(value.voice),
7504
7543
  slashPanel: normalizeSlashPanelConfig(value.slashPanel),
7505
7544
  groupMessagePermissionGranted: value.groupMessagePermissionGranted === true,
@@ -9747,6 +9786,7 @@ var QQ_ENDPOINTS = Object.freeze({
9747
9786
  setModel: SET_MODEL_ENDPOINT,
9748
9787
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
9749
9788
  setContextEnhancement: "bot.context-enhancement.set",
9789
+ setBusyMessageMode: "bot.message-mode.set",
9750
9790
  setAccessPolicy: "bot.access-policy.set",
9751
9791
  setAlias: "bot.alias.set"
9752
9792
  });
@@ -9816,6 +9856,7 @@ function normalizeBot3(value) {
9816
9856
  workspace: text3(value.workspace, "", 4096),
9817
9857
  model: normalizeModelSelection(value.model),
9818
9858
  agentPreset: normalizeAgentPresetId(value.agentPreset),
9859
+ busyMessageMode: normalizeBusyMessageMode(value.busyMessageMode),
9819
9860
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
9820
9861
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
9821
9862
  bot: {
@@ -11266,6 +11307,7 @@ var WECOM_ENDPOINTS = Object.freeze({
11266
11307
  setModel: SET_MODEL_ENDPOINT,
11267
11308
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
11268
11309
  setContextEnhancement: "bot.context-enhancement.set",
11310
+ setBusyMessageMode: "bot.message-mode.set",
11269
11311
  setAccessPolicy: "bot.access-policy.set",
11270
11312
  setAlias: "bot.alias.set"
11271
11313
  });
@@ -11341,6 +11383,7 @@ function normalizeBot4(value) {
11341
11383
  workspace: text4(value.workspace, "", 4096),
11342
11384
  model: normalizeModelSelection(value.model),
11343
11385
  agentPreset: normalizeAgentPresetId(value.agentPreset),
11386
+ busyMessageMode: normalizeBusyMessageMode(value.busyMessageMode),
11344
11387
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
11345
11388
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
11346
11389
  bot: {
@@ -12136,6 +12179,7 @@ var WECOM_APP_ENDPOINTS = Object.freeze({
12136
12179
  setModel: SET_MODEL_ENDPOINT,
12137
12180
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
12138
12181
  setContextEnhancement: "bot.context-enhancement.set",
12182
+ setBusyMessageMode: "bot.message-mode.set",
12139
12183
  setAccessPolicy: "bot.access-policy.set",
12140
12184
  setAlias: "bot.alias.set"
12141
12185
  });
@@ -12187,6 +12231,7 @@ function normalizeBot5(value) {
12187
12231
  workspace: text5(value.workspace, "", 4096),
12188
12232
  model: normalizeModelSelection(value.model),
12189
12233
  agentPreset: normalizeAgentPresetId(value.agentPreset),
12234
+ busyMessageMode: normalizeBusyMessageMode(value.busyMessageMode),
12190
12235
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
12191
12236
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
12192
12237
  bot: {
@@ -12999,6 +13044,7 @@ var WEIXIN_ENDPOINTS = Object.freeze({
12999
13044
  setModel: SET_MODEL_ENDPOINT,
13000
13045
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
13001
13046
  setContextEnhancement: "bot.context-enhancement.set",
13047
+ setBusyMessageMode: "bot.message-mode.set",
13002
13048
  setAccessPolicy: "bot.access-policy.set",
13003
13049
  setAlias: "bot.alias.set"
13004
13050
  });
@@ -13111,6 +13157,7 @@ function normalizeBot6(value) {
13111
13157
  workspace: string(value.workspace).slice(0, 4096),
13112
13158
  model: normalizeModelSelection(value.model),
13113
13159
  agentPreset: normalizeAgentPresetId(value.agentPreset),
13160
+ busyMessageMode: normalizeBusyMessageMode(value.busyMessageMode),
13114
13161
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
13115
13162
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
13116
13163
  bot: {
@@ -14178,7 +14225,8 @@ var WHATSAPP_ENDPOINTS = Object.freeze({
14178
14225
  setWorkspace: "bot.workspace.set",
14179
14226
  setModel: SET_MODEL_ENDPOINT,
14180
14227
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
14181
- setContextEnhancement: "bot.context-enhancement.set"
14228
+ setContextEnhancement: "bot.context-enhancement.set",
14229
+ setBusyMessageMode: "bot.message-mode.set"
14182
14230
  });
14183
14231
  var PROVISION_STATES5 = /* @__PURE__ */ new Set(["starting", "pending", "connecting", "connected", "failed", "cancelled"]);
14184
14232
  var BOT_STATES = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
@@ -14247,6 +14295,7 @@ function normalizeBot7(value) {
14247
14295
  workspace: text6(value.workspace, "", 4096),
14248
14296
  model: normalizeModelSelection(value.model),
14249
14297
  agentPreset: normalizeAgentPresetId(value.agentPreset),
14298
+ busyMessageMode: normalizeBusyMessageMode(value.busyMessageMode),
14250
14299
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
14251
14300
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
14252
14301
  bot: {
@@ -16202,7 +16251,7 @@ function installInterfaceLanguageMirror(ctx, {
16202
16251
  }
16203
16252
 
16204
16253
  // plugin-src/client/delivery-settings.js
16205
- var React34 = __toESM(require("react"), 1);
16254
+ var React35 = __toESM(require("react"), 1);
16206
16255
 
16207
16256
  // plugin-src/client/access-policy-settings.js
16208
16257
  var React28 = __toESM(require("react"), 1);
@@ -16620,8 +16669,167 @@ function AccessPolicySettingsPage({ channel: channel7, account, rpcCall, onSaved
16620
16669
  );
16621
16670
  }
16622
16671
 
16623
- // plugin-src/client/bot-settings-tabs.js
16672
+ // plugin-src/client/bot-general-settings.js
16624
16673
  var React29 = __toESM(require("react"), 1);
16674
+ function settingsFromResult(result, botId) {
16675
+ if (result?.ok !== true) throw new Error(result?.error?.message || "\u65E0\u6CD5\u8BFB\u53D6\u901A\u7528\u8BBE\u7F6E\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
16676
+ const bot = result.value?.bots?.find((entry) => entry.botId === botId);
16677
+ if (!bot) throw new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");
16678
+ return {
16679
+ busyMessageMode: normalizeBusyMessageMode(bot.busyMessageMode),
16680
+ stepCardPanels: normalizeFeishuStepCardPanels(bot.stepCardPanels)
16681
+ };
16682
+ }
16683
+ function BotGeneralSettingsPage({ channel: channel7, account, rpcCall }) {
16684
+ const modeId = React29.useId();
16685
+ const [settings, setSettings] = React29.useState(() => ({
16686
+ busyMessageMode: "queue",
16687
+ stepCardPanels: normalizeFeishuStepCardPanels()
16688
+ }));
16689
+ const [savedSettings, setSavedSettings] = React29.useState(null);
16690
+ const [busy, setBusy] = React29.useState(false);
16691
+ const [feedback, setFeedback] = React29.useState(null);
16692
+ const mounted = React29.useRef(false);
16693
+ const inFlight = React29.useRef(false);
16694
+ const mode = settings.busyMessageMode;
16695
+ const load = React29.useCallback(async () => {
16696
+ if (inFlight.current) return;
16697
+ inFlight.current = true;
16698
+ setBusy(true);
16699
+ setFeedback(null);
16700
+ try {
16701
+ const value = settingsFromResult(await rpcCall("connection.status", {}), account.botId);
16702
+ if (!mounted.current) return;
16703
+ setSettings(value);
16704
+ setSavedSettings(value);
16705
+ } catch (error) {
16706
+ if (mounted.current) setFeedback(error.message);
16707
+ } finally {
16708
+ inFlight.current = false;
16709
+ if (mounted.current) setBusy(false);
16710
+ }
16711
+ }, [account.botId, rpcCall]);
16712
+ React29.useEffect(() => {
16713
+ mounted.current = true;
16714
+ void load();
16715
+ return () => {
16716
+ mounted.current = false;
16717
+ };
16718
+ }, [load]);
16719
+ const save = async (field2, value) => {
16720
+ if (inFlight.current || savedSettings === null || value === savedSettings[field2]) return;
16721
+ inFlight.current = true;
16722
+ setSettings({ ...settings, [field2]: value });
16723
+ setBusy(true);
16724
+ setFeedback(null);
16725
+ try {
16726
+ const endpoint = field2 === "stepCardPanels" ? FEISHU_ENDPOINTS.setStepCardPanels : SET_MESSAGE_MODE_ENDPOINT;
16727
+ const saved = settingsFromResult(await rpcCall(endpoint, {
16728
+ botId: account.botId,
16729
+ [field2]: value
16730
+ }), account.botId);
16731
+ if (!mounted.current) return;
16732
+ setSettings(saved);
16733
+ setSavedSettings(saved);
16734
+ } catch (error) {
16735
+ if (mounted.current) {
16736
+ setSettings(savedSettings);
16737
+ setFeedback(error.message);
16738
+ }
16739
+ } finally {
16740
+ inFlight.current = false;
16741
+ if (mounted.current) setBusy(false);
16742
+ }
16743
+ };
16744
+ return h2(
16745
+ "section",
16746
+ { className: "dim-botGeneralSettings", "aria-label": "\u673A\u5668\u4EBA\u901A\u7528\u8BBE\u7F6E", "aria-busy": busy },
16747
+ h2(
16748
+ "div",
16749
+ { className: "dim-botGeneralList" },
16750
+ h2(
16751
+ "div",
16752
+ { className: "dim-botGeneralRow" },
16753
+ h2(
16754
+ "div",
16755
+ { className: "dim-botGeneralText" },
16756
+ h2("label", { className: "dim-botGeneralTitle", htmlFor: modeId }, "\u6D88\u606F\u5904\u7406\u65B9\u5F0F"),
16757
+ h2("p", { className: "dim-botGeneralHelp", id: `${modeId}-description` }, mode === "queue" ? "\u5F53\u524D\u4EFB\u52A1\u7ED3\u675F\u540E\u5904\u7406\u65B0\u6D88\u606F" : "\u5C06\u65B0\u6D88\u606F\u8865\u5145\u5230\u5F53\u524D\u4EFB\u52A1")
16758
+ ),
16759
+ h2(
16760
+ "div",
16761
+ { className: "dim-botGeneralControl" },
16762
+ h2(
16763
+ "select",
16764
+ {
16765
+ id: modeId,
16766
+ value: mode,
16767
+ disabled: busy || savedSettings === null,
16768
+ "aria-label": "\u6D88\u606F\u5904\u7406\u65B9\u5F0F",
16769
+ "aria-describedby": `${modeId}-description`,
16770
+ onChange: (event) => void save("busyMessageMode", event.target.value)
16771
+ },
16772
+ h2("option", { value: "queue" }, "\u6392\u961F"),
16773
+ h2("option", { value: "steer" }, "\u63D2\u8BDD")
16774
+ ),
16775
+ h2(
16776
+ "svg",
16777
+ { width: 14, height: 14, viewBox: "0 0 16 16", fill: "none", "aria-hidden": true },
16778
+ h2("path", { d: "m4 6 4 4 4-4", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round" })
16779
+ )
16780
+ )
16781
+ ),
16782
+ channel7 === "feishu" ? [
16783
+ ["thinkingExpanded", "\u5C55\u5F00\u601D\u8003\u8FC7\u7A0B"],
16784
+ ["toolsExpanded", "\u5C55\u5F00\u5DE5\u5177\u6458\u8981"]
16785
+ ].map(([field2, label]) => h2(
16786
+ "div",
16787
+ { key: field2, className: "dim-botGeneralRow dim-botGeneralPanelRow" },
16788
+ h2("label", { className: "dim-botGeneralTitle", htmlFor: `${modeId}-${field2}` }, label),
16789
+ h2(
16790
+ "div",
16791
+ { className: "dim-botGeneralControl" },
16792
+ h2("input", {
16793
+ id: `${modeId}-${field2}`,
16794
+ type: "checkbox",
16795
+ role: "switch",
16796
+ className: "dim-contextSwitch",
16797
+ checked: settings.stepCardPanels[field2],
16798
+ disabled: busy || savedSettings === null,
16799
+ "aria-label": label,
16800
+ "aria-describedby": `${modeId}-panels-description`,
16801
+ onChange: (event) => void save("stepCardPanels", {
16802
+ ...settings.stepCardPanels,
16803
+ [field2]: event.target.checked
16804
+ })
16805
+ })
16806
+ )
16807
+ )) : null
16808
+ ),
16809
+ channel7 === "feishu" ? h2(
16810
+ "p",
16811
+ { className: "dim-botGeneralHelp dim-botGeneralPanelHelp", id: `${modeId}-panels-description` },
16812
+ "\u4EC5\u5BF9\u5B9E\u65F6\u8FC7\u7A0B\u5361\u751F\u6548\uFF0C\u4EFB\u52A1\u7ED3\u675F\u540E\u81EA\u52A8\u6536\u8D77\u3002"
16813
+ ) : null,
16814
+ feedback ? h2("p", {
16815
+ className: "dim-accessFeedback",
16816
+ "data-tone": "error",
16817
+ role: "alert"
16818
+ }, feedback) : null,
16819
+ savedSettings === null && !busy ? h2(
16820
+ "div",
16821
+ { className: "dim-botGeneralActions" },
16822
+ h2("button", {
16823
+ type: "button",
16824
+ className: "dim-deliveryButton",
16825
+ onClick: () => void load()
16826
+ }, "\u91CD\u65B0\u8BFB\u53D6")
16827
+ ) : null
16828
+ );
16829
+ }
16830
+
16831
+ // plugin-src/client/bot-settings-tabs.js
16832
+ var React30 = __toESM(require("react"), 1);
16625
16833
  function revealTab(strip, tab) {
16626
16834
  if (!strip || !tab) return;
16627
16835
  const viewport = strip.getBoundingClientRect();
@@ -16630,11 +16838,11 @@ function revealTab(strip, tab) {
16630
16838
  else if (bounds.right > viewport.right) strip.scrollLeft += bounds.right - viewport.right;
16631
16839
  }
16632
16840
  function BotSettingsTabs({ tabs, activeTabId, onChange }) {
16633
- const barRef = React29.useRef(null);
16634
- const stripRef = React29.useRef(null);
16635
- const listRef = React29.useRef(null);
16636
- const [scroll, setScroll] = React29.useState({ overflow: false, left: false, right: false });
16637
- const measure = React29.useCallback(() => {
16841
+ const barRef = React30.useRef(null);
16842
+ const stripRef = React30.useRef(null);
16843
+ const listRef = React30.useRef(null);
16844
+ const [scroll, setScroll] = React30.useState({ overflow: false, left: false, right: false });
16845
+ const measure = React30.useCallback(() => {
16638
16846
  const bar = barRef.current;
16639
16847
  const strip = stripRef.current;
16640
16848
  const list = listRef.current;
@@ -16647,7 +16855,7 @@ function BotSettingsTabs({ tabs, activeTabId, onChange }) {
16647
16855
  };
16648
16856
  setScroll((previous) => Object.keys(next).every((key) => next[key] === previous[key]) ? previous : next);
16649
16857
  }, []);
16650
- React29.useEffect(() => {
16858
+ React30.useEffect(() => {
16651
16859
  const strip = stripRef.current;
16652
16860
  if (!strip) return void 0;
16653
16861
  const refresh = () => {
@@ -16737,7 +16945,7 @@ function BotSettingsTabs({ tabs, activeTabId, onChange }) {
16737
16945
  }
16738
16946
 
16739
16947
  // plugin-src/client/channels/feishu/group-settings.js
16740
- var React30 = __toESM(require("react"), 1);
16948
+ var React31 = __toESM(require("react"), 1);
16741
16949
  var GROUP_MESSAGE_PERMISSION_OPERATION2 = FEISHU_REGISTRATION_OPERATIONS.GROUP_MESSAGE_PERMISSION;
16742
16950
  function SettingsButton({ children, kind = "secondary", className = "", ...props }) {
16743
16951
  return h2("button", {
@@ -16798,9 +17006,9 @@ function GroupResponseModeEditor({
16798
17006
  onAuthorize
16799
17007
  }) {
16800
17008
  const current = normalizeGroupResponseMode(value);
16801
- const [saving, setSaving] = React30.useState(false);
16802
- const [authorizing, setAuthorizing] = React30.useState(false);
16803
- const [error, setError] = React30.useState(null);
17009
+ const [saving, setSaving] = React31.useState(false);
17010
+ const [authorizing, setAuthorizing] = React31.useState(false);
17011
+ const [error, setError] = React31.useState(null);
16804
17012
  const change = async (event) => {
16805
17013
  const next = normalizeGroupResponseMode(event.target.value);
16806
17014
  if (next === current || saving || disabled) return;
@@ -16881,8 +17089,8 @@ function GroupResponseModeEditor({
16881
17089
  }
16882
17090
  function MentionTopicReplyEditor({ value = true, disabled = false, onSave }) {
16883
17091
  const current = value === true ? "on" : "off";
16884
- const [saving, setSaving] = React30.useState(false);
16885
- const [error, setError] = React30.useState(null);
17092
+ const [saving, setSaving] = React31.useState(false);
17093
+ const [error, setError] = React31.useState(null);
16886
17094
  const change = async (event) => {
16887
17095
  const next = event.target.value === "on";
16888
17096
  if ((next ? "on" : "off") === current || saving || disabled) return;
@@ -17069,14 +17277,14 @@ function PermissionFlow({ provision, now, busy, botName, onRetry, onCancel, onCl
17069
17277
  );
17070
17278
  }
17071
17279
  function FeishuGroupSettingsPage({ account, rpcCall }) {
17072
- const [settings, setSettings] = React30.useState(() => groupSettingsFrom(account));
17073
- const [refreshing, setRefreshing] = React30.useState(false);
17074
- const [refreshError, setRefreshError] = React30.useState(null);
17075
- const [provision, setProvision] = React30.useState(null);
17076
- const [provisionBusy, setProvisionBusy] = React30.useState(false);
17077
- const [now, setNow] = React30.useState(() => Date.now());
17078
- const mounted = React30.useRef(true);
17079
- React30.useEffect(() => {
17280
+ const [settings, setSettings] = React31.useState(() => groupSettingsFrom(account));
17281
+ const [refreshing, setRefreshing] = React31.useState(false);
17282
+ const [refreshError, setRefreshError] = React31.useState(null);
17283
+ const [provision, setProvision] = React31.useState(null);
17284
+ const [provisionBusy, setProvisionBusy] = React31.useState(false);
17285
+ const [now, setNow] = React31.useState(() => Date.now());
17286
+ const mounted = React31.useRef(true);
17287
+ React31.useEffect(() => {
17080
17288
  setSettings(groupSettingsFrom(account));
17081
17289
  }, [
17082
17290
  account.botId,
@@ -17084,22 +17292,22 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
17084
17292
  account.mentionTopicReply,
17085
17293
  account.groupMessagePermissionGranted
17086
17294
  ]);
17087
- React30.useEffect(() => {
17295
+ React31.useEffect(() => {
17088
17296
  mounted.current = true;
17089
17297
  return () => {
17090
17298
  mounted.current = false;
17091
17299
  };
17092
17300
  }, []);
17093
- const invoke = React30.useCallback(async (endpoint, payload = {}, signal) => {
17301
+ const invoke = React31.useCallback(async (endpoint, payload = {}, signal) => {
17094
17302
  if (typeof rpcCall !== "function") throw new Error("\u98DE\u4E66\u7FA4\u804A\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
17095
17303
  return unwrapRpcResult3(await rpcCall(endpoint, payload, signal));
17096
17304
  }, [rpcCall]);
17097
- const applySnapshot = React30.useCallback((value) => {
17305
+ const applySnapshot = React31.useCallback((value) => {
17098
17306
  const result = targetBotFromSnapshot(value, account.botId);
17099
17307
  if (mounted.current) setSettings(groupSettingsFrom(result.bot));
17100
17308
  return result;
17101
17309
  }, [account.botId]);
17102
- const loadSettings = React30.useCallback(async ({ signal, restoreProvisioning = false } = {}) => {
17310
+ const loadSettings = React31.useCallback(async ({ signal, restoreProvisioning = false } = {}) => {
17103
17311
  setRefreshing(true);
17104
17312
  setRefreshError(null);
17105
17313
  try {
@@ -17128,16 +17336,16 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
17128
17336
  if (!signal?.aborted && mounted.current) setRefreshing(false);
17129
17337
  }
17130
17338
  }, [account.botId, applySnapshot, invoke]);
17131
- React30.useEffect(() => {
17339
+ React31.useEffect(() => {
17132
17340
  const controller = new AbortController();
17133
17341
  void loadSettings({ signal: controller.signal, restoreProvisioning: true });
17134
17342
  return () => controller.abort();
17135
17343
  }, [loadSettings]);
17136
- const saveSetting = React30.useCallback(async (endpoint, payload) => {
17344
+ const saveSetting = React31.useCallback(async (endpoint, payload) => {
17137
17345
  const value = await invoke(endpoint, { botId: account.botId, ...payload });
17138
17346
  applySnapshot(value);
17139
17347
  }, [account.botId, applySnapshot, invoke]);
17140
- const startAuthorization = React30.useCallback(async ({ replace = false } = {}) => {
17348
+ const startAuthorization = React31.useCallback(async ({ replace = false } = {}) => {
17141
17349
  if (provisionBusy) return;
17142
17350
  const previousAttemptId = provision?.attemptId;
17143
17351
  setProvisionBusy(true);
@@ -17178,13 +17386,13 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
17178
17386
  if (mounted.current) setProvisionBusy(false);
17179
17387
  }
17180
17388
  }, [account.botId, invoke, provision?.attemptId, provisionBusy]);
17181
- const finishAuthorization = React30.useCallback(async (signal) => {
17389
+ const finishAuthorization = React31.useCallback(async (signal) => {
17182
17390
  const bot = await loadSettings({ signal, restoreProvisioning: false });
17183
17391
  if (signal?.aborted || !mounted.current) return;
17184
17392
  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");
17185
17393
  setProvision(null);
17186
17394
  }, [loadSettings]);
17187
- React30.useEffect(() => {
17395
+ React31.useEffect(() => {
17188
17396
  if (!provision?.attemptId || !["qr", "connecting"].includes(provision.phase) || provision.expired) return void 0;
17189
17397
  const timerHost = globalThis.window ?? globalThis;
17190
17398
  const controller = new AbortController();
@@ -17228,7 +17436,7 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
17228
17436
  timerHost.clearTimeout(timer);
17229
17437
  };
17230
17438
  }, [account.botId, finishAuthorization, invoke, provision]);
17231
- React30.useEffect(() => {
17439
+ React31.useEffect(() => {
17232
17440
  if (!provision?.attemptId || provision.phase !== "qr" || provision.expired) return void 0;
17233
17441
  const timerHost = globalThis.window ?? globalThis;
17234
17442
  const tick = () => {
@@ -17242,7 +17450,7 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
17242
17450
  const timer = timerHost.setInterval(tick, 1e3);
17243
17451
  return () => timerHost.clearInterval(timer);
17244
17452
  }, [provision?.attemptId, provision?.expired, provision?.expiresAt, provision?.phase]);
17245
- const cancelAuthorization = React30.useCallback(async () => {
17453
+ const cancelAuthorization = React31.useCallback(async () => {
17246
17454
  if (!provision?.attemptId || provisionBusy) {
17247
17455
  setProvision(null);
17248
17456
  return;
@@ -17331,21 +17539,21 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
17331
17539
  }
17332
17540
 
17333
17541
  // plugin-src/client/channels/feishu/voice-settings.js
17334
- var React32 = __toESM(require("react"), 1);
17542
+ var React33 = __toESM(require("react"), 1);
17335
17543
 
17336
17544
  // plugin-src/client/channels/feishu/voice-editor.js
17337
- var React31 = __toESM(require("react"), 1);
17545
+ var React32 = __toESM(require("react"), 1);
17338
17546
  function VoiceEditor({ value = null, disabled = false, onSave }) {
17339
- const [enabled, setEnabled] = React31.useState(value != null);
17340
- const [secretRef, setSecretRef] = React31.useState(value?.secretRef ?? "DASHSCOPE_API_KEY");
17341
- const [asrModel, setAsrModel] = React31.useState(value?.asrModel ?? "qwen3-asr-flash");
17342
- const [ttsModel, setTtsModel] = React31.useState(value?.ttsModel ?? "qwen3-tts-flash");
17343
- const [ttsVoice, setTtsVoice] = React31.useState(value?.ttsVoice ?? "Momo");
17344
- const [saving, setSaving] = React31.useState(false);
17345
- const [error, setError] = React31.useState(null);
17346
- const titleId = React31.useId();
17547
+ const [enabled, setEnabled] = React32.useState(value != null);
17548
+ const [secretRef, setSecretRef] = React32.useState(value?.secretRef ?? "DASHSCOPE_API_KEY");
17549
+ const [asrModel, setAsrModel] = React32.useState(value?.asrModel ?? "qwen3-asr-flash");
17550
+ const [ttsModel, setTtsModel] = React32.useState(value?.ttsModel ?? "qwen3-tts-flash");
17551
+ const [ttsVoice, setTtsVoice] = React32.useState(value?.ttsVoice ?? "Momo");
17552
+ const [saving, setSaving] = React32.useState(false);
17553
+ const [error, setError] = React32.useState(null);
17554
+ const titleId = React32.useId();
17347
17555
  const helpId = `${titleId}-help`;
17348
- React31.useEffect(() => {
17556
+ React32.useEffect(() => {
17349
17557
  setEnabled(value != null);
17350
17558
  if (value) {
17351
17559
  setSecretRef(value.secretRef ?? "DASHSCOPE_API_KEY");
@@ -17459,20 +17667,20 @@ function VoiceEditor({ value = null, disabled = false, onSave }) {
17459
17667
 
17460
17668
  // plugin-src/client/channels/feishu/voice-settings.js
17461
17669
  function FeishuVoiceSettingsPage({ account, rpcCall }) {
17462
- const [voice, setVoice] = React32.useState(null);
17463
- const [phase, setPhase] = React32.useState("loading");
17464
- const [error, setError] = React32.useState(null);
17465
- const mounted = React32.useRef(true);
17466
- const invoke = React32.useCallback(async (endpoint, payload, signal) => {
17670
+ const [voice, setVoice] = React33.useState(null);
17671
+ const [phase, setPhase] = React33.useState("loading");
17672
+ const [error, setError] = React33.useState(null);
17673
+ const mounted = React33.useRef(true);
17674
+ const invoke = React33.useCallback(async (endpoint, payload, signal) => {
17467
17675
  if (typeof rpcCall !== "function") throw new Error("\u98DE\u4E66\u8BED\u97F3\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
17468
17676
  return unwrapRpcResult3(await rpcCall(endpoint, payload, signal));
17469
17677
  }, [rpcCall]);
17470
- const applySnapshot = React32.useCallback((value) => {
17678
+ const applySnapshot = React33.useCallback((value) => {
17471
17679
  const bot = normalizeBotsSnapshot(value).bots.find((entry) => entry.botId === account.botId);
17472
17680
  if (!bot) throw new Error("\u672A\u627E\u5230\u5F53\u524D\u98DE\u4E66\u673A\u5668\u4EBA\uFF0C\u8BF7\u8FD4\u56DE\u5217\u8868\u540E\u91CD\u8BD5\u3002");
17473
17681
  if (mounted.current) setVoice(bot.voice);
17474
17682
  }, [account.botId]);
17475
- const loadSettings = React32.useCallback(async (signal) => {
17683
+ const loadSettings = React33.useCallback(async (signal) => {
17476
17684
  setPhase("loading");
17477
17685
  setError(null);
17478
17686
  try {
@@ -17486,7 +17694,7 @@ function FeishuVoiceSettingsPage({ account, rpcCall }) {
17486
17694
  setPhase("error");
17487
17695
  }
17488
17696
  }, [applySnapshot, invoke]);
17489
- React32.useEffect(() => {
17697
+ React33.useEffect(() => {
17490
17698
  mounted.current = true;
17491
17699
  const controller = new AbortController();
17492
17700
  void loadSettings(controller.signal);
@@ -17525,7 +17733,7 @@ function FeishuVoiceSettingsPage({ account, rpcCall }) {
17525
17733
  }
17526
17734
 
17527
17735
  // plugin-src/client/channels/feishu/slash-panel-settings.js
17528
- var React33 = __toESM(require("react"), 1);
17736
+ var React34 = __toESM(require("react"), 1);
17529
17737
  var MANIFEST_BY_NAME = new Map(SLASH_COMMAND_MANIFEST.map((entry) => [entry.command, entry]));
17530
17738
  var ALL_COMMANDS = Object.freeze(SLASH_COMMAND_MANIFEST.map((entry) => entry.command));
17531
17739
  function PanelButton({ children, disabled = false, onClick, ...props }) {
@@ -17546,30 +17754,30 @@ function commandText(name2) {
17546
17754
  return `/${name2} \u2014 ${entry?.default ?? name2}`;
17547
17755
  }
17548
17756
  function FeishuSlashPanelSettingsPage({ account, rpcCall, onSaved }) {
17549
- const incoming = React33.useMemo(() => normalizeSlashPanelConfig(account.slashPanel), [account.botId, panelSignature(account.slashPanel)]);
17550
- const [mode, setMode] = React33.useState(incoming.mode);
17551
- const [order, setOrder] = React33.useState(() => [...incoming.order]);
17552
- const [pending, setPending] = React33.useState("");
17553
- const [dirty, setDirty] = React33.useState(false);
17554
- const [saving, setSaving] = React33.useState(false);
17555
- const [saved, setSaved] = React33.useState(false);
17556
- const [syncing, setSyncing] = React33.useState(false);
17557
- const [syncTargets, setSyncTargets] = React33.useState(null);
17558
- const [syncNotice, setSyncNotice] = React33.useState(null);
17559
- const [error, setError] = React33.useState(null);
17560
- const mounted = React33.useRef(true);
17561
- React33.useEffect(() => {
17757
+ const incoming = React34.useMemo(() => normalizeSlashPanelConfig(account.slashPanel), [account.botId, panelSignature(account.slashPanel)]);
17758
+ const [mode, setMode] = React34.useState(incoming.mode);
17759
+ const [order, setOrder] = React34.useState(() => [...incoming.order]);
17760
+ const [pending, setPending] = React34.useState("");
17761
+ const [dirty, setDirty] = React34.useState(false);
17762
+ const [saving, setSaving] = React34.useState(false);
17763
+ const [saved, setSaved] = React34.useState(false);
17764
+ const [syncing, setSyncing] = React34.useState(false);
17765
+ const [syncTargets, setSyncTargets] = React34.useState(null);
17766
+ const [syncNotice, setSyncNotice] = React34.useState(null);
17767
+ const [error, setError] = React34.useState(null);
17768
+ const mounted = React34.useRef(true);
17769
+ React34.useEffect(() => {
17562
17770
  mounted.current = true;
17563
17771
  return () => {
17564
17772
  mounted.current = false;
17565
17773
  };
17566
17774
  }, []);
17567
- React33.useEffect(() => {
17775
+ React34.useEffect(() => {
17568
17776
  if (dirty) return;
17569
17777
  setMode(incoming.mode);
17570
17778
  setOrder([...incoming.order]);
17571
17779
  }, [incoming.mode, incoming.order, dirty]);
17572
- const edit = React33.useCallback((update) => {
17780
+ const edit = React34.useCallback((update) => {
17573
17781
  setSaved(false);
17574
17782
  setDirty(true);
17575
17783
  update();
@@ -17706,7 +17914,7 @@ function FeishuSlashPanelSettingsPage({ account, rpcCall, onSaved }) {
17706
17914
  h2("option", { value: SLASH_PANEL_MODES.CUSTOM }, "\u81EA\u5B9A\u4E49\uFF08\u81EA\u5DF1\u6311\u6307\u4EE4\u548C\u987A\u5E8F\uFF09")
17707
17915
  ),
17708
17916
  mode === SLASH_PANEL_MODES.CUSTOM ? h2(
17709
- React33.Fragment,
17917
+ React34.Fragment,
17710
17918
  null,
17711
17919
  order.length === 0 ? h2("p", { className: "dim-feishuGroupHelp" }, "\u5F53\u524D\u6CA1\u6709\u9009\u62E9\u4EFB\u4F55\u6307\u4EE4\uFF0C\u4FDD\u5B58\u540E\u300C/\u300D\u9762\u677F\u4F1A\u53D8\u6210\u7A7A\u7684\u3002") : h2(
17712
17920
  "ul",
@@ -17843,6 +18051,7 @@ var DELIVERY_ENDPOINTS = Object.freeze({
17843
18051
  test: "target.test"
17844
18052
  });
17845
18053
  var BOT_SETTINGS_TABS = Object.freeze([
18054
+ Object.freeze({ id: "general", label: "\u901A\u7528" }),
17846
18055
  Object.freeze({ id: "delivery", label: "\u6295\u9012\u8BBE\u7F6E" }),
17847
18056
  Object.freeze({ id: "access", label: "\u8BBF\u95EE\u8BBE\u7F6E" })
17848
18057
  ]);
@@ -18062,13 +18271,13 @@ function TargetForm({
18062
18271
  }) {
18063
18272
  const editing = mode === "edit";
18064
18273
  const initialKind = initialValue?.kind && definition.fields[initialValue.kind] ? initialValue.kind : definition.kinds[0].value;
18065
- const [targetId, setTargetId] = React34.useState(initialValue?.targetId ?? "");
18066
- const [name2, setName] = React34.useState(initialValue?.name ?? "");
18067
- const [kind, setKind] = React34.useState(initialKind);
18068
- const [route, setRoute] = React34.useState(initialValue?.route ?? {});
18069
- const [error, setError] = React34.useState(null);
18070
- const [testing, setTesting] = React34.useState(false);
18071
- const [testState, setTestState] = React34.useState(null);
18274
+ const [targetId, setTargetId] = React35.useState(initialValue?.targetId ?? "");
18275
+ const [name2, setName] = React35.useState(initialValue?.name ?? "");
18276
+ const [kind, setKind] = React35.useState(initialKind);
18277
+ const [route, setRoute] = React35.useState(initialValue?.route ?? {});
18278
+ const [error, setError] = React35.useState(null);
18279
+ const [testing, setTesting] = React35.useState(false);
18280
+ const [testState, setTestState] = React35.useState(null);
18072
18281
  const currentTarget = () => {
18073
18282
  const normalizedRoute = Object.fromEntries(fieldsFor(definition, kind).map((field2) => {
18074
18283
  const raw = String(route[field2.key] ?? "").trim();
@@ -18285,7 +18494,7 @@ function TargetSuggestionPicker({
18285
18494
  suggestions.map((suggestion, index) => {
18286
18495
  const identity = routeIdentity(definition, suggestion);
18287
18496
  const added = configured.has(identity);
18288
- return React34.createElement("option", {
18497
+ return React35.createElement("option", {
18289
18498
  key: suggestion.id ?? suggestion.suggestionId ?? `${identity}:${index}`,
18290
18499
  value: String(index),
18291
18500
  disabled: added
@@ -18302,11 +18511,11 @@ function TargetSuggestionPicker({
18302
18511
  );
18303
18512
  }
18304
18513
  function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, onEdit }) {
18305
- const [action, setAction] = React34.useState(null);
18306
- const [testState, setTestState] = React34.useState(null);
18307
- const [syncFeedback, setSyncFeedback] = React34.useState(null);
18308
- const [copyState, setCopyState] = React34.useState(null);
18309
- const [confirmDelete, setConfirmDelete] = React34.useState(false);
18514
+ const [action, setAction] = React35.useState(null);
18515
+ const [testState, setTestState] = React35.useState(null);
18516
+ const [syncFeedback, setSyncFeedback] = React35.useState(null);
18517
+ const [copyState, setCopyState] = React35.useState(null);
18518
+ const [confirmDelete, setConfirmDelete] = React35.useState(false);
18310
18519
  const sessionSync = target.sessionSync ?? { enabled: false, state: "unavailable" };
18311
18520
  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";
18312
18521
  const testTarget = async () => {
@@ -18369,7 +18578,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
18369
18578
  h2(
18370
18579
  "div",
18371
18580
  { className: "dim-targetTitle" },
18372
- React34.createElement("strong", null, target.name || target.targetId),
18581
+ React35.createElement("strong", null, target.name || target.targetId),
18373
18582
  h2("span", null, kindLabel(definition, target.kind))
18374
18583
  ),
18375
18584
  h2("code", null, `targetId: ${target.targetId}`)
@@ -18455,30 +18664,30 @@ function DeliveryTargetSettingsPage({
18455
18664
  onBack
18456
18665
  }) {
18457
18666
  const definition = CHANNEL_DEFINITIONS[channel7];
18458
- const [activeTabId, setActiveTabId] = React34.useState(BOT_SETTINGS_TABS[0].id);
18459
- const [phase, setPhase] = React34.useState("loading");
18460
- const [targets, setTargets] = React34.useState([]);
18461
- const [suggestionPhase, setSuggestionPhase] = React34.useState("idle");
18462
- const [suggestions, setSuggestions] = React34.useState([]);
18463
- const [suggestionError, setSuggestionError] = React34.useState(null);
18464
- const [error, setError] = React34.useState(null);
18465
- const [editor, setEditor] = React34.useState(null);
18466
- const [saving, setSaving] = React34.useState(false);
18467
- const [botCopyState, setBotCopyState] = React34.useState(null);
18468
- const [accessPolicy, setAccessPolicy] = React34.useState(account.accessPolicy);
18469
- const [slashPanel, setSlashPanel] = React34.useState(account.slashPanel);
18470
- const mounted = React34.useRef(true);
18471
- React34.useEffect(() => {
18667
+ const [activeTabId, setActiveTabId] = React35.useState(BOT_SETTINGS_TABS[0].id);
18668
+ const [phase, setPhase] = React35.useState("loading");
18669
+ const [targets, setTargets] = React35.useState([]);
18670
+ const [suggestionPhase, setSuggestionPhase] = React35.useState("idle");
18671
+ const [suggestions, setSuggestions] = React35.useState([]);
18672
+ const [suggestionError, setSuggestionError] = React35.useState(null);
18673
+ const [error, setError] = React35.useState(null);
18674
+ const [editor, setEditor] = React35.useState(null);
18675
+ const [saving, setSaving] = React35.useState(false);
18676
+ const [botCopyState, setBotCopyState] = React35.useState(null);
18677
+ const [accessPolicy, setAccessPolicy] = React35.useState(account.accessPolicy);
18678
+ const [slashPanel, setSlashPanel] = React35.useState(account.slashPanel);
18679
+ const mounted = React35.useRef(true);
18680
+ React35.useEffect(() => {
18472
18681
  setAccessPolicy(account.accessPolicy);
18473
18682
  }, [account.botId, account.accessPolicy]);
18474
- React34.useEffect(() => {
18683
+ React35.useEffect(() => {
18475
18684
  setSlashPanel(account.slashPanel);
18476
18685
  }, [account.botId, account.slashPanel]);
18477
- const invoke = React34.useCallback(async (endpoint, payload = {}, signal) => {
18686
+ const invoke = React35.useCallback(async (endpoint, payload = {}, signal) => {
18478
18687
  if (typeof rpcCall !== "function") throw new Error("\u6295\u9012\u76EE\u6807\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
18479
18688
  return unwrapRpcResult15(await rpcCall(endpoint, payload, signal));
18480
18689
  }, [rpcCall]);
18481
- const loadTargets = React34.useCallback(async ({ signal, silent = false } = {}) => {
18690
+ const loadTargets = React35.useCallback(async ({ signal, silent = false } = {}) => {
18482
18691
  if (!silent) setPhase("loading");
18483
18692
  setError(null);
18484
18693
  try {
@@ -18492,7 +18701,7 @@ function DeliveryTargetSettingsPage({
18492
18701
  setPhase("error");
18493
18702
  }
18494
18703
  }, [account.botId, invoke]);
18495
- const loadSuggestions = React34.useCallback(async () => {
18704
+ const loadSuggestions = React35.useCallback(async () => {
18496
18705
  setSuggestionPhase("loading");
18497
18706
  setSuggestionError(null);
18498
18707
  try {
@@ -18506,7 +18715,7 @@ function DeliveryTargetSettingsPage({
18506
18715
  setSuggestionPhase("error");
18507
18716
  }
18508
18717
  }, [account.botId, definition, invoke]);
18509
- React34.useEffect(() => {
18718
+ React35.useEffect(() => {
18510
18719
  mounted.current = true;
18511
18720
  const controller = new AbortController();
18512
18721
  void loadTargets({ signal: controller.signal });
@@ -18601,7 +18810,7 @@ function DeliveryTargetSettingsPage({
18601
18810
  role: "tabpanel",
18602
18811
  "aria-labelledby": activeTabDomId
18603
18812
  },
18604
- activeTab.id === "access" ? h2(AccessPolicySettingsPage, {
18813
+ activeTab.id === "general" ? h2(BotGeneralSettingsPage, { key: `${channel7}:${account.botId}`, channel: channel7, account, rpcCall: accessRpcCall }) : activeTab.id === "access" ? h2(AccessPolicySettingsPage, {
18605
18814
  channel: channel7,
18606
18815
  account: { ...account, accessPolicy },
18607
18816
  rpcCall: accessRpcCall,
@@ -18618,7 +18827,7 @@ function DeliveryTargetSettingsPage({
18618
18827
  account,
18619
18828
  rpcCall: accessRpcCall
18620
18829
  }) : h2(
18621
- React34.Fragment,
18830
+ React35.Fragment,
18622
18831
  null,
18623
18832
  h2(
18624
18833
  "section",
@@ -18729,7 +18938,7 @@ function DeliveryTargetSettingsPage({
18729
18938
  }
18730
18939
 
18731
18940
  // plugin-src/client/global-settings.js
18732
- var React35 = __toESM(require("react"), 1);
18941
+ var React36 = __toESM(require("react"), 1);
18733
18942
 
18734
18943
  // src/channels/shared/inbound-ttl.mjs
18735
18944
  var DEFAULT_INBOUND_TTL_HOURS = 168;
@@ -18814,14 +19023,14 @@ function GlobalButton({ children, kind = "secondary", className = "", ...props }
18814
19023
  }, children);
18815
19024
  }
18816
19025
  function ImageInputSettings({ rpcCall }) {
18817
- const [values, setValues] = React35.useState(DEFAULT_IMAGE_INPUT_SETTINGS);
18818
- const [phase, setPhase] = React35.useState("loading");
18819
- const [error, setError] = React35.useState(null);
18820
- const [saved, setSaved] = React35.useState(false);
18821
- const mounted = React35.useRef(false);
18822
- const saving = React35.useRef(false);
18823
- const id6 = React35.useId();
18824
- const load = React35.useCallback(async (signal) => {
19026
+ const [values, setValues] = React36.useState(DEFAULT_IMAGE_INPUT_SETTINGS);
19027
+ const [phase, setPhase] = React36.useState("loading");
19028
+ const [error, setError] = React36.useState(null);
19029
+ const [saved, setSaved] = React36.useState(false);
19030
+ const mounted = React36.useRef(false);
19031
+ const saving = React36.useRef(false);
19032
+ const id6 = React36.useId();
19033
+ const load = React36.useCallback(async (signal) => {
18825
19034
  setPhase("loading");
18826
19035
  setError(null);
18827
19036
  try {
@@ -18837,7 +19046,7 @@ function ImageInputSettings({ rpcCall }) {
18837
19046
  setPhase("error");
18838
19047
  }
18839
19048
  }, [rpcCall]);
18840
- React35.useEffect(() => {
19049
+ React36.useEffect(() => {
18841
19050
  mounted.current = true;
18842
19051
  const controller = new AbortController();
18843
19052
  void load(controller.signal);
@@ -18944,29 +19153,29 @@ function ImageInputSettings({ rpcCall }) {
18944
19153
  );
18945
19154
  }
18946
19155
  function GlobalSettingsPanel({ rpcCall }) {
18947
- const [phase, setPhase] = React35.useState("loading");
18948
- const [loadError, setLoadError] = React35.useState(null);
18949
- const [ttlInput, setTtlInput] = React35.useState("");
18950
- const [savedTtl, setSavedTtl] = React35.useState(null);
18951
- const [ttlError, setTtlError] = React35.useState(false);
18952
- const [saveError, setSaveError] = React35.useState(null);
18953
- const [saveSucceeded, setSaveSucceeded] = React35.useState(false);
18954
- const [isSaving, setIsSaving] = React35.useState(false);
18955
- const [sweepConfirming, setSweepConfirming] = React35.useState(false);
18956
- const [sweeping, setSweeping] = React35.useState(false);
18957
- const ttlErrorId = React35.useId();
18958
- const ttlHintsId = React35.useId();
18959
- const sweepTriggerId = React35.useId();
18960
- const sweepConfirmId = React35.useId();
18961
- const sweepConfirmTextId = React35.useId();
18962
- const sweepConfirmButtonId = React35.useId();
18963
- const mounted = React35.useRef(true);
18964
- const saving = React35.useRef(false);
18965
- const invoke = React35.useCallback(async (endpoint, payload = {}, signal) => {
19156
+ const [phase, setPhase] = React36.useState("loading");
19157
+ const [loadError, setLoadError] = React36.useState(null);
19158
+ const [ttlInput, setTtlInput] = React36.useState("");
19159
+ const [savedTtl, setSavedTtl] = React36.useState(null);
19160
+ const [ttlError, setTtlError] = React36.useState(false);
19161
+ const [saveError, setSaveError] = React36.useState(null);
19162
+ const [saveSucceeded, setSaveSucceeded] = React36.useState(false);
19163
+ const [isSaving, setIsSaving] = React36.useState(false);
19164
+ const [sweepConfirming, setSweepConfirming] = React36.useState(false);
19165
+ const [sweeping, setSweeping] = React36.useState(false);
19166
+ const ttlErrorId = React36.useId();
19167
+ const ttlHintsId = React36.useId();
19168
+ const sweepTriggerId = React36.useId();
19169
+ const sweepConfirmId = React36.useId();
19170
+ const sweepConfirmTextId = React36.useId();
19171
+ const sweepConfirmButtonId = React36.useId();
19172
+ const mounted = React36.useRef(true);
19173
+ const saving = React36.useRef(false);
19174
+ const invoke = React36.useCallback(async (endpoint, payload = {}, signal) => {
18966
19175
  if (typeof rpcCall !== "function") throw new Error("\u901A\u7528\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
18967
19176
  return unwrapRpcResult16(await rpcCall(endpoint, payload, signal));
18968
19177
  }, [rpcCall]);
18969
- const loadSettings = React35.useCallback(async ({ signal } = {}) => {
19178
+ const loadSettings = React36.useCallback(async ({ signal } = {}) => {
18970
19179
  setPhase("loading");
18971
19180
  setLoadError(null);
18972
19181
  try {
@@ -18990,7 +19199,7 @@ function GlobalSettingsPanel({ rpcCall }) {
18990
19199
  setPhase("error");
18991
19200
  }
18992
19201
  }, [invoke]);
18993
- React35.useEffect(() => {
19202
+ React36.useEffect(() => {
18994
19203
  mounted.current = true;
18995
19204
  const controller = new AbortController();
18996
19205
  void loadSettings({ signal: controller.signal });
@@ -18999,7 +19208,7 @@ function GlobalSettingsPanel({ rpcCall }) {
18999
19208
  controller.abort();
19000
19209
  };
19001
19210
  }, [loadSettings]);
19002
- React35.useEffect(() => {
19211
+ React36.useEffect(() => {
19003
19212
  if (!sweepConfirming) return;
19004
19213
  globalThis.document?.getElementById(sweepConfirmButtonId)?.focus();
19005
19214
  }, [sweepConfirmButtonId, sweepConfirming]);
@@ -19940,6 +20149,25 @@ var CSS15 = String.raw`
19940
20149
  .dim-accessFeedback[data-tone="success"] { color: var(--dsw-alias-state-success-primary, #20a162); }
19941
20150
  .dim-accessFeedback[data-tone="error"] { color: var(--dsw-alias-state-error-primary, #d54941); }
19942
20151
  .dim-accessActions { display: flex; justify-content: flex-end; }
20152
+ .dim-botGeneralSettings { min-width: 0; }
20153
+ .dim-botGeneralList { min-width: 0; display: grid; }
20154
+ .dim-botGeneralRow { min-width: 0; display: grid; grid-template-columns: minmax(0, 1fr) max-content; align-items: center; gap: 24px; padding: 16px 0; border-bottom: 1px solid var(--dsw-alias-border-l2, #dfe1e5); }
20155
+ .dim-botGeneralRow:last-child { border-bottom: 0; }
20156
+ .dim-botGeneralPanelRow { border-bottom: 0; }
20157
+ .dim-botGeneralText { min-width: 0; display: grid; gap: 4px; }
20158
+ .dim-botGeneralTitle { color: var(--dsw-alias-label-primary, #1f2329); font-size: 14px; line-height: 22px; font-weight: 400; }
20159
+ .dim-botGeneralHelp { margin: 0; color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 12px; line-height: 18px; overflow-wrap: anywhere; }
20160
+ .dim-botGeneralPanelHelp { padding-bottom: 16px; border-bottom: 1px solid var(--dsw-alias-border-l2, #dfe1e5); }
20161
+ .dim-botGeneralControl { position: relative; min-width: 0; max-width: 100%; justify-self: end; color: var(--dsw-alias-label-primary, #1f2329); }
20162
+ .dim-botGeneralControl select { display: block; min-width: 104px; max-width: 100%; height: 36px; padding: 0 36px 0 14px; border: 0; border-radius: 10px; color: inherit; background: var(--dsw-alias-bg-module-platform, #f5f6f7); font: inherit; font-size: 14px; line-height: 22px; appearance: none; cursor: pointer; }
20163
+ .dim-botGeneralControl select:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover, #eef0f3); }
20164
+ .dim-botGeneralControl select:focus-visible { outline: 2px solid var(--dsw-alias-state-business-primary, #3370ff); outline-offset: 2px; }
20165
+ .dim-botGeneralControl select:disabled { opacity: .5; cursor: not-allowed; }
20166
+ .dim-botGeneralControl svg { position: absolute; top: 50%; right: 12px; transform: translateY(-50%); pointer-events: none; }
20167
+ .dim-botGeneralControl .dim-contextSwitch { display: block; }
20168
+ .dim-botGeneralControl .dim-contextSwitch:disabled { opacity: .5; cursor: not-allowed; }
20169
+ .dim-botGeneralControl .dim-contextSwitch:focus-visible { outline: 2px solid var(--dsw-alias-state-business-primary, #3370ff); outline-offset: 3px; }
20170
+ .dim-botGeneralActions { display: flex; align-items: center; justify-content: flex-end; flex-wrap: wrap; gap: 8px; padding-top: 16px; }
19943
20171
  .dim-generalSettingsPage { min-width: 0; display: grid; }
19944
20172
  .dim-generalSettingsHeader { min-width: 0; margin: 0 0 8px; }
19945
20173
  .dim-generalSettingsHeader h2 { margin: 0; color: var(--dsw-alias-label-primary, #1f2329); font-size: 18px; line-height: 25px; font-weight: 680; }
@@ -20334,7 +20562,7 @@ function installSessionChannelLogos(document2 = globalThis.document) {
20334
20562
  }
20335
20563
 
20336
20564
  // plugin-src/client/update-panel.js
20337
- var React36 = __toESM(require("react"), 1);
20565
+ var React37 = __toESM(require("react"), 1);
20338
20566
  var import_react_dom4 = require("react-dom");
20339
20567
  var import_valid = __toESM(require_valid(), 1);
20340
20568
  var import_rcompare = __toESM(require_rcompare(), 1);
@@ -20427,11 +20655,11 @@ function manualUpdateCommand(snapshot) {
20427
20655
  return `dsh plugin --profile ${profileArgument} add -w @xmanrui/dsh-im@${version}`;
20428
20656
  }
20429
20657
  function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
20430
- const [copyState, setCopyState] = React36.useState("idle");
20431
- const commandRef = React36.useRef(null);
20432
- const mounted = React36.useRef(false);
20433
- const copying = React36.useRef(false);
20434
- React36.useEffect(() => {
20658
+ const [copyState, setCopyState] = React37.useState("idle");
20659
+ const commandRef = React37.useRef(null);
20660
+ const mounted = React37.useRef(false);
20661
+ const copying = React37.useRef(false);
20662
+ React37.useEffect(() => {
20435
20663
  mounted.current = true;
20436
20664
  return () => {
20437
20665
  mounted.current = false;
@@ -20463,7 +20691,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
20463
20691
  { className: "dim-updateManual", "aria-label": "\u624B\u5DE5\u66F4\u65B0" },
20464
20692
  h2("h4", { className: "dim-updateManualHeading" }, "\u624B\u5DE5\u66F4\u65B0"),
20465
20693
  command ? h2(
20466
- React36.Fragment,
20694
+ React37.Fragment,
20467
20695
  null,
20468
20696
  h2("p", { className: "dim-updateManualHint" }, "\u81EA\u52A8\u66F4\u65B0\u5931\u8D25\u53EF\u4EE5\u4F7F\u7528\u547D\u4EE4\u66F4\u65B0\uFF1A"),
20469
20697
  h2(
@@ -20499,7 +20727,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
20499
20727
  "aria-hidden": "true",
20500
20728
  focusable: "false"
20501
20729
  }, copyState === "copied" ? h2("path", { d: "m4 10 4 4 8-8" }) : h2(
20502
- React36.Fragment,
20730
+ React37.Fragment,
20503
20731
  null,
20504
20732
  h2("rect", { x: 7, y: 7, width: 10, height: 11, rx: 1.5 }),
20505
20733
  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" })
@@ -20524,10 +20752,10 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
20524
20752
  );
20525
20753
  }
20526
20754
  function UpdateDialog({ children, onClose }) {
20527
- const dialogRef = React36.useRef(null);
20528
- const titleId = React36.useId();
20529
- const descriptionId = React36.useId();
20530
- React36.useEffect(() => {
20755
+ const dialogRef = React37.useRef(null);
20756
+ const titleId = React37.useId();
20757
+ const descriptionId = React37.useId();
20758
+ React37.useEffect(() => {
20531
20759
  const previous = globalThis.document?.activeElement;
20532
20760
  dialogRef.current?.focus?.();
20533
20761
  return () => {
@@ -20585,20 +20813,20 @@ function UpdateDialog({ children, onClose }) {
20585
20813
  return typeof document !== "undefined" && document.body ? (0, import_react_dom4.createPortal)(content, document.body) : content;
20586
20814
  }
20587
20815
  function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
20588
- const tooltipId = React36.useId();
20589
- const [snapshot, setSnapshot] = React36.useState(null);
20590
- const [action, setAction] = React36.useState("status");
20591
- const [error, setError] = React36.useState(null);
20592
- const [open, setOpen] = React36.useState(false);
20593
- const [uncertainInstall, setUncertainInstall] = React36.useState(false);
20594
- const mounted = React36.useRef(false);
20595
- const busy = React36.useRef(false);
20596
- const readController = React36.useRef(null);
20597
- const pollReadController = React36.useRef(null);
20598
- const installRequest = React36.useRef(null);
20599
- const onStatusRef = React36.useRef(onStatus);
20816
+ const tooltipId = React37.useId();
20817
+ const [snapshot, setSnapshot] = React37.useState(null);
20818
+ const [action, setAction] = React37.useState("status");
20819
+ const [error, setError] = React37.useState(null);
20820
+ const [open, setOpen] = React37.useState(false);
20821
+ const [uncertainInstall, setUncertainInstall] = React37.useState(false);
20822
+ const mounted = React37.useRef(false);
20823
+ const busy = React37.useRef(false);
20824
+ const readController = React37.useRef(null);
20825
+ const pollReadController = React37.useRef(null);
20826
+ const installRequest = React37.useRef(null);
20827
+ const onStatusRef = React37.useRef(onStatus);
20600
20828
  onStatusRef.current = onStatus;
20601
- const accept = React36.useCallback((next) => {
20829
+ const accept = React37.useCallback((next) => {
20602
20830
  setSnapshot(next);
20603
20831
  onStatusRef.current?.(next);
20604
20832
  }, []);
@@ -20607,7 +20835,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
20607
20835
  setUncertainInstall(false);
20608
20836
  accept(next);
20609
20837
  };
20610
- const invoke = React36.useCallback(async (endpoint, payload = {}, signal) => {
20838
+ const invoke = React37.useCallback(async (endpoint, payload = {}, signal) => {
20611
20839
  if (typeof rpcCall !== "function") {
20612
20840
  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");
20613
20841
  unavailable.code = "update-unavailable";
@@ -20615,7 +20843,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
20615
20843
  }
20616
20844
  return unwrapSnapshot(await rpcCall(endpoint, payload, signal));
20617
20845
  }, [rpcCall]);
20618
- React36.useEffect(() => {
20846
+ React37.useEffect(() => {
20619
20847
  mounted.current = true;
20620
20848
  busy.current = true;
20621
20849
  const controller = new AbortController();
@@ -20638,7 +20866,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
20638
20866
  const activeJob = ACTIVE_STATES4.has(snapshot?.job?.state);
20639
20867
  const restartRequired = snapshot?.job?.state === "restart-required" || snapshot?.blockedReason === "pending-restart";
20640
20868
  const shouldPoll = activeJob || uncertainInstall;
20641
- React36.useEffect(() => {
20869
+ React37.useEffect(() => {
20642
20870
  if (!shouldPoll) return void 0;
20643
20871
  let controller;
20644
20872
  const scheduler = createPollScheduler({
@@ -20739,7 +20967,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
20739
20967
  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";
20740
20968
  const buttonDescription = localizeText(buttonLabel) + (buttonLabel === "\u66F4\u65B0\u81F3" ? ` v${snapshot.latestVersion}` : "");
20741
20969
  return h2(
20742
- React36.Fragment,
20970
+ React37.Fragment,
20743
20971
  null,
20744
20972
  h2(
20745
20973
  "span",
@@ -20789,25 +21017,25 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
20789
21017
  h2("dt", null, "\u8FD0\u884C\u7248\u672C"),
20790
21018
  h2("dd", null, `v${snapshot?.runningVersion ?? clientVersion}`),
20791
21019
  snapshot?.installedVersion && snapshot.installedVersion !== snapshot.runningVersion ? h2(
20792
- React36.Fragment,
21020
+ React37.Fragment,
20793
21021
  null,
20794
21022
  h2("dt", null, "\u5DF2\u5B89\u88C5\u7248\u672C"),
20795
21023
  h2("dd", null, `v${snapshot.installedVersion}`)
20796
21024
  ) : null,
20797
21025
  targetVersion ? h2(
20798
- React36.Fragment,
21026
+ React37.Fragment,
20799
21027
  null,
20800
21028
  h2("dt", null, "\u76EE\u6807\u7248\u672C"),
20801
21029
  h2("dd", null, `v${targetVersion}`)
20802
21030
  ) : null,
20803
21031
  latestVersion ? h2(
20804
- React36.Fragment,
21032
+ React37.Fragment,
20805
21033
  null,
20806
21034
  h2("dt", null, "\u6700\u65B0\u7248\u672C"),
20807
21035
  h2("dd", null, `v${latestVersion}`)
20808
21036
  ) : null,
20809
21037
  historicalTargetVersion ? h2(
20810
- React36.Fragment,
21038
+ React37.Fragment,
20811
21039
  null,
20812
21040
  h2("dt", null, "\u4E0A\u6B21\u66F4\u65B0\u76EE\u6807"),
20813
21041
  h2("dd", null, `v${historicalTargetVersion}`)
@@ -20889,8 +21117,8 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
20889
21117
  }
20890
21118
 
20891
21119
  // plugin-src/client/panel-error-boundary.js
20892
- var React37 = __toESM(require("react"), 1);
20893
- var IMPanelErrorBoundary = class extends React37.Component {
21120
+ var React38 = __toESM(require("react"), 1);
21121
+ var IMPanelErrorBoundary = class extends React38.Component {
20894
21122
  state = { failed: false };
20895
21123
  static getDerivedStateFromError() {
20896
21124
  return { failed: true };
@@ -20910,9 +21138,9 @@ var IMPanelErrorBoundary = class extends React37.Component {
20910
21138
  };
20911
21139
 
20912
21140
  // plugin-src/client/plugin-page.js
20913
- var React38 = __toESM(require("react"), 1);
21141
+ var React39 = __toESM(require("react"), 1);
20914
21142
  var IM_MAIN_PANEL_ID = "xmanrui-dsh-im";
20915
- var h3 = React38.createElement;
21143
+ var h3 = React39.createElement;
20916
21144
  function OpenImAction({ subject, packageName, onOpen, t }) {
20917
21145
  if (subject?.kind !== "bundle" && subject?.kind !== "row") return null;
20918
21146
  if (subject.pkg?.name !== packageName) return null;
@@ -21143,28 +21371,28 @@ function IMSettingsTab({
21143
21371
  browserLocation = globalThis.location,
21144
21372
  navigateToRecoveryUrl = replacePageLocation
21145
21373
  }) {
21146
- const [selected, setSelected] = React39.useState(() => preferredSectionId === GLOBAL_SETTINGS_TAB_ID || CHANNELS.some((channel7) => channel7.id === preferredSectionId) ? preferredSectionId : "weixin");
21147
- const [loopbackRecovery, setLoopbackRecovery] = React39.useState(null);
21148
- const [runningVersion, setRunningVersion] = React39.useState(IM_PLUGIN_VERSION);
21149
- const [deliverySettings, setDeliverySettings] = React39.useState(null);
21374
+ const [selected, setSelected] = React40.useState(() => preferredSectionId === GLOBAL_SETTINGS_TAB_ID || CHANNELS.some((channel7) => channel7.id === preferredSectionId) ? preferredSectionId : "weixin");
21375
+ const [loopbackRecovery, setLoopbackRecovery] = React40.useState(null);
21376
+ const [runningVersion, setRunningVersion] = React40.useState(IM_PLUGIN_VERSION);
21377
+ const [deliverySettings, setDeliverySettings] = React40.useState(null);
21150
21378
  const emailEnabled = useEmailChannelEnabled(emailRpcCall);
21151
- const visibleChannels = React39.useMemo(
21379
+ const visibleChannels = React40.useMemo(
21152
21380
  () => CHANNELS.filter((channel7) => channel7.id !== "email" || emailEnabled),
21153
21381
  [emailEnabled]
21154
21382
  );
21155
- const githubTooltipId = React39.useId();
21156
- const generalSettingsTooltipId = React39.useId();
21383
+ const githubTooltipId = React40.useId();
21384
+ const generalSettingsTooltipId = React40.useId();
21157
21385
  const globalSettingsSelected = selected === GLOBAL_SETTINGS_TAB_ID;
21158
21386
  const active = visibleChannels.find((channel7) => channel7.id === selected) ?? visibleChannels[0];
21159
21387
  const activeTabId = globalSettingsSelected ? "dim-general-settings-trigger" : `dim-tab-${active.id}`;
21160
21388
  const activePanelId = globalSettingsSelected ? `dim-panel-${GLOBAL_SETTINGS_TAB_ID}` : `dim-panel-${active.id}`;
21161
- const reportLoopbackRecovery = React39.useCallback((recovery) => {
21389
+ const reportLoopbackRecovery = React40.useCallback((recovery) => {
21162
21390
  setLoopbackRecovery((current) => current?.url === recovery.url ? current : recovery);
21163
21391
  }, []);
21164
- const reportUpdateStatus = React39.useCallback((snapshot) => {
21392
+ const reportUpdateStatus = React40.useCallback((snapshot) => {
21165
21393
  setRunningVersion(snapshot.runningVersion);
21166
21394
  }, []);
21167
- const rpcCalls = React39.useMemo(() => createLoopbackAwareRpcCalls({
21395
+ const rpcCalls = React40.useMemo(() => createLoopbackAwareRpcCalls({
21168
21396
  dingtalkRpcCall,
21169
21397
  discordRpcCall,
21170
21398
  feishuRpcCall,
@@ -21206,7 +21434,7 @@ function IMSettingsTab({
21206
21434
  weixinRpcCall,
21207
21435
  whatsappRpcCall
21208
21436
  ]);
21209
- const botSettingsContext = React39.useMemo(() => Object.freeze({
21437
+ const botSettingsContext = React40.useMemo(() => Object.freeze({
21210
21438
  openBotSettings: setDeliverySettings
21211
21439
  }), []);
21212
21440
  return h2(
@@ -21430,7 +21658,7 @@ function apply(ctx) {
21430
21658
  };
21431
21659
  const localeSnapshot = () => ctx.locale.getLocale?.()?.active ?? "";
21432
21660
  function IMPanel({ preferredSectionId }) {
21433
- React39.useSyncExternalStore(subscribeLocale, localeSnapshot, localeSnapshot);
21661
+ React40.useSyncExternalStore(subscribeLocale, localeSnapshot, localeSnapshot);
21434
21662
  return h2(
21435
21663
  IMPanelErrorBoundary,
21436
21664
  null,