@xmanrui/dsh-im 4.18.0 → 4.19.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 (51) hide show
  1. package/README.en.md +8 -3
  2. package/README.md +8 -3
  3. package/lib/client.js +809 -515
  4. package/lib/index.js +269 -267
  5. package/package.json +5 -1
  6. package/plugin-src/client/bot-alias.js +92 -0
  7. package/plugin-src/client/channels/dingtalk/api.js +3 -0
  8. package/plugin-src/client/channels/dingtalk/index.js +7 -1
  9. package/plugin-src/client/channels/feishu/api.js +3 -0
  10. package/plugin-src/client/channels/feishu/index.js +7 -1
  11. package/plugin-src/client/channels/qq/api.js +3 -0
  12. package/plugin-src/client/channels/qq/index.js +9 -1
  13. package/plugin-src/client/channels/shared/token-api.js +3 -0
  14. package/plugin-src/client/channels/shared/token-channel.js +9 -2
  15. package/plugin-src/client/channels/wecom/api.js +3 -0
  16. package/plugin-src/client/channels/wecom/index.js +9 -1
  17. package/plugin-src/client/channels/wecom-app/api.js +3 -0
  18. package/plugin-src/client/channels/wecom-app/index.js +9 -1
  19. package/plugin-src/client/channels/weixin/api.js +3 -0
  20. package/plugin-src/client/channels/weixin/index.js +7 -1
  21. package/plugin-src/client/channels/whatsapp/api.js +3 -0
  22. package/plugin-src/client/channels/whatsapp/index.js +9 -1
  23. package/plugin-src/client/i18n.js +10 -0
  24. package/plugin-src/client/styles.js +26 -0
  25. package/plugin-src/host/channels/dingtalk/rpc.mjs +11 -0
  26. package/plugin-src/host/channels/feishu/production.mjs +22 -0
  27. package/plugin-src/host/channels/feishu/rpc.mjs +14 -0
  28. package/plugin-src/host/channels/imessage/rpc.mjs +1 -0
  29. package/plugin-src/host/channels/qq/rpc.mjs +11 -0
  30. package/plugin-src/host/channels/shared/bot-alias-rpc.mjs +15 -0
  31. package/plugin-src/host/channels/shared/rpc.mjs +9 -0
  32. package/plugin-src/host/channels/slack/rpc.mjs +10 -0
  33. package/plugin-src/host/channels/wecom/rpc.mjs +11 -0
  34. package/plugin-src/host/channels/wecom-app/rpc.mjs +10 -0
  35. package/plugin-src/host/channels/weixin/rpc.mjs +11 -0
  36. package/plugin-src/host/channels/whatsapp/rpc.mjs +13 -0
  37. package/plugin-src/host/rpc-authority.mjs +3 -2
  38. package/plugin-src/host/session-sync-coordinator.mjs +19 -1
  39. package/scripts/verify-lan-management.mjs +176 -0
  40. package/src/channels/feishu/bridge.mjs +370 -7
  41. package/src/channels/feishu/feishu-cards.mjs +1 -1
  42. package/src/channels/feishu/feishu-runtime.mjs +6 -0
  43. package/src/channels/feishu/state-store.mjs +17 -0
  44. package/src/channels/shared/bot-alias.mjs +29 -0
  45. package/src/channels/shared/bot-workspace-store.mjs +71 -3
  46. package/src/channels/shared/i18n-en/shared-a.mjs +2 -2
  47. package/src/channels/shared/message-failure.mjs +2 -1
  48. package/src/channels/shared/model-command.mjs +3 -2
  49. package/src/channels/shared/session-sync-registry.mjs +34 -0
  50. package/src/channels/shared/text-harness-bridge.mjs +38 -0
  51. package/src/channels/telegram/telegram-runtime.mjs +77 -25
package/lib/client.js CHANGED
@@ -577,12 +577,12 @@ function callManagementRpc(connection, channel5, method, payload, signal) {
577
577
  }
578
578
 
579
579
  // plugin-src/client/index.js
580
- var React29 = __toESM(require("react"), 1);
580
+ var React30 = __toESM(require("react"), 1);
581
581
 
582
582
  // package.json
