@xmanrui/dsh-im 4.18.1 → 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 (47) hide show
  1. package/README.en.md +1 -0
  2. package/README.md +1 -0
  3. package/lib/client.js +805 -515
  4. package/lib/index.js +269 -267
  5. package/package.json +1 -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/session-sync-coordinator.mjs +19 -1
  38. package/src/channels/feishu/bridge.mjs +370 -7
  39. package/src/channels/feishu/feishu-cards.mjs +1 -1
  40. package/src/channels/feishu/feishu-runtime.mjs +6 -0
  41. package/src/channels/feishu/state-store.mjs +17 -0
  42. package/src/channels/shared/bot-alias.mjs +29 -0
  43. package/src/channels/shared/bot-workspace-store.mjs +71 -3
  44. package/src/channels/shared/i18n-en/shared-a.mjs +2 -2
  45. package/src/channels/shared/message-failure.mjs +2 -1
  46. package/src/channels/shared/model-command.mjs +3 -2
  47. package/src/channels/shared/session-sync-registry.mjs +34 -0
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.1",
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",
@@ -891,6 +891,23 @@ function OfficeLogoGlyph({ size } = {}) {
891
891
  );
892
892
  }
893
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
+
894
911
  // plugin-src/client/agent-preset.js
895
912
  var React3 = __toESM(require("react"), 1);
896
913
 
@@ -899,6 +916,16 @@ var React2 = __toESM(require("react"), 1);
899
916
  var IM_LOCALE_NAMESPACE = "dsh-im";
