@xmanrui/dsh-im 4.36.0 → 4.37.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 (58) hide show
  1. package/README.en.md +14 -2
  2. package/README.md +13 -1
  3. package/lib/client.js +348 -195
  4. package/lib/index.js +314 -313
  5. package/package.json +2 -2
  6. package/plugin-src/client/bot-general-settings.js +83 -0
  7. package/plugin-src/client/channels/dingtalk/api.js +3 -1
  8. package/plugin-src/client/channels/feishu/api.js +3 -1
  9. package/plugin-src/client/channels/qq/api.js +3 -1
  10. package/plugin-src/client/channels/shared/token-api.js +3 -1
  11. package/plugin-src/client/channels/wecom/api.js +3 -1
  12. package/plugin-src/client/channels/wecom-app/api.js +3 -1
  13. package/plugin-src/client/channels/weixin/api.js +3 -1
  14. package/plugin-src/client/channels/whatsapp/api.js +3 -1
  15. package/plugin-src/client/connection-error.js +2 -1
  16. package/plugin-src/client/delivery-settings.js +5 -1
  17. package/plugin-src/client/i18n.js +13 -0
  18. package/plugin-src/host/channels/dingtalk/rpc.mjs +11 -0
  19. package/plugin-src/host/channels/email/rpc.mjs +1 -0
  20. package/plugin-src/host/channels/feishu/rpc.mjs +13 -0
  21. package/plugin-src/host/channels/imessage/rpc.mjs +1 -0
  22. package/plugin-src/host/channels/matrix/rpc.mjs +10 -0
  23. package/plugin-src/host/channels/qq/rpc.mjs +11 -0
  24. package/plugin-src/host/channels/shared/rpc.mjs +9 -0
  25. package/plugin-src/host/channels/slack/rpc.mjs +10 -0
  26. package/plugin-src/host/channels/wecom/rpc.mjs +11 -0
  27. package/plugin-src/host/channels/wecom-app/rpc.mjs +10 -0
  28. package/plugin-src/host/channels/weixin/rpc.mjs +11 -0
  29. package/plugin-src/host/channels/whatsapp/rpc.mjs +11 -0
  30. package/src/channels/dingtalk/dingtalk-bridge.mjs +31 -2
  31. package/src/channels/dingtalk/dingtalk-menu.mjs +1 -1
  32. package/src/channels/dingtalk/dingtalk-runtime.mjs +2 -1
  33. package/src/channels/discord/discord-runtime.mjs +3 -1
  34. package/src/channels/feishu/bridge.mjs +69 -5
  35. package/src/channels/feishu/feishu-cards.mjs +8 -4
  36. package/src/channels/feishu/slash-command-panel.mjs +1 -0
  37. package/src/channels/qq/qq-bridge.mjs +40 -2
  38. package/src/channels/qq/qq-menu.mjs +2 -2
  39. package/src/channels/shared/bot-workspace-store.mjs +69 -1
  40. package/src/channels/shared/busy-message-dispatcher.mjs +94 -0
  41. package/src/channels/shared/clear-command.mjs +85 -0
  42. package/src/channels/shared/command-catalog.mjs +3 -0
  43. package/src/channels/shared/command-permission.mjs +2 -0
  44. package/src/channels/shared/connection-error.mjs +1 -0
  45. package/src/channels/shared/control-command.mjs +20 -11
  46. package/src/channels/shared/diagnostic-details.mjs +7 -1
  47. package/src/channels/shared/harness-client.mjs +15 -8
  48. package/src/channels/shared/i18n-en/diagnostics.mjs +3 -0
  49. package/src/channels/shared/i18n-en/feishu.mjs +6 -4
  50. package/src/channels/shared/i18n-en/qq.mjs +2 -1
  51. package/src/channels/shared/i18n-en/shared-b.mjs +27 -0
  52. package/src/channels/shared/message-failure.mjs +1 -1
  53. package/src/channels/shared/message-mode.mjs +19 -0
  54. package/src/channels/shared/text-harness-bridge.mjs +48 -5
  55. package/src/channels/wecom/wecom-bridge.mjs +26 -2
  56. package/src/channels/wecom/wecom-cards.mjs +1 -1
  57. package/src/channels/wecom-app/wecom-app-bridge.mjs +26 -2
  58. 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.0",
598
+ version: "4.37.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
 
