@xmanrui/dsh-im 4.18.1 → 4.19.1

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 +917 -521
  4. package/lib/index.js +269 -267
  5. package/package.json +1 -1
  6. package/plugin-src/client/bot-alias.js +169 -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 +41 -6
  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 +20 -1
  38. package/src/channels/feishu/bridge.mjs +330 -10
  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 +22 -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.1",
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,271 @@ 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 BotNameTooltip({ anchorRef, id: id6, name: name2, onDismiss }) {
3109
+ const tooltipRef = React5.useRef(null);
3110
+ const [position, setPosition] = React5.useState(null);
3111
+ React5.useLayoutEffect(() => {
3112
+ const anchor = anchorRef.current;
3113
+ const tooltip = tooltipRef.current;
3114
+ if (!anchor || !tooltip) return void 0;
3115
+ const document2 = anchor.ownerDocument;
3116
+ const view = document2.defaultView;
3117
+ const place = () => {
3118
+ const rect = anchor.getBoundingClientRect();
3119
+ const { width, height } = tooltip.getBoundingClientRect();
3120
+ const viewport = document2.documentElement;
3121
+ const margin = 8;
3122
+ const below = rect.bottom + 6;
3123
+ setPosition({
3124
+ left: Math.max(margin, Math.min(rect.left, viewport.clientWidth - width - margin)),
3125
+ top: Math.max(margin, Math.min(
3126
+ below + height <= viewport.clientHeight - margin ? below : rect.top - height - 6,
3127
+ viewport.clientHeight - height - margin
3128
+ ))
3129
+ });
3130
+ };
3131
+ const dismiss = (event) => {
3132
+ if (event.key === "Escape") {
3133
+ event.stopPropagation();
3134
+ onDismiss();
3135
+ }
3136
+ };
3137
+ place();
3138
+ view.addEventListener("resize", place);
3139
+ document2.addEventListener("scroll", onDismiss, true);
3140
+ document2.addEventListener("keydown", dismiss, true);
3141
+ return () => {
3142
+ view.removeEventListener("resize", place);
3143
+ document2.removeEventListener("scroll", onDismiss, true);
3144
+ document2.removeEventListener("keydown", dismiss, true);
3145
+ };
3146
+ }, [anchorRef, name2, onDismiss]);
3147
+ const body = anchorRef.current?.ownerDocument.body;
3148
+ return body ? (0, import_react_dom.createPortal)(h2("span", {
3149
+ ref: tooltipRef,
3150
+ id: id6,
3151
+ role: "tooltip",
3152
+ className: "dim-botNameTooltip",
3153
+ style: position ?? { visibility: "hidden" }
3154
+ }, name2), body) : null;
3155
+ }
3156
+ function BotName({ bot, id: id6, disabled = false, onSave }) {
3157
+ const [open, setOpen] = React5.useState(false);
3158
+ const nameRef = React5.useRef(null);
3159
+ const tooltipId = React5.useId();
3160
+ const [truncated, setTruncated] = React5.useState(false);
3161
+ const [hovered, setHovered] = React5.useState(false);
3162
+ const [focused, setFocused] = React5.useState(false);
3163
+ const [dismissed, setDismissed] = React5.useState(false);
3164
+ const dismissTooltip = React5.useCallback(() => setDismissed(true), []);
3165
+ const measure = React5.useCallback(() => {
3166
+ const node = nameRef.current;
3167
+ setTruncated(Boolean(node && node.scrollWidth > node.clientWidth));
3168
+ }, []);
3169
+ React5.useEffect(() => {
3170
+ const node = nameRef.current;
3171
+ if (!node) return void 0;
3172
+ measure();
3173
+ const view = node.ownerDocument.defaultView;
3174
+ const observer = view.ResizeObserver ? new view.ResizeObserver(measure) : null;
3175
+ observer?.observe(node);
3176
+ view.addEventListener("resize", measure);
3177
+ return () => {
3178
+ observer?.disconnect();
3179
+ view.removeEventListener("resize", measure);
3180
+ };
3181
+ }, [bot.name, measure]);
3182
+ const showTooltip = truncated && !dismissed && !open && (hovered || focused);
3183
+ return h2(
3184
+ "div",
3185
+ { className: "dim-aliasName" },
3186
+ h2("h3", {
3187
+ id: id6,
3188
+ ref: nameRef,
3189
+ tabIndex: truncated ? 0 : void 0,
3190
+ "aria-describedby": showTooltip ? tooltipId : void 0,
3191
+ onMouseEnter: () => {
3192
+ measure();
3193
+ setHovered(true);
3194
+ setDismissed(false);
3195
+ },
3196
+ onMouseLeave: () => setHovered(false),
3197
+ onFocus: () => {
3198
+ measure();
3199
+ setFocused(true);
3200
+ setDismissed(false);
3201
+ },
3202
+ onBlur: () => setFocused(false),
3203
+ onClick: dismissTooltip
3204
+ }, bot.name),
3205
+ showTooltip ? h2(BotNameTooltip, {
3206
+ anchorRef: nameRef,
3207
+ id: tooltipId,
3208
+ name: bot.name,
3209
+ onDismiss: dismissTooltip
3210
+ }) : null,
3211
+ h2(
3212
+ "span",
3213
+ {
3214
+ className: "dim-aliasEntry",
3215
+ onClick: (event) => event.stopPropagation(),
3216
+ onKeyDown: (event) => event.stopPropagation()
3217
+ },
3218
+ h2(
3219
+ "button",
3220
+ {
3221
+ type: "button",
3222
+ className: "dim-aliasEdit",
3223
+ "aria-label": "\u4FEE\u6539\u522B\u540D",
3224
+ title: "\u4FEE\u6539\u522B\u540D",
3225
+ "aria-haspopup": "dialog",
3226
+ disabled: disabled || typeof onSave !== "function",
3227
+ onClick: () => setOpen(true)
3228
+ },
3229
+ h2(
3230
+ "svg",
3231
+ {
3232
+ width: 14,
3233
+ height: 14,
3234
+ viewBox: "0 0 24 24",
3235
+ fill: "none",
3236
+ stroke: "currentColor",
3237
+ strokeWidth: 1.7,
3238
+ strokeLinecap: "round",
3239
+ strokeLinejoin: "round",
3240
+ "aria-hidden": true
3241
+ },
3242
+ h2("path", { d: "m16 3 5 5M3 21l5-1L21 7a2.1 2.1 0 0 0-5-5L3 15Z" })
3243
+ )
3244
+ ),
3245
+ open ? h2(AliasDialog, { bot, onSave, onClose: () => setOpen(false) }) : null
3246
+ )
3247
+ );
3248
+ }
3249
+
2961
3250
  // plugin-src/client/channels/dingtalk/index.js
2962
- var React12 = __toESM(require("react"), 1);
3251
+ var React13 = __toESM(require("react"), 1);
2963
3252
 
2964
3253
  // plugin-src/client/credential-binding.js