900
917
  var EN = Object.freeze({
901
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).",
902
929
  " macOS Messages \u8FDE\u63A5": " macOS Messages connection",
903
930
  "\u63A5\u5165 iMessage": "Connect iMessage",
904
931
  "\u5148\u5728 macOS \u7CFB\u7EDF\u8BBE\u7F6E\u4E2D\u6388\u4E88 Messages \u6743\u9650\u3002": "Grant Messages permissions in macOS System Settings first.",
@@ -2748,7 +2775,8 @@ var DINGTALK_ENDPOINTS = Object.freeze({
2748
2775
  setModel: SET_MODEL_ENDPOINT,
2749
2776
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
2750
2777
  setContextEnhancement: "bot.context-enhancement.set",
2751
- setAccessPolicy: "bot.access-policy.set"
2778
+ setAccessPolicy: "bot.access-policy.set",
2779
+ setAlias: "bot.alias.set"
2752
2780
  });
2753
2781
  var ACCOUNT_STATES = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
2754
2782
  var SNAPSHOT_STATES = /* @__PURE__ */ new Set(["disconnected", "offline", "provisioning", "connected", "degraded"]);
@@ -2896,6 +2924,7 @@ function normalizeBot(value) {
2896
2924
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
2897
2925
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
2898
2926
  bot: {
2927
+ ...normalizeBotAlias(bot),
2899
2928
  name: optionalString(bot.name, 100) ?? "\u9489\u9489\u673A\u5668\u4EBA",
2900
2929
  clientIdMasked: optionalString(bot.clientIdMasked, 140) ?? "\u5DF2\u5B89\u5168\u4FDD\u5B58"
2901
2930
  },
@@ -2958,11 +2987,174 @@ function formatRemaining(milliseconds) {
2958
2987
  return `${String(Math.floor(seconds / 60)).padStart(2, "0")}:${String(seconds % 60).padStart(2, "0")}`;
2959
2988
  }
2960
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
+
2961
3153
  // plugin-src/client/channels/dingtalk/index.js
2962
- var React12 = __toESM(require("react"), 1);
3154
+ var React13 = __toESM(require("react"), 1);
2963
3155
 
2964
3156
  // plugin-src/client/credential-binding.js
2965
- var React5 = __toESM(require("react"), 1);
3157
+ var React6 = __toESM(require("react"), 1);
2966
3158
  function ActionIcon({ children }) {
2967
3159
  return h2("svg", {
2968
3160
  className: "dim-actionIcon",
@@ -3022,9 +3214,9 @@ function CredentialBindingPanel({
3022
3214
  onSubmit,
3023
3215
  onCancel
3024
3216
  }) {
3025
- const [identity, setIdentity] = React5.useState("");
3026
- const [secret, setSecret] = React5.useState("");
3027
- const headingId = React5.useId();
3217
+ const [identity, setIdentity] = React6.useState("");
3218
+ const [secret, setSecret] = React6.useState("");
3219
+ const headingId = React6.useId();
3028
3220
  const hasIdentity = Boolean(identityLabel);
3029
3221
  const submit = (event) => {
3030
3222
  event.preventDefault();
@@ -3103,7 +3295,7 @@ function CredentialBindingPanel({
3103
3295
  }
3104
3296
 
3105
3297
  // plugin-src/client/channels/shared/collapsible-account.js
3106
- var React6 = __toESM(require("react"), 1);
3298
+ var React7 = __toESM(require("react"), 1);
3107
3299
  function CollapsibleAccountSection({
3108
3300
  header,
3109
3301
  defaultOpen = false,
@@ -3113,7 +3305,7 @@ function CollapsibleAccountSection({
3113
3305
  className = "",
3114
3306
  children
3115
3307
  }) {
3116
- const [uncontrolledOpen, setUncontrolledOpen] = React6.useState(defaultOpen);
3308
+ const [uncontrolledOpen, setUncontrolledOpen] = React7.useState(defaultOpen);
3117
3309
  const open = controlledOpen ?? uncontrolledOpen;
3118
3310
  const contentId = id6 ? `${id6}-content` : void 0;
3119
3311
  const toggle = () => {
@@ -3160,11 +3352,11 @@ function CollapsibleAccountSection({
3160
3352
  }
3161
3353
 
3162
3354
  // plugin-src/client/workspace-editor.js
3163
- var React8 = __toESM(require("react"), 1);
3355
+ var React9 = __toESM(require("react"), 1);
3164
3356
 
3165
3357
  // plugin-src/client/workspace-directory-picker.js
3166
- var React7 = __toESM(require("react"), 1);
3167
- var import_react_dom = require("react-dom");
3358
+ var React8 = __toESM(require("react"), 1);
3359
+ var import_react_dom2 = require("react-dom");
3168
3360
  function pickerErrorCode(error) {
3169
3361
  return error?.rpcError?.code ?? error?.code;
3170
3362
  }
@@ -3184,7 +3376,7 @@ function pickerErrorMessage(error) {
3184
3376
  return error?.rpcError?.message ?? error?.message ?? "\u65E0\u6CD5\u8BFB\u53D6\u76EE\u5F55\uFF0C\u8BF7\u91CD\u8BD5\u3002";
3185
3377
  }
3186
3378
  function FolderIcon() {
3187
- return React7.createElement(
3379
+ return React8.createElement(
3188
3380
  "svg",
3189
3381
  {
3190
3382
  viewBox: "0 0 24 24",
@@ -3195,11 +3387,11 @@ function FolderIcon() {
3195
3387
  strokeLinejoin: "round",
3196
3388
  "aria-hidden": "true"
3197
3389
  },
3198
- 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" })
3199
3391
  );
3200
3392
  }
3201
3393
  function ChevronIcon() {
3202
- return React7.createElement("svg", {
3394
+ return React8.createElement("svg", {
3203
3395
  viewBox: "0 0 20 20",
3204
3396
  fill: "none",
3205
3397
  stroke: "currentColor",
@@ -3207,7 +3399,7 @@ function ChevronIcon() {
3207
3399
  strokeLinecap: "round",
3208
3400
  strokeLinejoin: "round",
3209
3401
  "aria-hidden": "true"
3210
- }, 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" }));
3211
3403
  }
3212
3404
  function displayCrumbs(listing) {
3213
3405
  const homeIndex = listing.crumbs.findIndex((crumb) => crumb.path === listing.home);
@@ -3223,28 +3415,28 @@ function WorkspaceDirectoryPicker({
3223
3415
  onPicked,
3224
3416
  onCancel
3225
3417
  }) {
3226
- const [listing, setListing] = React7.useState(null);
3227
- const [loading, setLoading] = React7.useState(false);
3228
- const [error, setError] = React7.useState(null);
3229
- const [pathDraft, setPathDraft] = React7.useState(startPath ?? "");
3230
- const [showHidden, setShowHidden] = React7.useState(false);
3231
- const [retryKey, setRetryKey] = React7.useState(0);
3232
- const requestRef = React7.useRef(0);
3233
- const controllerRef = React7.useRef(null);
3234
- const dialogRef = React7.useRef(null);
3235
- const bodyRef = React7.useRef(null);
3236
- const titleId = React7.useId();
3237
- const noticeId = React7.useId();
3238
- const pathInputId = React7.useId();
3239
- const errorId = React7.useId();
3240
- const initialPathRef = React7.useRef(startPath);
3241
- const onPickedRef = React7.useRef(onPicked);
3242
- const onCancelRef = React7.useRef(onCancel);
3243
- 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);
3244
3436
  onPickedRef.current = onPicked;
3245
3437
  onCancelRef.current = onCancel;
3246
3438
  busyRef.current = busy;
3247
- const loadDirectory = React7.useCallback(async (path, { reportError = true } = {}) => {
3439
+ const loadDirectory = React8.useCallback(async (path, { reportError = true } = {}) => {
3248
3440
  const request = requestRef.current + 1;
3249
3441
  requestRef.current = request;
3250
3442
  controllerRef.current?.abort();
@@ -3268,7 +3460,7 @@ function WorkspaceDirectoryPicker({
3268
3460
  if (request === requestRef.current) setLoading(false);
3269
3461
  }
3270
3462
  }, [picker]);
3271
- React7.useEffect(() => {
3463
+ React8.useEffect(() => {
3272
3464
  if (!open) return void 0;
3273
3465
  let active = true;
3274
3466
  setListing(null);
@@ -3348,10 +3540,10 @@ function WorkspaceDirectoryPicker({
3348
3540
  "nav",
3349
3541
  { className: "dim-directoryCrumbs", "aria-label": "\u5F53\u524D\u76EE\u5F55" },
3350
3542
  crumbs.map((crumb, index) => h2(
3351
- React7.Fragment,
3543
+ React8.Fragment,
3352
3544
  { key: crumb.path },
3353
3545
  index > 0 ? h2("span", { className: "dim-directoryCrumbSeparator", "aria-hidden": "true" }, "\u203A") : null,
3354
- React7.createElement("button", {
3546
+ React8.createElement("button", {
3355
3547
  type: "button",
3356
3548
  title: crumb.path,
3357
3549
  disabled: loading || busy,
@@ -3414,7 +3606,7 @@ function WorkspaceDirectoryPicker({
3414
3606
  ) : listing ? entries.length > 0 ? h2("ul", { className: "dim-directoryList" }, entries.map((entry) => h2(
3415
3607
  "li",
3416
3608
  { key: entry.path },
3417
- React7.createElement(
3609
+ React8.createElement(
3418
3610
  "button",
3419
3611
  {
3420
3612
  type: "button",
@@ -3423,7 +3615,7 @@ function WorkspaceDirectoryPicker({
3423
3615
  onClick: () => void loadDirectory(entry.path)
3424
3616
  },
3425
3617
  h2("span", { className: "dim-directoryFolder" }, h2(FolderIcon)),
3426
- React7.createElement("span", { className: "dim-directoryName" }, entry.name),
3618
+ React8.createElement("span", { className: "dim-directoryName" }, entry.name),
3427
3619
  h2("span", { className: "dim-directoryChevron" }, h2(ChevronIcon))
3428
3620
  )
3429
3621
  ))) : h2(
@@ -3472,25 +3664,25 @@ function WorkspaceDirectoryPicker({
3472
3664
  )
3473
3665
  )
3474
3666
  );
3475
- 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);
3476
3668
  }
3477
3669
 
3478
3670
  // plugin-src/client/workspace-editor.js
3479
- var WorkspaceDirectoryPickerContext = React8.createContext(null);
3671
+ var WorkspaceDirectoryPickerContext = React9.createContext(null);
3480
3672
  function WorkspaceEditor({ workspace, directoryPicker, disabled = false, onSave }) {
3481
- const sharedDirectoryPicker = React8.useContext(WorkspaceDirectoryPickerContext);
3673
+ const sharedDirectoryPicker = React9.useContext(WorkspaceDirectoryPickerContext);
3482
3674
  const activeDirectoryPicker = directoryPicker ?? sharedDirectoryPicker;
3483
- const [open, setOpen] = React8.useState(false);
3484
- const [saving, setSaving] = React8.useState(false);
3485
- const [error, setError] = React8.useState(null);
3486
- const editButtonRef = React8.useRef(null);
3487
- const savingRef = React8.useRef(false);
3488
- 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(() => {
3489
3681
  setOpen(false);
3490
3682
  setError(null);
3491
3683
  queueMicrotask(() => editButtonRef.current?.focus?.());
3492
3684
  }, []);
3493
- const pick = React8.useCallback(async (value) => {
3685
+ const pick = React9.useCallback(async (value) => {
3494
3686
  if (!value || savingRef.current || disabled) return;
3495
3687
  if (value === workspace) {
3496
3688
  close();
@@ -3527,7 +3719,7 @@ function WorkspaceEditor({ workspace, directoryPicker, disabled = false, onSave
3527
3719
  disabled: disabled || !activeDirectoryPicker
3528
3720
  }, "\u9009\u62E9\u76EE\u5F55")
3529
3721
  ),
3530
- workspace ? React8.createElement("code", {
3722
+ workspace ? React9.createElement("code", {
3531
3723
  className: "dim-workspacePath",
3532
3724
  title: workspace
3533
3725
  }, workspace) : h2("code", { className: "dim-workspacePath" }, "\u672A\u8BBE\u7F6E"),
@@ -3544,8 +3736,8 @@ function WorkspaceEditor({ workspace, directoryPicker, disabled = false, onSave
3544
3736
  }
3545
3737
 
3546
3738
  // plugin-src/client/context-enhancement.js
3547
- var React9 = __toESM(require("react"), 1);
3548
- var import_react_dom2 = require("react-dom");
3739
+ var React10 = __toESM(require("react"), 1);
3740
+ var import_react_dom3 = require("react-dom");
3549
3741
  var FIELD_LABELS = Object.freeze({
3550
3742
  channel: "\u6E20\u9053",
3551
3743
  conversationType: "\u4F1A\u8BDD\u7C7B\u578B",
@@ -3789,7 +3981,7 @@ function ContextEnhancementScopeEditor({
3789
3981
  );
3790
3982
  }
3791
3983
  function ContextEnhancementDialog({ config, groupSupported, disabled, onSave, onClose, returnFocusRef, id: id6 }) {
3792
- const [draft, setDraft] = React9.useState(() => {
3984
+ const [draft, setDraft] = React10.useState(() => {
3793
3985
  const normalized = normalizeContextEnhancementConfig(config);
3794
3986
  return {
3795
3987
  ...normalized,
@@ -3798,23 +3990,23 @@ function ContextEnhancementDialog({ config, groupSupported, disabled, onSave, on
3798
3990
  } : {}
3799
3991
  };
3800
3992
  });
3801
- const [saving, setSaving] = React9.useState(false);
3802
- const [error, setError] = React9.useState(null);
3803
- const [activeScope, setActiveScope] = React9.useState("direct");
3804
- const savingRef = React9.useRef(false);
3805
- const dialogRef = React9.useRef(null);
3806
- const mountedRef = React9.useRef(true);
3807
- const groupTabRef = React9.useRef(null);
3808
- const directTabRef = React9.useRef(null);
3809
- const titleId = React9.useId();
3810
- const descriptionId = React9.useId();
3811
- 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();
3812
4004
  const groupGuidanceExample = localizeText(CONTEXT_GROUP_GUIDANCE_EXAMPLE);
3813
4005
  const directGuidanceExample = localizeText(CONTEXT_DIRECT_GUIDANCE_EXAMPLE);
3814
4006
  const busy = disabled || saving;
3815
4007
  const scopeKinds = ["direct", "group"];
3816
4008
  const tabRefs = { group: groupTabRef, direct: directTabRef };
3817
- React9.useEffect(() => {
4009
+ React10.useEffect(() => {
3818
4010
  mountedRef.current = true;
3819
4011
  dialogRef.current?.focus?.();
3820
4012
  const keepFocus = (event) => {
@@ -4002,20 +4194,20 @@ function ContextEnhancementDialog({ config, groupSupported, disabled, onSave, on
4002
4194
  }, saving ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58")
4003
4195
  )
4004
4196
  ));
4005
- 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;
4006
4198
  }
4007
4199
  function ContextEnhancementEditor({ config, groupSupported = true, disabled = false, onSave }) {
4008
- const [open, setOpen] = React9.useState(false);
4009
- const entryRef = React9.useRef(null);
4010
- const dialogId = React9.useId();
4011
- 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();
4012
4204
  const saved = normalizeContextEnhancementConfig(config);
4013
4205
  const label = contextEnhancementLabel(groupSupported ? saved : {
4014
4206
  ...saved,
4015
4207
  group: { ...saved.group, enabled: false }
4016
4208
  });
4017
4209
  return h2(
4018
- React9.Fragment,
4210
+ React10.Fragment,
4019
4211
  null,
4020
4212
  h2(
4021
4213
  "button",
@@ -4049,10 +4241,10 @@ function ContextEnhancementEditor({ config, groupSupported = true, disabled = fa
4049
4241
  }
4050
4242
 
4051
4243
  // plugin-src/client/workspace-snapshot-fence.js
4052
- var React10 = __toESM(require("react"), 1);
4244
+ var React11 = __toESM(require("react"), 1);
4053
4245
  function useWorkspaceSnapshotFence() {
4054
- const state = React10.useRef({ version: 0, pendingMutations: 0 });
4055
- return React10.useMemo(() => Object.freeze({
4246
+ const state = React11.useRef({ version: 0, pendingMutations: 0 });
4247
+ return React11.useMemo(() => Object.freeze({
4056
4248
  beginStatus() {
4057
4249
  return state.current.pendingMutations === 0 ? state.current.version : null;
4058
4250
  },
@@ -4075,8 +4267,8 @@ function useWorkspaceSnapshotFence() {
4075
4267
  }
4076
4268
 
4077
4269
  // plugin-src/client/channel-card-meta.js
4078
- var React11 = __toESM(require("react"), 1);
4079
- var BotSettingsContext = React11.createContext(Object.freeze({
4270
+ var React12 = __toESM(require("react"), 1);
4271
+ var BotSettingsContext = React12.createContext(Object.freeze({
4080
4272
  openBotSettings() {
4081
4273
  }
4082
4274
  }));
@@ -4106,8 +4298,8 @@ function BotSettingsButton({
4106
4298
  accessPolicy,
4107
4299
  channelSettings
4108
4300
  }) {
4109
- const { openBotSettings } = React11.useContext(BotSettingsContext);
4110
- const tooltipId = React11.useId();
4301
+ const { openBotSettings } = React12.useContext(BotSettingsContext);
4302
+ const tooltipId = React12.useId();
4111
4303
  return h2(
4112
4304
  "span",
4113
4305
  { className: "dim-botSettingsAction" },
@@ -4147,7 +4339,7 @@ function messageErrorTime(value) {
4147
4339
  }
4148
4340
  }
4149
4341
  function ChannelListHeading({ className = "", id: id6, title, connectionLabel }) {
4150
- const helpId = React11.useId();
4342
+ const helpId = React12.useId();
4151
4343
  return h2(
4152
4344
  "div",
4153
4345
  { className: `${className} dim-listHeading`.trim() },
@@ -4228,7 +4420,7 @@ function LastMessageErrorSummary({ className = "", error }) {
4228
4420
  h2("span", null, "\u53C2\u8003\u53F7"),
4229
4421
  ` ${error.referenceId}`,
4230
4422
  occurredAt ? h2(
4231
- React11.Fragment,
4423
+ React12.Fragment,
4232
4424
  null,
4233
4425
  " \xB7 ",
4234
4426
  h2("time", { dateTime: new Date(error.at).toISOString() }, occurredAt)
@@ -4391,7 +4583,7 @@ function DingtalkIcon({ size = 28 }) {
4391
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"
4392
4584
  }));
4393
4585
  }
4394
- 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) {
4395
4587
  return h2("button", {
4396
4588
  ...props,
4397
4589
  ref,
@@ -4487,13 +4679,13 @@ function EmptyView({ busy, onStart }) {
4487
4679
  );
4488
4680
  }
4489
4681
  function QrPanel({ provision, now, busy, onRefresh, onCancel }) {
4490
- const [imageFailed, setImageFailed] = React12.useState(false);
4682
+ const [imageFailed, setImageFailed] = React13.useState(false);
4491
4683
  const source = safeQrSource(provision.qrCodeDataUrl);
4492
4684
  const remaining = Math.max(0, provision.expiresAt - now);
4493
4685
  const expired = remaining === 0 || provision.status === "expired";
4494
4686
  const duration = Math.max(1, provision.durationMs ?? 10 * 6e4);
4495
4687
  const progress = Math.round(Math.min(1, remaining / duration) * 100);
4496
- React12.useEffect(() => setImageFailed(false), [source]);
4688
+ React13.useEffect(() => setImageFailed(false), [source]);
4497
4689
  return h2(
4498
4690
  "div",
4499
4691
  { className: "ddt-card dim-surfaceCard" },
@@ -4585,7 +4777,7 @@ function ConnectionErrorDiagnostic({ error }) {
4585
4777
  { className: "ddt-errorCode" },
4586
4778
  h2("span", null, "\u9519\u8BEF\u7801"),
4587
4779
  `: ${error.code}`,
4588
- 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
4589
4781
  )
4590
4782
  );
4591
4783
  }
@@ -4608,7 +4800,7 @@ function ProvisionError({ provision, busy, onRetry, onClose }) {
4608
4800
  "div",
4609
4801
  { className: "ddt-actions dim-viewActions" },
4610
4802
  connectionFailed ? h2(Button, { kind: "primary", onClick: onClose, disabled: busy }, "\u67E5\u770B\u5DF2\u4FDD\u5B58\u7684\u673A\u5668\u4EBA") : h2(
4611
- React12.Fragment,
4803
+ React13.Fragment,
4612
4804
  null,
4613
4805
  h2(Button, { kind: "primary", onClick: onRetry, disabled: busy }, "\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801"),
4614
4806
  h2(Button, { onClick: onClose, disabled: busy }, "\u5173\u95ED")
@@ -4630,8 +4822,8 @@ function checkedTime(value) {
4630
4822
  }
4631
4823
  }
4632
4824
  function RemoveConfirmation({ account, busy, onConfirm, onCancel }) {
4633
- const cancelRef = React12.useRef(null);
4634
- React12.useEffect(() => cancelRef.current?.focus(), []);
4825
+ const cancelRef = React13.useRef(null);
4826
+ React13.useEffect(() => cancelRef.current?.focus(), []);
4635
4827
  return h2(
4636
4828
  "div",
4637
4829
  {
@@ -4663,6 +4855,7 @@ function AccountCard({
4663
4855
  removing,
4664
4856
  onReconnect,
4665
4857
  onWorkspaceSave,
4858
+ onAliasSave,
4666
4859
  onModelSave,
4667
4860
  onAgentPresetSave,
4668
4861
  onContextEnhancementSave,
@@ -4694,7 +4887,7 @@ function AccountCard({
4694
4887
  h2(
4695
4888
  "div",
4696
4889
  { className: "dim-botName" },
4697
- h2("h3", { title: account.bot.name }, account.bot.name),
4890
+ h2(BotName, { bot: account.bot, disabled: Boolean(busy), onSave: onAliasSave }),
4698
4891
  h2("p", { title: account.bot.clientIdMasked }, account.bot.clientIdMasked)
4699
4892
  )
4700
4893
  ),
@@ -4809,6 +5002,7 @@ function AccountList(props) {
4809
5002
  removing: props.removeTarget === account.botId,
4810
5003
  onReconnect: () => props.onReconnect(account),
4811
5004
  onWorkspaceSave: (workspace) => props.onWorkspaceSave(account, workspace),
5005
+ onAliasSave: (alias) => props.onAliasSave(account, alias),
4812
5006
  onModelSave: (model) => props.onModelSave(account, model),
4813
5007
  onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(account, agentPreset),
4814
5008
  onContextEnhancementSave: (config) => props.onContextEnhancementSave(account, config),
@@ -4821,7 +5015,7 @@ function AccountList(props) {
4821
5015
  }
4822
5016
  var EMPTY_TOTALS = Object.freeze({ configured: 0, connected: 0 });
4823
5017
  function DingtalkSettingsTab({ rpcCall }) {
4824
- const [model, setModel] = React12.useState({
5018
+ const [model, setModel] = React13.useState({
4825
5019
  phase: "loading",
4826
5020
  bots: [],
4827
5021
  totals: EMPTY_TOTALS,
@@ -4830,22 +5024,22 @@ function DingtalkSettingsTab({ rpcCall }) {
4830
5024
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
4831
5025
  modelCatalog: EMPTY_MODEL_CATALOG
4832
5026
  });
4833
- const [provision, setProvision] = React12.useState(null);
4834
- const [busy, setBusy] = React12.useState(false);
4835
- const [busyByBot, setBusyByBot] = React12.useState({});
4836
- const [feedbackByBot, setFeedbackByBot] = React12.useState({});
4837
- const [removeTarget, setRemoveTarget] = React12.useState(null);
4838
- const [credentialOpen, setCredentialOpen] = React12.useState(false);
4839
- const [credentialError, setCredentialError] = React12.useState(null);
4840
- const [notice, setNotice] = React12.useState("");
4841
- const [now, setNow] = React12.useState(() => Date.now());
4842
- const addButtonRef = React12.useRef(null);
4843
- const mountedRef = React12.useRef(true);
4844
- 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);
4845
5039
  const workspaceFence = useWorkspaceSnapshotFence();
4846
- const noticeFrameRef = React12.useRef(null);
4847
- const focusFrameRef = React12.useRef(null);
4848
- React12.useEffect(() => {
5040
+ const noticeFrameRef = React13.useRef(null);
5041
+ const focusFrameRef = React13.useRef(null);
5042
+ React13.useEffect(() => {
4849
5043
  mountedRef.current = true;
4850
5044
  return () => {
4851
5045
  mountedRef.current = false;
@@ -4860,8 +5054,8 @@ function DingtalkSettingsTab({ rpcCall }) {
4860
5054
  }
4861
5055
  };
4862
5056
  }, []);
4863
- React12.useEffect(() => installDingtalkStyles(), []);
4864
- const announce = React12.useCallback((message) => {
5057
+ React13.useEffect(() => installDingtalkStyles(), []);
5058
+ const announce = React13.useCallback((message) => {
4865
5059
  if (!mountedRef.current) return;
4866
5060
  if (noticeFrameRef.current !== null) {
4867
5061
  window.cancelAnimationFrame(noticeFrameRef.current);
@@ -4875,7 +5069,7 @@ function DingtalkSettingsTab({ rpcCall }) {
4875
5069
  });
4876
5070
  }
4877
5071
  }, []);
4878
- const discardStaleFeedback = React12.useCallback((snapshot) => {
5072
+ const discardStaleFeedback = React13.useCallback((snapshot) => {
4879
5073
  const botsById = new Map(snapshot.bots.map((bot) => [bot.botId, bot]));
4880
5074
  setFeedbackByBot((current) => {
4881
5075
  let changed = false;
@@ -4890,7 +5084,7 @@ function DingtalkSettingsTab({ rpcCall }) {
4890
5084
  return changed ? next : current;
4891
5085
  });
4892
5086
  }, []);
4893
- const focusAddButton = React12.useCallback(() => {
5087
+ const focusAddButton = React13.useCallback(() => {
4894
5088
  if (!mountedRef.current) return;
4895
5089
  if (focusFrameRef.current !== null) window.cancelAnimationFrame(focusFrameRef.current);
4896
5090
  focusFrameRef.current = window.requestAnimationFrame(() => {
@@ -4898,11 +5092,11 @@ function DingtalkSettingsTab({ rpcCall }) {
4898
5092
  if (mountedRef.current) addButtonRef.current?.focus();
4899
5093
  });
4900
5094
  }, []);
4901
- const invoke = React12.useCallback(async (endpoint, payload = {}, signal) => {
5095
+ const invoke = React13.useCallback(async (endpoint, payload = {}, signal) => {
4902
5096
  if (typeof rpcCall !== "function") throw new TypeError("\u9489\u9489\u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
4903
5097
  return unwrapRpcResult(await rpcCall(endpoint, payload, signal));
4904
5098
  }, [rpcCall]);
4905
- const loadStatus = React12.useCallback(async ({
5099
+ const loadStatus = React13.useCallback(async ({
4906
5100
  signal,
4907
5101
  silent = false,
4908
5102
  restoreProvisioning = false
@@ -4947,12 +5141,12 @@ function DingtalkSettingsTab({ rpcCall }) {
4947
5141
  return void 0;
4948
5142
  }
4949
5143
  }, [discardStaleFeedback, invoke, workspaceFence]);
4950
- React12.useEffect(() => {
5144
+ React13.useEffect(() => {
4951
5145
  const controller = new AbortController();
4952
5146
  void loadStatus({ signal: controller.signal, restoreProvisioning: true });
4953
5147
  return () => controller.abort();
4954
5148
  }, [loadStatus]);
4955
- React12.useEffect(() => {
5149
+ React13.useEffect(() => {
4956
5150
  if (model.phase !== "ready") return void 0;
4957
5151
  const controller = new AbortController();
4958
5152
  let running = false;
@@ -4971,14 +5165,14 @@ function DingtalkSettingsTab({ rpcCall }) {
4971
5165
  window.clearInterval(timer);
4972
5166
  };
4973
5167
  }, [loadStatus, model.phase]);
4974
- React12.useEffect(() => {
5168
+ React13.useEffect(() => {
4975
5169
  if (!provision || !ACTIVE_PROVISION_STATES.has(provision.status)) return void 0;
4976
5170
  const timer = window.setInterval(() => {
4977
5171
  if (mountedRef.current) setNow(Date.now());
4978
5172
  }, 1e3);
4979
5173
  return () => window.clearInterval(timer);
4980
5174
  }, [provision?.attemptId, provision?.status]);
4981
- const startProvisioning = React12.useCallback(async ({ replace = false } = {}) => {
5175
+ const startProvisioning = React13.useCallback(async ({ replace = false } = {}) => {
4982
5176
  if (!mountedRef.current) return;
4983
5177
  setCredentialOpen(false);
4984
5178
  setCredentialError(null);
@@ -5016,7 +5210,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5016
5210
  if (mountedRef.current) setBusy(false);
5017
5211
  }
5018
5212
  }, [announce, invoke, provision?.attemptId]);
5019
- const bindCredentials = React12.useCallback(async ({ identity, secret }) => {
5213
+ const bindCredentials = React13.useCallback(async ({ identity, secret }) => {
5020
5214
  if (!mountedRef.current) return;
5021
5215
  const snapshotVersion = workspaceFence.beginMutation();
5022
5216
  setBusy(true);
@@ -5049,7 +5243,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5049
5243
  if (mountedRef.current) setBusy(false);
5050
5244
  }
5051
5245
  }, [announce, discardStaleFeedback, invoke, loadStatus, workspaceFence]);
5052
- const cancelProvisioning = React12.useCallback(async () => {
5246
+ const cancelProvisioning = React13.useCallback(async () => {
5053
5247
  if (!mountedRef.current) return;
5054
5248
  setBusy(true);
5055
5249
  try {
@@ -5067,7 +5261,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5067
5261
  if (mountedRef.current) setBusy(false);
5068
5262
  }
5069
5263
  }, [announce, focusAddButton, invoke, provision?.attemptId, provision?.status]);
5070
- React12.useEffect(() => {
5264
+ React13.useEffect(() => {
5071
5265
  const attemptId = provision?.attemptId;
5072
5266
  if (!attemptId || !ACTIVE_PROVISION_STATES.has(provision.status)) return void 0;
5073
5267
  const controller = new AbortController();
@@ -5130,7 +5324,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5130
5324
  timer = null;
5131
5325
  };
5132
5326
  }, [announce, invoke, loadStatus, provision?.attemptId, provision?.pollIntervalMs, provision?.status]);
5133
- const setBotBusy = React12.useCallback((botId, operation) => {
5327
+ const setBotBusy = React13.useCallback((botId, operation) => {
5134
5328
  if (!mountedRef.current) return;
5135
5329
  setBusyByBot((current) => {
5136
5330
  const next = { ...current };
@@ -5139,7 +5333,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5139
5333
  return next;
5140
5334
  });
5141
5335
  }, []);
5142
- const runBotAction = React12.useCallback(async ({ account, operation, endpoint, payload, success }) => {
5336
+ const runBotAction = React13.useCallback(async ({ account, operation, endpoint, payload, success }) => {
5143
5337
  if (!mountedRef.current) return void 0;
5144
5338
  const snapshotVersion = workspaceFence.beginMutation();
5145
5339
  setBotBusy(account.botId, operation);
@@ -5195,7 +5389,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5195
5389
  if (mountedRef.current) setBotBusy(account.botId, null);
5196
5390
  }
5197
5391
  }, [announce, discardStaleFeedback, invoke, loadStatus, setBotBusy, workspaceFence]);
5198
- const reconnect = React12.useCallback((account) => runBotAction({
5392
+ const reconnect = React13.useCallback((account) => runBotAction({
5199
5393
  account,
5200
5394
  operation: "reconnect",
5201
5395
  endpoint: DINGTALK_ENDPOINTS.reconnectBot,
@@ -5206,7 +5400,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5206
5400
  return connectionTestFeedback(snapshot.testMessage) ?? "\u9489\u9489\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\u3002";
5207
5401
  }
5208
5402
  }), [runBotAction]);
5209
- const saveWorkspace = React12.useCallback(async (account, workspace) => {
5403
+ const saveWorkspace = React13.useCallback(async (account, workspace) => {
5210
5404
  const workspaceVersion = workspaceFence.beginMutation();
5211
5405
  setBotBusy(account.botId, "workspace");
5212
5406
  try {
@@ -5232,7 +5426,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5232
5426
  if (mountedRef.current) setBotBusy(account.botId, null);
5233
5427
  }
5234
5428
  }, [discardStaleFeedback, invoke, loadStatus, setBotBusy, workspaceFence]);
5235
- const saveBotSetting = React12.useCallback(async (account, operation, endpoint, payload) => {
5429
+ const saveBotSetting = React13.useCallback(async (account, operation, endpoint, payload) => {
5236
5430
  const snapshotVersion = workspaceFence.beginMutation();
5237
5431
  setBotBusy(account.botId, operation);
5238
5432
  try {
@@ -5258,7 +5452,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5258
5452
  if (mountedRef.current) setBotBusy(account.botId, null);
5259
5453
  }
5260
5454
  }, [discardStaleFeedback, invoke, loadStatus, setBotBusy, workspaceFence]);
5261
- const remove = React12.useCallback(async (account) => {
5455
+ const remove = React13.useCallback(async (account) => {
5262
5456
  const snapshot = await runBotAction({
5263
5457
  account,
5264
5458
  operation: "delete",
@@ -5344,7 +5538,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5344
5538
  h2(Button, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
5345
5539
  )
5346
5540
  ) : h2(
5347
- React12.Fragment,
5541
+ React13.Fragment,
5348
5542
  null,
5349
5543
  credentialView,
5350
5544
  provisionView,
@@ -5356,6 +5550,12 @@ function DingtalkSettingsTab({ rpcCall }) {
5356
5550
  removeTarget,
5357
5551
  onReconnect: (account) => void reconnect(account),
5358
5552
  onWorkspaceSave: saveWorkspace,
5553
+ onAliasSave: (account, alias) => saveBotSetting(
5554
+ account,
5555
+ "alias",
5556
+ DINGTALK_ENDPOINTS.setAlias,
5557
+ { alias }
5558
+ ),
5359
5559
  onModelSave: (account, selectedModel) => saveBotSetting(
5360
5560
  account,
5361
5561
  "model",
@@ -5408,7 +5608,8 @@ var TOKEN_BOT_ENDPOINTS = Object.freeze({
5408
5608
  setModel: SET_MODEL_ENDPOINT,
5409
5609
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
5410
5610
  setContextEnhancement: "bot.context-enhancement.set",
5411
- setAccessPolicy: "bot.access-policy.set"
5611
+ setAccessPolicy: "bot.access-policy.set",
5612
+ setAlias: "bot.alias.set"
5412
5613
  });
5413
5614
  function createTokenChannelApi(channel5, connectionSummary, {
5414
5615
  normalizeBotExtension = () => ({})
@@ -5439,6 +5640,7 @@ function createTokenChannelApi(channel5, connectionSummary, {
5439
5640
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
5440
5641
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
5441
5642
  bot: {
5643
+ ...normalizeBotAlias(value.bot),
5442
5644
  name: text2(value.bot?.name, `${channel5}\u673A\u5668\u4EBA`, 100),
5443
5645
  username: text2(value.bot?.username, "", 100),
5444
5646
  idMasked: text2(value.bot?.idMasked, "\u673A\u5668\u4EBA\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58", 140)
@@ -5489,8 +5691,8 @@ var normalizeSnapshot2 = api.normalizeSnapshot;
5489
5691
  var presentError2 = api.presentError;
5490
5692
 
5491
5693
  // plugin-src/client/channels/shared/token-channel.js
5492
- var React13 = __toESM(require("react"), 1);
5493
- 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) {
5494
5696
  return h2("button", {
5495
5697
  ...props,
5496
5698
  ref,
@@ -5542,7 +5744,7 @@ function createTokenChannelSettings(definition) {
5542
5744
  AccountSettings = null,
5543
5745
  accountSettingsEndpoint = null
5544
5746
  } = definition;
5545
- 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 }) {
5546
5748
  const state = busy === "reconnect" ? "connecting" : account.state;
5547
5749
  const tone = account.connected ? "success" : state === "error" ? "error" : "warning";
5548
5750
  const stateLabel2 = account.connected ? "\u8FD0\u884C\u6B63\u5E38" : state === "connecting" ? "\u6B63\u5728\u8FDE\u63A5" : "\u8FDE\u63A5\u672A\u5C31\u7EEA";
@@ -5572,7 +5774,7 @@ function createTokenChannelSettings(definition) {
5572
5774
  h2(
5573
5775
  "div",
5574
5776
  { className: "dim-botName" },
5575
- h2("h3", null, account.bot.name),
5777
+ h2(BotName, { bot: account.bot, disabled: Boolean(busy), onSave: onAliasSave }),
5576
5778
  h2("p", null, identity)
5577
5779
  )
5578
5780
  ),
@@ -5684,7 +5886,7 @@ function createTokenChannelSettings(definition) {
5684
5886
  );
5685
5887
  }
5686
5888
  function SettingsTab({ rpcCall }) {
5687
- const [model, setModel] = React13.useState({
5889
+ const [model, setModel] = React14.useState({
5688
5890
  phase: "loading",
5689
5891
  bots: [],
5690
5892
  totals: { configured: 0, connected: 0 },
@@ -5693,15 +5895,15 @@ function createTokenChannelSettings(definition) {
5693
5895
  modelCatalog: EMPTY_MODEL_CATALOG,
5694
5896
  permissions: null
5695
5897
  });
5696
- const [credentialOpen, setCredentialOpen] = React13.useState(false);
5697
- const [credentialError, setCredentialError] = React13.useState(null);
5698
- const [busy, setBusy] = React13.useState(false);
5699
- const [busyByBot, setBusyByBot] = React13.useState({});
5700
- const [testNoticeByBot, setTestNoticeByBot] = React13.useState({});
5701
- const [removeTarget, setRemoveTarget] = React13.useState(null);
5702
- 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);
5703
5905
  const workspaceFence = useWorkspaceSnapshotFence();
5704
- React13.useEffect(() => {
5906
+ React14.useEffect(() => {
5705
5907
  const disposeDingtalk = installDingtalkStyles();
5706
5908
  const disposeChannel = installStyles();
5707
5909
  mounted.current = true;
@@ -5711,11 +5913,11 @@ function createTokenChannelSettings(definition) {
5711
5913
  disposeDingtalk();
5712
5914
  };
5713
5915
  }, []);
5714
- const invoke = React13.useCallback(async (endpoint, payload = {}, signal) => {
5916
+ const invoke = React14.useCallback(async (endpoint, payload = {}, signal) => {
5715
5917
  if (typeof rpcCall !== "function") throw new TypeError(`${channel5} \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5`);
5716
5918
  return api5.unwrapRpcResult(await rpcCall(endpoint, payload, signal));
5717
5919
  }, [rpcCall]);
5718
- const loadStatus = React13.useCallback(async ({ signal, silent = false } = {}) => {
5920
+ const loadStatus = React14.useCallback(async ({ signal, silent = false } = {}) => {
5719
5921
  const workspaceVersion = workspaceFence.beginStatus();
5720
5922
  if (workspaceVersion === null) return;
5721
5923
  if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
@@ -5741,12 +5943,12 @@ function createTokenChannelSettings(definition) {
5741
5943
  }
5742
5944
  }
5743
5945
  }, [invoke, workspaceFence]);
5744
- React13.useEffect(() => {
5946
+ React14.useEffect(() => {
5745
5947
  const controller = new AbortController();
5746
5948
  void loadStatus({ signal: controller.signal });
5747
5949
  return () => controller.abort();
5748
5950
  }, [loadStatus]);
5749
- React13.useEffect(() => {
5951
+ React14.useEffect(() => {
5750
5952
  if (model.phase !== "ready") return void 0;
5751
5953
  const controller = new AbortController();
5752
5954
  const timer = window.setInterval(
@@ -5758,7 +5960,7 @@ function createTokenChannelSettings(definition) {
5758
5960
  window.clearInterval(timer);
5759
5961
  };
5760
5962
  }, [loadStatus, model.phase]);
5761
- const bindCredentials = React13.useCallback(async (values) => {
5963
+ const bindCredentials = React14.useCallback(async (values) => {
5762
5964
  const snapshotVersion = workspaceFence.beginMutation();
5763
5965
  setBusy(true);
5764
5966
  setCredentialError(null);
@@ -5788,7 +5990,7 @@ function createTokenChannelSettings(definition) {
5788
5990
  if (mounted.current) setBusy(false);
5789
5991
  }
5790
5992
  }, [invoke, loadStatus, workspaceFence]);
5791
- const botAction = React13.useCallback(async (account, operation, endpoint, payload) => {
5993
+ const botAction = React14.useCallback(async (account, operation, endpoint, payload) => {
5792
5994
  const snapshotVersion = workspaceFence.beginMutation();
5793
5995
  setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
5794
5996
  try {
@@ -5853,6 +6055,12 @@ function createTokenChannelSettings(definition) {
5853
6055
  endpoints.setWorkspace,
5854
6056
  { botId: account.botId, workspace }
5855
6057
  ),
6058
+ onAliasSave: (alias) => botAction(
6059
+ account,
6060
+ "alias",
6061
+ endpoints.setAlias,
6062
+ { botId: account.botId, alias }
6063
+ ),
5856
6064
  onModelSave: (selectedModel) => botAction(
5857
6065
  account,
5858
6066
  "model",
@@ -5940,7 +6148,7 @@ function createTokenChannelSettings(definition) {
5940
6148
  h2(Button3, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
5941
6149
  )
5942
6150
  ) : h2(
5943
- React13.Fragment,
6151
+ React14.Fragment,
5944
6152
  null,
5945
6153
  credentialOpen ? CredentialPanel ? h2(CredentialPanel, {
5946
6154
  channel: channel5,
@@ -6043,7 +6251,7 @@ var DiscordSettingsTab = channel.SettingsTab;
6043
6251
  var DiscordAccountCard = channel.AccountCard;
6044
6252
 
6045
6253
  // plugin-src/client/channels/feishu/index.js
6046
- var React15 = __toESM(require("react"), 1);
6254
+ var React16 = __toESM(require("react"), 1);
6047
6255
 
6048
6256
  // src/channels/feishu/step-push-mode.mjs
6049
6257
  var FEISHU_STEP_PUSH_MODES = Object.freeze({
@@ -6073,6 +6281,7 @@ var FEISHU_ENDPOINTS = Object.freeze({
6073
6281
  setAgentPreset: "bot.preset.set",
6074
6282
  setContextEnhancement: "bot.context-enhancement.set",
6075
6283
  setAccessPolicy: "bot.access-policy.set",
6284
+ setAlias: "bot.alias.set",
6076
6285
  setGroupResponseMode: "bot.group-response-mode.set",
6077
6286
  setGroupTopicReply: "bot.group-topic-reply.set",
6078
6287
  setStepPush: "bot.step-push.set",
@@ -6178,6 +6387,7 @@ function normalizeProvisioning2(value, now = Date.now()) {
6178
6387
  function normalizeBot2(value) {
6179
6388
  const source = isRecord3(value) ? value : {};
6180
6389
  return {
6390
+ ...normalizeBotAlias(source),
6181
6391
  name: optionalString2(source.name) ?? "\u98DE\u4E66\u673A\u5668\u4EBA",
6182
6392
  avatarUrl: optionalString2(source.avatarUrl),
6183
6393
  appIdMasked: optionalString2(source.appIdMasked),
@@ -6326,7 +6536,7 @@ function formatRemaining2(milliseconds) {
6326
6536
  }
6327
6537
 
6328
6538
  // plugin-src/client/lifecycle.js
6329
- var React14 = __toESM(require("react"), 1);
6539
+ var React15 = __toESM(require("react"), 1);
6330
6540
  function createPollScheduler({ setTimeoutFn, clearTimeoutFn }) {
6331
6541
  let disposed = false;
6332
6542
  let timer;
@@ -6388,8 +6598,8 @@ function createAnimationFrameScheduler({ requestFrame, cancelFrame }) {
6388
6598
  };
6389
6599
  }
6390
6600
  function useAnimationFrameScheduler() {
6391
- const schedulerRef = React14.useRef(null);
6392
- React14.useEffect(() => {
6601
+ const schedulerRef = React15.useRef(null);
6602
+ React15.useEffect(() => {
6393
6603
  const scheduler = createAnimationFrameScheduler({
6394
6604
  requestFrame: (callback) => window.requestAnimationFrame(callback),
6395
6605
  cancelFrame: (frame) => window.cancelAnimationFrame(frame)
@@ -6400,7 +6610,7 @@ function useAnimationFrameScheduler() {
6400
6610
  if (schedulerRef.current === scheduler) schedulerRef.current = null;
6401
6611
  };
6402
6612
  }, []);
6403
- return React14.useCallback(
6613
+ return React15.useCallback(
6404
6614
  (callback, key) => schedulerRef.current?.schedule(callback, key) ?? false,
6405
6615
  []
6406
6616
  );
@@ -6475,7 +6685,7 @@ function QrIcon({ size = 58 }) {
6475
6685
  fill: "currentColor"
6476
6686
  }));
6477
6687
  }
6478
- 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) {
6479
6689
  return h2("button", {
6480
6690
  ...props,
6481
6691
  ref,
@@ -6592,7 +6802,7 @@ function safeQrSource2(value) {
6592
6802
  return /^data:image\/(?:png|webp|svg\+xml)(?:;charset=[^;,]+)?;base64,/i.test(value) ? value : void 0;
6593
6803
  }
6594
6804
  function QrPane({ provision, now, onRefresh, onCancel, busy }) {
6595
- const [imageFailed, setImageFailed] = React15.useState(false);
6805
+ const [imageFailed, setImageFailed] = React16.useState(false);
6596
6806
  const qrSource = safeQrSource2(provision.qrCodeDataUrl);
6597
6807
  const href = safeVerificationHref(provision.verificationUrl);
6598
6808
  const remaining = Math.max(0, provision.expiresAt - now);
@@ -6601,7 +6811,7 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
6601
6811
  const repairing = isCallbackRepair(provision);
6602
6812
  const grantingGroupMessages = isGroupMessagePermission(provision);
6603
6813
  const botName = provision.botName ?? "\u6B64\u673A\u5668\u4EBA";
6604
- React15.useEffect(() => setImageFailed(false), [qrSource]);
6814
+ React16.useEffect(() => setImageFailed(false), [qrSource]);
6605
6815
  return h2(
6606
6816
  "div",
6607
6817
  { className: "bxf-card bxf-provisionCard dim-surfaceCard" },
@@ -6764,11 +6974,11 @@ function connectionTestNotice2(value) {
6764
6974
  return value?.testMessage ? "\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002" : null;
6765
6975
  }
6766
6976
  function RemoveConfirmation2({ bot, busy, onConfirm, onCancel }) {
6767
- const cancelRef = React15.useRef(null);
6977
+ const cancelRef = React16.useRef(null);
6768
6978
  const idPart = bot.botId.replace(/[^a-zA-Z0-9_-]/g, "-");
6769
6979
  const titleId = `bxf-remove-title-${idPart}`;
6770
6980
  const descriptionId = `bxf-remove-description-${idPart}`;
6771
- React15.useEffect(() => cancelRef.current?.focus(), []);
6981
+ React16.useEffect(() => cancelRef.current?.focus(), []);
6772
6982
  return h2(
6773
6983
  "div",
6774
6984
  {
@@ -6802,11 +7012,11 @@ function RemoveConfirmation2({ bot, busy, onConfirm, onCancel }) {
6802
7012
  );
6803
7013
  }
6804
7014
  function StepPushEditor({ value = false, mode = "post", disabled = false, onSave, onModeSave }) {
6805
- const titleId = React15.useId();
7015
+ const titleId = React16.useId();
6806
7016
  const helpId = `${titleId}-help`;
6807
7017
  const current = value === true ? mode : "off";
6808
- const [saving, setSaving] = React15.useState(false);
6809
- const [error, setError] = React15.useState(null);
7018
+ const [saving, setSaving] = React16.useState(false);
7019
+ const [error, setError] = React16.useState(null);
6810
7020
  const save = async (run) => {
6811
7021
  if (saving || disabled) return;
6812
7022
  setSaving(true);
@@ -6896,6 +7106,7 @@ function BotCard({
6896
7106
  onReconnect,
6897
7107
  onRepairCallback,
6898
7108
  onWorkspaceSave,
7109
+ onAliasSave,
6899
7110
  onModelSave,
6900
7111
  onAgentPresetSave,
6901
7112
  onContextEnhancementSave,
@@ -6908,7 +7119,7 @@ function BotCard({
6908
7119
  removeButtonRef
6909
7120
  }) {
6910
7121
  const { bot, health, state, connected } = connection;
6911
- const repairTooltipId = React15.useId();
7122
+ const repairTooltipId = React16.useId();
6912
7123
  const stateForDisplay = busy === "reconnect" ? "connecting" : state;
6913
7124
  const tone = stateForDisplay === "connected" ? "success" : stateForDisplay === "connecting" ? "warning" : "error";
6914
7125
  const summary2 = actionError?.message ?? connection.error?.message ?? (connected ? null : health.summary);
@@ -6943,7 +7154,7 @@ function BotCard({
6943
7154
  h2(
6944
7155
  "div",
6945
7156
  { className: "bxf-botName dim-botName" },
6946
- h2("h3", { id: titleId, title: bot.name }, bot.name),
7157
+ h2(BotName, { bot, id: titleId, disabled: Boolean(busy), onSave: onAliasSave }),
6947
7158
  h2("p", { title: bot.appIdMasked }, bot.appIdMasked ?? "\u5E94\u7528\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58")
6948
7159
  )
6949
7160
  ),
@@ -7117,6 +7328,7 @@ function BotList(props) {
7117
7328
  onReconnect: () => props.onReconnect(bot),
7118
7329
  onRepairCallback: () => props.onRepairCallback(bot),
7119
7330
  onWorkspaceSave: (workspace) => props.onWorkspaceSave(bot, workspace),
7331
+ onAliasSave: (alias) => props.onAliasSave(bot, alias),
7120
7332
  onModelSave: (model) => props.onModelSave(bot, model),
7121
7333
  onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(bot, agentPreset),
7122
7334
  onContextEnhancementSave: (config) => props.onContextEnhancementSave(bot, config),
@@ -7185,7 +7397,7 @@ function mergeFeishuSnapshotState(current, snapshot, { restoreProvisioning = fal
7185
7397
  };
7186
7398
  }
7187
7399
  function FeishuSettingsTab({ rpcCall }) {
7188
- const [model, setModel] = React15.useState({
7400
+ const [model, setModel] = React16.useState({
7189
7401
  phase: "loading",
7190
7402
  revision: 0,
7191
7403
  bots: [],
@@ -7196,41 +7408,41 @@ function FeishuSettingsTab({ rpcCall }) {
7196
7408
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
7197
7409
  modelCatalog: EMPTY_MODEL_CATALOG
7198
7410
  });
7199
- const [pageBusy, setPageBusy] = React15.useState(false);
7200
- const [provisionBusy, setProvisionBusy] = React15.useState(false);
7201
- const [credentialOpen, setCredentialOpen] = React15.useState(false);
7202
- const [credentialBusy, setCredentialBusy] = React15.useState(false);
7203
- const [credentialError, setCredentialError] = React15.useState(null);
7204
- const [busyByBot, setBusyByBot] = React15.useState({});
7205
- const [errorsByBot, setErrorsByBot] = React15.useState({});
7206
- const [testNoticesByBot, setTestNoticesByBot] = React15.useState({});
7207
- const [removeTargetId, setRemoveTargetId] = React15.useState(null);
7208
- const [announcement, setAnnouncement] = React15.useState("");
7209
- const [now, setNow] = React15.useState(() => Date.now());
7210
- const [focusBotId, setFocusBotId] = React15.useState(null);
7211
- const cardRefs = React15.useRef(/* @__PURE__ */ new Map());
7212
- const removeButtonRefs = React15.useRef(/* @__PURE__ */ new Map());
7213
- const targetedProvisionRef = React15.useRef(null);
7214
- const addButtonRef = React15.useRef(null);
7215
- 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);
7216
7428
  const workspaceFence = useWorkspaceSnapshotFence();
7217
7429
  const scheduleAnimationFrame = useAnimationFrameScheduler();
7218
- React15.useEffect(() => {
7430
+ React16.useEffect(() => {
7219
7431
  mountedRef.current = true;
7220
7432
  return () => {
7221
7433
  mountedRef.current = false;
7222
7434
  };
7223
7435
  }, []);
7224
- const announce = React15.useCallback((message) => {
7436
+ const announce = React16.useCallback((message) => {
7225
7437
  setAnnouncement("");
7226
7438
  scheduleAnimationFrame(() => {
7227
7439
  if (message) setAnnouncement(message);
7228
7440
  }, "announcement");
7229
7441
  }, [scheduleAnimationFrame]);
7230
- const invoke = React15.useCallback(async (endpoint, payload = {}, signal) => {
7442
+ const invoke = React16.useCallback(async (endpoint, payload = {}, signal) => {
7231
7443
  return unwrapRpcResult3(await rpcCall(endpoint, payload, signal));
7232
7444
  }, [rpcCall]);
7233
- const mergeSnapshot = React15.useCallback((snapshot, { restoreProvisioning = false } = {}) => {
7445
+ const mergeSnapshot = React16.useCallback((snapshot, { restoreProvisioning = false } = {}) => {
7234
7446
  const now2 = Date.now();
7235
7447
  setModel((current) => mergeFeishuSnapshotState(
7236
7448
  current,
@@ -7238,7 +7450,7 @@ function FeishuSettingsTab({ rpcCall }) {
7238
7450
  { restoreProvisioning, now: now2 }
7239
7451
  ));
7240
7452
  }, []);
7241
- const loadStatus = React15.useCallback(async ({ signal, silent = false, restoreProvisioning = false } = {}) => {
7453
+ const loadStatus = React16.useCallback(async ({ signal, silent = false, restoreProvisioning = false } = {}) => {
7242
7454
  const workspaceVersion = workspaceFence.beginStatus();
7243
7455
  if (workspaceVersion === null || !mountedRef.current) return void 0;
7244
7456
  if (!silent) setPageBusy(true);
@@ -7256,12 +7468,12 @@ function FeishuSettingsTab({ rpcCall }) {
7256
7468
  if (!silent && !signal?.aborted && mountedRef.current) setPageBusy(false);
7257
7469
  }
7258
7470
  }, [invoke, mergeSnapshot, workspaceFence]);
7259
- React15.useEffect(() => {
7471
+ React16.useEffect(() => {
7260
7472
  const controller = new AbortController();
7261
7473
  void loadStatus({ signal: controller.signal, restoreProvisioning: true });
7262
7474
  return () => controller.abort();
7263
7475
  }, [loadStatus]);
7264
- React15.useEffect(() => {
7476
+ React16.useEffect(() => {
7265
7477
  if (model.phase !== "ready") return void 0;
7266
7478
  const controller = new AbortController();
7267
7479
  let inFlight = false;
@@ -7280,7 +7492,7 @@ function FeishuSettingsTab({ rpcCall }) {
7280
7492
  window.clearInterval(timer);
7281
7493
  };
7282
7494
  }, [loadStatus, model.phase]);
7283
- React15.useEffect(() => {
7495
+ React16.useEffect(() => {
7284
7496
  if (!focusBotId) return;
7285
7497
  const node = cardRefs.current.get(focusBotId);
7286
7498
  if (!node) return;
@@ -7289,7 +7501,7 @@ function FeishuSettingsTab({ rpcCall }) {
7289
7501
  setFocusBotId(null);
7290
7502
  }, [focusBotId, model.bots]);
7291
7503
  const targetedProvisionFocusKey = isTargetedAppUpdate2(model.provisioning) ? `${model.provisioning.botId}:${model.provisioning.attemptId ?? "preparing"}:${model.provisioning.phase}` : null;
7292
- React15.useEffect(() => {
7504
+ React16.useEffect(() => {
7293
7505
  if (!targetedProvisionFocusKey) return;
7294
7506
  scheduleAnimationFrame(() => {
7295
7507
  const node = targetedProvisionRef.current;
@@ -7298,7 +7510,7 @@ function FeishuSettingsTab({ rpcCall }) {
7298
7510
  node.focus?.({ preventScroll: true });
7299
7511
  }, "targeted-provision-focus");
7300
7512
  }, [scheduleAnimationFrame, targetedProvisionFocusKey]);
7301
- const startProvisioning = React15.useCallback(async ({
7513
+ const startProvisioning = React16.useCallback(async ({
7302
7514
  replace = false,
7303
7515
  operation = FEISHU_REGISTRATION_OPERATIONS.PROVISION,
7304
7516
  bot
@@ -7374,7 +7586,7 @@ function FeishuSettingsTab({ rpcCall }) {
7374
7586
  model.provisioning?.botId,
7375
7587
  model.provisioning?.botName
7376
7588
  ]);
7377
- const bindCredentials = React15.useCallback(async ({ identity, secret }) => {
7589
+ const bindCredentials = React16.useCallback(async ({ identity, secret }) => {
7378
7590
  const snapshotVersion = workspaceFence.beginMutation();
7379
7591
  setCredentialBusy(true);
7380
7592
  setCredentialError(null);
@@ -7396,7 +7608,7 @@ function FeishuSettingsTab({ rpcCall }) {
7396
7608
  setCredentialBusy(false);
7397
7609
  }
7398
7610
  }, [announce, invoke, loadStatus, mergeSnapshot, workspaceFence]);
7399
- const cancelProvisioning = React15.useCallback(async () => {
7611
+ const cancelProvisioning = React16.useCallback(async () => {
7400
7612
  const activeProvision = model.provisioning;
7401
7613
  const attemptId = activeProvision?.attemptId;
7402
7614
  const repairing = isCallbackRepair(activeProvision);
@@ -7461,7 +7673,7 @@ function FeishuSettingsTab({ rpcCall }) {
7461
7673
  const countdownPhase = model.provisioning?.phase;
7462
7674
  const countdownExpiresAt = model.provisioning?.expiresAt;
7463
7675
  const countdownExpired = model.provisioning?.expired;
7464
- React15.useEffect(() => {
7676
+ React16.useEffect(() => {
7465
7677
  if (!countdownAttemptId || countdownPhase !== "qr" || countdownExpired) return void 0;
7466
7678
  const tick = () => {
7467
7679
  const timestamp8 = Date.now();
@@ -7474,7 +7686,7 @@ function FeishuSettingsTab({ rpcCall }) {
7474
7686
  const timer = window.setInterval(tick, 1e3);
7475
7687
  return () => window.clearInterval(timer);
7476
7688
  }, [countdownAttemptId, countdownPhase, countdownExpiresAt, countdownExpired]);
7477
- React15.useEffect(() => {
7689
+ React16.useEffect(() => {
7478
7690
  const provision2 = model.provisioning;
7479
7691
  if (!provision2 || !["qr", "connecting"].includes(provision2.phase) || !provision2.attemptId || provision2.expired) return void 0;
7480
7692
  const controller = new AbortController();
@@ -7542,7 +7754,7 @@ function FeishuSettingsTab({ rpcCall }) {
7542
7754
  window.clearTimeout(timer);
7543
7755
  };
7544
7756
  }, [announce, invoke, loadStatus, model.provisioning]);
7545
- const setBotBusy = React15.useCallback((botId, value) => {
7757
+ const setBotBusy = React16.useCallback((botId, value) => {
7546
7758
  setBusyByBot((current) => {
7547
7759
  const next = { ...current };
7548
7760
  if (value) next[botId] = value;
@@ -7550,7 +7762,7 @@ function FeishuSettingsTab({ rpcCall }) {
7550
7762
  return next;
7551
7763
  });
7552
7764
  }, []);
7553
- const setBotError = React15.useCallback((botId, error) => {
7765
+ const setBotError = React16.useCallback((botId, error) => {
7554
7766
  setErrorsByBot((current) => {
7555
7767
  const next = { ...current };
7556
7768
  if (error) next[botId] = presentError3(error);
@@ -7558,7 +7770,7 @@ function FeishuSettingsTab({ rpcCall }) {
7558
7770
  return next;
7559
7771
  });
7560
7772
  }, []);
7561
- const repairCallback = React15.useCallback((connection) => {
7773
+ const repairCallback = React16.useCallback((connection) => {
7562
7774
  if (model.provisioning) return;
7563
7775
  setRemoveTargetId(null);
7564
7776
  setBotError(connection.botId, null);
@@ -7572,7 +7784,7 @@ function FeishuSettingsTab({ rpcCall }) {
7572
7784
  bot: connection
7573
7785
  });
7574
7786
  }, [model.provisioning, setBotError, startProvisioning]);
7575
- const reconnectOneBot = React15.useCallback(async (connection) => {
7787
+ const reconnectOneBot = React16.useCallback(async (connection) => {
7576
7788
  const { botId, bot } = connection;
7577
7789
  const snapshotVersion = workspaceFence.beginMutation();
7578
7790
  setBotBusy(botId, "reconnect");
@@ -7612,7 +7824,7 @@ function FeishuSettingsTab({ rpcCall }) {
7612
7824
  setBotBusy(botId, null);
7613
7825
  }
7614
7826
  }, [announce, invoke, loadStatus, mergeSnapshot, setBotBusy, setBotError, workspaceFence]);
7615
- const saveWorkspace = React15.useCallback(async (connection, workspace) => {
7827
+ const saveWorkspace = React16.useCallback(async (connection, workspace) => {
7616
7828
  const { botId } = connection;
7617
7829
  const workspaceVersion = workspaceFence.beginMutation();
7618
7830
  setBotBusy(botId, "workspace");
@@ -7631,7 +7843,7 @@ function FeishuSettingsTab({ rpcCall }) {
7631
7843
  if (mountedRef.current) setBotBusy(botId, null);
7632
7844
  }
7633
7845
  }, [invoke, loadStatus, mergeSnapshot, setBotBusy, setBotError, workspaceFence]);
7634
- const saveBotSetting = React15.useCallback(async (connection, operation, endpoint, payload) => {
7846
+ const saveBotSetting = React16.useCallback(async (connection, operation, endpoint, payload) => {
7635
7847
  const { botId } = connection;
7636
7848
  const snapshotVersion = workspaceFence.beginMutation();
7637
7849
  setBotBusy(botId, operation);
@@ -7650,15 +7862,15 @@ function FeishuSettingsTab({ rpcCall }) {
7650
7862
  if (mountedRef.current) setBotBusy(botId, null);
7651
7863
  }
7652
7864
  }, [invoke, loadStatus, mergeSnapshot, setBotBusy, setBotError, workspaceFence]);
7653
- const requestRemove = React15.useCallback((connection) => {
7865
+ const requestRemove = React16.useCallback((connection) => {
7654
7866
  setRemoveTargetId(connection.botId);
7655
7867
  }, []);
7656
- const cancelRemove = React15.useCallback(() => {
7868
+ const cancelRemove = React16.useCallback(() => {
7657
7869
  const botId = removeTargetId;
7658
7870
  setRemoveTargetId(null);
7659
7871
  scheduleAnimationFrame(() => removeButtonRefs.current.get(botId)?.focus(), "focus");
7660
7872
  }, [removeTargetId, scheduleAnimationFrame]);
7661
- const confirmRemove = React15.useCallback(async (connection) => {
7873
+ const confirmRemove = React16.useCallback(async (connection) => {
7662
7874
  const { botId, bot } = connection;
7663
7875
  const snapshotVersion = workspaceFence.beginMutation();
7664
7876
  setBotBusy(botId, "delete");
@@ -7744,11 +7956,11 @@ function FeishuSettingsTab({ rpcCall }) {
7744
7956
  setCredentialError(null);
7745
7957
  }
7746
7958
  }) : null;
7747
- const setCardRef = React15.useCallback((botId, node) => {
7959
+ const setCardRef = React16.useCallback((botId, node) => {
7748
7960
  if (node) cardRefs.current.set(botId, node);
7749
7961
  else cardRefs.current.delete(botId);
7750
7962
  }, []);
7751
- const setRemoveButtonRef = React15.useCallback((botId, node) => {
7963
+ const setRemoveButtonRef = React16.useCallback((botId, node) => {
7752
7964
  if (node) removeButtonRefs.current.set(botId, node);
7753
7965
  else removeButtonRefs.current.delete(botId);
7754
7966
  }, []);
@@ -7789,7 +8001,7 @@ function FeishuSettingsTab({ rpcCall }) {
7789
8001
  onRetry: () => void loadStatus(),
7790
8002
  busy: pageBusy
7791
8003
  }) : h2(
7792
- React15.Fragment,
8004
+ React16.Fragment,
7793
8005
  null,
7794
8006
  credentialContent,
7795
8007
  targetedProvisioning ? null : provisionContent,
@@ -7806,6 +8018,12 @@ function FeishuSettingsTab({ rpcCall }) {
7806
8018
  onReconnect: (bot) => void reconnectOneBot(bot),
7807
8019
  onRepairCallback: repairCallback,
7808
8020
  onWorkspaceSave: saveWorkspace,
8021
+ onAliasSave: (connection, alias) => saveBotSetting(
8022
+ connection,
8023
+ "alias",
8024
+ FEISHU_ENDPOINTS.setAlias,
8025
+ { alias }
8026
+ ),
7809
8027
  onModelSave: (connection, selectedModel) => saveBotSetting(
7810
8028
  connection,
7811
8029
  "model",
@@ -8432,7 +8650,8 @@ var QQ_ENDPOINTS = Object.freeze({
8432
8650
  setModel: SET_MODEL_ENDPOINT,
8433
8651
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
8434
8652
  setContextEnhancement: "bot.context-enhancement.set",
8435
- setAccessPolicy: "bot.access-policy.set"
8653
+ setAccessPolicy: "bot.access-policy.set",
8654
+ setAlias: "bot.alias.set"
8436
8655
  });
8437
8656
  var PROVISION_STATES2 = /* @__PURE__ */ new Set(["starting", "pending", "refreshing", "connecting", "connected", "failed", "cancelled"]);
8438
8657
  var ACCOUNT_STATES3 = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
@@ -8501,6 +8720,7 @@ function normalizeBot3(value) {
8501
8720
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
8502
8721
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
8503
8722
  bot: {
8723
+ ...normalizeBotAlias(value.bot),
8504
8724
  name: text3(value.bot?.name, "QQ\u673A\u5668\u4EBA", 100),
8505
8725
  appIdMasked: text3(value.bot?.appIdMasked, "\u5E94\u7528\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58", 140)
8506
8726
  },
@@ -8558,7 +8778,7 @@ function formatRemaining3(milliseconds) {
8558
8778
  }
8559
8779
 
8560
8780
  // plugin-src/client/channels/qq/index.js
8561
- var React16 = __toESM(require("react"), 1);
8781
+ var React17 = __toESM(require("react"), 1);
8562
8782
 
8563
8783
  // plugin-src/client/channels/qq/styles.js
8564
8784
  var QQ_STYLE_ID = "xmanrui-dsh-im-qq-settings";
@@ -8583,7 +8803,7 @@ function installQqStyles() {
8583
8803
 
8584
8804
  // plugin-src/client/channels/qq/index.js
8585
8805
  var ACTIVE_STATES = /* @__PURE__ */ new Set(["pending", "refreshing", "connecting"]);
8586
- 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) {
8587
8807
  return h2("button", {
8588
8808
  ...props,
8589
8809
  ref,
@@ -8797,6 +9017,7 @@ function AccountCard2({
8797
9017
  removing,
8798
9018
  onReconnect,
8799
9019
  onWorkspaceSave,
9020
+ onAliasSave,
8800
9021
  onModelSave,
8801
9022
  onAgentPresetSave,
8802
9023
  onContextEnhancementSave,
@@ -8827,7 +9048,7 @@ function AccountCard2({
8827
9048
  h2(
8828
9049
  "div",
8829
9050
  { className: "dim-botName" },
8830
- h2("h3", null, account.bot.name),
9051
+ h2(BotName, { bot: account.bot, disabled: Boolean(busy), onSave: onAliasSave }),
8831
9052
  h2("p", null, account.bot.appIdMasked)
8832
9053
  )
8833
9054
  ),
@@ -8916,7 +9137,7 @@ function AccountCard2({
8916
9137
  );
8917
9138
  }
8918
9139
  function QqSettingsTab({ rpcCall }) {
8919
- const [model, setModel] = React16.useState({
9140
+ const [model, setModel] = React17.useState({
8920
9141
  phase: "loading",
8921
9142
  bots: [],
8922
9143
  totals: { configured: 0, connected: 0 },
@@ -8924,18 +9145,18 @@ function QqSettingsTab({ rpcCall }) {
8924
9145
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
8925
9146
  modelCatalog: EMPTY_MODEL_CATALOG
8926
9147
  });
8927
- const [provision, setProvision] = React16.useState(null);
8928
- const [busy, setBusy] = React16.useState(false);
8929
- const [busyByBot, setBusyByBot] = React16.useState({});
8930
- const [feedbackByBot, setFeedbackByBot] = React16.useState({});
8931
- const [removeTarget, setRemoveTarget] = React16.useState(null);
8932
- const [credentialOpen, setCredentialOpen] = React16.useState(false);
8933
- const [credentialError, setCredentialError] = React16.useState(null);
8934
- const [now, setNow] = React16.useState(Date.now());
8935
- 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);
8936
9157
  const workspaceFence = useWorkspaceSnapshotFence();
8937
- const addButtonRef = React16.useRef(null);
8938
- React16.useEffect(() => {
9158
+ const addButtonRef = React17.useRef(null);
9159
+ React17.useEffect(() => {
8939
9160
  const disposeDingtalk = installDingtalkStyles();
8940
9161
  const disposeQq = installQqStyles();
8941
9162
  mounted.current = true;
@@ -8945,11 +9166,11 @@ function QqSettingsTab({ rpcCall }) {
8945
9166
  disposeDingtalk();
8946
9167
  };
8947
9168
  }, []);
8948
- const invoke = React16.useCallback(async (endpoint, payload = {}, signal) => {
9169
+ const invoke = React17.useCallback(async (endpoint, payload = {}, signal) => {
8949
9170
  if (typeof rpcCall !== "function") throw new TypeError("QQ \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
8950
9171
  return unwrapRpcResult4(await rpcCall(endpoint, payload, signal));
8951
9172
  }, [rpcCall]);
8952
- const loadStatus = React16.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
9173
+ const loadStatus = React17.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
8953
9174
  const workspaceVersion = workspaceFence.beginStatus();
8954
9175
  if (workspaceVersion === null) return void 0;
8955
9176
  if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
@@ -8976,12 +9197,12 @@ function QqSettingsTab({ rpcCall }) {
8976
9197
  return void 0;
8977
9198
  }
8978
9199
  }, [invoke, workspaceFence]);
8979
- React16.useEffect(() => {
9200
+ React17.useEffect(() => {
8980
9201
  const controller = new AbortController();
8981
9202
  void loadStatus({ signal: controller.signal, restore: true });
8982
9203
  return () => controller.abort();
8983
9204
  }, [loadStatus]);
8984
- React16.useEffect(() => {
9205
+ React17.useEffect(() => {
8985
9206
  if (model.phase !== "ready") return void 0;
8986
9207
  const controller = new AbortController();
8987
9208
  const timer = window.setInterval(() => void loadStatus({ signal: controller.signal, silent: true }), 15e3);
@@ -8990,12 +9211,12 @@ function QqSettingsTab({ rpcCall }) {
8990
9211
  window.clearInterval(timer);
8991
9212
  };
8992
9213
  }, [loadStatus, model.phase]);
8993
- React16.useEffect(() => {
9214
+ React17.useEffect(() => {
8994
9215
  if (!provision || !ACTIVE_STATES.has(provision.status)) return void 0;
8995
9216
  const timer = window.setInterval(() => mounted.current && setNow(Date.now()), 1e3);
8996
9217
  return () => window.clearInterval(timer);
8997
9218
  }, [provision?.attemptId, provision?.status]);
8998
- const startProvisioning = React16.useCallback(async (replace = false) => {
9219
+ const startProvisioning = React17.useCallback(async (replace = false) => {
8999
9220
  setCredentialOpen(false);
9000
9221
  setCredentialError(null);
9001
9222
  setBusy(true);
@@ -9013,7 +9234,7 @@ function QqSettingsTab({ rpcCall }) {
9013
9234
  if (mounted.current) setBusy(false);
9014
9235
  }
9015
9236
  }, [invoke, provision?.attemptId]);
9016
- const bindCredentials = React16.useCallback(async ({ identity, secret }) => {
9237
+ const bindCredentials = React17.useCallback(async ({ identity, secret }) => {
9017
9238
  const snapshotVersion = workspaceFence.beginMutation();
9018
9239
  setBusy(true);
9019
9240
  setCredentialError(null);
@@ -9042,7 +9263,7 @@ function QqSettingsTab({ rpcCall }) {
9042
9263
  if (mounted.current) setBusy(false);
9043
9264
  }
9044
9265
  }, [invoke, loadStatus, workspaceFence]);
9045
- const closeProvision = React16.useCallback(async () => {
9266
+ const closeProvision = React17.useCallback(async () => {
9046
9267
  setBusy(true);
9047
9268
  try {
9048
9269
  if (provision?.attemptId && ACTIVE_STATES.has(provision.status)) {
@@ -9053,7 +9274,7 @@ function QqSettingsTab({ rpcCall }) {
9053
9274
  if (mounted.current) setBusy(false);
9054
9275
  }
9055
9276
  }, [invoke, provision?.attemptId, provision?.status]);
9056
- React16.useEffect(() => {
9277
+ React17.useEffect(() => {
9057
9278
  const attemptId = provision?.attemptId;
9058
9279
  if (!attemptId || !ACTIVE_STATES.has(provision.status)) return void 0;
9059
9280
  const controller = new AbortController();
@@ -9083,7 +9304,7 @@ function QqSettingsTab({ rpcCall }) {
9083
9304
  window.clearTimeout(timer);
9084
9305
  };
9085
9306
  }, [invoke, loadStatus, provision?.attemptId, provision?.pollIntervalMs, provision?.status]);
9086
- const botAction = React16.useCallback(async (account, operation, endpoint, payload) => {
9307
+ const botAction = React17.useCallback(async (account, operation, endpoint, payload) => {
9087
9308
  const snapshotVersion = workspaceFence.beginMutation();
9088
9309
  setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
9089
9310
  try {
@@ -9109,7 +9330,7 @@ function QqSettingsTab({ rpcCall }) {
9109
9330
  });
9110
9331
  }
9111
9332
  }, [invoke, loadStatus, workspaceFence]);
9112
- const reconnect = React16.useCallback(async (account) => {
9333
+ const reconnect = React17.useCallback(async (account) => {
9113
9334
  setFeedbackByBot((current) => {
9114
9335
  const next = { ...current };
9115
9336
  delete next[account.botId];
@@ -9172,6 +9393,12 @@ function QqSettingsTab({ rpcCall }) {
9172
9393
  QQ_ENDPOINTS.setWorkspace,
9173
9394
  { botId: account.botId, workspace }
9174
9395
  ),
9396
+ onAliasSave: (alias) => botAction(
9397
+ account,
9398
+ "alias",
9399
+ QQ_ENDPOINTS.setAlias,
9400
+ { botId: account.botId, alias }
9401
+ ),
9175
9402
  onModelSave: (selectedModel) => botAction(
9176
9403
  account,
9177
9404
  "model",
@@ -9232,7 +9459,7 @@ function QqSettingsTab({ rpcCall }) {
9232
9459
  addButtonRef
9233
9460
  }),
9234
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(
9235
- React16.Fragment,
9462
+ React17.Fragment,
9236
9463
  null,
9237
9464
  credentialView,
9238
9465
  provisionView,
@@ -9321,7 +9548,7 @@ function normalizeOfficeStatus(value) {
9321
9548
  }
9322
9549
 
9323
9550
  // plugin-src/client/channels/office/index.js
9324
- var React17 = __toESM(require("react"), 1);
9551
+ var React18 = __toESM(require("react"), 1);
9325
9552
  function Button9({ children, kind = "secondary", ...props }) {
9326
9553
  return h2("button", { ...props, type: "button", className: "ddt-button", "data-kind": kind }, children);
9327
9554
  }
@@ -9350,12 +9577,12 @@ function stateLabel(model) {
9350
9577
  return "\u5DF2\u914D\u7F6E";
9351
9578
  }
9352
9579
  function OfficeSettingsTab({ rpcCall, initialStatus }) {
9353
- const [model, setModel] = React17.useState(normalizeOfficeStatus(initialStatus));
9354
- const [phase, setPhase] = React17.useState(initialStatus === void 0 ? "loading" : "ready");
9355
- const [busy, setBusy] = React17.useState("");
9356
- const [error, setError] = React17.useState("");
9357
- const [notice, setNotice] = React17.useState("");
9358
- 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({
9359
9586
  baseUrl: "",
9360
9587
  deviceId: "local-harness",
9361
9588
  deviceToken: "",
@@ -9364,11 +9591,11 @@ function OfficeSettingsTab({ rpcCall, initialStatus }) {
9364
9591
  workspaces: "",
9365
9592
  instructionPresets: ""
9366
9593
  });
9367
- const invoke = React17.useCallback(async (endpoint, payload = {}) => {
9594
+ const invoke = React18.useCallback(async (endpoint, payload = {}) => {
9368
9595
  if (typeof rpcCall !== "function") throw new Error("AI Office \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
9369
9596
  return unwrapOfficeRpc(await rpcCall(endpoint, payload));
9370
9597
  }, [rpcCall]);
9371
- const adopt = React17.useCallback((value) => {
9598
+ const adopt = React18.useCallback((value) => {
9372
9599
  const next = normalizeOfficeStatus(value?.snapshot ?? value);
9373
9600
  setModel(next);
9374
9601
  if (next.config) setForm((current) => ({
@@ -9383,7 +9610,7 @@ function OfficeSettingsTab({ rpcCall, initialStatus }) {
9383
9610
  }));
9384
9611
  return next;
9385
9612
  }, []);
9386
- const load = React17.useCallback(async () => {
9613
+ const load = React18.useCallback(async () => {
9387
9614
  try {
9388
9615
  adopt(await invoke(OFFICE_RPC_ENDPOINTS.status));
9389
9616
  setPhase("ready");
@@ -9393,7 +9620,7 @@ function OfficeSettingsTab({ rpcCall, initialStatus }) {
9393
9620
  setError(caught.message);
9394
9621
  }
9395
9622
  }, [adopt, invoke]);
9396
- React17.useEffect(() => {
9623
+ React18.useEffect(() => {
9397
9624
  void load();
9398
9625
  }, [load]);
9399
9626
  const run = async (name2, operation) => {
@@ -9410,7 +9637,7 @@ function OfficeSettingsTab({ rpcCall, initialStatus }) {
9410
9637
  setBusy("");
9411
9638
  }
9412
9639
  };
9413
- const hooks = React17.useMemo(() => {
9640
+ const hooks = React18.useMemo(() => {
9414
9641
  try {
9415
9642
  return officeHookUrls(form.baseUrl);
9416
9643
  } catch {
@@ -9595,7 +9822,7 @@ var normalizeSnapshot4 = api2.normalizeSnapshot;
9595
9822
  var presentError5 = api2.presentError;
9596
9823
 
9597
9824
  // plugin-src/client/channels/slack/index.js
9598
- var React18 = __toESM(require("react"), 1);
9825
+ var React19 = __toESM(require("react"), 1);
9599
9826
 
9600
9827
  // src/channels/slack/manifest.mjs
9601
9828
  var SLACK_APP_MANIFEST_YAML = `_metadata:
@@ -9673,10 +9900,10 @@ function installSlackStyles() {
9673
9900
 
9674
9901
  // plugin-src/client/channels/slack/index.js
9675
9902
  function SlackCredentialPanel({ busy, error, onSubmit, onCancel }) {
9676
- const [botToken, setBotToken] = React18.useState("");
9677
- const [appToken, setAppToken] = React18.useState("");
9678
- const [copied, setCopied] = React18.useState(false);
9679
- 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();
9680
9907
  const copyManifest = async () => {
9681
9908
  try {
9682
9909
  await navigator.clipboard.writeText(SLACK_APP_MANIFEST_YAML);
@@ -9874,7 +10101,8 @@ var WECOM_ENDPOINTS = Object.freeze({
9874
10101
  setModel: SET_MODEL_ENDPOINT,
9875
10102
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
9876
10103
  setContextEnhancement: "bot.context-enhancement.set",
9877
- setAccessPolicy: "bot.access-policy.set"
10104
+ setAccessPolicy: "bot.access-policy.set",
10105
+ setAlias: "bot.alias.set"
9878
10106
  });
9879
10107
  var PROVISION_STATES3 = /* @__PURE__ */ new Set(["starting", "pending", "refreshing", "connecting", "connected", "failed", "cancelled"]);
9880
10108
  var ACCOUNT_STATES4 = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
@@ -9949,6 +10177,7 @@ function normalizeBot4(value) {
9949
10177
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
9950
10178
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
9951
10179
  bot: {
10180
+ ...normalizeBotAlias(value.bot),
9952
10181
  name: text4(value.bot?.name, "\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA", 100),
9953
10182
  appIdMasked: text4(value.bot?.appIdMasked, "\u5E94\u7528\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58", 140)
9954
10183
  },
@@ -9989,7 +10218,7 @@ function formatRemaining4(milliseconds) {
9989
10218
  }
9990
10219
 
9991
10220
  // plugin-src/client/channels/wecom/index.js
9992
- var React19 = __toESM(require("react"), 1);
10221
+ var React20 = __toESM(require("react"), 1);
9993
10222
 
9994
10223
  // plugin-src/client/channels/wecom/styles.js
9995
10224
  var WECOM_STYLE_ID = "xmanrui-dsh-im-wecom-settings";
@@ -10014,7 +10243,7 @@ function installWecomStyles() {
10014
10243
 
10015
10244
  // plugin-src/client/channels/wecom/index.js
10016
10245
  var ACTIVE_STATES2 = /* @__PURE__ */ new Set(["pending", "refreshing", "connecting"]);
10017
- 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) {
10018
10247
  return h2("button", {
10019
10248
  ...props,
10020
10249
  ref,
@@ -10228,6 +10457,7 @@ function AccountCard3({
10228
10457
  removing,
10229
10458
  onReconnect,
10230
10459
  onWorkspaceSave,
10460
+ onAliasSave,
10231
10461
  onModelSave,
10232
10462
  onAgentPresetSave,
10233
10463
  onContextEnhancementSave,
@@ -10258,7 +10488,7 @@ function AccountCard3({
10258
10488
  h2(
10259
10489
  "div",
10260
10490
  { className: "dim-botName" },
10261
- h2("h3", null, account.bot.name),
10491
+ h2(BotName, { bot: account.bot, disabled: Boolean(busy), onSave: onAliasSave }),
10262
10492
  h2("p", null, account.bot.appIdMasked)
10263
10493
  )
10264
10494
  ),
@@ -10347,7 +10577,7 @@ function AccountCard3({
10347
10577
  );
10348
10578
  }
10349
10579
  function WecomSettingsTab({ rpcCall }) {
10350
- const [model, setModel] = React19.useState({
10580
+ const [model, setModel] = React20.useState({
10351
10581
  phase: "loading",
10352
10582
  bots: [],
10353
10583
  totals: { configured: 0, connected: 0 },
@@ -10355,20 +10585,20 @@ function WecomSettingsTab({ rpcCall }) {
10355
10585
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
10356
10586
  modelCatalog: EMPTY_MODEL_CATALOG
10357
10587
  });
10358
- const [provision, setProvision] = React19.useState(null);
10359
- const [busy, setBusy] = React19.useState(false);
10360
- const [busyByBot, setBusyByBot] = React19.useState({});
10361
- const [feedbackByBot, setFeedbackByBot] = React19.useState({});
10362
- const [removeTarget, setRemoveTarget] = React19.useState(null);
10363
- const [credentialOpen, setCredentialOpen] = React19.useState(false);
10364
- const [credentialError, setCredentialError] = React19.useState(null);
10365
- const [notice, setNotice] = React19.useState("");
10366
- const [now, setNow] = React19.useState(Date.now());
10367
- 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);
10368
10598
  const workspaceFence = useWorkspaceSnapshotFence();
10369
- const addButtonRef = React19.useRef(null);
10370
- const noticeFrameRef = React19.useRef(null);
10371
- const announce = React19.useCallback((message) => {
10599
+ const addButtonRef = React20.useRef(null);
10600
+ const noticeFrameRef = React20.useRef(null);
10601
+ const announce = React20.useCallback((message) => {
10372
10602
  if (!mounted.current) return;
10373
10603
  if (noticeFrameRef.current !== null) {
10374
10604
  window.cancelAnimationFrame(noticeFrameRef.current);
@@ -10382,7 +10612,7 @@ function WecomSettingsTab({ rpcCall }) {
10382
10612
  });
10383
10613
  }
10384
10614
  }, []);
10385
- React19.useEffect(() => {
10615
+ React20.useEffect(() => {
10386
10616
  const disposeDingtalk = installDingtalkStyles();
10387
10617
  const disposeWecom = installWecomStyles();
10388
10618
  mounted.current = true;
@@ -10396,11 +10626,11 @@ function WecomSettingsTab({ rpcCall }) {
10396
10626
  disposeDingtalk();
10397
10627
  };
10398
10628
  }, []);
10399
- const invoke = React19.useCallback(async (endpoint, payload = {}, signal) => {
10629
+ const invoke = React20.useCallback(async (endpoint, payload = {}, signal) => {
10400
10630
  if (typeof rpcCall !== "function") throw new TypeError("\u4F01\u4E1A\u5FAE\u4FE1\u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
10401
10631
  return unwrapRpcResult7(await rpcCall(endpoint, payload, signal));
10402
10632
  }, [rpcCall]);
10403
- const loadStatus = React19.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
10633
+ const loadStatus = React20.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
10404
10634
  const workspaceVersion = workspaceFence.beginStatus();
10405
10635
  if (workspaceVersion === null) return void 0;
10406
10636
  if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
@@ -10427,12 +10657,12 @@ function WecomSettingsTab({ rpcCall }) {
10427
10657
  return void 0;
10428
10658
  }
10429
10659
  }, [invoke, workspaceFence]);
10430
- React19.useEffect(() => {
10660
+ React20.useEffect(() => {
10431
10661
  const controller = new AbortController();
10432
10662
  void loadStatus({ signal: controller.signal, restore: true });
10433
10663
  return () => controller.abort();
10434
10664
  }, [loadStatus]);
10435
- React19.useEffect(() => {
10665
+ React20.useEffect(() => {
10436
10666
  if (model.phase !== "ready") return void 0;
10437
10667
  const controller = new AbortController();
10438
10668
  const timer = window.setInterval(() => void loadStatus({ signal: controller.signal, silent: true }), 15e3);
@@ -10441,12 +10671,12 @@ function WecomSettingsTab({ rpcCall }) {
10441
10671
  window.clearInterval(timer);
10442
10672
  };
10443
10673
  }, [loadStatus, model.phase]);
10444
- React19.useEffect(() => {
10674
+ React20.useEffect(() => {
10445
10675
  if (!provision || !ACTIVE_STATES2.has(provision.status)) return void 0;
10446
10676
  const timer = window.setInterval(() => mounted.current && setNow(Date.now()), 1e3);
10447
10677
  return () => window.clearInterval(timer);
10448
10678
  }, [provision?.attemptId, provision?.status]);
10449
- const startProvisioning = React19.useCallback(async (replace = false) => {
10679
+ const startProvisioning = React20.useCallback(async (replace = false) => {
10450
10680
  setCredentialOpen(false);
10451
10681
  setCredentialError(null);
10452
10682
  setBusy(true);
@@ -10464,7 +10694,7 @@ function WecomSettingsTab({ rpcCall }) {
10464
10694
  if (mounted.current) setBusy(false);
10465
10695
  }
10466
10696
  }, [invoke, provision?.attemptId]);
10467
- const bindCredentials = React19.useCallback(async ({ identity, secret }) => {
10697
+ const bindCredentials = React20.useCallback(async ({ identity, secret }) => {
10468
10698
  const snapshotVersion = workspaceFence.beginMutation();
10469
10699
  setBusy(true);
10470
10700
  setCredentialError(null);
@@ -10493,7 +10723,7 @@ function WecomSettingsTab({ rpcCall }) {
10493
10723
  if (mounted.current) setBusy(false);
10494
10724
  }
10495
10725
  }, [invoke, loadStatus, workspaceFence]);
10496
- const closeProvision = React19.useCallback(async () => {
10726
+ const closeProvision = React20.useCallback(async () => {
10497
10727
  setBusy(true);
10498
10728
  try {
10499
10729
  if (provision?.attemptId && ACTIVE_STATES2.has(provision.status)) {
@@ -10504,7 +10734,7 @@ function WecomSettingsTab({ rpcCall }) {
10504
10734
  if (mounted.current) setBusy(false);
10505
10735
  }
10506
10736
  }, [invoke, provision?.attemptId, provision?.status]);
10507
- React19.useEffect(() => {
10737
+ React20.useEffect(() => {
10508
10738
  const attemptId = provision?.attemptId;
10509
10739
  if (!attemptId || !ACTIVE_STATES2.has(provision.status)) return void 0;
10510
10740
  const controller = new AbortController();
@@ -10534,7 +10764,7 @@ function WecomSettingsTab({ rpcCall }) {
10534
10764
  window.clearTimeout(timer);
10535
10765
  };
10536
10766
  }, [invoke, loadStatus, provision?.attemptId, provision?.pollIntervalMs, provision?.status]);
10537
- const botAction = React19.useCallback(async (account, operation, endpoint, payload) => {
10767
+ const botAction = React20.useCallback(async (account, operation, endpoint, payload) => {
10538
10768
  const snapshotVersion = workspaceFence.beginMutation();
10539
10769
  setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
10540
10770
  try {
@@ -10560,7 +10790,7 @@ function WecomSettingsTab({ rpcCall }) {
10560
10790
  });
10561
10791
  }
10562
10792
  }, [invoke, loadStatus, workspaceFence]);
10563
- const reconnect = React19.useCallback(async (account) => {
10793
+ const reconnect = React20.useCallback(async (account) => {
10564
10794
  setFeedbackByBot((current) => {
10565
10795
  const next = { ...current };
10566
10796
  delete next[account.botId];
@@ -10634,6 +10864,12 @@ function WecomSettingsTab({ rpcCall }) {
10634
10864
  WECOM_ENDPOINTS.setWorkspace,
10635
10865
  { botId: account.botId, workspace }
10636
10866
  ),
10867
+ onAliasSave: (alias) => botAction(
10868
+ account,
10869
+ "alias",
10870
+ WECOM_ENDPOINTS.setAlias,
10871
+ { botId: account.botId, alias }
10872
+ ),
10637
10873
  onModelSave: (selectedModel) => botAction(
10638
10874
  account,
10639
10875
  "model",
@@ -10695,7 +10931,7 @@ function WecomSettingsTab({ rpcCall }) {
10695
10931
  }),
10696
10932
  h2("div", { className: "ddt-visuallyHidden", role: "status", "aria-live": "polite" }, notice),
10697
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(
10698
- React19.Fragment,
10934
+ React20.Fragment,
10699
10935
  null,
10700
10936
  credentialView,
10701
10937
  provisionView,
@@ -10718,7 +10954,8 @@ var WECOM_APP_ENDPOINTS = Object.freeze({
10718
10954
  setModel: SET_MODEL_ENDPOINT,
10719
10955
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
10720
10956
  setContextEnhancement: "bot.context-enhancement.set",
10721
- setAccessPolicy: "bot.access-policy.set"
10957
+ setAccessPolicy: "bot.access-policy.set",
10958
+ setAlias: "bot.alias.set"
10722
10959
  });
10723
10960
  var ACCOUNT_STATES5 = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
10724
10961
  function isRecord6(value) {
@@ -10770,6 +11007,7 @@ function normalizeBot5(value) {
10770
11007
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
10771
11008
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
10772
11009
  bot: {
11010
+ ...normalizeBotAlias(value.bot),
10773
11011
  name: text5(value.bot?.name, "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528", 100),
10774
11012
  corpIdMasked: text5(value.bot?.corpIdMasked, "\u4F01\u4E1A ID \u5DF2\u4FDD\u5B58", 140),
10775
11013
  agentId: text5(value.bot?.agentId, "", 32),
@@ -10810,7 +11048,7 @@ function presentError8(error) {
10810
11048
  }
10811
11049
 
10812
11050
  // plugin-src/client/channels/wecom-app/index.js
10813
- var React20 = __toESM(require("react"), 1);
11051
+ var React21 = __toESM(require("react"), 1);
10814
11052
 
10815
11053
  // plugin-src/client/channels/wecom-app/styles.js
10816
11054
  var WECOM_APP_STYLE_ID = "xmanrui-dsh-im-wecom-app-settings";
@@ -10840,7 +11078,7 @@ function installWecomAppStyles() {
10840
11078
  }
10841
11079
 
10842
11080
  // plugin-src/client/channels/wecom-app/index.js
10843
- 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) {
10844
11082
  return h2("button", {
10845
11083
  ...props,
10846
11084
  ref,
@@ -10948,16 +11186,16 @@ function Field({ label, value, onChange, placeholder, busy, required = false, ty
10948
11186
  );
10949
11187
  }
10950
11188
  function BindForm({ busy, error, onSubmit, onCancel }) {
10951
- const [corpId, setCorpId] = React20.useState("");
10952
- const [agentId, setAgentId] = React20.useState("");
10953
- const [secret, setSecret] = React20.useState("");
10954
- const [token, setToken] = React20.useState("");
10955
- const [aesKey, setAesKey] = React20.useState("");
10956
- const [apiBaseUrl, setApiBaseUrl] = React20.useState("");
10957
- const [callbackBaseUrl, setCallbackBaseUrl] = React20.useState("");
10958
- const [streamEnabled, setStreamEnabled] = React20.useState(true);
10959
- const headingId = React20.useId();
10960
- 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);
10961
11199
  const submit = (event) => {
10962
11200
  event.preventDefault();
10963
11201
  if (busy) return;
@@ -11020,7 +11258,7 @@ function BindForm({ busy, error, onSubmit, onCancel }) {
11020
11258
  );
11021
11259
  }
11022
11260
  function CallbackUrlBox({ url, busy, resetBusy, onCopy, onReset }) {
11023
- const [copied, setCopied] = React20.useState(false);
11261
+ const [copied, setCopied] = React21.useState(false);
11024
11262
  const copy = async () => {
11025
11263
  try {
11026
11264
  await navigator.clipboard.writeText(url);
@@ -11054,12 +11292,12 @@ function CallbackUrlBox({ url, busy, resetBusy, onCopy, onReset }) {
11054
11292
  );
11055
11293
  }
11056
11294
  function AppSettingsEditor({ bot, busy, onSave }) {
11057
- const [apiBaseUrl, setApiBaseUrl] = React20.useState(bot.apiBaseUrl ?? "");
11058
- const [callbackBaseUrl, setCallbackBaseUrl] = React20.useState(bot.callbackBaseUrl ?? "");
11059
- const [streamEnabled, setStreamEnabled] = React20.useState(bot.streamEnabled !== false);
11060
- const [dirty, setDirty] = React20.useState(false);
11061
- const formRef = React20.useRef(null);
11062
- 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(() => {
11063
11301
  setApiBaseUrl(bot.apiBaseUrl ?? "");
11064
11302
  setCallbackBaseUrl(bot.callbackBaseUrl ?? "");
11065
11303
  setStreamEnabled(bot.streamEnabled !== false);
@@ -11131,6 +11369,7 @@ function AccountCard4({
11131
11369
  onSettingsSave,
11132
11370
  onSecretReset,
11133
11371
  onWorkspaceSave,
11372
+ onAliasSave,
11134
11373
  onModelSave,
11135
11374
  onAgentPresetSave,
11136
11375
  onContextEnhancementSave,
@@ -11162,7 +11401,7 @@ function AccountCard4({
11162
11401
  h2(
11163
11402
  "div",
11164
11403
  { className: "dim-botName" },
11165
- h2("h3", null, account.bot.name),
11404
+ h2(BotName, { bot: account.bot, disabled: Boolean(busy), onSave: onAliasSave }),
11166
11405
  h2("p", null, `${account.bot.corpIdMasked} \xB7 AgentId ${account.bot.agentId}`)
11167
11406
  )
11168
11407
  ),
@@ -11261,7 +11500,7 @@ function AccountCard4({
11261
11500
  );
11262
11501
  }
11263
11502
  function WecomAppSettingsTab({ rpcCall }) {
11264
- const [model, setModel] = React20.useState({
11503
+ const [model, setModel] = React21.useState({
11265
11504
  phase: "loading",
11266
11505
  bots: [],
11267
11506
  totals: { configured: 0, connected: 0 },
@@ -11269,18 +11508,18 @@ function WecomAppSettingsTab({ rpcCall }) {
11269
11508
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
11270
11509
  modelCatalog: EMPTY_MODEL_CATALOG
11271
11510
  });
11272
- const [bindOpen, setBindOpen] = React20.useState(false);
11273
- const [bindError, setBindError] = React20.useState(null);
11274
- const [busy, setBusy] = React20.useState(false);
11275
- const [busyByBot, setBusyByBot] = React20.useState({});
11276
- const [feedbackByBot, setFeedbackByBot] = React20.useState({});
11277
- const [removeTarget, setRemoveTarget] = React20.useState(null);
11278
- const [notice, setNotice] = React20.useState("");
11279
- 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);
11280
11519
  const workspaceFence = useWorkspaceSnapshotFence();
11281
- const addButtonRef = React20.useRef(null);
11282
- const noticeFrameRef = React20.useRef(null);
11283
- const announce = React20.useCallback((message) => {
11520
+ const addButtonRef = React21.useRef(null);
11521
+ const noticeFrameRef = React21.useRef(null);
11522
+ const announce = React21.useCallback((message) => {
11284
11523
  if (!mounted.current) return;
11285
11524
  if (noticeFrameRef.current !== null) {
11286
11525
  window.cancelAnimationFrame(noticeFrameRef.current);
@@ -11294,7 +11533,7 @@ function WecomAppSettingsTab({ rpcCall }) {
11294
11533
  });
11295
11534
  }
11296
11535
  }, []);
11297
- React20.useEffect(() => {
11536
+ React21.useEffect(() => {
11298
11537
  const disposeDingtalk = installDingtalkStyles();
11299
11538
  const disposeWecomApp = installWecomAppStyles();
11300
11539
  mounted.current = true;
@@ -11308,11 +11547,11 @@ function WecomAppSettingsTab({ rpcCall }) {
11308
11547
  disposeDingtalk();
11309
11548
  };
11310
11549
  }, []);
11311
- const invoke = React20.useCallback(async (endpoint, payload = {}, signal) => {
11550
+ const invoke = React21.useCallback(async (endpoint, payload = {}, signal) => {
11312
11551
  if (typeof rpcCall !== "function") throw new TypeError("\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
11313
11552
  return unwrapRpcResult8(await rpcCall(endpoint, payload, signal));
11314
11553
  }, [rpcCall]);
11315
- const loadStatus = React20.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
11554
+ const loadStatus = React21.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
11316
11555
  const workspaceVersion = workspaceFence.beginStatus();
11317
11556
  if (workspaceVersion === null) return void 0;
11318
11557
  if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
@@ -11336,12 +11575,12 @@ function WecomAppSettingsTab({ rpcCall }) {
11336
11575
  return void 0;
11337
11576
  }
11338
11577
  }, [invoke, workspaceFence]);
11339
- React20.useEffect(() => {
11578
+ React21.useEffect(() => {
11340
11579
  const controller = new AbortController();
11341
11580
  void loadStatus({ signal: controller.signal, restore: true });
11342
11581
  return () => controller.abort();
11343
11582
  }, [loadStatus]);
11344
- React20.useEffect(() => {
11583
+ React21.useEffect(() => {
11345
11584
  if (model.phase !== "ready") return void 0;
11346
11585
  const controller = new AbortController();
11347
11586
  const timer = window.setInterval(() => void loadStatus({ signal: controller.signal, silent: true }), 15e3);
@@ -11350,7 +11589,7 @@ function WecomAppSettingsTab({ rpcCall }) {
11350
11589
  window.clearInterval(timer);
11351
11590
  };
11352
11591
  }, [loadStatus, model.phase]);
11353
- const bindApp = React20.useCallback(async (payload) => {
11592
+ const bindApp = React21.useCallback(async (payload) => {
11354
11593
  const snapshotVersion = workspaceFence.beginMutation();
11355
11594
  setBusy(true);
11356
11595
  setBindError(null);
@@ -11377,7 +11616,7 @@ function WecomAppSettingsTab({ rpcCall }) {
11377
11616
  if (mounted.current) setBusy(false);
11378
11617
  }
11379
11618
  }, [announce, invoke, loadStatus, workspaceFence]);
11380
- const botAction = React20.useCallback(async (account, operation, endpoint, payload) => {
11619
+ const botAction = React21.useCallback(async (account, operation, endpoint, payload) => {
11381
11620
  const snapshotVersion = workspaceFence.beginMutation();
11382
11621
  setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
11383
11622
  try {
@@ -11403,7 +11642,7 @@ function WecomAppSettingsTab({ rpcCall }) {
11403
11642
  });
11404
11643
  }
11405
11644
  }, [invoke, loadStatus, workspaceFence]);
11406
- const reconnect = React20.useCallback(async (account) => {
11645
+ const reconnect = React21.useCallback(async (account) => {
11407
11646
  setFeedbackByBot((current) => {
11408
11647
  const next = { ...current };
11409
11648
  delete next[account.botId];
@@ -11476,6 +11715,12 @@ function WecomAppSettingsTab({ rpcCall }) {
11476
11715
  WECOM_APP_ENDPOINTS.setWorkspace,
11477
11716
  { botId: account.botId, workspace }
11478
11717
  ),
11718
+ onAliasSave: (alias) => botAction(
11719
+ account,
11720
+ "alias",
11721
+ WECOM_APP_ENDPOINTS.setAlias,
11722
+ { botId: account.botId, alias }
11723
+ ),
11479
11724
  onModelSave: (selectedModel) => botAction(
11480
11725
  account,
11481
11726
  "model",
@@ -11530,7 +11775,7 @@ function WecomAppSettingsTab({ rpcCall }) {
11530
11775
  }),
11531
11776
  h2("div", { className: "ddt-visuallyHidden", role: "status", "aria-live": "polite" }, notice),
11532
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(
11533
- React20.Fragment,
11778
+ React21.Fragment,
11534
11779
  null,
11535
11780
  bindView,
11536
11781
  model.bots.length === 0 && !bindOpen ? h2(EmptyView5, { busy, onStart: () => setBindOpen(true) }) : null,
@@ -11540,7 +11785,7 @@ function WecomAppSettingsTab({ rpcCall }) {
11540
11785
  }
11541
11786
 
11542
11787
  // plugin-src/client/channels/weixin/index.js
11543
- var React21 = __toESM(require("react"), 1);
11788
+ var React22 = __toESM(require("react"), 1);
11544
11789
 
11545
11790
  // plugin-src/client/channels/weixin/api.js
11546
11791
  var WEIXIN_RPC_CHANNEL = "/weixin";
@@ -11556,7 +11801,8 @@ var WEIXIN_ENDPOINTS = Object.freeze({
11556
11801
  setModel: SET_MODEL_ENDPOINT,
11557
11802
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
11558
11803
  setContextEnhancement: "bot.context-enhancement.set",
11559
- setAccessPolicy: "bot.access-policy.set"
11804
+ setAccessPolicy: "bot.access-policy.set",
11805
+ setAlias: "bot.alias.set"
11560
11806
  });
11561
11807
  var ACCOUNT_STATES6 = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
11562
11808
  var PROVISION_STATES4 = /* @__PURE__ */ new Set([
@@ -11651,6 +11897,7 @@ function normalizeBot6(value) {
11651
11897
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
11652
11898
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
11653
11899
  bot: {
11900
+ ...normalizeBotAlias(value.bot),
11654
11901
  name: string(value.bot.name, "\u5FAE\u4FE1\u673A\u5668\u4EBA"),
11655
11902
  accountIdMasked: string(value.bot.accountIdMasked, "\u5DF2\u5B89\u5168\u4FDD\u5B58")
11656
11903
  },
@@ -11702,7 +11949,7 @@ function formatRemaining5(milliseconds) {
11702
11949
  }
11703
11950
 
11704
11951
  // plugin-src/client/channels/weixin/index.js
11705
- 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) {
11706
11953
  return h2("button", {
11707
11954
  ...props,
11708
11955
  ref,
@@ -11775,14 +12022,14 @@ function EmptyView6({ onStart, busy }) {
11775
12022
  );
11776
12023
  }
11777
12024
  function QrPanel4({ provision, now, busy, onRefresh, onCancel }) {
11778
- const [imageFailed, setImageFailed] = React21.useState(false);
12025
+ const [imageFailed, setImageFailed] = React22.useState(false);
11779
12026
  const source = safeQrSource5(provision.qrCodeDataUrl);
11780
12027
  const href = safeVerificationUrl(provision.verificationUrl);
11781
12028
  const remaining = Math.max(0, provision.expiresAt - now);
11782
12029
  const expired = remaining === 0 || provision.status === "expired";
11783
12030
  const duration = Math.max(1, provision.durationMs ?? 5 * 6e4);
11784
12031
  const progress = Math.round(Math.min(1, remaining / duration) * 100);
11785
- React21.useEffect(() => setImageFailed(false), [source]);
12032
+ React22.useEffect(() => setImageFailed(false), [source]);
11786
12033
  return h2(
11787
12034
  "div",
11788
12035
  { className: "dxw-card dim-surfaceCard" },
@@ -11849,9 +12096,9 @@ function QrPanel4({ provision, now, busy, onRefresh, onCancel }) {
11849
12096
  );
11850
12097
  }
11851
12098
  function VerificationPanel({ provision, busy, onSubmit, onCancel }) {
11852
- const [code, setCode] = React21.useState("");
12099
+ const [code, setCode] = React22.useState("");
11853
12100
  const valid = /^\d{4,8}$/.test(code);
11854
- React21.useEffect(() => setCode(""), [provision.attemptId]);
12101
+ React22.useEffect(() => setCode(""), [provision.attemptId]);
11855
12102
  return h2(
11856
12103
  "div",
11857
12104
  { className: "dxw-card dim-surfaceCard" },
@@ -11949,6 +12196,7 @@ function AccountCard5({
11949
12196
  removing,
11950
12197
  onReconnect,
11951
12198
  onWorkspaceSave,
12199
+ onAliasSave,
11952
12200
  onModelSave,
11953
12201
  onAgentPresetSave,
11954
12202
  onContextEnhancementSave,
@@ -11976,7 +12224,7 @@ function AccountCard5({
11976
12224
  "div",
11977
12225
  { className: "dxw-accountIdentity dim-botIdentity" },
11978
12226
  h2("div", { className: "dxw-avatar dim-botAvatar", "aria-hidden": "true" }, h2(WeixinLogoGlyph, { size: 27 })),
11979
- 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))
11980
12228
  ),
11981
12229
  h2(
11982
12230
  "div",
@@ -12096,6 +12344,7 @@ function AccountList2(props) {
12096
12344
  removing: props.removeTarget === account.botId,
12097
12345
  onReconnect: () => props.onReconnect(account),
12098
12346
  onWorkspaceSave: (workspace) => props.onWorkspaceSave(account, workspace),
12347
+ onAliasSave: (alias) => props.onAliasSave(account, alias),
12099
12348
  onModelSave: (model) => props.onModelSave(account, model),
12100
12349
  onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(account, agentPreset),
12101
12350
  onContextEnhancementSave: (config) => props.onContextEnhancementSave(account, config),
@@ -12117,7 +12366,7 @@ function mergeWeixinProvisioningSnapshot(current, incoming, { restoreProvisionin
12117
12366
  };
12118
12367
  }
12119
12368
  function WeixinSettingsTab({ rpcCall }) {
12120
- const [model, setModel] = React21.useState({
12369
+ const [model, setModel] = React22.useState({
12121
12370
  phase: "loading",
12122
12371
  bots: [],
12123
12372
  totals: EMPTY_TOTALS3,
@@ -12126,33 +12375,33 @@ function WeixinSettingsTab({ rpcCall }) {
12126
12375
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
12127
12376
  modelCatalog: EMPTY_MODEL_CATALOG
12128
12377
  });
12129
- const [provision, setProvision] = React21.useState(null);
12130
- const [busy, setBusy] = React21.useState(false);
12131
- const [busyByBot, setBusyByBot] = React21.useState({});
12132
- const [feedbackByBot, setFeedbackByBot] = React21.useState({});
12133
- const [removeTarget, setRemoveTarget] = React21.useState(null);
12134
- const [notice, setNotice] = React21.useState("");
12135
- const [now, setNow] = React21.useState(() => Date.now());
12136
- const addButtonRef = React21.useRef(null);
12137
- 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);
12138
12387
  const workspaceFence = useWorkspaceSnapshotFence();
12139
12388
  const scheduleAnimationFrame = useAnimationFrameScheduler();
12140
- React21.useEffect(() => {
12389
+ React22.useEffect(() => {
12141
12390
  mountedRef.current = true;
12142
12391
  return () => {
12143
12392
  mountedRef.current = false;
12144
12393
  };
12145
12394
  }, []);
12146
- const announce = React21.useCallback((value) => {
12395
+ const announce = React22.useCallback((value) => {
12147
12396
  setNotice("");
12148
12397
  scheduleAnimationFrame(() => {
12149
12398
  if (value) setNotice(value);
12150
12399
  }, "announcement");
12151
12400
  }, [scheduleAnimationFrame]);
12152
- const invoke = React21.useCallback(async (endpoint, payload = {}, signal) => {
12401
+ const invoke = React22.useCallback(async (endpoint, payload = {}, signal) => {
12153
12402
  return unwrapRpcResult9(await rpcCall(endpoint, payload, signal));
12154
12403
  }, [rpcCall]);
12155
- const loadStatus = React21.useCallback(async ({
12404
+ const loadStatus = React22.useCallback(async ({
12156
12405
  signal,
12157
12406
  silent = false,
12158
12407
  restoreProvisioning = false
@@ -12190,12 +12439,12 @@ function WeixinSettingsTab({ rpcCall }) {
12190
12439
  return void 0;
12191
12440
  }
12192
12441
  }, [invoke, workspaceFence]);
12193
- React21.useEffect(() => {
12442
+ React22.useEffect(() => {
12194
12443
  const controller = new AbortController();
12195
12444
  void loadStatus({ signal: controller.signal, restoreProvisioning: true });
12196
12445
  return () => controller.abort();
12197
12446
  }, [loadStatus]);
12198
- React21.useEffect(() => {
12447
+ React22.useEffect(() => {
12199
12448
  if (model.phase !== "ready") return void 0;
12200
12449
  const controller = new AbortController();
12201
12450
  let running = false;
@@ -12214,12 +12463,12 @@ function WeixinSettingsTab({ rpcCall }) {
12214
12463
  window.clearInterval(timer);
12215
12464
  };
12216
12465
  }, [loadStatus, model.phase]);
12217
- React21.useEffect(() => {
12466
+ React22.useEffect(() => {
12218
12467
  if (!provision || !["pending", "scanned"].includes(provision.status)) return void 0;
12219
12468
  const timer = window.setInterval(() => setNow(Date.now()), 1e3);
12220
12469
  return () => window.clearInterval(timer);
12221
12470
  }, [provision?.attemptId, provision?.status]);
12222
- const startProvisioning = React21.useCallback(async ({ replace = false } = {}) => {
12471
+ const startProvisioning = React22.useCallback(async ({ replace = false } = {}) => {
12223
12472
  setBusy(true);
12224
12473
  try {
12225
12474
  if (replace && provision?.attemptId) {
@@ -12240,7 +12489,7 @@ function WeixinSettingsTab({ rpcCall }) {
12240
12489
  setBusy(false);
12241
12490
  }
12242
12491
  }, [announce, invoke, provision?.attemptId]);
12243
- const cancelProvisioning = React21.useCallback(async () => {
12492
+ const cancelProvisioning = React22.useCallback(async () => {
12244
12493
  setBusy(true);
12245
12494
  try {
12246
12495
  if (provision?.attemptId && !["failed", "expired", "cancelled"].includes(provision.status)) {
@@ -12255,7 +12504,7 @@ function WeixinSettingsTab({ rpcCall }) {
12255
12504
  setBusy(false);
12256
12505
  }
12257
12506
  }, [announce, invoke, provision?.attemptId, provision?.status, scheduleAnimationFrame]);
12258
- const submitVerification = React21.useCallback(async (verifyCode) => {
12507
+ const submitVerification = React22.useCallback(async (verifyCode) => {
12259
12508
  if (!provision?.attemptId) return;
12260
12509
  setBusy(true);
12261
12510
  try {
@@ -12271,7 +12520,7 @@ function WeixinSettingsTab({ rpcCall }) {
12271
12520
  setBusy(false);
12272
12521
  }
12273
12522
  }, [announce, invoke, provision?.attemptId]);
12274
- React21.useEffect(() => {
12523
+ React22.useEffect(() => {
12275
12524
  const attemptId = provision?.attemptId;
12276
12525
  if (!attemptId || !["pending", "scanned", "connecting"].includes(provision.status)) return void 0;
12277
12526
  const controller = new AbortController();
@@ -12319,7 +12568,7 @@ function WeixinSettingsTab({ rpcCall }) {
12319
12568
  controller.abort();
12320
12569
  };
12321
12570
  }, [announce, invoke, loadStatus, provision?.attemptId, provision?.status, provision?.pollIntervalMs]);
12322
- const setBotBusy = React21.useCallback((botId, value) => {
12571
+ const setBotBusy = React22.useCallback((botId, value) => {
12323
12572
  setBusyByBot((current) => {
12324
12573
  const next = { ...current };
12325
12574
  if (value) next[botId] = value;
@@ -12327,7 +12576,7 @@ function WeixinSettingsTab({ rpcCall }) {
12327
12576
  return next;
12328
12577
  });
12329
12578
  }, []);
12330
- const reconnect = React21.useCallback(async (account) => {
12579
+ const reconnect = React22.useCallback(async (account) => {
12331
12580
  const snapshotVersion = workspaceFence.beginMutation();
12332
12581
  setBotBusy(account.botId, "reconnect");
12333
12582
  setFeedbackByBot((current) => {
@@ -12379,7 +12628,7 @@ function WeixinSettingsTab({ rpcCall }) {
12379
12628
  setBotBusy(account.botId, null);
12380
12629
  }
12381
12630
  }, [announce, invoke, loadStatus, setBotBusy, workspaceFence]);
12382
- const saveWorkspace = React21.useCallback(async (account, workspace) => {
12631
+ const saveWorkspace = React22.useCallback(async (account, workspace) => {
12383
12632
  const workspaceVersion = workspaceFence.beginMutation();
12384
12633
  setBotBusy(account.botId, "workspace");
12385
12634
  try {
@@ -12404,7 +12653,7 @@ function WeixinSettingsTab({ rpcCall }) {
12404
12653
  if (mountedRef.current) setBotBusy(account.botId, null);
12405
12654
  }
12406
12655
  }, [invoke, loadStatus, setBotBusy, workspaceFence]);
12407
- const saveBotSetting = React21.useCallback(async (account, operation, endpoint, payload) => {
12656
+ const saveBotSetting = React22.useCallback(async (account, operation, endpoint, payload) => {
12408
12657
  const snapshotVersion = workspaceFence.beginMutation();
12409
12658
  setBotBusy(account.botId, operation);
12410
12659
  try {
@@ -12429,7 +12678,7 @@ function WeixinSettingsTab({ rpcCall }) {
12429
12678
  if (mountedRef.current) setBotBusy(account.botId, null);
12430
12679
  }
12431
12680
  }, [invoke, loadStatus, setBotBusy, workspaceFence]);
12432
- const remove = React21.useCallback(async (account) => {
12681
+ const remove = React22.useCallback(async (account) => {
12433
12682
  const snapshotVersion = workspaceFence.beginMutation();
12434
12683
  setBotBusy(account.botId, "delete");
12435
12684
  try {
@@ -12516,7 +12765,7 @@ function WeixinSettingsTab({ rpcCall }) {
12516
12765
  h2(Button14, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
12517
12766
  )
12518
12767
  ) : h2(
12519
- React21.Fragment,
12768
+ React22.Fragment,
12520
12769
  null,
12521
12770
  provisionView,
12522
12771
  model.bots.length === 0 && !provision ? h2(EmptyView6, { onStart: () => void startProvisioning(), busy }) : null,
@@ -12527,6 +12776,12 @@ function WeixinSettingsTab({ rpcCall }) {
12527
12776
  removeTarget,
12528
12777
  onReconnect: (account) => void reconnect(account),
12529
12778
  onWorkspaceSave: saveWorkspace,
12779
+ onAliasSave: (account, alias) => saveBotSetting(
12780
+ account,
12781
+ "alias",
12782
+ WEIXIN_ENDPOINTS.setAlias,
12783
+ { alias }
12784
+ ),
12530
12785
  onModelSave: (account, selectedModel) => saveBotSetting(
12531
12786
  account,
12532
12787
  "model",
@@ -12680,6 +12935,7 @@ var WHATSAPP_ENDPOINTS = Object.freeze({
12680
12935
  reconnectBot: "bot.reconnect",
12681
12936
  deleteBot: "bot.delete",
12682
12937
  setAccessPolicy: "bot.access-policy.set",
12938
+ setAlias: "bot.alias.set",
12683
12939
  setWorkspace: "bot.workspace.set",
12684
12940
  setModel: SET_MODEL_ENDPOINT,
12685
12941
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
@@ -12753,6 +13009,7 @@ function normalizeBot7(value) {
12753
13009
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
12754
13010
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
12755
13011
  bot: {
13012
+ ...normalizeBotAlias(value.bot),
12756
13013
  name: text6(value.bot?.name, "WhatsApp\u673A\u5668\u4EBA", 100),
12757
13014
  idMasked: text6(value.bot?.idMasked, "WhatsApp\u8D26\u53F7", 140)
12758
13015
  },
@@ -12794,7 +13051,7 @@ function formatRemaining6(milliseconds) {
12794
13051
  }
12795
13052
 
12796
13053
  // plugin-src/client/channels/whatsapp/index.js
12797
- var React22 = __toESM(require("react"), 1);
13054
+ var React23 = __toESM(require("react"), 1);
12798
13055
 
12799
13056
  // plugin-src/client/channels/whatsapp/styles.js
12800
13057
  var WHATSAPP_STYLE_ID = "xmanrui-dsh-im-whatsapp-settings";
@@ -12819,7 +13076,7 @@ function installWhatsappStyles() {
12819
13076
 
12820
13077
  // plugin-src/client/channels/whatsapp/index.js
12821
13078
  var ACTIVE_STATES3 = /* @__PURE__ */ new Set(["pending", "connecting"]);
12822
- 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) {
12823
13080
  return h2("button", {
12824
13081
  ...props,
12825
13082
  ref,
@@ -13041,6 +13298,7 @@ function WhatsappAccountCard({
13041
13298
  removing,
13042
13299
  onReconnect,
13043
13300
  onWorkspaceSave,
13301
+ onAliasSave,
13044
13302
  onModelSave,
13045
13303
  onAgentPresetSave,
13046
13304
  onContextEnhancementSave,
@@ -13075,7 +13333,7 @@ function WhatsappAccountCard({
13075
13333
  h2(
13076
13334
  "div",
13077
13335
  { className: "dim-botName" },
13078
- h2("h3", null, account.bot.name),
13336
+ h2(BotName, { bot: account.bot, disabled: Boolean(busy), onSave: onAliasSave }),
13079
13337
  h2("p", null, account.bot.idMasked)
13080
13338
  )
13081
13339
  ),
@@ -13172,7 +13430,7 @@ function WhatsappAccountCard({
13172
13430
  );
13173
13431
  }
13174
13432
  function WhatsappSettingsTab({ rpcCall }) {
13175
- const [model, setModel] = React22.useState({
13433
+ const [model, setModel] = React23.useState({
13176
13434
  phase: "loading",
13177
13435
  bots: [],
13178
13436
  totals: { configured: 0, connected: 0 },
@@ -13180,16 +13438,16 @@ function WhatsappSettingsTab({ rpcCall }) {
13180
13438
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
13181
13439
  modelCatalog: EMPTY_MODEL_CATALOG
13182
13440
  });
13183
- const [provision, setProvision] = React22.useState(null);
13184
- const [busy, setBusy] = React22.useState(false);
13185
- const [busyByBot, setBusyByBot] = React22.useState({});
13186
- const [testNoticeByBot, setTestNoticeByBot] = React22.useState({});
13187
- const [removeTarget, setRemoveTarget] = React22.useState(null);
13188
- const [now, setNow] = React22.useState(Date.now());
13189
- 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);
13190
13448
  const workspaceFence = useWorkspaceSnapshotFence();
13191
- const addButtonRef = React22.useRef(null);
13192
- React22.useEffect(() => {
13449
+ const addButtonRef = React23.useRef(null);
13450
+ React23.useEffect(() => {
13193
13451
  const disposeDingtalk = installDingtalkStyles();
13194
13452
  const disposeWhatsapp = installWhatsappStyles();
13195
13453
  mounted.current = true;
@@ -13199,11 +13457,11 @@ function WhatsappSettingsTab({ rpcCall }) {
13199
13457
  disposeDingtalk();
13200
13458
  };
13201
13459
  }, []);
13202
- const invoke = React22.useCallback(async (endpoint, payload = {}, signal) => {
13460
+ const invoke = React23.useCallback(async (endpoint, payload = {}, signal) => {
13203
13461
  if (typeof rpcCall !== "function") throw new TypeError("WhatsApp \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
13204
13462
  return unwrapRpcResult10(await rpcCall(endpoint, payload, signal));
13205
13463
  }, [rpcCall]);
13206
- const loadStatus = React22.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
13464
+ const loadStatus = React23.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
13207
13465
  const workspaceVersion = workspaceFence.beginStatus();
13208
13466
  if (workspaceVersion === null) return void 0;
13209
13467
  if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
@@ -13234,12 +13492,12 @@ function WhatsappSettingsTab({ rpcCall }) {
13234
13492
  return void 0;
13235
13493
  }
13236
13494
  }, [invoke, workspaceFence]);
13237
- React22.useEffect(() => {
13495
+ React23.useEffect(() => {
13238
13496
  const controller = new AbortController();
13239
13497
  void loadStatus({ signal: controller.signal, restore: true });
13240
13498
  return () => controller.abort();
13241
13499
  }, [loadStatus]);
13242
- React22.useEffect(() => {
13500
+ React23.useEffect(() => {
13243
13501
  if (model.phase !== "ready") return void 0;
13244
13502
  const controller = new AbortController();
13245
13503
  const timer = window.setInterval(
@@ -13251,12 +13509,12 @@ function WhatsappSettingsTab({ rpcCall }) {
13251
13509
  window.clearInterval(timer);
13252
13510
  };
13253
13511
  }, [loadStatus, model.phase]);
13254
- React22.useEffect(() => {
13512
+ React23.useEffect(() => {
13255
13513
  if (!provision || !ACTIVE_STATES3.has(provision.status)) return void 0;
13256
13514
  const timer = window.setInterval(() => mounted.current && setNow(Date.now()), 1e3);
13257
13515
  return () => window.clearInterval(timer);
13258
13516
  }, [provision?.attemptId, provision?.status]);
13259
- const startProvisioning = React22.useCallback(async (replace = false) => {
13517
+ const startProvisioning = React23.useCallback(async (replace = false) => {
13260
13518
  setBusy(true);
13261
13519
  try {
13262
13520
  if (replace && provision?.attemptId) {
@@ -13274,7 +13532,7 @@ function WhatsappSettingsTab({ rpcCall }) {
13274
13532
  if (mounted.current) setBusy(false);
13275
13533
  }
13276
13534
  }, [invoke, provision?.attemptId]);
13277
- const closeProvision = React22.useCallback(async () => {
13535
+ const closeProvision = React23.useCallback(async () => {
13278
13536
  setBusy(true);
13279
13537
  try {
13280
13538
  if (provision?.attemptId && ACTIVE_STATES3.has(provision.status)) {
@@ -13285,7 +13543,7 @@ function WhatsappSettingsTab({ rpcCall }) {
13285
13543
  if (mounted.current) setBusy(false);
13286
13544
  }
13287
13545
  }, [invoke, provision?.attemptId, provision?.status]);
13288
- React22.useEffect(() => {
13546
+ React23.useEffect(() => {
13289
13547
  const attemptId = provision?.attemptId;
13290
13548
  if (!attemptId || !ACTIVE_STATES3.has(provision.status)) return void 0;
13291
13549
  const controller = new AbortController();
@@ -13326,7 +13584,7 @@ function WhatsappSettingsTab({ rpcCall }) {
13326
13584
  if (timer) window.clearTimeout(timer);
13327
13585
  };
13328
13586
  }, [invoke, loadStatus, provision?.attemptId, provision?.status]);
13329
- const botAction = React22.useCallback(async (account, operation, endpoint, payload) => {
13587
+ const botAction = React23.useCallback(async (account, operation, endpoint, payload) => {
13330
13588
  const snapshotVersion = workspaceFence.beginMutation();
13331
13589
  setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
13332
13590
  if (operation === "reconnect") {
@@ -13398,6 +13656,12 @@ function WhatsappSettingsTab({ rpcCall }) {
13398
13656
  WHATSAPP_ENDPOINTS.setWorkspace,
13399
13657
  { botId: account.botId, workspace }
13400
13658
  ),
13659
+ onAliasSave: (alias) => botAction(
13660
+ account,
13661
+ "alias",
13662
+ WHATSAPP_ENDPOINTS.setAlias,
13663
+ { botId: account.botId, alias }
13664
+ ),
13401
13665
  onModelSave: (selectedModel) => botAction(
13402
13666
  account,
13403
13667
  "model",
@@ -13454,7 +13718,7 @@ function WhatsappSettingsTab({ rpcCall }) {
13454
13718
  h2(Button16, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
13455
13719
  )
13456
13720
  ) : h2(
13457
- React22.Fragment,
13721
+ React23.Fragment,
13458
13722
  null,
13459
13723
  provision?.status === "pending" ? h2(QrPanel5, {
13460
13724
  provision,
@@ -13485,7 +13749,7 @@ var normalizeSnapshot10 = api4.normalizeSnapshot;
13485
13749
  var presentError11 = api4.presentError;
13486
13750
 
13487
13751
  // plugin-src/client/channels/imessage/index.js
13488
- var React23 = __toESM(require("react"), 1);
13752
+ var React24 = __toESM(require("react"), 1);
13489
13753
 
13490
13754
  // plugin-src/client/channels/imessage/styles.js
13491
13755
  var IMESSAGE_STYLE_ID = "xmanrui-dsh-im-imessage-settings";
@@ -13578,10 +13842,10 @@ var IMessageSettingsTab = channel4.SettingsTab;
13578
13842
  var IMessageAccountCard = channel4.AccountCard;
13579
13843
 
13580
13844
  // plugin-src/client/delivery-settings.js
13581
- var React26 = __toESM(require("react"), 1);
13845
+ var React27 = __toESM(require("react"), 1);
13582
13846
 
13583
13847
  // plugin-src/client/access-policy-settings.js
13584
- var React24 = __toESM(require("react"), 1);
13848
+ var React25 = __toESM(require("react"), 1);
13585
13849
  var ACCESS_POLICY_ENDPOINT = "bot.access-policy.set";
13586
13850
  var ACCESS_CHANNEL_DEFINITIONS = Object.freeze({
13587
13851
  weixin: Object.freeze({
@@ -13694,8 +13958,8 @@ function ScenePolicyEditor({
13694
13958
  unsupported = false,
13695
13959
  onChange
13696
13960
  }) {
13697
- const ownerHelpId = React24.useId();
13698
- const emptyAllowlistHelpId = React24.useId();
13961
+ const ownerHelpId = React25.useId();
13962
+ const emptyAllowlistHelpId = React25.useId();
13699
13963
  const allowlist = policy.mode === "allowlist";
13700
13964
  const collectionKey = allowlist ? "users" : "commandPermissionOverrides";
13701
13965
  const branchKey = allowlist ? "allowlist" : "open";
@@ -13747,7 +14011,7 @@ function ScenePolicyEditor({
13747
14011
  h2("strong", null, "\u5F53\u524D\u6E20\u9053\u4E0D\u652F\u6301\u7FA4\u804A"),
13748
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")
13749
14013
  ) : h2(
13750
- React24.Fragment,
14014
+ React25.Fragment,
13751
14015
  null,
13752
14016
  h2(
13753
14017
  "div",
@@ -13888,16 +14152,16 @@ function AccessPolicySettingsPage({ channel: channel5, account, rpcCall, onSaved
13888
14152
  const definition = ACCESS_CHANNEL_DEFINITIONS[channel5];
13889
14153
  const initialPolicy = normalizeAccessPolicy(account?.accessPolicy);
13890
14154
  const initialKey = JSON.stringify(initialPolicy);
13891
- const [draft, setDraft] = React24.useState(() => clonePolicy(
14155
+ const [draft, setDraft] = React25.useState(() => clonePolicy(
13892
14156
  initialPolicy ?? DEFAULT_ACCESS_POLICY
13893
14157
  ));
13894
- const [saving, setSaving] = React24.useState(false);
13895
- const [feedback, setFeedback] = React24.useState(null);
13896
- React24.useEffect(() => {
14158
+ const [saving, setSaving] = React25.useState(false);
14159
+ const [feedback, setFeedback] = React25.useState(null);
14160
+ React25.useEffect(() => {
13897
14161
  const next = normalizeAccessPolicy(account?.accessPolicy);
13898
14162
  setDraft(clonePolicy(next ?? DEFAULT_ACCESS_POLICY));
13899
14163
  }, [account?.botId, initialKey]);
13900
- React24.useEffect(() => {
14164
+ React25.useEffect(() => {
13901
14165
  setFeedback(null);
13902
14166
  }, [account?.botId]);
13903
14167
  if (!definition) {
@@ -13988,7 +14252,7 @@ function AccessPolicySettingsPage({ channel: channel5, account, rpcCall, onSaved
13988
14252
  }
13989
14253
 
13990
14254
  // plugin-src/client/channels/feishu/group-settings.js
13991
- var React25 = __toESM(require("react"), 1);
14255
+ var React26 = __toESM(require("react"), 1);
13992
14256
  var GROUP_MESSAGE_PERMISSION_OPERATION2 = FEISHU_REGISTRATION_OPERATIONS.GROUP_MESSAGE_PERMISSION;
13993
14257
  function SettingsButton({ children, kind = "secondary", className = "", ...props }) {
13994
14258
  return h2("button", {
@@ -14049,9 +14313,9 @@ function GroupResponseModeEditor({
14049
14313
  onAuthorize
14050
14314
  }) {
14051
14315
  const current = normalizeGroupResponseMode(value);
14052
- const [saving, setSaving] = React25.useState(false);
14053
- const [authorizing, setAuthorizing] = React25.useState(false);
14054
- 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);
14055
14319
  const change = async (event) => {
14056
14320
  const next = normalizeGroupResponseMode(event.target.value);
14057
14321
  if (next === current || saving || disabled) return;
@@ -14132,8 +14396,8 @@ function GroupResponseModeEditor({
14132
14396
  }
14133
14397
  function GroupTopicReplyEditor({ value = false, disabled = false, onSave }) {
14134
14398
  const current = value === true ? "on" : "off";
14135
- const [saving, setSaving] = React25.useState(false);
14136
- const [error, setError] = React25.useState(null);
14399
+ const [saving, setSaving] = React26.useState(false);
14400
+ const [error, setError] = React26.useState(null);
14137
14401
  const change = async (event) => {
14138
14402
  const next = event.target.value === "on";
14139
14403
  if ((next ? "on" : "off") === current || saving || disabled) return;
@@ -14320,14 +14584,14 @@ function PermissionFlow({ provision, now, busy, botName, onRetry, onCancel, onCl
14320
14584
  );
14321
14585
  }
14322
14586
  function FeishuGroupSettingsPage({ account, rpcCall }) {
14323
- const [settings, setSettings] = React25.useState(() => groupSettingsFrom(account));
14324
- const [refreshing, setRefreshing] = React25.useState(false);
14325
- const [refreshError, setRefreshError] = React25.useState(null);
14326
- const [provision, setProvision] = React25.useState(null);
14327
- const [provisionBusy, setProvisionBusy] = React25.useState(false);
14328
- const [now, setNow] = React25.useState(() => Date.now());
14329
- const mounted = React25.useRef(true);
14330
- 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(() => {
14331
14595
  setSettings(groupSettingsFrom(account));
14332
14596
  }, [
14333
14597
  account.botId,
@@ -14335,22 +14599,22 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14335
14599
  account.groupTopicReply,
14336
14600
  account.groupMessagePermissionGranted
14337
14601
  ]);
14338
- React25.useEffect(() => {
14602
+ React26.useEffect(() => {
14339
14603
  mounted.current = true;
14340
14604
  return () => {
14341
14605
  mounted.current = false;
14342
14606
  };
14343
14607
  }, []);
14344
- const invoke = React25.useCallback(async (endpoint, payload = {}, signal) => {
14608
+ const invoke = React26.useCallback(async (endpoint, payload = {}, signal) => {
14345
14609
  if (typeof rpcCall !== "function") throw new Error("\u98DE\u4E66\u7FA4\u804A\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
14346
14610
  return unwrapRpcResult3(await rpcCall(endpoint, payload, signal));
14347
14611
  }, [rpcCall]);
14348
- const applySnapshot = React25.useCallback((value) => {
14612
+ const applySnapshot = React26.useCallback((value) => {
14349
14613
  const result = targetBotFromSnapshot(value, account.botId);
14350
14614
  if (mounted.current) setSettings(groupSettingsFrom(result.bot));
14351
14615
  return result;
14352
14616
  }, [account.botId]);
14353
- const loadSettings = React25.useCallback(async ({ signal, restoreProvisioning = false } = {}) => {
14617
+ const loadSettings = React26.useCallback(async ({ signal, restoreProvisioning = false } = {}) => {
14354
14618
  setRefreshing(true);
14355
14619
  setRefreshError(null);
14356
14620
  try {
@@ -14379,16 +14643,16 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14379
14643
  if (!signal?.aborted && mounted.current) setRefreshing(false);
14380
14644
  }
14381
14645
  }, [account.botId, applySnapshot, invoke]);
14382
- React25.useEffect(() => {
14646
+ React26.useEffect(() => {
14383
14647
  const controller = new AbortController();
14384
14648
  void loadSettings({ signal: controller.signal, restoreProvisioning: true });
14385
14649
  return () => controller.abort();
14386
14650
  }, [loadSettings]);
14387
- const saveSetting = React25.useCallback(async (endpoint, payload) => {
14651
+ const saveSetting = React26.useCallback(async (endpoint, payload) => {
14388
14652
  const value = await invoke(endpoint, { botId: account.botId, ...payload });
14389
14653
  applySnapshot(value);
14390
14654
  }, [account.botId, applySnapshot, invoke]);
14391
- const startAuthorization = React25.useCallback(async ({ replace = false } = {}) => {
14655
+ const startAuthorization = React26.useCallback(async ({ replace = false } = {}) => {
14392
14656
  if (provisionBusy) return;
14393
14657
  const previousAttemptId = provision?.attemptId;
14394
14658
  setProvisionBusy(true);
@@ -14429,13 +14693,13 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14429
14693
  if (mounted.current) setProvisionBusy(false);
14430
14694
  }
14431
14695
  }, [account.botId, invoke, provision?.attemptId, provisionBusy]);
14432
- const finishAuthorization = React25.useCallback(async (signal) => {
14696
+ const finishAuthorization = React26.useCallback(async (signal) => {
14433
14697
  const bot = await loadSettings({ signal, restoreProvisioning: false });
14434
14698
  if (signal?.aborted || !mounted.current) return;
14435
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");
14436
14700
  setProvision(null);
14437
14701
  }, [loadSettings]);
14438
- React25.useEffect(() => {
14702
+ React26.useEffect(() => {
14439
14703
  if (!provision?.attemptId || !["qr", "connecting"].includes(provision.phase) || provision.expired) return void 0;
14440
14704
  const timerHost = globalThis.window ?? globalThis;
14441
14705
  const controller = new AbortController();
@@ -14479,7 +14743,7 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14479
14743
  timerHost.clearTimeout(timer);
14480
14744
  };
14481
14745
  }, [account.botId, finishAuthorization, invoke, provision]);
14482
- React25.useEffect(() => {
14746
+ React26.useEffect(() => {
14483
14747
  if (!provision?.attemptId || provision.phase !== "qr" || provision.expired) return void 0;
14484
14748
  const timerHost = globalThis.window ?? globalThis;
14485
14749
  const tick = () => {
@@ -14493,7 +14757,7 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14493
14757
  const timer = timerHost.setInterval(tick, 1e3);
14494
14758
  return () => timerHost.clearInterval(timer);
14495
14759
  }, [provision?.attemptId, provision?.expired, provision?.expiresAt, provision?.phase]);
14496
- const cancelAuthorization = React25.useCallback(async () => {
14760
+ const cancelAuthorization = React26.useCallback(async () => {
14497
14761
  if (!provision?.attemptId || provisionBusy) {
14498
14762
  setProvision(null);
14499
14763
  return;
@@ -14814,13 +15078,13 @@ function TargetForm({
14814
15078
  }) {
14815
15079
  const editing = mode === "edit";
14816
15080
  const initialKind = initialValue?.kind && definition.fields[initialValue.kind] ? initialValue.kind : definition.kinds[0].value;
14817
- const [targetId, setTargetId] = React26.useState(initialValue?.targetId ?? "");
14818
- const [name2, setName] = React26.useState(initialValue?.name ?? "");
14819
- const [kind, setKind] = React26.useState(initialKind);
14820
- const [route, setRoute] = React26.useState(initialValue?.route ?? {});
14821
- const [error, setError] = React26.useState(null);
14822
- const [testing, setTesting] = React26.useState(false);
14823
- 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);
14824
15088
  const currentTarget = () => {
14825
15089
  const normalizedRoute = Object.fromEntries(fieldsFor(definition, kind).map((field) => {
14826
15090
  const raw = String(route[field.key] ?? "").trim();
@@ -15037,7 +15301,7 @@ function TargetSuggestionPicker({
15037
15301
  suggestions.map((suggestion, index) => {
15038
15302
  const identity = routeIdentity(definition, suggestion);
15039
15303
  const added = configured.has(identity);
15040
- return React26.createElement("option", {
15304
+ return React27.createElement("option", {
15041
15305
  key: suggestion.id ?? suggestion.suggestionId ?? `${identity}:${index}`,
15042
15306
  value: String(index),
15043
15307
  disabled: added
@@ -15054,11 +15318,11 @@ function TargetSuggestionPicker({
15054
15318
  );
15055
15319
  }
15056
15320
  function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, onEdit }) {
15057
- const [action, setAction] = React26.useState(null);
15058
- const [testState, setTestState] = React26.useState(null);
15059
- const [syncFeedback, setSyncFeedback] = React26.useState(null);
15060
- const [copyState, setCopyState] = React26.useState(null);
15061
- 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);
15062
15326
  const sessionSync = target.sessionSync ?? { enabled: false, state: "unavailable" };
15063
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";
15064
15328
  const testTarget = async () => {
@@ -15121,7 +15385,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
15121
15385
  h2(
15122
15386
  "div",
15123
15387
  { className: "dim-targetTitle" },
15124
- React26.createElement("strong", null, target.name || target.targetId),
15388
+ React27.createElement("strong", null, target.name || target.targetId),
15125
15389
  h2("span", null, kindLabel(definition, target.kind))
15126
15390
  ),
15127
15391
  h2("code", null, `targetId: ${target.targetId}`)
@@ -15207,26 +15471,26 @@ function DeliveryTargetSettingsPage({
15207
15471
  onBack
15208
15472
  }) {
15209
15473
  const definition = CHANNEL_DEFINITIONS[channel5];
15210
- const [activeTabId, setActiveTabId] = React26.useState(BOT_SETTINGS_TABS[0].id);
15211
- const [phase, setPhase] = React26.useState("loading");
15212
- const [targets, setTargets] = React26.useState([]);
15213
- const [suggestionPhase, setSuggestionPhase] = React26.useState("idle");
15214
- const [suggestions, setSuggestions] = React26.useState([]);
15215
- const [suggestionError, setSuggestionError] = React26.useState(null);
15216
- const [error, setError] = React26.useState(null);
15217
- const [editor, setEditor] = React26.useState(null);
15218
- const [saving, setSaving] = React26.useState(false);
15219
- const [botCopyState, setBotCopyState] = React26.useState(null);
15220
- const [accessPolicy, setAccessPolicy] = React26.useState(account.accessPolicy);
15221
- const mounted = React26.useRef(true);
15222
- 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(() => {
15223
15487
  setAccessPolicy(account.accessPolicy);
15224
15488
  }, [account.botId, account.accessPolicy]);
15225
- const invoke = React26.useCallback(async (endpoint, payload = {}, signal) => {
15489
+ const invoke = React27.useCallback(async (endpoint, payload = {}, signal) => {
15226
15490
  if (typeof rpcCall !== "function") throw new Error("\u6295\u9012\u76EE\u6807\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
15227
15491
  return unwrapRpcResult13(await rpcCall(endpoint, payload, signal));
15228
15492
  }, [rpcCall]);
15229
- const loadTargets = React26.useCallback(async ({ signal, silent = false } = {}) => {
15493
+ const loadTargets = React27.useCallback(async ({ signal, silent = false } = {}) => {
15230
15494
  if (!silent) setPhase("loading");
15231
15495
  setError(null);
15232
15496
  try {
@@ -15240,7 +15504,7 @@ function DeliveryTargetSettingsPage({
15240
15504
  setPhase("error");
15241
15505
  }
15242
15506
  }, [account.botId, invoke]);
15243
- const loadSuggestions = React26.useCallback(async () => {
15507
+ const loadSuggestions = React27.useCallback(async () => {
15244
15508
  setSuggestionPhase("loading");
15245
15509
  setSuggestionError(null);
15246
15510
  try {
@@ -15254,7 +15518,7 @@ function DeliveryTargetSettingsPage({
15254
15518
  setSuggestionPhase("error");
15255
15519
  }
15256
15520
  }, [account.botId, definition, invoke]);
15257
- React26.useEffect(() => {
15521
+ React27.useEffect(() => {
15258
15522
  mounted.current = true;
15259
15523
  const controller = new AbortController();
15260
15524
  void loadTargets({ signal: controller.signal });
@@ -15376,7 +15640,7 @@ function DeliveryTargetSettingsPage({
15376
15640
  account,
15377
15641
  rpcCall: accessRpcCall
15378
15642
  }) : h2(
15379
- React26.Fragment,
15643
+ React27.Fragment,
15380
15644
  null,
15381
15645
  h2(
15382
15646
  "section",
@@ -15487,7 +15751,7 @@ function DeliveryTargetSettingsPage({
15487
15751
  }
15488
15752
 
15489
15753
  // plugin-src/client/global-settings.js
15490
- var React27 = __toESM(require("react"), 1);
15754
+ var React28 = __toESM(require("react"), 1);
15491
15755
 
15492
15756
  // src/channels/shared/inbound-ttl.mjs
15493
15757
  var DEFAULT_INBOUND_TTL_HOURS = 168;
@@ -15549,29 +15813,29 @@ function GlobalButton({ children, kind = "secondary", className = "", ...props }
15549
15813
  }, children);
15550
15814
  }
15551
15815
  function GlobalSettingsPanel({ rpcCall }) {
15552
- const [phase, setPhase] = React27.useState("loading");
15553
- const [loadError, setLoadError] = React27.useState(null);
15554
- const [ttlInput, setTtlInput] = React27.useState("");
15555
- const [savedTtl, setSavedTtl] = React27.useState(null);
15556
- const [ttlError, setTtlError] = React27.useState(false);
15557
- const [saveError, setSaveError] = React27.useState(null);
15558
- const [saveSucceeded, setSaveSucceeded] = React27.useState(false);
15559
- const [isSaving, setIsSaving] = React27.useState(false);
15560
- const [sweepConfirming, setSweepConfirming] = React27.useState(false);
15561
- const [sweeping, setSweeping] = React27.useState(false);
15562
- const ttlErrorId = React27.useId();
15563
- const ttlHintsId = React27.useId();
15564
- const sweepTriggerId = React27.useId();
15565
- const sweepConfirmId = React27.useId();
15566
- const sweepConfirmTextId = React27.useId();
15567
- const sweepConfirmButtonId = React27.useId();
15568
- const mounted = React27.useRef(true);
15569
- const saving = React27.useRef(false);
15570
- 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) => {
15571
15835
  if (typeof rpcCall !== "function") throw new Error("\u901A\u7528\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
15572
15836
  return unwrapRpcResult14(await rpcCall(endpoint, payload, signal));
15573
15837
  }, [rpcCall]);
15574
- const loadSettings = React27.useCallback(async ({ signal } = {}) => {
15838
+ const loadSettings = React28.useCallback(async ({ signal } = {}) => {
15575
15839
  setPhase("loading");
15576
15840
  setLoadError(null);
15577
15841
  try {
@@ -15595,7 +15859,7 @@ function GlobalSettingsPanel({ rpcCall }) {
15595
15859
  setPhase("error");
15596
15860
  }
15597
15861
  }, [invoke]);
15598
- React27.useEffect(() => {
15862
+ React28.useEffect(() => {
15599
15863
  mounted.current = true;
15600
15864
  const controller = new AbortController();
15601
15865
  void loadSettings({ signal: controller.signal });
@@ -15604,7 +15868,7 @@ function GlobalSettingsPanel({ rpcCall }) {
15604
15868
  controller.abort();
15605
15869
  };
15606
15870
  }, [loadSettings]);
15607
- React27.useEffect(() => {
15871
+ React28.useEffect(() => {
15608
15872
  if (!sweepConfirming) return;
15609
15873
  globalThis.document?.getElementById(sweepConfirmButtonId)?.focus();
15610
15874
  }, [sweepConfirmButtonId, sweepConfirming]);
@@ -15912,6 +16176,32 @@ function replacePageLocation(url, location = globalThis.location) {
15912
16176
  // plugin-src/client/styles.js
15913
16177
  var IM_STYLE_ID = "xmanrui-dsh-im-settings";
15914
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; } }
15915
16205
  .dim-page {
15916
16206
  --dim-blue: var(--dsw-alias-state-business-primary, #3370ff);
15917
16207
  --dim-blue-soft: color-mix(in srgb, var(--dim-blue) 9%, transparent);
@@ -16841,8 +17131,8 @@ function installSessionChannelLogos(document2 = globalThis.document) {
16841
17131
  }
16842
17132
 
16843
17133
  // plugin-src/client/update-panel.js
16844
- var React28 = __toESM(require("react"), 1);
16845
- var import_react_dom3 = require("react-dom");
17134
+ var React29 = __toESM(require("react"), 1);
17135
+ var import_react_dom4 = require("react-dom");
16846
17136
  var import_valid = __toESM(require_valid(), 1);
16847
17137
  var import_rcompare = __toESM(require_rcompare(), 1);
16848
17138
  var UPDATE_RPC_CHANNEL = "/dsh-im";
@@ -16931,11 +17221,11 @@ function manualUpdateCommand(snapshot) {
16931
17221
  return `dsh plugin --profile ${profileArgument} add -w @xmanrui/dsh-im@${version}`;
16932
17222
  }
16933
17223
  function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
16934
- const [copyState, setCopyState] = React28.useState("idle");
16935
- const commandRef = React28.useRef(null);
16936
- const mounted = React28.useRef(false);
16937
- const copying = React28.useRef(false);
16938
- 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(() => {
16939
17229
  mounted.current = true;
16940
17230
  return () => {
16941
17231
  mounted.current = false;
@@ -16967,7 +17257,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
16967
17257
  { className: "dim-updateManual", "aria-label": "\u624B\u5DE5\u66F4\u65B0" },
16968
17258
  h2("h4", { className: "dim-updateManualHeading" }, "\u624B\u5DE5\u66F4\u65B0"),
16969
17259
  command ? h2(
16970
- React28.Fragment,
17260
+ React29.Fragment,
16971
17261
  null,
16972
17262
  h2("p", { className: "dim-updateManualHint" }, "\u81EA\u52A8\u66F4\u65B0\u5931\u8D25\u53EF\u4EE5\u4F7F\u7528\u547D\u4EE4\u66F4\u65B0\uFF1A"),
16973
17263
  h2(
@@ -17003,7 +17293,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
17003
17293
  "aria-hidden": "true",
17004
17294
  focusable: "false"
17005
17295
  }, copyState === "copied" ? h2("path", { d: "m4 10 4 4 8-8" }) : h2(
17006
- React28.Fragment,
17296
+ React29.Fragment,
17007
17297
  null,
17008
17298
  h2("rect", { x: 7, y: 7, width: 10, height: 11, rx: 1.5 }),
17009
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" })
@@ -17028,10 +17318,10 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
17028
17318
  );
17029
17319
  }
17030
17320
  function UpdateDialog({ children, onClose }) {
17031
- const dialogRef = React28.useRef(null);
17032
- const titleId = React28.useId();
17033
- const descriptionId = React28.useId();
17034
- React28.useEffect(() => {
17321
+ const dialogRef = React29.useRef(null);
17322
+ const titleId = React29.useId();
17323
+ const descriptionId = React29.useId();
17324
+ React29.useEffect(() => {
17035
17325
  const previous = globalThis.document?.activeElement;
17036
17326
  dialogRef.current?.focus?.();
17037
17327
  return () => {
@@ -17086,22 +17376,22 @@ function UpdateDialog({ children, onClose }) {
17086
17376
  children
17087
17377
  )
17088
17378
  );
17089
- 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;
17090
17380
  }
17091
17381
  function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17092
- const [snapshot, setSnapshot] = React28.useState(null);
17093
- const [action, setAction] = React28.useState("status");
17094
- const [error, setError] = React28.useState(null);
17095
- const [open, setOpen] = React28.useState(false);
17096
- const [uncertainInstall, setUncertainInstall] = React28.useState(false);
17097
- const mounted = React28.useRef(false);
17098
- const busy = React28.useRef(false);
17099
- const readController = React28.useRef(null);
17100
- const pollReadController = React28.useRef(null);
17101
- const installRequest = React28.useRef(null);
17102
- 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);
17103
17393
  onStatusRef.current = onStatus;
17104
- const accept = React28.useCallback((next) => {
17394
+ const accept = React29.useCallback((next) => {
17105
17395
  setSnapshot(next);
17106
17396
  onStatusRef.current?.(next);
17107
17397
  }, []);
@@ -17110,7 +17400,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17110
17400
  setUncertainInstall(false);
17111
17401
  accept(next);
17112
17402
  };
17113
- const invoke = React28.useCallback(async (endpoint, payload = {}, signal) => {
17403
+ const invoke = React29.useCallback(async (endpoint, payload = {}, signal) => {
17114
17404
  if (typeof rpcCall !== "function") {
17115
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");
17116
17406
  unavailable.code = "update-unavailable";
@@ -17118,7 +17408,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17118
17408
  }
17119
17409
  return unwrapSnapshot(await rpcCall(endpoint, payload, signal));
17120
17410
  }, [rpcCall]);
17121
- React28.useEffect(() => {
17411
+ React29.useEffect(() => {
17122
17412
  mounted.current = true;
17123
17413
  busy.current = true;
17124
17414
  const controller = new AbortController();
@@ -17141,7 +17431,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17141
17431
  const activeJob = ACTIVE_STATES4.has(snapshot?.job?.state);
17142
17432
  const restartRequired = snapshot?.job?.state === "restart-required" || snapshot?.blockedReason === "pending-restart";
17143
17433
  const shouldPoll = activeJob || uncertainInstall;
17144
- React28.useEffect(() => {
17434
+ React29.useEffect(() => {
17145
17435
  if (!shouldPoll) return void 0;
17146
17436
  let controller;
17147
17437
  const scheduler = createPollScheduler({
@@ -17239,7 +17529,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17239
17529
  const manualCommand = manualUpdateCommand(snapshot);
17240
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";
17241
17531
  return h2(
17242
- React28.Fragment,
17532
+ React29.Fragment,
17243
17533
  null,
17244
17534
  h2("button", {
17245
17535
  type: "button",
@@ -17264,13 +17554,13 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17264
17554
  h2("dt", null, "\u8FD0\u884C\u7248\u672C"),
17265
17555
  h2("dd", null, `v${snapshot?.runningVersion ?? clientVersion}`),
17266
17556
  snapshot?.installedVersion && snapshot.installedVersion !== snapshot.runningVersion ? h2(
17267
- React28.Fragment,
17557
+ React29.Fragment,
17268
17558
  null,
17269
17559
  h2("dt", null, "\u5DF2\u5B89\u88C5\u7248\u672C"),
17270
17560
  h2("dd", null, `v${snapshot.installedVersion}`)
17271
17561
  ) : null,
17272
17562
  targetVersion ? h2(
17273
- React28.Fragment,
17563
+ React29.Fragment,
17274
17564
  null,
17275
17565
  h2("dt", null, "\u76EE\u6807\u7248\u672C"),
17276
17566
  h2("dd", null, `v${targetVersion}`)
@@ -17491,23 +17781,23 @@ function IMSettingsTab({
17491
17781
  browserLocation = globalThis.location,
17492
17782
  navigateToRecoveryUrl = replacePageLocation
17493
17783
  }) {
17494
- const [selected, setSelected] = React29.useState("weixin");
17495
- const [loopbackRecovery, setLoopbackRecovery] = React29.useState(null);
17496
- const [runningVersion, setRunningVersion] = React29.useState(IM_PLUGIN_VERSION);
17497
- const [deliverySettings, setDeliverySettings] = React29.useState(null);
17498
- const githubTooltipId = React29.useId();
17499
- 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();
17500
17790
  const globalSettingsSelected = selected === GLOBAL_SETTINGS_TAB_ID;
17501
17791
  const active = CHANNELS.find((channel5) => channel5.id === selected) ?? CHANNELS[0];
17502
17792
  const activeTabId = globalSettingsSelected ? "dim-general-settings-trigger" : `dim-tab-${active.id}`;
17503
17793
  const activePanelId = globalSettingsSelected ? `dim-panel-${GLOBAL_SETTINGS_TAB_ID}` : `dim-panel-${active.id}`;
17504
- const reportLoopbackRecovery = React29.useCallback((recovery) => {
17794
+ const reportLoopbackRecovery = React30.useCallback((recovery) => {
17505
17795
  setLoopbackRecovery((current) => current?.url === recovery.url ? current : recovery);
17506
17796
  }, []);
17507
- const reportUpdateStatus = React29.useCallback((snapshot) => {
17797
+ const reportUpdateStatus = React30.useCallback((snapshot) => {
17508
17798
  setRunningVersion(snapshot.runningVersion);
17509
17799
  }, []);
17510
- const rpcCalls = React29.useMemo(() => createLoopbackAwareRpcCalls({
17800
+ const rpcCalls = React30.useMemo(() => createLoopbackAwareRpcCalls({
17511
17801
  dingtalkRpcCall,
17512
17802
  discordRpcCall,
17513
17803
  feishuRpcCall,
@@ -17545,7 +17835,7 @@ function IMSettingsTab({
17545
17835
  weixinRpcCall,
17546
17836
  whatsappRpcCall
17547
17837
  ]);
17548
- const botSettingsContext = React29.useMemo(() => Object.freeze({
17838
+ const botSettingsContext = React30.useMemo(() => Object.freeze({
17549
17839
  openBotSettings: setDeliverySettings
17550
17840
  }), []);
17551
17841
  return h2(