@@ -1002,6 +1008,9 @@ var diagnostics_default = Object.freeze({
1002
1008
  "\u6682\u672A\u8BC6\u522B\u5177\u4F53\u539F\u56E0\uFF0C\u8BF7\u590D\u5236\u8BCA\u65AD\u4FE1\u606F\uFF0C\u5E76\u67E5\u770B\u76F8\u540C\u53C2\u8003\u53F7\u7684 DSH \u65E5\u5FD7\u3002": "The underlying cause is unknown. Copy the diagnostics and find the matching reference in the DSH logs.",
1003
1009
  "\u591A\u4E2A\u539F\u56E0": "Multiple causes",
1004
1010
  "\u670D\u52A1\u57DF\u540D": "Service host",
1011
+ "RPC \u65B9\u6CD5": "RPC method",
1012
+ "\u8C03\u7528\u65B9\u5F0F": "Transport",
1013
+ "\u5BBF\u4E3B API\uFF08\u8FDB\u7A0B\u5185\uFF09": "Host API (in-process)",
1005
1014
  "\u8BF7\u6C42\u8017\u65F6\uFF08\u6BEB\u79D2\uFF09": "Request duration (ms)",
1006
1015
  "\u8D85\u65F6\u9608\u503C\uFF08\u6BEB\u79D2\uFF09": "Timeout (ms)",
1007
1016
  "Node \u7248\u672C": "Node version",
@@ -2165,6 +2174,19 @@ var EN = Object.freeze({
2165
2174
  "\u5C1A\u672A\u914D\u7F6E\u6295\u9012\u76EE\u6807": "No delivery targets yet",
2166
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.",
2167
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
+ "\u4EE5\u4E0B\u8BBE\u7F6E\u4EC5\u5F71\u54CD\u5F53\u524D\u673A\u5668\u4EBA\u3002": "These settings apply only to this bot.",
2181
+ "\u4EFB\u52A1\u8FD0\u884C\u65F6\u7684\u65B0\u6D88\u606F\u5904\u7406\u65B9\u5F0F": "New messages while a task is running",
2182
+ "\u6392\u961F\uFF08\u9ED8\u8BA4\uFF09": "Queue (default)",
2183
+ "\u63D2\u8BDD": "Steer",
2184
+ "\u5F53\u524D\u4EFB\u52A1\u7ED3\u675F\u540E\uFF0C\u518D\u5904\u7406\u65B0\u6D88\u606F\u3002\u53EF\u4F7F\u7528 /steer \u624B\u52A8\u63D2\u8BDD\u3002": "Process new messages after the current task finishes. Use /steer to send an explicit correction.",
2185
+ "\u5C06\u65B0\u7684\u7EAF\u6587\u5B57\u6D88\u606F\u4F5C\u4E3A\u8865\u5145\u6307\u4EE4\u52A0\u5165\u5F53\u524D\u4EFB\u52A1\uFF0CAgent \u5728\u4E0B\u4E00\u6B65\u8BFB\u53D6\u3002": "Add new plain-text messages to the running task. The Agent reads them at its next step.",
2186
+ "\u6CA1\u6709\u6B63\u5728\u8FD0\u884C\u7684\u4EFB\u52A1\u65F6\uFF0C\u6B63\u5E38\u5F00\u59CB\u65B0\u4EFB\u52A1\u3002\u56FE\u7247\u3001\u6587\u4EF6\u3001\u8BED\u97F3\u548C\u5E26\u5F15\u7528\u7684\u6D88\u606F\u6309\u539F\u6709\u65B9\u5F0F\u5904\u7406\u3002": "When idle, start a new task normally. Images, files, voice and quoted messages keep their existing handling.",
2187
+ "\u5DF2\u4FDD\u5B58\uFF0C\u5BF9\u65B0\u6536\u5230\u7684\u6D88\u606F\u751F\u6548\u3002": "Saved. Applies to newly received messages.",
2188
+ "\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.",
2189
+ "\u8BF7\u63D0\u4EA4\u6709\u6548\u7684\u6D88\u606F\u5904\u7406\u65B9\u5F0F\u3002": "Choose a valid message handling mode.",
2168
2190
  "\u901A\u7528\u8BBE\u7F6E": "General settings",
2169
2191
  "\u901A\u7528\u8BBE\u7F6E\u5206\u7C7B": "General settings categories",
2170
2192
  "\u9644\u4EF6": "Attachments",
@@ -2586,6 +2608,22 @@ var REASONS = /* @__PURE__ */ new Set([
2586
2608
  "read-only"
2587
2609
  ]);
2588
2610
  var RESOURCES = /* @__PURE__ */ new Set(["credential-store", "account-config", "account-state", "workspace-config", "workspace-directory"]);
2611
+ var RPC_METHODS = /* @__PURE__ */ new Set([
2612
+ "host.describe",
2613
+ "workspace.list",
2614
+ "workspace.create",
2615
+ "session.list",
2616
+ "session.create",
2617
+ "session.history",
2618
+ "session.prompt",
2619
+ "session.rename",
2620
+ "session.cancel",
2621
+ "session.models",
2622
+ "session.permissions",
2623
+ "session.selectModel",
2624
+ "llm.models"
2625
+ ]);
2626
+ var TRANSPORTS = /* @__PURE__ */ new Set(["host-api", "http"]);
2589
2627
  var CONFIG_FILES = /* @__PURE__ */ new Set(["config.json", "workspaces.json"]);
2590
2628
  var CONFIG_ISSUE_LABELS = Object.freeze({
2591
2629
  "expected-object": "\u5E94\u4E3A JSON \u5BF9\u8C61\u3002",
@@ -2607,7 +2645,7 @@ var CONFIG_FIELD = /^(?:\$|version|accounts(?:\[\d{1,10}\](?:\.(?:accountId|owne
2607
2645
  function normalizeDiagnosticDetails(value) {
2608
2646
  if (!value || typeof value !== "object" || Array.isArray(value)) return {};
2609
2647
  const result = {};
2610
- for (const [field2, allowed] of [["operation", OPERATIONS], ["stage", STAGES], ["reason", REASONS], ["resource", RESOURCES]]) {
2648
+ for (const [field2, allowed] of [["operation", OPERATIONS], ["stage", STAGES], ["reason", REASONS], ["resource", RESOURCES], ["method", RPC_METHODS], ["transport", TRANSPORTS]]) {
2611
2649
  if (allowed.has(value[field2])) result[field2] = value[field2];
2612
2650
  }
2613
2651
  if (DIAGNOSTIC_CHANNELS.includes(value.channel)) result.channel = value.channel;
@@ -2702,7 +2740,7 @@ function formatConnectionDiagnostic(value) {
2702
2740
  localizeText(error.message),
2703
2741
  details.hint ? localizeText(details.hint) : null,
2704
2742
  localizeText("\u9519\u8BEF\u7801") + ": " + error.code,
2705
- ...["channel", "operation", "stage", "reason", "reasons", "host", "durationMs", "timeoutMs", "nodeVersion", "dshVersion", "platform", "dependencies", "proxyConfigured", "truncated", "httpStatus", "providerCode", "resource", "file", "field", "issue", "referenceId", "occurredAt", "rollback", "pluginVersion"].filter((field2) => details[field2] !== void 0).map((field2) => `${field2}: ${typeof details[field2] === "object" ? JSON.stringify(details[field2]) : details[field2]}`)
2743
+ ...["channel", "operation", "stage", "method", "transport", "reason", "reasons", "host", "durationMs", "timeoutMs", "nodeVersion", "dshVersion", "platform", "dependencies", "proxyConfigured", "truncated", "httpStatus", "providerCode", "resource", "file", "field", "issue", "referenceId", "occurredAt", "rollback", "pluginVersion"].filter((field2) => details[field2] !== void 0).map((field2) => `${field2}: ${typeof details[field2] === "object" ? JSON.stringify(details[field2]) : details[field2]}`)
2706
2744
  ].filter(Boolean).join("\n");
2707
2745
  }
2708
2746
  function ConnectionError({ error: value, warning = false, showMessage = true }) {
@@ -2723,6 +2761,8 @@ function ConnectionError({ error: value, warning = false, showMessage = true })
2723
2761
  const fields = [
2724
2762
  ["\u9519\u8BEF\u7801", error.code],
2725
2763
  ["\u5931\u8D25\u9636\u6BB5", localizeText(STAGE_LABELS[details.stage] ?? details.stage ?? "")],
2764
+ ["RPC \u65B9\u6CD5", details.method],
2765
+ ["\u8C03\u7528\u65B9\u5F0F", details.transport === "host-api" ? localizeText("\u5BBF\u4E3B API\uFF08\u8FDB\u7A0B\u5185\uFF09") : details.transport === "http" ? "HTTP" : void 0],
2726
2766
  ["\u5E95\u5C42\u539F\u56E0", details.reason === "unknown" ? localizeText("\u6682\u672A\u8BC6\u522B") : details.reason],
2727
2767
  ["\u591A\u4E2A\u539F\u56E0", details.reasons?.join(", ")],
2728
2768
  ["\u670D\u52A1\u57DF\u540D", details.host],
@@ -3536,6 +3576,7 @@ var DINGTALK_ENDPOINTS = Object.freeze({
3536
3576
  setModel: SET_MODEL_ENDPOINT,
3537
3577
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
3538
3578
  setContextEnhancement: "bot.context-enhancement.set",
3579
+ setBusyMessageMode: "bot.message-mode.set",
3539
3580
  setAccessPolicy: "bot.access-policy.set",
3540
3581
  setAlias: "bot.alias.set"
3541
3582
  });
@@ -3684,6 +3725,7 @@ function normalizeBot(value) {
3684
3725
  workspace: optionalString(value.workspace, 4096) ?? "",
3685
3726
  model: normalizeModelSelection(value.model),
3686
3727
  agentPreset: normalizeAgentPresetId(value.agentPreset),
3728
+ busyMessageMode: normalizeBusyMessageMode(value.busyMessageMode),
3687
3729
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
3688
3730
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
3689
3731
  bot: {
@@ -6512,6 +6554,7 @@ var TOKEN_BOT_ENDPOINTS = Object.freeze({
6512
6554
  setModel: SET_MODEL_ENDPOINT,
6513
6555
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
6514
6556
  setContextEnhancement: "bot.context-enhancement.set",
6557
+ setBusyMessageMode: "bot.message-mode.set",
6515
6558
  setAccessPolicy: "bot.access-policy.set",
6516
6559
  setAlias: "bot.alias.set",
6517
6560
  setThinkingTraces: "bot.thinking-traces.set"
@@ -6543,6 +6586,7 @@ function createTokenChannelApi(channel7, connectionSummary, {
6543
6586
  workspace: text2(value.workspace, "", 4096),
6544
6587
  model: normalizeModelSelection(value.model),
6545
6588
  agentPreset: normalizeAgentPresetId(value.agentPreset),
6589
+ busyMessageMode: normalizeBusyMessageMode(value.busyMessageMode),
6546
6590
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
6547
6591
  // Absent from the backend means ON; only an explicit false opts out.
6548
6592
  thinkingTraces: value.thinkingTraces !== false,
@@ -7235,6 +7279,7 @@ var SLASH_COMMAND_MANIFEST = Object.freeze([
7235
7279
  { command: "help", icon: "promptword_outlined", default: "\u67E5\u770B\u5E2E\u52A9", en_us: "Show help" },
7236
7280
  { command: "status", icon: "ai-functions_outlined", default: "\u67E5\u770B\u673A\u5668\u4EBA\u72B6\u6001", en_us: "Show bot status" },
7237
7281
  { command: "compact", icon: "ai-block_outlined", default: "\u538B\u7F29\u5F53\u524D\u4F1A\u8BDD\u4E0A\u4E0B\u6587", en_us: "Compact the current session" },
7282
+ { command: "clear", icon: "clear_outlined", default: "\u6E05\u7A7A\u5F53\u524D\u4F1A\u8BDD\u4E0A\u4E0B\u6587", en_us: "Clear the current session context" },
7238
7283
  { command: "sessionlist", icon: "chat-ai_outlined", default: "\u5217\u51FA\u4F1A\u8BDD", en_us: "List sessions" },
7239
7284
  { command: "workspacelist", icon: "folder_outlined", default: "\u5217\u51FA\u5DE5\u4F5C\u533A", en_us: "List workspaces" },
7240
7285
  { command: "workspaces", icon: "folder_outlined", default: "\u5217\u51FA\u5DE5\u4F5C\u533A", en_us: "List workspaces" },
@@ -7315,6 +7360,7 @@ var FEISHU_ENDPOINTS = Object.freeze({
7315
7360
  setModel: SET_MODEL_ENDPOINT,
7316
7361
  setAgentPreset: "bot.preset.set",
7317
7362
  setContextEnhancement: "bot.context-enhancement.set",
7363
+ setBusyMessageMode: "bot.message-mode.set",
7318
7364
  setAccessPolicy: "bot.access-policy.set",
7319
7365
  setAlias: "bot.alias.set",
7320
7366
  setGroupResponseMode: "bot.group-response-mode.set",
@@ -7473,6 +7519,7 @@ function normalizeBotConnection(value, fallbackBotId) {
7473
7519
  workspace: optionalString2(value.workspace)?.slice(0, 4096) ?? "",
7474
7520
  model: normalizeModelSelection(value.model),
7475
7521
  agentPreset: normalizeAgentPresetId(value.agentPreset),
7522
+ busyMessageMode: normalizeBusyMessageMode(value.busyMessageMode),
7476
7523
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
7477
7524
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
7478
7525
  groupResponseMode: normalizeGroupResponseMode(value.groupResponseMode),
@@ -9726,6 +9773,7 @@ var QQ_ENDPOINTS = Object.freeze({
9726
9773
  setModel: SET_MODEL_ENDPOINT,
9727
9774
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
9728
9775
  setContextEnhancement: "bot.context-enhancement.set",
9776
+ setBusyMessageMode: "bot.message-mode.set",
9729
9777
  setAccessPolicy: "bot.access-policy.set",
9730
9778
  setAlias: "bot.alias.set"
9731
9779
  });
@@ -9795,6 +9843,7 @@ function normalizeBot3(value) {
9795
9843
  workspace: text3(value.workspace, "", 4096),
9796
9844
  model: normalizeModelSelection(value.model),
9797
9845
  agentPreset: normalizeAgentPresetId(value.agentPreset),
9846
+ busyMessageMode: normalizeBusyMessageMode(value.busyMessageMode),
9798
9847
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
9799
9848
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
9800
9849
  bot: {
@@ -11245,6 +11294,7 @@ var WECOM_ENDPOINTS = Object.freeze({
11245
11294
  setModel: SET_MODEL_ENDPOINT,
11246
11295
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
11247
11296
  setContextEnhancement: "bot.context-enhancement.set",
11297
+ setBusyMessageMode: "bot.message-mode.set",
11248
11298
  setAccessPolicy: "bot.access-policy.set",
11249
11299
  setAlias: "bot.alias.set"
11250
11300
  });
@@ -11320,6 +11370,7 @@ function normalizeBot4(value) {
11320
11370
  workspace: text4(value.workspace, "", 4096),
11321
11371
  model: normalizeModelSelection(value.model),
11322
11372
  agentPreset: normalizeAgentPresetId(value.agentPreset),
11373
+ busyMessageMode: normalizeBusyMessageMode(value.busyMessageMode),
11323
11374
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
11324
11375
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
11325
11376
  bot: {
@@ -12115,6 +12166,7 @@ var WECOM_APP_ENDPOINTS = Object.freeze({
12115
12166
  setModel: SET_MODEL_ENDPOINT,
12116
12167
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
12117
12168
  setContextEnhancement: "bot.context-enhancement.set",
12169
+ setBusyMessageMode: "bot.message-mode.set",
12118
12170
  setAccessPolicy: "bot.access-policy.set",
12119
12171
  setAlias: "bot.alias.set"
12120
12172
  });
@@ -12166,6 +12218,7 @@ function normalizeBot5(value) {
12166
12218
  workspace: text5(value.workspace, "", 4096),
12167
12219
  model: normalizeModelSelection(value.model),
12168
12220
  agentPreset: normalizeAgentPresetId(value.agentPreset),
12221
+ busyMessageMode: normalizeBusyMessageMode(value.busyMessageMode),
12169
12222
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
12170
12223
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
12171
12224
  bot: {
@@ -12978,6 +13031,7 @@ var WEIXIN_ENDPOINTS = Object.freeze({
12978
13031
  setModel: SET_MODEL_ENDPOINT,
12979
13032
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
12980
13033
  setContextEnhancement: "bot.context-enhancement.set",
13034
+ setBusyMessageMode: "bot.message-mode.set",
12981
13035
  setAccessPolicy: "bot.access-policy.set",
12982
13036
  setAlias: "bot.alias.set"
12983
13037
  });
@@ -13090,6 +13144,7 @@ function normalizeBot6(value) {
13090
13144
  workspace: string(value.workspace).slice(0, 4096),
13091
13145
  model: normalizeModelSelection(value.model),
13092
13146
  agentPreset: normalizeAgentPresetId(value.agentPreset),
13147
+ busyMessageMode: normalizeBusyMessageMode(value.busyMessageMode),
13093
13148
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
13094
13149
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
13095
13150
  bot: {
@@ -14157,7 +14212,8 @@ var WHATSAPP_ENDPOINTS = Object.freeze({
14157
14212
  setWorkspace: "bot.workspace.set",
14158
14213
  setModel: SET_MODEL_ENDPOINT,
14159
14214
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
14160
- setContextEnhancement: "bot.context-enhancement.set"
14215
+ setContextEnhancement: "bot.context-enhancement.set",
14216
+ setBusyMessageMode: "bot.message-mode.set"
14161
14217
  });
14162
14218
  var PROVISION_STATES5 = /* @__PURE__ */ new Set(["starting", "pending", "connecting", "connected", "failed", "cancelled"]);
14163
14219
  var BOT_STATES = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
@@ -14226,6 +14282,7 @@ function normalizeBot7(value) {
14226
14282
  workspace: text6(value.workspace, "", 4096),
14227
14283
  model: normalizeModelSelection(value.model),
14228
14284
  agentPreset: normalizeAgentPresetId(value.agentPreset),
14285
+ busyMessageMode: normalizeBusyMessageMode(value.busyMessageMode),
14229
14286
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
14230
14287
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
14231
14288
  bot: {
@@ -15191,7 +15248,7 @@ var PROVIDER_HINTS = {
15191
15248
  gmail: "\u9700\u8981\u5148\u5F00\u542F\u4E24\u6B65\u9A8C\u8BC1\uFF0C\u518D\u751F\u6210\u300C\u5E94\u7528\u4E13\u7528\u5BC6\u7801\u300D\u3002",
15192
15249
  custom: "\u8BF7\u586B\u5199\u90AE\u7BB1\u670D\u52A1\u5546\u63D0\u4F9B\u7684 IMAP \u4E0E SMTP \u670D\u52A1\u5668\u5730\u5740\u53CA\u7AEF\u53E3\u3002"
15193
15250
  };
15194
- var TRANSPORTS = [
15251
+ var TRANSPORTS2 = [
15195
15252
  {
15196
15253
  key: "imap-smtp",
15197
15254
  label: "IMAP / SMTP\uFF08\u4EFB\u610F\u90AE\u7BB1\uFF09",
@@ -15351,7 +15408,7 @@ function MailboxPanel({ busy, error, onSubmit, onCancel, rpcCall, endpoints }) {
15351
15408
  const [imapPort, setImapPort] = React26.useState("");
15352
15409
  const [smtpHost, setSmtpHost] = React26.useState("");
15353
15410
  const [smtpPort, setSmtpPort] = React26.useState("");
15354
- const transport = TRANSPORTS.find((entry) => entry.key === transportKey) ?? TRANSPORTS[0];
15411
+ const transport = TRANSPORTS2.find((entry) => entry.key === transportKey) ?? TRANSPORTS2[0];
15355
15412
  const custom = transport.needsProvider && provider === "custom";
15356
15413
  const isAgentMail = transport.key === "agent-mail";
15357
15414
  const maySubmit = Boolean(address.trim()) && (!transport.needsPassword || Boolean(password)) && (!isAgentMail || Boolean(tokens));
@@ -15397,7 +15454,7 @@ function MailboxPanel({ busy, error, onSubmit, onCancel, rpcCall, endpoints }) {
15397
15454
  value: transportKey,
15398
15455
  onChange: (event) => setTransportKey(event.target.value),
15399
15456
  disabled: busy
15400
- }, TRANSPORTS.map((entry) => h2("option", { key: entry.key, value: entry.key }, entry.label))),
15457
+ }, TRANSPORTS2.map((entry) => h2("option", { key: entry.key, value: entry.key }, entry.label))),
15401
15458
  h2("span", { className: "dim-emailHint" }, transport.hint)
15402
15459
  ),
15403
15460
  field(
@@ -16181,7 +16238,7 @@ function installInterfaceLanguageMirror(ctx, {
16181
16238
  }
16182
16239
 
16183
16240
  // plugin-src/client/delivery-settings.js
16184
- var React34 = __toESM(require("react"), 1);
16241
+ var React35 = __toESM(require("react"), 1);
16185
16242
 
16186
16243
  // plugin-src/client/access-policy-settings.js
16187
16244
  var React28 = __toESM(require("react"), 1);
@@ -16599,8 +16656,103 @@ function AccessPolicySettingsPage({ channel: channel7, account, rpcCall, onSaved
16599
16656
  );
16600
16657
  }
16601
16658
 
16602
- // plugin-src/client/bot-settings-tabs.js
16659
+ // plugin-src/client/bot-general-settings.js
16603
16660
  var React29 = __toESM(require("react"), 1);
16661
+ function modeFromResult(result, botId) {
16662
+ if (result?.ok !== true) throw new Error(result?.error?.message || "\u65E0\u6CD5\u8BFB\u53D6\u6D88\u606F\u5904\u7406\u8BBE\u7F6E\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
16663
+ const bot = result.value?.bots?.find((entry) => entry.botId === botId);
16664
+ if (!bot) throw new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");
16665
+ return normalizeBusyMessageMode(bot.busyMessageMode);
16666
+ }
16667
+ function BotGeneralSettingsPage({ account, rpcCall }) {
16668
+ const [mode, setMode] = React29.useState("queue");
16669
+ const [savedMode, setSavedMode] = React29.useState(null);
16670
+ const [busy, setBusy] = React29.useState(false);
16671
+ const [feedback, setFeedback] = React29.useState(null);
16672
+ const mounted = React29.useRef(false);
16673
+ const load = React29.useCallback(async () => {
16674
+ setBusy(true);
16675
+ setFeedback(null);
16676
+ try {
16677
+ const value = modeFromResult(await rpcCall("connection.status", {}), account.botId);
16678
+ if (!mounted.current) return;
16679
+ setMode(value);
16680
+ setSavedMode(value);
16681
+ } catch (error) {
16682
+ if (mounted.current) setFeedback({ error: true, text: error.message });
16683
+ } finally {
16684
+ if (mounted.current) setBusy(false);
16685
+ }
16686
+ }, [account.botId, rpcCall]);
16687
+ React29.useEffect(() => {
16688
+ mounted.current = true;
16689
+ void load();
16690
+ return () => {
16691
+ mounted.current = false;
16692
+ };
16693
+ }, [load]);
16694
+ const save = async () => {
16695
+ setBusy(true);
16696
+ setFeedback(null);
16697
+ try {
16698
+ const value = modeFromResult(await rpcCall(SET_MESSAGE_MODE_ENDPOINT, {
16699
+ botId: account.botId,
16700
+ busyMessageMode: mode
16701
+ }), account.botId);
16702
+ if (!mounted.current) return;
16703
+ setMode(value);
16704
+ setSavedMode(value);
16705
+ setFeedback({ text: "\u5DF2\u4FDD\u5B58\uFF0C\u5BF9\u65B0\u6536\u5230\u7684\u6D88\u606F\u751F\u6548\u3002" });
16706
+ } catch (error) {
16707
+ if (mounted.current) setFeedback({ error: true, text: error.message });
16708
+ } finally {
16709
+ if (mounted.current) setBusy(false);
16710
+ }
16711
+ };
16712
+ return h2(
16713
+ "section",
16714
+ { className: "dim-accessPage", "aria-label": "\u673A\u5668\u4EBA\u901A\u7528\u8BBE\u7F6E" },
16715
+ h2("h2", null, "\u901A\u7528"),
16716
+ h2("p", null, "\u4EE5\u4E0B\u8BBE\u7F6E\u4EC5\u5F71\u54CD\u5F53\u524D\u673A\u5668\u4EBA\u3002"),
16717
+ h2(
16718
+ "label",
16719
+ { className: "dim-accessField" },
16720
+ h2("span", null, "\u4EFB\u52A1\u8FD0\u884C\u65F6\u7684\u65B0\u6D88\u606F\u5904\u7406\u65B9\u5F0F"),
16721
+ h2(
16722
+ "select",
16723
+ {
16724
+ value: mode,
16725
+ disabled: busy || savedMode === null,
16726
+ "aria-label": "\u4EFB\u52A1\u8FD0\u884C\u65F6\u7684\u65B0\u6D88\u606F\u5904\u7406\u65B9\u5F0F",
16727
+ onChange: (event) => {
16728
+ setMode(event.target.value);
16729
+ setFeedback(null);
16730
+ }
16731
+ },
16732
+ h2("option", { value: "queue" }, "\u6392\u961F\uFF08\u9ED8\u8BA4\uFF09"),
16733
+ h2("option", { value: "steer" }, "\u63D2\u8BDD")
16734
+ )
16735
+ ),
16736
+ h2("p", null, mode === "queue" ? "\u5F53\u524D\u4EFB\u52A1\u7ED3\u675F\u540E\uFF0C\u518D\u5904\u7406\u65B0\u6D88\u606F\u3002\u53EF\u4F7F\u7528 /steer \u624B\u52A8\u63D2\u8BDD\u3002" : "\u5C06\u65B0\u7684\u7EAF\u6587\u5B57\u6D88\u606F\u4F5C\u4E3A\u8865\u5145\u6307\u4EE4\u52A0\u5165\u5F53\u524D\u4EFB\u52A1\uFF0CAgent \u5728\u4E0B\u4E00\u6B65\u8BFB\u53D6\u3002"),
16737
+ h2("p", null, "\u6CA1\u6709\u6B63\u5728\u8FD0\u884C\u7684\u4EFB\u52A1\u65F6\uFF0C\u6B63\u5E38\u5F00\u59CB\u65B0\u4EFB\u52A1\u3002\u56FE\u7247\u3001\u6587\u4EF6\u3001\u8BED\u97F3\u548C\u5E26\u5F15\u7528\u7684\u6D88\u606F\u6309\u539F\u6709\u65B9\u5F0F\u5904\u7406\u3002"),
16738
+ h2("button", {
16739
+ type: "button",
16740
+ className: "dim-deliveryButton",
16741
+ "data-kind": "primary",
16742
+ disabled: busy || savedMode === null || mode === savedMode,
16743
+ onClick: () => void save()
16744
+ }, busy ? "\u5904\u7406\u4E2D\u2026" : "\u4FDD\u5B58"),
16745
+ savedMode === null && !busy ? h2("button", {
16746
+ type: "button",
16747
+ className: "dim-deliveryButton",
16748
+ onClick: () => void load()
16749
+ }, "\u91CD\u65B0\u8BFB\u53D6") : null,
16750
+ feedback ? h2("p", { className: "dim-targetFeedback", role: feedback.error ? "alert" : "status" }, feedback.text) : null
16751
+ );
16752
+ }
16753
+
16754
+ // plugin-src/client/bot-settings-tabs.js
16755
+ var React30 = __toESM(require("react"), 1);
16604
16756
  function revealTab(strip, tab) {
16605
16757
  if (!strip || !tab) return;
16606
16758
  const viewport = strip.getBoundingClientRect();
@@ -16609,11 +16761,11 @@ function revealTab(strip, tab) {
16609
16761
  else if (bounds.right > viewport.right) strip.scrollLeft += bounds.right - viewport.right;
16610
16762
  }
16611
16763
  function BotSettingsTabs({ tabs, activeTabId, onChange }) {
16612
- const barRef = React29.useRef(null);
16613
- const stripRef = React29.useRef(null);
16614
- const listRef = React29.useRef(null);
16615
- const [scroll, setScroll] = React29.useState({ overflow: false, left: false, right: false });
16616
- const measure = React29.useCallback(() => {
16764
+ const barRef = React30.useRef(null);
16765
+ const stripRef = React30.useRef(null);
16766
+ const listRef = React30.useRef(null);
16767
+ const [scroll, setScroll] = React30.useState({ overflow: false, left: false, right: false });
16768
+ const measure = React30.useCallback(() => {
16617
16769
  const bar = barRef.current;
16618
16770
  const strip = stripRef.current;
16619
16771
  const list = listRef.current;
@@ -16626,7 +16778,7 @@ function BotSettingsTabs({ tabs, activeTabId, onChange }) {
16626
16778
  };
16627
16779
  setScroll((previous) => Object.keys(next).every((key) => next[key] === previous[key]) ? previous : next);
16628
16780
  }, []);
16629
- React29.useEffect(() => {
16781
+ React30.useEffect(() => {
16630
16782
  const strip = stripRef.current;
16631
16783
  if (!strip) return void 0;
16632
16784
  const refresh = () => {
@@ -16716,7 +16868,7 @@ function BotSettingsTabs({ tabs, activeTabId, onChange }) {
16716
16868
  }
16717
16869
 
16718
16870
  // plugin-src/client/channels/feishu/group-settings.js
16719
- var React30 = __toESM(require("react"), 1);
16871
+ var React31 = __toESM(require("react"), 1);
16720
16872
  var GROUP_MESSAGE_PERMISSION_OPERATION2 = FEISHU_REGISTRATION_OPERATIONS.GROUP_MESSAGE_PERMISSION;
16721
16873
  function SettingsButton({ children, kind = "secondary", className = "", ...props }) {
16722
16874
  return h2("button", {
@@ -16777,9 +16929,9 @@ function GroupResponseModeEditor({
16777
16929
  onAuthorize
16778
16930
  }) {
16779
16931
  const current = normalizeGroupResponseMode(value);
16780
- const [saving, setSaving] = React30.useState(false);
16781
- const [authorizing, setAuthorizing] = React30.useState(false);
16782
- const [error, setError] = React30.useState(null);
16932
+ const [saving, setSaving] = React31.useState(false);
16933
+ const [authorizing, setAuthorizing] = React31.useState(false);
16934
+ const [error, setError] = React31.useState(null);
16783
16935
  const change = async (event) => {
16784
16936
  const next = normalizeGroupResponseMode(event.target.value);
16785
16937
  if (next === current || saving || disabled) return;
@@ -16860,8 +17012,8 @@ function GroupResponseModeEditor({
16860
17012
  }
16861
17013
  function MentionTopicReplyEditor({ value = true, disabled = false, onSave }) {
16862
17014
  const current = value === true ? "on" : "off";
16863
- const [saving, setSaving] = React30.useState(false);
16864
- const [error, setError] = React30.useState(null);
17015
+ const [saving, setSaving] = React31.useState(false);
17016
+ const [error, setError] = React31.useState(null);
16865
17017
  const change = async (event) => {
16866
17018
  const next = event.target.value === "on";
16867
17019
  if ((next ? "on" : "off") === current || saving || disabled) return;
@@ -17048,14 +17200,14 @@ function PermissionFlow({ provision, now, busy, botName, onRetry, onCancel, onCl
17048
17200
  );
17049
17201
  }
17050
17202
  function FeishuGroupSettingsPage({ account, rpcCall }) {
17051
- const [settings, setSettings] = React30.useState(() => groupSettingsFrom(account));
17052
- const [refreshing, setRefreshing] = React30.useState(false);
17053
- const [refreshError, setRefreshError] = React30.useState(null);
17054
- const [provision, setProvision] = React30.useState(null);
17055
- const [provisionBusy, setProvisionBusy] = React30.useState(false);
17056
- const [now, setNow] = React30.useState(() => Date.now());
17057
- const mounted = React30.useRef(true);
17058
- React30.useEffect(() => {
17203
+ const [settings, setSettings] = React31.useState(() => groupSettingsFrom(account));
17204
+ const [refreshing, setRefreshing] = React31.useState(false);
17205
+ const [refreshError, setRefreshError] = React31.useState(null);
17206
+ const [provision, setProvision] = React31.useState(null);
17207
+ const [provisionBusy, setProvisionBusy] = React31.useState(false);
17208
+ const [now, setNow] = React31.useState(() => Date.now());
17209
+ const mounted = React31.useRef(true);
17210
+ React31.useEffect(() => {
17059
17211
  setSettings(groupSettingsFrom(account));
17060
17212
  }, [
17061
17213
  account.botId,
@@ -17063,22 +17215,22 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
17063
17215
  account.mentionTopicReply,
17064
17216
  account.groupMessagePermissionGranted
17065
17217
  ]);
17066
- React30.useEffect(() => {
17218
+ React31.useEffect(() => {
17067
17219
  mounted.current = true;
17068
17220
  return () => {
17069
17221
  mounted.current = false;
17070
17222
  };
17071
17223
  }, []);
17072
- const invoke = React30.useCallback(async (endpoint, payload = {}, signal) => {
17224
+ const invoke = React31.useCallback(async (endpoint, payload = {}, signal) => {
17073
17225
  if (typeof rpcCall !== "function") throw new Error("\u98DE\u4E66\u7FA4\u804A\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
17074
17226
  return unwrapRpcResult3(await rpcCall(endpoint, payload, signal));
17075
17227
  }, [rpcCall]);
17076
- const applySnapshot = React30.useCallback((value) => {
17228
+ const applySnapshot = React31.useCallback((value) => {
17077
17229
  const result = targetBotFromSnapshot(value, account.botId);
17078
17230
  if (mounted.current) setSettings(groupSettingsFrom(result.bot));
17079
17231
  return result;
17080
17232
  }, [account.botId]);
17081
- const loadSettings = React30.useCallback(async ({ signal, restoreProvisioning = false } = {}) => {
17233
+ const loadSettings = React31.useCallback(async ({ signal, restoreProvisioning = false } = {}) => {
17082
17234
  setRefreshing(true);
17083
17235
  setRefreshError(null);
17084
17236
  try {
@@ -17107,16 +17259,16 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
17107
17259
  if (!signal?.aborted && mounted.current) setRefreshing(false);
17108
17260
  }
17109
17261
  }, [account.botId, applySnapshot, invoke]);
17110
- React30.useEffect(() => {
17262
+ React31.useEffect(() => {
17111
17263
  const controller = new AbortController();
17112
17264
  void loadSettings({ signal: controller.signal, restoreProvisioning: true });
17113
17265
  return () => controller.abort();
17114
17266
  }, [loadSettings]);
17115
- const saveSetting = React30.useCallback(async (endpoint, payload) => {
17267
+ const saveSetting = React31.useCallback(async (endpoint, payload) => {
17116
17268
  const value = await invoke(endpoint, { botId: account.botId, ...payload });
17117
17269
  applySnapshot(value);
17118
17270
  }, [account.botId, applySnapshot, invoke]);
17119
- const startAuthorization = React30.useCallback(async ({ replace = false } = {}) => {
17271
+ const startAuthorization = React31.useCallback(async ({ replace = false } = {}) => {
17120
17272
  if (provisionBusy) return;
17121
17273
  const previousAttemptId = provision?.attemptId;
17122
17274
  setProvisionBusy(true);
@@ -17157,13 +17309,13 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
17157
17309
  if (mounted.current) setProvisionBusy(false);
17158
17310
  }
17159
17311
  }, [account.botId, invoke, provision?.attemptId, provisionBusy]);
17160
- const finishAuthorization = React30.useCallback(async (signal) => {
17312
+ const finishAuthorization = React31.useCallback(async (signal) => {
17161
17313
  const bot = await loadSettings({ signal, restoreProvisioning: false });
17162
17314
  if (signal?.aborted || !mounted.current) return;
17163
17315
  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");
17164
17316
  setProvision(null);
17165
17317
  }, [loadSettings]);
17166
- React30.useEffect(() => {
17318
+ React31.useEffect(() => {
17167
17319
  if (!provision?.attemptId || !["qr", "connecting"].includes(provision.phase) || provision.expired) return void 0;
17168
17320
  const timerHost = globalThis.window ?? globalThis;
17169
17321
  const controller = new AbortController();
@@ -17207,7 +17359,7 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
17207
17359
  timerHost.clearTimeout(timer);
17208
17360
  };
17209
17361
  }, [account.botId, finishAuthorization, invoke, provision]);
17210
- React30.useEffect(() => {
17362
+ React31.useEffect(() => {
17211
17363
  if (!provision?.attemptId || provision.phase !== "qr" || provision.expired) return void 0;
17212
17364
  const timerHost = globalThis.window ?? globalThis;
17213
17365
  const tick = () => {
@@ -17221,7 +17373,7 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
17221
17373
  const timer = timerHost.setInterval(tick, 1e3);
17222
17374
  return () => timerHost.clearInterval(timer);
17223
17375
  }, [provision?.attemptId, provision?.expired, provision?.expiresAt, provision?.phase]);
17224
- const cancelAuthorization = React30.useCallback(async () => {
17376
+ const cancelAuthorization = React31.useCallback(async () => {
17225
17377
  if (!provision?.attemptId || provisionBusy) {
17226
17378
  setProvision(null);
17227
17379
  return;
@@ -17310,21 +17462,21 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
17310
17462
  }
17311
17463
 
17312
17464
  // plugin-src/client/channels/feishu/voice-settings.js
17313
- var React32 = __toESM(require("react"), 1);
17465
+ var React33 = __toESM(require("react"), 1);
17314
17466
 
17315
17467
  // plugin-src/client/channels/feishu/voice-editor.js
17316
- var React31 = __toESM(require("react"), 1);
17468
+ var React32 = __toESM(require("react"), 1);
17317
17469
  function VoiceEditor({ value = null, disabled = false, onSave }) {
17318
- const [enabled, setEnabled] = React31.useState(value != null);
17319
- const [secretRef, setSecretRef] = React31.useState(value?.secretRef ?? "DASHSCOPE_API_KEY");
17320
- const [asrModel, setAsrModel] = React31.useState(value?.asrModel ?? "qwen3-asr-flash");
17321
- const [ttsModel, setTtsModel] = React31.useState(value?.ttsModel ?? "qwen3-tts-flash");
17322
- const [ttsVoice, setTtsVoice] = React31.useState(value?.ttsVoice ?? "Momo");
17323
- const [saving, setSaving] = React31.useState(false);
17324
- const [error, setError] = React31.useState(null);
17325
- const titleId = React31.useId();
17470
+ const [enabled, setEnabled] = React32.useState(value != null);
17471
+ const [secretRef, setSecretRef] = React32.useState(value?.secretRef ?? "DASHSCOPE_API_KEY");
17472
+ const [asrModel, setAsrModel] = React32.useState(value?.asrModel ?? "qwen3-asr-flash");
17473
+ const [ttsModel, setTtsModel] = React32.useState(value?.ttsModel ?? "qwen3-tts-flash");
17474
+ const [ttsVoice, setTtsVoice] = React32.useState(value?.ttsVoice ?? "Momo");
17475
+ const [saving, setSaving] = React32.useState(false);
17476
+ const [error, setError] = React32.useState(null);
17477
+ const titleId = React32.useId();
17326
17478
  const helpId = `${titleId}-help`;
17327
- React31.useEffect(() => {
17479
+ React32.useEffect(() => {
17328
17480
  setEnabled(value != null);
17329
17481
  if (value) {
17330
17482
  setSecretRef(value.secretRef ?? "DASHSCOPE_API_KEY");
@@ -17438,20 +17590,20 @@ function VoiceEditor({ value = null, disabled = false, onSave }) {
17438
17590
 
17439
17591
  // plugin-src/client/channels/feishu/voice-settings.js
17440
17592
  function FeishuVoiceSettingsPage({ account, rpcCall }) {
17441
- const [voice, setVoice] = React32.useState(null);
17442
- const [phase, setPhase] = React32.useState("loading");
17443
- const [error, setError] = React32.useState(null);
17444
- const mounted = React32.useRef(true);
17445
- const invoke = React32.useCallback(async (endpoint, payload, signal) => {
17593
+ const [voice, setVoice] = React33.useState(null);
17594
+ const [phase, setPhase] = React33.useState("loading");
17595
+ const [error, setError] = React33.useState(null);
17596
+ const mounted = React33.useRef(true);
17597
+ const invoke = React33.useCallback(async (endpoint, payload, signal) => {
17446
17598
  if (typeof rpcCall !== "function") throw new Error("\u98DE\u4E66\u8BED\u97F3\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
17447
17599
  return unwrapRpcResult3(await rpcCall(endpoint, payload, signal));
17448
17600
  }, [rpcCall]);
17449
- const applySnapshot = React32.useCallback((value) => {
17601
+ const applySnapshot = React33.useCallback((value) => {
17450
17602
  const bot = normalizeBotsSnapshot(value).bots.find((entry) => entry.botId === account.botId);
17451
17603
  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");
17452
17604
  if (mounted.current) setVoice(bot.voice);
17453
17605
  }, [account.botId]);
17454
- const loadSettings = React32.useCallback(async (signal) => {
17606
+ const loadSettings = React33.useCallback(async (signal) => {
17455
17607
  setPhase("loading");
17456
17608
  setError(null);
17457
17609
  try {
@@ -17465,7 +17617,7 @@ function FeishuVoiceSettingsPage({ account, rpcCall }) {
17465
17617
  setPhase("error");
17466
17618
  }
17467
17619
  }, [applySnapshot, invoke]);
17468
- React32.useEffect(() => {
17620
+ React33.useEffect(() => {
17469
17621
  mounted.current = true;
17470
17622
  const controller = new AbortController();
17471
17623
  void loadSettings(controller.signal);
@@ -17504,7 +17656,7 @@ function FeishuVoiceSettingsPage({ account, rpcCall }) {
17504
17656
  }
17505
17657
 
17506
17658
  // plugin-src/client/channels/feishu/slash-panel-settings.js
17507
- var React33 = __toESM(require("react"), 1);
17659
+ var React34 = __toESM(require("react"), 1);
17508
17660
  var MANIFEST_BY_NAME = new Map(SLASH_COMMAND_MANIFEST.map((entry) => [entry.command, entry]));
17509
17661
  var ALL_COMMANDS = Object.freeze(SLASH_COMMAND_MANIFEST.map((entry) => entry.command));
17510
17662
  function PanelButton({ children, disabled = false, onClick, ...props }) {
@@ -17525,30 +17677,30 @@ function commandText(name2) {
17525
17677
  return `/${name2} \u2014 ${entry?.default ?? name2}`;
17526
17678
  }
17527
17679
  function FeishuSlashPanelSettingsPage({ account, rpcCall, onSaved }) {
17528
- const incoming = React33.useMemo(() => normalizeSlashPanelConfig(account.slashPanel), [account.botId, panelSignature(account.slashPanel)]);
17529
- const [mode, setMode] = React33.useState(incoming.mode);
17530
- const [order, setOrder] = React33.useState(() => [...incoming.order]);
17531
- const [pending, setPending] = React33.useState("");
17532
- const [dirty, setDirty] = React33.useState(false);
17533
- const [saving, setSaving] = React33.useState(false);
17534
- const [saved, setSaved] = React33.useState(false);
17535
- const [syncing, setSyncing] = React33.useState(false);
17536
- const [syncTargets, setSyncTargets] = React33.useState(null);
17537
- const [syncNotice, setSyncNotice] = React33.useState(null);
17538
- const [error, setError] = React33.useState(null);
17539
- const mounted = React33.useRef(true);
17540
- React33.useEffect(() => {
17680
+ const incoming = React34.useMemo(() => normalizeSlashPanelConfig(account.slashPanel), [account.botId, panelSignature(account.slashPanel)]);
17681
+ const [mode, setMode] = React34.useState(incoming.mode);
17682
+ const [order, setOrder] = React34.useState(() => [...incoming.order]);
17683
+ const [pending, setPending] = React34.useState("");
17684
+ const [dirty, setDirty] = React34.useState(false);
17685
+ const [saving, setSaving] = React34.useState(false);
17686
+ const [saved, setSaved] = React34.useState(false);
17687
+ const [syncing, setSyncing] = React34.useState(false);
17688
+ const [syncTargets, setSyncTargets] = React34.useState(null);
17689
+ const [syncNotice, setSyncNotice] = React34.useState(null);
17690
+ const [error, setError] = React34.useState(null);
17691
+ const mounted = React34.useRef(true);
17692
+ React34.useEffect(() => {
17541
17693
  mounted.current = true;
17542
17694
  return () => {
17543
17695
  mounted.current = false;
17544
17696
  };
17545
17697
  }, []);
17546
- React33.useEffect(() => {
17698
+ React34.useEffect(() => {
17547
17699
  if (dirty) return;
17548
17700
  setMode(incoming.mode);
17549
17701
  setOrder([...incoming.order]);
17550
17702
  }, [incoming.mode, incoming.order, dirty]);
17551
- const edit = React33.useCallback((update) => {
17703
+ const edit = React34.useCallback((update) => {
17552
17704
  setSaved(false);
17553
17705
  setDirty(true);
17554
17706
  update();
@@ -17685,7 +17837,7 @@ function FeishuSlashPanelSettingsPage({ account, rpcCall, onSaved }) {
17685
17837
  h2("option", { value: SLASH_PANEL_MODES.CUSTOM }, "\u81EA\u5B9A\u4E49\uFF08\u81EA\u5DF1\u6311\u6307\u4EE4\u548C\u987A\u5E8F\uFF09")
17686
17838
  ),
17687
17839
  mode === SLASH_PANEL_MODES.CUSTOM ? h2(
17688
- React33.Fragment,
17840
+ React34.Fragment,
17689
17841
  null,
17690
17842
  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(
17691
17843
  "ul",
@@ -17823,7 +17975,8 @@ var DELIVERY_ENDPOINTS = Object.freeze({
17823
17975
  });
17824
17976
  var BOT_SETTINGS_TABS = Object.freeze([
17825
17977
  Object.freeze({ id: "delivery", label: "\u6295\u9012\u8BBE\u7F6E" }),
17826
- Object.freeze({ id: "access", label: "\u8BBF\u95EE\u8BBE\u7F6E" })
17978
+ Object.freeze({ id: "access", label: "\u8BBF\u95EE\u8BBE\u7F6E" }),
17979
+ Object.freeze({ id: "general", label: "\u901A\u7528" })
17827
17980
  ]);
17828
17981
  var FEISHU_BOT_SETTINGS_TABS = Object.freeze([
17829
17982
  ...BOT_SETTINGS_TABS,
@@ -18041,13 +18194,13 @@ function TargetForm({
18041
18194
  }) {
18042
18195
  const editing = mode === "edit";
18043
18196
  const initialKind = initialValue?.kind && definition.fields[initialValue.kind] ? initialValue.kind : definition.kinds[0].value;
18044
- const [targetId, setTargetId] = React34.useState(initialValue?.targetId ?? "");
18045
- const [name2, setName] = React34.useState(initialValue?.name ?? "");
18046
- const [kind, setKind] = React34.useState(initialKind);
18047
- const [route, setRoute] = React34.useState(initialValue?.route ?? {});
18048
- const [error, setError] = React34.useState(null);
18049
- const [testing, setTesting] = React34.useState(false);
18050
- const [testState, setTestState] = React34.useState(null);
18197
+ const [targetId, setTargetId] = React35.useState(initialValue?.targetId ?? "");
18198
+ const [name2, setName] = React35.useState(initialValue?.name ?? "");
18199
+ const [kind, setKind] = React35.useState(initialKind);
18200
+ const [route, setRoute] = React35.useState(initialValue?.route ?? {});
18201
+ const [error, setError] = React35.useState(null);
18202
+ const [testing, setTesting] = React35.useState(false);
18203
+ const [testState, setTestState] = React35.useState(null);
18051
18204
  const currentTarget = () => {
18052
18205
  const normalizedRoute = Object.fromEntries(fieldsFor(definition, kind).map((field2) => {
18053
18206
  const raw = String(route[field2.key] ?? "").trim();
@@ -18264,7 +18417,7 @@ function TargetSuggestionPicker({
18264
18417
  suggestions.map((suggestion, index) => {
18265
18418
  const identity = routeIdentity(definition, suggestion);
18266
18419
  const added = configured.has(identity);
18267
- return React34.createElement("option", {
18420
+ return React35.createElement("option", {
18268
18421
  key: suggestion.id ?? suggestion.suggestionId ?? `${identity}:${index}`,
18269
18422
  value: String(index),
18270
18423
  disabled: added
@@ -18281,11 +18434,11 @@ function TargetSuggestionPicker({
18281
18434
  );
18282
18435
  }
18283
18436
  function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, onEdit }) {
18284
- const [action, setAction] = React34.useState(null);
18285
- const [testState, setTestState] = React34.useState(null);
18286
- const [syncFeedback, setSyncFeedback] = React34.useState(null);
18287
- const [copyState, setCopyState] = React34.useState(null);
18288
- const [confirmDelete, setConfirmDelete] = React34.useState(false);
18437
+ const [action, setAction] = React35.useState(null);
18438
+ const [testState, setTestState] = React35.useState(null);
18439
+ const [syncFeedback, setSyncFeedback] = React35.useState(null);
18440
+ const [copyState, setCopyState] = React35.useState(null);
18441
+ const [confirmDelete, setConfirmDelete] = React35.useState(false);
18289
18442
  const sessionSync = target.sessionSync ?? { enabled: false, state: "unavailable" };
18290
18443
  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";
18291
18444
  const testTarget = async () => {
@@ -18348,7 +18501,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
18348
18501
  h2(
18349
18502
  "div",
18350
18503
  { className: "dim-targetTitle" },
18351
- React34.createElement("strong", null, target.name || target.targetId),
18504
+ React35.createElement("strong", null, target.name || target.targetId),
18352
18505
  h2("span", null, kindLabel(definition, target.kind))
18353
18506
  ),
18354
18507
  h2("code", null, `targetId: ${target.targetId}`)
@@ -18434,30 +18587,30 @@ function DeliveryTargetSettingsPage({
18434
18587
  onBack
18435
18588
  }) {
18436
18589
  const definition = CHANNEL_DEFINITIONS[channel7];
18437
- const [activeTabId, setActiveTabId] = React34.useState(BOT_SETTINGS_TABS[0].id);
18438
- const [phase, setPhase] = React34.useState("loading");
18439
- const [targets, setTargets] = React34.useState([]);
18440
- const [suggestionPhase, setSuggestionPhase] = React34.useState("idle");
18441
- const [suggestions, setSuggestions] = React34.useState([]);
18442
- const [suggestionError, setSuggestionError] = React34.useState(null);
18443
- const [error, setError] = React34.useState(null);
18444
- const [editor, setEditor] = React34.useState(null);
18445
- const [saving, setSaving] = React34.useState(false);
18446
- const [botCopyState, setBotCopyState] = React34.useState(null);
18447
- const [accessPolicy, setAccessPolicy] = React34.useState(account.accessPolicy);
18448
- const [slashPanel, setSlashPanel] = React34.useState(account.slashPanel);
18449
- const mounted = React34.useRef(true);
18450
- React34.useEffect(() => {
18590
+ const [activeTabId, setActiveTabId] = React35.useState(BOT_SETTINGS_TABS[0].id);
18591
+ const [phase, setPhase] = React35.useState("loading");
18592
+ const [targets, setTargets] = React35.useState([]);
18593
+ const [suggestionPhase, setSuggestionPhase] = React35.useState("idle");
18594
+ const [suggestions, setSuggestions] = React35.useState([]);
18595
+ const [suggestionError, setSuggestionError] = React35.useState(null);
18596
+ const [error, setError] = React35.useState(null);
18597
+ const [editor, setEditor] = React35.useState(null);
18598
+ const [saving, setSaving] = React35.useState(false);
18599
+ const [botCopyState, setBotCopyState] = React35.useState(null);
18600
+ const [accessPolicy, setAccessPolicy] = React35.useState(account.accessPolicy);
18601
+ const [slashPanel, setSlashPanel] = React35.useState(account.slashPanel);
18602
+ const mounted = React35.useRef(true);
18603
+ React35.useEffect(() => {
18451
18604
  setAccessPolicy(account.accessPolicy);
18452
18605
  }, [account.botId, account.accessPolicy]);
18453
- React34.useEffect(() => {
18606
+ React35.useEffect(() => {
18454
18607
  setSlashPanel(account.slashPanel);
18455
18608
  }, [account.botId, account.slashPanel]);
18456
- const invoke = React34.useCallback(async (endpoint, payload = {}, signal) => {
18609
+ const invoke = React35.useCallback(async (endpoint, payload = {}, signal) => {
18457
18610
  if (typeof rpcCall !== "function") throw new Error("\u6295\u9012\u76EE\u6807\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
18458
18611
  return unwrapRpcResult15(await rpcCall(endpoint, payload, signal));
18459
18612
  }, [rpcCall]);
18460
- const loadTargets = React34.useCallback(async ({ signal, silent = false } = {}) => {
18613
+ const loadTargets = React35.useCallback(async ({ signal, silent = false } = {}) => {
18461
18614
  if (!silent) setPhase("loading");
18462
18615
  setError(null);
18463
18616
  try {
@@ -18471,7 +18624,7 @@ function DeliveryTargetSettingsPage({
18471
18624
  setPhase("error");
18472
18625
  }
18473
18626
  }, [account.botId, invoke]);
18474
- const loadSuggestions = React34.useCallback(async () => {
18627
+ const loadSuggestions = React35.useCallback(async () => {
18475
18628
  setSuggestionPhase("loading");
18476
18629
  setSuggestionError(null);
18477
18630
  try {
@@ -18485,7 +18638,7 @@ function DeliveryTargetSettingsPage({
18485
18638
  setSuggestionPhase("error");
18486
18639
  }
18487
18640
  }, [account.botId, definition, invoke]);
18488
- React34.useEffect(() => {
18641
+ React35.useEffect(() => {
18489
18642
  mounted.current = true;
18490
18643
  const controller = new AbortController();
18491
18644
  void loadTargets({ signal: controller.signal });
@@ -18580,7 +18733,7 @@ function DeliveryTargetSettingsPage({
18580
18733
  role: "tabpanel",
18581
18734
  "aria-labelledby": activeTabDomId
18582
18735
  },
18583
- activeTab.id === "access" ? h2(AccessPolicySettingsPage, {
18736
+ activeTab.id === "general" ? h2(BotGeneralSettingsPage, { key: account.botId, account, rpcCall: accessRpcCall }) : activeTab.id === "access" ? h2(AccessPolicySettingsPage, {
18584
18737
  channel: channel7,
18585
18738
  account: { ...account, accessPolicy },
18586
18739
  rpcCall: accessRpcCall,
@@ -18597,7 +18750,7 @@ function DeliveryTargetSettingsPage({
18597
18750
  account,
18598
18751
  rpcCall: accessRpcCall
18599
18752
  }) : h2(
18600
- React34.Fragment,
18753
+ React35.Fragment,
18601
18754
  null,
18602
18755
  h2(
18603
18756
  "section",
@@ -18708,7 +18861,7 @@ function DeliveryTargetSettingsPage({
18708
18861
  }
18709
18862
 
18710
18863
  // plugin-src/client/global-settings.js
18711
- var React35 = __toESM(require("react"), 1);
18864
+ var React36 = __toESM(require("react"), 1);
18712
18865
 
18713
18866
  // src/channels/shared/inbound-ttl.mjs
18714
18867
  var DEFAULT_INBOUND_TTL_HOURS = 168;
@@ -18793,14 +18946,14 @@ function GlobalButton({ children, kind = "secondary", className = "", ...props }
18793
18946
  }, children);
18794
18947
  }
18795
18948
  function ImageInputSettings({ rpcCall }) {
18796
- const [values, setValues] = React35.useState(DEFAULT_IMAGE_INPUT_SETTINGS);
18797
- const [phase, setPhase] = React35.useState("loading");
18798
- const [error, setError] = React35.useState(null);
18799
- const [saved, setSaved] = React35.useState(false);
18800
- const mounted = React35.useRef(false);
18801
- const saving = React35.useRef(false);
18802
- const id6 = React35.useId();
18803
- const load = React35.useCallback(async (signal) => {
18949
+ const [values, setValues] = React36.useState(DEFAULT_IMAGE_INPUT_SETTINGS);
18950
+ const [phase, setPhase] = React36.useState("loading");
18951
+ const [error, setError] = React36.useState(null);
18952
+ const [saved, setSaved] = React36.useState(false);
18953
+ const mounted = React36.useRef(false);
18954
+ const saving = React36.useRef(false);
18955
+ const id6 = React36.useId();
18956
+ const load = React36.useCallback(async (signal) => {
18804
18957
  setPhase("loading");
18805
18958
  setError(null);
18806
18959
  try {
@@ -18816,7 +18969,7 @@ function ImageInputSettings({ rpcCall }) {
18816
18969
  setPhase("error");
18817
18970
  }
18818
18971
  }, [rpcCall]);
18819
- React35.useEffect(() => {
18972
+ React36.useEffect(() => {
18820
18973
  mounted.current = true;
18821
18974
  const controller = new AbortController();
18822
18975
  void load(controller.signal);
@@ -18923,29 +19076,29 @@ function ImageInputSettings({ rpcCall }) {
18923
19076
  );
18924
19077
  }
18925
19078
  function GlobalSettingsPanel({ rpcCall }) {
18926
- const [phase, setPhase] = React35.useState("loading");
18927
- const [loadError, setLoadError] = React35.useState(null);
18928
- const [ttlInput, setTtlInput] = React35.useState("");
18929
- const [savedTtl, setSavedTtl] = React35.useState(null);
18930
- const [ttlError, setTtlError] = React35.useState(false);
18931
- const [saveError, setSaveError] = React35.useState(null);
18932
- const [saveSucceeded, setSaveSucceeded] = React35.useState(false);
18933
- const [isSaving, setIsSaving] = React35.useState(false);
18934
- const [sweepConfirming, setSweepConfirming] = React35.useState(false);
18935
- const [sweeping, setSweeping] = React35.useState(false);
18936
- const ttlErrorId = React35.useId();
18937
- const ttlHintsId = React35.useId();
18938
- const sweepTriggerId = React35.useId();
18939
- const sweepConfirmId = React35.useId();
18940
- const sweepConfirmTextId = React35.useId();
18941
- const sweepConfirmButtonId = React35.useId();
18942
- const mounted = React35.useRef(true);
18943
- const saving = React35.useRef(false);
18944
- const invoke = React35.useCallback(async (endpoint, payload = {}, signal) => {
19079
+ const [phase, setPhase] = React36.useState("loading");
19080
+ const [loadError, setLoadError] = React36.useState(null);
19081
+ const [ttlInput, setTtlInput] = React36.useState("");
19082
+ const [savedTtl, setSavedTtl] = React36.useState(null);
19083
+ const [ttlError, setTtlError] = React36.useState(false);
19084
+ const [saveError, setSaveError] = React36.useState(null);
19085
+ const [saveSucceeded, setSaveSucceeded] = React36.useState(false);
19086
+ const [isSaving, setIsSaving] = React36.useState(false);
19087
+ const [sweepConfirming, setSweepConfirming] = React36.useState(false);
19088
+ const [sweeping, setSweeping] = React36.useState(false);
19089
+ const ttlErrorId = React36.useId();
19090
+ const ttlHintsId = React36.useId();
19091
+ const sweepTriggerId = React36.useId();
19092
+ const sweepConfirmId = React36.useId();
19093
+ const sweepConfirmTextId = React36.useId();
19094
+ const sweepConfirmButtonId = React36.useId();
19095
+ const mounted = React36.useRef(true);
19096
+ const saving = React36.useRef(false);
19097
+ const invoke = React36.useCallback(async (endpoint, payload = {}, signal) => {
18945
19098
  if (typeof rpcCall !== "function") throw new Error("\u901A\u7528\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
18946
19099
  return unwrapRpcResult16(await rpcCall(endpoint, payload, signal));
18947
19100
  }, [rpcCall]);
18948
- const loadSettings = React35.useCallback(async ({ signal } = {}) => {
19101
+ const loadSettings = React36.useCallback(async ({ signal } = {}) => {
18949
19102
  setPhase("loading");
18950
19103
  setLoadError(null);
18951
19104
  try {
@@ -18969,7 +19122,7 @@ function GlobalSettingsPanel({ rpcCall }) {
18969
19122
  setPhase("error");
18970
19123
  }
18971
19124
  }, [invoke]);
18972
- React35.useEffect(() => {
19125
+ React36.useEffect(() => {
18973
19126
  mounted.current = true;
18974
19127
  const controller = new AbortController();
18975
19128
  void loadSettings({ signal: controller.signal });
@@ -18978,7 +19131,7 @@ function GlobalSettingsPanel({ rpcCall }) {
18978
19131
  controller.abort();
18979
19132
  };
18980
19133
  }, [loadSettings]);
18981
- React35.useEffect(() => {
19134
+ React36.useEffect(() => {
18982
19135
  if (!sweepConfirming) return;
18983
19136
  globalThis.document?.getElementById(sweepConfirmButtonId)?.focus();
18984
19137
  }, [sweepConfirmButtonId, sweepConfirming]);
@@ -20313,7 +20466,7 @@ function installSessionChannelLogos(document2 = globalThis.document) {
20313
20466
  }
20314
20467
 
20315
20468
  // plugin-src/client/update-panel.js
20316
- var React36 = __toESM(require("react"), 1);
20469
+ var React37 = __toESM(require("react"), 1);
20317
20470
  var import_react_dom4 = require("react-dom");
20318
20471
  var import_valid = __toESM(require_valid(), 1);
20319
20472
  var import_rcompare = __toESM(require_rcompare(), 1);
@@ -20406,11 +20559,11 @@ function manualUpdateCommand(snapshot) {
20406
20559
  return `dsh plugin --profile ${profileArgument} add -w @xmanrui/dsh-im@${version}`;
20407
20560
  }
20408
20561
  function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
20409
- const [copyState, setCopyState] = React36.useState("idle");
20410
- const commandRef = React36.useRef(null);
20411
- const mounted = React36.useRef(false);
20412
- const copying = React36.useRef(false);
20413
- React36.useEffect(() => {
20562
+ const [copyState, setCopyState] = React37.useState("idle");
20563
+ const commandRef = React37.useRef(null);
20564
+ const mounted = React37.useRef(false);
20565
+ const copying = React37.useRef(false);
20566
+ React37.useEffect(() => {
20414
20567
  mounted.current = true;
20415
20568
  return () => {
20416
20569
  mounted.current = false;
@@ -20442,7 +20595,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
20442
20595
  { className: "dim-updateManual", "aria-label": "\u624B\u5DE5\u66F4\u65B0" },
20443
20596
  h2("h4", { className: "dim-updateManualHeading" }, "\u624B\u5DE5\u66F4\u65B0"),
20444
20597
  command ? h2(
20445
- React36.Fragment,
20598
+ React37.Fragment,
20446
20599
  null,
20447
20600
  h2("p", { className: "dim-updateManualHint" }, "\u81EA\u52A8\u66F4\u65B0\u5931\u8D25\u53EF\u4EE5\u4F7F\u7528\u547D\u4EE4\u66F4\u65B0\uFF1A"),
20448
20601
  h2(
@@ -20478,7 +20631,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
20478
20631
  "aria-hidden": "true",
20479
20632
  focusable: "false"
20480
20633
  }, copyState === "copied" ? h2("path", { d: "m4 10 4 4 8-8" }) : h2(
20481
- React36.Fragment,
20634
+ React37.Fragment,
20482
20635
  null,
20483
20636
  h2("rect", { x: 7, y: 7, width: 10, height: 11, rx: 1.5 }),
20484
20637
  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" })
@@ -20503,10 +20656,10 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
20503
20656
  );
20504
20657
  }
20505
20658
  function UpdateDialog({ children, onClose }) {
20506
- const dialogRef = React36.useRef(null);
20507
- const titleId = React36.useId();
20508
- const descriptionId = React36.useId();
20509
- React36.useEffect(() => {
20659
+ const dialogRef = React37.useRef(null);
20660
+ const titleId = React37.useId();
20661
+ const descriptionId = React37.useId();
20662
+ React37.useEffect(() => {
20510
20663
  const previous = globalThis.document?.activeElement;
20511
20664
  dialogRef.current?.focus?.();
20512
20665
  return () => {
@@ -20564,20 +20717,20 @@ function UpdateDialog({ children, onClose }) {
20564
20717
  return typeof document !== "undefined" && document.body ? (0, import_react_dom4.createPortal)(content, document.body) : content;
20565
20718
  }
20566
20719
  function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
20567
- const tooltipId = React36.useId();
20568
- const [snapshot, setSnapshot] = React36.useState(null);
20569
- const [action, setAction] = React36.useState("status");
20570
- const [error, setError] = React36.useState(null);
20571
- const [open, setOpen] = React36.useState(false);
20572
- const [uncertainInstall, setUncertainInstall] = React36.useState(false);
20573
- const mounted = React36.useRef(false);
20574
- const busy = React36.useRef(false);
20575
- const readController = React36.useRef(null);
20576
- const pollReadController = React36.useRef(null);
20577
- const installRequest = React36.useRef(null);
20578
- const onStatusRef = React36.useRef(onStatus);
20720
+ const tooltipId = React37.useId();
20721
+ const [snapshot, setSnapshot] = React37.useState(null);
20722
+ const [action, setAction] = React37.useState("status");
20723
+ const [error, setError] = React37.useState(null);
20724
+ const [open, setOpen] = React37.useState(false);
20725
+ const [uncertainInstall, setUncertainInstall] = React37.useState(false);
20726
+ const mounted = React37.useRef(false);
20727
+ const busy = React37.useRef(false);
20728
+ const readController = React37.useRef(null);
20729
+ const pollReadController = React37.useRef(null);
20730
+ const installRequest = React37.useRef(null);
20731
+ const onStatusRef = React37.useRef(onStatus);
20579
20732
  onStatusRef.current = onStatus;
20580
- const accept = React36.useCallback((next) => {
20733
+ const accept = React37.useCallback((next) => {
20581
20734
  setSnapshot(next);
20582
20735
  onStatusRef.current?.(next);
20583
20736
  }, []);
@@ -20586,7 +20739,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
20586
20739
  setUncertainInstall(false);
20587
20740
  accept(next);
20588
20741
  };
20589
- const invoke = React36.useCallback(async (endpoint, payload = {}, signal) => {
20742
+ const invoke = React37.useCallback(async (endpoint, payload = {}, signal) => {
20590
20743
  if (typeof rpcCall !== "function") {
20591
20744
  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");
20592
20745
  unavailable.code = "update-unavailable";
@@ -20594,7 +20747,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
20594
20747
  }
20595
20748
  return unwrapSnapshot(await rpcCall(endpoint, payload, signal));
20596
20749
  }, [rpcCall]);
20597
- React36.useEffect(() => {
20750
+ React37.useEffect(() => {
20598
20751
  mounted.current = true;
20599
20752
  busy.current = true;
20600
20753
  const controller = new AbortController();
@@ -20617,7 +20770,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
20617
20770
  const activeJob = ACTIVE_STATES4.has(snapshot?.job?.state);
20618
20771
  const restartRequired = snapshot?.job?.state === "restart-required" || snapshot?.blockedReason === "pending-restart";
20619
20772
  const shouldPoll = activeJob || uncertainInstall;
20620
- React36.useEffect(() => {
20773
+ React37.useEffect(() => {
20621
20774
  if (!shouldPoll) return void 0;
20622
20775
  let controller;
20623
20776
  const scheduler = createPollScheduler({
@@ -20718,7 +20871,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
20718
20871
  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";
20719
20872
  const buttonDescription = localizeText(buttonLabel) + (buttonLabel === "\u66F4\u65B0\u81F3" ? ` v${snapshot.latestVersion}` : "");
20720
20873
  return h2(
20721
- React36.Fragment,
20874
+ React37.Fragment,
20722
20875
  null,
20723
20876
  h2(
20724
20877
  "span",
@@ -20768,25 +20921,25 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
20768
20921
  h2("dt", null, "\u8FD0\u884C\u7248\u672C"),
20769
20922
  h2("dd", null, `v${snapshot?.runningVersion ?? clientVersion}`),
20770
20923
  snapshot?.installedVersion && snapshot.installedVersion !== snapshot.runningVersion ? h2(
20771
- React36.Fragment,
20924
+ React37.Fragment,
20772
20925
  null,
20773
20926
  h2("dt", null, "\u5DF2\u5B89\u88C5\u7248\u672C"),
20774
20927
  h2("dd", null, `v${snapshot.installedVersion}`)
20775
20928
  ) : null,
20776
20929
  targetVersion ? h2(
20777
- React36.Fragment,
20930
+ React37.Fragment,
20778
20931
  null,
20779
20932
  h2("dt", null, "\u76EE\u6807\u7248\u672C"),
20780
20933
  h2("dd", null, `v${targetVersion}`)
20781
20934
  ) : null,
20782
20935
  latestVersion ? h2(
20783
- React36.Fragment,
20936
+ React37.Fragment,
20784
20937
  null,
20785
20938
  h2("dt", null, "\u6700\u65B0\u7248\u672C"),
20786
20939
  h2("dd", null, `v${latestVersion}`)
20787
20940
  ) : null,
20788
20941
  historicalTargetVersion ? h2(
20789
- React36.Fragment,
20942
+ React37.Fragment,
20790
20943
  null,
20791
20944
  h2("dt", null, "\u4E0A\u6B21\u66F4\u65B0\u76EE\u6807"),
20792
20945
  h2("dd", null, `v${historicalTargetVersion}`)
@@ -20868,8 +21021,8 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
20868
21021
  }
20869
21022
 
20870
21023
  // plugin-src/client/panel-error-boundary.js
20871
- var React37 = __toESM(require("react"), 1);
20872
- var IMPanelErrorBoundary = class extends React37.Component {
21024
+ var React38 = __toESM(require("react"), 1);
21025
+ var IMPanelErrorBoundary = class extends React38.Component {
20873
21026
  state = { failed: false };
20874
21027
  static getDerivedStateFromError() {
20875
21028
  return { failed: true };
@@ -20889,9 +21042,9 @@ var IMPanelErrorBoundary = class extends React37.Component {
20889
21042
  };
20890
21043
 
20891
21044
  // plugin-src/client/plugin-page.js
20892
- var React38 = __toESM(require("react"), 1);
21045
+ var React39 = __toESM(require("react"), 1);
20893
21046
  var IM_MAIN_PANEL_ID = "xmanrui-dsh-im";
20894
- var h3 = React38.createElement;
21047
+ var h3 = React39.createElement;
20895
21048
  function OpenImAction({ subject, packageName, onOpen, t }) {
20896
21049
  if (subject?.kind !== "bundle" && subject?.kind !== "row") return null;
20897
21050
  if (subject.pkg?.name !== packageName) return null;
@@ -21122,28 +21275,28 @@ function IMSettingsTab({
21122
21275
  browserLocation = globalThis.location,
21123
21276
  navigateToRecoveryUrl = replacePageLocation
21124
21277
  }) {
21125
- const [selected, setSelected] = React39.useState(() => preferredSectionId === GLOBAL_SETTINGS_TAB_ID || CHANNELS.some((channel7) => channel7.id === preferredSectionId) ? preferredSectionId : "weixin");
21126
- const [loopbackRecovery, setLoopbackRecovery] = React39.useState(null);
21127
- const [runningVersion, setRunningVersion] = React39.useState(IM_PLUGIN_VERSION);
21128
- const [deliverySettings, setDeliverySettings] = React39.useState(null);
21278
+ const [selected, setSelected] = React40.useState(() => preferredSectionId === GLOBAL_SETTINGS_TAB_ID || CHANNELS.some((channel7) => channel7.id === preferredSectionId) ? preferredSectionId : "weixin");
21279
+ const [loopbackRecovery, setLoopbackRecovery] = React40.useState(null);
21280
+ const [runningVersion, setRunningVersion] = React40.useState(IM_PLUGIN_VERSION);
21281
+ const [deliverySettings, setDeliverySettings] = React40.useState(null);
21129
21282
  const emailEnabled = useEmailChannelEnabled(emailRpcCall);
21130
- const visibleChannels = React39.useMemo(
21283
+ const visibleChannels = React40.useMemo(
21131
21284
  () => CHANNELS.filter((channel7) => channel7.id !== "email" || emailEnabled),
21132
21285
  [emailEnabled]
21133
21286
  );
21134
- const githubTooltipId = React39.useId();
21135
- const generalSettingsTooltipId = React39.useId();
21287
+ const githubTooltipId = React40.useId();
21288
+ const generalSettingsTooltipId = React40.useId();
21136
21289
  const globalSettingsSelected = selected === GLOBAL_SETTINGS_TAB_ID;
21137
21290
  const active = visibleChannels.find((channel7) => channel7.id === selected) ?? visibleChannels[0];
21138
21291
  const activeTabId = globalSettingsSelected ? "dim-general-settings-trigger" : `dim-tab-${active.id}`;
21139
21292
  const activePanelId = globalSettingsSelected ? `dim-panel-${GLOBAL_SETTINGS_TAB_ID}` : `dim-panel-${active.id}`;
21140
- const reportLoopbackRecovery = React39.useCallback((recovery) => {
21293
+ const reportLoopbackRecovery = React40.useCallback((recovery) => {
21141
21294
  setLoopbackRecovery((current) => current?.url === recovery.url ? current : recovery);
21142
21295
  }, []);
21143
- const reportUpdateStatus = React39.useCallback((snapshot) => {
21296
+ const reportUpdateStatus = React40.useCallback((snapshot) => {
21144
21297
  setRunningVersion(snapshot.runningVersion);
21145
21298
  }, []);
21146
- const rpcCalls = React39.useMemo(() => createLoopbackAwareRpcCalls({
21299
+ const rpcCalls = React40.useMemo(() => createLoopbackAwareRpcCalls({
21147
21300
  dingtalkRpcCall,
21148
21301
  discordRpcCall,
21149
21302
  feishuRpcCall,
@@ -21185,7 +21338,7 @@ function IMSettingsTab({
21185
21338
  weixinRpcCall,
21186
21339
  whatsappRpcCall
21187
21340
  ]);
21188
- const botSettingsContext = React39.useMemo(() => Object.freeze({
21341
+ const botSettingsContext = React40.useMemo(() => Object.freeze({
21189
21342
  openBotSettings: setDeliverySettings
21190
21343
  }), []);
21191
21344
  return h2(
@@ -21409,7 +21562,7 @@ function apply(ctx) {
21409
21562
  };
21410
21563
  const localeSnapshot = () => ctx.locale.getLocale?.()?.active ?? "";
21411
21564
  function IMPanel({ preferredSectionId }) {
21412
- React39.useSyncExternalStore(subscribeLocale, localeSnapshot, localeSnapshot);
21565
+ React40.useSyncExternalStore(subscribeLocale, localeSnapshot, localeSnapshot);
21413
21566
  return h2(
21414
21567
  IMPanelErrorBoundary,
21415
21568
  null,