2965
- var React5 = __toESM(require("react"), 1);
3254
+ var React6 = __toESM(require("react"), 1);
2966
3255
  function ActionIcon({ children }) {
2967
3256
  return h2("svg", {
2968
3257
  className: "dim-actionIcon",
@@ -3022,9 +3311,9 @@ function CredentialBindingPanel({
3022
3311
  onSubmit,
3023
3312
  onCancel
3024
3313
  }) {
3025
- const [identity, setIdentity] = React5.useState("");
3026
- const [secret, setSecret] = React5.useState("");
3027
- const headingId = React5.useId();
3314
+ const [identity, setIdentity] = React6.useState("");
3315
+ const [secret, setSecret] = React6.useState("");
3316
+ const headingId = React6.useId();
3028
3317
  const hasIdentity = Boolean(identityLabel);
3029
3318
  const submit = (event) => {
3030
3319
  event.preventDefault();
@@ -3103,7 +3392,7 @@ function CredentialBindingPanel({
3103
3392
  }
3104
3393
 
3105
3394
  // plugin-src/client/channels/shared/collapsible-account.js
3106
- var React6 = __toESM(require("react"), 1);
3395
+ var React7 = __toESM(require("react"), 1);
3107
3396
  function CollapsibleAccountSection({
3108
3397
  header,
3109
3398
  defaultOpen = false,
@@ -3113,7 +3402,7 @@ function CollapsibleAccountSection({
3113
3402
  className = "",
3114
3403
  children
3115
3404
  }) {
3116
- const [uncontrolledOpen, setUncontrolledOpen] = React6.useState(defaultOpen);
3405
+ const [uncontrolledOpen, setUncontrolledOpen] = React7.useState(defaultOpen);
3117
3406
  const open = controlledOpen ?? uncontrolledOpen;
3118
3407
  const contentId = id6 ? `${id6}-content` : void 0;
3119
3408
  const toggle = () => {
@@ -3160,11 +3449,11 @@ function CollapsibleAccountSection({
3160
3449
  }
3161
3450
 
3162
3451
  // plugin-src/client/workspace-editor.js
3163
- var React8 = __toESM(require("react"), 1);
3452
+ var React9 = __toESM(require("react"), 1);
3164
3453
 
3165
3454
  // plugin-src/client/workspace-directory-picker.js
3166
- var React7 = __toESM(require("react"), 1);
3167
- var import_react_dom = require("react-dom");
3455
+ var React8 = __toESM(require("react"), 1);
3456
+ var import_react_dom2 = require("react-dom");
3168
3457
  function pickerErrorCode(error) {
3169
3458
  return error?.rpcError?.code ?? error?.code;
3170
3459
  }
@@ -3184,7 +3473,7 @@ function pickerErrorMessage(error) {
3184
3473
  return error?.rpcError?.message ?? error?.message ?? "\u65E0\u6CD5\u8BFB\u53D6\u76EE\u5F55\uFF0C\u8BF7\u91CD\u8BD5\u3002";
3185
3474
  }
3186
3475
  function FolderIcon() {
3187
- return React7.createElement(
3476
+ return React8.createElement(
3188
3477
  "svg",
3189
3478
  {
3190
3479
  viewBox: "0 0 24 24",
@@ -3195,11 +3484,11 @@ function FolderIcon() {
3195
3484
  strokeLinejoin: "round",
3196
3485
  "aria-hidden": "true"
3197
3486
  },
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" })
3487
+ 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
3488
  );
3200
3489
  }
3201
3490
  function ChevronIcon() {
3202
- return React7.createElement("svg", {
3491
+ return React8.createElement("svg", {
3203
3492
  viewBox: "0 0 20 20",
3204
3493
  fill: "none",
3205
3494
  stroke: "currentColor",
@@ -3207,7 +3496,7 @@ function ChevronIcon() {
3207
3496
  strokeLinecap: "round",
3208
3497
  strokeLinejoin: "round",
3209
3498
  "aria-hidden": "true"
3210
- }, React7.createElement("path", { d: "m7.5 4.5 5 5.5-5 5.5" }));
3499
+ }, React8.createElement("path", { d: "m7.5 4.5 5 5.5-5 5.5" }));
3211
3500
  }
3212
3501
  function displayCrumbs(listing) {
3213
3502
  const homeIndex = listing.crumbs.findIndex((crumb) => crumb.path === listing.home);
@@ -3223,28 +3512,28 @@ function WorkspaceDirectoryPicker({
3223
3512
  onPicked,
3224
3513
  onCancel
3225
3514
  }) {
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);
3515
+ const [listing, setListing] = React8.useState(null);
3516
+ const [loading, setLoading] = React8.useState(false);
3517
+ const [error, setError] = React8.useState(null);
3518
+ const [pathDraft, setPathDraft] = React8.useState(startPath ?? "");
3519
+ const [showHidden, setShowHidden] = React8.useState(false);
3520
+ const [retryKey, setRetryKey] = React8.useState(0);
3521
+ const requestRef = React8.useRef(0);
3522
+ const controllerRef = React8.useRef(null);
3523
+ const dialogRef = React8.useRef(null);
3524
+ const bodyRef = React8.useRef(null);
3525
+ const titleId = React8.useId();
3526
+ const noticeId = React8.useId();
3527
+ const pathInputId = React8.useId();
3528
+ const errorId = React8.useId();
3529
+ const initialPathRef = React8.useRef(startPath);
3530
+ const onPickedRef = React8.useRef(onPicked);
3531
+ const onCancelRef = React8.useRef(onCancel);
3532
+ const busyRef = React8.useRef(busy);
3244
3533
  onPickedRef.current = onPicked;
3245
3534
  onCancelRef.current = onCancel;
3246
3535
  busyRef.current = busy;
3247
- const loadDirectory = React7.useCallback(async (path, { reportError = true } = {}) => {
3536
+ const loadDirectory = React8.useCallback(async (path, { reportError = true } = {}) => {
3248
3537
  const request = requestRef.current + 1;
3249
3538
  requestRef.current = request;
3250
3539
  controllerRef.current?.abort();
@@ -3268,7 +3557,7 @@ function WorkspaceDirectoryPicker({
3268
3557
  if (request === requestRef.current) setLoading(false);
3269
3558
  }
3270
3559
  }, [picker]);
3271
- React7.useEffect(() => {
3560
+ React8.useEffect(() => {
3272
3561
  if (!open) return void 0;
3273
3562
  let active = true;
3274
3563
  setListing(null);
@@ -3348,10 +3637,10 @@ function WorkspaceDirectoryPicker({
3348
3637
  "nav",
3349
3638
  { className: "dim-directoryCrumbs", "aria-label": "\u5F53\u524D\u76EE\u5F55" },
3350
3639
  crumbs.map((crumb, index) => h2(
3351
- React7.Fragment,
3640
+ React8.Fragment,
3352
3641
  { key: crumb.path },
3353
3642
  index > 0 ? h2("span", { className: "dim-directoryCrumbSeparator", "aria-hidden": "true" }, "\u203A") : null,
3354
- React7.createElement("button", {
3643
+ React8.createElement("button", {
3355
3644
  type: "button",
3356
3645
  title: crumb.path,
3357
3646
  disabled: loading || busy,
@@ -3414,7 +3703,7 @@ function WorkspaceDirectoryPicker({
3414
3703
  ) : listing ? entries.length > 0 ? h2("ul", { className: "dim-directoryList" }, entries.map((entry) => h2(
3415
3704
  "li",
3416
3705
  { key: entry.path },
3417
- React7.createElement(
3706
+ React8.createElement(
3418
3707
  "button",
3419
3708
  {
3420
3709
  type: "button",
@@ -3423,7 +3712,7 @@ function WorkspaceDirectoryPicker({
3423
3712
  onClick: () => void loadDirectory(entry.path)
3424
3713
  },
3425
3714
  h2("span", { className: "dim-directoryFolder" }, h2(FolderIcon)),
3426
- React7.createElement("span", { className: "dim-directoryName" }, entry.name),
3715
+ React8.createElement("span", { className: "dim-directoryName" }, entry.name),
3427
3716
  h2("span", { className: "dim-directoryChevron" }, h2(ChevronIcon))
3428
3717
  )
3429
3718
  ))) : h2(
@@ -3472,25 +3761,25 @@ function WorkspaceDirectoryPicker({
3472
3761
  )
3473
3762
  )
3474
3763
  );
3475
- return typeof document === "undefined" ? content : (0, import_react_dom.createPortal)(content, document.body);
3764
+ return typeof document === "undefined" ? content : (0, import_react_dom2.createPortal)(content, document.body);
3476
3765
  }
3477
3766
 
3478
3767
  // plugin-src/client/workspace-editor.js
3479
- var WorkspaceDirectoryPickerContext = React8.createContext(null);
3768
+ var WorkspaceDirectoryPickerContext = React9.createContext(null);
3480
3769
  function WorkspaceEditor({ workspace, directoryPicker, disabled = false, onSave }) {
3481
- const sharedDirectoryPicker = React8.useContext(WorkspaceDirectoryPickerContext);
3770
+ const sharedDirectoryPicker = React9.useContext(WorkspaceDirectoryPickerContext);
3482
3771
  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(() => {
3772
+ const [open, setOpen] = React9.useState(false);
3773
+ const [saving, setSaving] = React9.useState(false);
3774
+ const [error, setError] = React9.useState(null);
3775
+ const editButtonRef = React9.useRef(null);
3776
+ const savingRef = React9.useRef(false);
3777
+ const close = React9.useCallback(() => {
3489
3778
  setOpen(false);
3490
3779
  setError(null);
3491
3780
  queueMicrotask(() => editButtonRef.current?.focus?.());
3492
3781
  }, []);
3493
- const pick = React8.useCallback(async (value) => {
3782
+ const pick = React9.useCallback(async (value) => {
3494
3783
  if (!value || savingRef.current || disabled) return;
3495
3784
  if (value === workspace) {
3496
3785
  close();
@@ -3527,7 +3816,7 @@ function WorkspaceEditor({ workspace, directoryPicker, disabled = false, onSave
3527
3816
  disabled: disabled || !activeDirectoryPicker
3528
3817
  }, "\u9009\u62E9\u76EE\u5F55")
3529
3818
  ),
3530
- workspace ? React8.createElement("code", {
3819
+ workspace ? React9.createElement("code", {
3531
3820
  className: "dim-workspacePath",
3532
3821
  title: workspace
3533
3822
  }, workspace) : h2("code", { className: "dim-workspacePath" }, "\u672A\u8BBE\u7F6E"),
@@ -3544,8 +3833,8 @@ function WorkspaceEditor({ workspace, directoryPicker, disabled = false, onSave
3544
3833
  }
3545
3834
 
3546
3835
  // plugin-src/client/context-enhancement.js
3547
- var React9 = __toESM(require("react"), 1);
3548
- var import_react_dom2 = require("react-dom");
3836
+ var React10 = __toESM(require("react"), 1);
3837
+ var import_react_dom3 = require("react-dom");
3549
3838
  var FIELD_LABELS = Object.freeze({
3550
3839
  channel: "\u6E20\u9053",
3551
3840
  conversationType: "\u4F1A\u8BDD\u7C7B\u578B",
@@ -3789,7 +4078,7 @@ function ContextEnhancementScopeEditor({
3789
4078
  );
3790
4079
  }
3791
4080
  function ContextEnhancementDialog({ config, groupSupported, disabled, onSave, onClose, returnFocusRef, id: id6 }) {
3792
- const [draft, setDraft] = React9.useState(() => {
4081
+ const [draft, setDraft] = React10.useState(() => {
3793
4082
  const normalized = normalizeContextEnhancementConfig(config);
3794
4083
  return {
3795
4084
  ...normalized,
@@ -3798,23 +4087,23 @@ function ContextEnhancementDialog({ config, groupSupported, disabled, onSave, on
3798
4087
  } : {}
3799
4088
  };
3800
4089
  });
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();
4090
+ const [saving, setSaving] = React10.useState(false);
4091
+ const [error, setError] = React10.useState(null);
4092
+ const [activeScope, setActiveScope] = React10.useState("direct");
4093
+ const savingRef = React10.useRef(false);
4094
+ const dialogRef = React10.useRef(null);
4095
+ const mountedRef = React10.useRef(true);
4096
+ const groupTabRef = React10.useRef(null);
4097
+ const directTabRef = React10.useRef(null);
4098
+ const titleId = React10.useId();
4099
+ const descriptionId = React10.useId();
4100
+ const scopeIdPrefix = React10.useId();
3812
4101
  const groupGuidanceExample = localizeText(CONTEXT_GROUP_GUIDANCE_EXAMPLE);
3813
4102
  const directGuidanceExample = localizeText(CONTEXT_DIRECT_GUIDANCE_EXAMPLE);
3814
4103
  const busy = disabled || saving;
3815
4104
  const scopeKinds = ["direct", "group"];
3816
4105
  const tabRefs = { group: groupTabRef, direct: directTabRef };
3817
- React9.useEffect(() => {
4106
+ React10.useEffect(() => {
3818
4107
  mountedRef.current = true;
3819
4108
  dialogRef.current?.focus?.();
3820
4109
  const keepFocus = (event) => {
@@ -4002,20 +4291,20 @@ function ContextEnhancementDialog({ config, groupSupported, disabled, onSave, on
4002
4291
  }, saving ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58")
4003
4292
  )
4004
4293
  ));
4005
- return globalThis.document?.body ? (0, import_react_dom2.createPortal)(content, document.body) : content;
4294
+ return globalThis.document?.body ? (0, import_react_dom3.createPortal)(content, document.body) : content;
4006
4295
  }
4007
4296
  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();
4297
+ const [open, setOpen] = React10.useState(false);
4298
+ const entryRef = React10.useRef(null);
4299
+ const dialogId = React10.useId();
4300
+ const statusId = React10.useId();
4012
4301
  const saved = normalizeContextEnhancementConfig(config);
4013
4302
  const label = contextEnhancementLabel(groupSupported ? saved : {
4014
4303
  ...saved,
4015
4304
  group: { ...saved.group, enabled: false }
4016
4305
  });
4017
4306
  return h2(
4018
- React9.Fragment,
4307
+ React10.Fragment,
4019
4308
  null,
4020
4309
  h2(
4021
4310
  "button",
@@ -4049,10 +4338,10 @@ function ContextEnhancementEditor({ config, groupSupported = true, disabled = fa
4049
4338
  }
4050
4339
 
4051
4340
  // plugin-src/client/workspace-snapshot-fence.js
4052
- var React10 = __toESM(require("react"), 1);
4341
+ var React11 = __toESM(require("react"), 1);
4053
4342
  function useWorkspaceSnapshotFence() {
4054
- const state = React10.useRef({ version: 0, pendingMutations: 0 });
4055
- return React10.useMemo(() => Object.freeze({
4343
+ const state = React11.useRef({ version: 0, pendingMutations: 0 });
4344
+ return React11.useMemo(() => Object.freeze({
4056
4345
  beginStatus() {
4057
4346
  return state.current.pendingMutations === 0 ? state.current.version : null;
4058
4347
  },
@@ -4075,8 +4364,8 @@ function useWorkspaceSnapshotFence() {
4075
4364
  }
4076
4365
 
4077
4366
  // plugin-src/client/channel-card-meta.js
4078
- var React11 = __toESM(require("react"), 1);
4079
- var BotSettingsContext = React11.createContext(Object.freeze({
4367
+ var React12 = __toESM(require("react"), 1);
4368
+ var BotSettingsContext = React12.createContext(Object.freeze({
4080
4369
  openBotSettings() {
4081
4370
  }
4082
4371
  }));
@@ -4106,8 +4395,8 @@ function BotSettingsButton({
4106
4395
  accessPolicy,
4107
4396
  channelSettings
4108
4397
  }) {
4109
- const { openBotSettings } = React11.useContext(BotSettingsContext);
4110
- const tooltipId = React11.useId();
4398
+ const { openBotSettings } = React12.useContext(BotSettingsContext);
4399
+ const tooltipId = React12.useId();
4111
4400
  return h2(
4112
4401
  "span",
4113
4402
  { className: "dim-botSettingsAction" },
@@ -4147,7 +4436,7 @@ function messageErrorTime(value) {
4147
4436
  }
4148
4437
  }
4149
4438
  function ChannelListHeading({ className = "", id: id6, title, connectionLabel }) {
4150
- const helpId = React11.useId();
4439
+ const helpId = React12.useId();
4151
4440
  return h2(
4152
4441
  "div",
4153
4442
  { className: `${className} dim-listHeading`.trim() },
@@ -4228,7 +4517,7 @@ function LastMessageErrorSummary({ className = "", error }) {
4228
4517
  h2("span", null, "\u53C2\u8003\u53F7"),
4229
4518
  ` ${error.referenceId}`,
4230
4519
  occurredAt ? h2(
4231
- React11.Fragment,
4520
+ React12.Fragment,
4232
4521
  null,
4233
4522
  " \xB7 ",
4234
4523
  h2("time", { dateTime: new Date(error.at).toISOString() }, occurredAt)
@@ -4391,7 +4680,7 @@ function DingtalkIcon({ size = 28 }) {
4391
4680
  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
4681
  }));
4393
4682
  }
4394
- var Button = React12.forwardRef(function Button2({ children, kind = "secondary", className = "", ...props }, ref) {
4683
+ var Button = React13.forwardRef(function Button2({ children, kind = "secondary", className = "", ...props }, ref) {
4395
4684
  return h2("button", {
4396
4685
  ...props,
4397
4686
  ref,
@@ -4487,13 +4776,13 @@ function EmptyView({ busy, onStart }) {
4487
4776
  );
4488
4777
  }
4489
4778
  function QrPanel({ provision, now, busy, onRefresh, onCancel }) {
4490
- const [imageFailed, setImageFailed] = React12.useState(false);
4779
+ const [imageFailed, setImageFailed] = React13.useState(false);
4491
4780
  const source = safeQrSource(provision.qrCodeDataUrl);
4492
4781
  const remaining = Math.max(0, provision.expiresAt - now);
4493
4782
  const expired = remaining === 0 || provision.status === "expired";
4494
4783
  const duration = Math.max(1, provision.durationMs ?? 10 * 6e4);
4495
4784
  const progress = Math.round(Math.min(1, remaining / duration) * 100);
4496
- React12.useEffect(() => setImageFailed(false), [source]);
4785
+ React13.useEffect(() => setImageFailed(false), [source]);
4497
4786
  return h2(
4498
4787
  "div",
4499
4788
  { className: "ddt-card dim-surfaceCard" },
@@ -4585,7 +4874,7 @@ function ConnectionErrorDiagnostic({ error }) {
4585
4874
  { className: "ddt-errorCode" },
4586
4875
  h2("span", null, "\u9519\u8BEF\u7801"),
4587
4876
  `: ${error.code}`,
4588
- error.referenceId ? h2(React12.Fragment, null, " \xB7 ", h2("span", null, "\u53C2\u8003\u53F7"), `: ${error.referenceId}`) : null
4877
+ error.referenceId ? h2(React13.Fragment, null, " \xB7 ", h2("span", null, "\u53C2\u8003\u53F7"), `: ${error.referenceId}`) : null
4589
4878
  )
4590
4879
  );
4591
4880
  }
@@ -4608,7 +4897,7 @@ function ProvisionError({ provision, busy, onRetry, onClose }) {
4608
4897
  "div",
4609
4898
  { className: "ddt-actions dim-viewActions" },
4610
4899
  connectionFailed ? h2(Button, { kind: "primary", onClick: onClose, disabled: busy }, "\u67E5\u770B\u5DF2\u4FDD\u5B58\u7684\u673A\u5668\u4EBA") : h2(
4611
- React12.Fragment,
4900
+ React13.Fragment,
4612
4901
  null,
4613
4902
  h2(Button, { kind: "primary", onClick: onRetry, disabled: busy }, "\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801"),
4614
4903
  h2(Button, { onClick: onClose, disabled: busy }, "\u5173\u95ED")
@@ -4630,8 +4919,8 @@ function checkedTime(value) {
4630
4919
  }
4631
4920
  }
4632
4921
  function RemoveConfirmation({ account, busy, onConfirm, onCancel }) {
4633
- const cancelRef = React12.useRef(null);
4634
- React12.useEffect(() => cancelRef.current?.focus(), []);
4922
+ const cancelRef = React13.useRef(null);
4923
+ React13.useEffect(() => cancelRef.current?.focus(), []);
4635
4924
  return h2(
4636
4925
  "div",
4637
4926
  {
@@ -4663,6 +4952,7 @@ function AccountCard({
4663
4952
  removing,
4664
4953
  onReconnect,
4665
4954
  onWorkspaceSave,
4955
+ onAliasSave,
4666
4956
  onModelSave,
4667
4957
  onAgentPresetSave,
4668
4958
  onContextEnhancementSave,
@@ -4694,7 +4984,7 @@ function AccountCard({
4694
4984
  h2(
4695
4985
  "div",
4696
4986
  { className: "dim-botName" },
4697
- h2("h3", { title: account.bot.name }, account.bot.name),
4987
+ h2(BotName, { bot: account.bot, disabled: Boolean(busy), onSave: onAliasSave }),
4698
4988
  h2("p", { title: account.bot.clientIdMasked }, account.bot.clientIdMasked)
4699
4989
  )
4700
4990
  ),
@@ -4809,6 +5099,7 @@ function AccountList(props) {
4809
5099
  removing: props.removeTarget === account.botId,
4810
5100
  onReconnect: () => props.onReconnect(account),
4811
5101
  onWorkspaceSave: (workspace) => props.onWorkspaceSave(account, workspace),
5102
+ onAliasSave: (alias) => props.onAliasSave(account, alias),
4812
5103
  onModelSave: (model) => props.onModelSave(account, model),
4813
5104
  onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(account, agentPreset),
4814
5105
  onContextEnhancementSave: (config) => props.onContextEnhancementSave(account, config),
@@ -4821,7 +5112,7 @@ function AccountList(props) {
4821
5112
  }
4822
5113
  var EMPTY_TOTALS = Object.freeze({ configured: 0, connected: 0 });
4823
5114
  function DingtalkSettingsTab({ rpcCall }) {
4824
- const [model, setModel] = React12.useState({
5115
+ const [model, setModel] = React13.useState({
4825
5116
  phase: "loading",
4826
5117
  bots: [],
4827
5118
  totals: EMPTY_TOTALS,
@@ -4830,22 +5121,22 @@ function DingtalkSettingsTab({ rpcCall }) {
4830
5121
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
4831
5122
  modelCatalog: EMPTY_MODEL_CATALOG
4832
5123
  });
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);
5124
+ const [provision, setProvision] = React13.useState(null);
5125
+ const [busy, setBusy] = React13.useState(false);
5126
+ const [busyByBot, setBusyByBot] = React13.useState({});
5127
+ const [feedbackByBot, setFeedbackByBot] = React13.useState({});
5128
+ const [removeTarget, setRemoveTarget] = React13.useState(null);
5129
+ const [credentialOpen, setCredentialOpen] = React13.useState(false);
5130
+ const [credentialError, setCredentialError] = React13.useState(null);
5131
+ const [notice, setNotice] = React13.useState("");
5132
+ const [now, setNow] = React13.useState(() => Date.now());
5133
+ const addButtonRef = React13.useRef(null);
5134
+ const mountedRef = React13.useRef(true);
5135
+ const statusRequestRef = React13.useRef(0);
4845
5136
  const workspaceFence = useWorkspaceSnapshotFence();
4846
- const noticeFrameRef = React12.useRef(null);
4847
- const focusFrameRef = React12.useRef(null);
4848
- React12.useEffect(() => {
5137
+ const noticeFrameRef = React13.useRef(null);
5138
+ const focusFrameRef = React13.useRef(null);
5139
+ React13.useEffect(() => {
4849
5140
  mountedRef.current = true;
4850
5141
  return () => {
4851
5142
  mountedRef.current = false;
@@ -4860,8 +5151,8 @@ function DingtalkSettingsTab({ rpcCall }) {
4860
5151
  }
4861
5152
  };
4862
5153
  }, []);
4863
- React12.useEffect(() => installDingtalkStyles(), []);
4864
- const announce = React12.useCallback((message) => {
5154
+ React13.useEffect(() => installDingtalkStyles(), []);
5155
+ const announce = React13.useCallback((message) => {
4865
5156
  if (!mountedRef.current) return;
4866
5157
  if (noticeFrameRef.current !== null) {
4867
5158
  window.cancelAnimationFrame(noticeFrameRef.current);
@@ -4875,7 +5166,7 @@ function DingtalkSettingsTab({ rpcCall }) {
4875
5166
  });
4876
5167
  }
4877
5168
  }, []);
4878
- const discardStaleFeedback = React12.useCallback((snapshot) => {
5169
+ const discardStaleFeedback = React13.useCallback((snapshot) => {
4879
5170
  const botsById = new Map(snapshot.bots.map((bot) => [bot.botId, bot]));
4880
5171
  setFeedbackByBot((current) => {
4881
5172
  let changed = false;
@@ -4890,7 +5181,7 @@ function DingtalkSettingsTab({ rpcCall }) {
4890
5181
  return changed ? next : current;
4891
5182
  });
4892
5183
  }, []);
4893
- const focusAddButton = React12.useCallback(() => {
5184
+ const focusAddButton = React13.useCallback(() => {
4894
5185
  if (!mountedRef.current) return;
4895
5186
  if (focusFrameRef.current !== null) window.cancelAnimationFrame(focusFrameRef.current);
4896
5187
  focusFrameRef.current = window.requestAnimationFrame(() => {
@@ -4898,11 +5189,11 @@ function DingtalkSettingsTab({ rpcCall }) {
4898
5189
  if (mountedRef.current) addButtonRef.current?.focus();
4899
5190
  });
4900
5191
  }, []);
4901
- const invoke = React12.useCallback(async (endpoint, payload = {}, signal) => {
5192
+ const invoke = React13.useCallback(async (endpoint, payload = {}, signal) => {
4902
5193
  if (typeof rpcCall !== "function") throw new TypeError("\u9489\u9489\u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
4903
5194
  return unwrapRpcResult(await rpcCall(endpoint, payload, signal));
4904
5195
  }, [rpcCall]);
4905
- const loadStatus = React12.useCallback(async ({
5196
+ const loadStatus = React13.useCallback(async ({
4906
5197
  signal,
4907
5198
  silent = false,
4908
5199
  restoreProvisioning = false
@@ -4947,12 +5238,12 @@ function DingtalkSettingsTab({ rpcCall }) {
4947
5238
  return void 0;
4948
5239
  }
4949
5240
  }, [discardStaleFeedback, invoke, workspaceFence]);
4950
- React12.useEffect(() => {
5241
+ React13.useEffect(() => {
4951
5242
  const controller = new AbortController();
4952
5243
  void loadStatus({ signal: controller.signal, restoreProvisioning: true });
4953
5244
  return () => controller.abort();
4954
5245
  }, [loadStatus]);
4955
- React12.useEffect(() => {
5246
+ React13.useEffect(() => {
4956
5247
  if (model.phase !== "ready") return void 0;
4957
5248
  const controller = new AbortController();
4958
5249
  let running = false;
@@ -4971,14 +5262,14 @@ function DingtalkSettingsTab({ rpcCall }) {
4971
5262
  window.clearInterval(timer);
4972
5263
  };
4973
5264
  }, [loadStatus, model.phase]);
4974
- React12.useEffect(() => {
5265
+ React13.useEffect(() => {
4975
5266
  if (!provision || !ACTIVE_PROVISION_STATES.has(provision.status)) return void 0;
4976
5267
  const timer = window.setInterval(() => {
4977
5268
  if (mountedRef.current) setNow(Date.now());
4978
5269
  }, 1e3);
4979
5270
  return () => window.clearInterval(timer);
4980
5271
  }, [provision?.attemptId, provision?.status]);
4981
- const startProvisioning = React12.useCallback(async ({ replace = false } = {}) => {
5272
+ const startProvisioning = React13.useCallback(async ({ replace = false } = {}) => {
4982
5273
  if (!mountedRef.current) return;
4983
5274
  setCredentialOpen(false);
4984
5275
  setCredentialError(null);
@@ -5016,7 +5307,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5016
5307
  if (mountedRef.current) setBusy(false);
5017
5308
  }
5018
5309
  }, [announce, invoke, provision?.attemptId]);
5019
- const bindCredentials = React12.useCallback(async ({ identity, secret }) => {
5310
+ const bindCredentials = React13.useCallback(async ({ identity, secret }) => {
5020
5311
  if (!mountedRef.current) return;
5021
5312
  const snapshotVersion = workspaceFence.beginMutation();
5022
5313
  setBusy(true);
@@ -5049,7 +5340,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5049
5340
  if (mountedRef.current) setBusy(false);
5050
5341
  }
5051
5342
  }, [announce, discardStaleFeedback, invoke, loadStatus, workspaceFence]);
5052
- const cancelProvisioning = React12.useCallback(async () => {
5343
+ const cancelProvisioning = React13.useCallback(async () => {
5053
5344
  if (!mountedRef.current) return;
5054
5345
  setBusy(true);
5055
5346
  try {
@@ -5067,7 +5358,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5067
5358
  if (mountedRef.current) setBusy(false);
5068
5359
  }
5069
5360
  }, [announce, focusAddButton, invoke, provision?.attemptId, provision?.status]);
5070
- React12.useEffect(() => {
5361
+ React13.useEffect(() => {
5071
5362
  const attemptId = provision?.attemptId;
5072
5363
  if (!attemptId || !ACTIVE_PROVISION_STATES.has(provision.status)) return void 0;
5073
5364
  const controller = new AbortController();
@@ -5130,7 +5421,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5130
5421
  timer = null;
5131
5422
  };
5132
5423
  }, [announce, invoke, loadStatus, provision?.attemptId, provision?.pollIntervalMs, provision?.status]);
5133
- const setBotBusy = React12.useCallback((botId, operation) => {
5424
+ const setBotBusy = React13.useCallback((botId, operation) => {
5134
5425
  if (!mountedRef.current) return;
5135
5426
  setBusyByBot((current) => {
5136
5427
  const next = { ...current };
@@ -5139,7 +5430,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5139
5430
  return next;
5140
5431
  });
5141
5432
  }, []);
5142
- const runBotAction = React12.useCallback(async ({ account, operation, endpoint, payload, success }) => {
5433
+ const runBotAction = React13.useCallback(async ({ account, operation, endpoint, payload, success }) => {
5143
5434
  if (!mountedRef.current) return void 0;
5144
5435
  const snapshotVersion = workspaceFence.beginMutation();
5145
5436
  setBotBusy(account.botId, operation);
@@ -5195,7 +5486,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5195
5486
  if (mountedRef.current) setBotBusy(account.botId, null);
5196
5487
  }
5197
5488
  }, [announce, discardStaleFeedback, invoke, loadStatus, setBotBusy, workspaceFence]);
5198
- const reconnect = React12.useCallback((account) => runBotAction({
5489
+ const reconnect = React13.useCallback((account) => runBotAction({
5199
5490
  account,
5200
5491
  operation: "reconnect",
5201
5492
  endpoint: DINGTALK_ENDPOINTS.reconnectBot,
@@ -5206,7 +5497,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5206
5497
  return connectionTestFeedback(snapshot.testMessage) ?? "\u9489\u9489\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\u3002";
5207
5498
  }
5208
5499
  }), [runBotAction]);
5209
- const saveWorkspace = React12.useCallback(async (account, workspace) => {
5500
+ const saveWorkspace = React13.useCallback(async (account, workspace) => {
5210
5501
  const workspaceVersion = workspaceFence.beginMutation();
5211
5502
  setBotBusy(account.botId, "workspace");
5212
5503
  try {
@@ -5232,7 +5523,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5232
5523
  if (mountedRef.current) setBotBusy(account.botId, null);
5233
5524
  }
5234
5525
  }, [discardStaleFeedback, invoke, loadStatus, setBotBusy, workspaceFence]);
5235
- const saveBotSetting = React12.useCallback(async (account, operation, endpoint, payload) => {
5526
+ const saveBotSetting = React13.useCallback(async (account, operation, endpoint, payload) => {
5236
5527
  const snapshotVersion = workspaceFence.beginMutation();
5237
5528
  setBotBusy(account.botId, operation);
5238
5529
  try {
@@ -5258,7 +5549,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5258
5549
  if (mountedRef.current) setBotBusy(account.botId, null);
5259
5550
  }
5260
5551
  }, [discardStaleFeedback, invoke, loadStatus, setBotBusy, workspaceFence]);
5261
- const remove = React12.useCallback(async (account) => {
5552
+ const remove = React13.useCallback(async (account) => {
5262
5553
  const snapshot = await runBotAction({
5263
5554
  account,
5264
5555
  operation: "delete",
@@ -5344,7 +5635,7 @@ function DingtalkSettingsTab({ rpcCall }) {
5344
5635
  h2(Button, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
5345
5636
  )
5346
5637
  ) : h2(
5347
- React12.Fragment,
5638
+ React13.Fragment,
5348
5639
  null,
5349
5640
  credentialView,
5350
5641
  provisionView,
@@ -5356,6 +5647,12 @@ function DingtalkSettingsTab({ rpcCall }) {
5356
5647
  removeTarget,
5357
5648
  onReconnect: (account) => void reconnect(account),
5358
5649
  onWorkspaceSave: saveWorkspace,
5650
+ onAliasSave: (account, alias) => saveBotSetting(
5651
+ account,
5652
+ "alias",
5653
+ DINGTALK_ENDPOINTS.setAlias,
5654
+ { alias }
5655
+ ),
5359
5656
  onModelSave: (account, selectedModel) => saveBotSetting(
5360
5657
  account,
5361
5658
  "model",
@@ -5408,7 +5705,8 @@ var TOKEN_BOT_ENDPOINTS = Object.freeze({
5408
5705
  setModel: SET_MODEL_ENDPOINT,
5409
5706
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
5410
5707
  setContextEnhancement: "bot.context-enhancement.set",
5411
- setAccessPolicy: "bot.access-policy.set"
5708
+ setAccessPolicy: "bot.access-policy.set",
5709
+ setAlias: "bot.alias.set"
5412
5710
  });
5413
5711
  function createTokenChannelApi(channel5, connectionSummary, {
5414
5712
  normalizeBotExtension = () => ({})
@@ -5439,6 +5737,7 @@ function createTokenChannelApi(channel5, connectionSummary, {
5439
5737
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
5440
5738
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
5441
5739
  bot: {
5740
+ ...normalizeBotAlias(value.bot),
5442
5741
  name: text2(value.bot?.name, `${channel5}\u673A\u5668\u4EBA`, 100),
5443
5742
  username: text2(value.bot?.username, "", 100),
5444
5743
  idMasked: text2(value.bot?.idMasked, "\u673A\u5668\u4EBA\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58", 140)
@@ -5489,8 +5788,8 @@ var normalizeSnapshot2 = api.normalizeSnapshot;
5489
5788
  var presentError2 = api.presentError;
5490
5789
 
5491
5790
  // 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) {
5791
+ var React14 = __toESM(require("react"), 1);
5792
+ var Button3 = React14.forwardRef(function Button4({ children, kind = "secondary", className = "", ...props }, ref) {
5494
5793
  return h2("button", {
5495
5794
  ...props,
5496
5795
  ref,
@@ -5542,7 +5841,7 @@ function createTokenChannelSettings(definition) {
5542
5841
  AccountSettings = null,
5543
5842
  accountSettingsEndpoint = null
5544
5843
  } = definition;
5545
- function AccountCard6({ account, busy, testNotice, removing, onReconnect, onWorkspaceSave, onModelSave, onAgentPresetSave, onContextEnhancementSave, onAccountSettingsSave, onRequestRemove, onConfirmRemove, onCancelRemove }) {
5844
+ function AccountCard6({ account, busy, testNotice, removing, onReconnect, onWorkspaceSave, onAliasSave, onModelSave, onAgentPresetSave, onContextEnhancementSave, onAccountSettingsSave, onRequestRemove, onConfirmRemove, onCancelRemove }) {
5546
5845
  const state = busy === "reconnect" ? "connecting" : account.state;
5547
5846
  const tone = account.connected ? "success" : state === "error" ? "error" : "warning";
5548
5847
  const stateLabel2 = account.connected ? "\u8FD0\u884C\u6B63\u5E38" : state === "connecting" ? "\u6B63\u5728\u8FDE\u63A5" : "\u8FDE\u63A5\u672A\u5C31\u7EEA";
@@ -5572,7 +5871,7 @@ function createTokenChannelSettings(definition) {
5572
5871
  h2(
5573
5872
  "div",
5574
5873
  { className: "dim-botName" },
5575
- h2("h3", null, account.bot.name),
5874
+ h2(BotName, { bot: account.bot, disabled: Boolean(busy), onSave: onAliasSave }),
5576
5875
  h2("p", null, identity)
5577
5876
  )
5578
5877
  ),
@@ -5684,7 +5983,7 @@ function createTokenChannelSettings(definition) {
5684
5983
  );
5685
5984
  }
5686
5985
  function SettingsTab({ rpcCall }) {
5687
- const [model, setModel] = React13.useState({
5986
+ const [model, setModel] = React14.useState({
5688
5987
  phase: "loading",
5689
5988
  bots: [],
5690
5989
  totals: { configured: 0, connected: 0 },
@@ -5693,15 +5992,15 @@ function createTokenChannelSettings(definition) {
5693
5992
  modelCatalog: EMPTY_MODEL_CATALOG,
5694
5993
  permissions: null
5695
5994
  });
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);
5995
+ const [credentialOpen, setCredentialOpen] = React14.useState(false);
5996
+ const [credentialError, setCredentialError] = React14.useState(null);
5997
+ const [busy, setBusy] = React14.useState(false);
5998
+ const [busyByBot, setBusyByBot] = React14.useState({});
5999
+ const [testNoticeByBot, setTestNoticeByBot] = React14.useState({});
6000
+ const [removeTarget, setRemoveTarget] = React14.useState(null);
6001
+ const mounted = React14.useRef(true);
5703
6002
  const workspaceFence = useWorkspaceSnapshotFence();
5704
- React13.useEffect(() => {
6003
+ React14.useEffect(() => {
5705
6004
  const disposeDingtalk = installDingtalkStyles();
5706
6005
  const disposeChannel = installStyles();
5707
6006
  mounted.current = true;
@@ -5711,11 +6010,11 @@ function createTokenChannelSettings(definition) {
5711
6010
  disposeDingtalk();
5712
6011
  };
5713
6012
  }, []);
5714
- const invoke = React13.useCallback(async (endpoint, payload = {}, signal) => {
6013
+ const invoke = React14.useCallback(async (endpoint, payload = {}, signal) => {
5715
6014
  if (typeof rpcCall !== "function") throw new TypeError(`${channel5} \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5`);
5716
6015
  return api5.unwrapRpcResult(await rpcCall(endpoint, payload, signal));
5717
6016
  }, [rpcCall]);
5718
- const loadStatus = React13.useCallback(async ({ signal, silent = false } = {}) => {
6017
+ const loadStatus = React14.useCallback(async ({ signal, silent = false } = {}) => {
5719
6018
  const workspaceVersion = workspaceFence.beginStatus();
5720
6019
  if (workspaceVersion === null) return;
5721
6020
  if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
@@ -5741,12 +6040,12 @@ function createTokenChannelSettings(definition) {
5741
6040
  }
5742
6041
  }
5743
6042
  }, [invoke, workspaceFence]);
5744
- React13.useEffect(() => {
6043
+ React14.useEffect(() => {
5745
6044
  const controller = new AbortController();
5746
6045
  void loadStatus({ signal: controller.signal });
5747
6046
  return () => controller.abort();
5748
6047
  }, [loadStatus]);
5749
- React13.useEffect(() => {
6048
+ React14.useEffect(() => {
5750
6049
  if (model.phase !== "ready") return void 0;
5751
6050
  const controller = new AbortController();
5752
6051
  const timer = window.setInterval(
@@ -5758,7 +6057,7 @@ function createTokenChannelSettings(definition) {
5758
6057
  window.clearInterval(timer);
5759
6058
  };
5760
6059
  }, [loadStatus, model.phase]);
5761
- const bindCredentials = React13.useCallback(async (values) => {
6060
+ const bindCredentials = React14.useCallback(async (values) => {
5762
6061
  const snapshotVersion = workspaceFence.beginMutation();
5763
6062
  setBusy(true);
5764
6063
  setCredentialError(null);
@@ -5788,7 +6087,7 @@ function createTokenChannelSettings(definition) {
5788
6087
  if (mounted.current) setBusy(false);
5789
6088
  }
5790
6089
  }, [invoke, loadStatus, workspaceFence]);
5791
- const botAction = React13.useCallback(async (account, operation, endpoint, payload) => {
6090
+ const botAction = React14.useCallback(async (account, operation, endpoint, payload) => {
5792
6091
  const snapshotVersion = workspaceFence.beginMutation();
5793
6092
  setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
5794
6093
  try {
@@ -5853,6 +6152,12 @@ function createTokenChannelSettings(definition) {
5853
6152
  endpoints.setWorkspace,
5854
6153
  { botId: account.botId, workspace }
5855
6154
  ),
6155
+ onAliasSave: (alias) => botAction(
6156
+ account,
6157
+ "alias",
6158
+ endpoints.setAlias,
6159
+ { botId: account.botId, alias }
6160
+ ),
5856
6161
  onModelSave: (selectedModel) => botAction(
5857
6162
  account,
5858
6163
  "model",
@@ -5940,7 +6245,7 @@ function createTokenChannelSettings(definition) {
5940
6245
  h2(Button3, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
5941
6246
  )
5942
6247
  ) : h2(
5943
- React13.Fragment,
6248
+ React14.Fragment,
5944
6249
  null,
5945
6250
  credentialOpen ? CredentialPanel ? h2(CredentialPanel, {
5946
6251
  channel: channel5,
@@ -6043,7 +6348,7 @@ var DiscordSettingsTab = channel.SettingsTab;
6043
6348
  var DiscordAccountCard = channel.AccountCard;
6044
6349
 
6045
6350
  // plugin-src/client/channels/feishu/index.js
6046
- var React15 = __toESM(require("react"), 1);
6351
+ var React16 = __toESM(require("react"), 1);
6047
6352
 
6048
6353
  // src/channels/feishu/step-push-mode.mjs
6049
6354
  var FEISHU_STEP_PUSH_MODES = Object.freeze({
@@ -6073,6 +6378,7 @@ var FEISHU_ENDPOINTS = Object.freeze({
6073
6378
  setAgentPreset: "bot.preset.set",
6074
6379
  setContextEnhancement: "bot.context-enhancement.set",
6075
6380
  setAccessPolicy: "bot.access-policy.set",
6381
+ setAlias: "bot.alias.set",
6076
6382
  setGroupResponseMode: "bot.group-response-mode.set",
6077
6383
  setGroupTopicReply: "bot.group-topic-reply.set",
6078
6384
  setStepPush: "bot.step-push.set",
@@ -6178,6 +6484,7 @@ function normalizeProvisioning2(value, now = Date.now()) {
6178
6484
  function normalizeBot2(value) {
6179
6485
  const source = isRecord3(value) ? value : {};
6180
6486
  return {
6487
+ ...normalizeBotAlias(source),
6181
6488
  name: optionalString2(source.name) ?? "\u98DE\u4E66\u673A\u5668\u4EBA",
6182
6489
  avatarUrl: optionalString2(source.avatarUrl),
6183
6490
  appIdMasked: optionalString2(source.appIdMasked),
@@ -6326,7 +6633,7 @@ function formatRemaining2(milliseconds) {
6326
6633
  }
6327
6634
 
6328
6635
  // plugin-src/client/lifecycle.js
6329
- var React14 = __toESM(require("react"), 1);
6636
+ var React15 = __toESM(require("react"), 1);
6330
6637
  function createPollScheduler({ setTimeoutFn, clearTimeoutFn }) {
6331
6638
  let disposed = false;
6332
6639
  let timer;
@@ -6388,8 +6695,8 @@ function createAnimationFrameScheduler({ requestFrame, cancelFrame }) {
6388
6695
  };
6389
6696
  }
6390
6697
  function useAnimationFrameScheduler() {
6391
- const schedulerRef = React14.useRef(null);
6392
- React14.useEffect(() => {
6698
+ const schedulerRef = React15.useRef(null);
6699
+ React15.useEffect(() => {
6393
6700
  const scheduler = createAnimationFrameScheduler({
6394
6701
  requestFrame: (callback) => window.requestAnimationFrame(callback),
6395
6702
  cancelFrame: (frame) => window.cancelAnimationFrame(frame)
@@ -6400,7 +6707,7 @@ function useAnimationFrameScheduler() {
6400
6707
  if (schedulerRef.current === scheduler) schedulerRef.current = null;
6401
6708
  };
6402
6709
  }, []);
6403
- return React14.useCallback(
6710
+ return React15.useCallback(
6404
6711
  (callback, key) => schedulerRef.current?.schedule(callback, key) ?? false,
6405
6712
  []
6406
6713
  );
@@ -6475,7 +6782,7 @@ function QrIcon({ size = 58 }) {
6475
6782
  fill: "currentColor"
6476
6783
  }));
6477
6784
  }
6478
- var Button5 = React15.forwardRef(function Button6({ children, kind = "secondary", size, icon, className = "", ...props }, ref) {
6785
+ var Button5 = React16.forwardRef(function Button6({ children, kind = "secondary", size, icon, className = "", ...props }, ref) {
6479
6786
  return h2("button", {
6480
6787
  ...props,
6481
6788
  ref,
@@ -6592,7 +6899,7 @@ function safeQrSource2(value) {
6592
6899
  return /^data:image\/(?:png|webp|svg\+xml)(?:;charset=[^;,]+)?;base64,/i.test(value) ? value : void 0;
6593
6900
  }
6594
6901
  function QrPane({ provision, now, onRefresh, onCancel, busy }) {
6595
- const [imageFailed, setImageFailed] = React15.useState(false);
6902
+ const [imageFailed, setImageFailed] = React16.useState(false);
6596
6903
  const qrSource = safeQrSource2(provision.qrCodeDataUrl);
6597
6904
  const href = safeVerificationHref(provision.verificationUrl);
6598
6905
  const remaining = Math.max(0, provision.expiresAt - now);
@@ -6601,7 +6908,7 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
6601
6908
  const repairing = isCallbackRepair(provision);
6602
6909
  const grantingGroupMessages = isGroupMessagePermission(provision);
6603
6910
  const botName = provision.botName ?? "\u6B64\u673A\u5668\u4EBA";
6604
- React15.useEffect(() => setImageFailed(false), [qrSource]);
6911
+ React16.useEffect(() => setImageFailed(false), [qrSource]);
6605
6912
  return h2(
6606
6913
  "div",
6607
6914
  { className: "bxf-card bxf-provisionCard dim-surfaceCard" },
@@ -6764,11 +7071,11 @@ function connectionTestNotice2(value) {
6764
7071
  return value?.testMessage ? "\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002" : null;
6765
7072
  }
6766
7073
  function RemoveConfirmation2({ bot, busy, onConfirm, onCancel }) {
6767
- const cancelRef = React15.useRef(null);
7074
+ const cancelRef = React16.useRef(null);
6768
7075
  const idPart = bot.botId.replace(/[^a-zA-Z0-9_-]/g, "-");
6769
7076
  const titleId = `bxf-remove-title-${idPart}`;
6770
7077
  const descriptionId = `bxf-remove-description-${idPart}`;
6771
- React15.useEffect(() => cancelRef.current?.focus(), []);
7078
+ React16.useEffect(() => cancelRef.current?.focus(), []);
6772
7079
  return h2(
6773
7080
  "div",
6774
7081
  {
@@ -6802,11 +7109,11 @@ function RemoveConfirmation2({ bot, busy, onConfirm, onCancel }) {
6802
7109
  );
6803
7110
  }
6804
7111
  function StepPushEditor({ value = false, mode = "post", disabled = false, onSave, onModeSave }) {
6805
- const titleId = React15.useId();
7112
+ const titleId = React16.useId();
6806
7113
  const helpId = `${titleId}-help`;
6807
7114
  const current = value === true ? mode : "off";
6808
- const [saving, setSaving] = React15.useState(false);
6809
- const [error, setError] = React15.useState(null);
7115
+ const [saving, setSaving] = React16.useState(false);
7116
+ const [error, setError] = React16.useState(null);
6810
7117
  const save = async (run) => {
6811
7118
  if (saving || disabled) return;
6812
7119
  setSaving(true);
@@ -6896,6 +7203,7 @@ function BotCard({
6896
7203
  onReconnect,
6897
7204
  onRepairCallback,
6898
7205
  onWorkspaceSave,
7206
+ onAliasSave,
6899
7207
  onModelSave,
6900
7208
  onAgentPresetSave,
6901
7209
  onContextEnhancementSave,
@@ -6908,7 +7216,7 @@ function BotCard({
6908
7216
  removeButtonRef
6909
7217
  }) {
6910
7218
  const { bot, health, state, connected } = connection;
6911
- const repairTooltipId = React15.useId();
7219
+ const repairTooltipId = React16.useId();
6912
7220
  const stateForDisplay = busy === "reconnect" ? "connecting" : state;
6913
7221
  const tone = stateForDisplay === "connected" ? "success" : stateForDisplay === "connecting" ? "warning" : "error";
6914
7222
  const summary2 = actionError?.message ?? connection.error?.message ?? (connected ? null : health.summary);
@@ -6943,7 +7251,7 @@ function BotCard({
6943
7251
  h2(
6944
7252
  "div",
6945
7253
  { className: "bxf-botName dim-botName" },
6946
- h2("h3", { id: titleId, title: bot.name }, bot.name),
7254
+ h2(BotName, { bot, id: titleId, disabled: Boolean(busy), onSave: onAliasSave }),
6947
7255
  h2("p", { title: bot.appIdMasked }, bot.appIdMasked ?? "\u5E94\u7528\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58")
6948
7256
  )
6949
7257
  ),
@@ -7117,6 +7425,7 @@ function BotList(props) {
7117
7425
  onReconnect: () => props.onReconnect(bot),
7118
7426
  onRepairCallback: () => props.onRepairCallback(bot),
7119
7427
  onWorkspaceSave: (workspace) => props.onWorkspaceSave(bot, workspace),
7428
+ onAliasSave: (alias) => props.onAliasSave(bot, alias),
7120
7429
  onModelSave: (model) => props.onModelSave(bot, model),
7121
7430
  onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(bot, agentPreset),
7122
7431
  onContextEnhancementSave: (config) => props.onContextEnhancementSave(bot, config),
@@ -7185,7 +7494,7 @@ function mergeFeishuSnapshotState(current, snapshot, { restoreProvisioning = fal
7185
7494
  };
7186
7495
  }
7187
7496
  function FeishuSettingsTab({ rpcCall }) {
7188
- const [model, setModel] = React15.useState({
7497
+ const [model, setModel] = React16.useState({
7189
7498
  phase: "loading",
7190
7499
  revision: 0,
7191
7500
  bots: [],
@@ -7196,41 +7505,41 @@ function FeishuSettingsTab({ rpcCall }) {
7196
7505
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
7197
7506
  modelCatalog: EMPTY_MODEL_CATALOG
7198
7507
  });
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);
7508
+ const [pageBusy, setPageBusy] = React16.useState(false);
7509
+ const [provisionBusy, setProvisionBusy] = React16.useState(false);
7510
+ const [credentialOpen, setCredentialOpen] = React16.useState(false);
7511
+ const [credentialBusy, setCredentialBusy] = React16.useState(false);
7512
+ const [credentialError, setCredentialError] = React16.useState(null);
7513
+ const [busyByBot, setBusyByBot] = React16.useState({});
7514
+ const [errorsByBot, setErrorsByBot] = React16.useState({});
7515
+ const [testNoticesByBot, setTestNoticesByBot] = React16.useState({});
7516
+ const [removeTargetId, setRemoveTargetId] = React16.useState(null);
7517
+ const [announcement, setAnnouncement] = React16.useState("");
7518
+ const [now, setNow] = React16.useState(() => Date.now());
7519
+ const [focusBotId, setFocusBotId] = React16.useState(null);
7520
+ const cardRefs = React16.useRef(/* @__PURE__ */ new Map());
7521
+ const removeButtonRefs = React16.useRef(/* @__PURE__ */ new Map());
7522
+ const targetedProvisionRef = React16.useRef(null);
7523
+ const addButtonRef = React16.useRef(null);
7524
+ const mountedRef = React16.useRef(true);
7216
7525
  const workspaceFence = useWorkspaceSnapshotFence();
7217
7526
  const scheduleAnimationFrame = useAnimationFrameScheduler();
7218
- React15.useEffect(() => {
7527
+ React16.useEffect(() => {
7219
7528
  mountedRef.current = true;
7220
7529
  return () => {
7221
7530
  mountedRef.current = false;
7222
7531
  };
7223
7532
  }, []);
7224
- const announce = React15.useCallback((message) => {
7533
+ const announce = React16.useCallback((message) => {
7225
7534
  setAnnouncement("");
7226
7535
  scheduleAnimationFrame(() => {
7227
7536
  if (message) setAnnouncement(message);
7228
7537
  }, "announcement");
7229
7538
  }, [scheduleAnimationFrame]);
7230
- const invoke = React15.useCallback(async (endpoint, payload = {}, signal) => {
7539
+ const invoke = React16.useCallback(async (endpoint, payload = {}, signal) => {
7231
7540
  return unwrapRpcResult3(await rpcCall(endpoint, payload, signal));
7232
7541
  }, [rpcCall]);
7233
- const mergeSnapshot = React15.useCallback((snapshot, { restoreProvisioning = false } = {}) => {
7542
+ const mergeSnapshot = React16.useCallback((snapshot, { restoreProvisioning = false } = {}) => {
7234
7543
  const now2 = Date.now();
7235
7544
  setModel((current) => mergeFeishuSnapshotState(
7236
7545
  current,
@@ -7238,7 +7547,7 @@ function FeishuSettingsTab({ rpcCall }) {
7238
7547
  { restoreProvisioning, now: now2 }
7239
7548
  ));
7240
7549
  }, []);
7241
- const loadStatus = React15.useCallback(async ({ signal, silent = false, restoreProvisioning = false } = {}) => {
7550
+ const loadStatus = React16.useCallback(async ({ signal, silent = false, restoreProvisioning = false } = {}) => {
7242
7551
  const workspaceVersion = workspaceFence.beginStatus();
7243
7552
  if (workspaceVersion === null || !mountedRef.current) return void 0;
7244
7553
  if (!silent) setPageBusy(true);
@@ -7256,12 +7565,12 @@ function FeishuSettingsTab({ rpcCall }) {
7256
7565
  if (!silent && !signal?.aborted && mountedRef.current) setPageBusy(false);
7257
7566
  }
7258
7567
  }, [invoke, mergeSnapshot, workspaceFence]);
7259
- React15.useEffect(() => {
7568
+ React16.useEffect(() => {
7260
7569
  const controller = new AbortController();
7261
7570
  void loadStatus({ signal: controller.signal, restoreProvisioning: true });
7262
7571
  return () => controller.abort();
7263
7572
  }, [loadStatus]);
7264
- React15.useEffect(() => {
7573
+ React16.useEffect(() => {
7265
7574
  if (model.phase !== "ready") return void 0;
7266
7575
  const controller = new AbortController();
7267
7576
  let inFlight = false;
@@ -7280,7 +7589,7 @@ function FeishuSettingsTab({ rpcCall }) {
7280
7589
  window.clearInterval(timer);
7281
7590
  };
7282
7591
  }, [loadStatus, model.phase]);
7283
- React15.useEffect(() => {
7592
+ React16.useEffect(() => {
7284
7593
  if (!focusBotId) return;
7285
7594
  const node = cardRefs.current.get(focusBotId);
7286
7595
  if (!node) return;
@@ -7289,7 +7598,7 @@ function FeishuSettingsTab({ rpcCall }) {
7289
7598
  setFocusBotId(null);
7290
7599
  }, [focusBotId, model.bots]);
7291
7600
  const targetedProvisionFocusKey = isTargetedAppUpdate2(model.provisioning) ? `${model.provisioning.botId}:${model.provisioning.attemptId ?? "preparing"}:${model.provisioning.phase}` : null;
7292
- React15.useEffect(() => {
7601
+ React16.useEffect(() => {
7293
7602
  if (!targetedProvisionFocusKey) return;
7294
7603
  scheduleAnimationFrame(() => {
7295
7604
  const node = targetedProvisionRef.current;
@@ -7298,7 +7607,7 @@ function FeishuSettingsTab({ rpcCall }) {
7298
7607
  node.focus?.({ preventScroll: true });
7299
7608
  }, "targeted-provision-focus");
7300
7609
  }, [scheduleAnimationFrame, targetedProvisionFocusKey]);
7301
- const startProvisioning = React15.useCallback(async ({
7610
+ const startProvisioning = React16.useCallback(async ({
7302
7611
  replace = false,
7303
7612
  operation = FEISHU_REGISTRATION_OPERATIONS.PROVISION,
7304
7613
  bot
@@ -7374,7 +7683,7 @@ function FeishuSettingsTab({ rpcCall }) {
7374
7683
  model.provisioning?.botId,
7375
7684
  model.provisioning?.botName
7376
7685
  ]);
7377
- const bindCredentials = React15.useCallback(async ({ identity, secret }) => {
7686
+ const bindCredentials = React16.useCallback(async ({ identity, secret }) => {
7378
7687
  const snapshotVersion = workspaceFence.beginMutation();
7379
7688
  setCredentialBusy(true);
7380
7689
  setCredentialError(null);
@@ -7396,7 +7705,7 @@ function FeishuSettingsTab({ rpcCall }) {
7396
7705
  setCredentialBusy(false);
7397
7706
  }
7398
7707
  }, [announce, invoke, loadStatus, mergeSnapshot, workspaceFence]);
7399
- const cancelProvisioning = React15.useCallback(async () => {
7708
+ const cancelProvisioning = React16.useCallback(async () => {
7400
7709
  const activeProvision = model.provisioning;
7401
7710
  const attemptId = activeProvision?.attemptId;
7402
7711
  const repairing = isCallbackRepair(activeProvision);
@@ -7461,7 +7770,7 @@ function FeishuSettingsTab({ rpcCall }) {
7461
7770
  const countdownPhase = model.provisioning?.phase;
7462
7771
  const countdownExpiresAt = model.provisioning?.expiresAt;
7463
7772
  const countdownExpired = model.provisioning?.expired;
7464
- React15.useEffect(() => {
7773
+ React16.useEffect(() => {
7465
7774
  if (!countdownAttemptId || countdownPhase !== "qr" || countdownExpired) return void 0;
7466
7775
  const tick = () => {
7467
7776
  const timestamp8 = Date.now();
@@ -7474,7 +7783,7 @@ function FeishuSettingsTab({ rpcCall }) {
7474
7783
  const timer = window.setInterval(tick, 1e3);
7475
7784
  return () => window.clearInterval(timer);
7476
7785
  }, [countdownAttemptId, countdownPhase, countdownExpiresAt, countdownExpired]);
7477
- React15.useEffect(() => {
7786
+ React16.useEffect(() => {
7478
7787
  const provision2 = model.provisioning;
7479
7788
  if (!provision2 || !["qr", "connecting"].includes(provision2.phase) || !provision2.attemptId || provision2.expired) return void 0;
7480
7789
  const controller = new AbortController();
@@ -7542,7 +7851,7 @@ function FeishuSettingsTab({ rpcCall }) {
7542
7851
  window.clearTimeout(timer);
7543
7852
  };
7544
7853
  }, [announce, invoke, loadStatus, model.provisioning]);
7545
- const setBotBusy = React15.useCallback((botId, value) => {
7854
+ const setBotBusy = React16.useCallback((botId, value) => {
7546
7855
  setBusyByBot((current) => {
7547
7856
  const next = { ...current };
7548
7857
  if (value) next[botId] = value;
@@ -7550,7 +7859,7 @@ function FeishuSettingsTab({ rpcCall }) {
7550
7859
  return next;
7551
7860
  });
7552
7861
  }, []);
7553
- const setBotError = React15.useCallback((botId, error) => {
7862
+ const setBotError = React16.useCallback((botId, error) => {
7554
7863
  setErrorsByBot((current) => {
7555
7864
  const next = { ...current };
7556
7865
  if (error) next[botId] = presentError3(error);
@@ -7558,7 +7867,7 @@ function FeishuSettingsTab({ rpcCall }) {
7558
7867
  return next;
7559
7868
  });
7560
7869
  }, []);
7561
- const repairCallback = React15.useCallback((connection) => {
7870
+ const repairCallback = React16.useCallback((connection) => {
7562
7871
  if (model.provisioning) return;
7563
7872
  setRemoveTargetId(null);
7564
7873
  setBotError(connection.botId, null);
@@ -7572,7 +7881,7 @@ function FeishuSettingsTab({ rpcCall }) {
7572
7881
  bot: connection
7573
7882
  });
7574
7883
  }, [model.provisioning, setBotError, startProvisioning]);
7575
- const reconnectOneBot = React15.useCallback(async (connection) => {
7884
+ const reconnectOneBot = React16.useCallback(async (connection) => {
7576
7885
  const { botId, bot } = connection;
7577
7886
  const snapshotVersion = workspaceFence.beginMutation();
7578
7887
  setBotBusy(botId, "reconnect");
@@ -7612,7 +7921,7 @@ function FeishuSettingsTab({ rpcCall }) {
7612
7921
  setBotBusy(botId, null);
7613
7922
  }
7614
7923
  }, [announce, invoke, loadStatus, mergeSnapshot, setBotBusy, setBotError, workspaceFence]);
7615
- const saveWorkspace = React15.useCallback(async (connection, workspace) => {
7924
+ const saveWorkspace = React16.useCallback(async (connection, workspace) => {
7616
7925
  const { botId } = connection;
7617
7926
  const workspaceVersion = workspaceFence.beginMutation();
7618
7927
  setBotBusy(botId, "workspace");
@@ -7631,7 +7940,7 @@ function FeishuSettingsTab({ rpcCall }) {
7631
7940
  if (mountedRef.current) setBotBusy(botId, null);
7632
7941
  }
7633
7942
  }, [invoke, loadStatus, mergeSnapshot, setBotBusy, setBotError, workspaceFence]);
7634
- const saveBotSetting = React15.useCallback(async (connection, operation, endpoint, payload) => {
7943
+ const saveBotSetting = React16.useCallback(async (connection, operation, endpoint, payload) => {
7635
7944
  const { botId } = connection;
7636
7945
  const snapshotVersion = workspaceFence.beginMutation();
7637
7946
  setBotBusy(botId, operation);
@@ -7650,15 +7959,15 @@ function FeishuSettingsTab({ rpcCall }) {
7650
7959
  if (mountedRef.current) setBotBusy(botId, null);
7651
7960
  }
7652
7961
  }, [invoke, loadStatus, mergeSnapshot, setBotBusy, setBotError, workspaceFence]);
7653
- const requestRemove = React15.useCallback((connection) => {
7962
+ const requestRemove = React16.useCallback((connection) => {
7654
7963
  setRemoveTargetId(connection.botId);
7655
7964
  }, []);
7656
- const cancelRemove = React15.useCallback(() => {
7965
+ const cancelRemove = React16.useCallback(() => {
7657
7966
  const botId = removeTargetId;
7658
7967
  setRemoveTargetId(null);
7659
7968
  scheduleAnimationFrame(() => removeButtonRefs.current.get(botId)?.focus(), "focus");
7660
7969
  }, [removeTargetId, scheduleAnimationFrame]);
7661
- const confirmRemove = React15.useCallback(async (connection) => {
7970
+ const confirmRemove = React16.useCallback(async (connection) => {
7662
7971
  const { botId, bot } = connection;
7663
7972
  const snapshotVersion = workspaceFence.beginMutation();
7664
7973
  setBotBusy(botId, "delete");
@@ -7744,11 +8053,11 @@ function FeishuSettingsTab({ rpcCall }) {
7744
8053
  setCredentialError(null);
7745
8054
  }
7746
8055
  }) : null;
7747
- const setCardRef = React15.useCallback((botId, node) => {
8056
+ const setCardRef = React16.useCallback((botId, node) => {
7748
8057
  if (node) cardRefs.current.set(botId, node);
7749
8058
  else cardRefs.current.delete(botId);
7750
8059
  }, []);
7751
- const setRemoveButtonRef = React15.useCallback((botId, node) => {
8060
+ const setRemoveButtonRef = React16.useCallback((botId, node) => {
7752
8061
  if (node) removeButtonRefs.current.set(botId, node);
7753
8062
  else removeButtonRefs.current.delete(botId);
7754
8063
  }, []);
@@ -7789,7 +8098,7 @@ function FeishuSettingsTab({ rpcCall }) {
7789
8098
  onRetry: () => void loadStatus(),
7790
8099
  busy: pageBusy
7791
8100
  }) : h2(
7792
- React15.Fragment,
8101
+ React16.Fragment,
7793
8102
  null,
7794
8103
  credentialContent,
7795
8104
  targetedProvisioning ? null : provisionContent,
@@ -7806,6 +8115,12 @@ function FeishuSettingsTab({ rpcCall }) {
7806
8115
  onReconnect: (bot) => void reconnectOneBot(bot),
7807
8116
  onRepairCallback: repairCallback,
7808
8117
  onWorkspaceSave: saveWorkspace,
8118
+ onAliasSave: (connection, alias) => saveBotSetting(
8119
+ connection,
8120
+ "alias",
8121
+ FEISHU_ENDPOINTS.setAlias,
8122
+ { alias }
8123
+ ),
7809
8124
  onModelSave: (connection, selectedModel) => saveBotSetting(
7810
8125
  connection,
7811
8126
  "model",
@@ -8432,7 +8747,8 @@ var QQ_ENDPOINTS = Object.freeze({
8432
8747
  setModel: SET_MODEL_ENDPOINT,
8433
8748
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
8434
8749
  setContextEnhancement: "bot.context-enhancement.set",
8435
- setAccessPolicy: "bot.access-policy.set"
8750
+ setAccessPolicy: "bot.access-policy.set",
8751
+ setAlias: "bot.alias.set"
8436
8752
  });
8437
8753
  var PROVISION_STATES2 = /* @__PURE__ */ new Set(["starting", "pending", "refreshing", "connecting", "connected", "failed", "cancelled"]);
8438
8754
  var ACCOUNT_STATES3 = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
@@ -8501,6 +8817,7 @@ function normalizeBot3(value) {
8501
8817
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
8502
8818
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
8503
8819
  bot: {
8820
+ ...normalizeBotAlias(value.bot),
8504
8821
  name: text3(value.bot?.name, "QQ\u673A\u5668\u4EBA", 100),
8505
8822
  appIdMasked: text3(value.bot?.appIdMasked, "\u5E94\u7528\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58", 140)
8506
8823
  },
@@ -8558,7 +8875,7 @@ function formatRemaining3(milliseconds) {
8558
8875
  }
8559
8876
 
8560
8877
  // plugin-src/client/channels/qq/index.js
8561
- var React16 = __toESM(require("react"), 1);
8878
+ var React17 = __toESM(require("react"), 1);
8562
8879
 
8563
8880
  // plugin-src/client/channels/qq/styles.js
8564
8881
  var QQ_STYLE_ID = "xmanrui-dsh-im-qq-settings";
@@ -8583,7 +8900,7 @@ function installQqStyles() {
8583
8900
 
8584
8901
  // plugin-src/client/channels/qq/index.js
8585
8902
  var ACTIVE_STATES = /* @__PURE__ */ new Set(["pending", "refreshing", "connecting"]);
8586
- var Button7 = React16.forwardRef(function Button8({ children, kind = "secondary", className = "", ...props }, ref) {
8903
+ var Button7 = React17.forwardRef(function Button8({ children, kind = "secondary", className = "", ...props }, ref) {
8587
8904
  return h2("button", {
8588
8905
  ...props,
8589
8906
  ref,
@@ -8797,6 +9114,7 @@ function AccountCard2({
8797
9114
  removing,
8798
9115
  onReconnect,
8799
9116
  onWorkspaceSave,
9117
+ onAliasSave,
8800
9118
  onModelSave,
8801
9119
  onAgentPresetSave,
8802
9120
  onContextEnhancementSave,
@@ -8827,7 +9145,7 @@ function AccountCard2({
8827
9145
  h2(
8828
9146
  "div",
8829
9147
  { className: "dim-botName" },
8830
- h2("h3", null, account.bot.name),
9148
+ h2(BotName, { bot: account.bot, disabled: Boolean(busy), onSave: onAliasSave }),
8831
9149
  h2("p", null, account.bot.appIdMasked)
8832
9150
  )
8833
9151
  ),
@@ -8916,7 +9234,7 @@ function AccountCard2({
8916
9234
  );
8917
9235
  }
8918
9236
  function QqSettingsTab({ rpcCall }) {
8919
- const [model, setModel] = React16.useState({
9237
+ const [model, setModel] = React17.useState({
8920
9238
  phase: "loading",
8921
9239
  bots: [],
8922
9240
  totals: { configured: 0, connected: 0 },
@@ -8924,18 +9242,18 @@ function QqSettingsTab({ rpcCall }) {
8924
9242
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
8925
9243
  modelCatalog: EMPTY_MODEL_CATALOG
8926
9244
  });
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);
9245
+ const [provision, setProvision] = React17.useState(null);
9246
+ const [busy, setBusy] = React17.useState(false);
9247
+ const [busyByBot, setBusyByBot] = React17.useState({});
9248
+ const [feedbackByBot, setFeedbackByBot] = React17.useState({});
9249
+ const [removeTarget, setRemoveTarget] = React17.useState(null);
9250
+ const [credentialOpen, setCredentialOpen] = React17.useState(false);
9251
+ const [credentialError, setCredentialError] = React17.useState(null);
9252
+ const [now, setNow] = React17.useState(Date.now());
9253
+ const mounted = React17.useRef(true);
8936
9254
  const workspaceFence = useWorkspaceSnapshotFence();
8937
- const addButtonRef = React16.useRef(null);
8938
- React16.useEffect(() => {
9255
+ const addButtonRef = React17.useRef(null);
9256
+ React17.useEffect(() => {
8939
9257
  const disposeDingtalk = installDingtalkStyles();
8940
9258
  const disposeQq = installQqStyles();
8941
9259
  mounted.current = true;
@@ -8945,11 +9263,11 @@ function QqSettingsTab({ rpcCall }) {
8945
9263
  disposeDingtalk();
8946
9264
  };
8947
9265
  }, []);
8948
- const invoke = React16.useCallback(async (endpoint, payload = {}, signal) => {
9266
+ const invoke = React17.useCallback(async (endpoint, payload = {}, signal) => {
8949
9267
  if (typeof rpcCall !== "function") throw new TypeError("QQ \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
8950
9268
  return unwrapRpcResult4(await rpcCall(endpoint, payload, signal));
8951
9269
  }, [rpcCall]);
8952
- const loadStatus = React16.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
9270
+ const loadStatus = React17.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
8953
9271
  const workspaceVersion = workspaceFence.beginStatus();
8954
9272
  if (workspaceVersion === null) return void 0;
8955
9273
  if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
@@ -8976,12 +9294,12 @@ function QqSettingsTab({ rpcCall }) {
8976
9294
  return void 0;
8977
9295
  }
8978
9296
  }, [invoke, workspaceFence]);
8979
- React16.useEffect(() => {
9297
+ React17.useEffect(() => {
8980
9298
  const controller = new AbortController();
8981
9299
  void loadStatus({ signal: controller.signal, restore: true });
8982
9300
  return () => controller.abort();
8983
9301
  }, [loadStatus]);
8984
- React16.useEffect(() => {
9302
+ React17.useEffect(() => {
8985
9303
  if (model.phase !== "ready") return void 0;
8986
9304
  const controller = new AbortController();
8987
9305
  const timer = window.setInterval(() => void loadStatus({ signal: controller.signal, silent: true }), 15e3);
@@ -8990,12 +9308,12 @@ function QqSettingsTab({ rpcCall }) {
8990
9308
  window.clearInterval(timer);
8991
9309
  };
8992
9310
  }, [loadStatus, model.phase]);
8993
- React16.useEffect(() => {
9311
+ React17.useEffect(() => {
8994
9312
  if (!provision || !ACTIVE_STATES.has(provision.status)) return void 0;
8995
9313
  const timer = window.setInterval(() => mounted.current && setNow(Date.now()), 1e3);
8996
9314
  return () => window.clearInterval(timer);
8997
9315
  }, [provision?.attemptId, provision?.status]);
8998
- const startProvisioning = React16.useCallback(async (replace = false) => {
9316
+ const startProvisioning = React17.useCallback(async (replace = false) => {
8999
9317
  setCredentialOpen(false);
9000
9318
  setCredentialError(null);
9001
9319
  setBusy(true);
@@ -9013,7 +9331,7 @@ function QqSettingsTab({ rpcCall }) {
9013
9331
  if (mounted.current) setBusy(false);
9014
9332
  }
9015
9333
  }, [invoke, provision?.attemptId]);
9016
- const bindCredentials = React16.useCallback(async ({ identity, secret }) => {
9334
+ const bindCredentials = React17.useCallback(async ({ identity, secret }) => {
9017
9335
  const snapshotVersion = workspaceFence.beginMutation();
9018
9336
  setBusy(true);
9019
9337
  setCredentialError(null);
@@ -9042,7 +9360,7 @@ function QqSettingsTab({ rpcCall }) {
9042
9360
  if (mounted.current) setBusy(false);
9043
9361
  }
9044
9362
  }, [invoke, loadStatus, workspaceFence]);
9045
- const closeProvision = React16.useCallback(async () => {
9363
+ const closeProvision = React17.useCallback(async () => {
9046
9364
  setBusy(true);
9047
9365
  try {
9048
9366
  if (provision?.attemptId && ACTIVE_STATES.has(provision.status)) {
@@ -9053,7 +9371,7 @@ function QqSettingsTab({ rpcCall }) {
9053
9371
  if (mounted.current) setBusy(false);
9054
9372
  }
9055
9373
  }, [invoke, provision?.attemptId, provision?.status]);
9056
- React16.useEffect(() => {
9374
+ React17.useEffect(() => {
9057
9375
  const attemptId = provision?.attemptId;
9058
9376
  if (!attemptId || !ACTIVE_STATES.has(provision.status)) return void 0;
9059
9377
  const controller = new AbortController();
@@ -9083,7 +9401,7 @@ function QqSettingsTab({ rpcCall }) {
9083
9401
  window.clearTimeout(timer);
9084
9402
  };
9085
9403
  }, [invoke, loadStatus, provision?.attemptId, provision?.pollIntervalMs, provision?.status]);
9086
- const botAction = React16.useCallback(async (account, operation, endpoint, payload) => {
9404
+ const botAction = React17.useCallback(async (account, operation, endpoint, payload) => {
9087
9405
  const snapshotVersion = workspaceFence.beginMutation();
9088
9406
  setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
9089
9407
  try {
@@ -9109,7 +9427,7 @@ function QqSettingsTab({ rpcCall }) {
9109
9427
  });
9110
9428
  }
9111
9429
  }, [invoke, loadStatus, workspaceFence]);
9112
- const reconnect = React16.useCallback(async (account) => {
9430
+ const reconnect = React17.useCallback(async (account) => {
9113
9431
  setFeedbackByBot((current) => {
9114
9432
  const next = { ...current };
9115
9433
  delete next[account.botId];
@@ -9172,6 +9490,12 @@ function QqSettingsTab({ rpcCall }) {
9172
9490
  QQ_ENDPOINTS.setWorkspace,
9173
9491
  { botId: account.botId, workspace }
9174
9492
  ),
9493
+ onAliasSave: (alias) => botAction(
9494
+ account,
9495
+ "alias",
9496
+ QQ_ENDPOINTS.setAlias,
9497
+ { botId: account.botId, alias }
9498
+ ),
9175
9499
  onModelSave: (selectedModel) => botAction(
9176
9500
  account,
9177
9501
  "model",
@@ -9232,7 +9556,7 @@ function QqSettingsTab({ rpcCall }) {
9232
9556
  addButtonRef
9233
9557
  }),
9234
9558
  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,
9559
+ React17.Fragment,
9236
9560
  null,
9237
9561
  credentialView,
9238
9562
  provisionView,
@@ -9321,7 +9645,7 @@ function normalizeOfficeStatus(value) {
9321
9645
  }
9322
9646
 
9323
9647
  // plugin-src/client/channels/office/index.js
9324
- var React17 = __toESM(require("react"), 1);
9648
+ var React18 = __toESM(require("react"), 1);
9325
9649
  function Button9({ children, kind = "secondary", ...props }) {
9326
9650
  return h2("button", { ...props, type: "button", className: "ddt-button", "data-kind": kind }, children);
9327
9651
  }
@@ -9350,12 +9674,12 @@ function stateLabel(model) {
9350
9674
  return "\u5DF2\u914D\u7F6E";
9351
9675
  }
9352
9676
  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({
9677
+ const [model, setModel] = React18.useState(normalizeOfficeStatus(initialStatus));
9678
+ const [phase, setPhase] = React18.useState(initialStatus === void 0 ? "loading" : "ready");
9679
+ const [busy, setBusy] = React18.useState("");
9680
+ const [error, setError] = React18.useState("");
9681
+ const [notice, setNotice] = React18.useState("");
9682
+ const [form, setForm] = React18.useState({
9359
9683
  baseUrl: "",
9360
9684
  deviceId: "local-harness",
9361
9685
  deviceToken: "",
@@ -9364,11 +9688,11 @@ function OfficeSettingsTab({ rpcCall, initialStatus }) {
9364
9688
  workspaces: "",
9365
9689
  instructionPresets: ""
9366
9690
  });
9367
- const invoke = React17.useCallback(async (endpoint, payload = {}) => {
9691
+ const invoke = React18.useCallback(async (endpoint, payload = {}) => {
9368
9692
  if (typeof rpcCall !== "function") throw new Error("AI Office \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
9369
9693
  return unwrapOfficeRpc(await rpcCall(endpoint, payload));
9370
9694
  }, [rpcCall]);
9371
- const adopt = React17.useCallback((value) => {
9695
+ const adopt = React18.useCallback((value) => {
9372
9696
  const next = normalizeOfficeStatus(value?.snapshot ?? value);
9373
9697
  setModel(next);
9374
9698
  if (next.config) setForm((current) => ({
@@ -9383,7 +9707,7 @@ function OfficeSettingsTab({ rpcCall, initialStatus }) {
9383
9707
  }));
9384
9708
  return next;
9385
9709
  }, []);
9386
- const load = React17.useCallback(async () => {
9710
+ const load = React18.useCallback(async () => {
9387
9711
  try {
9388
9712
  adopt(await invoke(OFFICE_RPC_ENDPOINTS.status));
9389
9713
  setPhase("ready");
@@ -9393,7 +9717,7 @@ function OfficeSettingsTab({ rpcCall, initialStatus }) {
9393
9717
  setError(caught.message);
9394
9718
  }
9395
9719
  }, [adopt, invoke]);
9396
- React17.useEffect(() => {
9720
+ React18.useEffect(() => {
9397
9721
  void load();
9398
9722
  }, [load]);
9399
9723
  const run = async (name2, operation) => {
@@ -9410,7 +9734,7 @@ function OfficeSettingsTab({ rpcCall, initialStatus }) {
9410
9734
  setBusy("");
9411
9735
  }
9412
9736
  };
9413
- const hooks = React17.useMemo(() => {
9737
+ const hooks = React18.useMemo(() => {
9414
9738
  try {
9415
9739
  return officeHookUrls(form.baseUrl);
9416
9740
  } catch {
@@ -9595,7 +9919,7 @@ var normalizeSnapshot4 = api2.normalizeSnapshot;
9595
9919
  var presentError5 = api2.presentError;
9596
9920
 
9597
9921
  // plugin-src/client/channels/slack/index.js
9598
- var React18 = __toESM(require("react"), 1);
9922
+ var React19 = __toESM(require("react"), 1);
9599
9923
 
9600
9924
  // src/channels/slack/manifest.mjs
9601
9925
  var SLACK_APP_MANIFEST_YAML = `_metadata:
@@ -9673,10 +9997,10 @@ function installSlackStyles() {
9673
9997
 
9674
9998
  // plugin-src/client/channels/slack/index.js
9675
9999
  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();
10000
+ const [botToken, setBotToken] = React19.useState("");
10001
+ const [appToken, setAppToken] = React19.useState("");
10002
+ const [copied, setCopied] = React19.useState(false);
10003
+ const headingId = React19.useId();
9680
10004
  const copyManifest = async () => {
9681
10005
  try {
9682
10006
  await navigator.clipboard.writeText(SLACK_APP_MANIFEST_YAML);
@@ -9874,7 +10198,8 @@ var WECOM_ENDPOINTS = Object.freeze({
9874
10198
  setModel: SET_MODEL_ENDPOINT,
9875
10199
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
9876
10200
  setContextEnhancement: "bot.context-enhancement.set",
9877
- setAccessPolicy: "bot.access-policy.set"
10201
+ setAccessPolicy: "bot.access-policy.set",
10202
+ setAlias: "bot.alias.set"
9878
10203
  });
9879
10204
  var PROVISION_STATES3 = /* @__PURE__ */ new Set(["starting", "pending", "refreshing", "connecting", "connected", "failed", "cancelled"]);
9880
10205
  var ACCOUNT_STATES4 = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
@@ -9949,6 +10274,7 @@ function normalizeBot4(value) {
9949
10274
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
9950
10275
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
9951
10276
  bot: {
10277
+ ...normalizeBotAlias(value.bot),
9952
10278
  name: text4(value.bot?.name, "\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA", 100),
9953
10279
  appIdMasked: text4(value.bot?.appIdMasked, "\u5E94\u7528\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58", 140)
9954
10280
  },
@@ -9989,7 +10315,7 @@ function formatRemaining4(milliseconds) {
9989
10315
  }
9990
10316
 
9991
10317
  // plugin-src/client/channels/wecom/index.js
9992
- var React19 = __toESM(require("react"), 1);
10318
+ var React20 = __toESM(require("react"), 1);
9993
10319
 
9994
10320
  // plugin-src/client/channels/wecom/styles.js
9995
10321
  var WECOM_STYLE_ID = "xmanrui-dsh-im-wecom-settings";
@@ -10014,7 +10340,7 @@ function installWecomStyles() {
10014
10340
 
10015
10341
  // plugin-src/client/channels/wecom/index.js
10016
10342
  var ACTIVE_STATES2 = /* @__PURE__ */ new Set(["pending", "refreshing", "connecting"]);
10017
- var Button10 = React19.forwardRef(function Button11({ children, kind = "secondary", className = "", ...props }, ref) {
10343
+ var Button10 = React20.forwardRef(function Button11({ children, kind = "secondary", className = "", ...props }, ref) {
10018
10344
  return h2("button", {
10019
10345
  ...props,
10020
10346
  ref,
@@ -10228,6 +10554,7 @@ function AccountCard3({
10228
10554
  removing,
10229
10555
  onReconnect,
10230
10556
  onWorkspaceSave,
10557
+ onAliasSave,
10231
10558
  onModelSave,
10232
10559
  onAgentPresetSave,
10233
10560
  onContextEnhancementSave,
@@ -10258,7 +10585,7 @@ function AccountCard3({
10258
10585
  h2(
10259
10586
  "div",
10260
10587
  { className: "dim-botName" },
10261
- h2("h3", null, account.bot.name),
10588
+ h2(BotName, { bot: account.bot, disabled: Boolean(busy), onSave: onAliasSave }),
10262
10589
  h2("p", null, account.bot.appIdMasked)
10263
10590
  )
10264
10591
  ),
@@ -10347,7 +10674,7 @@ function AccountCard3({
10347
10674
  );
10348
10675
  }
10349
10676
  function WecomSettingsTab({ rpcCall }) {
10350
- const [model, setModel] = React19.useState({
10677
+ const [model, setModel] = React20.useState({
10351
10678
  phase: "loading",
10352
10679
  bots: [],
10353
10680
  totals: { configured: 0, connected: 0 },
@@ -10355,20 +10682,20 @@ function WecomSettingsTab({ rpcCall }) {
10355
10682
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
10356
10683
  modelCatalog: EMPTY_MODEL_CATALOG
10357
10684
  });
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);
10685
+ const [provision, setProvision] = React20.useState(null);
10686
+ const [busy, setBusy] = React20.useState(false);
10687
+ const [busyByBot, setBusyByBot] = React20.useState({});
10688
+ const [feedbackByBot, setFeedbackByBot] = React20.useState({});
10689
+ const [removeTarget, setRemoveTarget] = React20.useState(null);
10690
+ const [credentialOpen, setCredentialOpen] = React20.useState(false);
10691
+ const [credentialError, setCredentialError] = React20.useState(null);
10692
+ const [notice, setNotice] = React20.useState("");
10693
+ const [now, setNow] = React20.useState(Date.now());
10694
+ const mounted = React20.useRef(true);
10368
10695
  const workspaceFence = useWorkspaceSnapshotFence();
10369
- const addButtonRef = React19.useRef(null);
10370
- const noticeFrameRef = React19.useRef(null);
10371
- const announce = React19.useCallback((message) => {
10696
+ const addButtonRef = React20.useRef(null);
10697
+ const noticeFrameRef = React20.useRef(null);
10698
+ const announce = React20.useCallback((message) => {
10372
10699
  if (!mounted.current) return;
10373
10700
  if (noticeFrameRef.current !== null) {
10374
10701
  window.cancelAnimationFrame(noticeFrameRef.current);
@@ -10382,7 +10709,7 @@ function WecomSettingsTab({ rpcCall }) {
10382
10709
  });
10383
10710
  }
10384
10711
  }, []);
10385
- React19.useEffect(() => {
10712
+ React20.useEffect(() => {
10386
10713
  const disposeDingtalk = installDingtalkStyles();
10387
10714
  const disposeWecom = installWecomStyles();
10388
10715
  mounted.current = true;
@@ -10396,11 +10723,11 @@ function WecomSettingsTab({ rpcCall }) {
10396
10723
  disposeDingtalk();
10397
10724
  };
10398
10725
  }, []);
10399
- const invoke = React19.useCallback(async (endpoint, payload = {}, signal) => {
10726
+ const invoke = React20.useCallback(async (endpoint, payload = {}, signal) => {
10400
10727
  if (typeof rpcCall !== "function") throw new TypeError("\u4F01\u4E1A\u5FAE\u4FE1\u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
10401
10728
  return unwrapRpcResult7(await rpcCall(endpoint, payload, signal));
10402
10729
  }, [rpcCall]);
10403
- const loadStatus = React19.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
10730
+ const loadStatus = React20.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
10404
10731
  const workspaceVersion = workspaceFence.beginStatus();
10405
10732
  if (workspaceVersion === null) return void 0;
10406
10733
  if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
@@ -10427,12 +10754,12 @@ function WecomSettingsTab({ rpcCall }) {
10427
10754
  return void 0;
10428
10755
  }
10429
10756
  }, [invoke, workspaceFence]);
10430
- React19.useEffect(() => {
10757
+ React20.useEffect(() => {
10431
10758
  const controller = new AbortController();
10432
10759
  void loadStatus({ signal: controller.signal, restore: true });
10433
10760
  return () => controller.abort();
10434
10761
  }, [loadStatus]);
10435
- React19.useEffect(() => {
10762
+ React20.useEffect(() => {
10436
10763
  if (model.phase !== "ready") return void 0;
10437
10764
  const controller = new AbortController();
10438
10765
  const timer = window.setInterval(() => void loadStatus({ signal: controller.signal, silent: true }), 15e3);
@@ -10441,12 +10768,12 @@ function WecomSettingsTab({ rpcCall }) {
10441
10768
  window.clearInterval(timer);
10442
10769
  };
10443
10770
  }, [loadStatus, model.phase]);
10444
- React19.useEffect(() => {
10771
+ React20.useEffect(() => {
10445
10772
  if (!provision || !ACTIVE_STATES2.has(provision.status)) return void 0;
10446
10773
  const timer = window.setInterval(() => mounted.current && setNow(Date.now()), 1e3);
10447
10774
  return () => window.clearInterval(timer);
10448
10775
  }, [provision?.attemptId, provision?.status]);
10449
- const startProvisioning = React19.useCallback(async (replace = false) => {
10776
+ const startProvisioning = React20.useCallback(async (replace = false) => {
10450
10777
  setCredentialOpen(false);
10451
10778
  setCredentialError(null);
10452
10779
  setBusy(true);
@@ -10464,7 +10791,7 @@ function WecomSettingsTab({ rpcCall }) {
10464
10791
  if (mounted.current) setBusy(false);
10465
10792
  }
10466
10793
  }, [invoke, provision?.attemptId]);
10467
- const bindCredentials = React19.useCallback(async ({ identity, secret }) => {
10794
+ const bindCredentials = React20.useCallback(async ({ identity, secret }) => {
10468
10795
  const snapshotVersion = workspaceFence.beginMutation();
10469
10796
  setBusy(true);
10470
10797
  setCredentialError(null);
@@ -10493,7 +10820,7 @@ function WecomSettingsTab({ rpcCall }) {
10493
10820
  if (mounted.current) setBusy(false);
10494
10821
  }
10495
10822
  }, [invoke, loadStatus, workspaceFence]);
10496
- const closeProvision = React19.useCallback(async () => {
10823
+ const closeProvision = React20.useCallback(async () => {
10497
10824
  setBusy(true);
10498
10825
  try {
10499
10826
  if (provision?.attemptId && ACTIVE_STATES2.has(provision.status)) {
@@ -10504,7 +10831,7 @@ function WecomSettingsTab({ rpcCall }) {
10504
10831
  if (mounted.current) setBusy(false);
10505
10832
  }
10506
10833
  }, [invoke, provision?.attemptId, provision?.status]);
10507
- React19.useEffect(() => {
10834
+ React20.useEffect(() => {
10508
10835
  const attemptId = provision?.attemptId;
10509
10836
  if (!attemptId || !ACTIVE_STATES2.has(provision.status)) return void 0;
10510
10837
  const controller = new AbortController();
@@ -10534,7 +10861,7 @@ function WecomSettingsTab({ rpcCall }) {
10534
10861
  window.clearTimeout(timer);
10535
10862
  };
10536
10863
  }, [invoke, loadStatus, provision?.attemptId, provision?.pollIntervalMs, provision?.status]);
10537
- const botAction = React19.useCallback(async (account, operation, endpoint, payload) => {
10864
+ const botAction = React20.useCallback(async (account, operation, endpoint, payload) => {
10538
10865
  const snapshotVersion = workspaceFence.beginMutation();
10539
10866
  setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
10540
10867
  try {
@@ -10560,7 +10887,7 @@ function WecomSettingsTab({ rpcCall }) {
10560
10887
  });
10561
10888
  }
10562
10889
  }, [invoke, loadStatus, workspaceFence]);
10563
- const reconnect = React19.useCallback(async (account) => {
10890
+ const reconnect = React20.useCallback(async (account) => {
10564
10891
  setFeedbackByBot((current) => {
10565
10892
  const next = { ...current };
10566
10893
  delete next[account.botId];
@@ -10634,6 +10961,12 @@ function WecomSettingsTab({ rpcCall }) {
10634
10961
  WECOM_ENDPOINTS.setWorkspace,
10635
10962
  { botId: account.botId, workspace }
10636
10963
  ),
10964
+ onAliasSave: (alias) => botAction(
10965
+ account,
10966
+ "alias",
10967
+ WECOM_ENDPOINTS.setAlias,
10968
+ { botId: account.botId, alias }
10969
+ ),
10637
10970
  onModelSave: (selectedModel) => botAction(
10638
10971
  account,
10639
10972
  "model",
@@ -10695,7 +11028,7 @@ function WecomSettingsTab({ rpcCall }) {
10695
11028
  }),
10696
11029
  h2("div", { className: "ddt-visuallyHidden", role: "status", "aria-live": "polite" }, notice),
10697
11030
  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,
11031
+ React20.Fragment,
10699
11032
  null,
10700
11033
  credentialView,
10701
11034
  provisionView,
@@ -10718,7 +11051,8 @@ var WECOM_APP_ENDPOINTS = Object.freeze({
10718
11051
  setModel: SET_MODEL_ENDPOINT,
10719
11052
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
10720
11053
  setContextEnhancement: "bot.context-enhancement.set",
10721
- setAccessPolicy: "bot.access-policy.set"
11054
+ setAccessPolicy: "bot.access-policy.set",
11055
+ setAlias: "bot.alias.set"
10722
11056
  });
10723
11057
  var ACCOUNT_STATES5 = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
10724
11058
  function isRecord6(value) {
@@ -10770,6 +11104,7 @@ function normalizeBot5(value) {
10770
11104
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
10771
11105
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
10772
11106
  bot: {
11107
+ ...normalizeBotAlias(value.bot),
10773
11108
  name: text5(value.bot?.name, "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528", 100),
10774
11109
  corpIdMasked: text5(value.bot?.corpIdMasked, "\u4F01\u4E1A ID \u5DF2\u4FDD\u5B58", 140),
10775
11110
  agentId: text5(value.bot?.agentId, "", 32),
@@ -10810,7 +11145,7 @@ function presentError8(error) {
10810
11145
  }
10811
11146
 
10812
11147
  // plugin-src/client/channels/wecom-app/index.js
10813
- var React20 = __toESM(require("react"), 1);
11148
+ var React21 = __toESM(require("react"), 1);
10814
11149
 
10815
11150
  // plugin-src/client/channels/wecom-app/styles.js
10816
11151
  var WECOM_APP_STYLE_ID = "xmanrui-dsh-im-wecom-app-settings";
@@ -10840,7 +11175,7 @@ function installWecomAppStyles() {
10840
11175
  }
10841
11176
 
10842
11177
  // plugin-src/client/channels/wecom-app/index.js
10843
- var Button12 = React20.forwardRef(function Button13({ children, kind = "secondary", className = "", ...props }, ref) {
11178
+ var Button12 = React21.forwardRef(function Button13({ children, kind = "secondary", className = "", ...props }, ref) {
10844
11179
  return h2("button", {
10845
11180
  ...props,
10846
11181
  ref,
@@ -10948,16 +11283,16 @@ function Field({ label, value, onChange, placeholder, busy, required = false, ty
10948
11283
  );
10949
11284
  }
10950
11285
  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);
11286
+ const [corpId, setCorpId] = React21.useState("");
11287
+ const [agentId, setAgentId] = React21.useState("");
11288
+ const [secret, setSecret] = React21.useState("");
11289
+ const [token, setToken] = React21.useState("");
11290
+ const [aesKey, setAesKey] = React21.useState("");
11291
+ const [apiBaseUrl, setApiBaseUrl] = React21.useState("");
11292
+ const [callbackBaseUrl, setCallbackBaseUrl] = React21.useState("");
11293
+ const [streamEnabled, setStreamEnabled] = React21.useState(true);
11294
+ const headingId = React21.useId();
11295
+ const formRef = React21.useRef(null);
10961
11296
  const submit = (event) => {
10962
11297
  event.preventDefault();
10963
11298
  if (busy) return;
@@ -11020,7 +11355,7 @@ function BindForm({ busy, error, onSubmit, onCancel }) {
11020
11355
  );
11021
11356
  }
11022
11357
  function CallbackUrlBox({ url, busy, resetBusy, onCopy, onReset }) {
11023
- const [copied, setCopied] = React20.useState(false);
11358
+ const [copied, setCopied] = React21.useState(false);
11024
11359
  const copy = async () => {
11025
11360
  try {
11026
11361
  await navigator.clipboard.writeText(url);
@@ -11054,12 +11389,12 @@ function CallbackUrlBox({ url, busy, resetBusy, onCopy, onReset }) {
11054
11389
  );
11055
11390
  }
11056
11391
  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(() => {
11392
+ const [apiBaseUrl, setApiBaseUrl] = React21.useState(bot.apiBaseUrl ?? "");
11393
+ const [callbackBaseUrl, setCallbackBaseUrl] = React21.useState(bot.callbackBaseUrl ?? "");
11394
+ const [streamEnabled, setStreamEnabled] = React21.useState(bot.streamEnabled !== false);
11395
+ const [dirty, setDirty] = React21.useState(false);
11396
+ const formRef = React21.useRef(null);
11397
+ React21.useEffect(() => {
11063
11398
  setApiBaseUrl(bot.apiBaseUrl ?? "");
11064
11399
  setCallbackBaseUrl(bot.callbackBaseUrl ?? "");
11065
11400
  setStreamEnabled(bot.streamEnabled !== false);
@@ -11131,6 +11466,7 @@ function AccountCard4({
11131
11466
  onSettingsSave,
11132
11467
  onSecretReset,
11133
11468
  onWorkspaceSave,
11469
+ onAliasSave,
11134
11470
  onModelSave,
11135
11471
  onAgentPresetSave,
11136
11472
  onContextEnhancementSave,
@@ -11162,7 +11498,7 @@ function AccountCard4({
11162
11498
  h2(
11163
11499
  "div",
11164
11500
  { className: "dim-botName" },
11165
- h2("h3", null, account.bot.name),
11501
+ h2(BotName, { bot: account.bot, disabled: Boolean(busy), onSave: onAliasSave }),
11166
11502
  h2("p", null, `${account.bot.corpIdMasked} \xB7 AgentId ${account.bot.agentId}`)
11167
11503
  )
11168
11504
  ),
@@ -11261,7 +11597,7 @@ function AccountCard4({
11261
11597
  );
11262
11598
  }
11263
11599
  function WecomAppSettingsTab({ rpcCall }) {
11264
- const [model, setModel] = React20.useState({
11600
+ const [model, setModel] = React21.useState({
11265
11601
  phase: "loading",
11266
11602
  bots: [],
11267
11603
  totals: { configured: 0, connected: 0 },
@@ -11269,18 +11605,18 @@ function WecomAppSettingsTab({ rpcCall }) {
11269
11605
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
11270
11606
  modelCatalog: EMPTY_MODEL_CATALOG
11271
11607
  });
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);
11608
+ const [bindOpen, setBindOpen] = React21.useState(false);
11609
+ const [bindError, setBindError] = React21.useState(null);
11610
+ const [busy, setBusy] = React21.useState(false);
11611
+ const [busyByBot, setBusyByBot] = React21.useState({});
11612
+ const [feedbackByBot, setFeedbackByBot] = React21.useState({});
11613
+ const [removeTarget, setRemoveTarget] = React21.useState(null);
11614
+ const [notice, setNotice] = React21.useState("");
11615
+ const mounted = React21.useRef(true);
11280
11616
  const workspaceFence = useWorkspaceSnapshotFence();
11281
- const addButtonRef = React20.useRef(null);
11282
- const noticeFrameRef = React20.useRef(null);
11283
- const announce = React20.useCallback((message) => {
11617
+ const addButtonRef = React21.useRef(null);
11618
+ const noticeFrameRef = React21.useRef(null);
11619
+ const announce = React21.useCallback((message) => {
11284
11620
  if (!mounted.current) return;
11285
11621
  if (noticeFrameRef.current !== null) {
11286
11622
  window.cancelAnimationFrame(noticeFrameRef.current);
@@ -11294,7 +11630,7 @@ function WecomAppSettingsTab({ rpcCall }) {
11294
11630
  });
11295
11631
  }
11296
11632
  }, []);
11297
- React20.useEffect(() => {
11633
+ React21.useEffect(() => {
11298
11634
  const disposeDingtalk = installDingtalkStyles();
11299
11635
  const disposeWecomApp = installWecomAppStyles();
11300
11636
  mounted.current = true;
@@ -11308,11 +11644,11 @@ function WecomAppSettingsTab({ rpcCall }) {
11308
11644
  disposeDingtalk();
11309
11645
  };
11310
11646
  }, []);
11311
- const invoke = React20.useCallback(async (endpoint, payload = {}, signal) => {
11647
+ const invoke = React21.useCallback(async (endpoint, payload = {}, signal) => {
11312
11648
  if (typeof rpcCall !== "function") throw new TypeError("\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
11313
11649
  return unwrapRpcResult8(await rpcCall(endpoint, payload, signal));
11314
11650
  }, [rpcCall]);
11315
- const loadStatus = React20.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
11651
+ const loadStatus = React21.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
11316
11652
  const workspaceVersion = workspaceFence.beginStatus();
11317
11653
  if (workspaceVersion === null) return void 0;
11318
11654
  if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
@@ -11336,12 +11672,12 @@ function WecomAppSettingsTab({ rpcCall }) {
11336
11672
  return void 0;
11337
11673
  }
11338
11674
  }, [invoke, workspaceFence]);
11339
- React20.useEffect(() => {
11675
+ React21.useEffect(() => {
11340
11676
  const controller = new AbortController();
11341
11677
  void loadStatus({ signal: controller.signal, restore: true });
11342
11678
  return () => controller.abort();
11343
11679
  }, [loadStatus]);
11344
- React20.useEffect(() => {
11680
+ React21.useEffect(() => {
11345
11681
  if (model.phase !== "ready") return void 0;
11346
11682
  const controller = new AbortController();
11347
11683
  const timer = window.setInterval(() => void loadStatus({ signal: controller.signal, silent: true }), 15e3);
@@ -11350,7 +11686,7 @@ function WecomAppSettingsTab({ rpcCall }) {
11350
11686
  window.clearInterval(timer);
11351
11687
  };
11352
11688
  }, [loadStatus, model.phase]);
11353
- const bindApp = React20.useCallback(async (payload) => {
11689
+ const bindApp = React21.useCallback(async (payload) => {
11354
11690
  const snapshotVersion = workspaceFence.beginMutation();
11355
11691
  setBusy(true);
11356
11692
  setBindError(null);
@@ -11377,7 +11713,7 @@ function WecomAppSettingsTab({ rpcCall }) {
11377
11713
  if (mounted.current) setBusy(false);
11378
11714
  }
11379
11715
  }, [announce, invoke, loadStatus, workspaceFence]);
11380
- const botAction = React20.useCallback(async (account, operation, endpoint, payload) => {
11716
+ const botAction = React21.useCallback(async (account, operation, endpoint, payload) => {
11381
11717
  const snapshotVersion = workspaceFence.beginMutation();
11382
11718
  setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
11383
11719
  try {
@@ -11403,7 +11739,7 @@ function WecomAppSettingsTab({ rpcCall }) {
11403
11739
  });
11404
11740
  }
11405
11741
  }, [invoke, loadStatus, workspaceFence]);
11406
- const reconnect = React20.useCallback(async (account) => {
11742
+ const reconnect = React21.useCallback(async (account) => {
11407
11743
  setFeedbackByBot((current) => {
11408
11744
  const next = { ...current };
11409
11745
  delete next[account.botId];
@@ -11476,6 +11812,12 @@ function WecomAppSettingsTab({ rpcCall }) {
11476
11812
  WECOM_APP_ENDPOINTS.setWorkspace,
11477
11813
  { botId: account.botId, workspace }
11478
11814
  ),
11815
+ onAliasSave: (alias) => botAction(
11816
+ account,
11817
+ "alias",
11818
+ WECOM_APP_ENDPOINTS.setAlias,
11819
+ { botId: account.botId, alias }
11820
+ ),
11479
11821
  onModelSave: (selectedModel) => botAction(
11480
11822
  account,
11481
11823
  "model",
@@ -11530,7 +11872,7 @@ function WecomAppSettingsTab({ rpcCall }) {
11530
11872
  }),
11531
11873
  h2("div", { className: "ddt-visuallyHidden", role: "status", "aria-live": "polite" }, notice),
11532
11874
  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,
11875
+ React21.Fragment,
11534
11876
  null,
11535
11877
  bindView,
11536
11878
  model.bots.length === 0 && !bindOpen ? h2(EmptyView5, { busy, onStart: () => setBindOpen(true) }) : null,
@@ -11540,7 +11882,7 @@ function WecomAppSettingsTab({ rpcCall }) {
11540
11882
  }
11541
11883
 
11542
11884
  // plugin-src/client/channels/weixin/index.js
11543
- var React21 = __toESM(require("react"), 1);
11885
+ var React22 = __toESM(require("react"), 1);
11544
11886
 
11545
11887
  // plugin-src/client/channels/weixin/api.js
11546
11888
  var WEIXIN_RPC_CHANNEL = "/weixin";
@@ -11556,7 +11898,8 @@ var WEIXIN_ENDPOINTS = Object.freeze({
11556
11898
  setModel: SET_MODEL_ENDPOINT,
11557
11899
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
11558
11900
  setContextEnhancement: "bot.context-enhancement.set",
11559
- setAccessPolicy: "bot.access-policy.set"
11901
+ setAccessPolicy: "bot.access-policy.set",
11902
+ setAlias: "bot.alias.set"
11560
11903
  });
11561
11904
  var ACCOUNT_STATES6 = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
11562
11905
  var PROVISION_STATES4 = /* @__PURE__ */ new Set([
@@ -11651,6 +11994,7 @@ function normalizeBot6(value) {
11651
11994
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
11652
11995
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
11653
11996
  bot: {
11997
+ ...normalizeBotAlias(value.bot),
11654
11998
  name: string(value.bot.name, "\u5FAE\u4FE1\u673A\u5668\u4EBA"),
11655
11999
  accountIdMasked: string(value.bot.accountIdMasked, "\u5DF2\u5B89\u5168\u4FDD\u5B58")
11656
12000
  },
@@ -11702,7 +12046,7 @@ function formatRemaining5(milliseconds) {
11702
12046
  }
11703
12047
 
11704
12048
  // plugin-src/client/channels/weixin/index.js
11705
- var Button14 = React21.forwardRef(function Button15({ children, kind = "secondary", className = "", ...props }, ref) {
12049
+ var Button14 = React22.forwardRef(function Button15({ children, kind = "secondary", className = "", ...props }, ref) {
11706
12050
  return h2("button", {
11707
12051
  ...props,
11708
12052
  ref,
@@ -11775,14 +12119,14 @@ function EmptyView6({ onStart, busy }) {
11775
12119
  );
11776
12120
  }
11777
12121
  function QrPanel4({ provision, now, busy, onRefresh, onCancel }) {
11778
- const [imageFailed, setImageFailed] = React21.useState(false);
12122
+ const [imageFailed, setImageFailed] = React22.useState(false);
11779
12123
  const source = safeQrSource5(provision.qrCodeDataUrl);
11780
12124
  const href = safeVerificationUrl(provision.verificationUrl);
11781
12125
  const remaining = Math.max(0, provision.expiresAt - now);
11782
12126
  const expired = remaining === 0 || provision.status === "expired";
11783
12127
  const duration = Math.max(1, provision.durationMs ?? 5 * 6e4);
11784
12128
  const progress = Math.round(Math.min(1, remaining / duration) * 100);
11785
- React21.useEffect(() => setImageFailed(false), [source]);
12129
+ React22.useEffect(() => setImageFailed(false), [source]);
11786
12130
  return h2(
11787
12131
  "div",
11788
12132
  { className: "dxw-card dim-surfaceCard" },
@@ -11849,9 +12193,9 @@ function QrPanel4({ provision, now, busy, onRefresh, onCancel }) {
11849
12193
  );
11850
12194
  }
11851
12195
  function VerificationPanel({ provision, busy, onSubmit, onCancel }) {
11852
- const [code, setCode] = React21.useState("");
12196
+ const [code, setCode] = React22.useState("");
11853
12197
  const valid = /^\d{4,8}$/.test(code);
11854
- React21.useEffect(() => setCode(""), [provision.attemptId]);
12198
+ React22.useEffect(() => setCode(""), [provision.attemptId]);
11855
12199
  return h2(
11856
12200
  "div",
11857
12201
  { className: "dxw-card dim-surfaceCard" },
@@ -11949,6 +12293,7 @@ function AccountCard5({
11949
12293
  removing,
11950
12294
  onReconnect,
11951
12295
  onWorkspaceSave,
12296
+ onAliasSave,
11952
12297
  onModelSave,
11953
12298
  onAgentPresetSave,
11954
12299
  onContextEnhancementSave,
@@ -11976,7 +12321,7 @@ function AccountCard5({
11976
12321
  "div",
11977
12322
  { className: "dxw-accountIdentity dim-botIdentity" },
11978
12323
  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))
12324
+ h2("div", { className: "dim-botName" }, h2(BotName, { bot: account.bot, disabled: Boolean(busy), onSave: onAliasSave }), h2("p", null, account.bot.accountIdMasked))
11980
12325
  ),
11981
12326
  h2(
11982
12327
  "div",
@@ -12096,6 +12441,7 @@ function AccountList2(props) {
12096
12441
  removing: props.removeTarget === account.botId,
12097
12442
  onReconnect: () => props.onReconnect(account),
12098
12443
  onWorkspaceSave: (workspace) => props.onWorkspaceSave(account, workspace),
12444
+ onAliasSave: (alias) => props.onAliasSave(account, alias),
12099
12445
  onModelSave: (model) => props.onModelSave(account, model),
12100
12446
  onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(account, agentPreset),
12101
12447
  onContextEnhancementSave: (config) => props.onContextEnhancementSave(account, config),
@@ -12117,7 +12463,7 @@ function mergeWeixinProvisioningSnapshot(current, incoming, { restoreProvisionin
12117
12463
  };
12118
12464
  }
12119
12465
  function WeixinSettingsTab({ rpcCall }) {
12120
- const [model, setModel] = React21.useState({
12466
+ const [model, setModel] = React22.useState({
12121
12467
  phase: "loading",
12122
12468
  bots: [],
12123
12469
  totals: EMPTY_TOTALS3,
@@ -12126,33 +12472,33 @@ function WeixinSettingsTab({ rpcCall }) {
12126
12472
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
12127
12473
  modelCatalog: EMPTY_MODEL_CATALOG
12128
12474
  });
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);
12475
+ const [provision, setProvision] = React22.useState(null);
12476
+ const [busy, setBusy] = React22.useState(false);
12477
+ const [busyByBot, setBusyByBot] = React22.useState({});
12478
+ const [feedbackByBot, setFeedbackByBot] = React22.useState({});
12479
+ const [removeTarget, setRemoveTarget] = React22.useState(null);
12480
+ const [notice, setNotice] = React22.useState("");
12481
+ const [now, setNow] = React22.useState(() => Date.now());
12482
+ const addButtonRef = React22.useRef(null);
12483
+ const mountedRef = React22.useRef(true);
12138
12484
  const workspaceFence = useWorkspaceSnapshotFence();
12139
12485
  const scheduleAnimationFrame = useAnimationFrameScheduler();
12140
- React21.useEffect(() => {
12486
+ React22.useEffect(() => {
12141
12487
  mountedRef.current = true;
12142
12488
  return () => {
12143
12489
  mountedRef.current = false;
12144
12490
  };
12145
12491
  }, []);
12146
- const announce = React21.useCallback((value) => {
12492
+ const announce = React22.useCallback((value) => {
12147
12493
  setNotice("");
12148
12494
  scheduleAnimationFrame(() => {
12149
12495
  if (value) setNotice(value);
12150
12496
  }, "announcement");
12151
12497
  }, [scheduleAnimationFrame]);
12152
- const invoke = React21.useCallback(async (endpoint, payload = {}, signal) => {
12498
+ const invoke = React22.useCallback(async (endpoint, payload = {}, signal) => {
12153
12499
  return unwrapRpcResult9(await rpcCall(endpoint, payload, signal));
12154
12500
  }, [rpcCall]);
12155
- const loadStatus = React21.useCallback(async ({
12501
+ const loadStatus = React22.useCallback(async ({
12156
12502
  signal,
12157
12503
  silent = false,
12158
12504
  restoreProvisioning = false
@@ -12190,12 +12536,12 @@ function WeixinSettingsTab({ rpcCall }) {
12190
12536
  return void 0;
12191
12537
  }
12192
12538
  }, [invoke, workspaceFence]);
12193
- React21.useEffect(() => {
12539
+ React22.useEffect(() => {
12194
12540
  const controller = new AbortController();
12195
12541
  void loadStatus({ signal: controller.signal, restoreProvisioning: true });
12196
12542
  return () => controller.abort();
12197
12543
  }, [loadStatus]);
12198
- React21.useEffect(() => {
12544
+ React22.useEffect(() => {
12199
12545
  if (model.phase !== "ready") return void 0;
12200
12546
  const controller = new AbortController();
12201
12547
  let running = false;
@@ -12214,12 +12560,12 @@ function WeixinSettingsTab({ rpcCall }) {
12214
12560
  window.clearInterval(timer);
12215
12561
  };
12216
12562
  }, [loadStatus, model.phase]);
12217
- React21.useEffect(() => {
12563
+ React22.useEffect(() => {
12218
12564
  if (!provision || !["pending", "scanned"].includes(provision.status)) return void 0;
12219
12565
  const timer = window.setInterval(() => setNow(Date.now()), 1e3);
12220
12566
  return () => window.clearInterval(timer);
12221
12567
  }, [provision?.attemptId, provision?.status]);
12222
- const startProvisioning = React21.useCallback(async ({ replace = false } = {}) => {
12568
+ const startProvisioning = React22.useCallback(async ({ replace = false } = {}) => {
12223
12569
  setBusy(true);
12224
12570
  try {
12225
12571
  if (replace && provision?.attemptId) {
@@ -12240,7 +12586,7 @@ function WeixinSettingsTab({ rpcCall }) {
12240
12586
  setBusy(false);
12241
12587
  }
12242
12588
  }, [announce, invoke, provision?.attemptId]);
12243
- const cancelProvisioning = React21.useCallback(async () => {
12589
+ const cancelProvisioning = React22.useCallback(async () => {
12244
12590
  setBusy(true);
12245
12591
  try {
12246
12592
  if (provision?.attemptId && !["failed", "expired", "cancelled"].includes(provision.status)) {
@@ -12255,7 +12601,7 @@ function WeixinSettingsTab({ rpcCall }) {
12255
12601
  setBusy(false);
12256
12602
  }
12257
12603
  }, [announce, invoke, provision?.attemptId, provision?.status, scheduleAnimationFrame]);
12258
- const submitVerification = React21.useCallback(async (verifyCode) => {
12604
+ const submitVerification = React22.useCallback(async (verifyCode) => {
12259
12605
  if (!provision?.attemptId) return;
12260
12606
  setBusy(true);
12261
12607
  try {
@@ -12271,7 +12617,7 @@ function WeixinSettingsTab({ rpcCall }) {
12271
12617
  setBusy(false);
12272
12618
  }
12273
12619
  }, [announce, invoke, provision?.attemptId]);
12274
- React21.useEffect(() => {
12620
+ React22.useEffect(() => {
12275
12621
  const attemptId = provision?.attemptId;
12276
12622
  if (!attemptId || !["pending", "scanned", "connecting"].includes(provision.status)) return void 0;
12277
12623
  const controller = new AbortController();
@@ -12319,7 +12665,7 @@ function WeixinSettingsTab({ rpcCall }) {
12319
12665
  controller.abort();
12320
12666
  };
12321
12667
  }, [announce, invoke, loadStatus, provision?.attemptId, provision?.status, provision?.pollIntervalMs]);
12322
- const setBotBusy = React21.useCallback((botId, value) => {
12668
+ const setBotBusy = React22.useCallback((botId, value) => {
12323
12669
  setBusyByBot((current) => {
12324
12670
  const next = { ...current };
12325
12671
  if (value) next[botId] = value;
@@ -12327,7 +12673,7 @@ function WeixinSettingsTab({ rpcCall }) {
12327
12673
  return next;
12328
12674
  });
12329
12675
  }, []);
12330
- const reconnect = React21.useCallback(async (account) => {
12676
+ const reconnect = React22.useCallback(async (account) => {
12331
12677
  const snapshotVersion = workspaceFence.beginMutation();
12332
12678
  setBotBusy(account.botId, "reconnect");
12333
12679
  setFeedbackByBot((current) => {
@@ -12379,7 +12725,7 @@ function WeixinSettingsTab({ rpcCall }) {
12379
12725
  setBotBusy(account.botId, null);
12380
12726
  }
12381
12727
  }, [announce, invoke, loadStatus, setBotBusy, workspaceFence]);
12382
- const saveWorkspace = React21.useCallback(async (account, workspace) => {
12728
+ const saveWorkspace = React22.useCallback(async (account, workspace) => {
12383
12729
  const workspaceVersion = workspaceFence.beginMutation();
12384
12730
  setBotBusy(account.botId, "workspace");
12385
12731
  try {
@@ -12404,7 +12750,7 @@ function WeixinSettingsTab({ rpcCall }) {
12404
12750
  if (mountedRef.current) setBotBusy(account.botId, null);
12405
12751
  }
12406
12752
  }, [invoke, loadStatus, setBotBusy, workspaceFence]);
12407
- const saveBotSetting = React21.useCallback(async (account, operation, endpoint, payload) => {
12753
+ const saveBotSetting = React22.useCallback(async (account, operation, endpoint, payload) => {
12408
12754
  const snapshotVersion = workspaceFence.beginMutation();
12409
12755
  setBotBusy(account.botId, operation);
12410
12756
  try {
@@ -12429,7 +12775,7 @@ function WeixinSettingsTab({ rpcCall }) {
12429
12775
  if (mountedRef.current) setBotBusy(account.botId, null);
12430
12776
  }
12431
12777
  }, [invoke, loadStatus, setBotBusy, workspaceFence]);
12432
- const remove = React21.useCallback(async (account) => {
12778
+ const remove = React22.useCallback(async (account) => {
12433
12779
  const snapshotVersion = workspaceFence.beginMutation();
12434
12780
  setBotBusy(account.botId, "delete");
12435
12781
  try {
@@ -12516,7 +12862,7 @@ function WeixinSettingsTab({ rpcCall }) {
12516
12862
  h2(Button14, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
12517
12863
  )
12518
12864
  ) : h2(
12519
- React21.Fragment,
12865
+ React22.Fragment,
12520
12866
  null,
12521
12867
  provisionView,
12522
12868
  model.bots.length === 0 && !provision ? h2(EmptyView6, { onStart: () => void startProvisioning(), busy }) : null,
@@ -12527,6 +12873,12 @@ function WeixinSettingsTab({ rpcCall }) {
12527
12873
  removeTarget,
12528
12874
  onReconnect: (account) => void reconnect(account),
12529
12875
  onWorkspaceSave: saveWorkspace,
12876
+ onAliasSave: (account, alias) => saveBotSetting(
12877
+ account,
12878
+ "alias",
12879
+ WEIXIN_ENDPOINTS.setAlias,
12880
+ { alias }
12881
+ ),
12530
12882
  onModelSave: (account, selectedModel) => saveBotSetting(
12531
12883
  account,
12532
12884
  "model",
@@ -12680,6 +13032,7 @@ var WHATSAPP_ENDPOINTS = Object.freeze({
12680
13032
  reconnectBot: "bot.reconnect",
12681
13033
  deleteBot: "bot.delete",
12682
13034
  setAccessPolicy: "bot.access-policy.set",
13035
+ setAlias: "bot.alias.set",
12683
13036
  setWorkspace: "bot.workspace.set",
12684
13037
  setModel: SET_MODEL_ENDPOINT,
12685
13038
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
@@ -12753,6 +13106,7 @@ function normalizeBot7(value) {
12753
13106
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
12754
13107
  ...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
12755
13108
  bot: {
13109
+ ...normalizeBotAlias(value.bot),
12756
13110
  name: text6(value.bot?.name, "WhatsApp\u673A\u5668\u4EBA", 100),
12757
13111
  idMasked: text6(value.bot?.idMasked, "WhatsApp\u8D26\u53F7", 140)
12758
13112
  },
@@ -12794,7 +13148,7 @@ function formatRemaining6(milliseconds) {
12794
13148
  }
12795
13149
 
12796
13150
  // plugin-src/client/channels/whatsapp/index.js
12797
- var React22 = __toESM(require("react"), 1);
13151
+ var React23 = __toESM(require("react"), 1);
12798
13152
 
12799
13153
  // plugin-src/client/channels/whatsapp/styles.js
12800
13154
  var WHATSAPP_STYLE_ID = "xmanrui-dsh-im-whatsapp-settings";
@@ -12819,7 +13173,7 @@ function installWhatsappStyles() {
12819
13173
 
12820
13174
  // plugin-src/client/channels/whatsapp/index.js
12821
13175
  var ACTIVE_STATES3 = /* @__PURE__ */ new Set(["pending", "connecting"]);
12822
- var Button16 = React22.forwardRef(function Button17({ children, kind = "secondary", className = "", ...props }, ref) {
13176
+ var Button16 = React23.forwardRef(function Button17({ children, kind = "secondary", className = "", ...props }, ref) {
12823
13177
  return h2("button", {
12824
13178
  ...props,
12825
13179
  ref,
@@ -13041,6 +13395,7 @@ function WhatsappAccountCard({
13041
13395
  removing,
13042
13396
  onReconnect,
13043
13397
  onWorkspaceSave,
13398
+ onAliasSave,
13044
13399
  onModelSave,
13045
13400
  onAgentPresetSave,
13046
13401
  onContextEnhancementSave,
@@ -13075,7 +13430,7 @@ function WhatsappAccountCard({
13075
13430
  h2(
13076
13431
  "div",
13077
13432
  { className: "dim-botName" },
13078
- h2("h3", null, account.bot.name),
13433
+ h2(BotName, { bot: account.bot, disabled: Boolean(busy), onSave: onAliasSave }),
13079
13434
  h2("p", null, account.bot.idMasked)
13080
13435
  )
13081
13436
  ),
@@ -13172,7 +13527,7 @@ function WhatsappAccountCard({
13172
13527
  );
13173
13528
  }
13174
13529
  function WhatsappSettingsTab({ rpcCall }) {
13175
- const [model, setModel] = React22.useState({
13530
+ const [model, setModel] = React23.useState({
13176
13531
  phase: "loading",
13177
13532
  bots: [],
13178
13533
  totals: { configured: 0, connected: 0 },
@@ -13180,16 +13535,16 @@ function WhatsappSettingsTab({ rpcCall }) {
13180
13535
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
13181
13536
  modelCatalog: EMPTY_MODEL_CATALOG
13182
13537
  });
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);
13538
+ const [provision, setProvision] = React23.useState(null);
13539
+ const [busy, setBusy] = React23.useState(false);
13540
+ const [busyByBot, setBusyByBot] = React23.useState({});
13541
+ const [testNoticeByBot, setTestNoticeByBot] = React23.useState({});
13542
+ const [removeTarget, setRemoveTarget] = React23.useState(null);
13543
+ const [now, setNow] = React23.useState(Date.now());
13544
+ const mounted = React23.useRef(true);
13190
13545
  const workspaceFence = useWorkspaceSnapshotFence();
13191
- const addButtonRef = React22.useRef(null);
13192
- React22.useEffect(() => {
13546
+ const addButtonRef = React23.useRef(null);
13547
+ React23.useEffect(() => {
13193
13548
  const disposeDingtalk = installDingtalkStyles();
13194
13549
  const disposeWhatsapp = installWhatsappStyles();
13195
13550
  mounted.current = true;
@@ -13199,11 +13554,11 @@ function WhatsappSettingsTab({ rpcCall }) {
13199
13554
  disposeDingtalk();
13200
13555
  };
13201
13556
  }, []);
13202
- const invoke = React22.useCallback(async (endpoint, payload = {}, signal) => {
13557
+ const invoke = React23.useCallback(async (endpoint, payload = {}, signal) => {
13203
13558
  if (typeof rpcCall !== "function") throw new TypeError("WhatsApp \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
13204
13559
  return unwrapRpcResult10(await rpcCall(endpoint, payload, signal));
13205
13560
  }, [rpcCall]);
13206
- const loadStatus = React22.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
13561
+ const loadStatus = React23.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
13207
13562
  const workspaceVersion = workspaceFence.beginStatus();
13208
13563
  if (workspaceVersion === null) return void 0;
13209
13564
  if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
@@ -13234,12 +13589,12 @@ function WhatsappSettingsTab({ rpcCall }) {
13234
13589
  return void 0;
13235
13590
  }
13236
13591
  }, [invoke, workspaceFence]);
13237
- React22.useEffect(() => {
13592
+ React23.useEffect(() => {
13238
13593
  const controller = new AbortController();
13239
13594
  void loadStatus({ signal: controller.signal, restore: true });
13240
13595
  return () => controller.abort();
13241
13596
  }, [loadStatus]);
13242
- React22.useEffect(() => {
13597
+ React23.useEffect(() => {
13243
13598
  if (model.phase !== "ready") return void 0;
13244
13599
  const controller = new AbortController();
13245
13600
  const timer = window.setInterval(
@@ -13251,12 +13606,12 @@ function WhatsappSettingsTab({ rpcCall }) {
13251
13606
  window.clearInterval(timer);
13252
13607
  };
13253
13608
  }, [loadStatus, model.phase]);
13254
- React22.useEffect(() => {
13609
+ React23.useEffect(() => {
13255
13610
  if (!provision || !ACTIVE_STATES3.has(provision.status)) return void 0;
13256
13611
  const timer = window.setInterval(() => mounted.current && setNow(Date.now()), 1e3);
13257
13612
  return () => window.clearInterval(timer);
13258
13613
  }, [provision?.attemptId, provision?.status]);
13259
- const startProvisioning = React22.useCallback(async (replace = false) => {
13614
+ const startProvisioning = React23.useCallback(async (replace = false) => {
13260
13615
  setBusy(true);
13261
13616
  try {
13262
13617
  if (replace && provision?.attemptId) {
@@ -13274,7 +13629,7 @@ function WhatsappSettingsTab({ rpcCall }) {
13274
13629
  if (mounted.current) setBusy(false);
13275
13630
  }
13276
13631
  }, [invoke, provision?.attemptId]);
13277
- const closeProvision = React22.useCallback(async () => {
13632
+ const closeProvision = React23.useCallback(async () => {
13278
13633
  setBusy(true);
13279
13634
  try {
13280
13635
  if (provision?.attemptId && ACTIVE_STATES3.has(provision.status)) {
@@ -13285,7 +13640,7 @@ function WhatsappSettingsTab({ rpcCall }) {
13285
13640
  if (mounted.current) setBusy(false);
13286
13641
  }
13287
13642
  }, [invoke, provision?.attemptId, provision?.status]);
13288
- React22.useEffect(() => {
13643
+ React23.useEffect(() => {
13289
13644
  const attemptId = provision?.attemptId;
13290
13645
  if (!attemptId || !ACTIVE_STATES3.has(provision.status)) return void 0;
13291
13646
  const controller = new AbortController();
@@ -13326,7 +13681,7 @@ function WhatsappSettingsTab({ rpcCall }) {
13326
13681
  if (timer) window.clearTimeout(timer);
13327
13682
  };
13328
13683
  }, [invoke, loadStatus, provision?.attemptId, provision?.status]);
13329
- const botAction = React22.useCallback(async (account, operation, endpoint, payload) => {
13684
+ const botAction = React23.useCallback(async (account, operation, endpoint, payload) => {
13330
13685
  const snapshotVersion = workspaceFence.beginMutation();
13331
13686
  setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
13332
13687
  if (operation === "reconnect") {
@@ -13398,6 +13753,12 @@ function WhatsappSettingsTab({ rpcCall }) {
13398
13753
  WHATSAPP_ENDPOINTS.setWorkspace,
13399
13754
  { botId: account.botId, workspace }
13400
13755
  ),
13756
+ onAliasSave: (alias) => botAction(
13757
+ account,
13758
+ "alias",
13759
+ WHATSAPP_ENDPOINTS.setAlias,
13760
+ { botId: account.botId, alias }
13761
+ ),
13401
13762
  onModelSave: (selectedModel) => botAction(
13402
13763
  account,
13403
13764
  "model",
@@ -13454,7 +13815,7 @@ function WhatsappSettingsTab({ rpcCall }) {
13454
13815
  h2(Button16, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
13455
13816
  )
13456
13817
  ) : h2(
13457
- React22.Fragment,
13818
+ React23.Fragment,
13458
13819
  null,
13459
13820
  provision?.status === "pending" ? h2(QrPanel5, {
13460
13821
  provision,
@@ -13485,7 +13846,7 @@ var normalizeSnapshot10 = api4.normalizeSnapshot;
13485
13846
  var presentError11 = api4.presentError;
13486
13847
 
13487
13848
  // plugin-src/client/channels/imessage/index.js
13488
- var React23 = __toESM(require("react"), 1);
13849
+ var React24 = __toESM(require("react"), 1);
13489
13850
 
13490
13851
  // plugin-src/client/channels/imessage/styles.js
13491
13852
  var IMESSAGE_STYLE_ID = "xmanrui-dsh-im-imessage-settings";
@@ -13578,10 +13939,10 @@ var IMessageSettingsTab = channel4.SettingsTab;
13578
13939
  var IMessageAccountCard = channel4.AccountCard;
13579
13940
 
13580
13941
  // plugin-src/client/delivery-settings.js
13581
- var React26 = __toESM(require("react"), 1);
13942
+ var React27 = __toESM(require("react"), 1);
13582
13943
 
13583
13944
  // plugin-src/client/access-policy-settings.js
13584
- var React24 = __toESM(require("react"), 1);
13945
+ var React25 = __toESM(require("react"), 1);
13585
13946
  var ACCESS_POLICY_ENDPOINT = "bot.access-policy.set";
13586
13947
  var ACCESS_CHANNEL_DEFINITIONS = Object.freeze({
13587
13948
  weixin: Object.freeze({
@@ -13694,8 +14055,8 @@ function ScenePolicyEditor({
13694
14055
  unsupported = false,
13695
14056
  onChange
13696
14057
  }) {
13697
- const ownerHelpId = React24.useId();
13698
- const emptyAllowlistHelpId = React24.useId();
14058
+ const ownerHelpId = React25.useId();
14059
+ const emptyAllowlistHelpId = React25.useId();
13699
14060
  const allowlist = policy.mode === "allowlist";
13700
14061
  const collectionKey = allowlist ? "users" : "commandPermissionOverrides";
13701
14062
  const branchKey = allowlist ? "allowlist" : "open";
@@ -13747,7 +14108,7 @@ function ScenePolicyEditor({
13747
14108
  h2("strong", null, "\u5F53\u524D\u6E20\u9053\u4E0D\u652F\u6301\u7FA4\u804A"),
13748
14109
  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
14110
  ) : h2(
13750
- React24.Fragment,
14111
+ React25.Fragment,
13751
14112
  null,
13752
14113
  h2(
13753
14114
  "div",
@@ -13888,16 +14249,16 @@ function AccessPolicySettingsPage({ channel: channel5, account, rpcCall, onSaved
13888
14249
  const definition = ACCESS_CHANNEL_DEFINITIONS[channel5];
13889
14250
  const initialPolicy = normalizeAccessPolicy(account?.accessPolicy);
13890
14251
  const initialKey = JSON.stringify(initialPolicy);
13891
- const [draft, setDraft] = React24.useState(() => clonePolicy(
14252
+ const [draft, setDraft] = React25.useState(() => clonePolicy(
13892
14253
  initialPolicy ?? DEFAULT_ACCESS_POLICY
13893
14254
  ));
13894
- const [saving, setSaving] = React24.useState(false);
13895
- const [feedback, setFeedback] = React24.useState(null);
13896
- React24.useEffect(() => {
14255
+ const [saving, setSaving] = React25.useState(false);
14256
+ const [feedback, setFeedback] = React25.useState(null);
14257
+ React25.useEffect(() => {
13897
14258
  const next = normalizeAccessPolicy(account?.accessPolicy);
13898
14259
  setDraft(clonePolicy(next ?? DEFAULT_ACCESS_POLICY));
13899
14260
  }, [account?.botId, initialKey]);
13900
- React24.useEffect(() => {
14261
+ React25.useEffect(() => {
13901
14262
  setFeedback(null);
13902
14263
  }, [account?.botId]);
13903
14264
  if (!definition) {
@@ -13988,7 +14349,7 @@ function AccessPolicySettingsPage({ channel: channel5, account, rpcCall, onSaved
13988
14349
  }
13989
14350
 
13990
14351
  // plugin-src/client/channels/feishu/group-settings.js
13991
- var React25 = __toESM(require("react"), 1);
14352
+ var React26 = __toESM(require("react"), 1);
13992
14353
  var GROUP_MESSAGE_PERMISSION_OPERATION2 = FEISHU_REGISTRATION_OPERATIONS.GROUP_MESSAGE_PERMISSION;
13993
14354
  function SettingsButton({ children, kind = "secondary", className = "", ...props }) {
13994
14355
  return h2("button", {
@@ -14049,9 +14410,9 @@ function GroupResponseModeEditor({
14049
14410
  onAuthorize
14050
14411
  }) {
14051
14412
  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);
14413
+ const [saving, setSaving] = React26.useState(false);
14414
+ const [authorizing, setAuthorizing] = React26.useState(false);
14415
+ const [error, setError] = React26.useState(null);
14055
14416
  const change = async (event) => {
14056
14417
  const next = normalizeGroupResponseMode(event.target.value);
14057
14418
  if (next === current || saving || disabled) return;
@@ -14132,8 +14493,8 @@ function GroupResponseModeEditor({
14132
14493
  }
14133
14494
  function GroupTopicReplyEditor({ value = false, disabled = false, onSave }) {
14134
14495
  const current = value === true ? "on" : "off";
14135
- const [saving, setSaving] = React25.useState(false);
14136
- const [error, setError] = React25.useState(null);
14496
+ const [saving, setSaving] = React26.useState(false);
14497
+ const [error, setError] = React26.useState(null);
14137
14498
  const change = async (event) => {
14138
14499
  const next = event.target.value === "on";
14139
14500
  if ((next ? "on" : "off") === current || saving || disabled) return;
@@ -14320,14 +14681,14 @@ function PermissionFlow({ provision, now, busy, botName, onRetry, onCancel, onCl
14320
14681
  );
14321
14682
  }
14322
14683
  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(() => {
14684
+ const [settings, setSettings] = React26.useState(() => groupSettingsFrom(account));
14685
+ const [refreshing, setRefreshing] = React26.useState(false);
14686
+ const [refreshError, setRefreshError] = React26.useState(null);
14687
+ const [provision, setProvision] = React26.useState(null);
14688
+ const [provisionBusy, setProvisionBusy] = React26.useState(false);
14689
+ const [now, setNow] = React26.useState(() => Date.now());
14690
+ const mounted = React26.useRef(true);
14691
+ React26.useEffect(() => {
14331
14692
  setSettings(groupSettingsFrom(account));
14332
14693
  }, [
14333
14694
  account.botId,
@@ -14335,22 +14696,22 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14335
14696
  account.groupTopicReply,
14336
14697
  account.groupMessagePermissionGranted
14337
14698
  ]);
14338
- React25.useEffect(() => {
14699
+ React26.useEffect(() => {
14339
14700
  mounted.current = true;
14340
14701
  return () => {
14341
14702
  mounted.current = false;
14342
14703
  };
14343
14704
  }, []);
14344
- const invoke = React25.useCallback(async (endpoint, payload = {}, signal) => {
14705
+ const invoke = React26.useCallback(async (endpoint, payload = {}, signal) => {
14345
14706
  if (typeof rpcCall !== "function") throw new Error("\u98DE\u4E66\u7FA4\u804A\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
14346
14707
  return unwrapRpcResult3(await rpcCall(endpoint, payload, signal));
14347
14708
  }, [rpcCall]);
14348
- const applySnapshot = React25.useCallback((value) => {
14709
+ const applySnapshot = React26.useCallback((value) => {
14349
14710
  const result = targetBotFromSnapshot(value, account.botId);
14350
14711
  if (mounted.current) setSettings(groupSettingsFrom(result.bot));
14351
14712
  return result;
14352
14713
  }, [account.botId]);
14353
- const loadSettings = React25.useCallback(async ({ signal, restoreProvisioning = false } = {}) => {
14714
+ const loadSettings = React26.useCallback(async ({ signal, restoreProvisioning = false } = {}) => {
14354
14715
  setRefreshing(true);
14355
14716
  setRefreshError(null);
14356
14717
  try {
@@ -14379,16 +14740,16 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14379
14740
  if (!signal?.aborted && mounted.current) setRefreshing(false);
14380
14741
  }
14381
14742
  }, [account.botId, applySnapshot, invoke]);
14382
- React25.useEffect(() => {
14743
+ React26.useEffect(() => {
14383
14744
  const controller = new AbortController();
14384
14745
  void loadSettings({ signal: controller.signal, restoreProvisioning: true });
14385
14746
  return () => controller.abort();
14386
14747
  }, [loadSettings]);
14387
- const saveSetting = React25.useCallback(async (endpoint, payload) => {
14748
+ const saveSetting = React26.useCallback(async (endpoint, payload) => {
14388
14749
  const value = await invoke(endpoint, { botId: account.botId, ...payload });
14389
14750
  applySnapshot(value);
14390
14751
  }, [account.botId, applySnapshot, invoke]);
14391
- const startAuthorization = React25.useCallback(async ({ replace = false } = {}) => {
14752
+ const startAuthorization = React26.useCallback(async ({ replace = false } = {}) => {
14392
14753
  if (provisionBusy) return;
14393
14754
  const previousAttemptId = provision?.attemptId;
14394
14755
  setProvisionBusy(true);
@@ -14429,13 +14790,13 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14429
14790
  if (mounted.current) setProvisionBusy(false);
14430
14791
  }
14431
14792
  }, [account.botId, invoke, provision?.attemptId, provisionBusy]);
14432
- const finishAuthorization = React25.useCallback(async (signal) => {
14793
+ const finishAuthorization = React26.useCallback(async (signal) => {
14433
14794
  const bot = await loadSettings({ signal, restoreProvisioning: false });
14434
14795
  if (signal?.aborted || !mounted.current) return;
14435
14796
  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
14797
  setProvision(null);
14437
14798
  }, [loadSettings]);
14438
- React25.useEffect(() => {
14799
+ React26.useEffect(() => {
14439
14800
  if (!provision?.attemptId || !["qr", "connecting"].includes(provision.phase) || provision.expired) return void 0;
14440
14801
  const timerHost = globalThis.window ?? globalThis;
14441
14802
  const controller = new AbortController();
@@ -14479,7 +14840,7 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14479
14840
  timerHost.clearTimeout(timer);
14480
14841
  };
14481
14842
  }, [account.botId, finishAuthorization, invoke, provision]);
14482
- React25.useEffect(() => {
14843
+ React26.useEffect(() => {
14483
14844
  if (!provision?.attemptId || provision.phase !== "qr" || provision.expired) return void 0;
14484
14845
  const timerHost = globalThis.window ?? globalThis;
14485
14846
  const tick = () => {
@@ -14493,7 +14854,7 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
14493
14854
  const timer = timerHost.setInterval(tick, 1e3);
14494
14855
  return () => timerHost.clearInterval(timer);
14495
14856
  }, [provision?.attemptId, provision?.expired, provision?.expiresAt, provision?.phase]);
14496
- const cancelAuthorization = React25.useCallback(async () => {
14857
+ const cancelAuthorization = React26.useCallback(async () => {
14497
14858
  if (!provision?.attemptId || provisionBusy) {
14498
14859
  setProvision(null);
14499
14860
  return;
@@ -14814,13 +15175,13 @@ function TargetForm({
14814
15175
  }) {
14815
15176
  const editing = mode === "edit";
14816
15177
  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);
15178
+ const [targetId, setTargetId] = React27.useState(initialValue?.targetId ?? "");
15179
+ const [name2, setName] = React27.useState(initialValue?.name ?? "");
15180
+ const [kind, setKind] = React27.useState(initialKind);
15181
+ const [route, setRoute] = React27.useState(initialValue?.route ?? {});
15182
+ const [error, setError] = React27.useState(null);
15183
+ const [testing, setTesting] = React27.useState(false);
15184
+ const [testState, setTestState] = React27.useState(null);
14824
15185
  const currentTarget = () => {
14825
15186
  const normalizedRoute = Object.fromEntries(fieldsFor(definition, kind).map((field) => {
14826
15187
  const raw = String(route[field.key] ?? "").trim();
@@ -15037,7 +15398,7 @@ function TargetSuggestionPicker({
15037
15398
  suggestions.map((suggestion, index) => {
15038
15399
  const identity = routeIdentity(definition, suggestion);
15039
15400
  const added = configured.has(identity);
15040
- return React26.createElement("option", {
15401
+ return React27.createElement("option", {
15041
15402
  key: suggestion.id ?? suggestion.suggestionId ?? `${identity}:${index}`,
15042
15403
  value: String(index),
15043
15404
  disabled: added
@@ -15054,11 +15415,11 @@ function TargetSuggestionPicker({
15054
15415
  );
15055
15416
  }
15056
15417
  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);
15418
+ const [action, setAction] = React27.useState(null);
15419
+ const [testState, setTestState] = React27.useState(null);
15420
+ const [syncFeedback, setSyncFeedback] = React27.useState(null);
15421
+ const [copyState, setCopyState] = React27.useState(null);
15422
+ const [confirmDelete, setConfirmDelete] = React27.useState(false);
15062
15423
  const sessionSync = target.sessionSync ?? { enabled: false, state: "unavailable" };
15063
15424
  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
15425
  const testTarget = async () => {
@@ -15121,7 +15482,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
15121
15482
  h2(
15122
15483
  "div",
15123
15484
  { className: "dim-targetTitle" },
15124
- React26.createElement("strong", null, target.name || target.targetId),
15485
+ React27.createElement("strong", null, target.name || target.targetId),
15125
15486
  h2("span", null, kindLabel(definition, target.kind))
15126
15487
  ),
15127
15488
  h2("code", null, `targetId: ${target.targetId}`)
@@ -15207,26 +15568,26 @@ function DeliveryTargetSettingsPage({
15207
15568
  onBack
15208
15569
  }) {
15209
15570
  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(() => {
15571
+ const [activeTabId, setActiveTabId] = React27.useState(BOT_SETTINGS_TABS[0].id);
15572
+ const [phase, setPhase] = React27.useState("loading");
15573
+ const [targets, setTargets] = React27.useState([]);
15574
+ const [suggestionPhase, setSuggestionPhase] = React27.useState("idle");
15575
+ const [suggestions, setSuggestions] = React27.useState([]);
15576
+ const [suggestionError, setSuggestionError] = React27.useState(null);
15577
+ const [error, setError] = React27.useState(null);
15578
+ const [editor, setEditor] = React27.useState(null);
15579
+ const [saving, setSaving] = React27.useState(false);
15580
+ const [botCopyState, setBotCopyState] = React27.useState(null);
15581
+ const [accessPolicy, setAccessPolicy] = React27.useState(account.accessPolicy);
15582
+ const mounted = React27.useRef(true);
15583
+ React27.useEffect(() => {
15223
15584
  setAccessPolicy(account.accessPolicy);
15224
15585
  }, [account.botId, account.accessPolicy]);
15225
- const invoke = React26.useCallback(async (endpoint, payload = {}, signal) => {
15586
+ const invoke = React27.useCallback(async (endpoint, payload = {}, signal) => {
15226
15587
  if (typeof rpcCall !== "function") throw new Error("\u6295\u9012\u76EE\u6807\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
15227
15588
  return unwrapRpcResult13(await rpcCall(endpoint, payload, signal));
15228
15589
  }, [rpcCall]);
15229
- const loadTargets = React26.useCallback(async ({ signal, silent = false } = {}) => {
15590
+ const loadTargets = React27.useCallback(async ({ signal, silent = false } = {}) => {
15230
15591
  if (!silent) setPhase("loading");
15231
15592
  setError(null);
15232
15593
  try {
@@ -15240,7 +15601,7 @@ function DeliveryTargetSettingsPage({
15240
15601
  setPhase("error");
15241
15602
  }
15242
15603
  }, [account.botId, invoke]);
15243
- const loadSuggestions = React26.useCallback(async () => {
15604
+ const loadSuggestions = React27.useCallback(async () => {
15244
15605
  setSuggestionPhase("loading");
15245
15606
  setSuggestionError(null);
15246
15607
  try {
@@ -15254,7 +15615,7 @@ function DeliveryTargetSettingsPage({
15254
15615
  setSuggestionPhase("error");
15255
15616
  }
15256
15617
  }, [account.botId, definition, invoke]);
15257
- React26.useEffect(() => {
15618
+ React27.useEffect(() => {
15258
15619
  mounted.current = true;
15259
15620
  const controller = new AbortController();
15260
15621
  void loadTargets({ signal: controller.signal });
@@ -15376,7 +15737,7 @@ function DeliveryTargetSettingsPage({
15376
15737
  account,
15377
15738
  rpcCall: accessRpcCall
15378
15739
  }) : h2(
15379
- React26.Fragment,
15740
+ React27.Fragment,
15380
15741
  null,
15381
15742
  h2(
15382
15743
  "section",
@@ -15487,7 +15848,7 @@ function DeliveryTargetSettingsPage({
15487
15848
  }
15488
15849
 
15489
15850
  // plugin-src/client/global-settings.js
15490
- var React27 = __toESM(require("react"), 1);
15851
+ var React28 = __toESM(require("react"), 1);
15491
15852
 
15492
15853
  // src/channels/shared/inbound-ttl.mjs
15493
15854
  var DEFAULT_INBOUND_TTL_HOURS = 168;
@@ -15549,29 +15910,29 @@ function GlobalButton({ children, kind = "secondary", className = "", ...props }
15549
15910
  }, children);
15550
15911
  }
15551
15912
  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) => {
15913
+ const [phase, setPhase] = React28.useState("loading");
15914
+ const [loadError, setLoadError] = React28.useState(null);
15915
+ const [ttlInput, setTtlInput] = React28.useState("");
15916
+ const [savedTtl, setSavedTtl] = React28.useState(null);
15917
+ const [ttlError, setTtlError] = React28.useState(false);
15918
+ const [saveError, setSaveError] = React28.useState(null);
15919
+ const [saveSucceeded, setSaveSucceeded] = React28.useState(false);
15920
+ const [isSaving, setIsSaving] = React28.useState(false);
15921
+ const [sweepConfirming, setSweepConfirming] = React28.useState(false);
15922
+ const [sweeping, setSweeping] = React28.useState(false);
15923
+ const ttlErrorId = React28.useId();
15924
+ const ttlHintsId = React28.useId();
15925
+ const sweepTriggerId = React28.useId();
15926
+ const sweepConfirmId = React28.useId();
15927
+ const sweepConfirmTextId = React28.useId();
15928
+ const sweepConfirmButtonId = React28.useId();
15929
+ const mounted = React28.useRef(true);
15930
+ const saving = React28.useRef(false);
15931
+ const invoke = React28.useCallback(async (endpoint, payload = {}, signal) => {
15571
15932
  if (typeof rpcCall !== "function") throw new Error("\u901A\u7528\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
15572
15933
  return unwrapRpcResult14(await rpcCall(endpoint, payload, signal));
15573
15934
  }, [rpcCall]);
15574
- const loadSettings = React27.useCallback(async ({ signal } = {}) => {
15935
+ const loadSettings = React28.useCallback(async ({ signal } = {}) => {
15575
15936
  setPhase("loading");
15576
15937
  setLoadError(null);
15577
15938
  try {
@@ -15595,7 +15956,7 @@ function GlobalSettingsPanel({ rpcCall }) {
15595
15956
  setPhase("error");
15596
15957
  }
15597
15958
  }, [invoke]);
15598
- React27.useEffect(() => {
15959
+ React28.useEffect(() => {
15599
15960
  mounted.current = true;
15600
15961
  const controller = new AbortController();
15601
15962
  void loadSettings({ signal: controller.signal });
@@ -15604,7 +15965,7 @@ function GlobalSettingsPanel({ rpcCall }) {
15604
15965
  controller.abort();
15605
15966
  };
15606
15967
  }, [loadSettings]);
15607
- React27.useEffect(() => {
15968
+ React28.useEffect(() => {
15608
15969
  if (!sweepConfirming) return;
15609
15970
  globalThis.document?.getElementById(sweepConfirmButtonId)?.focus();
15610
15971
  }, [sweepConfirmButtonId, sweepConfirming]);
@@ -15912,6 +16273,38 @@ function replacePageLocation(url, location = globalThis.location) {
15912
16273
  // plugin-src/client/styles.js
15913
16274
  var IM_STYLE_ID = "xmanrui-dsh-im-settings";
15914
16275
  var CSS13 = String.raw`
16276
+ .dim-aliasName { display: flex; align-items: center; gap: 4px; min-width: 0; }
16277
+ .dim-aliasName h3 { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
16278
+ .dim-aliasName h3:focus-visible { outline: 2px solid var(--dsw-alias-state-business-primary, #3370ff); outline-offset: 2px; border-radius: 3px; }
16279
+ .dim-botNameTooltip { position: fixed; z-index: 1000; box-sizing: border-box; width: max-content; max-width: min(320px, calc(100vw - 16px)); padding: 6px 9px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 7px; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-bg-layer-3, #fff); box-shadow: 0 8px 24px rgb(31 35 41 / 14%); font: 500 12px/18px -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; white-space: normal; overflow-wrap: anywhere; pointer-events: none; animation: dim-botNameTooltip-in .15s ease; }
16280
+ @keyframes dim-botNameTooltip-in { from { opacity: 0; } to { opacity: 1; } }
16281
+ @media (prefers-reduced-motion: reduce) { .dim-botNameTooltip { animation: none; } }
16282
+ .dim-aliasEntry { display: inline-flex; flex: none; }
16283
+ .dim-aliasEdit { display: grid; place-items: center; width: 28px; height: 28px; padding: 4px; border: 0; border-radius: 5px; color: var(--dsw-alias-label-tertiary, #8f959e); background: transparent; cursor: pointer; }
16284
+ .dim-aliasEdit svg { opacity: .55; transition: opacity .15s ease; }
16285
+ .dim-aliasName:hover .dim-aliasEdit:not(:disabled) svg, .dim-aliasEdit:focus-visible svg { opacity: 1; }
16286
+ .dim-aliasEdit:hover:not(:disabled), .dim-aliasEdit:focus-visible { color: var(--dsw-alias-state-business-primary, #3370ff); background: var(--dsw-alias-interactive-bg-hover, #f7f8fa); }
16287
+ .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; }
16288
+ .dim-aliasDialog * { box-sizing: border-box; }
16289
+ .dim-aliasDialog::backdrop { background: rgb(15 17 21 / 30%); }
16290
+ .dim-aliasHeader { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 18px; }
16291
+ .dim-aliasHeader h3 { margin: 0; font-size: 16px; }
16292
+ .dim-aliasDialog button { font: inherit; cursor: pointer; }
16293
+ .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; }
16294
+ .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; }
16295
+ .dim-aliasOriginal > span:first-child { flex: none; color: var(--dsw-alias-label-secondary, #646a73); }
16296
+ .dim-aliasDialog label { display: block; margin-bottom: 7px; }
16297
+ .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; }
16298
+ .dim-aliasHelp { margin: 8px 0 0; color: var(--dsw-alias-label-secondary, #646a73); font-size: 12px; }
16299
+ .dim-aliasError { color: var(--dsw-alias-state-danger-primary, #c53030); overflow-wrap: anywhere; }
16300
+ .dim-aliasFooter { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 14px; margin-top: 24px; }
16301
+ .dim-aliasRestore { padding: 4px 0; border: 0; color: var(--dsw-alias-state-business-primary, #3370ff); background: transparent; }
16302
+ .dim-aliasActions { display: flex; gap: 8px; margin-left: auto; }
16303
+ .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); }
16304
+ .dim-aliasActions .dim-aliasSave { color: #fff; border-color: var(--dsw-alias-state-business-primary, #3370ff); background: var(--dsw-alias-state-business-primary, #3370ff); }
16305
+ .dim-aliasEdit:disabled, .dim-aliasDialog button:disabled, .dim-aliasDialog input:disabled { opacity: .55; cursor: not-allowed; }
16306
+ .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; }
16307
+ @media (pointer: coarse) { .dim-aliasEdit, .dim-aliasDialog button { min-width: 44px; min-height: 44px; } .dim-aliasDialog input { font-size: 16px; } }
15915
16308
  .dim-page {
15916
16309
  --dim-blue: var(--dsw-alias-state-business-primary, #3370ff);
15917
16310
  --dim-blue-soft: color-mix(in srgb, var(--dim-blue) 9%, transparent);
@@ -16286,9 +16679,9 @@ var CSS13 = String.raw`
16286
16679
  /* Header tooltips may extend beyond the card; the collapsible body clips its own content. */
16287
16680
  .dim-panel .dim-botCard { position: relative; min-width: 0; width: 100%; max-width: 100%; overflow: visible; border: 1px solid var(--dsw-alias-border-l2, #e5e6eb); border-radius: 14px; background: var(--dsw-alias-bg-layer-1, #fff); box-shadow: 0 1px 2px rgb(31 35 41 / 3%); }
16288
16681
  .dim-panel .dim-botCard::before { display: none; }
16289
- .dim-panel .dim-botCardBody { position: relative; min-width: 0; width: 100%; max-width: 100%; padding: 12px; }
16682
+ .dim-panel .dim-botCardBody { position: relative; min-width: 0; width: 100%; max-width: 100%; padding: 12px 8px; }
16290
16683
  .dim-collapsibleAccount { min-width: 0; display: flex; flex-direction: column; }
16291
- .dim-collapsibleHead { min-width: 0; display: flex; align-items: center; gap: 10px; cursor: pointer; user-select: none; -webkit-user-select: none; }
16684
+ .dim-collapsibleHead { min-width: 0; display: flex; align-items: center; gap: 4px; cursor: pointer; user-select: none; -webkit-user-select: none; }
16292
16685
  .dim-collapsibleHead:focus-visible { outline: 2px solid var(--dsw-alias-state-business-primary, #3370ff); outline-offset: 2px; border-radius: 8px; }
16293
16686
  .dim-collapsibleHeaderContent { min-width: 0; flex: 1 1 auto; display: flex; align-items: center; }
16294
16687
  .dim-collapsibleChevron { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 9px; height: 9px; border-right: 1.6px solid var(--dsw-alias-label-tertiary, #8f959e); border-bottom: 1.6px solid var(--dsw-alias-label-tertiary, #8f959e); transform: rotate(-45deg); transition: transform .22s cubic-bezier(.4, 0, .2, 1); transform-origin: 50% 50%; }
@@ -16298,14 +16691,17 @@ var CSS13 = String.raw`
16298
16691
  .dim-collapsibleAccount.is-open > .dim-collapsibleBody { grid-template-rows: 1fr; }
16299
16692
  .dim-collapsibleBodyInner { min-height: 0; overflow: hidden; }
16300
16693
  .dim-collapsibleAccount:not(.is-open) .dim-collapsibleBodyInner { visibility: hidden; }
16301
- .dim-panel .dim-botCardTop { min-width: 0; max-width: 100%; display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
16302
- .dim-panel .dim-botIdentity { min-width: 0; flex: 1 1 0; display: flex; align-items: center; gap: 10px; }
16694
+ /* Reclaim horizontal spacing for names while keeping status on the same row,
16695
+ including when a channel's mobile stylesheet requests a column layout. */
16696
+ .dim-panel .dim-botCardTop { min-width: 0; width: 100%; max-width: 100%; display: flex; flex-direction: row; flex-wrap: nowrap; align-items: flex-start; justify-content: space-between; gap: 6px; }
16697
+ .dim-panel .dim-botIdentity { min-width: 0; flex: 1 1 0; display: flex; align-items: center; gap: 6px; }
16303
16698
  .dim-panel .dim-botAvatar { flex: none; width: 38px; height: 38px; display: grid; place-items: center; overflow: hidden; border-radius: 11px; box-shadow: none; }
16304
16699
  .dim-panel .dim-botAvatar svg { width: 27px; height: 27px; }
16305
- .dim-panel .dim-botName { min-width: 0; }
16700
+ .dim-panel .dim-botName { min-width: 0; flex: 1; }
16701
+ .dim-panel .dim-aliasName { gap: 2px; }
16306
16702
  .dim-panel .dim-botName h3 { overflow: hidden; margin: 0; color: var(--dsw-alias-label-primary, #1f2329); font-size: 15px; font-weight: 650; line-height: normal; text-overflow: ellipsis; white-space: nowrap; }
16307
16703
  .dim-panel .dim-botName p { overflow: hidden; margin: 4px 0 0; color: var(--dsw-alias-label-secondary, #646a73); font: 12px ui-monospace, SFMono-Regular, monospace; line-height: normal; text-overflow: ellipsis; white-space: nowrap; }
16308
- .dim-panel .dim-botCardTools { flex: none; display: flex; align-items: flex-start; gap: 8px; }
16704
+ .dim-panel .dim-botCardTools { flex: none; display: flex; align-items: flex-start; gap: 4px; }
16309
16705
  .dim-panel .dim-botHealthGroup { min-width: 0; max-width: 100%; flex: none; display: grid; justify-items: end; gap: 5px; }
16310
16706
  .dim-panel .dim-botCard .dim-botHealth { flex: none; min-height: 0; display: inline-flex; align-items: center; gap: 7px; padding: 0; border: 0; border-radius: 0; color: var(--dsw-alias-label-secondary, #646a73); background: transparent; font: inherit; font-size: 12px; font-weight: 400; line-height: normal; white-space: nowrap; }
16311
16707
  .dim-panel .dim-lastChecked { display: inline-flex; align-items: baseline; gap: 4px; color: var(--dsw-alias-label-tertiary, #8f959e); font: inherit; font-size: 11px; font-weight: 400; line-height: normal; white-space: nowrap; }
@@ -16841,8 +17237,8 @@ function installSessionChannelLogos(document2 = globalThis.document) {
16841
17237
  }
16842
17238
 
16843
17239
  // plugin-src/client/update-panel.js
16844
- var React28 = __toESM(require("react"), 1);
16845
- var import_react_dom3 = require("react-dom");
17240
+ var React29 = __toESM(require("react"), 1);
17241
+ var import_react_dom4 = require("react-dom");
16846
17242
  var import_valid = __toESM(require_valid(), 1);
16847
17243
  var import_rcompare = __toESM(require_rcompare(), 1);
16848
17244
  var UPDATE_RPC_CHANNEL = "/dsh-im";
@@ -16931,11 +17327,11 @@ function manualUpdateCommand(snapshot) {
16931
17327
  return `dsh plugin --profile ${profileArgument} add -w @xmanrui/dsh-im@${version}`;
16932
17328
  }
16933
17329
  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(() => {
17330
+ const [copyState, setCopyState] = React29.useState("idle");
17331
+ const commandRef = React29.useRef(null);
17332
+ const mounted = React29.useRef(false);
17333
+ const copying = React29.useRef(false);
17334
+ React29.useEffect(() => {
16939
17335
  mounted.current = true;
16940
17336
  return () => {
16941
17337
  mounted.current = false;
@@ -16967,7 +17363,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
16967
17363
  { className: "dim-updateManual", "aria-label": "\u624B\u5DE5\u66F4\u65B0" },
16968
17364
  h2("h4", { className: "dim-updateManualHeading" }, "\u624B\u5DE5\u66F4\u65B0"),
16969
17365
  command ? h2(
16970
- React28.Fragment,
17366
+ React29.Fragment,
16971
17367
  null,
16972
17368
  h2("p", { className: "dim-updateManualHint" }, "\u81EA\u52A8\u66F4\u65B0\u5931\u8D25\u53EF\u4EE5\u4F7F\u7528\u547D\u4EE4\u66F4\u65B0\uFF1A"),
16973
17369
  h2(
@@ -17003,7 +17399,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
17003
17399
  "aria-hidden": "true",
17004
17400
  focusable: "false"
17005
17401
  }, copyState === "copied" ? h2("path", { d: "m4 10 4 4 8-8" }) : h2(
17006
- React28.Fragment,
17402
+ React29.Fragment,
17007
17403
  null,
17008
17404
  h2("rect", { x: 7, y: 7, width: 10, height: 11, rx: 1.5 }),
17009
17405
  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 +17424,10 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
17028
17424
  );
17029
17425
  }
17030
17426
  function UpdateDialog({ children, onClose }) {
17031
- const dialogRef = React28.useRef(null);
17032
- const titleId = React28.useId();
17033
- const descriptionId = React28.useId();
17034
- React28.useEffect(() => {
17427
+ const dialogRef = React29.useRef(null);
17428
+ const titleId = React29.useId();
17429
+ const descriptionId = React29.useId();
17430
+ React29.useEffect(() => {
17035
17431
  const previous = globalThis.document?.activeElement;
17036
17432
  dialogRef.current?.focus?.();
17037
17433
  return () => {
@@ -17086,22 +17482,22 @@ function UpdateDialog({ children, onClose }) {
17086
17482
  children
17087
17483
  )
17088
17484
  );
17089
- return typeof document !== "undefined" && document.body ? (0, import_react_dom3.createPortal)(content, document.body) : content;
17485
+ return typeof document !== "undefined" && document.body ? (0, import_react_dom4.createPortal)(content, document.body) : content;
17090
17486
  }
17091
17487
  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);
17488
+ const [snapshot, setSnapshot] = React29.useState(null);
17489
+ const [action, setAction] = React29.useState("status");
17490
+ const [error, setError] = React29.useState(null);
17491
+ const [open, setOpen] = React29.useState(false);
17492
+ const [uncertainInstall, setUncertainInstall] = React29.useState(false);
17493
+ const mounted = React29.useRef(false);
17494
+ const busy = React29.useRef(false);
17495
+ const readController = React29.useRef(null);
17496
+ const pollReadController = React29.useRef(null);
17497
+ const installRequest = React29.useRef(null);
17498
+ const onStatusRef = React29.useRef(onStatus);
17103
17499
  onStatusRef.current = onStatus;
17104
- const accept = React28.useCallback((next) => {
17500
+ const accept = React29.useCallback((next) => {
17105
17501
  setSnapshot(next);
17106
17502
  onStatusRef.current?.(next);
17107
17503
  }, []);
@@ -17110,7 +17506,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17110
17506
  setUncertainInstall(false);
17111
17507
  accept(next);
17112
17508
  };
17113
- const invoke = React28.useCallback(async (endpoint, payload = {}, signal) => {
17509
+ const invoke = React29.useCallback(async (endpoint, payload = {}, signal) => {
17114
17510
  if (typeof rpcCall !== "function") {
17115
17511
  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
17512
  unavailable.code = "update-unavailable";
@@ -17118,7 +17514,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17118
17514
  }
17119
17515
  return unwrapSnapshot(await rpcCall(endpoint, payload, signal));
17120
17516
  }, [rpcCall]);
17121
- React28.useEffect(() => {
17517
+ React29.useEffect(() => {
17122
17518
  mounted.current = true;
17123
17519
  busy.current = true;
17124
17520
  const controller = new AbortController();
@@ -17141,7 +17537,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17141
17537
  const activeJob = ACTIVE_STATES4.has(snapshot?.job?.state);
17142
17538
  const restartRequired = snapshot?.job?.state === "restart-required" || snapshot?.blockedReason === "pending-restart";
17143
17539
  const shouldPoll = activeJob || uncertainInstall;
17144
- React28.useEffect(() => {
17540
+ React29.useEffect(() => {
17145
17541
  if (!shouldPoll) return void 0;
17146
17542
  let controller;
17147
17543
  const scheduler = createPollScheduler({
@@ -17239,7 +17635,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17239
17635
  const manualCommand = manualUpdateCommand(snapshot);
17240
17636
  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
17637
  return h2(
17242
- React28.Fragment,
17638
+ React29.Fragment,
17243
17639
  null,
17244
17640
  h2("button", {
17245
17641
  type: "button",
@@ -17264,13 +17660,13 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
17264
17660
  h2("dt", null, "\u8FD0\u884C\u7248\u672C"),
17265
17661
  h2("dd", null, `v${snapshot?.runningVersion ?? clientVersion}`),
17266
17662
  snapshot?.installedVersion && snapshot.installedVersion !== snapshot.runningVersion ? h2(
17267
- React28.Fragment,
17663
+ React29.Fragment,
17268
17664
  null,
17269
17665
  h2("dt", null, "\u5DF2\u5B89\u88C5\u7248\u672C"),
17270
17666
  h2("dd", null, `v${snapshot.installedVersion}`)
17271
17667
  ) : null,
17272
17668
  targetVersion ? h2(
17273
- React28.Fragment,
17669
+ React29.Fragment,
17274
17670
  null,
17275
17671
  h2("dt", null, "\u76EE\u6807\u7248\u672C"),
17276
17672
  h2("dd", null, `v${targetVersion}`)
@@ -17491,23 +17887,23 @@ function IMSettingsTab({
17491
17887
  browserLocation = globalThis.location,
17492
17888
  navigateToRecoveryUrl = replacePageLocation
17493
17889
  }) {
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();
17890
+ const [selected, setSelected] = React30.useState("weixin");
17891
+ const [loopbackRecovery, setLoopbackRecovery] = React30.useState(null);
17892
+ const [runningVersion, setRunningVersion] = React30.useState(IM_PLUGIN_VERSION);
17893
+ const [deliverySettings, setDeliverySettings] = React30.useState(null);
17894
+ const githubTooltipId = React30.useId();
17895
+ const generalSettingsTooltipId = React30.useId();
17500
17896
  const globalSettingsSelected = selected === GLOBAL_SETTINGS_TAB_ID;
17501
17897
  const active = CHANNELS.find((channel5) => channel5.id === selected) ?? CHANNELS[0];
17502
17898
  const activeTabId = globalSettingsSelected ? "dim-general-settings-trigger" : `dim-tab-${active.id}`;
17503
17899
  const activePanelId = globalSettingsSelected ? `dim-panel-${GLOBAL_SETTINGS_TAB_ID}` : `dim-panel-${active.id}`;
17504
- const reportLoopbackRecovery = React29.useCallback((recovery) => {
17900
+ const reportLoopbackRecovery = React30.useCallback((recovery) => {
17505
17901
  setLoopbackRecovery((current) => current?.url === recovery.url ? current : recovery);
17506
17902
  }, []);
17507
- const reportUpdateStatus = React29.useCallback((snapshot) => {
17903
+ const reportUpdateStatus = React30.useCallback((snapshot) => {
17508
17904
  setRunningVersion(snapshot.runningVersion);
17509
17905
  }, []);
17510
- const rpcCalls = React29.useMemo(() => createLoopbackAwareRpcCalls({
17906
+ const rpcCalls = React30.useMemo(() => createLoopbackAwareRpcCalls({
17511
17907
  dingtalkRpcCall,
17512
17908
  discordRpcCall,
17513
17909
  feishuRpcCall,
@@ -17545,7 +17941,7 @@ function IMSettingsTab({
17545
17941
  weixinRpcCall,
17546
17942
  whatsappRpcCall
17547
17943
  ]);
17548
- const botSettingsContext = React29.useMemo(() => Object.freeze({
17944
+ const botSettingsContext = React30.useMemo(() => Object.freeze({
17549
17945
  openBotSettings: setDeliverySettings
17550
17946
  }), []);
17551
17947
  return h2(