583
583
  var package_default = {
584
584
  name: "@xmanrui/dsh-im",
585
- version: "4.18.0",
585
+ version: "4.19.0",
586
586
  description: "\u628A\u5341\u4E00\u79CD IM \u6E20\u9053\u548C\u516C\u7F51 AI Office \u63A5\u5165\u672C\u673A DeepSeek Harness\u3002 Connect eleven IM channels and a public AI Office to a local DeepSeek Harness.",
587
587
  keywords: [
588
588
  "deepseek-harness",
@@ -630,6 +630,10 @@ var package_default = {
630
630
  {
631
631
  name: "cherryFloris",
632
632
  url: "https://github.com/cherryFloris"
633
+ },
634
+ {
635
+ name: "geekyfoxlab",
636
+ url: "https://github.com/geekyfoxlab"
633
637
  }
634
638
  ],
635
639
  license: "MIT",
@@ -887,6 +891,23 @@ function OfficeLogoGlyph({ size } = {}) {
887
891
  );
888
892
  }
889
893
 
894
+ // src/channels/shared/bot-alias.mjs
895
+ var MAX_BOT_ALIAS_LENGTH = 80;
896
+ function validateBotAlias(value) {
897
+ if (typeof value !== "string" || value.trim().length > MAX_BOT_ALIAS_LENGTH || /[\u0000-\u001f\u007f]/u.test(value)) {
898
+ throw new TypeError("\u522B\u540D\u4E0D\u80FD\u5305\u542B\u6362\u884C\u6216\u63A7\u5236\u5B57\u7B26\uFF0C\u4E14\u6700\u591A 80 \u4E2A\u5B57\u7B26\u3002");
899
+ }
900
+ return value.trim();
901
+ }
902
+ function normalizeBotAlias(bot) {
903
+ try {
904
+ const alias = validateBotAlias(bot?.alias);
905
+ return alias && typeof bot.originalName === "string" ? { alias, originalName: bot.originalName } : {};
906
+ } catch {
907
+ return {};
908
+ }
909
+ }
910
+
890
911
  // plugin-src/client/agent-preset.js
891
912
  var React3 = __toESM(require("react"), 1);
892
913
 
@@ -895,6 +916,16 @@ var React2 = __toESM(require("react"), 1);
895
916
  var IM_LOCALE_NAMESPACE = "dsh-im";
896
917
  var EN = Object.freeze({
897
918
  "$locale": "en",
919
+ "\u4FEE\u6539\u522B\u540D": "Edit alias",
920
+ "\u5173\u95ED\u4FEE\u6539\u522B\u540D": "Close alias editor",
921
+ "\u539F\u540D\u79F0": "Original name",
922
+ "\u522B\u540D": "Alias",
923
+ "\u6062\u590D\u539F\u540D\u79F0": "Restore original name",
924
+ "\u4F8B\u5982\uFF1A\u5BA2\u670D\u52A9\u624B": "e.g. Customer support",
925
+ "\u4EC5\u66F4\u6539\u663E\u793A\u540D\u79F0\uFF0C\u7559\u7A7A\u5219\u663E\u793A\u539F\u540D\u79F0\u3002": "Only changes the display name. Leave blank to use the original name.",
926
+ "\u522B\u540D\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002": "Could not save the alias. Try again.",
927
+ "\u522B\u540D\u4E0D\u80FD\u5305\u542B\u6362\u884C\u6216\u63A7\u5236\u5B57\u7B26\uFF0C\u4E14\u6700\u591A 80 \u4E2A\u5B57\u7B26\u3002": "Use at most 80 characters without line breaks or control characters.",
928
+ "\u8BF7\u8F93\u5165\u6709\u6548\u7684\u522B\u540D\uFF08\u6700\u591A 80 \u4E2A\u5B57\u7B26\uFF09\u3002": "Enter a valid alias (up to 80 characters).",
898
929
  " macOS Messages \u8FDE\u63A5": " macOS Messages connection",
899
930
  "\u63A5\u5165 iMessage": "Connect iMessage",
900
931
  "\u5148\u5728 macOS \u7CFB\u7EDF\u8BBE\u7F6E\u4E2D\u6388\u4E88 Messages \u6743\u9650\u3002": "Grant Messages permissions in macOS System Settings first.",
@@ -2744,7 +2775,8 @@ var DINGTALK_ENDPOINTS = Object.freeze({
2744
2775
  setModel: SET_MODEL_ENDPOINT,
2745
2776
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
2746
2777
  setContextEnhancement: "bot.context-enhancement.set",
2747
- setAccessPolicy: "bot.access-policy.set"
2778
+ setAccessPolicy: "bot.access-policy.set",
2779
+ setAlias: "bot.alias.set"
2748
2780
  });
2749
2781
  var ACCOUNT_STATES = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
2750
2782
  var SNAPSHOT_STATES = /* @__PURE__ */ new Set(["disconnected", "offline", "provisioning", "connected", "degraded"]);
@@ -2892,6 +2924,7 @@ function normalizeBot(value) {
2892
2924
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
2893
2925
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
2894
2926
  bot: {
2927
+ ...normalizeBotAlias(bot),
2895
2928
  name: optionalString(bot.name, 100) ?? "\u9489\u9489\u673A\u5668\u4EBA",
2896
2929
  clientIdMasked: optionalString(bot.clientIdMasked, 140) ?? "\u5DF2\u5B89\u5168\u4FDD\u5B58"
2897
2930
  },
@@ -2954,11 +2987,174 @@ function formatRemaining(milliseconds) {
2954
2987
  return `${String(Math.floor(seconds / 60)).padStart(2, "0")}:${String(seconds % 60).padStart(2, "0")}`;
2955
2988
  }
2956
2989
 
2990
+ // plugin-src/client/bot-alias.js
2991
+ var React5 = __toESM(require("react"), 1);
2992
+ var import_react_dom = require("react-dom");
2993
+ function AliasDialog({ bot, onSave, onClose }) {
2994
+ const id6 = React5.useId();
2995
+ const dialogRef = React5.useRef(null);
2996
+ const inputRef = React5.useRef(null);
2997
+ const savingRef = React5.useRef(false);
2998
+ const [draft, setDraft] = React5.useState(bot.alias ?? "");
2999
+ const [saving, setSaving] = React5.useState(false);
3000
+ const [error, setError] = React5.useState(null);
3001
+ React5.useEffect(() => {
3002
+ const previous = globalThis.document?.activeElement;
3003
+ dialogRef.current?.showModal?.();
3004
+ inputRef.current?.focus?.();
3005
+ inputRef.current?.select?.();
3006
+ return () => {
3007
+ if (previous?.isConnected) previous.focus?.();
3008
+ };
3009
+ }, []);
3010
+ const close = () => {
3011
+ if (!savingRef.current) onClose();
3012
+ };
3013
+ const save = async (value) => {
3014
+ if (savingRef.current) return;
3015
+ setError(null);
3016
+ try {
3017
+ const alias = validateBotAlias(value);
3018
+ if (alias === (bot.alias ?? "")) {
3019
+ onClose();
3020
+ return;
3021
+ }
3022
+ savingRef.current = true;
3023
+ setSaving(true);
3024
+ await onSave(alias);
3025
+ onClose();
3026
+ } catch (cause) {
3027
+ setError(cause?.message ?? "\u522B\u540D\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002");
3028
+ } finally {
3029
+ savingRef.current = false;
3030
+ setSaving(false);
3031
+ }
3032
+ };
3033
+ const content = h2(
3034
+ "dialog",
3035
+ {
3036
+ ref: dialogRef,
3037
+ className: "dim-aliasDialog",
3038
+ "aria-labelledby": `${id6}-title`,
3039
+ "aria-busy": saving,
3040
+ onCancel: (event) => {
3041
+ event.preventDefault();
3042
+ close();
3043
+ },
3044
+ onClick: (event) => event.stopPropagation(),
3045
+ onKeyDown: (event) => event.stopPropagation()
3046
+ },
3047
+ h2(
3048
+ "div",
3049
+ { className: "dim-aliasHeader" },
3050
+ h2("h3", { id: `${id6}-title` }, "\u4FEE\u6539\u522B\u540D"),
3051
+ h2("button", {
3052
+ type: "button",
3053
+ className: "dim-aliasClose",
3054
+ disabled: saving,
3055
+ "aria-label": "\u5173\u95ED\u4FEE\u6539\u522B\u540D",
3056
+ onClick: close
3057
+ }, "\xD7")
3058
+ ),
3059
+ h2(
3060
+ "div",
3061
+ { className: "dim-aliasOriginal" },
3062
+ h2("span", null, "\u539F\u540D\u79F0"),
3063
+ h2("span", null, bot.originalName ?? bot.name)
3064
+ ),
3065
+ h2("label", { htmlFor: `${id6}-input` }, "\u522B\u540D"),
3066
+ h2("input", {
3067
+ id: `${id6}-input`,
3068
+ ref: inputRef,
3069
+ value: draft,
3070
+ disabled: saving,
3071
+ maxLength: MAX_BOT_ALIAS_LENGTH,
3072
+ placeholder: "\u4F8B\u5982\uFF1A\u5BA2\u670D\u52A9\u624B",
3073
+ "aria-describedby": `${id6}-help`,
3074
+ onChange: (event) => setDraft(event.target.value),
3075
+ onKeyDown: (event) => {
3076
+ if (event.key === "Enter" && !event.nativeEvent?.isComposing) {
3077
+ event.preventDefault();
3078
+ void save(draft);
3079
+ }
3080
+ }
3081
+ }),
3082
+ h2("p", { id: `${id6}-help`, className: "dim-aliasHelp" }, "\u4EC5\u66F4\u6539\u663E\u793A\u540D\u79F0\uFF0C\u7559\u7A7A\u5219\u663E\u793A\u539F\u540D\u79F0\u3002"),
3083
+ error ? h2("p", { className: "dim-aliasError", role: "alert" }, error) : null,
3084
+ h2(
3085
+ "div",
3086
+ { className: "dim-aliasFooter" },
3087
+ h2("button", {
3088
+ type: "button",
3089
+ className: "dim-aliasRestore",
3090
+ disabled: saving || !bot.alias,
3091
+ onClick: () => void save("")
3092
+ }, "\u6062\u590D\u539F\u540D\u79F0"),
3093
+ h2(
3094
+ "div",
3095
+ { className: "dim-aliasActions" },
3096
+ h2("button", { type: "button", disabled: saving, onClick: close }, "\u53D6\u6D88"),
3097
+ h2("button", {
3098
+ type: "button",
3099
+ className: "dim-aliasSave",
3100
+ disabled: saving,
3101
+ onClick: () => void save(draft)
3102
+ }, saving ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58")
3103
+ )
3104
+ )
3105
+ );
3106
+ return globalThis.document?.body ? (0, import_react_dom.createPortal)(content, document.body) : content;
3107
+ }
3108
+ function BotName({ bot, id: id6, disabled = false, onSave }) {
3109
+ const [open, setOpen] = React5.useState(false);
3110
+ return h2(
3111
+ "div",
3112
+ { className: "dim-aliasName" },
3113
+ h2("h3", { id: id6, title: bot.name }, bot.name),
3114
+ h2(
3115
+ "span",
3116
+ {
3117
+ className: "dim-aliasEntry",
3118
+ onClick: (event) => event.stopPropagation(),
3119
+ onKeyDown: (event) => event.stopPropagation()
3120
+ },
3121
+ h2(
3122
+ "button",
3123
+ {
3124
+ type: "button",
3125
+ className: "dim-aliasEdit",
3126
+ "aria-label": "\u4FEE\u6539\u522B\u540D",
3127
+ title: "\u4FEE\u6539\u522B\u540D",
3128
+ "aria-haspopup": "dialog",
3129
+ disabled: disabled || typeof onSave !== "function",
3130
+ onClick: () => setOpen(true)
3131
+ },
3132
+ h2(
3133
+ "svg",
3134
+ {
3135
+ width: 14,
3136
+ height: 14,
3137
+ viewBox: "0 0 24 24",
3138
+ fill: "none",
3139
+ stroke: "currentColor",
3140
+ strokeWidth: 1.7,
3141
+ strokeLinecap: "round",
3142
+ strokeLinejoin: "round",
3143
+ "aria-hidden": true
3144
+ },
3145
+ h2("path", { d: "m16 3 5 5M3 21l5-1L21 7a2.1 2.1 0 0 0-5-5L3 15Z" })
3146
+ )
3147
+ ),
3148
+ open ? h2(AliasDialog, { bot, onSave, onClose: () => setOpen(false) }) : null
3149
+ )
3150
+ );
3151
+ }
3152
+
2957
3153
  // plugin-src/client/channels/dingtalk/index.js
2958
- var React12 = __toESM(require("react"), 1);
3154
+ var React13 = __toESM(require("react"), 1);
2959
3155
 
2960
3156
  // plugin-src/client/credential-binding.js
2961
- var React5 = __toESM(require("react"), 1);
3157
+ var React6 = __toESM(require("react"), 1);
2962
3158
  function ActionIcon({ children }) {
2963
3159
  return h2("svg", {
2964
3160
  className: "dim-actionIcon",
@@ -3018,9 +3214,9 @@ function CredentialBindingPanel({
3018
3214
  onSubmit,
3019
3215
  onCancel
3020
3216
  }) {
3021
- const [identity, setIdentity] = React5.useState("");
3022
- const [secret, setSecret] = React5.useState("");
3023
- const headingId = React5.useId();
3217
+ const [identity, setIdentity] = React6.useState("");
3218
+ const [secret, setSecret] = React6.useState("");
3219
+ const headingId = React6.useId();
3024
3220
  const hasIdentity = Boolean(identityLabel);
3025
3221
  const submit = (event) => {
3026
3222
  event.preventDefault();
@@ -3099,7 +3295,7 @@ function CredentialBindingPanel({
3099
3295
  }
3100
3296
 
3101
3297
  // plugin-src/client/channels/shared/collapsible-account.js
3102
- var React6 = __toESM(require("react"), 1);
3298
+ var React7 = __toESM(require("react"), 1);
3103
3299
  function CollapsibleAccountSection({
3104
3300
  header,
3105
3301
  defaultOpen = false,
@@ -3109,7 +3305,7 @@ function CollapsibleAccountSection({
3109
3305
  className = "",
3110
3306
  children
3111
3307
  }) {
3112
- const [uncontrolledOpen, setUncontrolledOpen] = React6.useState(defaultOpen);
3308
+ const [uncontrolledOpen, setUncontrolledOpen] = React7.useState(defaultOpen);
3113
3309
  const open = controlledOpen ?? uncontrolledOpen;
3114
3310
  const contentId = id6 ? `${id6}-content` : void 0;
3115
3311
  const toggle = () => {
@@ -3156,11 +3352,11 @@ function CollapsibleAccountSection({
3156
3352
  }
3157
3353
 
3158
3354
  // plugin-src/client/workspace-editor.js
3159
- var React8 = __toESM(require("react"), 1);
3355
+ var React9 = __toESM(require("react"), 1);
3160
3356
 
3161
3357
  // plugin-src/client/workspace-directory-picker.js
3162
- var React7 = __toESM(require("react"), 1);
3163
- var import_react_dom = require("react-dom");
3358
+ var React8 = __toESM(require("react"), 1);
3359
+ var import_react_dom2 = require("react-dom");
3164
3360
  function pickerErrorCode(error) {
3165
3361
  return error?.rpcError?.code ?? error?.code;
3166
3362
  }
@@ -3180,7 +3376,7 @@ function pickerErrorMessage(error) {
3180
3376
  return error?.rpcError?.message ?? error?.message ?? "\u65E0\u6CD5\u8BFB\u53D6\u76EE\u5F55\uFF0C\u8BF7\u91CD\u8BD5\u3002";
3181
3377
  }
3182
3378
  function FolderIcon() {
3183
- return React7.createElement(
3379
+ return React8.createElement(
3184
3380
  "svg",
3185
3381
  {
3186
3382
  viewBox: "0 0 24 24",
@@ -3191,11 +3387,11 @@ function FolderIcon() {
3191
3387
  strokeLinejoin: "round",
3192
3388
  "aria-hidden": "true"
3193
3389
  },
3194
- React7.createElement("path", { d: "M3.5 7.25A2.25 2.25 0 0 1 5.75 5h4.1l1.8 2h6.6a2.25 2.25 0 0 1 2.25 2.25v7A2.75 2.75 0 0 1 17.75 19h-12A2.25 2.25 0 0 1 3.5 16.75v-9.5Z" })
3390
+ React8.createElement("path", { d: "M3.5 7.25A2.25 2.25 0 0 1 5.75 5h4.1l1.8 2h6.6a2.25 2.25 0 0 1 2.25 2.25v7A2.75 2.75 0 0 1 17.75 19h-12A2.25 2.25 0 0 1 3.5 16.75v-9.5Z" })
3195
3391
  );
3196
3392
  }
3197
3393
  function ChevronIcon() {
3198
- return React7.createElement("svg", {
3394
+ return React8.createElement("svg", {
3199
3395
  viewBox: "0 0 20 20",
3200
3396
  fill: "none",
3201
3397
  stroke: "currentColor",
@@ -3203,7 +3399,7 @@ function ChevronIcon() {
3203
3399
  strokeLinecap: "round",
3204
3400
  strokeLinejoin: "round",
3205
3401
  "aria-hidden": "true"
3206
- }, React7.createElement("path", { d: "m7.5 4.5 5 5.5-5 5.5" }));
3402
+ }, React8.createElement("path", { d: "m7.5 4.5 5 5.5-5 5.5" }));
3207
3403
  }
3208
3404
  function displayCrumbs(listing) {
3209
3405
  const homeIndex = listing.crumbs.findIndex((crumb) => crumb.path === listing.home);
@@ -3219,28 +3415,28 @@ function WorkspaceDirectoryPicker({
3219
3415
  onPicked,
3220
3416
  onCancel
3221
3417
  }) {
3222
- const [listing, setListing] = React7.useState(null);
3223
- const [loading, setLoading] = React7.useState(false);
3224
- const [error, setError] = React7.useState(null);
3225
- const [pathDraft, setPathDraft] = React7.useState(startPath ?? "");
3226
- const [showHidden, setShowHidden] = React7.useState(false);
3227
- const [retryKey, setRetryKey] = React7.useState(0);
3228
- const requestRef = React7.useRef(0);
3229
- const controllerRef = React7.useRef(null);
3230
- const dialogRef = React7.useRef(null);
3231
- const bodyRef = React7.useRef(null);
3232
- const titleId = React7.useId();
3233
- const noticeId = React7.useId();
3234
- const pathInputId = React7.useId();
3235
- const errorId = React7.useId();
3236
- const initialPathRef = React7.useRef(startPath);
3237
- const onPickedRef = React7.useRef(onPicked);
3238
- const onCancelRef = React7.useRef(onCancel);
3239
- const busyRef = React7.useRef(busy);
3418
+ const [listing, setListing] = React8.useState(null);
3419
+ const [loading, setLoading] = React8.useState(false);
3420
+ const [error, setError] = React8.useState(null);
3421
+ const [pathDraft, setPathDraft] = React8.useState(startPath ?? "");
3422
+ const [showHidden, setShowHidden] = React8.useState(false);
3423
+ const [retryKey, setRetryKey] = React8.useState(0);
3424
+ const requestRef = React8.useRef(0);
3425
+ const controllerRef = React8.useRef(null);
3426
+ const dialogRef = React8.useRef(null);
3427
+ const bodyRef = React8.useRef(null);
3428
+ const titleId = React8.useId();
3429
+ const noticeId = React8.useId();
3430
+ const pathInputId = React8.useId();
3431
+ const errorId = React8.useId();
3432
+ const initialPathRef = React8.useRef(startPath);
3433
+ const onPickedRef = React8.useRef(onPicked);
3434
+ const onCancelRef = React8.useRef(onCancel);
3435
+ const busyRef = React8.useRef(busy);
3240
3436
  onPickedRef.current = onPicked;
3241
3437
  onCancelRef.current = onCancel;
3242
3438
  busyRef.current = busy;
3243
- const loadDirectory = React7.useCallback(async (path, { reportError = true } = {}) => {
3439
+ const loadDirectory = React8.useCallback(async (path, { reportError = true } = {}) => {
3244
3440
  const request = requestRef.current + 1;
3245
3441
  requestRef.current = request;
3246
3442
  controllerRef.current?.abort();
@@ -3264,7 +3460,7 @@ function WorkspaceDirectoryPicker({
3264
3460
  if (request === requestRef.current) setLoading(false);
3265
3461
  }
3266
3462
  }, [picker]);
3267
- React7.useEffect(() => {
3463
+ React8.useEffect(() => {
3268
3464
  if (!open) return void 0;
3269
3465
  let active = true;
3270
3466
  setListing(null);
@@ -3344,10 +3540,10 @@ function WorkspaceDirectoryPicker({
3344
3540
  "nav",
3345
3541
  { className: "dim-directoryCrumbs", "aria-label": "\u5F53\u524D\u76EE\u5F55" },
3346
3542
  crumbs.map((crumb, index) => h2(
3347
- React7.Fragment,
3543
+ React8.Fragment,
3348
3544
  { key: crumb.path },
3349
3545
  index > 0 ? h2("span", { className: "dim-directoryCrumbSeparator", "aria-hidden": "true" }, "\u203A") : null,
3350
- React7.createElement("button", {
3546
+ React8.createElement("button", {
3351
3547
  type: "button",
3352
3548
  title: crumb.path,
3353
3549
  disabled: loading || busy,
@@ -3410,7 +3606,7 @@ function WorkspaceDirectoryPicker({
3410
3606
  ) : listing ? entries.length > 0 ? h2("ul", { className: "dim-directoryList" }, entries.map((entry) => h2(
3411
3607
  "li",
3412
3608
  { key: entry.path },
3413
- React7.createElement(
3609
+ React8.createElement(
3414
3610
  "button",
3415
3611
  {
3416
3612
  type: "button",
@@ -3419,7 +3615,7 @@ function WorkspaceDirectoryPicker({
3419
3615
  onClick: () => void loadDirectory(entry.path)
3420
3616
  },
3421
3617
  h2("span", { className: "dim-directoryFolder" }, h2(FolderIcon)),
3422
- React7.createElement("span", { className: "dim-directoryName" }, entry.name),
3618
+ React8.createElement("span", { className: "dim-directoryName" }, entry.name),
3423
3619
  h2("span", { className: "dim-directoryChevron" }, h2(ChevronIcon))
3424
3620
  )
3425
3621
  ))) : h2(
@@ -3468,25 +3664,25 @@ function WorkspaceDirectoryPicker({
3468
3664
  )
3469
3665
  )
3470
3666
  );
3471
- return typeof document === "undefined" ? content : (0, import_react_dom.createPortal)(content, document.body);
3667
+ return typeof document === "undefined" ? content : (0, import_react_dom2.createPortal)(content, document.body);
3472
3668
  }
3473
3669
 
3474
3670
  // plugin-src/client/workspace-editor.js
3475
- var WorkspaceDirectoryPickerContext = React8.createContext(null);
3671
+ var WorkspaceDirectoryPickerContext = React9.createContext(null);
3476
3672
  function WorkspaceEditor({ workspace, directoryPicker, disabled = false, onSave }) {
3477
- const sharedDirectoryPicker = React8.useContext(WorkspaceDirectoryPickerContext);
3673
+ const sharedDirectoryPicker = React9.useContext(WorkspaceDirectoryPickerContext);
3478
3674
  const activeDirectoryPicker = directoryPicker ?? sharedDirectoryPicker;
3479
- const [open, setOpen] = React8.useState(false);
3480
- const [saving, setSaving] = React8.useState(false);
3481
- const [error, setError] = React8.useState(null);
3482
- const editButtonRef = React8.useRef(null);
3483
- const savingRef = React8.useRef(false);
3484
- const close = React8.useCallback(() => {
3675
+ const [open, setOpen] = React9.useState(false);
3676
+ const [saving, setSaving] = React9.useState(false);
3677
+ const [error, setError] = React9.useState(null);
3678
+ const editButtonRef = React9.useRef(null);
3679
+ const savingRef = React9.useRef(false);
3680
+ const close = React9.useCallback(() => {
3485
3681
  setOpen(false);
3486
3682
  setError(null);
3487
3683
  queueMicrotask(() => editButtonRef.current?.focus?.());
3488
3684
  }, []);
3489
- const pick = React8.useCallback(async (value) => {
3685
+ const pick = React9.useCallback(async (value) => {
3490
3686
  if (!value || savingRef.current || disabled) return;
3491
3687
  if (value === workspace) {
3492
3688
  close();
@@ -3523,7 +3719,7 @@ function WorkspaceEditor({ workspace, directoryPicker, disabled = false, onSave
3523
3719
  disabled: disabled || !activeDirectoryPicker
3524
3720
  }, "\u9009\u62E9\u76EE\u5F55")
3525
3721
  ),
3526
- workspace ? React8.createElement("code", {
3722
+ workspace ? React9.createElement("code", {
3527
3723
  className: "dim-workspacePath",
3528
3724
  title: workspace
3529
3725
  }, workspace) : h2("code", { className: "dim-workspacePath" }, "\u672A\u8BBE\u7F6E"),
@@ -3540,8 +3736,8 @@ function WorkspaceEditor({ workspace, directoryPicker, disabled = false, onSave
3540
3736
  }
3541
3737
 
3542
3738
  // plugin-src/client/context-enhancement.js
3543
- var React9 = __toESM(require("react"), 1);
3544
- var import_react_dom2 = require("react-dom");
3739
+ var React10 = __toESM(require("react"), 1);
3740
+ var import_react_dom3 = require("react-dom");
3545
3741
  var FIELD_LABELS = Object.freeze({
3546
3742
  channel: "\u6E20\u9053",
3547
3743
  conversationType: "\u4F1A\u8BDD\u7C7B\u578B",
@@ -3785,7 +3981,7 @@ function ContextEnhancementScopeEditor({
3785
3981
  );
3786
3982
  }
3787
3983
  function ContextEnhancementDialog({ config, groupSupported, disabled, onSave, onClose, returnFocusRef, id: id6 }) {
3788
- const [draft, setDraft] = React9.useState(() => {
3984
+ const [draft, setDraft] = React10.useState(() => {
3789
3985
  const normalized = normalizeContextEnhancementConfig(config);
3790
3986
  return {
3791
3987
  ...normalized,
@@ -3794,23 +3990,23 @@ function ContextEnhancementDialog({ config, groupSupported, disabled, onSave, on
3794
3990
  } : {}
3795
3991
  };
3796
3992
  });
3797
- const [saving, setSaving] = React9.useState(false);
3798
- const [error, setError] = React9.useState(null);
3799
- const [activeScope, setActiveScope] = React9.useState("direct");
3800
- const savingRef = React9.useRef(false);
3801
- const dialogRef = React9.useRef(null);
3802
- const mountedRef = React9.useRef(true);
3803
- const groupTabRef = React9.useRef(null);
3804
- const directTabRef = React9.useRef(null);
3805
- const titleId = React9.useId();
3806
- const descriptionId = React9.useId();
3807
- const scopeIdPrefix = React9.useId();
3993
+ const [saving, setSaving] = React10.useState(false);
3994
+ const [error, setError] = React10.useState(null);
3995
+ const [activeScope, setActiveScope] = React10.useState("direct");
3996
+ const savingRef = React10.useRef(false);
3997
+ const dialogRef = React10.useRef(null);
3998
+ const mountedRef = React10.useRef(true);
3999
+ const groupTabRef = React10.useRef(null);
4000
+ const directTabRef = React10.useRef(null);
4001
+ const titleId = React10.useId();
4002
+ const descriptionId = React10.useId();
4003
+ const scopeIdPrefix = React10.useId();
3808
4004
  const groupGuidanceExample = localizeText(CONTEXT_GROUP_GUIDANCE_EXAMPLE);
3809
4005
  const directGuidanceExample = localizeText(CONTEXT_DIRECT_GUIDANCE_EXAMPLE);
3810
4006
  const busy = disabled || saving;
3811
4007
  const scopeKinds = ["direct", "group"];
3812
4008
  const tabRefs = { group: groupTabRef, direct: directTabRef };
3813
- React9.useEffect(() => {
4009
+ React10.useEffect(() => {
3814
4010
  mountedRef.current = true;
3815
4011
  dialogRef.current?.focus?.();
3816
4012
  const keepFocus = (event) => {
@@ -3998,20 +4194,20 @@ function ContextEnhancementDialog({ config, groupSupported, disabled, onSave, on
3998
4194
  }, saving ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58")
3999
4195
  )
4000
4196
  ));
4001
- return globalThis.document?.body ? (0, import_react_dom2.createPortal)(content, document.body) : content;
4197
+ return globalThis.document?.body ? (0, import_react_dom3.createPortal)(content, document.body) : content;
4002
4198
  }
4003
4199
  function ContextEnhancementEditor({ config, groupSupported = true, disabled = false, onSave }) {
4004
- const [open, setOpen] = React9.useState(false);
4005
- const entryRef = React9.useRef(null);
4006
- const dialogId = React9.useId();
4007
- const statusId = React9.useId();
4200
+ const [open, setOpen] = React10.useState(false);
4201
+ const entryRef = React10.useRef(null);
4202
+ const dialogId = React10.useId();
4203
+ const statusId = React10.useId();
4008
4204
  const saved = normalizeContextEnhancementConfig(config);
4009
4205
  const label = contextEnhancementLabel(groupSupported ? saved : {
4010
4206
  ...saved,
4011
4207
  group: { ...saved.group, enabled: false }
4012
4208
  });
4013
4209
  return h2(
4014
- React9.Fragment,
4210
+ React10.Fragment,
4015
4211
  null,
4016
4212
  h2(
4017
4213
  "button",
@@ -4045,10 +4241,10 @@ function ContextEnhancementEditor({ config, groupSupported = true, disabled = fa
4045
4241
  }
4046
4242
 
4047
4243
  // plugin-src/client/workspace-snapshot-fence.js
4048
- var React10 = __toESM(require("react"), 1);
4244
+ var React11 = __toESM(require("react"), 1);
4049
4245
  function useWorkspaceSnapshotFence() {
4050
- const state = React10.useRef({ version: 0, pendingMutations: 0 });
4051
- return React10.useMemo(() => Object.freeze({
4246
+ const state = React11.useRef({ version: 0, pendingMutations: 0 });
4247
+ return React11.useMemo(() => Object.freeze({
4052
4248
  beginStatus() {
4053
4249
  return state.current.pendingMutations === 0 ? state.current.version : null;
4054
4250
  },
@@ -4071,8 +4267,8 @@ function useWorkspaceSnapshotFence() {
4071
4267
  }
4072
4268
 
4073
4269
  // plugin-src/client/channel-card-meta.js
4074
- var React11 = __toESM(require("react"), 1);
4075
- var BotSettingsContext = React11.createContext(Object.freeze({
4270
+ var React12 = __toESM(require("react"), 1);
4271
+ var BotSettingsContext = React12.createContext(Object.freeze({
4076
4272
  openBotSettings() {
4077
4273
  }
4078
4274
  }));
@@ -4102,8 +4298,8 @@ function BotSettingsButton({
4102
4298
  accessPolicy,
4103
4299
  channelSettings
4104
4300
  }) {
4105
- const { openBotSettings } = React11.useContext(BotSettingsContext);
4106
- const tooltipId = React11.useId();
4301
+ const { openBotSettings } = React12.useContext(BotSettingsContext);
4302
+ const tooltipId = React12.useId();
4107
4303
  return h2(
4108
4304
  "span",
4109
4305
  { className: "dim-botSettingsAction" },
@@ -4143,7 +4339,7 @@ function messageErrorTime(value) {
4143
4339
  }
4144
4340
  }
4145
4341
  function ChannelListHeading({ className = "", id: id6, title, connectionLabel }) {
4146
- const helpId = React11.useId();
4342
+ const helpId = React12.useId();
4147
4343
  return h2(
4148
4344
  "div",
4149
4345
  { className: `${className} dim-listHeading`.trim() },
@@ -4224,7 +4420,7 @@ function LastMessageErrorSummary({ className = "", error }) {
4224
4420
  h2("span", null, "\u53C2\u8003\u53F7"),
4225
4421
  ` ${error.referenceId}`,
4226
4422
  occurredAt ? h2(
4227
- React11.Fragment,
4423
+ React12.Fragment,
4228
4424
  null,
4229
4425
  " \xB7 ",
4230
4426
  h2("time", { dateTime: new Date(error.at).toISOString() }, occurredAt)
@@ -4387,7 +4583,7 @@ function DingtalkIcon({ size = 28 }) {
4387
4583
  d: "M37.05 22.783c-6.758-5.216-14.378-12.128-22.73-19.538-.655-.585-1.242-.354-1.536.42-1.88 4.973-.058 9.386 2.889 11.932s7.368 4.912 10.058 6.155c.105.049.013.203-.093.163-4.953-2.182-8.397-3.765-13.07-7.368-.497-.388-1.01-.242-1.07.521-.384 4.748 2.657 8.483 6.058 9.745 2.1.781 4.398 1.212 6.53 1.474.109.015.084.178-.027.178-2.747.01-6.058-.654-8.935-1.751-.606-.233-.818.25-.722.633.491 2.008 2.974 5.076 6.926 5.73a12 12 0 0 0 2.228.115c.164 0 .208.089.154.217q-2.685 4.6-2.803 4.797c-.091.152-.036.275.156.275h3.543c.164 0 .264.106.18.246l-4.958 8.196c-.191.328.035.565.395.301s15.212-11.133 15.636-11.448c.195-.142.148-.327-.124-.327h-3.18c-.206 0-.252-.14-.111-.28.14-.141 3.602-3.594 4.837-4.888 1.283-1.35 1.938-3.825-.231-5.498"
4388
4584
  }));
4389
4585
  }
4390
- var Button = React12.forwardRef(function Button2({ children, kind = "secondary", className = "", ...props }, ref) {
4586
+ var Button = React13.forwardRef(function Button2({ children, kind = "secondary", className = "", ...props }, ref) {
4391
4587
  return h2("button", {
4392
4588
  ...props,
4393
4589
  ref,
@@ -4483,13 +4679,13 @@ function EmptyView({ busy, onStart }) {
4483
4679
  );
4484
4680
  }
4485
4681
  function QrPanel({ provision, now, busy, onRefresh, onCancel }) {
4486
- const [imageFailed, setImageFailed] = React12.useState(false);
4682
+ const [imageFailed, setImageFailed] = React13.useState(false);
4487
4683
  const source = safeQrSource(provision.qrCodeDataUrl);
4488
4684
  const remaining = Math.max(0, provision.expiresAt - now);
4489
4685
  const expired = remaining === 0 || provision.status === "expired";
4490
4686
  const duration = Math.max(1, provision.durationMs ?? 10 * 6e4);
4491
4687
  const progress = Math.round(Math.min(1, remaining / duration) * 100);
4492
- React12.useEffect(() => setImageFailed(false), [source]);
4688
+ React13.useEffect(() => setImageFailed(false), [source]);
4493
4689
  return h2(
4494
4690
  "div",
4495
4691
  { className: "ddt-card dim-surfaceCard" },
@@ -4581,7 +4777,7 @@ function ConnectionErrorDiagnostic({ error }) {
4581
4777
  { className: "ddt-errorCode" },
4582
4778
  h2("span", null, "\u9519\u8BEF\u7801"),
4583
4779
  `: ${error.code}`,
4584
- error.referenceId ? h2(React12.Fragment, null, " \xB7 ", h2("span", null, "\u53C2\u8003\u53F7"), `: ${error.referenceId}`) : null
4780
+ error.referenceId ? h2(React13.Fragment, null, " \xB7 ", h2("span", null, "\u53C2\u8003\u53F7"), `: ${error.referenceId}`) : null
4585
4781
  )
4586
4782
  );
4587
4783
  }
@@ -4604,7 +4800,7 @@ function ProvisionError({ provision, busy, onRetry, onClose }) {
4604
4800
  "div",
4605
4801
  { className: "ddt-actions dim-viewActions" },
4606
4802
  connectionFailed ? h2(Button, { kind: "primary", onClick: onClose, disabled: busy }, "\u67E5\u770B\u5DF2\u4FDD\u5B58\u7684\u673A\u5668\u4EBA") : h2(
4607
- React12.Fragment,
4803
+ React13.Fragment,
4608
4804
  null,
4609
4805
  h2(Button, { kind: "primary", onClick: onRetry, disabled: busy }, "\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801"),
4610
4806
  h2(Button, { onClick: onClose, disabled: busy }, "\u5173\u95ED")
@@ -4626,8 +4822,8 @@ function checkedTime(value) {
4626
4822
  }
4627
4823
  }
4628
4824
  function RemoveConfirmation({ account, busy, onConfirm, onCancel }) {
4629
- const cancelRef = React12.useRef(null);
4630
- React12.useEffect(() => cancelRef.current?.focus(), []);
4825
+ const cancelRef = React13.useRef(null);
4826
+ React13.useEffect(() => cancelRef.current?.focus(), []);
4631
4827
  return h2(
4632
4828
  "div",
4633
4829
  {
@@ -4659,6 +4855,7 @@ function AccountCard({
4659
4855
  removing,
4660
4856
  onReconnect,
4661
4857
  onWorkspaceSave,
4858
+ onAliasSave,
4662
4859
  onModelSave,
4663
4860
  onAgentPresetSave,
4664
4861
  onContextEnhancementSave,
@@ -4690,7 +4887,7 @@ function AccountCard({
4690
4887
  h2(
4691
4888
  "div",
4692
4889
  { className: "dim-botName" },
4693
- h2("h3", { title: account.bot.name }, account.bot.name),
4890
+ h2(BotName, { bot: account.bot, disabled: Boolean(busy), onSave: onAliasSave }),
4694
4891
  h2("p", { title: account.bot.clientIdMasked }, account.bot.clientIdMasked)
4695
4892
  )
4696
4893
  ),
@@ -4805,6 +5002,7 @@ function AccountList(props) {
4805
5002
  removing: props.removeTarget === account.botId,
4806
5003
  onReconnect: () => props.onReconnect(account),
4807
5004
  onWorkspaceSave: (workspace) => props.onWorkspaceSave(account, workspace),
5005
+ onAliasSave: (alias) => props.onAliasSave(account, alias),
4808
5006
  onModelSave: (model) => props.onModelSave(account, model),
4809
5007
  onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(account, agentPreset),
4810
5008
  onContextEnhancementSave: (config) => props.onContextEnhancementSave(account, config),
@@ -4817,7 +5015,7 @@ function AccountList(props) {
4817
5015
  }
4818
5016
  var EMPTY_TOTALS = Object.freeze({ configured: 0, connected: 0 });
4819
5017
  function DingtalkSettingsTab({ rpcCall }) {
4820
- const [model, setModel] = React12.useState({
5018
+ const [model, setModel] = React13.useState({
4821
5019
  phase: "loading",
4822
5020
  bots: [],
4823
5021
  totals: EMPTY_TOTALS,
@@ -4826,22 +5024,22 @@ function DingtalkSettingsTab({ rpcCall }) {
4826
5024
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
4827
5025
  modelCatalog: EMPTY_MODEL_CATALOG
4828
5026
  });
4829
- const [provision, setProvision] = React12.useState(null);
4830
- const [busy, setBusy] = React12.useState(false);
4831
- const [busyByBot, setBusyByBot] = React12.useState({});
4832
- const [feedbackByBot, setFeedbackByBot] = React12.useState({});
4833
- const [removeTarget, setRemoveTarget] = React12.useState(null);
4834
- const [credentialOpen, setCredentialOpen] = React12.useState(false);
4835
- const [credentialError, setCredentialError] = React12.useState(null);
4836
- const [notice, setNotice] = React12.useState("");
4837
- const [now, setNow] = React12.useState(() => Date.now());
4838
- const addButtonRef = React12.useRef(null);
4839
- const mountedRef = React12.useRef(true);
4840
- const statusRequestRef = React12.useRef(0);
5027
+ const [provision, setProvision] = React13.useState(null);
5028
+ const [busy, setBusy] = React13.useState(false);
5029
+ const [busyByBot, setBusyByBot] = React13.useState({});
5030
+ const [feedbackByBot, setFeedbackByBot] = React13.useState({});
5031
+ const [removeTarget, setRemoveTarget] = React13.useState(null);
5032
+ const [credentialOpen, setCredentialOpen] = React13.useState(false);
5033
+ const [credentialError, setCredentialError] = React13.useState(null);
5034
+ const [notice, setNotice] = React13.useState("");
5035
+ const [now, setNow] = React13.useState(() => Date.now());
5036
+ const addButtonRef = React13.useRef(null);
5037
+ const mountedRef = React13.useRef(true);
5038
+ const statusRequestRef = React13.useRef(0);
4841
5039
  const workspaceFence = useWorkspaceSnapshotFence();
4842
- const noticeFrameRef = React12.useRef(null);
4843
- const focusFrameRef = React12.useRef(null);
4844
- React12.useEffect(() => {
5040
+ const noticeFrameRef = React13.useRef(null);
5041
+ const focusFrameRef = React13.useRef(null);
5042
+ React13.useEffect(() => {
4845
5043
  mountedRef.current = true;
4846
5044
  return () => {
4847
5045
  mountedRef.current = false;
@@ -4856,8 +5054,8 @@ function DingtalkSettingsTab({ rpcCall }) {
4856
5054
  }
4857
5055
  };
4858
5056
  }, []);
4859
- React12.useEffect(() => installDingtalkStyles(), []);
4860
- const announce = React12.useCallback((message) => {
5057
+ React13.useEffect(() => installDingtalkStyles(), []);
5058
+ const announce = React13.useCallback((message) => {
4861
5059
  if (!mountedRef.current) return;
4862
5060
  if (noticeFrameRef.current !== null) {
4863
5061
  window.cancelAnimationFrame(noticeFrameRef.current);
@@ -4871,7 +5069,7 @@ function DingtalkSettingsTab({ rpcCall }) {
4871
5069
  });
4872
5070
  }
4873
5071
  }, []);
4874
- const discardStaleFeedback = React12.useCallback((snapshot) => {
5072
+ const discardStaleFeedback = React13.useCallback((snapshot) => {
4875
5073
  const botsById = new Map(snapshot.bots.map((bot) => [bot.botId, bot]));
4876
5074
  setFeedbackByBot((current) => {
4877
5075
  let changed = false;
@@ -4886,7 +5084,7 @@ function DingtalkSettingsTab({ rpcCall }) {
4886
5084
  return changed ? next : current;
4887
5085
  });
4888
5086
  }, []);
4889
- const focusAddButton = React12.useCallback(() => {
5087
+ const focusAddButton = React13.useCallback(() => {
4890
5088
  if (!mountedRef.current) return;
4891
5089
  if (focusFrameRef.current !== null) window.cancelAnimationFrame(focusFrameRef.current);
4892
5090
  focusFrameRef.current = window.requestAnimationFrame(() => {
@@ -4894,11 +5092,11 @@ function DingtalkSettingsTab({ rpcCall }) {
4894
5092
  if (mountedRef.current) addButtonRef.current?.focus();
4895
5093
  });
4896
5094
  }, []);
4897
- const invoke = React12.useCallback(async (endpoint, payload = {}, signal) => {
5095
+ const invoke = React13.useCallback(async (endpoint, payload = {}, signal) => {
4898
5096
  if (typeof rpcCall !== "function") throw new TypeError("\u9489\u9489\u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
4899
5097
  return unwrapRpcResult(await rpcCall(endpoint, payload, signal));
4900
5098
  }, [rpcCall]);
4901
- const loadStatus = React12.useCallback(async ({
5099
+ const loadStatus = React13.useCallback(async ({
4902
5100
  signal,
4903
5101
  silent = false,
4904
5102
  restoreProvisioning = false
@@ -4943,12 +5141,12 @@ function DingtalkSettingsTab({ rpcCall }) {
4943
5141
  return void 0;
4944
5142
  }
4945
5143
  }, [discardStaleFeedback, invoke, workspaceFence]);
4946
- React12.useEffect(() => {
5144
+ React13.useEffect(() => {
4947
5145
  const controller = new AbortController();
4948
5146
  void loadStatus({ signal: controller.signal, restoreProvisioning: true });
4949
5147
  return () => controller.abort();
4950
5148
  }, [loadStatus]);
4951
- React12.useEffect(() => {
5149
+ React13.useEffect(() => {
4952
5150
  if (model.phase !== "ready") return void 0;
4953
5151
  const controller = new AbortController();
4954
5152
  let running = false;
@@ -4967,14 +5165,14 @@ function DingtalkSettingsTab({ rpcCall }) {
4967
5165
  window.clearInterval(timer);
4968
5166
  };
4969
5167
  }, [loadStatus, model.phase]);
4970
- React12.useEffect(() => {
5168
+ React13.useEffect(() => {
4971
5169
  if (!provision || !ACTIVE_PROVISION_STATES.has(provision.status)) return void 0;
4972
5170
  const timer = window.setInterval(() => {
4973
5171
  if (mountedRef.current) setNow(Date.now());
4974
5172
  }, 1e3);
4975
5173
  return () => window.clearInterval(timer);
4976
5174
  }, [provision?.attemptId, provision?.status]);
4977
- const startProvisioning = React12.useCallback(async ({ replace = false } = {}) => {
5175
+ const startProvisioning = React13.useCallback(async ({ replace = false } = {}) => {
4978
5176
  if (!mountedRef.current) return;
4979
5177
  setCredentialOpen(false);
4980
5178
  setCredentialError(null);
@@ -5012,7 +5210,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5012
5210
  if (mountedRef.current) setBusy(false);
5013
5211
  }
5014
5212
  }, [announce, invoke, provision?.attemptId]);
5015
- const bindCredentials = React12.useCallback(async ({ identity, secret }) => {
5213
+ const bindCredentials = React13.useCallback(async ({ identity, secret }) => {
5016
5214
  if (!mountedRef.current) return;
5017
5215
  const snapshotVersion = workspaceFence.beginMutation();
5018
5216
  setBusy(true);
@@ -5045,7 +5243,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5045
5243
  if (mountedRef.current) setBusy(false);
5046
5244
  }
5047
5245
  }, [announce, discardStaleFeedback, invoke, loadStatus, workspaceFence]);
5048
- const cancelProvisioning = React12.useCallback(async () => {
5246
+ const cancelProvisioning = React13.useCallback(async () => {
5049
5247
  if (!mountedRef.current) return;
5050
5248
  setBusy(true);
5051
5249
  try {
@@ -5063,7 +5261,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5063
5261
  if (mountedRef.current) setBusy(false);
5064
5262
  }
5065
5263
  }, [announce, focusAddButton, invoke, provision?.attemptId, provision?.status]);
5066
- React12.useEffect(() => {
5264
+ React13.useEffect(() => {
5067
5265
  const attemptId = provision?.attemptId;
5068
5266
  if (!attemptId || !ACTIVE_PROVISION_STATES.has(provision.status)) return void 0;
5069
5267
  const controller = new AbortController();
@@ -5126,7 +5324,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5126
5324
  timer = null;
5127
5325
  };
5128
5326
  }, [announce, invoke, loadStatus, provision?.attemptId, provision?.pollIntervalMs, provision?.status]);
5129
- const setBotBusy = React12.useCallback((botId, operation) => {
5327
+ const setBotBusy = React13.useCallback((botId, operation) => {
5130
5328
  if (!mountedRef.current) return;
5131
5329
  setBusyByBot((current) => {
5132
5330
  const next = { ...current };
@@ -5135,7 +5333,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5135
5333
  return next;
5136
5334
  });
5137
5335
  }, []);
5138
- const runBotAction = React12.useCallback(async ({ account, operation, endpoint, payload, success }) => {
5336
+ const runBotAction = React13.useCallback(async ({ account, operation, endpoint, payload, success }) => {
5139
5337
  if (!mountedRef.current) return void 0;
5140
5338
  const snapshotVersion = workspaceFence.beginMutation();
5141
5339
  setBotBusy(account.botId, operation);
@@ -5191,7 +5389,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5191
5389
  if (mountedRef.current) setBotBusy(account.botId, null);
5192
5390
  }
5193
5391
  }, [announce, discardStaleFeedback, invoke, loadStatus, setBotBusy, workspaceFence]);
5194
- const reconnect = React12.useCallback((account) => runBotAction({
5392
+ const reconnect = React13.useCallback((account) => runBotAction({
5195
5393
  account,
5196
5394
  operation: "reconnect",
5197
5395
  endpoint: DINGTALK_ENDPOINTS.reconnectBot,
@@ -5202,7 +5400,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5202
5400
  return connectionTestFeedback(snapshot.testMessage) ?? "\u9489\u9489\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\u3002";
5203
5401
  }
5204
5402
  }), [runBotAction]);
5205
- const saveWorkspace = React12.useCallback(async (account, workspace) => {
5403
+ const saveWorkspace = React13.useCallback(async (account, workspace) => {
5206
5404
  const workspaceVersion = workspaceFence.beginMutation();
5207
5405
  setBotBusy(account.botId, "workspace");
5208
5406
  try {
@@ -5228,7 +5426,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5228
5426
  if (mountedRef.current) setBotBusy(account.botId, null);
5229
5427
  }
5230
5428
  }, [discardStaleFeedback, invoke, loadStatus, setBotBusy, workspaceFence]);
5231
- const saveBotSetting = React12.useCallback(async (account, operation, endpoint, payload) => {
5429
+ const saveBotSetting = React13.useCallback(async (account, operation, endpoint, payload) => {
5232
5430
  const snapshotVersion = workspaceFence.beginMutation();
5233
5431
  setBotBusy(account.botId, operation);
5234
5432
  try {
@@ -5254,7 +5452,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5254
5452
  if (mountedRef.current) setBotBusy(account.botId, null);
5255
5453
  }
5256
5454
  }, [discardStaleFeedback, invoke, loadStatus, setBotBusy, workspaceFence]);
5257
- const remove = React12.useCallback(async (account) => {
5455
+ const remove = React13.useCallback(async (account) => {
5258
5456
  const snapshot = await runBotAction({
5259
5457
  account,
5260
5458
  operation: "delete",
@@ -5340,7 +5538,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5340
5538
  h2(Button, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
5341
5539
  )
5342
5540
  ) : h2(
5343
- React12.Fragment,
5541
+ React13.Fragment,
5344
5542
  null,
5345
5543
  credentialView,
5346
5544
  provisionView,
@@ -5352,6 +5550,12 @@ function DingtalkSettingsTab({ rpcCall }) {
5352
5550
  removeTarget,
5353
5551
  onReconnect: (account) => void reconnect(account),
5354
5552
  onWorkspaceSave: saveWorkspace,
5553
+ onAliasSave: (account, alias) => saveBotSetting(
5554
+ account,
5555
+ "alias",
5556
+ DINGTALK_ENDPOINTS.setAlias,
5557
+ { alias }
5558
+ ),
5355
5559
  onModelSave: (account, selectedModel) => saveBotSetting(
5356
5560
  account,
5357
5561
  "model",
@@ -5404,7 +5608,8 @@ var TOKEN_BOT_ENDPOINTS = Object.freeze({
5404
5608
  setModel: SET_MODEL_ENDPOINT,
5405
5609
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
5406
5610
  setContextEnhancement: "bot.context-enhancement.set",
5407
- setAccessPolicy: "bot.access-policy.set"
5611
+ setAccessPolicy: "bot.access-policy.set",
5612
+ setAlias: "bot.alias.set"
5408
5613
  });
5409
5614
  function createTokenChannelApi(channel5, connectionSummary, {
5410
5615
  normalizeBotExtension = () => ({})
@@ -5435,6 +5640,7 @@ function createTokenChannelApi(channel5, connectionSummary, {
5435
5640
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
5436
5641
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
5437
5642
  bot: {
5643
+ ...normalizeBotAlias(value.bot),
5438
5644
  name: text2(value.bot?.name, `${channel5}\u673A\u5668\u4EBA`, 100),
5439
5645
  username: text2(value.bot?.username, "", 100),
5440
5646
  idMasked: text2(value.bot?.idMasked, "\u673A\u5668\u4EBA\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58", 140)
@@ -5485,8 +5691,8 @@ var normalizeSnapshot2 = api.normalizeSnapshot;
5485
5691
  var presentError2 = api.presentError;
5486
5692
 
5487
5693
  // plugin-src/client/channels/shared/token-channel.js
5488
- var React13 = __toESM(require("react"), 1);
5489
- var Button3 = React13.forwardRef(function Button4({ children, kind = "secondary", className = "", ...props }, ref) {
5694
+ var React14 = __toESM(require("react"), 1);
5695
+ var Button3 = React14.forwardRef(function Button4({ children, kind = "secondary", className = "", ...props }, ref) {
5490
5696
  return h2("button", {
5491
5697
  ...props,
5492
5698
  ref,
@@ -5538,7 +5744,7 @@ function createTokenChannelSettings(definition) {
5538
5744
  AccountSettings = null,
5539
5745
  accountSettingsEndpoint = null
5540
5746
  } = definition;
5541
- function AccountCard6({ account, busy, testNotice, removing, onReconnect, onWorkspaceSave, onModelSave, onAgentPresetSave, onContextEnhancementSave, onAccountSettingsSave, onRequestRemove, onConfirmRemove, onCancelRemove }) {
5747
+ function AccountCard6({ account, busy, testNotice, removing, onReconnect, onWorkspaceSave, onAliasSave, onModelSave, onAgentPresetSave, onContextEnhancementSave, onAccountSettingsSave, onRequestRemove, onConfirmRemove, onCancelRemove }) {
5542
5748
  const state = busy === "reconnect" ? "connecting" : account.state;
5543
5749
  const tone = account.connected ? "success" : state === "error" ? "error" : "warning";
5544
5750
  const stateLabel2 = account.connected ? "\u8FD0\u884C\u6B63\u5E38" : state === "connecting" ? "\u6B63\u5728\u8FDE\u63A5" : "\u8FDE\u63A5\u672A\u5C31\u7EEA";
@@ -5568,7 +5774,7 @@ function createTokenChannelSettings(definition) {
5568
5774
  h2(
5569
5775
  "div",
5570
5776
  { className: "dim-botName" },
5571
- h2("h3", null, account.bot.name),
5777
+ h2(BotName, { bot: account.bot, disabled: Boolean(busy), onSave: onAliasSave }),
5572
5778
  h2("p", null, identity)
5573
5779
  )
5574
5780
  ),
@@ -5680,7 +5886,7 @@ function createTokenChannelSettings(definition) {
5680
5886
  );
5681
5887
  }
5682
5888
  function SettingsTab({ rpcCall }) {
5683
- const [model, setModel] = React13.useState({
5889
+ const [model, setModel] = React14.useState({
5684
5890
  phase: "loading",
5685
5891
  bots: [],
5686
5892
  totals: { configured: 0, connected: 0 },
@@ -5689,15 +5895,15 @@ function createTokenChannelSettings(definition) {
5689
5895
  modelCatalog: EMPTY_MODEL_CATALOG,
5690
5896
  permissions: null
5691
5897
  });
5692
- const [credentialOpen, setCredentialOpen] = React13.useState(false);
5693
- const [credentialError, setCredentialError] = React13.useState(null);
5694
- const [busy, setBusy] = React13.useState(false);
5695
- const [busyByBot, setBusyByBot] = React13.useState({});
5696
- const [testNoticeByBot, setTestNoticeByBot] = React13.useState({});
5697
- const [removeTarget, setRemoveTarget] = React13.useState(null);
5698
- const mounted = React13.useRef(true);
5898
+ const [credentialOpen, setCredentialOpen] = React14.useState(false);
5899
+ const [credentialError, setCredentialError] = React14.useState(null);
5900
+ const [busy, setBusy] = React14.useState(false);
5901
+ const [busyByBot, setBusyByBot] = React14.useState({});
5902
+ const [testNoticeByBot, setTestNoticeByBot] = React14.useState({});
5903
+ const [removeTarget, setRemoveTarget] = React14.useState(null);
5904
+ const mounted = React14.useRef(true);
5699
5905
  const workspaceFence = useWorkspaceSnapshotFence();
5700
- React13.useEffect(() => {
5906
+ React14.useEffect(() => {
5701
5907
  const disposeDingtalk = installDingtalkStyles();
5702
5908
  const disposeChannel = installStyles();
5703
5909
  mounted.current = true;
@@ -5707,11 +5913,11 @@ function createTokenChannelSettings(definition) {
5707
5913
  disposeDingtalk();
5708
5914
  };
5709
5915
  }, []);
5710
- const invoke = React13.useCallback(async (endpoint, payload = {}, signal) => {
5916
+ const invoke = React14.useCallback(async (endpoint, payload = {}, signal) => {
5711
5917
  if (typeof rpcCall !== "function") throw new TypeError(`${channel5} \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5`);
5712
5918
  return api5.unwrapRpcResult(await rpcCall(endpoint, payload, signal));
5713
5919
  }, [rpcCall]);
5714
- const loadStatus = React13.useCallback(async ({ signal, silent = false } = {}) => {
5920
+ const loadStatus = React14.useCallback(async ({ signal, silent = false } = {}) => {
5715
5921
  const workspaceVersion = workspaceFence.beginStatus();
5716
5922
  if (workspaceVersion === null) return;
5717
5923
  if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
@@ -5737,12 +5943,12 @@ function createTokenChannelSettings(definition) {
5737
5943
  }
5738
5944
  }
5739
5945
  }, [invoke, workspaceFence]);
5740
- React13.useEffect(() => {
5946
+ React14.useEffect(() => {
5741
5947
  const controller = new AbortController();
5742
5948
  void loadStatus({ signal: controller.signal });
5743
5949
  return () => controller.abort();
5744
5950
  }, [loadStatus]);
5745
- React13.useEffect(() => {
5951
+ React14.useEffect(() => {
5746
5952
  if (model.phase !== "ready") return void 0;
5747
5953
  const controller = new AbortController();
5748
5954
  const timer = window.setInterval(
@@ -5754,7 +5960,7 @@ function createTokenChannelSettings(definition) {
5754
5960
  window.clearInterval(timer);
5755
5961
  };
5756
5962
  }, [loadStatus, model.phase]);
5757
- const bindCredentials = React13.useCallback(async (values) => {
5963
+ const bindCredentials = React14.useCallback(async (values) => {
5758
5964
  const snapshotVersion = workspaceFence.beginMutation();
5759
5965
  setBusy(true);
5760
5966
  setCredentialError(null);
@@ -5784,7 +5990,7 @@ function createTokenChannelSettings(definition) {
5784
5990
  if (mounted.current) setBusy(false);
5785
5991
  }
5786
5992
  }, [invoke, loadStatus, workspaceFence]);
5787
- const botAction = React13.useCallback(async (account, operation, endpoint, payload) => {
5993
+ const botAction = React14.useCallback(async (account, operation, endpoint, payload) => {
5788
5994
  const snapshotVersion = workspaceFence.beginMutation();
5789
5995
  setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
5790
5996
  try {
@@ -5849,6 +6055,12 @@ function createTokenChannelSettings(definition) {
5849
6055
  endpoints.setWorkspace,
5850
6056
  { botId: account.botId, workspace }
5851
6057
  ),
6058
+ onAliasSave: (alias) => botAction(
6059
+ account,
6060
+ "alias",
6061
+ endpoints.setAlias,
6062
+ { botId: account.botId, alias }
6063
+ ),
5852
6064
  onModelSave: (selectedModel) => botAction(
5853
6065
  account,
5854
6066
  "model",
@@ -5936,7 +6148,7 @@ function createTokenChannelSettings(definition) {
5936
6148
  h2(Button3, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
5937
6149
  )
5938
6150
  ) : h2(
5939
- React13.Fragment,
6151
+ React14.Fragment,
5940
6152
  null,
5941
6153
  credentialOpen ? CredentialPanel ? h2(CredentialPanel, {
5942
6154
  channel: channel5,
@@ -6039,7 +6251,7 @@ var DiscordSettingsTab = channel.SettingsTab;
6039
6251
  var DiscordAccountCard = channel.AccountCard;
6040
6252
 
6041
6253
  // plugin-src/client/channels/feishu/index.js
6042
- var React15 = __toESM(require("react"), 1);
6254
+ var React16 = __toESM(require("react"), 1);
6043
6255
 
6044
6256
  // src/channels/feishu/step-push-mode.mjs
6045
6257
  var FEISHU_STEP_PUSH_MODES = Object.freeze({
@@ -6069,6 +6281,7 @@ var FEISHU_ENDPOINTS = Object.freeze({
6069
6281
  setAgentPreset: "bot.preset.set",
6070
6282
  setContextEnhancement: "bot.context-enhancement.set",
6071
6283
  setAccessPolicy: "bot.access-policy.set",
6284
+ setAlias: "bot.alias.set",
6072
6285
  setGroupResponseMode: "bot.group-response-mode.set",
6073
6286
  setGroupTopicReply: "bot.group-topic-reply.set",
6074
6287
  setStepPush: "bot.step-push.set",
@@ -6174,6 +6387,7 @@ function normalizeProvisioning2(value, now = Date.now()) {
6174
6387
  function normalizeBot2(value) {
6175
6388
  const source = isRecord3(value) ? value : {};
6176
6389
  return {
6390
+ ...normalizeBotAlias(source),
6177
6391
  name: optionalString2(source.name) ?? "\u98DE\u4E66\u673A\u5668\u4EBA",
6178
6392
  avatarUrl: optionalString2(source.avatarUrl),
6179
6393
  appIdMasked: optionalString2(source.appIdMasked),
@@ -6322,7 +6536,7 @@ function formatRemaining2(milliseconds) {
6322
6536
  }
6323
6537
 
6324
6538
  // plugin-src/client/lifecycle.js
6325
- var React14 = __toESM(require("react"), 1);
6539
+ var React15 = __toESM(require("react"), 1);
6326
6540
  function createPollScheduler({ setTimeoutFn, clearTimeoutFn }) {
6327
6541
  let disposed = false;
6328
6542
  let timer;
@@ -6384,8 +6598,8 @@ function createAnimationFrameScheduler({ requestFrame, cancelFrame }) {
6384
6598
  };
6385
6599
  }
6386
6600
  function useAnimationFrameScheduler() {
6387
- const schedulerRef = React14.useRef(null);
6388
- React14.useEffect(() => {
6601
+ const schedulerRef = React15.useRef(null);
6602
+ React15.useEffect(() => {
6389
6603
  const scheduler = createAnimationFrameScheduler({
6390
6604
  requestFrame: (callback) => window.requestAnimationFrame(callback),
6391
6605
  cancelFrame: (frame) => window.cancelAnimationFrame(frame)
@@ -6396,7 +6610,7 @@ function useAnimationFrameScheduler() {
6396
6610
  if (schedulerRef.current === scheduler) schedulerRef.current = null;
6397
6611
  };
6398
6612
  }, []);
6399
- return React14.useCallback(
6613
+ return React15.useCallback(
6400
6614
  (callback, key) => schedulerRef.current?.schedule(callback, key) ?? false,
6401
6615
  []
6402
6616
  );
@@ -6471,7 +6685,7 @@ function QrIcon({ size = 58 }) {
6471
6685
  fill: "currentColor"
6472
6686
  }));
6473
6687
  }
6474
- var Button5 = React15.forwardRef(function Button6({ children, kind = "secondary", size, icon, className = "", ...props }, ref) {
6688
+ var Button5 = React16.forwardRef(function Button6({ children, kind = "secondary", size, icon, className = "", ...props }, ref) {
6475
6689
  return h2("button", {
6476
6690
  ...props,
6477
6691
  ref,
@@ -6588,7 +6802,7 @@ function safeQrSource2(value) {
6588
6802
  return /^data:image\/(?:png|webp|svg\+xml)(?:;charset=[^;,]+)?;base64,/i.test(value) ? value : void 0;
6589
6803
  }
6590
6804
  function QrPane({ provision, now, onRefresh, onCancel, busy }) {
6591
- const [imageFailed, setImageFailed] = React15.useState(false);
6805
+ const [imageFailed, setImageFailed] = React16.useState(false);
6592
6806
  const qrSource = safeQrSource2(provision.qrCodeDataUrl);
6593
6807
  const href = safeVerificationHref(provision.verificationUrl);
6594
6808
  const remaining = Math.max(0, provision.expiresAt - now);
@@ -6597,7 +6811,7 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
6597
6811
  const repairing = isCallbackRepair(provision);
6598
6812
  const grantingGroupMessages = isGroupMessagePermission(provision);
6599
6813
  const botName = provision.botName ?? "\u6B64\u673A\u5668\u4EBA";
6600
- React15.useEffect(() => setImageFailed(false), [qrSource]);
6814
+ React16.useEffect(() => setImageFailed(false), [qrSource]);
6601
6815
  return h2(
6602
6816
  "div",
6603
6817
  { className: "bxf-card bxf-provisionCard dim-surfaceCard" },
@@ -6760,11 +6974,11 @@ function connectionTestNotice2(value) {
6760
6974
  return value?.testMessage ? "\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002" : null;
6761
6975
  }
6762
6976
  function RemoveConfirmation2({ bot, busy, onConfirm, onCancel }) {
6763
- const cancelRef = React15.useRef(null);
6977
+ const cancelRef = React16.useRef(null);
6764
6978
  const idPart = bot.botId.replace(/[^a-zA-Z0-9_-]/g, "-");
6765
6979
  const titleId = `bxf-remove-title-${idPart}`;
6766
6980
  const descriptionId = `bxf-remove-description-${idPart}`;
6767
- React15.useEffect(() => cancelRef.current?.focus(), []);
6981
+ React16.useEffect(() => cancelRef.current?.focus(), []);
6768
6982
  return h2(
6769
6983
  "div",
6770
6984
  {
@@ -6798,11 +7012,11 @@ function RemoveConfirmation2({ bot, busy, onConfirm, onCancel }) {
6798
7012
  );
6799
7013
  }
6800
7014
  function StepPushEditor({ value = false, mode = "post", disabled = false, onSave, onModeSave }) {
6801
- const titleId = React15.useId();
7015
+ const titleId = React16.useId();
6802
7016
  const helpId = `${titleId}-help`;
6803
7017
  const current = value === true ? mode : "off";
6804
- const [saving, setSaving] = React15.useState(false);
6805
- const [error, setError] = React15.useState(null);
7018
+ const [saving, setSaving] = React16.useState(false);
7019
+ const [error, setError] = React16.useState(null);
6806
7020
  const save = async (run) => {
6807
7021
  if (saving || disabled) return;
6808
7022
  setSaving(true);
@@ -6892,6 +7106,7 @@ function BotCard({
6892
7106
  onReconnect,
6893
7107
  onRepairCallback,
6894
7108
  onWorkspaceSave,
7109
+ onAliasSave,
6895
7110
  onModelSave,
6896
7111
  onAgentPresetSave,
6897
7112
  onContextEnhancementSave,
@@ -6904,7 +7119,7 @@ function BotCard({
6904
7119
  removeButtonRef
6905
7120
  }) {
6906
7121
  const { bot, health, state, connected } = connection;
6907
- const repairTooltipId = React15.useId();
7122
+ const repairTooltipId = React16.useId();
6908
7123
  const stateForDisplay = busy === "reconnect" ? "connecting" : state;
6909
7124
  const tone = stateForDisplay === "connected" ? "success" : stateForDisplay === "connecting" ? "warning" : "error";
6910
7125
  const summary2 = actionError?.message ?? connection.error?.message ?? (connected ? null : health.summary);
@@ -6939,7 +7154,7 @@ function BotCard({
6939
7154
  h2(
6940
7155
  "div",
6941
7156
  { className: "bxf-botName dim-botName" },
6942
- h2("h3", { id: titleId, title: bot.name }, bot.name),
7157
+ h2(BotName, { bot, id: titleId, disabled: Boolean(busy), onSave: onAliasSave }),
6943
7158
  h2("p", { title: bot.appIdMasked }, bot.appIdMasked ?? "\u5E94\u7528\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58")
6944
7159
  )
6945
7160
  ),
@@ -7113,6 +7328,7 @@ function BotList(props) {
7113
7328
  onReconnect: () => props.onReconnect(bot),
7114
7329
  onRepairCallback: () => props.onRepairCallback(bot),
7115
7330
  onWorkspaceSave: (workspace) => props.onWorkspaceSave(bot, workspace),
7331
+ onAliasSave: (alias) => props.onAliasSave(bot, alias),
7116
7332
  onModelSave: (model) => props.onModelSave(bot, model),
7117
7333
  onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(bot, agentPreset),
7118
7334
  onContextEnhancementSave: (config) => props.onContextEnhancementSave(bot, config),
@@ -7181,7 +7397,7 @@ function mergeFeishuSnapshotState(current, snapshot, { restoreProvisioning = fal
7181
7397
  };
7182
7398
  }
7183
7399
  function FeishuSettingsTab({ rpcCall }) {
7184
- const [model, setModel] = React15.useState({
7400
+ const [model, setModel] = React16.useState({
7185
7401
  phase: "loading",
7186
7402
  revision: 0,
7187
7403
  bots: [],
@@ -7192,41 +7408,41 @@ function FeishuSettingsTab({ rpcCall }) {
7192
7408
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
7193
7409
  modelCatalog: EMPTY_MODEL_CATALOG
7194
7410
  });
7195
- const [pageBusy, setPageBusy] = React15.useState(false);
7196
- const [provisionBusy, setProvisionBusy] = React15.useState(false);
7197
- const [credentialOpen, setCredentialOpen] = React15.useState(false);
7198
- const [credentialBusy, setCredentialBusy] = React15.useState(false);
7199
- const [credentialError, setCredentialError] = React15.useState(null);
7200
- const [busyByBot, setBusyByBot] = React15.useState({});
7201
- const [errorsByBot, setErrorsByBot] = React15.useState({});
7202
- const [testNoticesByBot, setTestNoticesByBot] = React15.useState({});
7203
- const [removeTargetId, setRemoveTargetId] = React15.useState(null);
7204
- const [announcement, setAnnouncement] = React15.useState("");
7205
- const [now, setNow] = React15.useState(() => Date.now());
7206
- const [focusBotId, setFocusBotId] = React15.useState(null);
7207
- const cardRefs = React15.useRef(/* @__PURE__ */ new Map());
7208
- const removeButtonRefs = React15.useRef(/* @__PURE__ */ new Map());
7209
- const targetedProvisionRef = React15.useRef(null);
7210
- const addButtonRef = React15.useRef(null);
7211
- const mountedRef = React15.useRef(true);
7411
+ const [pageBusy, setPageBusy] = React16.useState(false);
7412
+ const [provisionBusy, setProvisionBusy] = React16.useState(false);
7413
+ const [credentialOpen, setCredentialOpen] = React16.useState(false);
7414
+ const [credentialBusy, setCredentialBusy] = React16.useState(false);
7415
+ const [credentialError, setCredentialError] = React16.useState(null);
7416
+ const [busyByBot, setBusyByBot] = React16.useState({});
7417
+ const [errorsByBot, setErrorsByBot] = React16.useState({});
7418
+ const [testNoticesByBot, setTestNoticesByBot] = React16.useState({});
7419
+ const [removeTargetId, setRemoveTargetId] = React16.useState(null);
7420
+ const [announcement, setAnnouncement] = React16.useState("");
7421
+ const [now, setNow] = React16.useState(() => Date.now());
7422
+ const [focusBotId, setFocusBotId] = React16.useState(null);
7423
+ const cardRefs = React16.useRef(/* @__PURE__ */ new Map());
7424
+ const removeButtonRefs = React16.useRef(/* @__PURE__ */ new Map());
7425
+ const targetedProvisionRef = React16.useRef(null);
7426
+ const addButtonRef = React16.useRef(null);
7427
+ const mountedRef = React16.useRef(true);
7212
7428
  const workspaceFence = useWorkspaceSnapshotFence();
7213
7429
  const scheduleAnimationFrame = useAnimationFrameScheduler();
7214
- React15.useEffect(() => {
7430
+ React16.useEffect(() => {
7215
7431
  mountedRef.current = true;
7216
7432
  return () => {
7217
7433
  mountedRef.current = false;
7218
7434
  };
7219
7435
  }, []);
7220
- const announce = React15.useCallback((message) => {
7436
+ const announce = React16.useCallback((message) => {
7221
7437
  setAnnouncement("");
7222
7438
  scheduleAnimationFrame(() => {
7223
7439
  if (message) setAnnouncement(message);
7224
7440
  }, "announcement");
7225
7441
  }, [scheduleAnimationFrame]);
7226
- const invoke = React15.useCallback(async (endpoint, payload = {}, signal) => {
7442
+ const invoke = React16.useCallback(async (endpoint, payload = {}, signal) => {
7227
7443
  return unwrapRpcResult3(await rpcCall(endpoint, payload, signal));
7228
7444
  }, [rpcCall]);
7229
- const mergeSnapshot = React15.useCallback((snapshot, { restoreProvisioning = false } = {}) => {
7445
+ const mergeSnapshot = React16.useCallback((snapshot, { restoreProvisioning = false } = {}) => {
7230
7446
  const now2 = Date.now();
7231
7447
  setModel((current) => mergeFeishuSnapshotState(
7232
7448
  current,
@@ -7234,7 +7450,7 @@ function FeishuSettingsTab({ rpcCall }) {
7234
7450
  { restoreProvisioning, now: now2 }
7235
7451
  ));
7236
7452
  }, []);
7237
- const loadStatus = React15.useCallback(async ({ signal, silent = false, restoreProvisioning = false } = {}) => {
7453
+ const loadStatus = React16.useCallback(async ({ signal, silent = false, restoreProvisioning = false } = {}) => {
7238
7454
  const workspaceVersion = workspaceFence.beginStatus();
7239
7455
  if (workspaceVersion === null || !mountedRef.current) return void 0;
7240
7456
  if (!silent) setPageBusy(true);
@@ -7252,12 +7468,12 @@ function FeishuSettingsTab({ rpcCall }) {
7252
7468
  if (!silent && !signal?.aborted && mountedRef.current) setPageBusy(false);
7253
7469
  }
7254
7470
  }, [invoke, mergeSnapshot, workspaceFence]);
7255
- React15.useEffect(() => {
7471
+ React16.useEffect(() => {
7256
7472
  const controller = new AbortController();
7257
7473
  void loadStatus({ signal: controller.signal, restoreProvisioning: true });
7258
7474
  return () => controller.abort();
7259
7475
  }, [loadStatus]);
7260
- React15.useEffect(() => {
7476
+ React16.useEffect(() => {
7261
7477
  if (model.phase !== "ready") return void 0;
7262
7478
  const controller = new AbortController();
7263
7479
  let inFlight = false;
@@ -7276,7 +7492,7 @@ function FeishuSettingsTab({ rpcCall }) {
7276
7492
  window.clearInterval(timer);
7277
7493
  };
7278
7494
  }, [loadStatus, model.phase]);
7279
- React15.useEffect(() => {
7495
+ React16.useEffect(() => {
7280
7496
  if (!focusBotId) return;
7281
7497
  const node = cardRefs.current.get(focusBotId);
7282
7498
  if (!node) return;
@@ -7285,7 +7501,7 @@ function FeishuSettingsTab({ rpcCall }) {
7285
7501
  setFocusBotId(null);
7286
7502
  }, [focusBotId, model.bots]);
7287
7503
  const targetedProvisionFocusKey = isTargetedAppUpdate2(model.provisioning) ? `${model.provisioning.botId}:${model.provisioning.attemptId ?? "preparing"}:${model.provisioning.phase}` : null;
7288
- React15.useEffect(() => {
7504
+ React16.useEffect(() => {
7289
7505
  if (!targetedProvisionFocusKey) return;
7290
7506
  scheduleAnimationFrame(() => {
7291
7507
  const node = targetedProvisionRef.current;
@@ -7294,7 +7510,7 @@ function FeishuSettingsTab({ rpcCall }) {
7294
7510
  node.focus?.({ preventScroll: true });
7295
7511
  }, "targeted-provision-focus");
7296
7512
  }, [scheduleAnimationFrame, targetedProvisionFocusKey]);
7297
- const startProvisioning = React15.useCallback(async ({
7513
+ const startProvisioning = React16.useCallback(async ({
7298
7514
  replace = false,
7299
7515
  operation = FEISHU_REGISTRATION_OPERATIONS.PROVISION,
7300
7516
  bot
@@ -7370,7 +7586,7 @@ function FeishuSettingsTab({ rpcCall }) {
7370
7586
  model.provisioning?.botId,
7371
7587
  model.provisioning?.botName
7372
7588
  ]);
7373
- const bindCredentials = React15.useCallback(async ({ identity, secret }) => {
7589
+ const bindCredentials = React16.useCallback(async ({ identity, secret }) => {
7374
7590
  const snapshotVersion = workspaceFence.beginMutation();
7375
7591
  setCredentialBusy(true);
7376
7592
  setCredentialError(null);
@@ -7392,7 +7608,7 @@ function FeishuSettingsTab({ rpcCall }) {
7392
7608
  setCredentialBusy(false);
7393
7609
  }
7394
7610
  }, [announce, invoke, loadStatus, mergeSnapshot, workspaceFence]);
7395
- const cancelProvisioning = React15.useCallback(async () => {
7611
+ const cancelProvisioning = React16.useCallback(async () => {
7396
7612
  const activeProvision = model.provisioning;
7397
7613
  const attemptId = activeProvision?.attemptId;
7398
7614
  const repairing = isCallbackRepair(activeProvision);
@@ -7457,7 +7673,7 @@ function FeishuSettingsTab({ rpcCall }) {
7457
7673
  const countdownPhase = model.provisioning?.phase;
7458
7674
  const countdownExpiresAt = model.provisioning?.expiresAt;
7459
7675
  const countdownExpired = model.provisioning?.expired;
7460
- React15.useEffect(() => {
7676
+ React16.useEffect(() => {
7461
7677
  if (!countdownAttemptId || countdownPhase !== "qr" || countdownExpired) return void 0;
7462
7678
  const tick = () => {
7463
7679
  const timestamp8 = Date.now();
@@ -7470,7 +7686,7 @@ function FeishuSettingsTab({ rpcCall }) {
7470
7686
  const timer = window.setInterval(tick, 1e3);
7471
7687
  return () => window.clearInterval(timer);
7472
7688
  }, [countdownAttemptId, countdownPhase, countdownExpiresAt, countdownExpired]);
7473
- React15.useEffect(() => {
7689
+ React16.useEffect(() => {
7474
7690
  const provision2 = model.provisioning;
7475
7691
  if (!provision2 || !["qr", "connecting"].includes(provision2.phase) || !provision2.attemptId || provision2.expired) return void 0;
7476
7692
  const controller = new AbortController();
@@ -7538,7 +7754,7 @@ function FeishuSettingsTab({ rpcCall }) {
7538
7754
  window.clearTimeout(timer);
7539
7755
  };
7540
7756
  }, [announce, invoke, loadStatus, model.provisioning]);
7541
- const setBotBusy = React15.useCallback((botId, value) => {
7757
+ const setBotBusy = React16.useCallback((botId, value) => {
7542
7758
  setBusyByBot((current) => {
7543
7759
  const next = { ...current };
7544
7760
  if (value) next[botId] = value;
@@ -7546,7 +7762,7 @@ function FeishuSettingsTab({ rpcCall }) {
7546
7762
  return next;
7547
7763
  });
7548
7764
  }, []);
7549
- const setBotError = React15.useCallback((botId, error) => {
7765
+ const setBotError = React16.useCallback((botId, error) => {
7550
7766
  setErrorsByBot((current) => {
7551
7767
  const next = { ...current };
7552
7768
  if (error) next[botId] = presentError3(error);
@@ -7554,7 +7770,7 @@ function FeishuSettingsTab({ rpcCall }) {
7554
7770
  return next;
7555
7771
  });
7556
7772
  }, []);
7557
- const repairCallback = React15.useCallback((connection) => {
7773
+ const repairCallback = React16.useCallback((connection) => {
7558
7774
  if (model.provisioning) return;
7559
7775
  setRemoveTargetId(null);
7560
7776
  setBotError(connection.botId, null);
@@ -7568,7 +7784,7 @@ function FeishuSettingsTab({ rpcCall }) {
7568
7784
  bot: connection
7569
7785
  });
7570
7786
  }, [model.provisioning, setBotError, startProvisioning]);
7571
- const reconnectOneBot = React15.useCallback(async (connection) => {
7787
+ const reconnectOneBot = React16.useCallback(async (connection) => {
7572
7788
  const { botId, bot } = connection;
7573
7789
  const snapshotVersion = workspaceFence.beginMutation();
7574
7790
  setBotBusy(botId, "reconnect");
@@ -7608,7 +7824,7 @@ function FeishuSettingsTab({ rpcCall }) {
7608
7824
  setBotBusy(botId, null);
7609
7825
  }
7610
7826
  }, [announce, invoke, loadStatus, mergeSnapshot, setBotBusy, setBotError, workspaceFence]);
7611
- const saveWorkspace = React15.useCallback(async (connection, workspace) => {
7827
+ const saveWorkspace = React16.useCallback(async (connection, workspace) => {
7612
7828
  const { botId } = connection;
7613
7829
  const workspaceVersion = workspaceFence.beginMutation();
7614
7830
  setBotBusy(botId, "workspace");
@@ -7627,7 +7843,7 @@ function FeishuSettingsTab({ rpcCall }) {
7627
7843
  if (mountedRef.current) setBotBusy(botId, null);
7628
7844
  }
7629
7845
  }, [invoke, loadStatus, mergeSnapshot, setBotBusy, setBotError, workspaceFence]);
7630
- const saveBotSetting = React15.useCallback(async (connection, operation, endpoint, payload) => {
7846
+ const saveBotSetting = React16.useCallback(async (connection, operation, endpoint, payload) => {
7631
7847
  const { botId } = connection;
7632
7848
  const snapshotVersion = workspaceFence.beginMutation();
7633
7849
  setBotBusy(botId, operation);
@@ -7646,15 +7862,15 @@ function FeishuSettingsTab({ rpcCall }) {
7646
7862
  if (mountedRef.current) setBotBusy(botId, null);
7647
7863
  }
7648
7864
  }, [invoke, loadStatus, mergeSnapshot, setBotBusy, setBotError, workspaceFence]);
7649
- const requestRemove = React15.useCallback((connection) => {
7865
+ const requestRemove = React16.useCallback((connection) => {
7650
7866
  setRemoveTargetId(connection.botId);
7651
7867
  }, []);
7652
- const cancelRemove = React15.useCallback(() => {
7868
+ const cancelRemove = React16.useCallback(() => {
7653
7869
  const botId = removeTargetId;
7654
7870
  setRemoveTargetId(null);
7655
7871
  scheduleAnimationFrame(() => removeButtonRefs.current.get(botId)?.focus(), "focus");
7656
7872
  }, [removeTargetId, scheduleAnimationFrame]);
7657
- const confirmRemove = React15.useCallback(async (connection) => {
7873
+ const confirmRemove = React16.useCallback(async (connection) => {
7658
7874
  const { botId, bot } = connection;
7659
7875
  const snapshotVersion = workspaceFence.beginMutation();
7660
7876
  setBotBusy(botId, "delete");
@@ -7740,11 +7956,11 @@ function FeishuSettingsTab({ rpcCall }) {
7740
7956
  setCredentialError(null);
7741
7957
  }
7742
7958
  }) : null;
7743
- const setCardRef = React15.useCallback((botId, node) => {
7959
+ const setCardRef = React16.useCallback((botId, node) => {
7744
7960
  if (node) cardRefs.current.set(botId, node);
7745
7961
  else cardRefs.current.delete(botId);
7746
7962
  }, []);
7747
- const setRemoveButtonRef = React15.useCallback((botId, node) => {
7963
+ const setRemoveButtonRef = React16.useCallback((botId, node) => {
7748
7964
  if (node) removeButtonRefs.current.set(botId, node);
7749
7965
  else removeButtonRefs.current.delete(botId);
7750
7966
  }, []);
@@ -7785,7 +8001,7 @@ function FeishuSettingsTab({ rpcCall }) {
7785
8001
  onRetry: () => void loadStatus(),
7786
8002
  busy: pageBusy
7787
8003
  }) : h2(
7788
- React15.Fragment,
8004
+ React16.Fragment,
7789
8005
  null,
7790
8006
  credentialContent,
7791
8007
  targetedProvisioning ? null : provisionContent,
@@ -7802,6 +8018,12 @@ function FeishuSettingsTab({ rpcCall }) {
7802
8018
  onReconnect: (bot) => void reconnectOneBot(bot),
7803
8019
  onRepairCallback: repairCallback,
7804
8020
  onWorkspaceSave: saveWorkspace,
8021
+ onAliasSave: (connection, alias) => saveBotSetting(
8022
+ connection,
8023
+ "alias",
8024
+ FEISHU_ENDPOINTS.setAlias,
8025
+ { alias }
8026
+ ),
7805
8027
  onModelSave: (connection, selectedModel) => saveBotSetting(
7806
8028
  connection,
7807
8029
  "model",
@@ -8428,7 +8650,8 @@ var QQ_ENDPOINTS = Object.freeze({
8428
8650
  setModel: SET_MODEL_ENDPOINT,
8429
8651
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
8430
8652
  setContextEnhancement: "bot.context-enhancement.set",
8431
- setAccessPolicy: "bot.access-policy.set"
8653
+ setAccessPolicy: "bot.access-policy.set",
8654
+ setAlias: "bot.alias.set"
8432
8655
  });
8433
8656
  var PROVISION_STATES2 = /* @__PURE__ */ new Set(["starting", "pending", "refreshing", "connecting", "connected", "failed", "cancelled"]);
8434
8657
  var ACCOUNT_STATES3 = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
@@ -8497,6 +8720,7 @@ function normalizeBot3(value) {
8497
8720
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
8498
8721
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
8499
8722
  bot: {
8723
+ ...normalizeBotAlias(value.bot),
8500
8724
  name: text3(value.bot?.name, "QQ\u673A\u5668\u4EBA", 100),
8501
8725
  appIdMasked: text3(value.bot?.appIdMasked, "\u5E94\u7528\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58", 140)
8502
8726
  },
@@ -8554,7 +8778,7 @@ function formatRemaining3(milliseconds) {
8554
8778
  }
8555
8779
 
8556
8780
  // plugin-src/client/channels/qq/index.js
8557
- var React16 = __toESM(require("react"), 1);
8781
+ var React17 = __toESM(require("react"), 1);
8558
8782
 
8559
8783
  // plugin-src/client/channels/qq/styles.js
8560
8784
  var QQ_STYLE_ID = "xmanrui-dsh-im-qq-settings";
@@ -8579,7 +8803,7 @@ function installQqStyles() {
8579
8803
 
8580
8804
  // plugin-src/client/channels/qq/index.js
8581
8805
  var ACTIVE_STATES = /* @__PURE__ */ new Set(["pending", "refreshing", "connecting"]);
8582
- var Button7 = React16.forwardRef(function Button8({ children, kind = "secondary", className = "", ...props }, ref) {
8806
+ var Button7 = React17.forwardRef(function Button8({ children, kind = "secondary", className = "", ...props }, ref) {
8583
8807
  return h2("button", {
8584
8808
  ...props,
8585
8809
  ref,
@@ -8793,6 +9017,7 @@ function AccountCard2({
8793
9017
  removing,
8794
9018
  onReconnect,
8795
9019
  onWorkspaceSave,
9020
+ onAliasSave,
8796
9021
  onModelSave,
8797
9022
  onAgentPresetSave,
8798
9023
  onContextEnhancementSave,
@@ -8823,7 +9048,7 @@ function AccountCard2({
8823
9048
  h2(
8824
9049
  "div",
8825
9050
  { className: "dim-botName" },
8826
- h2("h3", null, account.bot.name),
9051
+ h2(BotName, { bot: account.bot, disabled: Boolean(busy), onSave: onAliasSave }),
8827
9052
  h2("p", null, account.bot.appIdMasked)
8828
9053
  )
8829
9054
  ),
@@ -8912,7 +9137,7 @@ function AccountCard2({
8912
9137
  );
8913
9138
  }
8914
9139
  function QqSettingsTab({ rpcCall }) {
8915
- const [model, setModel] = React16.useState({
9140
+ const [model, setModel] = React17.useState({
8916
9141
  phase: "loading",
8917
9142
  bots: [],
8918
9143
  totals: { configured: 0, connected: 0 },
@@ -8920,18 +9145,18 @@ function QqSettingsTab({ rpcCall }) {
8920
9145
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
8921
9146
  modelCatalog: EMPTY_MODEL_CATALOG
8922
9147
  });
8923
- const [provision, setProvision] = React16.useState(null);
8924
- const [busy, setBusy] = React16.useState(false);
8925
- const [busyByBot, setBusyByBot] = React16.useState({});
8926
- const [feedbackByBot, setFeedbackByBot] = React16.useState({});
8927
- const [removeTarget, setRemoveTarget] = React16.useState(null);
8928
- const [credentialOpen, setCredentialOpen] = React16.useState(false);
8929
- const [credentialError, setCredentialError] = React16.useState(null);
8930
- const [now, setNow] = React16.useState(Date.now());
8931
- const mounted = React16.useRef(true);
9148
+ const [provision, setProvision] = React17.useState(null);
9149
+ const [busy, setBusy] = React17.useState(false);
9150
+ const [busyByBot, setBusyByBot] = React17.useState({});
9151
+ const [feedbackByBot, setFeedbackByBot] = React17.useState({});
9152
+ const [removeTarget, setRemoveTarget] = React17.useState(null);
9153
+ const [credentialOpen, setCredentialOpen] = React17.useState(false);
9154
+ const [credentialError, setCredentialError] = React17.useState(null);
9155
+ const [now, setNow] = React17.useState(Date.now());
9156
+ const mounted = React17.useRef(true);
8932
9157
  const workspaceFence = useWorkspaceSnapshotFence();
8933
- const addButtonRef = React16.useRef(null);
8934
- React16.useEffect(() => {
9158
+ const addButtonRef = React17.useRef(null);
9159
+ React17.useEffect(() => {
8935
9160
  const disposeDingtalk = installDingtalkStyles();
8936
9161
  const disposeQq = installQqStyles();
8937
9162
  mounted.current = true;
@@ -8941,11 +9166,11 @@ function QqSettingsTab({ rpcCall }) {
8941
9166
  disposeDingtalk();
8942
9167
  };
8943
9168
  }, []);
8944
- const invoke = React16.useCallback(async (endpoint, payload = {}, signal) => {
9169
+ const invoke = React17.useCallback(async (endpoint, payload = {}, signal) => {
8945
9170
  if (typeof rpcCall !== "function") throw new TypeError("QQ \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
8946
9171
  return unwrapRpcResult4(await rpcCall(endpoint, payload, signal));
8947
9172
  }, [rpcCall]);
8948
- const loadStatus = React16.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
9173
+ const loadStatus = React17.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
8949
9174
  const workspaceVersion = workspaceFence.beginStatus();
8950
9175
  if (workspaceVersion === null) return void 0;
8951
9176
  if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
@@ -8972,12 +9197,12 @@ function QqSettingsTab({ rpcCall }) {
8972
9197
  return void 0;
8973
9198
  }
8974
9199
  }, [invoke, workspaceFence]);
8975
- React16.useEffect(() => {
9200
+ React17.useEffect(() => {
8976
9201
  const controller = new AbortController();
8977
9202
  void loadStatus({ signal: controller.signal, restore: true });
8978
9203
  return () => controller.abort();
8979
9204
  }, [loadStatus]);
8980
- React16.useEffect(() => {
9205
+ React17.useEffect(() => {
8981
9206
  if (model.phase !== "ready") return void 0;
8982
9207
  const controller = new AbortController();
8983
9208
  const timer = window.setInterval(() => void loadStatus({ signal: controller.signal, silent: true }), 15e3);
@@ -8986,12 +9211,12 @@ function QqSettingsTab({ rpcCall }) {
8986
9211
  window.clearInterval(timer);
8987
9212
  };
8988
9213
  }, [loadStatus, model.phase]);
8989
- React16.useEffect(() => {
9214
+ React17.useEffect(() => {
8990
9215
  if (!provision || !ACTIVE_STATES.has(provision.status)) return void 0;
8991
9216
  const timer = window.setInterval(() => mounted.current && setNow(Date.now()), 1e3);
8992
9217
  return () => window.clearInterval(timer);
8993
9218
  }, [provision?.attemptId, provision?.status]);
8994
- const startProvisioning = React16.useCallback(async (replace = false) => {
9219
+ const startProvisioning = React17.useCallback(async (replace = false) => {
8995
9220
  setCredentialOpen(false);
8996
9221
  setCredentialError(null);
8997
9222
  setBusy(true);
@@ -9009,7 +9234,7 @@ function QqSettingsTab({ rpcCall }) {
9009
9234
  if (mounted.current) setBusy(false);
9010
9235
  }
9011
9236
  }, [invoke, provision?.attemptId]);
9012
- const bindCredentials = React16.useCallback(async ({ identity, secret }) => {
9237
+ const bindCredentials = React17.useCallback(async ({ identity, secret }) => {
9013
9238
  const snapshotVersion = workspaceFence.beginMutation();
9014
9239
  setBusy(true);
9015
9240
  setCredentialError(null);
@@ -9038,7 +9263,7 @@ function QqSettingsTab({ rpcCall }) {
9038
9263
  if (mounted.current) setBusy(false);
9039
9264
  }
9040
9265
  }, [invoke, loadStatus, workspaceFence]);
9041
- const closeProvision = React16.useCallback(async () => {
9266
+ const closeProvision = React17.useCallback(async () => {
9042
9267
  setBusy(true);
9043
9268
  try {
9044
9269
  if (provision?.attemptId && ACTIVE_STATES.has(provision.status)) {
@@ -9049,7 +9274,7 @@ function QqSettingsTab({ rpcCall }) {
9049
9274
  if (mounted.current) setBusy(false);
9050
9275
  }
9051
9276
  }, [invoke, provision?.attemptId, provision?.status]);
9052
- React16.useEffect(() => {
9277
+ React17.useEffect(() => {
9053
9278
  const attemptId = provision?.attemptId;
9054
9279
  if (!attemptId || !ACTIVE_STATES.has(provision.status)) return void 0;
9055
9280
  const controller = new AbortController();
@@ -9079,7 +9304,7 @@ function QqSettingsTab({ rpcCall }) {
9079
9304
  window.clearTimeout(timer);
9080
9305
  };
9081
9306
  }, [invoke, loadStatus, provision?.attemptId, provision?.pollIntervalMs, provision?.status]);
9082
- const botAction = React16.useCallback(async (account, operation, endpoint, payload) => {
9307
+ const botAction = React17.useCallback(async (account, operation, endpoint, payload) => {
9083
9308
  const snapshotVersion = workspaceFence.beginMutation();
9084
9309
  setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
9085
9310
  try {
@@ -9105,7 +9330,7 @@ function QqSettingsTab({ rpcCall }) {
9105
9330
  });
9106
9331
  }
9107
9332
  }, [invoke, loadStatus, workspaceFence]);
9108
- const reconnect = React16.useCallback(async (account) => {
9333
+ const reconnect = React17.useCallback(async (account) => {
9109
9334
  setFeedbackByBot((current) => {
9110
9335
  const next = { ...current };
9111
9336
  delete next[account.botId];
@@ -9168,6 +9393,12 @@ function QqSettingsTab({ rpcCall }) {
9168
9393
  QQ_ENDPOINTS.setWorkspace,
9169
9394
  { botId: account.botId, workspace }
9170
9395
  ),
9396
+ onAliasSave: (alias) => botAction(
9397
+ account,
9398
+ "alias",
9399
+ QQ_ENDPOINTS.setAlias,
9400
+ { botId: account.botId, alias }
9401
+ ),
9171
9402
  onModelSave: (selectedModel) => botAction(
9172
9403
  account,
9173
9404
  "model",
@@ -9228,7 +9459,7 @@ function QqSettingsTab({ rpcCall }) {
9228
9459
  addButtonRef
9229
9460
  }),
9230
9461
  model.phase === "loading" ? h2(LoadingView3) : model.phase === "error" ? h2("div", { className: "ddt-card dim-surfaceCard" }, h2("div", { className: "ddt-inlineError dim-inlineError" }, h2("h3", null, "\u65E0\u6CD5\u8BFB\u53D6 QQ \u673A\u5668\u4EBA\u72B6\u6001"), h2("p", null, model.error?.message), h2(Button7, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6"))) : h2(
9231
- React16.Fragment,
9462
+ React17.Fragment,
9232
9463
  null,
9233
9464
  credentialView,
9234
9465
  provisionView,
@@ -9317,7 +9548,7 @@ function normalizeOfficeStatus(value) {
9317
9548
  }
9318
9549
 
9319
9550
  // plugin-src/client/channels/office/index.js
9320
- var React17 = __toESM(require("react"), 1);
9551
+ var React18 = __toESM(require("react"), 1);
9321
9552
  function Button9({ children, kind = "secondary", ...props }) {
9322
9553
  return h2("button", { ...props, type: "button", className: "ddt-button", "data-kind": kind }, children);
9323
9554
  }
@@ -9346,12 +9577,12 @@ function stateLabel(model) {
9346
9577
  return "\u5DF2\u914D\u7F6E";
9347
9578
  }
9348
9579
  function OfficeSettingsTab({ rpcCall, initialStatus }) {
9349
- const [model, setModel] = React17.useState(normalizeOfficeStatus(initialStatus));
9350
- const [phase, setPhase] = React17.useState(initialStatus === void 0 ? "loading" : "ready");
9351
- const [busy, setBusy] = React17.useState("");
9352
- const [error, setError] = React17.useState("");
9353
- const [notice, setNotice] = React17.useState("");
9354
- const [form, setForm] = React17.useState({
9580
+ const [model, setModel] = React18.useState(normalizeOfficeStatus(initialStatus));
9581
+ const [phase, setPhase] = React18.useState(initialStatus === void 0 ? "loading" : "ready");
9582
+ const [busy, setBusy] = React18.useState("");
9583
+ const [error, setError] = React18.useState("");
9584
+ const [notice, setNotice] = React18.useState("");
9585
+ const [form, setForm] = React18.useState({
9355
9586
  baseUrl: "",
9356
9587
  deviceId: "local-harness",
9357
9588
  deviceToken: "",
@@ -9360,11 +9591,11 @@ function OfficeSettingsTab({ rpcCall, initialStatus }) {
9360
9591
  workspaces: "",
9361
9592
  instructionPresets: ""
9362
9593
  });
9363
- const invoke = React17.useCallback(async (endpoint, payload = {}) => {
9594
+ const invoke = React18.useCallback(async (endpoint, payload = {}) => {
9364
9595
  if (typeof rpcCall !== "function") throw new Error("AI Office \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
9365
9596
  return unwrapOfficeRpc(await rpcCall(endpoint, payload));
9366
9597
  }, [rpcCall]);
9367
- const adopt = React17.useCallback((value) => {
9598
+ const adopt = React18.useCallback((value) => {
9368
9599
  const next = normalizeOfficeStatus(value?.snapshot ?? value);
9369
9600
  setModel(next);
9370
9601
  if (next.config) setForm((current) => ({
@@ -9379,7 +9610,7 @@ function OfficeSettingsTab({ rpcCall, initialStatus }) {
9379
9610
  }));
9380
9611
  return next;
9381
9612
  }, []);
9382
- const load = React17.useCallback(async () => {
9613
+ const load = React18.useCallback(async () => {
9383
9614
  try {
9384
9615
  adopt(await invoke(OFFICE_RPC_ENDPOINTS.status));
9385
9616
  setPhase("ready");
@@ -9389,7 +9620,7 @@ function OfficeSettingsTab({ rpcCall, initialStatus }) {
9389
9620
  setError(caught.message);
9390
9621
  }
9391
9622
  }, [adopt, invoke]);
9392
- React17.useEffect(() => {
9623
+ React18.useEffect(() => {
9393
9624
  void load();
9394
9625
  }, [load]);
9395
9626
  const run = async (name2, operation) => {
@@ -9406,7 +9637,7 @@ function OfficeSettingsTab({ rpcCall, initialStatus }) {
9406
9637
  setBusy("");
9407
9638
  }
9408
9639
  };
9409
- const hooks = React17.useMemo(() => {
9640
+ const hooks = React18.useMemo(() => {
9410
9641
  try {
9411
9642
  return officeHookUrls(form.baseUrl);
9412
9643
  } catch {
@@ -9591,7 +9822,7 @@ var normalizeSnapshot4 = api2.normalizeSnapshot;
9591
9822
  var presentError5 = api2.presentError;
9592
9823
 
9593
9824
  // plugin-src/client/channels/slack/index.js
9594
- var React18 = __toESM(require("react"), 1);
9825
+ var React19 = __toESM(require("react"), 1);
9595
9826
 
9596
9827
  // src/channels/slack/manifest.mjs
9597
9828
  var SLACK_APP_MANIFEST_YAML = `_metadata:
@@ -9669,10 +9900,10 @@ function installSlackStyles() {
9669
9900
 
9670
9901
  // plugin-src/client/channels/slack/index.js
9671
9902
  function SlackCredentialPanel({ busy, error, onSubmit, onCancel }) {
9672
- const [botToken, setBotToken] = React18.useState("");
9673
- const [appToken, setAppToken] = React18.useState("");
9674
- const [copied, setCopied] = React18.useState(false);
9675
- const headingId = React18.useId();
9903
+ const [botToken, setBotToken] = React19.useState("");
9904
+ const [appToken, setAppToken] = React19.useState("");
9905
+ const [copied, setCopied] = React19.useState(false);
9906
+ const headingId = React19.useId();
9676
9907
  const copyManifest = async () => {
9677
9908
  try {
9678
9909
  await navigator.clipboard.writeText(SLACK_APP_MANIFEST_YAML);
@@ -9870,7 +10101,8 @@ var WECOM_ENDPOINTS = Object.freeze({
9870
10101
  setModel: SET_MODEL_ENDPOINT,
9871
10102
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
9872
10103
  setContextEnhancement: "bot.context-enhancement.set",
9873
- setAccessPolicy: "bot.access-policy.set"
10104
+ setAccessPolicy: "bot.access-policy.set",
10105
+ setAlias: "bot.alias.set"
9874
10106
  });
9875
10107
  var PROVISION_STATES3 = /* @__PURE__ */ new Set(["starting", "pending", "refreshing", "connecting", "connected", "failed", "cancelled"]);
9876
10108
  var ACCOUNT_STATES4 = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
@@ -9945,6 +10177,7 @@ function normalizeBot4(value) {
9945
10177
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
9946
10178
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
9947
10179
  bot: {
10180
+ ...normalizeBotAlias(value.bot),
9948
10181
  name: text4(value.bot?.name, "\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA", 100),
9949
10182
  appIdMasked: text4(value.bot?.appIdMasked, "\u5E94\u7528\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58", 140)
9950
10183
  },
@@ -9985,7 +10218,7 @@ function formatRemaining4(milliseconds) {
9985
10218
  }
9986
10219
 
9987
10220
  // plugin-src/client/channels/wecom/index.js
9988
- var React19 = __toESM(require("react"), 1);
10221
+ var React20 = __toESM(require("react"), 1);
9989
10222
 
9990
10223
  // plugin-src/client/channels/wecom/styles.js
9991
10224
  var WECOM_STYLE_ID = "xmanrui-dsh-im-wecom-settings";
@@ -10010,7 +10243,7 @@ function installWecomStyles() {
10010
10243
 
10011
10244
  // plugin-src/client/channels/wecom/index.js
10012
10245
  var ACTIVE_STATES2 = /* @__PURE__ */ new Set(["pending", "refreshing", "connecting"]);
10013
- var Button10 = React19.forwardRef(function Button11({ children, kind = "secondary", className = "", ...props }, ref) {
10246
+ var Button10 = React20.forwardRef(function Button11({ children, kind = "secondary", className = "", ...props }, ref) {
10014
10247
  return h2("button", {
10015
10248
  ...props,
10016
10249
  ref,
@@ -10224,6 +10457,7 @@ function AccountCard3({
10224
10457
  removing,
10225
10458
  onReconnect,
10226
10459
  onWorkspaceSave,
10460
+ onAliasSave,
10227
10461
  onModelSave,
10228
10462
  onAgentPresetSave,
10229
10463
  onContextEnhancementSave,
@@ -10254,7 +10488,7 @@ function AccountCard3({
10254
10488
  h2(
10255
10489
  "div",
10256
10490
  { className: "dim-botName" },
10257
- h2("h3", null, account.bot.name),
10491
+ h2(BotName, { bot: account.bot, disabled: Boolean(busy), onSave: onAliasSave }),
10258
10492
  h2("p", null, account.bot.appIdMasked)
10259
10493
  )
10260
10494
  ),
@@ -10343,7 +10577,7 @@ function AccountCard3({
10343
10577
  );
10344
10578
  }
10345
10579
  function WecomSettingsTab({ rpcCall }) {
10346
- const [model, setModel] = React19.useState({
10580
+ const [model, setModel] = React20.useState({
10347
10581
  phase: "loading",
10348
10582
  bots: [],
10349
10583
  totals: { configured: 0, connected: 0 },
@@ -10351,20 +10585,20 @@ function WecomSettingsTab({ rpcCall }) {
10351
10585
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
10352
10586
  modelCatalog: EMPTY_MODEL_CATALOG
10353
10587
  });
10354
- const [provision, setProvision] = React19.useState(null);
10355
- const [busy, setBusy] = React19.useState(false);
10356
- const [busyByBot, setBusyByBot] = React19.useState({});
10357
- const [feedbackByBot, setFeedbackByBot] = React19.useState({});
10358
- const [removeTarget, setRemoveTarget] = React19.useState(null);
10359
- const [credentialOpen, setCredentialOpen] = React19.useState(false);
10360
- const [credentialError, setCredentialError] = React19.useState(null);
10361
- const [notice, setNotice] = React19.useState("");
10362
- const [now, setNow] = React19.useState(Date.now());
10363
- const mounted = React19.useRef(true);
10588
+ const [provision, setProvision] = React20.useState(null);
10589
+ const [busy, setBusy] = React20.useState(false);
10590
+ const [busyByBot, setBusyByBot] = React20.useState({});
10591
+ const [feedbackByBot, setFeedbackByBot] = React20.useState({});
10592
+ const [removeTarget, setRemoveTarget] = React20.useState(null);
10593
+ const [credentialOpen, setCredentialOpen] = React20.useState(false);
10594
+ const [credentialError, setCredentialError] = React20.useState(null);
10595
+ const [notice, setNotice] = React20.useState("");
10596
+ const [now, setNow] = React20.useState(Date.now());
10597
+ const mounted = React20.useRef(true);
10364
10598
  const workspaceFence = useWorkspaceSnapshotFence();
10365
- const addButtonRef = React19.useRef(null);
10366
- const noticeFrameRef = React19.useRef(null);
10367
- const announce = React19.useCallback((message) => {
10599
+ const addButtonRef = React20.useRef(null);
10600
+ const noticeFrameRef = React20.useRef(null);
10601
+ const announce = React20.useCallback((message) => {
10368
10602
  if (!mounted.current) return;
10369
10603
  if (noticeFrameRef.current !== null) {
10370
10604
  window.cancelAnimationFrame(noticeFrameRef.current);
@@ -10378,7 +10612,7 @@ function WecomSettingsTab({ rpcCall }) {
10378
10612
  });
10379
10613
  }
10380
10614
  }, []);
10381
- React19.useEffect(() => {
10615
+ React20.useEffect(() => {
10382
10616
  const disposeDingtalk = installDingtalkStyles();
10383
10617
  const disposeWecom = installWecomStyles();
10384
10618
  mounted.current = true;
@@ -10392,11 +10626,11 @@ function WecomSettingsTab({ rpcCall }) {
10392
10626
  disposeDingtalk();
10393
10627
  };
10394
10628
  }, []);
10395
- const invoke = React19.useCallback(async (endpoint, payload = {}, signal) => {
10629
+ const invoke = React20.useCallback(async (endpoint, payload = {}, signal) => {
10396
10630
  if (typeof rpcCall !== "function") throw new TypeError("\u4F01\u4E1A\u5FAE\u4FE1\u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
10397
10631
  return unwrapRpcResult7(await rpcCall(endpoint, payload, signal));
10398
10632
  }, [rpcCall]);
10399
- const loadStatus = React19.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
10633
+ const loadStatus = React20.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
10400
10634
  const workspaceVersion = workspaceFence.beginStatus();
10401
10635
  if (workspaceVersion === null) return void 0;
10402
10636
  if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
@@ -10423,12 +10657,12 @@ function WecomSettingsTab({ rpcCall }) {
10423
10657
  return void 0;
10424
10658
  }
10425
10659
  }, [invoke, workspaceFence]);
10426
- React19.useEffect(() => {
10660
+ React20.useEffect(() => {
10427
10661
  const controller = new AbortController();
10428
10662
  void loadStatus({ signal: controller.signal, restore: true });
10429
10663
  return () => controller.abort();
10430
10664
  }, [loadStatus]);
10431
- React19.useEffect(() => {
10665
+ React20.useEffect(() => {
10432
10666
  if (model.phase !== "ready") return void 0;
10433
10667
  const controller = new AbortController();
10434
10668
  const timer = window.setInterval(() => void loadStatus({ signal: controller.signal, silent: true }), 15e3);
@@ -10437,12 +10671,12 @@ function WecomSettingsTab({ rpcCall }) {
10437
10671
  window.clearInterval(timer);
10438
10672
  };
10439
10673
  }, [loadStatus, model.phase]);
10440
- React19.useEffect(() => {
10674
+ React20.useEffect(() => {
10441
10675
  if (!provision || !ACTIVE_STATES2.has(provision.status)) return void 0;
10442
10676
  const timer = window.setInterval(() => mounted.current && setNow(Date.now()), 1e3);
10443
10677
  return () => window.clearInterval(timer);
10444
10678
  }, [provision?.attemptId, provision?.status]);
10445
- const startProvisioning = React19.useCallback(async (replace = false) => {
10679
+ const startProvisioning = React20.useCallback(async (replace = false) => {
10446
10680
  setCredentialOpen(false);
10447
10681
  setCredentialError(null);
10448
10682
  setBusy(true);
@@ -10460,7 +10694,7 @@ function WecomSettingsTab({ rpcCall }) {
10460
10694
  if (mounted.current) setBusy(false);
10461
10695
  }
10462
10696
  }, [invoke, provision?.attemptId]);
10463
- const bindCredentials = React19.useCallback(async ({ identity, secret }) => {
10697
+ const bindCredentials = React20.useCallback(async ({ identity, secret }) => {
10464
10698
  const snapshotVersion = workspaceFence.beginMutation();
10465
10699
  setBusy(true);
10466
10700
  setCredentialError(null);
@@ -10489,7 +10723,7 @@ function WecomSettingsTab({ rpcCall }) {
10489
10723
  if (mounted.current) setBusy(false);
10490
10724
  }
10491
10725
  }, [invoke, loadStatus, workspaceFence]);
10492
- const closeProvision = React19.useCallback(async () => {
10726
+ const closeProvision = React20.useCallback(async () => {
10493
10727
  setBusy(true);
10494
10728
  try {
10495
10729
  if (provision?.attemptId && ACTIVE_STATES2.has(provision.status)) {
@@ -10500,7 +10734,7 @@ function WecomSettingsTab({ rpcCall }) {
10500
10734
  if (mounted.current) setBusy(false);
10501
10735
  }
10502
10736
  }, [invoke, provision?.attemptId, provision?.status]);
10503
- React19.useEffect(() => {
10737
+ React20.useEffect(() => {
10504
10738
  const attemptId = provision?.attemptId;
10505
10739
  if (!attemptId || !ACTIVE_STATES2.has(provision.status)) return void 0;
10506
10740
  const controller = new AbortController();
@@ -10530,7 +10764,7 @@ function WecomSettingsTab({ rpcCall }) {
10530
10764
  window.clearTimeout(timer);
10531
10765
  };
10532
10766
  }, [invoke, loadStatus, provision?.attemptId, provision?.pollIntervalMs, provision?.status]);
10533
- const botAction = React19.useCallback(async (account, operation, endpoint, payload) => {
10767
+ const botAction = React20.useCallback(async (account, operation, endpoint, payload) => {
10534
10768
  const snapshotVersion = workspaceFence.beginMutation();
10535
10769
  setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
10536
10770
  try {
@@ -10556,7 +10790,7 @@ function WecomSettingsTab({ rpcCall }) {
10556
10790
  });
10557
10791
  }
10558
10792
  }, [invoke, loadStatus, workspaceFence]);
10559
- const reconnect = React19.useCallback(async (account) => {
10793
+ const reconnect = React20.useCallback(async (account) => {
10560
10794
  setFeedbackByBot((current) => {
10561
10795
  const next = { ...current };
10562
10796
  delete next[account.botId];
@@ -10630,6 +10864,12 @@ function WecomSettingsTab({ rpcCall }) {
10630
10864
  WECOM_ENDPOINTS.setWorkspace,
10631
10865
  { botId: account.botId, workspace }
10632
10866
  ),
10867
+ onAliasSave: (alias) => botAction(
10868
+ account,
10869
+ "alias",
10870
+ WECOM_ENDPOINTS.setAlias,
10871
+ { botId: account.botId, alias }
10872
+ ),
10633
10873
  onModelSave: (selectedModel) => botAction(
10634
10874
  account,
10635
10875
  "model",
@@ -10691,7 +10931,7 @@ function WecomSettingsTab({ rpcCall }) {
10691
10931
  }),
10692
10932
  h2("div", { className: "ddt-visuallyHidden", role: "status", "aria-live": "polite" }, notice),
10693
10933
  model.phase === "loading" ? h2(LoadingView4) : model.phase === "error" ? h2("div", { className: "ddt-card dim-surfaceCard" }, h2("div", { className: "ddt-inlineError dim-inlineError" }, h2("h3", null, "\u65E0\u6CD5\u8BFB\u53D6\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u72B6\u6001"), h2("p", null, model.error?.message), h2(Button10, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6"))) : h2(
10694
- React19.Fragment,
10934
+ React20.Fragment,
10695
10935
  null,
10696
10936
  credentialView,
10697
10937
  provisionView,
@@ -10714,7 +10954,8 @@ var WECOM_APP_ENDPOINTS = Object.freeze({
10714
10954
  setModel: SET_MODEL_ENDPOINT,
10715
10955
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
10716
10956
  setContextEnhancement: "bot.context-enhancement.set",
10717
- setAccessPolicy: "bot.access-policy.set"
10957
+ setAccessPolicy: "bot.access-policy.set",
10958
+ setAlias: "bot.alias.set"
10718
10959
  });
10719
10960
  var ACCOUNT_STATES5 = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
10720
10961
  function isRecord6(value) {
@@ -10766,6 +11007,7 @@ function normalizeBot5(value) {
10766
11007
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
10767
11008
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
10768
11009
  bot: {
11010
+ ...normalizeBotAlias(value.bot),
10769
11011
  name: text5(value.bot?.name, "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528", 100),
10770
11012
  corpIdMasked: text5(value.bot?.corpIdMasked, "\u4F01\u4E1A ID \u5DF2\u4FDD\u5B58", 140),
10771
11013
  agentId: text5(value.bot?.agentId, "", 32),
@@ -10806,7 +11048,7 @@ function presentError8(error) {
10806
11048
  }
10807
11049
 
10808
11050
  // plugin-src/client/channels/wecom-app/index.js
10809
- var React20 = __toESM(require("react"), 1);
11051
+ var React21 = __toESM(require("react"), 1);
10810
11052
 
10811
11053
  // plugin-src/client/channels/wecom-app/styles.js
10812
11054
  var WECOM_APP_STYLE_ID = "xmanrui-dsh-im-wecom-app-settings";
@@ -10836,7 +11078,7 @@ function installWecomAppStyles() {
10836
11078
  }
10837
11079
 
10838
11080
  // plugin-src/client/channels/wecom-app/index.js
10839
- var Button12 = React20.forwardRef(function Button13({ children, kind = "secondary", className = "", ...props }, ref) {
11081
+ var Button12 = React21.forwardRef(function Button13({ children, kind = "secondary", className = "", ...props }, ref) {
10840
11082
  return h2("button", {
10841
11083
  ...props,
10842
11084
  ref,
@@ -10944,16 +11186,16 @@ function Field({ label, value, onChange, placeholder, busy, required = false, ty
10944
11186
  );
10945
11187
  }
10946
11188
  function BindForm({ busy, error, onSubmit, onCancel }) {
10947
- const [corpId, setCorpId] = React20.useState("");
10948
- const [agentId, setAgentId] = React20.useState("");
10949
- const [secret, setSecret] = React20.useState("");
10950
- const [token, setToken] = React20.useState("");
10951
- const [aesKey, setAesKey] = React20.useState("");
10952
- const [apiBaseUrl, setApiBaseUrl] = React20.useState("");
10953
- const [callbackBaseUrl, setCallbackBaseUrl] = React20.useState("");
10954
- const [streamEnabled, setStreamEnabled] = React20.useState(true);
10955
- const headingId = React20.useId();
10956
- const formRef = React20.useRef(null);
11189
+ const [corpId, setCorpId] = React21.useState("");
11190
+ const [agentId, setAgentId] = React21.useState("");
11191
+ const [secret, setSecret] = React21.useState("");
11192
+ const [token, setToken] = React21.useState("");
11193
+ const [aesKey, setAesKey] = React21.useState("");
11194
+ const [apiBaseUrl, setApiBaseUrl] = React21.useState("");
11195
+ const [callbackBaseUrl, setCallbackBaseUrl] = React21.useState("");
11196
+ const [streamEnabled, setStreamEnabled] = React21.useState(true);
11197
+ const headingId = React21.useId();
11198
+ const formRef = React21.useRef(null);
10957
11199
  const submit = (event) => {
10958
11200
  event.preventDefault();
10959
11201
  if (busy) return;
@@ -11016,7 +11258,7 @@ function BindForm({ busy, error, onSubmit, onCancel }) {
11016
11258
  );
11017
11259
  }
11018
11260
  function CallbackUrlBox({ url, busy, resetBusy, onCopy, onReset }) {
11019
- const [copied, setCopied] = React20.useState(false);
11261
+ const [copied, setCopied] = React21.useState(false);
11020
11262
  const copy = async () => {
11021
11263
  try {
11022
11264
  await navigator.clipboard.writeText(url);
@@ -11050,12 +11292,12 @@ function CallbackUrlBox({ url, busy, resetBusy, onCopy, onReset }) {
11050
11292
  );
11051
11293
  }
11052
11294
  function AppSettingsEditor({ bot, busy, onSave }) {
11053
- const [apiBaseUrl, setApiBaseUrl] = React20.useState(bot.apiBaseUrl ?? "");
11054
- const [callbackBaseUrl, setCallbackBaseUrl] = React20.useState(bot.callbackBaseUrl ?? "");
11055
- const [streamEnabled, setStreamEnabled] = React20.useState(bot.streamEnabled !== false);
11056
- const [dirty, setDirty] = React20.useState(false);
11057
- const formRef = React20.useRef(null);
11058
- React20.useEffect(() => {
11295
+ const [apiBaseUrl, setApiBaseUrl] = React21.useState(bot.apiBaseUrl ?? "");
11296
+ const [callbackBaseUrl, setCallbackBaseUrl] = React21.useState(bot.callbackBaseUrl ?? "");
11297
+ const [streamEnabled, setStreamEnabled] = React21.useState(bot.streamEnabled !== false);
11298
+ const [dirty, setDirty] = React21.useState(false);
11299
+ const formRef = React21.useRef(null);
11300
+ React21.useEffect(() => {
11059
11301
  setApiBaseUrl(bot.apiBaseUrl ?? "");
11060
11302
  setCallbackBaseUrl(bot.callbackBaseUrl ?? "");
11061
11303
  setStreamEnabled(bot.streamEnabled !== false);
@@ -11127,6 +11369,7 @@ function AccountCard4({
11127
11369
  onSettingsSave,
11128
11370
  onSecretReset,
11129
11371
  onWorkspaceSave,
11372
+ onAliasSave,
11130
11373
  onModelSave,
11131
11374
  onAgentPresetSave,
11132
11375
  onContextEnhancementSave,
@@ -11158,7 +11401,7 @@ function AccountCard4({
11158
11401
  h2(
11159
11402
  "div",
11160
11403
  { className: "dim-botName" },
11161
- h2("h3", null, account.bot.name),
11404
+ h2(BotName, { bot: account.bot, disabled: Boolean(busy), onSave: onAliasSave }),
11162
11405
  h2("p", null, `${account.bot.corpIdMasked} \xB7 AgentId ${account.bot.agentId}`)
11163
11406
  )
11164
11407
  ),
@@ -11257,7 +11500,7 @@ function AccountCard4({
11257
11500
  );
11258
11501
  }
11259
11502
  function WecomAppSettingsTab({ rpcCall }) {
11260
- const [model, setModel] = React20.useState({
11503
+ const [model, setModel] = React21.useState({
11261
11504
  phase: "loading",
11262
11505
  bots: [],
11263
11506
  totals: { configured: 0, connected: 0 },
@@ -11265,18 +11508,18 @@ function WecomAppSettingsTab({ rpcCall }) {
11265
11508
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
11266
11509
  modelCatalog: EMPTY_MODEL_CATALOG
11267
11510
  });
11268
- const [bindOpen, setBindOpen] = React20.useState(false);
11269
- const [bindError, setBindError] = React20.useState(null);
11270
- const [busy, setBusy] = React20.useState(false);
11271
- const [busyByBot, setBusyByBot] = React20.useState({});
11272
- const [feedbackByBot, setFeedbackByBot] = React20.useState({});
11273
- const [removeTarget, setRemoveTarget] = React20.useState(null);
11274
- const [notice, setNotice] = React20.useState("");
11275
- const mounted = React20.useRef(true);
11511
+ const [bindOpen, setBindOpen] = React21.useState(false);
11512
+ const [bindError, setBindError] = React21.useState(null);
11513
+ const [busy, setBusy] = React21.useState(false);
11514
+ const [busyByBot, setBusyByBot] = React21.useState({});
11515
+ const [feedbackByBot, setFeedbackByBot] = React21.useState({});
11516
+ const [removeTarget, setRemoveTarget] = React21.useState(null);
11517
+ const [notice, setNotice] = React21.useState("");
11518
+ const mounted = React21.useRef(true);
11276
11519
  const workspaceFence = useWorkspaceSnapshotFence();
11277
- const addButtonRef = React20.useRef(null);
11278
- const noticeFrameRef = React20.useRef(null);
11279
- const announce = React20.useCallback((message) => {
11520
+ const addButtonRef = React21.useRef(null);
11521
+ const noticeFrameRef = React21.useRef(null);
11522
+ const announce = React21.useCallback((message) => {
11280
11523
  if (!mounted.current) return;
11281
11524
  if (noticeFrameRef.current !== null) {
11282
11525
  window.cancelAnimationFrame(noticeFrameRef.current);
@@ -11290,7 +11533,7 @@ function WecomAppSettingsTab({ rpcCall }) {
11290
11533
  });
11291
11534
  }
11292
11535
  }, []);
11293
- React20.useEffect(() => {
11536
+ React21.useEffect(() => {
11294
11537
  const disposeDingtalk = installDingtalkStyles();
11295
11538
  const disposeWecomApp = installWecomAppStyles();
11296
11539
  mounted.current = true;
@@ -11304,11 +11547,11 @@ function WecomAppSettingsTab({ rpcCall }) {
11304
11547
  disposeDingtalk();
11305
11548
  };
11306
11549
  }, []);
11307
- const invoke = React20.useCallback(async (endpoint, payload = {}, signal) => {
11550
+ const invoke = React21.useCallback(async (endpoint, payload = {}, signal) => {
11308
11551
  if (typeof rpcCall !== "function") throw new TypeError("\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
11309
11552
  return unwrapRpcResult8(await rpcCall(endpoint, payload, signal));
11310
11553
  }, [rpcCall]);
11311
- const loadStatus = React20.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
11554
+ const loadStatus = React21.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
11312
11555
  const workspaceVersion = workspaceFence.beginStatus();
11313
11556
  if (workspaceVersion === null) return void 0;
11314
11557
  if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
@@ -11332,12 +11575,12 @@ function WecomAppSettingsTab({ rpcCall }) {
11332
11575
  return void 0;
11333
11576
  }
11334
11577
  }, [invoke, workspaceFence]);
11335
- React20.useEffect(() => {
11578
+ React21.useEffect(() => {
11336
11579
  const controller = new AbortController();
11337
11580
  void loadStatus({ signal: controller.signal, restore: true });
11338
11581
  return () => controller.abort();
11339
11582
  }, [loadStatus]);
11340
- React20.useEffect(() => {
11583
+ React21.useEffect(() => {
11341
11584
  if (model.phase !== "ready") return void 0;
11342
11585
  const controller = new AbortController();
11343
11586
  const timer = window.setInterval(() => void loadStatus({ signal: controller.signal, silent: true }), 15e3);
@@ -11346,7 +11589,7 @@ function WecomAppSettingsTab({ rpcCall }) {
11346
11589
  window.clearInterval(timer);
11347
11590
  };
11348
11591
  }, [loadStatus, model.phase]);
11349
- const bindApp = React20.useCallback(async (payload) => {
11592
+ const bindApp = React21.useCallback(async (payload) => {
11350
11593
  const snapshotVersion = workspaceFence.beginMutation();
11351
11594
  setBusy(true);
11352
11595
  setBindError(null);
@@ -11373,7 +11616,7 @@ function WecomAppSettingsTab({ rpcCall }) {
11373
11616
  if (mounted.current) setBusy(false);
11374
11617
  }
11375
11618
  }, [announce, invoke, loadStatus, workspaceFence]);
11376
- const botAction = React20.useCallback(async (account, operation, endpoint, payload) => {
11619
+ const botAction = React21.useCallback(async (account, operation, endpoint, payload) => {
11377
11620
  const snapshotVersion = workspaceFence.beginMutation();
11378
11621
  setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
11379
11622
  try {
@@ -11399,7 +11642,7 @@ function WecomAppSettingsTab({ rpcCall }) {
11399
11642
  });
11400
11643
  }
11401
11644
  }, [invoke, loadStatus, workspaceFence]);
11402
- const reconnect = React20.useCallback(async (account) => {
11645
+ const reconnect = React21.useCallback(async (account) => {
11403
11646
  setFeedbackByBot((current) => {
11404
11647
  const next = { ...current };
11405
11648
  delete next[account.botId];
@@ -11472,6 +11715,12 @@ function WecomAppSettingsTab({ rpcCall }) {
11472
11715
  WECOM_APP_ENDPOINTS.setWorkspace,
11473
11716
  { botId: account.botId, workspace }
11474
11717
  ),
11718
+ onAliasSave: (alias) => botAction(
11719
+ account,
11720
+ "alias",
11721
+ WECOM_APP_ENDPOINTS.setAlias,
11722
+ { botId: account.botId, alias }
11723
+ ),
11475
11724
  onModelSave: (selectedModel) => botAction(
11476
11725
  account,
11477
11726
  "model",
@@ -11526,7 +11775,7 @@ function WecomAppSettingsTab({ rpcCall }) {
11526
11775
  }),
11527
11776
  h2("div", { className: "ddt-visuallyHidden", role: "status", "aria-live": "polite" }, notice),
11528
11777
  model.phase === "loading" ? h2(LoadingView5) : model.phase === "error" ? h2("div", { className: "ddt-card dim-surfaceCard" }, h2("div", { className: "ddt-inlineError dim-inlineError" }, h2("h3", null, "\u65E0\u6CD5\u8BFB\u53D6\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u72B6\u6001"), h2("p", null, model.error?.message), h2(Button12, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6"))) : h2(
11529
- React20.Fragment,
11778
+ React21.Fragment,
11530
11779
  null,
11531
11780
  bindView,
11532
11781
  model.bots.length === 0 && !bindOpen ? h2(EmptyView5, { busy, onStart: () => setBindOpen(true) }) : null,
@@ -11536,7 +11785,7 @@ function WecomAppSettingsTab({ rpcCall }) {
11536
11785
  }
11537
11786
 
11538
11787
  // plugin-src/client/channels/weixin/index.js
11539
- var React21 = __toESM(require("react"), 1);
11788
+ var React22 = __toESM(require("react"), 1);
11540
11789
 
11541
11790
  // plugin-src/client/channels/weixin/api.js
11542
11791
  var WEIXIN_RPC_CHANNEL = "/weixin";
@@ -11552,7 +11801,8 @@ var WEIXIN_ENDPOINTS = Object.freeze({
11552
11801
  setModel: SET_MODEL_ENDPOINT,
11553
11802
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
11554
11803
  setContextEnhancement: "bot.context-enhancement.set",
11555
- setAccessPolicy: "bot.access-policy.set"
11804
+ setAccessPolicy: "bot.access-policy.set",
11805
+ setAlias: "bot.alias.set"
11556
11806
  });
11557
11807
  var ACCOUNT_STATES6 = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
11558
11808
  var PROVISION_STATES4 = /* @__PURE__ */ new Set([
@@ -11647,6 +11897,7 @@ function normalizeBot6(value) {
11647
11897
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
11648
11898
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
11649
11899
  bot: {
11900
+ ...normalizeBotAlias(value.bot),
11650
11901
  name: string(value.bot.name, "\u5FAE\u4FE1\u673A\u5668\u4EBA"),
11651
11902
  accountIdMasked: string(value.bot.accountIdMasked, "\u5DF2\u5B89\u5168\u4FDD\u5B58")
11652
11903
  },
@@ -11698,7 +11949,7 @@ function formatRemaining5(milliseconds) {
11698
11949
  }
11699
11950
 
11700
11951
  // plugin-src/client/channels/weixin/index.js
11701
- var Button14 = React21.forwardRef(function Button15({ children, kind = "secondary", className = "", ...props }, ref) {
11952
+ var Button14 = React22.forwardRef(function Button15({ children, kind = "secondary", className = "", ...props }, ref) {
11702
11953
  return h2("button", {
11703
11954
  ...props,
11704
11955
  ref,
@@ -11771,14 +12022,14 @@ function EmptyView6({ onStart, busy }) {
11771
12022
  );
11772
12023
  }
11773
12024
  function QrPanel4({ provision, now, busy, onRefresh, onCancel }) {
11774
- const [imageFailed, setImageFailed] = React21.useState(false);
12025
+ const [imageFailed, setImageFailed] = React22.useState(false);
11775
12026
  const source = safeQrSource5(provision.qrCodeDataUrl);
11776
12027
  const href = safeVerificationUrl(provision.verificationUrl);
11777
12028
  const remaining = Math.max(0, provision.expiresAt - now);
11778
12029
  const expired = remaining === 0 || provision.status === "expired";
11779
12030
  const duration = Math.max(1, provision.durationMs ?? 5 * 6e4);
11780
12031
  const progress = Math.round(Math.min(1, remaining / duration) * 100);
11781
- React21.useEffect(() => setImageFailed(false), [source]);
12032
+ React22.useEffect(() => setImageFailed(false), [source]);
11782
12033
  return h2(
11783
12034
  "div",
11784
12035
  { className: "dxw-card dim-surfaceCard" },
@@ -11845,9 +12096,9 @@ function QrPanel4({ provision, now, busy, onRefresh, onCancel }) {
11845
12096
  );
11846
12097
  }
11847
12098
  function VerificationPanel({ provision, busy, onSubmit, onCancel }) {
11848
- const [code, setCode] = React21.useState("");
12099
+ const [code, setCode] = React22.useState("");
11849
12100
  const valid = /^\d{4,8}$/.test(code);
11850
- React21.useEffect(() => setCode(""), [provision.attemptId]);
12101
+ React22.useEffect(() => setCode(""), [provision.attemptId]);
11851
12102
  return h2(
11852
12103
  "div",
11853
12104
  { className: "dxw-card dim-surfaceCard" },
@@ -11945,6 +12196,7 @@ function AccountCard5({
11945
12196
  removing,
11946
12197
  onReconnect,
11947
12198
  onWorkspaceSave,
12199
+ onAliasSave,
11948
12200
  onModelSave,
11949
12201
  onAgentPresetSave,
11950
12202
  onContextEnhancementSave,
@@ -11972,7 +12224,7 @@ function AccountCard5({
11972
12224
  "div",
11973
12225
  { className: "dxw-accountIdentity dim-botIdentity" },
11974
12226
  h2("div", { className: "dxw-avatar dim-botAvatar", "aria-hidden": "true" }, h2(WeixinLogoGlyph, { size: 27 })),
11975
- h2("div", { className: "dim-botName" }, h2("h3", null, account.bot.name), h2("p", null, account.bot.accountIdMasked))
12227
+ h2("div", { className: "dim-botName" }, h2(BotName, { bot: account.bot, disabled: Boolean(busy), onSave: onAliasSave }), h2("p", null, account.bot.accountIdMasked))
11976
12228
  ),
11977
12229
  h2(
11978
12230
  "div",
@@ -12092,6 +12344,7 @@ function AccountList2(props) {
12092
12344
  removing: props.removeTarget === account.botId,
12093
12345
  onReconnect: () => props.onReconnect(account),
12094
12346
  onWorkspaceSave: (workspace) => props.onWorkspaceSave(account, workspace),
12347
+ onAliasSave: (alias) => props.onAliasSave(account, alias),
12095
12348
  onModelSave: (model) => props.onModelSave(account, model),
12096
12349
  onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(account, agentPreset),
12097
12350
  onContextEnhancementSave: (config) => props.onContextEnhancementSave(account, config),
@@ -12113,7 +12366,7 @@ function mergeWeixinProvisioningSnapshot(current, incoming, { restoreProvisionin
12113
12366
  };
12114
12367
  }
12115
12368
  function WeixinSettingsTab({ rpcCall }) {
12116
- const [model, setModel] = React21.useState({
12369
+ const [model, setModel] = React22.useState({
12117
12370
  phase: "loading",
12118
12371
  bots: [],
12119
12372
  totals: EMPTY_TOTALS3,
@@ -12122,33 +12375,33 @@ function WeixinSettingsTab({ rpcCall }) {
12122
12375
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
12123
12376
  modelCatalog: EMPTY_MODEL_CATALOG
12124
12377
  });
12125
- const [provision, setProvision] = React21.useState(null);
12126
- const [busy, setBusy] = React21.useState(false);
12127
- const [busyByBot, setBusyByBot] = React21.useState({});
12128
- const [feedbackByBot, setFeedbackByBot] = React21.useState({});
12129
- const [removeTarget, setRemoveTarget] = React21.useState(null);
12130
- const [notice, setNotice] = React21.useState("");
12131
- const [now, setNow] = React21.useState(() => Date.now());
12132
- const addButtonRef = React21.useRef(null);
12133
- const mountedRef = React21.useRef(true);
12378
+ const [provision, setProvision] = React22.useState(null);
12379
+ const [busy, setBusy] = React22.useState(false);
12380
+ const [busyByBot, setBusyByBot] = React22.useState({});
12381
+ const [feedbackByBot, setFeedbackByBot] = React22.useState({});
12382
+ const [removeTarget, setRemoveTarget] = React22.useState(null);
12383
+ const [notice, setNotice] = React22.useState("");
12384
+ const [now, setNow] = React22.useState(() => Date.now());
12385
+ const addButtonRef = React22.useRef(null);
12386
+ const mountedRef = React22.useRef(true);
12134
12387
  const workspaceFence = useWorkspaceSnapshotFence();
12135
12388
  const scheduleAnimationFrame = useAnimationFrameScheduler();
12136
- React21.useEffect(() => {
12389
+ React22.useEffect(() => {
12137
12390
  mountedRef.current = true;
12138
12391
  return () => {
12139
12392
  mountedRef.current = false;
12140
12393
  };
12141
12394
  }, []);
12142
- const announce = React21.useCallback((value) => {
12395
+ const announce = React22.useCallback((value) => {
12143
12396
  setNotice("");
12144
12397
  scheduleAnimationFrame(() => {
12145
12398
  if (value) setNotice(value);
12146
12399
  }, "announcement");
12147
12400
  }, [scheduleAnimationFrame]);
12148
- const invoke = React21.useCallback(async (endpoint, payload = {}, signal) => {
12401
+ const invoke = React22.useCallback(async (endpoint, payload = {}, signal) => {
12149
12402
  return unwrapRpcResult9(await rpcCall(endpoint, payload, signal));
12150
12403
  }, [rpcCall]);
12151
- const loadStatus = React21.useCallback(async ({
12404
+ const loadStatus = React22.useCallback(async ({
12152
12405
  signal,
12153
12406
  silent = false,
12154
12407
  restoreProvisioning = false
@@ -12186,12 +12439,12 @@ function WeixinSettingsTab({ rpcCall }) {
12186
12439
  return void 0;
12187
12440
  }
12188
12441
  }, [invoke, workspaceFence]);
12189
- React21.useEffect(() => {
12442
+ React22.useEffect(() => {
12190
12443
  const controller = new AbortController();
12191
12444
  void loadStatus({ signal: controller.signal, restoreProvisioning: true });
12192
12445
  return () => controller.abort();
12193
12446
  }, [loadStatus]);
12194
- React21.useEffect(() => {
12447
+ React22.useEffect(() => {
12195
12448
  if (model.phase !== "ready") return void 0;
12196
12449
  const controller = new AbortController();
12197
12450
  let running = false;
@@ -12210,12 +12463,12 @@ function WeixinSettingsTab({ rpcCall }) {
12210
12463
  window.clearInterval(timer);
12211
12464
  };
12212
12465
  }, [loadStatus, model.phase]);
12213
- React21.useEffect(() => {
12466
+ React22.useEffect(() => {
12214
12467
  if (!provision || !["pending", "scanned"].includes(provision.status)) return void 0;
12215
12468
  const timer = window.setInterval(() => setNow(Date.now()), 1e3);
12216
12469
  return () => window.clearInterval(timer);
12217
12470
  }, [provision?.attemptId, provision?.status]);
12218
- const startProvisioning = React21.useCallback(async ({ replace = false } = {}) => {
12471
+ const startProvisioning = React22.useCallback(async ({ replace = false } = {}) => {
12219
12472
  setBusy(true);
12220
12473
  try {
12221
12474
  if (replace && provision?.attemptId) {
@@ -12236,7 +12489,7 @@ function WeixinSettingsTab({ rpcCall }) {
12236
12489
  setBusy(false);
12237
12490
  }
12238
12491
  }, [announce, invoke, provision?.attemptId]);
12239
- const cancelProvisioning = React21.useCallback(async () => {
12492
+ const cancelProvisioning = React22.useCallback(async () => {
12240
12493
  setBusy(true);
12241
12494
  try {
12242
12495
  if (provision?.attemptId && !["failed", "expired", "cancelled"].includes(provision.status)) {
@@ -12251,7 +12504,7 @@ function WeixinSettingsTab({ rpcCall }) {
12251
12504
  setBusy(false);
12252
12505
  }
12253
12506
  }, [announce, invoke, provision?.attemptId, provision?.status, scheduleAnimationFrame]);
12254
- const submitVerification = React21.useCallback(async (verifyCode) => {
12507
+ const submitVerification = React22.useCallback(async (verifyCode) => {
12255
12508
  if (!provision?.attemptId) return;
12256
12509
  setBusy(true);
12257
12510
  try {
@@ -12267,7 +12520,7 @@ function WeixinSettingsTab({ rpcCall }) {
12267
12520
  setBusy(false);
12268
12521
  }
12269
12522
  }, [announce, invoke, provision?.attemptId]);
12270
- React21.useEffect(() => {
12523
+ React22.useEffect(() => {
12271
12524
  const attemptId = provision?.attemptId;
12272
12525
  if (!attemptId || !["pending", "scanned", "connecting"].includes(provision.status)) return void 0;
12273
12526
  const controller = new AbortController();
@@ -12315,7 +12568,7 @@ function WeixinSettingsTab({ rpcCall }) {
12315
12568
  controller.abort();
12316
12569
  };
12317
12570
  }, [announce, invoke, loadStatus, provision?.attemptId, provision?.status, provision?.pollIntervalMs]);
12318
- const setBotBusy = React21.useCallback((botId, value) => {
12571
+ const setBotBusy = React22.useCallback((botId, value) => {
12319
12572
  setBusyByBot((current) => {
12320
12573
  const next = { ...current };
12321
12574
  if (value) next[botId] = value;
@@ -12323,7 +12576,7 @@ function WeixinSettingsTab({ rpcCall }) {
12323
12576
  return next;
12324
12577
  });
12325
12578
  }, []);
12326
- const reconnect = React21.useCallback(async (account) => {
12579
+ const reconnect = React22.useCallback(async (account) => {
12327
12580
  const snapshotVersion = workspaceFence.beginMutation();
12328
12581
  setBotBusy(account.botId, "reconnect");
12329
12582
  setFeedbackByBot((current) => {
@@ -12375,7 +12628,7 @@ function WeixinSettingsTab({ rpcCall }) {
12375
12628
  setBotBusy(account.botId, null);
12376
12629
  }
12377
12630
  }, [announce, invoke, loadStatus, setBotBusy, workspaceFence]);
12378
- const saveWorkspace = React21.useCallback(async (account, workspace) => {
12631
+ const saveWorkspace = React22.useCallback(async (account, workspace) => {
12379
12632
  const workspaceVersion = workspaceFence.beginMutation();
12380
12633
  setBotBusy(account.botId, "workspace");
12381
12634
  try {
@@ -12400,7 +12653,7 @@ function WeixinSettingsTab({ rpcCall }) {
12400
12653
  if (mountedRef.current) setBotBusy(account.botId, null);
12401
12654
  }
12402
12655
  }, [invoke, loadStatus, setBotBusy, workspaceFence]);
12403
- const saveBotSetting = React21.useCallback(async (account, operation, endpoint, payload) => {
12656
+ const saveBotSetting = React22.useCallback(async (account, operation, endpoint, payload) => {
12404
12657
  const snapshotVersion = workspaceFence.beginMutation();
12405
12658
  setBotBusy(account.botId, operation);
12406
12659
  try {
@@ -12425,7 +12678,7 @@ function WeixinSettingsTab({ rpcCall }) {
12425
12678
  if (mountedRef.current) setBotBusy(account.botId, null);
12426
12679
  }
12427
12680
  }, [invoke, loadStatus, setBotBusy, workspaceFence]);
12428
- const remove = React21.useCallback(async (account) => {
12681
+ const remove = React22.useCallback(async (account) => {
12429
12682
  const snapshotVersion = workspaceFence.beginMutation();
12430
12683
  setBotBusy(account.botId, "delete");
12431
12684
  try {
@@ -12512,7 +12765,7 @@ function WeixinSettingsTab({ rpcCall }) {
12512
12765
  h2(Button14, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
12513
12766
  )
12514
12767
  ) : h2(
12515
- React21.Fragment,
12768
+ React22.Fragment,
12516
12769
  null,
12517
12770
  provisionView,
12518
12771
  model.bots.length === 0 && !provision ? h2(EmptyView6, { onStart: () => void startProvisioning(), busy }) : null,
@@ -12523,6 +12776,12 @@ function WeixinSettingsTab({ rpcCall }) {
12523
12776
  removeTarget,
12524
12777
  onReconnect: (account) => void reconnect(account),
12525
12778
  onWorkspaceSave: saveWorkspace,
12779
+ onAliasSave: (account, alias) => saveBotSetting(
12780
+ account,
12781
+ "alias",
12782
+ WEIXIN_ENDPOINTS.setAlias,
12783
+ { alias }
12784
+ ),
12526
12785
  onModelSave: (account, selectedModel) => saveBotSetting(
12527
12786
  account,
12528
12787
  "model",
@@ -12676,6 +12935,7 @@ var WHATSAPP_ENDPOINTS = Object.freeze({
12676
12935
  reconnectBot: "bot.reconnect",
12677
12936
  deleteBot: "bot.delete",
12678
12937
  setAccessPolicy: "bot.access-policy.set",
12938
+ setAlias: "bot.alias.set",
12679
12939
  setWorkspace: "bot.workspace.set",
12680
12940
  setModel: SET_MODEL_ENDPOINT,
12681
12941
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
@@ -12749,6 +13009,7 @@ function normalizeBot7(value) {
12749
13009
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
12750
13010
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
12751
13011
  bot: {
13012
+ ...normalizeBotAlias(value.bot),
12752
13013
  name: text6(value.bot?.name, "WhatsApp\u673A\u5668\u4EBA", 100),
12753
13014
  idMasked: text6(value.bot?.idMasked, "WhatsApp\u8D26\u53F7", 140)
12754
13015
  },
@@ -12790,7 +13051,7 @@ function formatRemaining6(milliseconds) {
12790
13051
  }
12791
13052
 
12792
13053
  // plugin-src/client/channels/whatsapp/index.js
12793
- var React22 = __toESM(require("react"), 1);
13054
+ var React23 = __toESM(require("react"), 1);
12794
13055
 
12795
13056
  // plugin-src/client/channels/whatsapp/styles.js
12796
13057
  var WHATSAPP_STYLE_ID = "xmanrui-dsh-im-whatsapp-settings";
@@ -12815,7 +13076,7 @@ function installWhatsappStyles() {
12815
13076
 
12816
13077
  // plugin-src/client/channels/whatsapp/index.js
12817
13078
  var ACTIVE_STATES3 = /* @__PURE__ */ new Set(["pending", "connecting"]);
12818
- var Button16 = React22.forwardRef(function Button17({ children, kind = "secondary", className = "", ...props }, ref) {
13079
+ var Button16 = React23.forwardRef(function Button17({ children, kind = "secondary", className = "", ...props }, ref) {
12819
13080
  return h2("button", {
12820
13081
  ...props,
12821
13082
  ref,
@@ -13037,6 +13298,7 @@ function WhatsappAccountCard({
13037
13298
  removing,
13038
13299
  onReconnect,
13039
13300
  onWorkspaceSave,
13301
+ onAliasSave,
13040
13302
  onModelSave,
13041
13303
  onAgentPresetSave,
13042
13304
  onContextEnhancementSave,
@@ -13071,7 +13333,7 @@ function WhatsappAccountCard({
13071
13333
  h2(
13072
13334
  "div",
13073
13335
  { className: "dim-botName" },
13074
- h2("h3", null, account.bot.name),
13336
+ h2(BotName, { bot: account.bot, disabled: Boolean(busy), onSave: onAliasSave }),
13075
13337
  h2("p", null, account.bot.idMasked)
13076
13338
  )
13077
13339
  ),
@@ -13168,7 +13430,7 @@ function WhatsappAccountCard({
13168
13430
  );
13169
13431
  }
13170
13432
  function WhatsappSettingsTab({ rpcCall }) {
13171
- const [model, setModel] = React22.useState({
13433
+ const [model, setModel] = React23.useState({
13172
13434
  phase: "loading",
13173
13435
  bots: [],
13174
13436
  totals: { configured: 0, connected: 0 },
@@ -13176,16 +13438,16 @@ function WhatsappSettingsTab({ rpcCall }) {
13176
13438
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
13177
13439
  modelCatalog: EMPTY_MODEL_CATALOG
13178
13440
  });
13179
- const [provision, setProvision] = React22.useState(null);
13180
- const [busy, setBusy] = React22.useState(false);
13181
- const [busyByBot, setBusyByBot] = React22.useState({});
13182
- const [testNoticeByBot, setTestNoticeByBot] = React22.useState({});
13183
- const [removeTarget, setRemoveTarget] = React22.useState(null);
13184
- const [now, setNow] = React22.useState(Date.now());
13185
- const mounted = React22.useRef(true);
13441
+ const [provision, setProvision] = React23.useState(null);
13442
+ const [busy, setBusy] = React23.useState(false);
13443
+ const [busyByBot, setBusyByBot] = React23.useState({});
13444
+ const [testNoticeByBot, setTestNoticeByBot] = React23.useState({});
13445
+ const [removeTarget, setRemoveTarget] = React23.useState(null);
13446
+ const [now, setNow] = React23.useState(Date.now());
13447
+ const mounted = React23.useRef(true);
13186
13448
  const workspaceFence = useWorkspaceSnapshotFence();
13187
- const addButtonRef = React22.useRef(null);
13188
- React22.useEffect(() => {
13449
+ const addButtonRef = React23.useRef(null);
13450
+ React23.useEffect(() => {
13189
13451
  const disposeDingtalk = installDingtalkStyles();
13190
13452
  const disposeWhatsapp = installWhatsappStyles();
13191
13453
  mounted.current = true;
@@ -13195,11 +13457,11 @@ function WhatsappSettingsTab({ rpcCall }) {
13195
13457
  disposeDingtalk();
13196
13458
  };
13197
13459
  }, []);
13198
- const invoke = React22.useCallback(async (endpoint, payload = {}, signal) => {
13460
+ const invoke = React23.useCallback(async (endpoint, payload = {}, signal) => {
13199
13461
  if (typeof rpcCall !== "function") throw new TypeError("WhatsApp \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
13200
13462
  return unwrapRpcResult10(await rpcCall(endpoint, payload, signal));
13201
13463
  }, [rpcCall]);
13202
- const loadStatus = React22.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
13464
+ const loadStatus = React23.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
13203
13465
  const workspaceVersion = workspaceFence.beginStatus();
13204
13466
  if (workspaceVersion === null) return void 0;
13205
13467
  if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
@@ -13230,12 +13492,12 @@ function WhatsappSettingsTab({ rpcCall }) {
13230
13492
  return void 0;
13231
13493
  }
13232
13494
  }, [invoke, workspaceFence]);
13233
- React22.useEffect(() => {
13495
+ React23.useEffect(() => {
13234
13496
  const controller = new AbortController();
13235
13497
  void loadStatus({ signal: controller.signal, restore: true });
13236
13498
  return () => controller.abort();
13237
13499
  }, [loadStatus]);
13238
- React22.useEffect(() => {
13500
+ React23.useEffect(() => {
13239
13501
  if (model.phase !== "ready") return void 0;
13240
13502
  const controller = new AbortController();
13241
13503
  const timer = window.setInterval(
@@ -13247,12 +13509,12 @@ function WhatsappSettingsTab({ rpcCall }) {
13247
13509
  window.clearInterval(timer);
13248
13510
  };
13249
13511
  }, [loadStatus, model.phase]);
13250
- React22.useEffect(() => {
13512
+ React23.useEffect(() => {
13251
13513
  if (!provision || !ACTIVE_STATES3.has(provision.status)) return void 0;
13252
13514
  const timer = window.setInterval(() => mounted.current && setNow(Date.now()), 1e3);
13253
13515
  return () => window.clearInterval(timer);
13254
13516
  }, [provision?.attemptId, provision?.status]);
13255
- const startProvisioning = React22.useCallback(async (replace = false) => {
13517
+ const startProvisioning = React23.useCallback(async (replace = false) => {
13256
13518
  setBusy(true);
13257
13519
  try {
13258
13520
  if (replace && provision?.attemptId) {
@@ -13270,7 +13532,7 @@ function WhatsappSettingsTab({ rpcCall }) {
13270
13532
  if (mounted.current) setBusy(false);
13271
13533
  }
13272
13534
  }, [invoke, provision?.attemptId]);
13273
- const closeProvision = React22.useCallback(async () => {
13535
+ const closeProvision = React23.useCallback(async () => {
13274
13536
  setBusy(true);
13275
13537
  try {
13276
13538
  if (provision?.attemptId && ACTIVE_STATES3.has(provision.status)) {
@@ -13281,7 +13543,7 @@ function WhatsappSettingsTab({ rpcCall }) {
13281
13543
  if (mounted.current) setBusy(false);
13282
13544
  }
13283
13545
  }, [invoke, provision?.attemptId, provision?.status]);
13284
- React22.useEffect(() => {
13546
+ React23.useEffect(() => {
13285
13547
  const attemptId = provision?.attemptId;
13286
13548
  if (!attemptId || !ACTIVE_STATES3.has(provision.status)) return void 0;
13287
13549
  const controller = new AbortController();
@@ -13322,7 +13584,7 @@ function WhatsappSettingsTab({ rpcCall }) {
13322
13584
  if (timer) window.clearTimeout(timer);
13323
13585
  };
13324
13586
  }, [invoke, loadStatus, provision?.attemptId, provision?.status]);
13325
- const botAction = React22.useCallback(async (account, operation, endpoint, payload) => {
13587
+ const botAction = React23.useCallback(async (account, operation, endpoint, payload) => {
13326
13588
  const snapshotVersion = workspaceFence.beginMutation();
13327
13589
  setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
13328
13590
  if (operation === "reconnect") {
@@ -13394,6 +13656,12 @@ function WhatsappSettingsTab({ rpcCall }) {
13394
13656
  WHATSAPP_ENDPOINTS.setWorkspace,
13395
13657
  { botId: account.botId, workspace }
13396
13658
  ),
13659
+ onAliasSave: (alias) => botAction(
13660
+ account,
13661
+ "alias",
13662
+ WHATSAPP_ENDPOINTS.setAlias,
13663
+ { botId: account.botId, alias }
13664
+ ),
13397
13665
  onModelSave: (selectedModel) => botAction(
13398
13666
  account,
13399
13667
  "model",
@@ -13450,7 +13718,7 @@ function WhatsappSettingsTab({ rpcCall }) {
13450
13718
  h2(Button16, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
13451
13719
  )
13452
13720
  ) : h2(
13453
- React22.Fragment,
13721
+ React23.Fragment,
13454
13722
  null,
13455
13723
  provision?.status === "pending" ? h2(QrPanel5, {
13456
13724
  provision,
@@ -13481,7 +13749,7 @@ var normalizeSnapshot10 = api4.normalizeSnapshot;
13481
13749
  var presentError11 = api4.presentError;
13482
13750
 
13483
13751
  // plugin-src/client/channels/imessage/index.js
13484
- var React23 = __toESM(require("react"), 1);
13752
+ var React24 = __toESM(require("react"), 1);
13485
13753
 
13486
13754
  // plugin-src/client/channels/imessage/styles.js
13487
13755
  var IMESSAGE_STYLE_ID = "xmanrui-dsh-im-imessage-settings";
@@ -13574,10 +13842,10 @@ var IMessageSettingsTab = channel4.SettingsTab;
13574
13842
  var IMessageAccountCard = channel4.AccountCard;
13575
13843
 
13576
13844
  // plugin-src/client/delivery-settings.js
13577
- var React26 = __toESM(require("react"), 1);
13845
+ var React27 = __toESM(require("react"), 1);
13578
13846
 
13579
13847
  // plugin-src/client/access-policy-settings.js
13580
- var React24 = __toESM(require("react"), 1);
13848
+ var React25 = __toESM(require("react"), 1);
13581
13849
  var ACCESS_POLICY_ENDPOINT = "bot.access-policy.set";
13582
13850
  var ACCESS_CHANNEL_DEFINITIONS = Object.freeze({
13583
13851
  weixin: Object.freeze({
@@ -13690,8 +13958,8 @@ function ScenePolicyEditor({
13690
13958
  unsupported = false,
13691
13959
  onChange
13692
13960
  }) {
13693
- const ownerHelpId = React24.useId();
13694
- const emptyAllowlistHelpId = React24.useId();
13961
+ const ownerHelpId = React25.useId();
13962
+ const emptyAllowlistHelpId = React25.useId();
13695
13963
  const allowlist = policy.mode === "allowlist";
13696
13964
  const collectionKey = allowlist ? "users" : "commandPermissionOverrides";
13697
13965
  const branchKey = allowlist ? "allowlist" : "open";
@@ -13743,7 +14011,7 @@ function ScenePolicyEditor({
13743
14011
  h2("strong", null, "\u5F53\u524D\u6E20\u9053\u4E0D\u652F\u6301\u7FA4\u804A"),
13744
14012
  h2("p", null, "\u6B64\u533A\u57DF\u65E0\u9700\u914D\u7F6E\uFF0C\u4FDD\u5B58\u79C1\u804A\u8BBE\u7F6E\u65F6\u4F1A\u4FDD\u7559\u73B0\u6709\u7FA4\u804A\u7B56\u7565\u3002")
13745
14013
  ) : h2(
13746
- React24.Fragment,
14014
+ React25.Fragment,
13747
14015
  null,
13748
14016
  h2(
13749
14017
  "div",
@@ -13884,16 +14152,16 @@ function AccessPolicySettingsPage({ channel: channel5, account, rpcCall, onSaved
13884
14152
  const definition = ACCESS_CHANNEL_DEFINITIONS[channel5];
13885
14153
  const initialPolicy = normalizeAccessPolicy(account?.accessPolicy);
13886
14154
  const initialKey = JSON.stringify(initialPolicy);
13887
- const [draft, setDraft] = React24.useState(() => clonePolicy(
14155
+ const [draft, setDraft] = React25.useState(() => clonePolicy(
13888
14156
  initialPolicy ?? DEFAULT_ACCESS_POLICY
13889
14157
  ));
13890
- const [saving, setSaving] = React24.useState(false);
13891
- const [feedback, setFeedback] = React24.useState(null);
13892
- React24.useEffect(() => {
14158
+ const [saving, setSaving] = React25.useState(false);
14159
+ const [feedback, setFeedback] = React25.useState(null);
14160
+ React25.useEffect(() => {
13893
14161
  const next = normalizeAccessPolicy(account?.accessPolicy);
13894
14162
  setDraft(clonePolicy(next ?? DEFAULT_ACCESS_POLICY));
13895
14163
  }, [account?.botId, initialKey]);
13896
- React24.useEffect(() => {
14164
+ React25.useEffect(() => {
13897
14165
  setFeedback(null);
13898
14166
  }, [account?.botId]);
13899
14167
  if (!definition) {
@@ -13984,7 +14252,7 @@ function AccessPolicySettingsPage({ channel: channel5, account, rpcCall, onSaved
13984
14252
  }
13985
14253
 
13986
14254
  // plugin-src/client/channels/feishu/group-settings.js
13987
- var React25 = __toESM(require("react"), 1);
14255
+ var React26 = __toESM(require("react"), 1);
13988
14256
  var GROUP_MESSAGE_PERMISSION_OPERATION2 = FEISHU_REGISTRATION_OPERATIONS.GROUP_MESSAGE_PERMISSION;
13989
14257
  function SettingsButton({ children, kind = "secondary", className = "", ...props }) {
13990
14258
  return h2("button", {
@@ -14045,9 +14313,9 @@ function GroupResponseModeEditor({
14045
14313
  onAuthorize
14046
14314
  }) {
14047
14315
  const current = normalizeGroupResponseMode(value);
14048
- const [saving, setSaving] = React25.useState(false);
14049
- const [authorizing, setAuthorizing] = React25.useState(false);
14050
- const [error, setError] = React25.useState(null);
14316
+ const [saving, setSaving] = React26.useState(false);
14317
+ const [authorizing, setAuthorizing] = React26.useState(false);
14318
+ const [error, setError] = React26.useState(null);
14051
14319
  const change = async (event) => {
14052
14320
  const next = normalizeGroupResponseMode(event.target.value);
14053
14321
  if (next === current || saving || disabled) return;
@@ -14128,8 +14396,8 @@ function GroupResponseModeEditor({
14128
14396
  }
14129
14397
  function GroupTopicReplyEditor({ value = false, disabled = false, onSave }) {
14130
14398
  const current = value === true ? "on" : "off";
14131
- const [saving, setSaving] = React25.useState(false);
14132
- const [error, setError] = React25.useState(null);
14399
+ const [saving, setSaving] = React26.useState(false);
14400
+ const [error, setError] = React26.useState(null);
14133
14401
  const change = async (event) => {
14134
14402
  const next = event.target.value === "on";
14135
14403
  if ((next ? "on" : "off") === current || saving || disabled) return;
@@ -14316,14 +14584,14 @@ function PermissionFlow({ provision, now, busy, botName, onRetry, onCancel, onCl
14316
14584
  );
14317
14585
  }
14318
14586
  function FeishuGroupSettingsPage({ account, rpcCall }) {
14319
- const [settings, setSettings] = React25.useState(() => groupSettingsFrom(account));
14320
- const [refreshing, setRefreshing] = React25.useState(false);
14321
- const [refreshError, setRefreshError] = React25.useState(null);
14322
- const [provision, setProvision] = React25.useState(null);
14323
- const [provisionBusy, setProvisionBusy] = React25.useState(false);
14324
- const [now, setNow] = React25.useState(() => Date.now());
14325
- const mounted = React25.useRef(true);
14326
- React25.useEffect(() => {
14587
+ const [settings, setSettings] = React26.useState(() => groupSettingsFrom(account));
14588
+ const [refreshing, setRefreshing] = React26.useState(false);
14589
+ const [refreshError, setRefreshError] = React26.useState(null);
14590
+ const [provision, setProvision] = React26.useState(null);
14591
+ const [provisionBusy, setProvisionBusy] = React26.useState(false);
14592
+ const [now, setNow] = React26.useState(() => Date.now());
14593
+ const mounted = React26.useRef(true);
14594
+ React26.useEffect(() => {
14327
14595
  setSettings(groupSettingsFrom(account));
14328
14596
  }, [
14329
14597
  account.botId,
@@ -14331,22 +14599,22 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14331
14599
  account.groupTopicReply,
14332
14600
  account.groupMessagePermissionGranted
14333
14601
  ]);
14334
- React25.useEffect(() => {
14602
+ React26.useEffect(() => {
14335
14603
  mounted.current = true;
14336
14604
  return () => {
14337
14605
  mounted.current = false;
14338
14606
  };
14339
14607
  }, []);
14340
- const invoke = React25.useCallback(async (endpoint, payload = {}, signal) => {
14608
+ const invoke = React26.useCallback(async (endpoint, payload = {}, signal) => {
14341
14609
  if (typeof rpcCall !== "function") throw new Error("\u98DE\u4E66\u7FA4\u804A\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
14342
14610
  return unwrapRpcResult3(await rpcCall(endpoint, payload, signal));
14343
14611
  }, [rpcCall]);
14344
- const applySnapshot = React25.useCallback((value) => {
14612
+ const applySnapshot = React26.useCallback((value) => {
14345
14613
  const result = targetBotFromSnapshot(value, account.botId);
14346
14614
  if (mounted.current) setSettings(groupSettingsFrom(result.bot));
14347
14615
  return result;
14348
14616
  }, [account.botId]);
14349
- const loadSettings = React25.useCallback(async ({ signal, restoreProvisioning = false } = {}) => {
14617
+ const loadSettings = React26.useCallback(async ({ signal, restoreProvisioning = false } = {}) => {
14350
14618
  setRefreshing(true);
14351
14619
  setRefreshError(null);
14352
14620
  try {
@@ -14375,16 +14643,16 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14375
14643
  if (!signal?.aborted && mounted.current) setRefreshing(false);
14376
14644
  }
14377
14645
  }, [account.botId, applySnapshot, invoke]);
14378
- React25.useEffect(() => {
14646
+ React26.useEffect(() => {
14379
14647
  const controller = new AbortController();
14380
14648
  void loadSettings({ signal: controller.signal, restoreProvisioning: true });
14381
14649
  return () => controller.abort();
14382
14650
  }, [loadSettings]);
14383
- const saveSetting = React25.useCallback(async (endpoint, payload) => {
14651
+ const saveSetting = React26.useCallback(async (endpoint, payload) => {
14384
14652
  const value = await invoke(endpoint, { botId: account.botId, ...payload });
14385
14653
  applySnapshot(value);
14386
14654
  }, [account.botId, applySnapshot, invoke]);
14387
- const startAuthorization = React25.useCallback(async ({ replace = false } = {}) => {
14655
+ const startAuthorization = React26.useCallback(async ({ replace = false } = {}) => {
14388
14656
  if (provisionBusy) return;
14389
14657
  const previousAttemptId = provision?.attemptId;
14390
14658
  setProvisionBusy(true);
@@ -14425,13 +14693,13 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14425
14693
  if (mounted.current) setProvisionBusy(false);
14426
14694
  }
14427
14695
  }, [account.botId, invoke, provision?.attemptId, provisionBusy]);
14428
- const finishAuthorization = React25.useCallback(async (signal) => {
14696
+ const finishAuthorization = React26.useCallback(async (signal) => {
14429
14697
  const bot = await loadSettings({ signal, restoreProvisioning: false });
14430
14698
  if (signal?.aborted || !mounted.current) return;
14431
14699
  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");
14432
14700
  setProvision(null);
14433
14701
  }, [loadSettings]);
14434
- React25.useEffect(() => {
14702
+ React26.useEffect(() => {
14435
14703
  if (!provision?.attemptId || !["qr", "connecting"].includes(provision.phase) || provision.expired) return void 0;
14436
14704
  const timerHost = globalThis.window ?? globalThis;
14437
14705
  const controller = new AbortController();
@@ -14475,7 +14743,7 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14475
14743
  timerHost.clearTimeout(timer);
14476
14744
  };
14477
14745
  }, [account.botId, finishAuthorization, invoke, provision]);
14478
- React25.useEffect(() => {
14746
+ React26.useEffect(() => {
14479
14747
  if (!provision?.attemptId || provision.phase !== "qr" || provision.expired) return void 0;
14480
14748
  const timerHost = globalThis.window ?? globalThis;
14481
14749
  const tick = () => {
@@ -14489,7 +14757,7 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14489
14757
  const timer = timerHost.setInterval(tick, 1e3);
14490
14758
  return () => timerHost.clearInterval(timer);
14491
14759
  }, [provision?.attemptId, provision?.expired, provision?.expiresAt, provision?.phase]);
14492
- const cancelAuthorization = React25.useCallback(async () => {
14760
+ const cancelAuthorization = React26.useCallback(async () => {
14493
14761
  if (!provision?.attemptId || provisionBusy) {
14494
14762
  setProvision(null);
14495
14763
  return;
@@ -14810,13 +15078,13 @@ function TargetForm({
14810
15078
  }) {
14811
15079
  const editing = mode === "edit";
14812
15080
  const initialKind = initialValue?.kind && definition.fields[initialValue.kind] ? initialValue.kind : definition.kinds[0].value;
14813
- const [targetId, setTargetId] = React26.useState(initialValue?.targetId ?? "");
14814
- const [name2, setName] = React26.useState(initialValue?.name ?? "");
14815
- const [kind, setKind] = React26.useState(initialKind);
14816
- const [route, setRoute] = React26.useState(initialValue?.route ?? {});
14817
- const [error, setError] = React26.useState(null);
14818
- const [testing, setTesting] = React26.useState(false);
14819
- const [testState, setTestState] = React26.useState(null);
15081
+ const [targetId, setTargetId] = React27.useState(initialValue?.targetId ?? "");
15082
+ const [name2, setName] = React27.useState(initialValue?.name ?? "");
15083
+ const [kind, setKind] = React27.useState(initialKind);
15084
+ const [route, setRoute] = React27.useState(initialValue?.route ?? {});
15085
+ const [error, setError] = React27.useState(null);
15086
+ const [testing, setTesting] = React27.useState(false);
15087
+ const [testState, setTestState] = React27.useState(null);
14820
15088
  const currentTarget = () => {
14821
15089
  const normalizedRoute = Object.fromEntries(fieldsFor(definition, kind).map((field) => {
14822
15090
  const raw = String(route[field.key] ?? "").trim();
@@ -15033,7 +15301,7 @@ function TargetSuggestionPicker({
15033
15301
  suggestions.map((suggestion, index) => {
15034
15302
  const identity = routeIdentity(definition, suggestion);
15035
15303
  const added = configured.has(identity);
15036
- return React26.createElement("option", {
15304
+ return React27.createElement("option", {
15037
15305
  key: suggestion.id ?? suggestion.suggestionId ?? `${identity}:${index}`,
15038
15306
  value: String(index),
15039
15307
  disabled: added
@@ -15050,11 +15318,11 @@ function TargetSuggestionPicker({
15050
15318
  );
15051
15319
  }
15052
15320
  function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, onEdit }) {
15053
- const [action, setAction] = React26.useState(null);
15054
- const [testState, setTestState] = React26.useState(null);
15055
- const [syncFeedback, setSyncFeedback] = React26.useState(null);
15056
- const [copyState, setCopyState] = React26.useState(null);
15057
- const [confirmDelete, setConfirmDelete] = React26.useState(false);
15321
+ const [action, setAction] = React27.useState(null);
15322
+ const [testState, setTestState] = React27.useState(null);
15323
+ const [syncFeedback, setSyncFeedback] = React27.useState(null);
15324
+ const [copyState, setCopyState] = React27.useState(null);
15325
+ const [confirmDelete, setConfirmDelete] = React27.useState(false);
15058
15326
  const sessionSync = target.sessionSync ?? { enabled: false, state: "unavailable" };
15059
15327
  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";
15060
15328
  const testTarget = async () => {
@@ -15117,7 +15385,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
15117
15385
  h2(
15118
15386
  "div",
15119
15387
  { className: "dim-targetTitle" },
15120
- React26.createElement("strong", null, target.name || target.targetId),
15388
+ React27.createElement("strong", null, target.name || target.targetId),
15121
15389
  h2("span", null, kindLabel(definition, target.kind))
15122
15390
  ),
15123
15391
  h2("code", null, `targetId: ${target.targetId}`)
@@ -15203,26 +15471,26 @@ function DeliveryTargetSettingsPage({
15203
15471
  onBack
15204
15472
  }) {
15205
15473
  const definition = CHANNEL_DEFINITIONS[channel5];
15206
- const [activeTabId, setActiveTabId] = React26.useState(BOT_SETTINGS_TABS[0].id);
15207
- const [phase, setPhase] = React26.useState("loading");
15208
- const [targets, setTargets] = React26.useState([]);
15209
- const [suggestionPhase, setSuggestionPhase] = React26.useState("idle");
15210
- const [suggestions, setSuggestions] = React26.useState([]);
15211
- const [suggestionError, setSuggestionError] = React26.useState(null);
15212
- const [error, setError] = React26.useState(null);
15213
- const [editor, setEditor] = React26.useState(null);
15214
- const [saving, setSaving] = React26.useState(false);
15215
- const [botCopyState, setBotCopyState] = React26.useState(null);
15216
- const [accessPolicy, setAccessPolicy] = React26.useState(account.accessPolicy);
15217
- const mounted = React26.useRef(true);
15218
- React26.useEffect(() => {
15474
+ const [activeTabId, setActiveTabId] = React27.useState(BOT_SETTINGS_TABS[0].id);
15475
+ const [phase, setPhase] = React27.useState("loading");
15476
+ const [targets, setTargets] = React27.useState([]);
15477
+ const [suggestionPhase, setSuggestionPhase] = React27.useState("idle");
15478
+ const [suggestions, setSuggestions] = React27.useState([]);
15479
+ const [suggestionError, setSuggestionError] = React27.useState(null);
15480
+ const [error, setError] = React27.useState(null);
15481
+ const [editor, setEditor] = React27.useState(null);
15482
+ const [saving, setSaving] = React27.useState(false);
15483
+ const [botCopyState, setBotCopyState] = React27.useState(null);
15484
+ const [accessPolicy, setAccessPolicy] = React27.useState(account.accessPolicy);
15485
+ const mounted = React27.useRef(true);
15486
+ React27.useEffect(() => {
15219
15487
  setAccessPolicy(account.accessPolicy);
15220
15488
  }, [account.botId, account.accessPolicy]);
15221
- const invoke = React26.useCallback(async (endpoint, payload = {}, signal) => {
15489
+ const invoke = React27.useCallback(async (endpoint, payload = {}, signal) => {
15222
15490
  if (typeof rpcCall !== "function") throw new Error("\u6295\u9012\u76EE\u6807\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
15223
15491
  return unwrapRpcResult13(await rpcCall(endpoint, payload, signal));
15224
15492
  }, [rpcCall]);
15225
- const loadTargets = React26.useCallback(async ({ signal, silent = false } = {}) => {
15493
+ const loadTargets = React27.useCallback(async ({ signal, silent = false } = {}) => {
15226
15494
  if (!silent) setPhase("loading");
15227
15495
  setError(null);
15228
15496
  try {
@@ -15236,7 +15504,7 @@ function DeliveryTargetSettingsPage({
15236
15504
  setPhase("error");
15237
15505
  }
15238
15506
  }, [account.botId, invoke]);
15239
- const loadSuggestions = React26.useCallback(async () => {
15507
+ const loadSuggestions = React27.useCallback(async () => {
15240
15508
  setSuggestionPhase("loading");
15241
15509
  setSuggestionError(null);
15242
15510
  try {
@@ -15250,7 +15518,7 @@ function DeliveryTargetSettingsPage({
15250
15518
  setSuggestionPhase("error");
15251
15519
  }
15252
15520
  }, [account.botId, definition, invoke]);
15253
- React26.useEffect(() => {
15521
+ React27.useEffect(() => {
15254
15522
  mounted.current = true;
15255
15523
  const controller = new AbortController();
15256
15524
  void loadTargets({ signal: controller.signal });
@@ -15372,7 +15640,7 @@ function DeliveryTargetSettingsPage({
15372
15640
  account,
15373
15641
  rpcCall: accessRpcCall
15374
15642
  }) : h2(
15375
- React26.Fragment,
15643
+ React27.Fragment,
15376
15644
  null,
15377
15645
  h2(
15378
15646
  "section",
@@ -15483,7 +15751,7 @@ function DeliveryTargetSettingsPage({
15483
15751
  }
15484
15752
 
15485
15753
  // plugin-src/client/global-settings.js
15486
- var React27 = __toESM(require("react"), 1);
15754
+ var React28 = __toESM(require("react"), 1);
15487
15755
 
15488
15756
  // src/channels/shared/inbound-ttl.mjs
15489
15757
  var DEFAULT_INBOUND_TTL_HOURS = 168;
@@ -15545,29 +15813,29 @@ function GlobalButton({ children, kind = "secondary", className = "", ...props }
15545
15813
  }, children);
15546
15814
  }
15547
15815
  function GlobalSettingsPanel({ rpcCall }) {
15548
- const [phase, setPhase] = React27.useState("loading");
15549
- const [loadError, setLoadError] = React27.useState(null);
15550
- const [ttlInput, setTtlInput] = React27.useState("");
15551
- const [savedTtl, setSavedTtl] = React27.useState(null);
15552
- const [ttlError, setTtlError] = React27.useState(false);
15553
- const [saveError, setSaveError] = React27.useState(null);
15554
- const [saveSucceeded, setSaveSucceeded] = React27.useState(false);
15555
- const [isSaving, setIsSaving] = React27.useState(false);
15556
- const [sweepConfirming, setSweepConfirming] = React27.useState(false);
15557
- const [sweeping, setSweeping] = React27.useState(false);
15558
- const ttlErrorId = React27.useId();
15559
- const ttlHintsId = React27.useId();
15560
- const sweepTriggerId = React27.useId();
15561
- const sweepConfirmId = React27.useId();
15562
- const sweepConfirmTextId = React27.useId();
15563
- const sweepConfirmButtonId = React27.useId();
15564
- const mounted = React27.useRef(true);
15565
- const saving = React27.useRef(false);
15566
- const invoke = React27.useCallback(async (endpoint, payload = {}, signal) => {
15816
+ const [phase, setPhase] = React28.useState("loading");
15817
+ const [loadError, setLoadError] = React28.useState(null);
15818
+ const [ttlInput, setTtlInput] = React28.useState("");
15819
+ const [savedTtl, setSavedTtl] = React28.useState(null);
15820
+ const [ttlError, setTtlError] = React28.useState(false);
15821
+ const [saveError, setSaveError] = React28.useState(null);
15822
+ const [saveSucceeded, setSaveSucceeded] = React28.useState(false);
15823
+ const [isSaving, setIsSaving] = React28.useState(false);
15824
+ const [sweepConfirming, setSweepConfirming] = React28.useState(false);
15825
+ const [sweeping, setSweeping] = React28.useState(false);
15826
+ const ttlErrorId = React28.useId();
15827
+ const ttlHintsId = React28.useId();
15828
+ const sweepTriggerId = React28.useId();
15829
+ const sweepConfirmId = React28.useId();
15830
+ const sweepConfirmTextId = React28.useId();
15831
+ const sweepConfirmButtonId = React28.useId();
15832
+ const mounted = React28.useRef(true);
15833
+ const saving = React28.useRef(false);
15834
+ const invoke = React28.useCallback(async (endpoint, payload = {}, signal) => {
15567
15835
  if (typeof rpcCall !== "function") throw new Error("\u901A\u7528\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
15568
15836
  return unwrapRpcResult14(await rpcCall(endpoint, payload, signal));
15569
15837
  }, [rpcCall]);
15570
- const loadSettings = React27.useCallback(async ({ signal } = {}) => {
15838
+ const loadSettings = React28.useCallback(async ({ signal } = {}) => {
15571
15839
  setPhase("loading");
15572
15840
  setLoadError(null);
15573
15841
  try {
@@ -15591,7 +15859,7 @@ function GlobalSettingsPanel({ rpcCall }) {
15591
15859
  setPhase("error");
15592
15860
  }
15593
15861
  }, [invoke]);
15594
- React27.useEffect(() => {
15862
+ React28.useEffect(() => {
15595
15863
  mounted.current = true;
15596
15864
  const controller = new AbortController();
15597
15865
  void loadSettings({ signal: controller.signal });
@@ -15600,7 +15868,7 @@ function GlobalSettingsPanel({ rpcCall }) {
15600
15868
  controller.abort();
15601
15869
  };
15602
15870
  }, [loadSettings]);
15603
- React27.useEffect(() => {
15871
+ React28.useEffect(() => {
15604
15872
  if (!sweepConfirming) return;
15605
15873
  globalThis.document?.getElementById(sweepConfirmButtonId)?.focus();
15606
15874
  }, [sweepConfirmButtonId, sweepConfirming]);
@@ -15908,6 +16176,32 @@ function replacePageLocation(url, location = globalThis.location) {
15908
16176
  // plugin-src/client/styles.js
15909
16177
  var IM_STYLE_ID = "xmanrui-dsh-im-settings";
15910
16178
  var CSS13 = String.raw`
16179
+ .dim-aliasName { display: flex; align-items: center; gap: 4px; min-width: 0; }
16180
+ .dim-aliasName h3 { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
16181
+ .dim-aliasEntry { display: inline-flex; flex: none; }
16182
+ .dim-aliasEdit { display: grid; place-items: center; width: 28px; height: 28px; padding: 4px; border: 0; border-radius: 5px; color: var(--dsw-alias-label-secondary, #646a73); background: transparent; cursor: pointer; }
16183
+ .dim-aliasEdit:hover:not(:disabled) { color: var(--dsw-alias-state-business-primary, #3370ff); background: var(--dsw-alias-interactive-bg-hover, #f7f8fa); }
16184
+ .dim-aliasDialog { box-sizing: border-box; width: min(380px, calc(100% - 32px)); max-height: calc(100dvh - 32px); overflow-y: auto; padding: 22px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 12px; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-bg-layer-3, #fff); box-shadow: 0 12px 36px rgb(0 0 0 / 18%); font: 13px/1.5 -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
16185
+ .dim-aliasDialog * { box-sizing: border-box; }
16186
+ .dim-aliasDialog::backdrop { background: rgb(15 17 21 / 30%); }
16187
+ .dim-aliasHeader { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 18px; }
16188
+ .dim-aliasHeader h3 { margin: 0; font-size: 16px; }
16189
+ .dim-aliasDialog button { font: inherit; cursor: pointer; }
16190
+ .dim-aliasDialog .dim-aliasClose { width: 28px; height: 28px; padding: 0; border: 0; border-radius: 5px; background: transparent; color: var(--dsw-alias-label-secondary, #646a73); font-size: 20px; }
16191
+ .dim-aliasOriginal { display: flex; flex-wrap: wrap; gap: 6px 14px; padding: 10px 12px; margin-bottom: 18px; border-radius: 6px; background: var(--dsw-alias-bg-layer-2, #f5f6f7); overflow-wrap: anywhere; }
16192
+ .dim-aliasOriginal > span:first-child { flex: none; color: var(--dsw-alias-label-secondary, #646a73); }
16193
+ .dim-aliasDialog label { display: block; margin-bottom: 7px; }
16194
+ .dim-aliasDialog input { width: 100%; min-height: 38px; padding: 8px 10px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 6px; color: inherit; background: var(--dsw-alias-bg-layer-1, #fff); font: inherit; }
16195
+ .dim-aliasHelp { margin: 8px 0 0; color: var(--dsw-alias-label-secondary, #646a73); font-size: 12px; }
16196
+ .dim-aliasError { color: var(--dsw-alias-state-danger-primary, #c53030); overflow-wrap: anywhere; }
16197
+ .dim-aliasFooter { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 14px; margin-top: 24px; }
16198
+ .dim-aliasRestore { padding: 4px 0; border: 0; color: var(--dsw-alias-state-business-primary, #3370ff); background: transparent; }
16199
+ .dim-aliasActions { display: flex; gap: 8px; margin-left: auto; }
16200
+ .dim-aliasActions button { padding: 7px 14px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 6px; color: inherit; background: var(--dsw-alias-bg-layer-1, #fff); }
16201
+ .dim-aliasActions .dim-aliasSave { color: #fff; border-color: var(--dsw-alias-state-business-primary, #3370ff); background: var(--dsw-alias-state-business-primary, #3370ff); }
16202
+ .dim-aliasEdit:disabled, .dim-aliasDialog button:disabled, .dim-aliasDialog input:disabled { opacity: .55; cursor: not-allowed; }
16203
+ .dim-aliasEdit:focus-visible, .dim-aliasDialog button:focus-visible, .dim-aliasDialog input:focus-visible { outline: 2px solid var(--dsw-alias-state-business-primary, #3370ff); outline-offset: 2px; }
16204
+ @media (pointer: coarse) { .dim-aliasEdit, .dim-aliasDialog button { min-width: 44px; min-height: 44px; } .dim-aliasDialog input { font-size: 16px; } }
15911
16205
  .dim-page {
15912
16206
  --dim-blue: var(--dsw-alias-state-business-primary, #3370ff);
15913
16207
  --dim-blue-soft: color-mix(in srgb, var(--dim-blue) 9%, transparent);
@@ -16837,8 +17131,8 @@ function installSessionChannelLogos(document2 = globalThis.document) {
16837
17131
  }
16838
17132
 
16839
17133
  // plugin-src/client/update-panel.js
16840
- var React28 = __toESM(require("react"), 1);
16841
- var import_react_dom3 = require("react-dom");
17134
+ var React29 = __toESM(require("react"), 1);
17135
+ var import_react_dom4 = require("react-dom");
16842
17136
  var import_valid = __toESM(require_valid(), 1);
16843
17137
  var import_rcompare = __toESM(require_rcompare(), 1);
16844
17138
  var UPDATE_RPC_CHANNEL = "/dsh-im";
@@ -16927,11 +17221,11 @@ function manualUpdateCommand(snapshot) {
16927
17221
  return `dsh plugin --profile ${profileArgument} add -w @xmanrui/dsh-im@${version}`;
16928
17222
  }
16929
17223
  function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
16930
- const [copyState, setCopyState] = React28.useState("idle");
16931
- const commandRef = React28.useRef(null);
16932
- const mounted = React28.useRef(false);
16933
- const copying = React28.useRef(false);
16934
- React28.useEffect(() => {
17224
+ const [copyState, setCopyState] = React29.useState("idle");
17225
+ const commandRef = React29.useRef(null);
17226
+ const mounted = React29.useRef(false);
17227
+ const copying = React29.useRef(false);
17228
+ React29.useEffect(() => {
16935
17229
  mounted.current = true;
16936
17230
  return () => {
16937
17231
  mounted.current = false;
@@ -16963,7 +17257,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
16963
17257
  { className: "dim-updateManual", "aria-label": "\u624B\u5DE5\u66F4\u65B0" },
16964
17258
  h2("h4", { className: "dim-updateManualHeading" }, "\u624B\u5DE5\u66F4\u65B0"),
16965
17259
  command ? h2(
16966
- React28.Fragment,
17260
+ React29.Fragment,
16967
17261
  null,
16968
17262
  h2("p", { className: "dim-updateManualHint" }, "\u81EA\u52A8\u66F4\u65B0\u5931\u8D25\u53EF\u4EE5\u4F7F\u7528\u547D\u4EE4\u66F4\u65B0\uFF1A"),
16969
17263
  h2(
@@ -16999,7 +17293,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
16999
17293
  "aria-hidden": "true",
17000
17294
  focusable: "false"
17001
17295
  }, copyState === "copied" ? h2("path", { d: "m4 10 4 4 8-8" }) : h2(
17002
- React28.Fragment,
17296
+ React29.Fragment,
17003
17297
  null,
17004
17298
  h2("rect", { x: 7, y: 7, width: 10, height: 11, rx: 1.5 }),
17005
17299
  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" })
@@ -17024,10 +17318,10 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
17024
17318
  );
17025
17319
  }
17026
17320
  function UpdateDialog({ children, onClose }) {
17027
- const dialogRef = React28.useRef(null);
17028
- const titleId = React28.useId();
17029
- const descriptionId = React28.useId();
17030
- React28.useEffect(() => {
17321
+ const dialogRef = React29.useRef(null);
17322
+ const titleId = React29.useId();
17323
+ const descriptionId = React29.useId();
17324
+ React29.useEffect(() => {
17031
17325
  const previous = globalThis.document?.activeElement;
17032
17326
  dialogRef.current?.focus?.();
17033
17327
  return () => {
@@ -17082,22 +17376,22 @@ function UpdateDialog({ children, onClose }) {
17082
17376
  children
17083
17377
  )
17084
17378
  );
17085
- return typeof document !== "undefined" && document.body ? (0, import_react_dom3.createPortal)(content, document.body) : content;
17379
+ return typeof document !== "undefined" && document.body ? (0, import_react_dom4.createPortal)(content, document.body) : content;
17086
17380
  }
17087
17381
  function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17088
- const [snapshot, setSnapshot] = React28.useState(null);
17089
- const [action, setAction] = React28.useState("status");
17090
- const [error, setError] = React28.useState(null);
17091
- const [open, setOpen] = React28.useState(false);
17092
- const [uncertainInstall, setUncertainInstall] = React28.useState(false);
17093
- const mounted = React28.useRef(false);
17094
- const busy = React28.useRef(false);
17095
- const readController = React28.useRef(null);
17096
- const pollReadController = React28.useRef(null);
17097
- const installRequest = React28.useRef(null);
17098
- const onStatusRef = React28.useRef(onStatus);
17382
+ const [snapshot, setSnapshot] = React29.useState(null);
17383
+ const [action, setAction] = React29.useState("status");
17384
+ const [error, setError] = React29.useState(null);
17385
+ const [open, setOpen] = React29.useState(false);
17386
+ const [uncertainInstall, setUncertainInstall] = React29.useState(false);
17387
+ const mounted = React29.useRef(false);
17388
+ const busy = React29.useRef(false);
17389
+ const readController = React29.useRef(null);
17390
+ const pollReadController = React29.useRef(null);
17391
+ const installRequest = React29.useRef(null);
17392
+ const onStatusRef = React29.useRef(onStatus);
17099
17393
  onStatusRef.current = onStatus;
17100
- const accept = React28.useCallback((next) => {
17394
+ const accept = React29.useCallback((next) => {
17101
17395
  setSnapshot(next);
17102
17396
  onStatusRef.current?.(next);
17103
17397
  }, []);
@@ -17106,7 +17400,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17106
17400
  setUncertainInstall(false);
17107
17401
  accept(next);
17108
17402
  };
17109
- const invoke = React28.useCallback(async (endpoint, payload = {}, signal) => {
17403
+ const invoke = React29.useCallback(async (endpoint, payload = {}, signal) => {
17110
17404
  if (typeof rpcCall !== "function") {
17111
17405
  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");
17112
17406
  unavailable.code = "update-unavailable";
@@ -17114,7 +17408,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17114
17408
  }
17115
17409
  return unwrapSnapshot(await rpcCall(endpoint, payload, signal));
17116
17410
  }, [rpcCall]);
17117
- React28.useEffect(() => {
17411
+ React29.useEffect(() => {
17118
17412
  mounted.current = true;
17119
17413
  busy.current = true;
17120
17414
  const controller = new AbortController();
@@ -17137,7 +17431,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17137
17431
  const activeJob = ACTIVE_STATES4.has(snapshot?.job?.state);
17138
17432
  const restartRequired = snapshot?.job?.state === "restart-required" || snapshot?.blockedReason === "pending-restart";
17139
17433
  const shouldPoll = activeJob || uncertainInstall;
17140
- React28.useEffect(() => {
17434
+ React29.useEffect(() => {
17141
17435
  if (!shouldPoll) return void 0;
17142
17436
  let controller;
17143
17437
  const scheduler = createPollScheduler({
@@ -17235,7 +17529,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17235
17529
  const manualCommand = manualUpdateCommand(snapshot);
17236
17530
  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";
17237
17531
  return h2(
17238
- React28.Fragment,
17532
+ React29.Fragment,
17239
17533
  null,
17240
17534
  h2("button", {
17241
17535
  type: "button",
@@ -17260,13 +17554,13 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17260
17554
  h2("dt", null, "\u8FD0\u884C\u7248\u672C"),
17261
17555
  h2("dd", null, `v${snapshot?.runningVersion ?? clientVersion}`),
17262
17556
  snapshot?.installedVersion && snapshot.installedVersion !== snapshot.runningVersion ? h2(
17263
- React28.Fragment,
17557
+ React29.Fragment,
17264
17558
  null,
17265
17559
  h2("dt", null, "\u5DF2\u5B89\u88C5\u7248\u672C"),
17266
17560
  h2("dd", null, `v${snapshot.installedVersion}`)
17267
17561
  ) : null,
17268
17562
  targetVersion ? h2(
17269
- React28.Fragment,
17563
+ React29.Fragment,
17270
17564
  null,
17271
17565
  h2("dt", null, "\u76EE\u6807\u7248\u672C"),
17272
17566
  h2("dd", null, `v${targetVersion}`)
@@ -17487,23 +17781,23 @@ function IMSettingsTab({
17487
17781
  browserLocation = globalThis.location,
17488
17782
  navigateToRecoveryUrl = replacePageLocation
17489
17783
  }) {
17490
- const [selected, setSelected] = React29.useState("weixin");
17491
- const [loopbackRecovery, setLoopbackRecovery] = React29.useState(null);
17492
- const [runningVersion, setRunningVersion] = React29.useState(IM_PLUGIN_VERSION);
17493
- const [deliverySettings, setDeliverySettings] = React29.useState(null);
17494
- const githubTooltipId = React29.useId();
17495
- const generalSettingsTooltipId = React29.useId();
17784
+ const [selected, setSelected] = React30.useState("weixin");
17785
+ const [loopbackRecovery, setLoopbackRecovery] = React30.useState(null);
17786
+ const [runningVersion, setRunningVersion] = React30.useState(IM_PLUGIN_VERSION);
17787
+ const [deliverySettings, setDeliverySettings] = React30.useState(null);
17788
+ const githubTooltipId = React30.useId();
17789
+ const generalSettingsTooltipId = React30.useId();
17496
17790
  const globalSettingsSelected = selected === GLOBAL_SETTINGS_TAB_ID;
17497
17791
  const active = CHANNELS.find((channel5) => channel5.id === selected) ?? CHANNELS[0];
17498
17792
  const activeTabId = globalSettingsSelected ? "dim-general-settings-trigger" : `dim-tab-${active.id}`;
17499
17793
  const activePanelId = globalSettingsSelected ? `dim-panel-${GLOBAL_SETTINGS_TAB_ID}` : `dim-panel-${active.id}`;
17500
- const reportLoopbackRecovery = React29.useCallback((recovery) => {
17794
+ const reportLoopbackRecovery = React30.useCallback((recovery) => {
17501
17795
  setLoopbackRecovery((current) => current?.url === recovery.url ? current : recovery);
17502
17796
  }, []);
17503
- const reportUpdateStatus = React29.useCallback((snapshot) => {
17797
+ const reportUpdateStatus = React30.useCallback((snapshot) => {
17504
17798
  setRunningVersion(snapshot.runningVersion);
17505
17799
  }, []);
17506
- const rpcCalls = React29.useMemo(() => createLoopbackAwareRpcCalls({
17800
+ const rpcCalls = React30.useMemo(() => createLoopbackAwareRpcCalls({
17507
17801
  dingtalkRpcCall,
17508
17802
  discordRpcCall,
17509
17803
  feishuRpcCall,
@@ -17541,7 +17835,7 @@ function IMSettingsTab({
17541
17835
  weixinRpcCall,
17542
17836
  whatsappRpcCall
17543
17837
  ]);
17544
- const botSettingsContext = React29.useMemo(() => Object.freeze({
17838
+ const botSettingsContext = React30.useMemo(() => Object.freeze({
17545
17839
  openBotSettings: setDeliverySettings
17546
17840
  }), []);
17547
17841
  return h2(