dsh-dock 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/client.js CHANGED
@@ -41,7 +41,7 @@ __export(client_exports, {
41
41
  inject: () => inject
42
42
  });
43
43
  module.exports = __toCommonJS(client_exports);
44
- var import_react8 = __toESM(require("react"), 1);
44
+ var import_react9 = __toESM(require("react"), 1);
45
45
 
46
46
  // src/shared.js
47
47
  var import_react = __toESM(require("react"), 1);
@@ -722,7 +722,7 @@ function TokenLogChip(props) {
722
722
  }, [sid]);
723
723
  if (!sid) return null;
724
724
  const t = snap.totals;
725
- const label = snap.err && !t ? snap.err.includes("\u91CD\u542F") ? "\u7528\u91CF\xB7\u9700\u91CD\u542F\u5BBF\u4E3B" : "\u7528\u91CF\xB7\u5931\u8D25" : t ? "\u26C1 " + fmtCompact(t.totalTokens) + (t.cost > 0 ? " \xB7 " + fmtCost(t.cost) : "") : "\u26C1 \u2026";
725
+ const label = snap.err && !t ? snap.err.includes("\u91CD\u542F") ? "\u7528\u91CF\xB7\u9700\u91CD\u542F\u5BBF\u4E3B" : "\u7528\u91CF\xB7\u5931\u8D25" : t ? "\u26C1 " + fmtCompact(t.totalTokens) + (t.cost > 0 ? " \xB7 $" + t.cost.toFixed(2) : "") : "\u26C1 \u2026";
726
726
  const title = t ? "\u672C\u4F1A\u8BDD " + fmtNum(t.calls) + " \u6B21\u8C03\u7528 \xB7 " + fmtNum(t.totalTokens) + " Token \xB7 " + fmtCost(t.cost) + "\uFF08\u4F30\u7B97\uFF09\n\u70B9\u51FB\u5728\u529F\u80FD\u575E\u67E5\u770B\u7528\u91CF\u8BB0\u5F55" : (snap.err ? snap.err + "\n" : "") + "\u70B9\u51FB\u5728\u529F\u80FD\u575E\u67E5\u770B\u7528\u91CF\u8BB0\u5F55";
727
727
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
728
728
  "button",
@@ -768,8 +768,8 @@ var modelsStore = {
768
768
  },
769
769
  load() {
770
770
  if (this.snap.loading) return;
771
- this.set({ loading: true });
772
- fetch("/dsh-dock/models", { signal: AbortSignal.timeout(2e4) }).then((res) => res.ok ? res.json() : Promise.reject(new Error("\u6A21\u578B\u76EE\u5F55\u63A5\u53E3 HTTP " + res.status))).then((data) => this.set({ data, loading: false, error: null })).catch((e) => this.set({ loading: false, error: e && e.message || String(e) }));
771
+ this.set({ loading: true, error: null });
772
+ fetch("/dsh-dock/models", { cache: "no-store", signal: AbortSignal.timeout(2e4) }).then((res) => res.ok ? res.json() : Promise.reject(new Error("\u6A21\u578B\u76EE\u5F55\u63A5\u53E3 HTTP " + res.status))).then((data) => this.set({ data, loading: false, error: null })).catch((e) => this.set({ loading: false, error: e && e.message || String(e) }));
773
773
  }
774
774
  };
775
775
  function useModels() {
@@ -826,6 +826,14 @@ function ModelsView() {
826
826
  const [vpDirty, setVpDirty] = import_react3.default.useState(false);
827
827
  const [vpSaving, setVpSaving] = import_react3.default.useState(false);
828
828
  const [vpMsg, setVpMsg] = import_react3.default.useState(null);
829
+ const [vpDirectExpanded, setVpDirectExpanded] = import_react3.default.useState(false);
830
+ import_react3.default.useEffect(() => {
831
+ modelsStore.load();
832
+ }, []);
833
+ const refreshModels = () => {
834
+ setBuiltKey(null);
835
+ modelsStore.load();
836
+ };
829
837
  const cur = providers.length > 0 ? providers.find((p) => p.id === selId) || providers[0] : null;
830
838
  const wantKey = cur ? cur.id + ":" + String(data && data.generatedAt || 0) : null;
831
839
  if (cur && builtKey !== wantKey) {
@@ -944,7 +952,7 @@ function ModelsView() {
944
952
  {
945
953
  key: v,
946
954
  className: "dkm-check",
947
- title: v === "image" ? "\u52FE\u9009=\u7AEF\u70B9\u539F\u751F\u652F\u6301\u56FE\u7247\uFF08\u539F\u56FE\u76F4\u53D1\uFF0C\u56FE\u7247\u7406\u89E3\u4EE3\u7406\u8DF3\u8FC7\uFF09\uFF1B\u7EAF\u6587\u672C\u6A21\u578B\u52FF\u52FE\u2014\u2014\u6536\u56FE\u4F1A\u81EA\u52A8\u4EA4\u7ED9\u56FE\u7247\u7406\u89E3\u4EE3\u7406\u8BC6\u522B" : null
955
+ title: v === "image" ? "\u7531\u4F60\u58F0\u660E\u8BE5\u7AEF\u70B9\u652F\u6301\u56FE\u7247\uFF1A\u4FDD\u5B58\u540E\u539F\u56FE\u76F4\u53D1\uFF0C\u5E76\u53EF\u4F5C\u4E3A\u89C6\u89C9\u6A21\u578B\u5019\u9009\u3002\u7CFB\u7EDF\u4E0D\u4F1A\u66FF\u4F60\u731C\u6D4B\uFF1B\u7AEF\u70B9\u5B9E\u9645\u4E0D\u652F\u6301\u65F6\u53D6\u6D88\u52FE\u9009\u5373\u53EF\u6062\u590D\u8D70\u56FE\u7247\u7406\u89E3\u4EE3\u7406" : null
948
956
  },
949
957
  import_react3.default.createElement("input", {
950
958
  type: "checkbox",
@@ -1007,6 +1015,14 @@ function ModelsView() {
1007
1015
  )
1008
1016
  );
1009
1017
  const body = [];
1018
+ if (data) {
1019
+ body.push(import_react3.default.createElement(
1020
+ "div",
1021
+ { key: "refresh", className: "dkm-topbar" },
1022
+ import_react3.default.createElement("span", { className: "dkm-sub" }, "\u5DF2\u8F7D\u5165 " + providers.length + " \u4E2A Provider\uFF1B\u5728 DSH \u539F\u751F\u6A21\u578B\u8BBE\u7F6E\u4E2D\u65B0\u589E\u540E\uFF0C\u8FD4\u56DE\u672C\u9875\u4F1A\u81EA\u52A8\u66F4\u65B0"),
1023
+ import_react3.default.createElement("button", { type: "button", className: "dkb-refresh", disabled: snap.loading || saving, onClick: refreshModels }, snap.loading ? "\u5237\u65B0\u4E2D\u2026" : "\u5237\u65B0\u6A21\u578B\u76EE\u5F55")
1024
+ ));
1025
+ }
1010
1026
  if (snap.error) {
1011
1027
  body.push(import_react3.default.createElement(
1012
1028
  "div",
@@ -1025,13 +1041,23 @@ function ModelsView() {
1025
1041
  ));
1026
1042
  }
1027
1043
  if (data && data.visionProxy !== void 0 && vpDraft) {
1028
- const effInput = (m) => (m.runtimeInput && m.runtimeInput.length > 0 ? m.runtimeInput : m.input) || [];
1044
+ const runtimeImage = (m) => Array.isArray(m.runtimeInput) && m.runtimeInput.indexOf("image") >= 0;
1045
+ const declaredImage = (m) => Array.isArray(m.input) && m.input.indexOf("image") >= 0;
1029
1046
  const vpDirect = [];
1030
1047
  const vpProxied = [];
1031
1048
  for (const p of providers) {
1032
1049
  for (const m of p.models || []) {
1033
- const item = { key: p.id + "/" + m.id, label: (p.displayName || p.id) + " / " + (m.name || m.id), model: m.name || m.id };
1034
- (effInput(m).indexOf("image") >= 0 ? vpDirect : vpProxied).push(item);
1050
+ const declared = declaredImage(m);
1051
+ const runtime = runtimeImage(m);
1052
+ const source = declared ? "\u4F60\u5DF2\u6807\u8BB0\u56FE\u7247" : runtime ? "\u8FD0\u884C\u65F6\u8BC6\u522B" : "\u672A\u6807\u8BB0\u56FE\u7247";
1053
+ const item = {
1054
+ key: p.id + "/" + m.id,
1055
+ label: (p.displayName || p.id) + " / " + (m.name || m.id) + "\uFF08" + source + "\uFF09",
1056
+ model: m.name || m.id,
1057
+ source,
1058
+ declared
1059
+ };
1060
+ (declared || runtime ? vpDirect : vpProxied).push(item);
1035
1061
  }
1036
1062
  }
1037
1063
  const vpCandidates = vpDirect.slice();
@@ -1086,23 +1112,37 @@ function ModelsView() {
1086
1112
  !vpKnown && vpDraft.provider ? import_react3.default.createElement("option", { value: vpKey }, vpDraft.provider + " / " + vpDraft.model + "\uFF08\u5F53\u524D\uFF09") : null,
1087
1113
  vpCandidates.map((c) => import_react3.default.createElement("option", { key: c.key, value: c.key }, c.label))
1088
1114
  ),
1089
- vpCandidates.length === 0 ? import_react3.default.createElement("span", { className: "dkm-sub" }, "\u76EE\u5F55\u91CC\u6682\u65E0\u591A\u6A21\u6001\u6A21\u578B\u2014\u2014\u5148\u5728\u4E0B\u65B9\u7ED9\u771F\xB7\u591A\u6A21\u6001\u6A21\u578B\u52FE\u9009\u300C\u56FE\u7247\u300D\u8F93\u5165\u7C7B\u578B") : null
1115
+ vpCandidates.length === 0 ? import_react3.default.createElement("span", { className: "dkm-sub" }, "\u8FD8\u6CA1\u6709\u6807\u8BB0\u56FE\u7247\u80FD\u529B\u7684\u6A21\u578B\u2014\u2014\u5728\u4E0B\u65B9\u7ED9\u4F60\u786E\u8BA4\u652F\u6301\u56FE\u7247\u7684\u6A21\u578B\u52FE\u9009\u300C\u56FE\u7247\u300D\u5E76\u4FDD\u5B58") : null
1090
1116
  ),
1091
1117
  import_react3.default.createElement(
1092
1118
  "div",
1093
1119
  { className: "dkm-sub" },
1094
- "\u5224\u5B9A\u4E0E\u5B98\u65B9\u8FD0\u884C\u65F6\u540C\u6E90\uFF1A\u300C\u56FE\u7247\u300D\u52FE\u9009\uFF08\u6216\u76EE\u5F55\u9ED8\u8BA4\uFF09= \u7AEF\u70B9\u539F\u751F\u652F\u6301\u3001\u539F\u56FE\u76F4\u53D1\uFF1B\u5176\u4F59\u6A21\u578B\u6536\u56FE\u81EA\u52A8\u8D70\u89C6\u89C9\u6A21\u578B\u3002\u6CE8\u610F\uFF1A\u82E5\u7AEF\u70B9\u5B9E\u9645\u4E0D\u8BA4\u56FE\u5374\u52FE\u4E86\u300C\u56FE\u7247\u300D\uFF0C\u6A21\u578B\u4F1A\u770B\u4E0D\u89C1\u56FE\u7247\u3001\u8F6C\u800C\u7528\u5DE5\u5177\u778E\u6298\u817E\u2014\u2014\u4E0D\u786E\u5B9A\u5C31\u4E0D\u8981\u52FE\uFF0C\u4EA4\u7ED9\u4EE3\u7406\u3002"
1120
+ "\u4EE5\u4F60\u5728\u4E0B\u65B9\u52FE\u9009\u7684\u300C\u56FE\u7247\u300D\u4E3A\u51C6\uFF1B\u8FD0\u884C\u65F6\u8BC6\u522B\u53EA\u662F\u8F85\u52A9\u63D0\u793A\u3002\u5B83\u4E0D\u4EE3\u8868\u5DF2\u8054\u7F51\u5B9E\u6D4B\u53EF\u8C03\u7528\uFF0C\u5B9E\u9645\u53EF\u7528\u6027\u4ECD\u53D6\u51B3\u4E8E Provider \u51ED\u636E\u3001\u989D\u5EA6\u4E0E\u4E0A\u6E38\u670D\u52A1\u3002\u82E5\u7AEF\u70B9\u5B9E\u9645\u4E0D\u8BA4\u56FE\uFF0C\u53D6\u6D88\u8BE5\u6A21\u578B\u7684\u300C\u56FE\u7247\u300D\u52FE\u9009\u5373\u53EF\u6062\u590D\u8D70\u56FE\u7247\u7406\u89E3\u4EE3\u7406\u3002"
1095
1121
  ),
1096
1122
  vpDirect.length > 0 ? import_react3.default.createElement(
1097
1123
  "div",
1098
- { className: "dkm-checks" },
1099
- import_react3.default.createElement("span", { className: "dkm-label" }, "\u539F\u56FE\u76F4\u53D1\uFF08\u591A\u6A21\u6001\uFF0C" + vpDirect.length + "\uFF09\uFF1A"),
1100
- vpDirect.map((c) => import_react3.default.createElement("span", { key: c.key, className: "dkm-chip", title: c.key }, c.model))
1124
+ { className: "dkm-capabilities" },
1125
+ import_react3.default.createElement(
1126
+ "div",
1127
+ { className: "dkm-checks" },
1128
+ import_react3.default.createElement("span", { className: "dkm-label" }, "\u539F\u56FE\u76F4\u53D1\u5019\u9009\uFF08\u4F60\u7684\u6807\u8BB0\u4F18\u5148\uFF0C" + vpDirect.length + "\uFF09\uFF1A"),
1129
+ import_react3.default.createElement("button", {
1130
+ type: "button",
1131
+ className: "dkm-mini",
1132
+ "aria-expanded": vpDirectExpanded,
1133
+ onClick: () => setVpDirectExpanded(!vpDirectExpanded)
1134
+ }, vpDirectExpanded ? "\u6536\u8D77\u5217\u8868" : "\u5C55\u5F00\u5217\u8868")
1135
+ ),
1136
+ vpDirectExpanded ? import_react3.default.createElement(
1137
+ "div",
1138
+ { className: "dkm-checks dkm-capability-list" },
1139
+ vpDirect.map((c) => import_react3.default.createElement("span", { key: c.key, className: "dkm-chip", title: c.key + " \xB7 " + c.source }, c.model))
1140
+ ) : null
1101
1141
  ) : null,
1102
1142
  vpProxied.length > 0 ? import_react3.default.createElement(
1103
1143
  "div",
1104
1144
  { className: "dkm-checks" },
1105
- import_react3.default.createElement("span", { className: "dkm-label" }, "\u8D70\u89C6\u89C9\u4EE3\u7406\uFF08\u7EAF\u6587\u672C\uFF0C" + vpProxied.length + "\uFF09\uFF1A"),
1145
+ import_react3.default.createElement("span", { className: "dkm-label" }, "\u8D70\u89C6\u89C9\u4EE3\u7406\uFF08\u672A\u6807\u8BB0\u56FE\u7247\uFF0C" + vpProxied.length + "\uFF09\uFF1A"),
1106
1146
  import_react3.default.createElement("span", { className: "dkm-sub" }, vpProxied.map((c) => c.model).join("\u3001"))
1107
1147
  ) : null,
1108
1148
  import_react3.default.createElement(
@@ -1182,10 +1222,7 @@ function ModelsView() {
1182
1222
  { className: "dkm-savebar" },
1183
1223
  import_react3.default.createElement("span", { className: "dkm-msg" }, dirty ? "\u6709\u672A\u4FDD\u5B58\u7684\u4FEE\u6539" : "\u65E0\u672A\u4FDD\u5B58\u4FEE\u6539"),
1184
1224
  import_react3.default.createElement("button", { type: "button", className: "dkm-save", disabled: !dirty || saving, onClick: save }, saving ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58\u5199\u56DE\u5B98\u65B9\u914D\u7F6E"),
1185
- import_react3.default.createElement("button", { type: "button", className: "dkb-refresh", disabled: saving, onClick: () => {
1186
- setBuiltKey(null);
1187
- modelsStore.load();
1188
- } }, "\u91CD\u65B0\u62C9\u53D6"),
1225
+ import_react3.default.createElement("button", { type: "button", className: "dkb-refresh", disabled: saving || snap.loading, onClick: refreshModels }, snap.loading ? "\u5237\u65B0\u4E2D\u2026" : "\u91CD\u65B0\u62C9\u53D6"),
1189
1226
  msg ? import_react3.default.createElement("span", { className: "dkm-msg " + (msg.ok ? "ok" : "err") }, msg.text) : null
1190
1227
  )
1191
1228
  ));
@@ -1244,6 +1281,9 @@ var feature2 = {
1244
1281
  ".dkm-msg.ok{color:var(--dsw-alias-state-success-primary);}",
1245
1282
  ".dkm-msg.err{color:var(--dsw-alias-state-error-primary);}",
1246
1283
  ".dkm-list{display:flex;flex-direction:column;gap:8px;}",
1284
+ ".dkm-topbar{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;}",
1285
+ ".dkm-capabilities{display:flex;flex-direction:column;gap:6px;}",
1286
+ ".dkm-capability-list{max-height:168px;overflow:auto;padding:2px 0 2px 2px;}",
1247
1287
  ".dkm-ro{color:var(--dsw-alias-label-secondary);font-size:12px;}",
1248
1288
  ".dkm-mini{cursor:pointer;border:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-tertiary);border-radius:999px;padding:1px 8px;font-family:inherit;font-size:11px;flex:none;}",
1249
1289
  ".dkm-mini:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-secondary);}",
@@ -1286,40 +1326,64 @@ var feature3 = {
1286
1326
 
1287
1327
  // features/theme/view.js
1288
1328
  var import_react5 = __toESM(require("react"), 1);
1289
- function readThemeLabel(ctx) {
1329
+ var import_react6 = require("react");
1330
+ var PREFERENCE_LABELS = { light: "\u4EAE\u8272", dark: "\u6697\u8272", system: "\u8DDF\u968F\u7CFB\u7EDF" };
1331
+ var THEME_LABELS = { light: "\u4EAE\u8272", dark: "\u6697\u8272" };
1332
+ function readThemeInfo(ctx) {
1290
1333
  const theme = ctx && ctx.get ? ctx.get("theme") : void 0;
1291
- if (theme === void 0) return { err: "theme \u670D\u52A1\u4E0D\u53EF\u7528" };
1334
+ if (!theme || typeof theme.getTheme !== "function") return { err: "theme \u670D\u52A1\u4E0D\u53EF\u7528" };
1292
1335
  let snap = null;
1293
1336
  try {
1294
1337
  snap = theme.getTheme();
1295
1338
  } catch (err) {
1296
1339
  return { err: "\u8BFB\u53D6\u5931\u8D25\uFF1A" + String(err && err.message || err) };
1297
1340
  }
1298
- const label = snap && typeof snap.id === "string" ? snap.id : snap && typeof snap.name === "string" ? snap.name : "\u672A\u77E5";
1341
+ const preference = snap && typeof snap.preference === "string" ? snap.preference : "";
1342
+ const activeId = snap && snap.active && typeof snap.active.id === "string" ? snap.active.id : "";
1343
+ const label = (PREFERENCE_LABELS[preference] || preference || "\u672A\u77E5") + (activeId && activeId !== preference && THEME_LABELS[activeId] ? "\uFF08\u5B9E\u9645" + THEME_LABELS[activeId] + "\uFF09" : "");
1299
1344
  return { label };
1300
1345
  }
1346
+ function useThemeInfo(ctx) {
1347
+ const [info, setInfo] = (0, import_react6.useState)(() => readThemeInfo(ctx));
1348
+ (0, import_react6.useEffect)(() => {
1349
+ let off = null;
1350
+ try {
1351
+ if (ctx && typeof ctx.on === "function") {
1352
+ off = ctx.on("theme/change", () => setInfo(readThemeInfo(ctx)));
1353
+ }
1354
+ } catch {
1355
+ }
1356
+ return () => {
1357
+ try {
1358
+ if (typeof off === "function") off();
1359
+ } catch {
1360
+ }
1361
+ };
1362
+ }, [ctx]);
1363
+ return info;
1364
+ }
1301
1365
  function ThemeView(props) {
1302
- const r = readThemeLabel(props && props.ctx);
1366
+ const r = useThemeInfo(props && props.ctx);
1303
1367
  if (r.err) return import_react5.default.createElement("div", null, r.err);
1304
1368
  return import_react5.default.createElement("div", null, "\u5F53\u524D\u4E3B\u9898\uFF1A" + r.label);
1305
1369
  }
1306
1370
  function ThemeStat(props) {
1307
- const r = readThemeLabel(props && props.ctx);
1371
+ const r = useThemeInfo(props && props.ctx);
1308
1372
  if (r.err) return import_react5.default.createElement("span", null, r.err);
1309
- return import_react5.default.createElement("span", null, "\u5F53\u524D\u4E3B\u9898\uFF1A" + r.label);
1373
+ return import_react5.default.createElement("span", null, "\u4E3B\u9898\uFF1A" + r.label);
1310
1374
  }
1311
1375
  var feature4 = {
1312
1376
  id: "theme",
1313
1377
  name: "\u4E3B\u9898\u4FE1\u606F",
1314
1378
  order: 150,
1315
1379
  accent: "#a78bfa",
1316
- description: "\u793A\u4F8B\u529F\u80FD\uFF1A\u8BFB\u53D6\u5F53\u524D\u4E3B\u9898\u5FEB\u7167\uFF08\u7EAF Client\uFF09",
1380
+ description: "\u8BFB\u53D6\u5F53\u524D\u4E3B\u9898\u5FEB\u7167\uFF1A\u504F\u597D\u4E0E\u5B9E\u9645\u751F\u6548\u4E3B\u9898\uFF08\u7EAF Client\uFF0C\u4E3B\u9898\u5207\u6362\u5B9E\u65F6\u5237\u65B0\uFF09",
1317
1381
  View: ThemeView,
1318
1382
  HomeStat: ThemeStat
1319
1383
  };
1320
1384
 
1321
1385
  // features/balance/view.js
1322
- var import_react6 = __toESM(require("react"), 1);
1386
+ var import_react7 = __toESM(require("react"), 1);
1323
1387
  var ACCENT_PALETTE = ["#4d9fff", "#34d399", "#fbbf24", "#a78bfa", "#f472b6", "#38bdf8", "#fb923c", "#4ade80", "#e879f9", "#22d3ee"];
1324
1388
  var CURATED_ACCENTS = {
1325
1389
  "deepseek-official": "#4d9fff",
@@ -1361,8 +1425,8 @@ var balanceStore = {
1361
1425
  }
1362
1426
  };
1363
1427
  function useBalance(ctx) {
1364
- const [snap, setSnap] = import_react6.default.useState(balanceStore.snap);
1365
- import_react6.default.useEffect(() => {
1428
+ const [snap, setSnap] = import_react7.default.useState(balanceStore.snap);
1429
+ import_react7.default.useEffect(() => {
1366
1430
  const off = balanceStore.subscribe(() => setSnap(balanceStore.snap));
1367
1431
  if (!balanceStore.snap.data && !balanceStore.snap.loading) balanceStore.load();
1368
1432
  const disposer = ctx && typeof ctx.interval === "function" ? ctx.interval(() => balanceStore.load(), 5 * 60 * 1e3) : null;
@@ -1376,7 +1440,7 @@ function useBalance(ctx) {
1376
1440
  function BalanceView(props) {
1377
1441
  const snap = useBalance(props && props.ctx);
1378
1442
  const load = () => balanceStore.load();
1379
- import_react6.default.useEffect(() => {
1443
+ import_react7.default.useEffect(() => {
1380
1444
  const pid = props && props.params && props.params.provider;
1381
1445
  if (!pid || typeof document === "undefined") return;
1382
1446
  const t = setTimeout(() => {
@@ -1399,15 +1463,15 @@ function BalanceView(props) {
1399
1463
  const def = data && data.default ? data.default.provider : null;
1400
1464
  const body = [];
1401
1465
  if (snap.error) {
1402
- body.push(import_react6.default.createElement("div", { key: "err", className: "dkb-note dkb-error" }, "\u4F59\u989D\u67E5\u8BE2\u5931\u8D25\uFF1A" + snap.error));
1466
+ body.push(import_react7.default.createElement("div", { key: "err", className: "dkb-note dkb-error" }, "\u4F59\u989D\u67E5\u8BE2\u5931\u8D25\uFF1A" + snap.error));
1403
1467
  } else if (!data) {
1404
- body.push(import_react6.default.createElement("div", { key: "loading", className: "dkb-note" }, snap.loading ? "\u6B63\u5728\u62C9\u53D6\u4F59\u989D\u2026" : "\u8FD8\u6CA1\u6709\u6570\u636E\uFF0C\u70B9\u51FB\u4E0B\u65B9\u5237\u65B0"));
1468
+ body.push(import_react7.default.createElement("div", { key: "loading", className: "dkb-note" }, snap.loading ? "\u6B63\u5728\u62C9\u53D6\u4F59\u989D\u2026" : "\u8FD8\u6CA1\u6709\u6570\u636E\uFF0C\u70B9\u51FB\u4E0B\u65B9\u5237\u65B0"));
1405
1469
  } else if (providers.length === 0) {
1406
- body.push(import_react6.default.createElement("div", { key: "empty", className: "dkb-note" }, "\u6CA1\u6709\u627E\u5230\u5DF2\u914D\u7F6E\u7684\u6A21\u578B Provider"));
1470
+ body.push(import_react7.default.createElement("div", { key: "empty", className: "dkb-note" }, "\u6CA1\u6709\u627E\u5230\u5DF2\u914D\u7F6E\u7684\u6A21\u578B Provider"));
1407
1471
  } else {
1408
1472
  const rank = (p) => p.balance && p.balance.status === "ok" ? 0 : p.balance && p.balance.status === "login-required" ? 1 : 2;
1409
1473
  const sorted = providers.slice().sort((a, b) => rank(a) - rank(b));
1410
- body.push(import_react6.default.createElement(
1474
+ body.push(import_react7.default.createElement(
1411
1475
  "div",
1412
1476
  { key: "rows", className: "dkb-rows" },
1413
1477
  sorted.map((p) => {
@@ -1424,73 +1488,73 @@ function BalanceView(props) {
1424
1488
  let balBody = null;
1425
1489
  if (b && b.status === "ok" && b.kind === "quota") {
1426
1490
  const dims = Array.isArray(b.dims) ? b.dims : [];
1427
- balBody = import_react6.default.createElement(
1428
- import_react6.default.Fragment,
1491
+ balBody = import_react7.default.createElement(
1492
+ import_react7.default.Fragment,
1429
1493
  null,
1430
- import_react6.default.createElement(
1494
+ import_react7.default.createElement(
1431
1495
  "div",
1432
1496
  { className: "dkb-main" },
1433
- import_react6.default.createElement("span", { className: "dkb-main-label" }, "\u5269\u4F59\u989D\u5EA6"),
1434
- import_react6.default.createElement("span", { className: "dkb-main-value" }, fmt(b.remaining) + (b.unit ? " " + b.unit : "")),
1435
- import_react6.default.createElement(
1497
+ import_react7.default.createElement("span", { className: "dkb-main-label" }, "\u5269\u4F59\u989D\u5EA6"),
1498
+ import_react7.default.createElement("span", { className: "dkb-main-value" }, fmt(b.remaining) + (b.unit ? " " + b.unit : "")),
1499
+ import_react7.default.createElement(
1436
1500
  "span",
1437
1501
  { className: "dkb-main-part" },
1438
1502
  "\u5DF2\u7528 " + fmt(b.used) + " / \u603B " + fmt(b.limit),
1439
- b.resetTime ? import_react6.default.createElement("span", null, " \xB7 \u91CD\u7F6E " + String(b.resetTime).slice(0, 10)) : null
1503
+ b.resetTime ? import_react7.default.createElement("span", null, " \xB7 \u91CD\u7F6E " + String(b.resetTime).slice(0, 10)) : null
1440
1504
  )
1441
1505
  ),
1442
- dims.map((d, i) => import_react6.default.createElement(
1506
+ dims.map((d, i) => import_react7.default.createElement(
1443
1507
  "div",
1444
1508
  { key: "d" + i, className: "dkb-dim" },
1445
- import_react6.default.createElement("span", { className: "dkb-dim-label" }, d.window === "weekly" ? "\u5468\u989D\u5EA6" : "\u5C0F\u65F6\u989D\u5EA6"),
1446
- import_react6.default.createElement(
1509
+ import_react7.default.createElement("span", { className: "dkb-dim-label" }, d.window === "weekly" ? "\u5468\u989D\u5EA6" : "\u5C0F\u65F6\u989D\u5EA6"),
1510
+ import_react7.default.createElement(
1447
1511
  "span",
1448
1512
  { className: "dkb-dim-bar" },
1449
- import_react6.default.createElement("span", { className: "dkb-dim-fill", style: { width: (d.limit > 0 ? Math.min(100, Math.round(d.remaining / d.limit * 100)) : 0) + "%" } })
1513
+ import_react7.default.createElement("span", { className: "dkb-dim-fill", style: { width: (d.limit > 0 ? Math.min(100, Math.round(d.remaining / d.limit * 100)) : 0) + "%" } })
1450
1514
  ),
1451
- import_react6.default.createElement("span", { className: "dkb-dim-text" }, "\u5269 " + fmt(d.remaining) + " / " + fmt(d.limit))
1515
+ import_react7.default.createElement("span", { className: "dkb-dim-text" }, "\u5269 " + fmt(d.remaining) + " / " + fmt(d.limit))
1452
1516
  ))
1453
1517
  );
1454
1518
  } else if (b && b.status === "ok") {
1455
1519
  const infos = Array.isArray(b.infos) ? b.infos : [];
1456
- balBody = import_react6.default.createElement(
1520
+ balBody = import_react7.default.createElement(
1457
1521
  "div",
1458
1522
  { className: "dkb-mains" },
1459
- infos.map((i, idx) => import_react6.default.createElement(
1523
+ infos.map((i, idx) => import_react7.default.createElement(
1460
1524
  "div",
1461
1525
  { key: idx, className: "dkb-main" },
1462
- import_react6.default.createElement("span", { className: "dkb-main-label", style: { color: accent } }, i.currency),
1463
- import_react6.default.createElement("span", { className: "dkb-main-value" }, fmt(i.totalBalance)),
1464
- import_react6.default.createElement(
1526
+ import_react7.default.createElement("span", { className: "dkb-main-label", style: { color: accent } }, i.currency),
1527
+ import_react7.default.createElement("span", { className: "dkb-main-value" }, fmt(i.totalBalance)),
1528
+ import_react7.default.createElement(
1465
1529
  "span",
1466
1530
  { className: "dkb-main-parts" },
1467
- i.grantedBalance != null ? import_react6.default.createElement("span", { className: "dkb-main-part", style: { color: C_GRANTED } }, "\u8D60\u9001 " + fmt(i.grantedBalance)) : null,
1468
- i.toppedUpBalance != null ? import_react6.default.createElement("span", { className: "dkb-main-part", style: { color: C_TOPUP } }, "\u5145\u503C " + fmt(i.toppedUpBalance)) : null
1531
+ i.grantedBalance != null ? import_react7.default.createElement("span", { className: "dkb-main-part", style: { color: C_GRANTED } }, "\u8D60\u9001 " + fmt(i.grantedBalance)) : null,
1532
+ i.toppedUpBalance != null ? import_react7.default.createElement("span", { className: "dkb-main-part", style: { color: C_TOPUP } }, "\u5145\u503C " + fmt(i.toppedUpBalance)) : null
1469
1533
  )
1470
1534
  ))
1471
1535
  );
1472
1536
  } else if (b && b.status === "login-required" && b.consoleUrl) {
1473
- balBody = import_react6.default.createElement(
1537
+ balBody = import_react7.default.createElement(
1474
1538
  "div",
1475
1539
  { className: "dkb-main" },
1476
- import_react6.default.createElement("a", { href: b.consoleUrl, target: "_blank", rel: "noreferrer", className: "dkb-link", style: { color: accent } }, "\u53BB\u63A7\u5236\u53F0\u67E5\u770B\u4F59\u989D \u2192")
1540
+ import_react7.default.createElement("a", { href: b.consoleUrl, target: "_blank", rel: "noreferrer", className: "dkb-link", style: { color: accent } }, "\u53BB\u63A7\u5236\u53F0\u67E5\u770B\u4F59\u989D \u2192")
1477
1541
  );
1478
1542
  } else {
1479
- balBody = b && b.message ? import_react6.default.createElement("div", { className: "dkb-note" }, b.message) : import_react6.default.createElement("div", { className: "dkb-note" }, "\u8BE5 Provider \u6CA1\u6709\u5DF2\u77E5\u7684\u4F59\u989D\u67E5\u8BE2\u63A5\u53E3");
1543
+ balBody = b && b.message ? import_react7.default.createElement("div", { className: "dkb-note" }, b.message) : import_react7.default.createElement("div", { className: "dkb-note" }, "\u8BE5 Provider \u6CA1\u6709\u5DF2\u77E5\u7684\u4F59\u989D\u67E5\u8BE2\u63A5\u53E3");
1480
1544
  }
1481
1545
  const sub = ["ID " + p.id, p.api, p.baseURL ? p.baseURL.replace(/^https?:\/\//, "") : null].filter(Boolean).join(" \xB7 ");
1482
- return import_react6.default.createElement(
1546
+ return import_react7.default.createElement(
1483
1547
  "div",
1484
1548
  { key: p.id, className: "dkb-row", "data-dock-provider": p.id },
1485
- import_react6.default.createElement(
1549
+ import_react7.default.createElement(
1486
1550
  "div",
1487
1551
  { className: "dkb-row-head" },
1488
- import_react6.default.createElement("span", { className: "dkb-dot", style: { background: accent } }),
1489
- import_react6.default.createElement("span", { className: "dkb-name", style: { color: accent } }, p.displayName),
1490
- def === p.id ? import_react6.default.createElement("span", { className: "dkb-default" }, "\u9ED8\u8BA4") : null,
1491
- import_react6.default.createElement("span", { className: "dkb-badge" + (badge[1] ? " " + badge[1] : ""), style: badge[1] === "err" ? { color: C_ERR, borderColor: C_ERR } : null }, badge[0]),
1552
+ import_react7.default.createElement("span", { className: "dkb-dot", style: { background: accent } }),
1553
+ import_react7.default.createElement("span", { className: "dkb-name", style: { color: accent } }, p.displayName),
1554
+ def === p.id ? import_react7.default.createElement("span", { className: "dkb-default" }, "\u9ED8\u8BA4") : null,
1555
+ import_react7.default.createElement("span", { className: "dkb-badge" + (badge[1] ? " " + badge[1] : ""), style: badge[1] === "err" ? { color: C_ERR, borderColor: C_ERR } : null }, badge[0]),
1492
1556
  // 模型数折叠提示(点开展开 chips)
1493
- p.models && p.models.length > 0 ? import_react6.default.createElement("button", {
1557
+ p.models && p.models.length > 0 ? import_react7.default.createElement("button", {
1494
1558
  type: "button",
1495
1559
  className: "dkb-models-toggle",
1496
1560
  title: p.models.join(", "),
@@ -1500,13 +1564,13 @@ function BalanceView(props) {
1500
1564
  }
1501
1565
  }, p.models.length + " \u4E2A\u6A21\u578B \u25BE") : null
1502
1566
  ),
1503
- sub ? import_react6.default.createElement("div", { className: "dkb-sub" }, sub) : null,
1504
- p.apiKeyEnv ? import_react6.default.createElement("div", { className: "dkb-sub" }, "\u5BC6\u94A5: " + p.apiKeyEnv + (p.credentialConfigured ? " \u2713" : " \u2717")) : null,
1505
- p.models && p.models.length > 0 ? import_react6.default.createElement(
1567
+ sub ? import_react7.default.createElement("div", { className: "dkb-sub" }, sub) : null,
1568
+ p.apiKeyEnv ? import_react7.default.createElement("div", { className: "dkb-sub" }, "\u5BC6\u94A5: " + p.apiKeyEnv + (p.credentialConfigured ? " \u2713" : " \u2717")) : null,
1569
+ p.models && p.models.length > 0 ? import_react7.default.createElement(
1506
1570
  "div",
1507
1571
  { className: "dkb-chips" },
1508
- p.models.slice(0, 8).map((m) => import_react6.default.createElement("span", { key: m, className: "dkb-chip", style: { border: "1px solid " + accent, color: accent, background: accent + "1a" } }, m)),
1509
- p.models.length > 8 ? import_react6.default.createElement("span", { key: "more", className: "dkb-chip" }, "+" + (p.models.length - 8)) : null
1572
+ p.models.slice(0, 8).map((m) => import_react7.default.createElement("span", { key: m, className: "dkb-chip", style: { border: "1px solid " + accent, color: accent, background: accent + "1a" } }, m)),
1573
+ p.models.length > 8 ? import_react7.default.createElement("span", { key: "more", className: "dkb-chip" }, "+" + (p.models.length - 8)) : null
1510
1574
  ) : null,
1511
1575
  balBody
1512
1576
  );
@@ -1514,20 +1578,20 @@ function BalanceView(props) {
1514
1578
  ));
1515
1579
  }
1516
1580
  const now = new Date(data && data.generatedAt ? data.generatedAt : Date.now());
1517
- return import_react6.default.createElement(
1581
+ return import_react7.default.createElement(
1518
1582
  "div",
1519
1583
  { className: "dkb-rows" },
1520
- import_react6.default.createElement(
1584
+ import_react7.default.createElement(
1521
1585
  "div",
1522
1586
  { className: "dkb-note" },
1523
1587
  data && !snap.error && providers.length > 0 ? okCount + "/" + providers.length + " \u4E2A Provider \u53EF\u67E5\u4F59\u989D\uFF08\u53EF\u67E5\u7684\u6392\u524D\u9762\uFF09" : "\u6A21\u578B\u4F59\u989D \xB7 Host \u534A\u90E8\u5B9E\u65F6\u62C9\u53D6"
1524
1588
  ),
1525
1589
  body,
1526
- import_react6.default.createElement(
1590
+ import_react7.default.createElement(
1527
1591
  "div",
1528
1592
  { className: "dkb-foot" },
1529
- import_react6.default.createElement("span", null, snap.loading ? "\u5237\u65B0\u4E2D\u2026" : "\u66F4\u65B0\u4E8E " + now.toLocaleTimeString()),
1530
- import_react6.default.createElement("button", { type: "button", className: "dkb-refresh", onClick: load }, "\u5237\u65B0")
1593
+ import_react7.default.createElement("span", null, snap.loading ? "\u5237\u65B0\u4E2D\u2026" : "\u66F4\u65B0\u4E8E " + now.toLocaleTimeString()),
1594
+ import_react7.default.createElement("button", { type: "button", className: "dkb-refresh", onClick: load }, "\u5237\u65B0")
1531
1595
  )
1532
1596
  );
1533
1597
  }
@@ -1535,14 +1599,14 @@ function BalanceStat(props) {
1535
1599
  const snap = useBalance(props && props.ctx);
1536
1600
  const data = snap.data;
1537
1601
  const providers = data && Array.isArray(data.providers) ? data.providers : [];
1538
- if (snap.error) return import_react6.default.createElement("span", { className: "dockm-err" }, "\u4F59\u989D\u67E5\u8BE2\u5931\u8D25\uFF08\u70B9\u51FB\u8FDB\u5165\u67E5\u770B\u8BE6\u60C5\uFF09");
1539
- if (!data) return import_react6.default.createElement("span", null, snap.loading ? "\u6B63\u5728\u62C9\u53D6\u4F59\u989D\u2026" : "\u7B49\u5F85\u62C9\u53D6\u4F59\u989D");
1602
+ if (snap.error) return import_react7.default.createElement("span", { className: "dockm-err" }, "\u4F59\u989D\u67E5\u8BE2\u5931\u8D25\uFF08\u70B9\u51FB\u8FDB\u5165\u67E5\u770B\u8BE6\u60C5\uFF09");
1603
+ if (!data) return import_react7.default.createElement("span", null, snap.loading ? "\u6B63\u5728\u62C9\u53D6\u4F59\u989D\u2026" : "\u7B49\u5F85\u62C9\u53D6\u4F59\u989D");
1540
1604
  const ok = providers.filter((p) => p.balance && p.balance.status === "ok").length;
1541
- return import_react6.default.createElement("span", null, providers.length + " \u4E2A Provider \xB7 " + ok + " \u4E2A\u53EF\u67E5\u4F59\u989D");
1605
+ return import_react7.default.createElement("span", null, providers.length + " \u4E2A Provider \xB7 " + ok + " \u4E2A\u53EF\u67E5\u4F59\u989D");
1542
1606
  }
1543
1607
  function useCurrentProvider(ctx, sessionId) {
1544
- const [cur, setCur] = import_react6.default.useState(null);
1545
- import_react6.default.useEffect(() => {
1608
+ const [cur, setCur] = import_react7.default.useState(null);
1609
+ import_react7.default.useEffect(() => {
1546
1610
  let alive = true, off = null;
1547
1611
  try {
1548
1612
  const models = ctx && ctx.get ? ctx.get("modelDirectories") : void 0;
@@ -1604,7 +1668,7 @@ function BalanceChip(props) {
1604
1668
  const text = snap.error ? "\u4F59\u989D\xB7\u5931\u8D25" : !data ? snap.loading ? "\u4F59\u989D \u2026" : "\u4F59\u989D \u2014" : cur ? chipBalanceText(cur) : "\u4F59\u989D \u2014";
1605
1669
  const selModel = sel && (sel.model || sel.selected && sel.selected.model) || null;
1606
1670
  const title = cur ? (cur.displayName || cur.id) + (selModel ? " \xB7 \u5F53\u524D\u6A21\u578B " + selModel : "") + " \xB7 \u70B9\u51FB\u5728\u529F\u80FD\u575E\u67E5\u770B\u4F59\u989D\u8BE6\u60C5" : "\u70B9\u51FB\u6253\u5F00\u529F\u80FD\u575E \xB7 \u6A21\u578B\u4F59\u989D";
1607
- return import_react6.default.createElement(
1671
+ return import_react7.default.createElement(
1608
1672
  "button",
1609
1673
  {
1610
1674
  type: "button",
@@ -1613,8 +1677,8 @@ function BalanceChip(props) {
1613
1677
  "aria-label": "\u6A21\u578B\u4F59\u989D",
1614
1678
  onClick: () => openPanel("balance", def ? { provider: def } : null)
1615
1679
  },
1616
- import_react6.default.createElement("span", { className: "dockchip-dot", style: { background: accent } }),
1617
- import_react6.default.createElement("span", null, text)
1680
+ import_react7.default.createElement("span", { className: "dockchip-dot", style: { background: accent } }),
1681
+ import_react7.default.createElement("span", null, text)
1618
1682
  );
1619
1683
  }
1620
1684
  var feature5 = {
@@ -1674,7 +1738,7 @@ var feature5 = {
1674
1738
  };
1675
1739
 
1676
1740
  // features/animation/view.jsx
1677
- var import_react7 = require("react");
1741
+ var import_react8 = require("react");
1678
1742
  var import_jsx_runtime2 = require("react/jsx-runtime");
1679
1743
  function rpcCall2(method, args) {
1680
1744
  return fetch("/dsh-dock/animation/" + method, {
@@ -1693,10 +1757,10 @@ function rpcCall2(method, args) {
1693
1757
  }
1694
1758
  var EFFECT_MODES = [
1695
1759
  { id: "flow", name: "\u6D41\u5149\u7EC6\u7EBF", desc: "\u9876\u90E8\u7EC6\u7EBF\u6D41\u5149\u5F80\u8FD4\uFF0C\u901F\u5EA6\u968F\u4EFB\u52A1\u541E\u5410\u52A0\u5FEB" },
1696
- { id: "breathe", name: "\u547C\u5438\u5149\u70B9", desc: "\u72B6\u6001\u5FBD\u6807\u5706\u70B9\u547C\u5438\uFF0C\u8D8A\u5FD9\u547C\u5438\u8D8A\u5FEB" },
1760
+ { id: "breathe", name: "\u547C\u5438\u5149\u70B9", desc: "\u9192\u76EE\u547C\u5438\u5149\u70B9\u5E26\u6269\u6563\u5149\u6655\uFF1A\u989C\u8272\u968F\u4EFB\u52A1\u9636\u6BB5\uFF08\u601D\u8003\u84DD/\u8F93\u51FA\u7EFF/\u4EE3\u7801\u6A59/\u67E5\u8D44\u6599\u9752\uFF09\uFF0C\u547C\u5438\u968F\u541E\u5410\u52A0\u5FEB" },
1697
1761
  { id: "ring", name: "\u8F68\u9053\u5149\u73AF", desc: "\u7EC6\u73AF\u7ED5\u5706\u70B9\u65CB\u8F6C\uFF0C\u8F6C\u901F\u968F\u4EFB\u52A1\u901F\u5EA6" },
1698
1762
  { id: "orbit", name: "\u73AF\u5C4F\u5DE1\u822A", desc: "\u4E00\u9897\u5149\u70B9\u6CBF\u5C4F\u5E55\u8FB9\u7F18\u5DE1\u822A\u6574\u5708\uFF0C\u9192\u76EE\u4E0D\u906E\u6321" },
1699
- { id: "robot", name: "\u684C\u9762\u4F19\u4F34", desc: "\u66F4\u5177\u8C61\u7684\u4EBA\u7269\u5750\u9547\u56DB\u5C4F\u5DE5\u4F4D\uFF1A\u601D\u8003\u3001\u8F93\u51FA\u3001\u67E5\u8D44\u6599\u968F\u4EFB\u52A1\u9636\u6BB5\u5207\u6362" },
1763
+ { id: "robot", name: "\u684C\u9762\u4F19\u4F34", desc: "\u771F\u4EBA\u5316\u53CC\u5DE5\u4F4D\uFF1A\u67E5\u8D44\u6599\u770B\u5DE6\u5C4F\u3001\u5199\u5165/\u6539\u4EE3\u7801\u79FB\u5230\u53F3\u5C4F\uFF1B\u5EA7\u6905\u548C\u8F6C\u5934\u968F\u5B9E\u65F6\u4EFB\u52A1\u8282\u594F\u52A0\u901F" },
1700
1764
  { id: "matrix", name: "\u4EE3\u7801\u96E8", desc: "\u5B57\u7B26\u6CBF\u5C4F\u5E55\u7F13\u843D\u5982\u6570\u636E\u6D41\uFF0C\u901F\u5EA6\u968F\u4EFB\u52A1\u541E\u5410\uFF0C\u514B\u5236\u7684\u4F4E\u900F\u660E\u5EA6" },
1701
1765
  { id: "stars", name: "\u661F\u91CE", desc: "\u7EC6\u788E\u661F\u70B9\u7F13\u6162\u98D8\u79FB\u95EA\u70C1\uFF0C\u5B89\u9759\u8010\u770B\u7684\u80CC\u666F\u6C1B\u56F4" },
1702
1766
  { id: "aurora", name: "\u6781\u5149", desc: "\u5C4F\u5E55\u9876\u90E8\u67D4\u5149\u5E26\u7F13\u6162\u547C\u5438\u6D41\u52A8\uFF0C\u50CF\u6781\u5149\u62C2\u8FC7" }
@@ -1705,6 +1769,10 @@ var PHASE_LABELS = { think: "\u601D\u8003\u4E2D", write: "\u8F93\u51FA\u4E2D", c
1705
1769
  function phaseLabel(p) {
1706
1770
  return PHASE_LABELS[p] || "\u5DE5\u4F5C\u4E2D";
1707
1771
  }
1772
+ var PHASE_COLORS = { think: "#60a5fa", write: "#34d399", code: "#fbbf24", search: "#2dd4bf" };
1773
+ function phaseColor(p) {
1774
+ return PHASE_COLORS[p] || "#4d9fff";
1775
+ }
1708
1776
  var END_LABELS = {
1709
1777
  completed: { label: "\u5B8C\u6210", cls: "ok" },
1710
1778
  error: { label: "\u51FA\u9519", cls: "err" },
@@ -1783,13 +1851,13 @@ var animationStore = {
1783
1851
  }
1784
1852
  };
1785
1853
  function useAnimation() {
1786
- const [snap, setSnap] = (0, import_react7.useState)(animationStore.snap);
1787
- (0, import_react7.useEffect)(() => animationStore.subscribe(() => setSnap(animationStore.snap)), []);
1854
+ const [snap, setSnap] = (0, import_react8.useState)(animationStore.snap);
1855
+ (0, import_react8.useEffect)(() => animationStore.subscribe(() => setSnap(animationStore.snap)), []);
1788
1856
  return snap;
1789
1857
  }
1790
1858
  function useTicker(ctx, active) {
1791
- const [, bump] = (0, import_react7.useState)(0);
1792
- (0, import_react7.useEffect)(() => {
1859
+ const [, bump] = (0, import_react8.useState)(0);
1860
+ (0, import_react8.useEffect)(() => {
1793
1861
  if (!active) return;
1794
1862
  if (ctx && typeof ctx.interval === "function") return ctx.interval(bump, 1e3);
1795
1863
  const t = setInterval(bump, 1e3);
@@ -1824,6 +1892,7 @@ function Box3(props) {
1824
1892
  }
1825
1893
  function Monitor3(props) {
1826
1894
  const w = props.w, h = props.h;
1895
+ const searchScreen = props.mode === "search";
1827
1896
  const lines = [1, 2, 3, 4, 5, 1, 2, 3, 4, 5];
1828
1897
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1829
1898
  "span",
@@ -1832,7 +1901,10 @@ function Monitor3(props) {
1832
1901
  style: { left: props.x - w / 2, top: props.y - h / 2, width: w, height: h, transform: "translateZ(" + (props.z || -3) + "px) rotateY(" + (props.ry || 0) + "deg)" },
1833
1902
  children: [
1834
1903
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w, h, d: 5, cls: "dk3-frame", x: w / 2, y: h / 2 }),
1835
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-screen", style: { width: w - 4, height: h - 4, transform: "translate(-50%,-50%) translateZ(3.1px)" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-code", children: [
1904
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-screen", style: { width: w - 4, height: h - 4, transform: "translate(-50%,-50%) translateZ(3.1px)" }, children: searchScreen ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-search-ui", children: [
1905
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-search-box", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("b", {}) }),
1906
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-search-results", children: lines.slice(0, 6).map((n, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}, i)) })
1907
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-code", children: [
1836
1908
  lines.map((n, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}, i)),
1837
1909
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-cur" })
1838
1910
  ] }) })
@@ -1842,57 +1914,86 @@ function Monitor3(props) {
1842
1914
  }
1843
1915
  function RobotScene(props) {
1844
1916
  const phase = props && props.phase ? props.phase : "code";
1845
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-bot-scene", "data-phase": phase, "aria-hidden": "true", children: [
1917
+ const tasks = Array.isArray(props && props.tasks) ? props.tasks : null;
1918
+ const n = tasks ? Math.max(1, Math.min(3, tasks.length)) : 1;
1919
+ const station = phase === "search" ? "left" : phase === "write" || phase === "code" ? "right" : "center";
1920
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-bot-scene", "data-phase": phase, "data-station": station, "data-tasks": tasks ? String(n) : void 0, "aria-hidden": "true", children: [
1846
1921
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-world", children: [
1847
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 150, h: 7, d: 40, cls: "dk3-desk", x: 115, y: 78 }),
1848
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 5, h: 26, d: 32, cls: "dk3-metal dk3-leg", x: 48, y: 94 }),
1849
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 5, h: 26, d: 32, cls: "dk3-metal dk3-leg", x: 182, y: 94 }),
1850
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Monitor3, { w: 34, h: 24, x: 140, y: 60, ry: 24, cls: "left" }),
1851
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Monitor3, { w: 40, h: 30, x: 168, y: 58, ry: 0, cls: "center" }),
1852
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Monitor3, { w: 28, h: 21, x: 188, y: 62, ry: -24, cls: "right" }),
1853
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Monitor3, { w: 30, h: 20, x: 168, y: 28, ry: 0, cls: "top" }),
1854
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 16, h: 2.5, d: 9, cls: "dk3-metal dk3-kb3", x: 126, y: 73, z: 14 }),
1855
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 5, d: 4, cls: "dk3-mug", x: 140, y: 71, z: 14 }),
1922
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 134, h: 7, d: 38, cls: "dk3-desk", x: 145, y: 76 }),
1923
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 5, h: 24, d: 30, cls: "dk3-metal dk3-leg", x: 84, y: 89 }),
1924
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 5, h: 24, d: 30, cls: "dk3-metal dk3-leg", x: 206, y: 89 }),
1925
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Monitor3, { w: 34, h: 24, x: 140, y: 59, ry: 20, cls: "left", mode: "search" }),
1926
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Monitor3, { w: 42, h: 30, x: 180, y: 57, ry: -16, cls: "right" }),
1927
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Monitor3, { w: 28, h: 18, x: 160, y: 31, ry: 0, cls: "top" }),
1928
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 16, h: 2.5, d: 9, cls: "dk3-metal dk3-kb3", x: 130, y: 71, z: 14 }),
1929
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 2.5, d: 6, cls: "dk3-metal dk3-mouse3", x: 141, y: 71, z: 14 }),
1930
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 5, d: 4, cls: "dk3-mug", x: 154, y: 69, z: 14 }),
1931
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 16, h: 2.5, d: 9, cls: "dk3-metal dk3-kb3", x: 170, y: 71, z: 14 }),
1932
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 2.5, d: 6, cls: "dk3-metal dk3-mouse3", x: 181, y: 71, z: 14 }),
1856
1933
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-person", children: [
1857
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 30, d: 22, cls: "dk3-chairback", x: 2, y: 42 }),
1858
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 20, h: 4, d: 22, cls: "dk3-chairseat", x: 12, y: 58 }),
1859
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3, h: 12, d: 3, cls: "dk3-metal", x: 12, y: 68 }),
1860
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 14, h: 2, d: 14, cls: "dk3-metal", x: 12, y: 74 }),
1861
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 13, h: 5, d: 9, cls: "dk3-pants", x: 20, y: 54 }),
1862
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 12, d: 4, cls: "dk3-pants", x: 26, y: 62 }),
1863
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 6, h: 3, d: 5, cls: "dk3-shoe", x: 28, y: 73 }),
1864
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 15, h: 20, d: 11, cls: "dk3-hood dk3-torso", x: 12, y: 36 }),
1865
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 5, h: 8, d: 9, cls: "dk3-hood dk3-hoodbump", x: 5, y: 30 }),
1866
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 3, d: 4, cls: "dk3-skin", x: 14, y: 25 }),
1867
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-head3", children: [
1868
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box3, { w: 13, h: 12, d: 12, cls: "dk3-skin dk3-headbox", x: 8, y: 10, children: [
1869
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-brows", style: { width: 10, height: 4, transform: "translate(-50%,-50%) rotateY(90deg) translateZ(6.3px)" }, children: [
1870
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
1871
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
1934
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 20, d: 20, cls: "dk3-chairback", x: 2, y: 47 }),
1935
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 18, h: 4, d: 20, cls: "dk3-chairseat", x: 12, y: 59 }),
1936
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3, h: 9, d: 3, cls: "dk3-metal", x: 12, y: 66 }),
1937
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 13, h: 2, d: 13, cls: "dk3-metal", x: 12, y: 71 }),
1938
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3, h: 3, d: 3, cls: "dk3-wheel", x: 6, y: 74 }),
1939
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3, h: 3, d: 3, cls: "dk3-wheel", x: 18, y: 74 }),
1940
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 12, h: 5, d: 9, cls: "dk3-pants", x: 20, y: 54 }),
1941
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 10, d: 4, cls: "dk3-pants", x: 26, y: 62 }),
1942
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 6, h: 3, d: 5, cls: "dk3-shoe", x: 28, y: 70 }),
1943
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-upper3", children: [
1944
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 18, h: 5, d: 12, cls: "dk3-hood dk3-shoulders3", x: 13, y: 30 }),
1945
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 15, h: 14, d: 11, cls: "dk3-hood dk3-torso dk3-chest3", x: 12, y: 38 }),
1946
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 12, h: 7, d: 10, cls: "dk3-hood dk3-torso dk3-waist3", x: 12, y: 47 }),
1947
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 5, h: 8, d: 9, cls: "dk3-hood dk3-hoodbump", x: 5, y: 32 }),
1948
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 5, h: 7, d: 5, cls: "dk3-skin dk3-neck3", x: 14, y: 24 }),
1949
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 8, h: 3, d: 8, cls: "dk3-collar3", x: 14, y: 28 }),
1950
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-head3", children: [
1951
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box3, { w: 12, h: 11, d: 11, cls: "dk3-skin dk3-cranium", x: 8, y: 8, children: [
1952
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-brows", style: { width: 9, height: 4, transform: "translate(-50%,-50%) rotateY(90deg) translateZ(5.8px)" }, children: [
1953
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
1954
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
1955
+ ] }),
1956
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-eyes", style: { width: 9, height: 6, transform: "translate(-50%,-50%) rotateY(90deg) translateZ(5.7px)" }, children: [
1957
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
1958
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
1959
+ ] }),
1960
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-nose", style: { transform: "translate(-50%,-50%) rotateY(90deg) translateZ(6.1px)" } })
1872
1961
  ] }),
1873
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-eyes", style: { width: 10, height: 7, transform: "translate(-50%,-50%) rotateY(90deg) translateZ(6.2px)" }, children: [
1962
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 9, h: 7, d: 9, cls: "dk3-skin dk3-jaw3", x: 8.5, y: 14, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-mouth", style: { transform: "translate(-50%,-50%) rotateY(90deg) translateZ(4.7px)" } }) }),
1963
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 12, h: 5, d: 12, cls: "dk3-hair dk3-hair-crown", x: 8, y: 3.5 }),
1964
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 8, d: 11, cls: "dk3-hair dk3-hair-back", x: 3, y: 7.5 }),
1965
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-fringe3", children: [
1966
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
1874
1967
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
1875
1968
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
1876
1969
  ] }),
1877
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-nose", style: { transform: "translate(-50%,-50%) rotateY(90deg) translateZ(6.8px)" } }),
1878
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-mouth", style: { transform: "translate(-50%,-50%) rotateY(90deg) translateZ(6.2px)" } })
1970
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-ear" })
1879
1971
  ] }),
1880
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 14, h: 6, d: 13, cls: "dk3-hair", x: 8, y: 4 }),
1881
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 11, d: 13, cls: "dk3-hair", x: 2, y: 9 }),
1882
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-ear" })
1883
- ] }),
1884
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-arm3", children: [
1885
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 11, d: 4, cls: "dk3-hood dk3-uarm", x: 2, y: 6 }),
1886
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-elbow", children: [
1887
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 11, h: 3.5, d: 3.5, cls: "dk3-hood dk3-farm", x: 6, y: 2 }),
1888
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3.5, h: 3, d: 3, cls: "dk3-skin dk3-hand", x: 12.5, y: 2 })
1889
- ] })
1890
- ] }),
1891
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-arm3 dk3-far", children: [
1892
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 11, d: 4, cls: "dk3-hood dk3-uarm", x: 2, y: 6 }),
1893
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-elbow", children: [
1894
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 11, h: 3.5, d: 3.5, cls: "dk3-hood dk3-farm", x: 6, y: 2 }),
1895
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3.5, h: 3, d: 3, cls: "dk3-skin dk3-hand", x: 12.5, y: 2 })
1972
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-arm3 dk3-near", children: [
1973
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 11, d: 4, cls: "dk3-hood dk3-uarm", x: 2, y: 6 }),
1974
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-elbow", children: [
1975
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 10, h: 3.5, d: 3.5, cls: "dk3-hood dk3-farm", x: 5.5, y: 2 }),
1976
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-wrist3", children: [
1977
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3.5, h: 3, d: 3, cls: "dk3-skin dk3-hand", x: 2, y: 2 }),
1978
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-fingers3", children: [
1979
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
1980
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
1981
+ ] })
1982
+ ] })
1983
+ ] })
1984
+ ] }),
1985
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-arm3 dk3-far", children: [
1986
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 11, d: 4, cls: "dk3-hood dk3-uarm", x: 2, y: 6 }),
1987
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-elbow", children: [
1988
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 10, h: 3.5, d: 3.5, cls: "dk3-hood dk3-farm", x: 5.5, y: 2 }),
1989
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-wrist3", children: [
1990
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3.5, h: 3, d: 3, cls: "dk3-skin dk3-hand", x: 2, y: 2 }),
1991
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-fingers3", children: [
1992
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
1993
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
1994
+ ] })
1995
+ ] })
1996
+ ] })
1896
1997
  ] })
1897
1998
  ] })
1898
1999
  ] })
@@ -1950,16 +2051,16 @@ function previewSound(effect) {
1950
2051
  }
1951
2052
  function Toast(props) {
1952
2053
  const t = props.t;
1953
- const [closing, setClosing] = (0, import_react7.useState)(false);
1954
- const close = (0, import_react7.useCallback)(() => {
2054
+ const [closing, setClosing] = (0, import_react8.useState)(false);
2055
+ const close = (0, import_react8.useCallback)(() => {
1955
2056
  if (!closing) setClosing(true);
1956
2057
  }, [closing]);
1957
- (0, import_react7.useEffect)(() => {
2058
+ (0, import_react8.useEffect)(() => {
1958
2059
  if (!t.stayMs) return;
1959
2060
  const timer = setTimeout(close, t.stayMs);
1960
2061
  return () => clearTimeout(timer);
1961
2062
  }, []);
1962
- (0, import_react7.useEffect)(() => {
2063
+ (0, import_react8.useEffect)(() => {
1963
2064
  if (!closing) return;
1964
2065
  const timer = setTimeout(() => props.onClose(t.id), 240);
1965
2066
  return () => clearTimeout(timer);
@@ -2001,7 +2102,7 @@ var MATRIX_CHARS = "01</>;{}=+*#";
2001
2102
  function AmbientLayer(props) {
2002
2103
  const mode = props.mode;
2003
2104
  const speed = props.speed;
2004
- const matrix = (0, import_react7.useMemo)(() => makeBits(34, () => ({
2105
+ const matrix = (0, import_react8.useMemo)(() => makeBits(34, () => ({
2005
2106
  l: Math.random() * 100,
2006
2107
  d: 4 + Math.random() * 6,
2007
2108
  delay: -Math.random() * 8,
@@ -2009,7 +2110,7 @@ function AmbientLayer(props) {
2009
2110
  s: 11 + Math.round(Math.random() * 4),
2010
2111
  c: MATRIX_CHARS[Math.floor(Math.random() * MATRIX_CHARS.length)] + MATRIX_CHARS[Math.floor(Math.random() * MATRIX_CHARS.length)] + MATRIX_CHARS[Math.floor(Math.random() * MATRIX_CHARS.length)]
2011
2112
  })), []);
2012
- const stars = (0, import_react7.useMemo)(() => makeBits(80, () => ({
2113
+ const stars = (0, import_react8.useMemo)(() => makeBits(80, () => ({
2013
2114
  l: Math.random() * 100,
2014
2115
  t: Math.random() * 100,
2015
2116
  sz: 1.5 + Math.random() * 2,
@@ -2042,17 +2143,17 @@ function AmbientLayer(props) {
2042
2143
  function AnimationOverlay(props) {
2043
2144
  const ctx = props && props.ctx;
2044
2145
  const snap = useAnimation();
2045
- const [toasts, setToasts] = (0, import_react7.useState)([]);
2046
- const [flourish, setFlourish] = (0, import_react7.useState)(null);
2047
- const [bursts, setBursts] = (0, import_react7.useState)([]);
2048
- const prevActiveRef = (0, import_react7.useRef)(null);
2049
- const burstIdRef = (0, import_react7.useRef)(0);
2050
- const pushBurst = (0, import_react7.useCallback)((type, x, y, bits) => {
2146
+ const [toasts, setToasts] = (0, import_react8.useState)([]);
2147
+ const [flourish, setFlourish] = (0, import_react8.useState)(null);
2148
+ const [bursts, setBursts] = (0, import_react8.useState)([]);
2149
+ const prevActiveRef = (0, import_react8.useRef)(null);
2150
+ const burstIdRef = (0, import_react8.useRef)(0);
2151
+ const pushBurst = (0, import_react8.useCallback)((type, x, y, bits) => {
2051
2152
  const id = ++burstIdRef.current;
2052
2153
  setBursts((prev) => prev.concat([{ id, type, x, y, bits }]).slice(-6));
2053
2154
  setTimeout(() => setBursts((prev) => prev.filter((b) => b.id !== id)), 2600);
2054
2155
  }, []);
2055
- (0, import_react7.useEffect)(() => {
2156
+ (0, import_react8.useEffect)(() => {
2056
2157
  if (typeof document === "undefined") return;
2057
2158
  const onClick = (e) => {
2058
2159
  const t = e.target;
@@ -2078,22 +2179,22 @@ function AnimationOverlay(props) {
2078
2179
  document.addEventListener("click", onClick, true);
2079
2180
  return () => document.removeEventListener("click", onClick, true);
2080
2181
  }, [pushBurst]);
2081
- const taskCountRef = (0, import_react7.useRef)(0);
2082
- (0, import_react7.useEffect)(() => {
2182
+ const taskCountRef = (0, import_react8.useRef)(0);
2183
+ (0, import_react8.useEffect)(() => {
2083
2184
  const st2 = snap.status;
2084
2185
  if (!st2 || !st2.active) return;
2085
2186
  const n = st2.active.length;
2086
2187
  if (n > taskCountRef.current) pushBurst("surge");
2087
2188
  taskCountRef.current = n;
2088
2189
  }, [snap.status, pushBurst]);
2089
- (0, import_react7.useEffect)(() => {
2190
+ (0, import_react8.useEffect)(() => {
2090
2191
  let stopped = false;
2091
2192
  let timer = null;
2092
2193
  const loop = async () => {
2093
2194
  await animationStore.refresh();
2094
2195
  if (stopped) return;
2095
2196
  const s = animationStore.snap;
2096
- timer = setTimeout(loop, s.error ? 15e3 : s.status && s.status.active && s.status.active.length > 0 ? 2e3 : 6e3);
2197
+ timer = setTimeout(loop, s.error ? 15e3 : s.status && s.status.active && s.status.active.length > 0 ? 850 : 6e3);
2097
2198
  };
2098
2199
  loop();
2099
2200
  const onVisible = () => {
@@ -2106,7 +2207,7 @@ function AnimationOverlay(props) {
2106
2207
  document.removeEventListener("visibilitychange", onVisible);
2107
2208
  };
2108
2209
  }, []);
2109
- (0, import_react7.useEffect)(() => {
2210
+ (0, import_react8.useEffect)(() => {
2110
2211
  const st2 = snap.status;
2111
2212
  if (!st2 || !st2.active) return;
2112
2213
  const prev = prevActiveRef.current;
@@ -2177,47 +2278,50 @@ function AnimationOverlay(props) {
2177
2278
  const active = st && st.active ? st.active : [];
2178
2279
  const animOn = !!(cfg && cfg.animationEnabled && active.length > 0);
2179
2280
  const mode = cfg && cfg.effectMode ? cfg.effectMode : "flow";
2281
+ const phase = active.length > 0 ? active.reduce((best, x) => !best || (x.phaseAt || 0) > (best.phaseAt || 0) ? x : best, null).phase : "think";
2180
2282
  useTicker(ctx, animOn);
2181
2283
  const now = Date.now();
2182
2284
  const elapsed = active.length > 0 ? fmtClock(now - Math.min(...active.map((x) => x.startTime || now))) : "";
2183
- const [panelOpen, setPanelOpen2] = (0, import_react7.useState)(false);
2184
- (0, import_react7.useEffect)(() => {
2285
+ const [panelOpen, setPanelOpen2] = (0, import_react8.useState)(false);
2286
+ (0, import_react8.useEffect)(() => {
2185
2287
  setPanelOpen2(panelNav.open);
2186
2288
  return subscribePanel(() => setPanelOpen2(panelNav.open));
2187
2289
  }, []);
2188
- const [speed, setSpeed] = (0, import_react7.useState)(1);
2189
- const speedRef = (0, import_react7.useRef)({ tokens: -1, at: 0 });
2190
- (0, import_react7.useEffect)(() => {
2290
+ const [speed, setSpeed] = (0, import_react8.useState)(1);
2291
+ const speedRef = (0, import_react8.useRef)({ ticks: -1, at: 0 });
2292
+ (0, import_react8.useEffect)(() => {
2191
2293
  if (!st || active.length === 0) {
2192
- speedRef.current = { tokens: -1, at: 0 };
2294
+ speedRef.current = { ticks: -1, at: 0 };
2295
+ setSpeed(1);
2193
2296
  return;
2194
2297
  }
2195
- const total = active.reduce((a, x) => a + (x.totalTokens || 0), 0);
2298
+ const ticks = active.reduce((a, x) => a + (x.motionTicks || 0), 0);
2196
2299
  const t = Date.now();
2197
2300
  const prev = speedRef.current;
2198
- if (prev.tokens < 0 || t - prev.at < 500) {
2199
- speedRef.current = { tokens: total, at: t };
2301
+ if (prev.ticks < 0 || t - prev.at < 300) {
2302
+ speedRef.current = { ticks, at: t };
2200
2303
  return;
2201
2304
  }
2202
- const rate = Math.max(0, (total - prev.tokens) / ((t - prev.at) / 1e3));
2203
- setSpeed(Math.max(0.7, Math.min(3, 0.7 + rate / 45)));
2204
- speedRef.current = { tokens: total, at: t };
2305
+ const rate = Math.max(0, (ticks - prev.ticks) / ((t - prev.at) / 1e3));
2306
+ const phaseBoost = phase === "write" || phase === "code" ? 0.28 : phase === "search" ? 0.18 : 0;
2307
+ const next = Math.max(0.9, Math.min(4, Number((0.9 + rate / 14 + phaseBoost).toFixed(2))));
2308
+ setSpeed((current) => Math.abs(current - next) < 0.03 ? current : next);
2309
+ speedRef.current = { ticks, at: t };
2205
2310
  }, [snap.status]);
2206
- const phase = active.length > 0 ? active.reduce((best, x) => !best || (x.phaseAt || 0) > (best.phaseAt || 0) ? x : best, null).phase : "think";
2207
2311
  const ambientOn = animOn && !panelOpen;
2208
2312
  const robotScaleFromConfig = Math.max(0.85, Math.min(2.2, Number(cfg && cfg.robotScale) || 1.35));
2209
2313
  const speedStyle = { "--dkan-speed": Number(speed).toFixed(2) };
2210
- const saveRobotScale = (0, import_react7.useCallback)((robotScale) => {
2314
+ const saveRobotScale = (0, import_react8.useCallback)((robotScale) => {
2211
2315
  rpcCall2("config", { robotScale }).then((d) => animationStore.applyConfig(d && d.config)).catch(() => {
2212
2316
  });
2213
2317
  }, []);
2214
- const [botPos, setBotPos] = (0, import_react7.useState)(null);
2215
- const botPosRef = (0, import_react7.useRef)(null);
2216
- const botDragRef = (0, import_react7.useRef)(null);
2217
- const botResizeRef = (0, import_react7.useRef)(null);
2218
- const [botScaleDraft, setBotScaleDraft] = (0, import_react7.useState)(null);
2219
- const botClickBlockRef = (0, import_react7.useRef)(false);
2220
- (0, import_react7.useEffect)(() => {
2318
+ const [botPos, setBotPos] = (0, import_react8.useState)(null);
2319
+ const botPosRef = (0, import_react8.useRef)(null);
2320
+ const botDragRef = (0, import_react8.useRef)(null);
2321
+ const botResizeRef = (0, import_react8.useRef)(null);
2322
+ const [botScaleDraft, setBotScaleDraft] = (0, import_react8.useState)(null);
2323
+ const botClickBlockRef = (0, import_react8.useRef)(false);
2324
+ (0, import_react8.useEffect)(() => {
2221
2325
  try {
2222
2326
  if (typeof localStorage === "undefined") return;
2223
2327
  const raw = localStorage.getItem("dsh-dock/anim/robot-pos/v1");
@@ -2340,7 +2444,7 @@ function AnimationOverlay(props) {
2340
2444
  }
2341
2445
  },
2342
2446
  children: [
2343
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RobotScene, { phase }),
2447
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RobotScene, { phase, tasks: active }),
2344
2448
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-bot-cap", children: [
2345
2449
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "n", children: active.length }),
2346
2450
  " \u4E2A\u4EFB\u52A1",
@@ -2376,19 +2480,22 @@ function AnimationOverlay(props) {
2376
2480
  "button",
2377
2481
  {
2378
2482
  type: "button",
2379
- className: "dkan-badge",
2380
- style: speedStyle,
2381
- title: active.length + " \u4E2A\u4EFB\u52A1\u8FDB\u884C\u4E2D \xB7 \u70B9\u51FB\u67E5\u770B\u4EFB\u52A1\u52A8\u753B\u9875",
2483
+ className: "dkan-badge" + (mode === "breathe" ? " dkan-badge-breathe" : ""),
2484
+ style: Object.assign({}, speedStyle, { "--dkan-phase": phaseColor(phase) }),
2485
+ title: active.length + " \u4E2A\u4EFB\u52A1\u8FDB\u884C\u4E2D \xB7 " + phaseLabel(phase) + " \xB7 \u70B9\u51FB\u67E5\u770B\u4EFB\u52A1\u52A8\u753B\u9875",
2382
2486
  onClick: () => openPanel("animation"),
2383
2487
  children: [
2384
2488
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-dotwrap", children: [
2385
2489
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-dot" }),
2490
+ mode === "breathe" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-halo" }) : null,
2386
2491
  mode === "ring" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-ring" }) : null
2387
2492
  ] }),
2388
2493
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-badge-txt", children: [
2389
2494
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "n", children: active.length }),
2390
2495
  " \u4E2A\u4EFB\u52A1",
2391
- elapsed ? " \xB7 " + elapsed : ""
2496
+ elapsed ? " \xB7 " + elapsed : "",
2497
+ " \xB7 ",
2498
+ phaseLabel(phase)
2392
2499
  ] })
2393
2500
  ]
2394
2501
  }
@@ -2444,7 +2551,10 @@ function ModePreview({ id }) {
2444
2551
  if (id === "robot") {
2445
2552
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-prev dkan-prev-bot", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RobotScene, { phase: "code" }) });
2446
2553
  }
2447
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-prev", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-dotwrap dkan-breathe", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-dot" }) }) });
2554
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-prev", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-dotwrap dkan-breathe", children: [
2555
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-dot" }),
2556
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-halo" })
2557
+ ] }) });
2448
2558
  }
2449
2559
  function TaskRow(props) {
2450
2560
  const t = props.t;
@@ -2467,23 +2577,26 @@ function TaskRow(props) {
2467
2577
  function AnimationView(props) {
2468
2578
  const ctx = props && props.ctx;
2469
2579
  const snap = useAnimation(ctx);
2470
- const [cfg, setCfg] = (0, import_react7.useState)(null);
2471
- const [saveErr, setSaveErr] = (0, import_react7.useState)("");
2472
- const [testing, setTesting] = (0, import_react7.useState)(false);
2473
- const [testState, setTestState] = (0, import_react7.useState)(null);
2474
- const cfgRef = (0, import_react7.useRef)(null);
2475
- const pendingSavesRef = (0, import_react7.useRef)(0);
2476
- const editingWebhookRef = (0, import_react7.useRef)(false);
2477
- (0, import_react7.useEffect)(() => {
2580
+ const [cfg, setCfg] = (0, import_react8.useState)(null);
2581
+ const [saveErr, setSaveErr] = (0, import_react8.useState)("");
2582
+ const [testing, setTesting] = (0, import_react8.useState)(false);
2583
+ const [testState, setTestState] = (0, import_react8.useState)(null);
2584
+ const [feishuTestState, setFeishuTestState] = (0, import_react8.useState)(null);
2585
+ const [feishuTesting, setFeishuTesting] = (0, import_react8.useState)(false);
2586
+ const cfgRef = (0, import_react8.useRef)(null);
2587
+ const pendingSavesRef = (0, import_react8.useRef)(0);
2588
+ const editingWebhookRef = (0, import_react8.useRef)(false);
2589
+ const editingFeishuRef = (0, import_react8.useRef)(false);
2590
+ (0, import_react8.useEffect)(() => {
2478
2591
  const c = snap.status && snap.status.config;
2479
2592
  if (!c) return;
2480
- if (pendingSavesRef.current > 0 || editingWebhookRef.current) return;
2593
+ if (pendingSavesRef.current > 0 || editingWebhookRef.current || editingFeishuRef.current) return;
2481
2594
  if (c !== cfgRef.current) {
2482
2595
  cfgRef.current = c;
2483
2596
  setCfg(Object.assign({}, c));
2484
2597
  }
2485
2598
  }, [snap.status]);
2486
- (0, import_react7.useEffect)(() => {
2599
+ (0, import_react8.useEffect)(() => {
2487
2600
  if (!animationStore.snap.status) animationStore.refresh();
2488
2601
  }, []);
2489
2602
  const patch = (p) => {
@@ -2509,6 +2622,17 @@ function AnimationView(props) {
2509
2622
  setCfg(Object.assign({}, c));
2510
2623
  }
2511
2624
  };
2625
+ const saveFeishuWebhook = async () => {
2626
+ if (!editingFeishuRef.current) return;
2627
+ const hook = String(cfg.feishuWebhook || "").trim();
2628
+ await patch({ feishuWebhook: hook });
2629
+ editingFeishuRef.current = false;
2630
+ const c = animationStore.snap.status && animationStore.snap.status.config;
2631
+ if (c && c !== cfgRef.current) {
2632
+ cfgRef.current = c;
2633
+ setCfg(Object.assign({}, c));
2634
+ }
2635
+ };
2512
2636
  const runDingtalkTest = async () => {
2513
2637
  setTesting(true);
2514
2638
  setTestState(null);
@@ -2530,6 +2654,27 @@ function AnimationView(props) {
2530
2654
  setTesting(false);
2531
2655
  }
2532
2656
  };
2657
+ const runFeishuTest = async () => {
2658
+ setFeishuTesting(true);
2659
+ setFeishuTestState(null);
2660
+ try {
2661
+ if (editingFeishuRef.current) {
2662
+ const hook = String(cfg.feishuWebhook || "").trim();
2663
+ if (!hook) throw new Error("\u8BF7\u5148\u586B\u5199 Webhook \u5730\u5740");
2664
+ const d = await rpcCall2("config", { feishuWebhook: hook });
2665
+ animationStore.applyConfig(d && d.config);
2666
+ editingFeishuRef.current = false;
2667
+ cfgRef.current = d && d.config || cfgRef.current;
2668
+ setCfg(Object.assign({}, cfg, { feishuWebhook: hook }));
2669
+ }
2670
+ const r = await rpcCall2("test", { target: "feishu" });
2671
+ setFeishuTestState(r && r.sent ? { ok: true, msg: "\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u53BB\u7FA4\u91CC\u770B\u770B" } : { ok: false, msg: r && r.error || "\u53D1\u9001\u5931\u8D25" });
2672
+ } catch (e) {
2673
+ setFeishuTestState({ ok: false, msg: e && e.message || String(e) });
2674
+ } finally {
2675
+ setFeishuTesting(false);
2676
+ }
2677
+ };
2533
2678
  const enableSystemNotify = async (next) => {
2534
2679
  if (next && typeof Notification !== "undefined" && Notification.permission !== "granted") {
2535
2680
  try {
@@ -2812,7 +2957,66 @@ function AnimationView(props) {
2812
2957
  ] }),
2813
2958
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note", children: "\u673A\u5668\u4EBA\u521B\u5EFA\uFF1A\u9489\u9489\u7FA4 \u2192 \u8BBE\u7F6E \u2192 \u667A\u80FD\u7FA4\u52A9\u624B \u2192 \u6DFB\u52A0\u673A\u5668\u4EBA \u2192 \u81EA\u5B9A\u4E49\uFF08Webhook\uFF09\uFF0C \u5B89\u5168\u8BBE\u7F6E\u9009\u300C\u81EA\u5B9A\u4E49\u5173\u952E\u8BCD\u300D\u586B\u300C\u4EFB\u52A1\u300D\u6216\u300Cdsh\u300D\uFF08\u63A8\u9001\u6807\u9898\u542B\u300C\u4EFB\u52A1\u300D\u5373\u53EF\u547D\u4E2D\uFF09\u3002" })
2814
2959
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note", children: "\u672A\u5F00\u542F\u2014\u2014\u4EFB\u52A1\u7ED3\u675F\u4E0D\u63A8\u9001\u9489\u9489\u3002" })
2815
- ] }, "dingtalk")
2960
+ ] }, "dingtalk"),
2961
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec", children: [
2962
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec-head", children: [
2963
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-title", children: "\u98DE\u4E66\u63A8\u9001" }),
2964
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-sub", children: "\u4EFB\u52A1\u7ED3\u675F\u63A8\u9001\u5230\u98DE\u4E66\u7FA4\u673A\u5668\u4EBA\uFF08\u5BBF\u4E3B\u76F4\u53D1\uFF0C\u6D4F\u89C8\u5668\u5173\u7740\u4E5F\u80FD\u63A8\uFF1B\u4E8B\u4EF6\u8DDF\u968F\u4E0A\u65B9\u5B8C\u6210/\u5F02\u5E38\u5F00\u5173\uFF09" }),
2965
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-sec-sw", children: [
2966
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-swlabel" + (cfg.feishuEnabled ? " on" : ""), children: cfg.feishuEnabled ? "\u5DF2\u5F00\u542F" : "\u5DF2\u5173\u95ED" }),
2967
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2968
+ "button",
2969
+ {
2970
+ type: "button",
2971
+ className: "dock-sw" + (cfg.feishuEnabled ? " on" : ""),
2972
+ role: "switch",
2973
+ "aria-checked": cfg.feishuEnabled,
2974
+ "aria-label": "\u5F00\u5173\u98DE\u4E66\u63A8\u9001",
2975
+ title: cfg.feishuEnabled ? "\u5173\u95ED\u98DE\u4E66\u63A8\u9001" : "\u5F00\u542F\u98DE\u4E66\u63A8\u9001",
2976
+ onClick: () => patch({ feishuEnabled: !cfg.feishuEnabled })
2977
+ }
2978
+ )
2979
+ ] })
2980
+ ] }),
2981
+ cfg.feishuEnabled ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-rows-narrow", children: [
2982
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-row dkan-row-webhook", children: [
2983
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-label", children: "Webhook" }),
2984
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2985
+ "input",
2986
+ {
2987
+ type: "text",
2988
+ className: "dkan-input",
2989
+ spellCheck: false,
2990
+ value: cfg.feishuWebhook || "",
2991
+ placeholder: "https://open.feishu.cn/open-apis/bot/v2/hook/\u2026",
2992
+ onChange: (e) => {
2993
+ editingFeishuRef.current = true;
2994
+ setCfg(Object.assign({}, cfg, { feishuWebhook: e.target.value }));
2995
+ }
2996
+ }
2997
+ ),
2998
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2999
+ "button",
3000
+ {
3001
+ type: "button",
3002
+ className: "dkan-btn",
3003
+ disabled: !editingFeishuRef.current,
3004
+ onClick: saveFeishuWebhook,
3005
+ children: editingFeishuRef.current ? "\u4FDD\u5B58" : "\u5DF2\u4FDD\u5B58"
3006
+ }
3007
+ )
3008
+ ] }),
3009
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-row", children: [
3010
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-label", children: "\u8FDE\u901A\u6D4B\u8BD5" }),
3011
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "dkan-btn", disabled: feishuTesting, onClick: runFeishuTest, children: feishuTesting ? "\u53D1\u9001\u4E2D\u2026" : "\u53D1\u9001\u6D4B\u8BD5\u6D88\u606F" }),
3012
+ feishuTestState ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-row-sub" + (feishuTestState.ok ? " dkan-ok" : " dkan-err"), children: [
3013
+ feishuTestState.ok ? "\u2713 " : "\u2717 ",
3014
+ feishuTestState.msg
3015
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-sub", children: "\u7528\u5F53\u524D\u4FDD\u5B58\u7684 Webhook \u53D1\u4E00\u6761\u6D4B\u8BD5\u6D88\u606F" })
3016
+ ] }),
3017
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note", children: "\u673A\u5668\u4EBA\u521B\u5EFA\uFF1A\u98DE\u4E66\u7FA4 \u2192 \u8BBE\u7F6E \u2192 \u7FA4\u673A\u5668\u4EBA \u2192 \u6DFB\u52A0\u673A\u5668\u4EBA \u2192 \u81EA\u5B9A\u4E49\u673A\u5668\u4EBA\uFF08\u83B7\u53D6 Webhook \u5730\u5740\uFF09\uFF1B \u5B89\u5168\u8BBE\u7F6E\u5982\u9009\u300C\u81EA\u5B9A\u4E49\u5173\u952E\u8BCD\u300D\u586B\u300C\u4EFB\u52A1\u300D\u6216\u300Cdsh\u300D\uFF08\u63A8\u9001\u6807\u9898\u542B\u300C\u4EFB\u52A1\u300D\u5373\u53EF\u547D\u4E2D\uFF09\u3002" })
3018
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note", children: "\u672A\u5F00\u542F\u2014\u2014\u4EFB\u52A1\u7ED3\u675F\u4E0D\u63A8\u9001\u98DE\u4E66\u3002" })
3019
+ ] }, "feishu")
2816
3020
  );
2817
3021
  }
2818
3022
  if (saveErr) rows.push(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note dkan-err", children: saveErr }, "err"));
@@ -2855,6 +3059,8 @@ var css2 = [
2855
3059
  "@keyframes dkan-orbit{0%{top:0;left:0}25%{top:0;left:calc(100vw - 12px)}50%{top:calc(100vh - 12px);left:calc(100vw - 12px)}75%{top:calc(100vh - 12px);left:0}100%{top:0;left:0}}",
2856
3060
  // ===== 氛围动效 =====
2857
3061
  ".dkan-amb{position:fixed;inset:0;z-index:9989;pointer-events:none;overflow:hidden;}",
3062
+ // pointer-events 不继承:全屏装饰层的子粒子(星点/流星/极光/火花/彩带)必须各自透明于点击
3063
+ ".dkan-amb *,.dkan-fxwrap *{pointer-events:none;}",
2858
3064
  // 代码雨:字符列缓落(提亮加大,速度随吞吐)
2859
3065
  ".dkan-matrix span{position:absolute;top:-12%;writing-mode:vertical-rl;font-family:var(--ds-font-family-code,monospace);color:var(--dsw-alias-accent,#4d9fff);text-shadow:0 0 6px color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 60%,transparent);animation:dkan-fall linear infinite;will-change:transform;}",
2860
3066
  "@keyframes dkan-fall{to{transform:translateY(125vh)}}",
@@ -2901,10 +3107,16 @@ var css2 = [
2901
3107
  ".dkan-badge .n{color:var(--dsw-alias-label-primary);font-weight:600;}",
2902
3108
  "@keyframes dkan-rise{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}",
2903
3109
  // 徽标圆点与两种动效(呼吸 / 轨道环)
2904
- ".dkan-dotwrap{position:relative;width:16px;height:16px;flex:none;display:inline-flex;align-items:center;justify-content:center;}",
2905
- ".dkan-dot{width:9px;height:9px;border-radius:50%;background:var(--dsw-alias-accent,#4d9fff);box-shadow:0 0 8px color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 55%,transparent);}",
2906
- ".dkan-breathe .dkan-dot{animation:dkan-breathe calc(2.6s / var(--dkan-speed,1)) ease-in-out infinite;}",
2907
- "@keyframes dkan-breathe{0%,100%{transform:scale(1);opacity:.55}50%{transform:scale(1.6);opacity:1}}",
3110
+ ".dkan-dotwrap{position:relative;width:20px;height:20px;flex:none;display:inline-flex;align-items:center;justify-content:center;}",
3111
+ ".dkan-dot{width:12px;height:12px;border-radius:50%;background:var(--dkan-phase,var(--dsw-alias-accent,#4d9fff));box-shadow:0 0 10px color-mix(in srgb,var(--dkan-phase,var(--dsw-alias-accent,#4d9fff)) 70%,transparent);transition:background .4s var(--ds-ease-in-out),box-shadow .4s var(--ds-ease-in-out);}",
3112
+ ".dkan-breathe .dkan-dot{animation:dkan-breathe calc(2.2s / var(--dkan-speed,1)) ease-in-out infinite;}",
3113
+ "@keyframes dkan-breathe{0%,100%{transform:scale(1);opacity:.5}50%{transform:scale(1.7);opacity:1}}",
3114
+ // 呼吸光晕:向外扩散的波纹环,与圆点同频(颜色随阶段)
3115
+ ".dkan-halo{position:absolute;inset:0;border-radius:50%;border:2px solid var(--dkan-phase,var(--dsw-alias-accent,#4d9fff));animation:dkan-halo calc(2.2s / var(--dkan-speed,1)) ease-out infinite;}",
3116
+ "@keyframes dkan-halo{0%{transform:scale(.5);opacity:.9}70%{transform:scale(1.5);opacity:.25}100%{transform:scale(1.7);opacity:0}}",
3117
+ // breathe 模式徽标更醒目:阶段色描边 + 呼吸辉光
3118
+ ".dkan-badge-breathe{border-color:color-mix(in srgb,var(--dkan-phase,#4d9fff) 55%,transparent);animation:dkan-rise .3s var(--ds-ease-in-out),dkan-badge-breathe calc(2.2s / var(--dkan-speed,1)) ease-in-out infinite;}",
3119
+ "@keyframes dkan-badge-breathe{0%,100%{box-shadow:0 0 6px color-mix(in srgb,var(--dkan-phase,#4d9fff) 22%,transparent),0 6px 24px rgb(0 0 0 / .16)}50%{box-shadow:0 0 18px color-mix(in srgb,var(--dkan-phase,#4d9fff) 55%,transparent),0 6px 24px rgb(0 0 0 / .16)}}",
2908
3120
  ".dkan-ring{position:absolute;inset:0;border-radius:50%;background:conic-gradient(from 0deg,transparent 0 68%,var(--dsw-alias-accent,#4d9fff) 92%,#fff);-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 2px),#000 calc(100% - 2px));mask:radial-gradient(farthest-side,transparent calc(100% - 2px),#000 calc(100% - 2px));animation:dkan-spin calc(2.2s / var(--dkan-speed,1)) linear infinite;opacity:.9;}",
2909
3121
  "@keyframes dkan-spin{to{transform:rotate(360deg)}}",
2910
3122
  // 通知卡片栈(右上角)
@@ -2979,7 +3191,7 @@ var css2 = [
2979
3191
  "@keyframes dkan-prev-aurora{0%{transform:translateX(-10%)}100%{transform:translateX(15%)}}",
2980
3192
  ".dkan-prev-bot{height:92px;justify-content:center;}",
2981
3193
  ".dkan-prev-bot .dkan-bot-scene{--dkan-bot-scale:1;transform:scale(.56);transform-origin:center;}",
2982
- // ===== 桌面伙伴:具象人物 + 四屏工位(尺寸可调,整卡可拖拽) =====
3194
+ // ===== 桌面伙伴:具象人物 + 紧凑双工位(尺寸可调,整卡可拖拽) =====
2983
3195
  // 卡片:玻璃拟态;默认停泊右下(dsh 输入卡上方),拖动后位置持久化、可放屏幕任意处
2984
3196
  ".dkan-botcard{--dkan-bot-scale:1.35;position:fixed;right:20px;bottom:calc(var(--dsh-composer-height,152px) + 20px);z-index:9990;display:flex;flex-direction:column;gap:6px;padding:10px 12px;border-radius:16px;cursor:grab;border:1px solid var(--dsw-alias-border-l1);background:color-mix(in srgb,var(--dsw-alias-bg-layer-2) 86%,transparent);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);box-shadow:0 12px 36px rgb(0 0 0 / .22);color:var(--dsw-alias-label-secondary);font-family:inherit;font-size:12px;pointer-events:auto;touch-action:none;user-select:none;animation:dkan-rise .3s var(--ds-ease-in-out);}",
2985
3197
  ".dkan-botcard:hover,.dkan-botcard:focus-visible{border-color:var(--dsw-alias-accent,#4d9fff);outline:none;}",
@@ -3014,9 +3226,24 @@ var css2 = [
3014
3226
  ".dk3-code i:nth-child(5n+4){width:72%;}",
3015
3227
  ".dk3-code i:nth-child(5n){width:54%;background:var(--dkan-code-a);}",
3016
3228
  ".dk3-cur{position:absolute;left:3px;bottom:2px;width:4px;height:2px;background:var(--dkan-code-b);animation:dkan-blink3 1s steps(1) infinite;}",
3229
+ // 左屏检索视图:搜索框、放大镜与结果条,和右侧代码编辑器明确区分
3230
+ ".dk3-search-ui{position:absolute;inset:3px;display:block;overflow:hidden;}",
3231
+ ".dk3-search-box{display:block;height:5px;margin:0 1px 3px;border:1px solid color-mix(in srgb,var(--dkan-code-a) 72%,#d7fff4);border-radius:2px;box-sizing:border-box;}",
3232
+ ".dk3-search-box b{display:block;width:2px;height:2px;margin:1px 0 0 2px;border:1px solid var(--dkan-code-a);border-radius:50%;position:relative;}",
3233
+ ".dk3-search-box b:after{content:'';position:absolute;width:2px;height:1px;background:var(--dkan-code-a);right:-2px;bottom:-1px;transform:rotate(45deg);transform-origin:left center;}",
3234
+ ".dk3-search-results{display:block;animation:dk3-search-scroll calc(2.1s / var(--dkan-speed,1)) linear infinite;}",
3235
+ ".dk3-search-results i{display:block;height:2px;margin:2px 1px 0;border-radius:1px;background:var(--dkan-code-a);opacity:.72;}",
3236
+ ".dk3-search-results i:nth-child(2n){width:74%;background:var(--dkan-code-b);}",
3237
+ ".dk3-search-results i:nth-child(3n){width:48%;background:var(--dkan-code-c);}",
3238
+ "@keyframes dk3-search-scroll{to{transform:translateY(-5px)}}",
3017
3239
  "@keyframes dk3-scroll{to{transform:translateY(-50%)}}",
3018
- // 人物组(坐在桌子中间近镜头侧 z=30,侧身面朝 +X 三屏;不会被桌体遮挡)
3019
- ".dk3-person{position:absolute;left:96px;top:14px;width:44px;height:64px;transform-style:preserve-3d;transform:translateZ(30px);}",
3240
+ // 人物与椅子始终正对桌面:工位切换只横移,不再旋转整个人和座椅。
3241
+ ".dk3-person{--dk3-seat-x:22px;position:absolute;left:98px;top:14px;width:44px;height:61px;transform-style:preserve-3d;transform:translateZ(30px) translateX(var(--dk3-seat-x));transition:transform max(.18s,calc(.38s / var(--dkan-speed,1))) cubic-bezier(.23,1,.32,1);will-change:transform;}",
3242
+ ".dkan-bot-scene[data-station=left] .dk3-person{--dk3-seat-x:0px;}",
3243
+ ".dkan-bot-scene[data-station=center] .dk3-person{--dk3-seat-x:22px;}",
3244
+ ".dkan-bot-scene[data-station=right] .dk3-person{--dk3-seat-x:44px;}",
3245
+ // 上身以髋部为旋转原点;只做前后倾,始终朝向桌面。
3246
+ ".dk3-upper3{position:absolute;inset:0;transform-style:preserve-3d;transform-origin:12px 52px;transform:translateZ(0);transition:transform .24s cubic-bezier(.77,0,.175,1);will-change:transform;}",
3020
3247
  // 动漫人物配色:皮肤/头发/卫衣/裤子
3021
3248
  ".dk3-skin .dk3-face{background:linear-gradient(180deg,#ffd9b8,#f3b98d);}",
3022
3249
  ".dk3-skin .dk3-face:nth-child(5){background:#ffe3c9;}",
@@ -3026,64 +3253,106 @@ var css2 = [
3026
3253
  ".dk3-hood .dk3-face:nth-child(5){background:#93a5ba;}",
3027
3254
  ".dk3-pants .dk3-face{background:linear-gradient(180deg,#3d4a5c,#2c3646);}",
3028
3255
  ".dk3-pants .dk3-face:nth-child(5){background:#4a5a70;}",
3029
- // 人物细节:圆角 + 鞋 + 咖啡杯 + 嘴
3030
- ".dk3-headbox .dk3-face{border-radius:3px;}",
3031
- ".dk3-torso .dk3-face{border-radius:3px;}",
3256
+ // 人物细节:收窄下颌、连续肩颈、短侧渐层发型
3257
+ ".dk3-cranium .dk3-face{border-radius:42% 46% 38% 36%;}",
3258
+ ".dk3-jaw3 .dk3-face{border-radius:30% 30% 48% 48%;}",
3259
+ ".dk3-neck3 .dk3-face{border-radius:2px;}",
3260
+ ".dk3-collar3 .dk3-face{background:linear-gradient(180deg,#516176,#374459);border-radius:3px;}",
3261
+ ".dk3-shoulders3 .dk3-face{border-radius:4px;}",
3262
+ ".dk3-chest3 .dk3-face{border-radius:4px;}",
3263
+ ".dk3-waist3 .dk3-face{border-radius:3px;}",
3032
3264
  ".dk3-hair .dk3-face{border-radius:2px;}",
3265
+ ".dk3-hair-crown .dk3-face{border-radius:48% 42% 28% 30%;}",
3266
+ ".dk3-hair-back .dk3-face{background:linear-gradient(180deg,#493727,#2f241b);border-radius:46% 24% 38% 44%;}",
3033
3267
  ".dk3-shoe .dk3-face{background:#20262f;border-radius:2px;}",
3034
3268
  ".dk3-mug .dk3-face{background:#c2703d;border-radius:1px;}",
3035
3269
  ".dk3-mug .dk3-face:nth-child(5){background:#e08a52;}",
3036
- ".dk3-mouth{position:absolute;left:50%;top:78%;width:5px;height:1.5px;border-radius:1px;background:#b5766a;}",
3270
+ ".dk3-mouth{position:absolute;left:50%;top:64%;width:3.5px;height:1px;border-radius:2px;background:#a9635c;}",
3037
3271
  // 椅子
3038
3272
  ".dk3-chairback .dk3-face{background:linear-gradient(180deg,#3f4c60,#2c3648);}",
3039
3273
  ".dk3-chairseat .dk3-face{background:#33415a;}",
3040
- // 头组(俯仰=rotateZ,左右看=rotateY);眼睛贴在 +X 面板上
3041
- ".dk3-head3{position:absolute;left:14px;top:2px;width:17px;height:20px;transform-style:preserve-3d;transform-origin:50% 85%;transition:transform .25s var(--ds-ease-in-out);}",
3042
- ".dk3-brows{position:absolute;left:50%;top:30%;display:flex;gap:3px;align-items:center;justify-content:center;}",
3043
- ".dk3-brows i{width:3px;height:1px;border-radius:2px;background:#4a3428;}",
3044
- ".dk3-eyes{position:absolute;left:50%;top:52%;display:flex;gap:3px;align-items:center;justify-content:center;}",
3045
- ".dk3-eyes i{width:3px;height:4px;border-radius:50%;background:radial-gradient(circle at 60% 35%,#fff 0 .5px,#2b3442 .8px);animation:dkan-blink3 4.6s infinite;}",
3046
- ".dk3-nose{position:absolute;left:50%;top:64%;width:2px;height:2px;border-radius:50%;background:#d99277;}",
3047
- ".dk3-ear{position:absolute;left:-1px;top:11px;width:3px;height:5px;border-radius:50%;background:#f3b98d;transform:translateZ(2px);}",
3274
+ // 头组与颈部中心均为 x=14;只让头部观察左右屏,身体和椅子不转向。
3275
+ ".dk3-head3{--dk3-head-turn:rotateY(0deg);position:absolute;left:6px;top:3px;width:17px;height:21px;transform-style:preserve-3d;transform-origin:8px 18px;transform:var(--dk3-head-turn);transition:transform max(.18s,calc(.22s / var(--dkan-speed,1))) cubic-bezier(.23,1,.32,1);will-change:transform;}",
3276
+ ".dkan-bot-scene[data-station=left] .dk3-head3{--dk3-head-turn:rotateY(-18deg);}",
3277
+ ".dkan-bot-scene[data-station=center] .dk3-head3{--dk3-head-turn:rotateY(0deg);}",
3278
+ ".dkan-bot-scene[data-station=right] .dk3-head3{--dk3-head-turn:rotateY(14deg);}",
3279
+ ".dk3-brows{position:absolute;left:50%;top:29%;display:flex;gap:2.5px;align-items:center;justify-content:center;}",
3280
+ ".dk3-brows i{width:3.5px;height:1px;border-radius:2px;background:#3a2a21;transform:rotate(-7deg);}",
3281
+ ".dk3-brows i+ i{transform:rotate(7deg);}",
3282
+ ".dk3-eyes{position:absolute;left:50%;top:51%;display:flex;gap:2.5px;align-items:center;justify-content:center;}",
3283
+ ".dk3-eyes i{width:3.5px;height:2.5px;border-radius:50%;background:radial-gradient(circle at 62% 30%,#fff 0 .5px,#263141 .8px 1.7px,#111827 1.9px);animation:dkan-blink3 4.8s infinite;}",
3284
+ ".dk3-nose{position:absolute;left:50%;top:66%;width:2px;height:3px;border-radius:60% 40% 55% 45%;background:linear-gradient(90deg,#e7a67e,#c77f67);}",
3285
+ ".dk3-ear{position:absolute;left:1px;top:10px;width:3px;height:5px;border-radius:52% 44% 48% 52%;background:linear-gradient(90deg,#edaa82,#ffd2ad);transform:translateZ(2px);}",
3286
+ ".dk3-fringe3{position:absolute;left:13px;top:4px;width:5px;height:7px;transform-style:preserve-3d;transform:rotateY(90deg) translateZ(5.8px);}",
3287
+ ".dk3-fringe3 i{position:absolute;top:0;width:2px;height:6px;border-radius:70% 25% 60% 30%;background:linear-gradient(180deg,#6b5239,#392b20);transform-origin:top center;}",
3288
+ ".dk3-fringe3 i:nth-child(1){left:0;transform:rotate(-18deg);height:5px;}",
3289
+ ".dk3-fringe3 i:nth-child(2){left:1.8px;transform:rotate(-6deg);height:6px;}",
3290
+ ".dk3-fringe3 i:nth-child(3){left:3.5px;transform:rotate(12deg);height:4px;}",
3048
3291
  "@keyframes dkan-blink3{0%,91%,100%{transform:scaleY(1)}94%{transform:scaleY(.15)}}",
3049
- // 手臂:肩组挂躯干前上,肘组在其下端(前臂+手伸向键盘);write/code 时肘部高频敲击
3050
- ".dk3-arm3{position:absolute;left:20px;top:30px;width:16px;height:16px;transform-style:preserve-3d;}",
3051
- ".dk3-elbow{position:absolute;left:0;top:10px;width:15px;height:5px;transform-style:preserve-3d;transform-origin:2px 2px;}",
3052
- ".dk3-far{transform:translateZ(-8px);filter:brightness(.62);}",
3292
+ // 手臂按肩→肘→腕分段,旋转原点位于真实关节连接处。
3293
+ ".dk3-arm3{position:absolute;left:20px;top:30px;width:16px;height:16px;transform-style:preserve-3d;transform-origin:2px 2px;will-change:transform;}",
3294
+ ".dk3-elbow{position:absolute;left:0;top:10px;width:15px;height:5px;transform-style:preserve-3d;transform-origin:1px 2px;will-change:transform;}",
3295
+ ".dk3-wrist3{position:absolute;left:9.5px;top:0;width:6px;height:5px;transform-style:preserve-3d;transform-origin:1px 2px;will-change:transform;}",
3296
+ ".dk3-fingers3{position:absolute;left:3px;top:1px;width:4px;height:3px;transform:translateZ(2px);}",
3297
+ ".dk3-fingers3 i{position:absolute;left:0;width:4px;height:.8px;border-radius:2px;background:#f2b58d;}",
3298
+ ".dk3-fingers3 i+ i{top:1.4px;width:3.5px;}",
3299
+ ".dk3-far{transform:translateZ(-7px);filter:brightness(.72);}",
3053
3300
  // 思考泡泡(贴镜头 2D 层,think 阶段显示)
3054
3301
  ".dkan-bubble{position:absolute;left:80px;top:4px;display:none;gap:3px;padding:4px 6px;border-radius:8px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);box-shadow:0 2px 6px rgb(0 0 0 / .15);z-index:3;}",
3055
3302
  ".dkan-bubble i{width:4px;height:4px;border-radius:50%;background:var(--dsw-alias-label-tertiary);animation:dkan-bubdot 1.2s ease-in-out infinite;}",
3056
3303
  ".dkan-bubble i:nth-child(2){animation-delay:.2s;}",
3057
3304
  ".dkan-bubble i:nth-child(3){animation-delay:.4s;}",
3058
3305
  "@keyframes dkan-bubdot{0%,100%{opacity:.25;transform:translateY(0)}50%{opacity:1;transform:translateY(-2px)}}",
3306
+ // ===== 多任务工位(data-tasks=活跃任务数,上限 3) =====
3307
+ // 椅子滚轮
3308
+ ".dk3-wheel .dk3-face{background:#1c232e;border-radius:50%;}",
3309
+ // 有活跃任务时,未轮到的侧工位稍暗;多任务则两个工位均保持可见。
3310
+ ".dkan-bot-scene[data-tasks] .dk3-mon3.left .dk3-screen,.dkan-bot-scene[data-tasks] .dk3-mon3.right .dk3-screen{opacity:.3;}",
3311
+ // 2 个及以上任务:左右工位同时点亮(各自带辉光、代码滚动加速)。
3312
+ '.dkan-bot-scene[data-tasks="2"] .dk3-mon3.left .dk3-screen,.dkan-bot-scene[data-tasks="2"] .dk3-mon3.right .dk3-screen,.dkan-bot-scene[data-tasks="3"] .dk3-mon3.left .dk3-screen,.dkan-bot-scene[data-tasks="3"] .dk3-mon3.right .dk3-screen{opacity:1;box-shadow:0 0 8px color-mix(in srgb,var(--dkan-code-b,#60a5fa) 42%,transparent);}',
3313
+ '.dkan-bot-scene[data-tasks="2"] .dk3-mon3.left .dk3-code,.dkan-bot-scene[data-tasks="2"] .dk3-mon3.right .dk3-code,.dkan-bot-scene[data-tasks="3"] .dk3-mon3.left .dk3-code,.dkan-bot-scene[data-tasks="3"] .dk3-mon3.right .dk3-code{animation-duration:calc(2.6s / var(--dkan-speed,1));}',
3314
+ // 座椅移动期间滚轮跟随任务节奏转动;思考中停下,避免无意义的常驻运动。
3315
+ ".dkan-bot-scene[data-station=left] .dk3-wheel,.dkan-bot-scene[data-station=right] .dk3-wheel{animation:dkan-wheel calc(.46s / var(--dkan-speed,1)) linear infinite;transform-origin:center;}",
3316
+ "@keyframes dkan-wheel{to{transform:rotateZ(360deg)}}",
3059
3317
  // ===== 阶段驱动(data-phase 四态,host 由 chunk 流实时同步) =====
3060
- // think:屏幕调暗 + 仰头苦想 + 泡泡浮现
3318
+ // think:上身轻靠、近侧手托下巴、远侧手留在桌面;动作有停顿而不是机械往返。
3061
3319
  ".dkan-bot-scene[data-phase=think] .dk3-screen{opacity:.32;}",
3062
3320
  ".dkan-bot-scene[data-phase=think] .dkan-bubble{display:inline-flex;}",
3063
- ".dkan-bot-scene[data-phase=think] .dk3-head3{animation:dkan-think-head 1.8s ease-in-out infinite alternate;}",
3064
- ".dkan-bot-scene[data-phase=think] .dk3-arm3:not(.dk3-far){animation:dkan-think-arm 1.8s ease-in-out infinite alternate;}",
3065
- ".dkan-bot-scene[data-phase=think] .dk3-arm3.dk3-far{animation:dkan-think-arm-far 1.8s ease-in-out infinite alternate;}",
3066
- "@keyframes dkan-think-head{from{transform:rotateZ(-12deg) translateY(-1px)}to{transform:rotateZ(-22deg) translate(3px,-4px)}}",
3067
- "@keyframes dkan-think-arm{from{transform:rotateZ(-4deg)}to{transform:rotateZ(-34deg) translate(1px,-8px)}}",
3068
- "@keyframes dkan-think-arm-far{from{transform:translateZ(-8px) rotateZ(-2deg)}to{transform:translateZ(-8px) rotateZ(-24deg) translate(1px,-7px)}}",
3069
- // write/code:中屏高亮代码滚动 + 肘部高频敲击 + 低头专注
3070
- ".dkan-bot-scene[data-phase=write] .dk3-mon3.center .dk3-screen,.dkan-bot-scene[data-phase=code] .dk3-mon3.center .dk3-screen{opacity:1;box-shadow:0 0 10px color-mix(in srgb,var(--dkan-code-b,#60a5fa) 45%,transparent);}",
3071
- ".dkan-bot-scene[data-phase=write] .dk3-mon3.center .dk3-code,.dkan-bot-scene[data-phase=code] .dk3-mon3.center .dk3-code{animation-duration:calc(2.2s / var(--dkan-speed,1));}",
3072
- ".dkan-bot-scene[data-phase=write] .dk3-arm3:not(.dk3-far),.dkan-bot-scene[data-phase=code] .dk3-arm3:not(.dk3-far){animation:dkan-output-arm calc(.46s / var(--dkan-speed,1)) ease-in-out infinite alternate;}",
3073
- ".dkan-bot-scene[data-phase=write] .dk3-arm3.dk3-far,.dkan-bot-scene[data-phase=code] .dk3-arm3.dk3-far{animation:dkan-output-arm-far calc(.46s / var(--dkan-speed,1)) ease-in-out infinite alternate;}",
3074
- ".dkan-bot-scene[data-phase=write] .dk3-elbow,.dkan-bot-scene[data-phase=code] .dk3-elbow{animation:dkan-type3 calc(.22s / var(--dkan-speed,1)) ease-in-out infinite alternate;}",
3075
- ".dkan-bot-scene[data-phase=write] .dk3-arm3.dk3-far .dk3-elbow,.dkan-bot-scene[data-phase=code] .dk3-arm3.dk3-far .dk3-elbow{animation-delay:.11s;}",
3076
- "@keyframes dkan-type3{from{transform:rotate(12deg) translateY(-1px)}to{transform:rotate(-14deg) translateY(2px)}}",
3077
- "@keyframes dkan-output-arm{from{transform:rotateZ(7deg) translateY(0)}to{transform:rotateZ(-13deg) translateY(4px)}}",
3078
- "@keyframes dkan-output-arm-far{from{transform:translateZ(-8px) rotateZ(5deg)}to{transform:translateZ(-8px) rotateZ(-11deg) translateY(4px)}}",
3079
- ".dkan-bot-scene[data-phase=write] .dk3-head3,.dkan-bot-scene[data-phase=code] .dk3-head3{animation:dkan-output-head calc(.8s / var(--dkan-speed,1)) ease-in-out infinite alternate;}",
3080
- "@keyframes dkan-output-head{from{transform:rotateZ(4deg) translateY(0)}to{transform:rotateZ(10deg) translate(2px,2px)}}",
3081
- // search:侧屏高亮 + 滚动加速 + 头部左右扫视(一会忙这个一会看那个)
3082
- ".dkan-bot-scene[data-phase=search] .dk3-mon3.left .dk3-screen,.dkan-bot-scene[data-phase=search] .dk3-mon3.right .dk3-screen{opacity:1;box-shadow:0 0 8px color-mix(in srgb,var(--dkan-code-a,#4ade80) 40%,transparent);}",
3083
- ".dkan-bot-scene[data-phase=search] .dk3-mon3.left .dk3-code,.dkan-bot-scene[data-phase=search] .dk3-mon3.right .dk3-code{animation-duration:calc(1.6s / var(--dkan-speed,1));}",
3084
- ".dkan-bot-scene[data-phase=search] .dk3-head3{animation:dkan-scan3 3.4s ease-in-out infinite;}",
3085
- "@keyframes dkan-scan3{0%,16%{transform:rotateZ(3deg) rotateY(-38deg)}30%,48%{transform:rotateZ(3deg) rotateY(6deg)}62%,80%{transform:rotateZ(3deg) rotateY(38deg)}100%{transform:rotateZ(3deg) rotateY(-38deg)}}",
3086
- "@media (prefers-reduced-motion:reduce){.dkan-botcard *{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;}}",
3321
+ ".dkan-bot-scene[data-phase=think] .dk3-upper3{animation:dkan-think-upper max(1.8s,calc(2.4s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
3322
+ ".dkan-bot-scene[data-phase=think] .dk3-head3{animation:dkan-think-head max(1.8s,calc(2.4s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
3323
+ ".dkan-bot-scene[data-phase=think] .dk3-arm3.dk3-near{animation:dkan-think-near max(1.8s,calc(2.4s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
3324
+ ".dkan-bot-scene[data-phase=think] .dk3-arm3.dk3-far{transform:translateZ(-7px) rotateZ(3deg);}",
3325
+ ".dkan-bot-scene[data-phase=think] .dk3-near .dk3-elbow{transform:rotateZ(-28deg) translateY(-1px);}",
3326
+ ".dkan-bot-scene[data-phase=think] .dk3-near .dk3-wrist3{transform:rotateZ(-18deg) translateY(-1px);}",
3327
+ "@keyframes dkan-think-upper{0%,44%{transform:rotateZ(-1deg) translateY(0)}62%,100%{transform:rotateZ(-1.8deg) translateY(-.5px)}}",
3328
+ "@keyframes dkan-think-head{0%,44%{transform:var(--dk3-head-turn) rotateZ(-3deg)}62%,100%{transform:var(--dk3-head-turn) rotateZ(-6deg) translateY(-.5px)}}",
3329
+ "@keyframes dkan-think-near{0%,44%{transform:rotateZ(-31deg) translate(-8px,-14.5px)}62%,100%{transform:rotateZ(-34deg) translate(-8.5px,-15px)}}",
3330
+ // write/code:身体仍面向桌面,仅轻微前倾;主要由手腕和手指敲击。
3331
+ ".dkan-bot-scene[data-phase=write] .dk3-mon3.right .dk3-screen,.dkan-bot-scene[data-phase=code] .dk3-mon3.right .dk3-screen{opacity:1;box-shadow:0 0 11px color-mix(in srgb,var(--dkan-code-b,#60a5fa) 52%,transparent);}",
3332
+ ".dkan-bot-scene[data-phase=write] .dk3-mon3.right .dk3-code,.dkan-bot-scene[data-phase=code] .dk3-mon3.right .dk3-code{animation-duration:calc(1.35s / var(--dkan-speed,1));}",
3333
+ ".dkan-bot-scene[data-phase=write] .dk3-upper3,.dkan-bot-scene[data-phase=code] .dk3-upper3{animation:dkan-code-upper max(1.2s,calc(2.4s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
3334
+ ".dkan-bot-scene[data-phase=write] .dk3-arm3.dk3-near,.dkan-bot-scene[data-phase=code] .dk3-arm3.dk3-near{transform:rotateZ(3deg);}",
3335
+ ".dkan-bot-scene[data-phase=write] .dk3-arm3.dk3-far,.dkan-bot-scene[data-phase=code] .dk3-arm3.dk3-far{transform:translateZ(-7px) rotateZ(1deg);}",
3336
+ ".dkan-bot-scene[data-phase=write] .dk3-elbow,.dkan-bot-scene[data-phase=code] .dk3-elbow{animation:dkan-type-elbow max(.28s,calc(.58s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
3337
+ ".dkan-bot-scene[data-phase=write] .dk3-wrist3,.dkan-bot-scene[data-phase=code] .dk3-wrist3{animation:dkan-type-wrist max(.18s,calc(.29s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
3338
+ ".dkan-bot-scene[data-phase=write] .dk3-far .dk3-elbow,.dkan-bot-scene[data-phase=code] .dk3-far .dk3-elbow{animation-delay:-.09s;animation-duration:max(.3s,calc(.63s / var(--dkan-speed,1)));}",
3339
+ ".dkan-bot-scene[data-phase=write] .dk3-far .dk3-wrist3,.dkan-bot-scene[data-phase=code] .dk3-far .dk3-wrist3{animation-delay:-.09s;animation-duration:max(.2s,calc(.33s / var(--dkan-speed,1)));}",
3340
+ ".dkan-bot-scene[data-phase=write] .dk3-head3,.dkan-bot-scene[data-phase=code] .dk3-head3{animation:dkan-output-head max(1.2s,calc(2.4s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
3341
+ "@keyframes dkan-code-upper{0%,38%{transform:rotateZ(2deg) translate(1px,0)}62%,100%{transform:rotateZ(3deg) translate(1px,1px)}}",
3342
+ "@keyframes dkan-type-elbow{0%,38%{transform:rotateZ(-4deg)}62%,100%{transform:rotateZ(5deg) translateY(1px)}}",
3343
+ "@keyframes dkan-type-wrist{0%,34%{transform:rotateZ(-2deg) translateY(0)}62%,100%{transform:rotateZ(3deg) translateY(1.5px)}}",
3344
+ "@keyframes dkan-output-head{0%,46%,100%{transform:var(--dk3-head-turn) rotateZ(3deg)}58%{transform:var(--dk3-head-turn) rotateZ(5deg) translateY(1px)}}",
3345
+ // search:身体正对桌面,头看左屏,近侧手腕小幅操作鼠标。
3346
+ ".dkan-bot-scene[data-phase=search] .dk3-mon3.left .dk3-screen{opacity:1;box-shadow:0 0 10px color-mix(in srgb,var(--dkan-code-a,#4ade80) 52%,transparent);}",
3347
+ ".dkan-bot-scene[data-phase=search] .dk3-mon3.left .dk3-search-results{animation-duration:calc(1.05s / var(--dkan-speed,1));}",
3348
+ ".dkan-bot-scene[data-phase=search] .dk3-upper3{transform:rotateZ(2deg) translateY(1px);}",
3349
+ ".dkan-bot-scene[data-phase=search] .dk3-head3{animation:dkan-search-head max(.72s,calc(1.15s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
3350
+ ".dkan-bot-scene[data-phase=search] .dk3-near .dk3-wrist3{animation:dkan-search-wrist max(.45s,calc(.72s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
3351
+ ".dkan-bot-scene[data-phase=search] .dk3-far{transform:translateZ(-7px) rotateZ(2deg);}",
3352
+ "@keyframes dkan-search-head{0%,28%{transform:var(--dk3-head-turn) rotateZ(1deg)}48%,68%{transform:var(--dk3-head-turn) rotateZ(6deg) translate(1px,1px)}88%,100%{transform:var(--dk3-head-turn) rotateZ(2deg)}}",
3353
+ "@keyframes dkan-search-wrist{0%,34%{transform:translateX(-1px)}62%,100%{transform:translateX(1.5px)}}",
3354
+ // 减少动态时停止空间位移,保留屏幕亮暗与思考状态的淡入反馈。
3355
+ "@media (prefers-reduced-motion:reduce){.dk3-person,.dk3-upper3,.dk3-head3,.dk3-arm3,.dk3-elbow,.dk3-wrist3,.dk3-wheel,.dk3-code,.dk3-search-results{animation:none!important;transition:none!important}.dk3-screen,.dkan-bubble{transition:opacity .2s cubic-bezier(.23,1,.32,1)!important}}",
3087
3356
  // 通知子选项行
3088
3357
  ".dkan-rows-narrow{display:flex;flex-direction:column;gap:6px;}",
3089
3358
  ".dkan-row{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--dsw-alias-label-secondary);flex-wrap:wrap;}",
@@ -3201,9 +3470,13 @@ var SHELL_CSS = [
3201
3470
  ".dock-badge{flex:none;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:3px 10px;font-size:12px;}",
3202
3471
  ".dock-body{border-top:1px solid var(--dsw-alias-border-l1);padding-top:8px;color:var(--dsw-alias-label-secondary);display:flex;flex-direction:column;gap:4px;}",
3203
3472
  // 侧栏入口按钮(docke2- 前缀)+ 功能坞弹出面板(dockm- 前缀,仿 dsh 设置的居中模态:遮罩 + 对话框,左导航 + 右内容)
3204
- ".docke2-btn{box-sizing:border-box;cursor:pointer;display:inline-flex;align-items:center;gap:6px;border:none;background:transparent;color:var(--dsw-alias-label-secondary);border-radius:10px;height:32px;font-family:inherit;font-size:13px;line-height:32px;transition:background .15s var(--ds-ease-in-out),color .15s var(--ds-ease-in-out);}",
3205
- ".docke2-btn:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);}",
3473
+ // 侧栏入口按钮(docke2- 前缀):与 dsh 设置按钮(.VOzbGW_trigger)几何逐条对齐——
3474
+ // 宽栏同为整宽左对齐行按钮(高 42、margin 4/-2、padding 0 10px 0 8px、圆角 12),窄栏同为 36 圆钮居中,
3475
+ // 使两按钮上下成列、左右边缘完全对齐(此前右对齐/叠放都会错位)。
3476
+ ".docke2-btn{box-sizing:border-box;cursor:pointer;display:flex;align-items:center;gap:8px;border:none;background:transparent;color:var(--dsw-alias-label-primary);border-radius:12px;width:calc(100% + 4px);height:42px;margin:4px -2px;padding:0 10px 0 8px;font-family:inherit;font-size:14px;line-height:22px;transition:background .15s var(--ds-ease-in-out),color .15s var(--ds-ease-in-out);}",
3477
+ ".docke2-btn:hover{background:var(--dsw-alias-interactive-bg-hover);}",
3206
3478
  ".docke2-btn.docke2-on{color:var(--dsw-alias-accent,#4d9fff);background:var(--dsw-alias-accent-soft,color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 12%,transparent));}",
3479
+ ".docke2-btn.docke2-rail{width:36px;height:36px;margin:8px 0 10px;padding:0;border-radius:50%;justify-content:center;gap:0;}",
3207
3480
  ".docke2-label{white-space:nowrap;overflow:hidden;}",
3208
3481
  ".dockm-backdrop{position:fixed;inset:0;z-index:80;display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--dsw-alias-bg-layer-1) 55%,transparent);backdrop-filter:blur(4px);pointer-events:auto;animation:dockm-fade .15s var(--ds-ease-in-out);}",
3209
3482
  "@keyframes dockm-fade{from{opacity:0}to{opacity:1}}",
@@ -3268,8 +3541,15 @@ var SHELL_CSS = [
3268
3541
  ".dockh-foot{display:flex;align-items:center;gap:8px;}",
3269
3542
  ".dockh-go{color:var(--dsw-alias-label-tertiary);font-size:11px;}",
3270
3543
  // 会话输入区工具行 chips(dockchip- 前缀):余额/用量随身小控件,挂在模型选择器左侧
3271
- ".dockchip-row{display:inline-flex;align-items:center;gap:4px;min-width:0;}",
3272
- ".dockchip{display:inline-flex;align-items:center;gap:5px;cursor:pointer;border:none;background:transparent;color:var(--dsw-alias-label-tertiary);border-radius:8px;padding:2px 8px;font-family:inherit;font-size:11px;line-height:18px;white-space:nowrap;transition:background .15s var(--ds-ease-in-out),color .15s var(--ds-ease-in-out);}",
3544
+ // 溢出兼容(两层防护,缺一不可):
3545
+ // 1) 宽度上限:宿主 .row 是 flex-wrap:wrap 且换行优先于收缩,chips 一长 tools 整行变宽,
3546
+ // 右侧模型选择器/发送键被挤到第二行(左右错位)。宿主 .row 带 container-type:inline-size,
3547
+ // 用容器单位 cqw 让上限随输入卡宽度自适应(窄卡少占、宽卡多占);不支持 cqw 的老内核退回固定 280px。
3548
+ // 2) 截断:超限部分用省略号截断(完整数值在 title 悬浮提示里),防 chips 凸出输入卡圆角(悬空)。
3549
+ ".dockchip-row{display:inline-flex;align-items:center;gap:4px;min-width:0;flex:0 1 auto;overflow:hidden;max-width:280px;}",
3550
+ "@supports (width:1cqw){.dockchip-row{max-width:min(280px,36cqw);}}",
3551
+ ".dockchip{display:inline-flex;align-items:center;gap:5px;cursor:pointer;border:none;background:transparent;color:var(--dsw-alias-label-tertiary);border-radius:8px;padding:2px 8px;font-family:inherit;font-size:11px;line-height:18px;white-space:nowrap;min-width:0;overflow:hidden;transition:background .15s var(--ds-ease-in-out),color .15s var(--ds-ease-in-out);}",
3552
+ ".dockchip > span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;}",
3273
3553
  ".dockchip:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);}",
3274
3554
  ".dockchip .dockchip-dot{width:6px;height:6px;border-radius:50%;flex:none;}",
3275
3555
  ".dockchip.err{color:var(--dsw-alias-state-error-primary);}"
@@ -3299,8 +3579,8 @@ function ensureCss() {
3299
3579
  }
3300
3580
  }
3301
3581
  function useExternalVersion() {
3302
- const [, bump] = import_react8.default.useReducer((n) => n + 1, 0);
3303
- import_react8.default.useEffect(() => {
3582
+ const [, bump] = import_react9.default.useReducer((n) => n + 1, 0);
3583
+ import_react9.default.useEffect(() => {
3304
3584
  externalListeners.add(bump);
3305
3585
  return () => {
3306
3586
  externalListeners.delete(bump);
@@ -3308,42 +3588,42 @@ function useExternalVersion() {
3308
3588
  }, []);
3309
3589
  }
3310
3590
  var lastGeom = { x: null, y: null, w: null, h: null };
3311
- function DockIcon() {
3312
- return import_react8.default.createElement(
3591
+ function DockIcon(props) {
3592
+ const size = props && props.size || 16;
3593
+ return import_react9.default.createElement(
3313
3594
  "svg",
3314
- { width: 16, height: 16, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: 1.3, "aria-hidden": true },
3315
- import_react8.default.createElement("rect", { x: 2.5, y: 2.5, width: 4.4, height: 4.4, rx: 1.2 }),
3316
- import_react8.default.createElement("rect", { x: 9, y: 2.5, width: 4.4, height: 4.4, rx: 1.2 }),
3317
- import_react8.default.createElement("rect", { x: 2.5, y: 9, width: 4.4, height: 4.4, rx: 1.2 }),
3318
- import_react8.default.createElement("rect", { x: 9, y: 9, width: 4.4, height: 4.4, rx: 1.2 })
3595
+ { width: size, height: size, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: 1.3, "aria-hidden": true },
3596
+ import_react9.default.createElement("rect", { x: 2.5, y: 2.5, width: 4.4, height: 4.4, rx: 1.2 }),
3597
+ import_react9.default.createElement("rect", { x: 9, y: 2.5, width: 4.4, height: 4.4, rx: 1.2 }),
3598
+ import_react9.default.createElement("rect", { x: 2.5, y: 9, width: 4.4, height: 4.4, rx: 1.2 }),
3599
+ import_react9.default.createElement("rect", { x: 9, y: 9, width: 4.4, height: 4.4, rx: 1.2 })
3319
3600
  );
3320
3601
  }
3321
3602
  function DockEntry(props) {
3322
3603
  const wide = !!props.wide;
3323
- const [open, setOpen] = import_react8.default.useState(panelNav.open);
3324
- import_react8.default.useEffect(() => subscribePanel(() => setOpen(panelNav.open)), []);
3325
- return import_react8.default.createElement("button", {
3604
+ const [open, setOpen] = import_react9.default.useState(panelNav.open);
3605
+ import_react9.default.useEffect(() => subscribePanel(() => setOpen(panelNav.open)), []);
3606
+ return import_react9.default.createElement("button", {
3326
3607
  type: "button",
3327
- className: "docke2-btn" + (open ? " docke2-on" : ""),
3328
- style: wide ? { marginLeft: "auto", transform: "translateY(46px)", zIndex: 1, height: 42, lineHeight: "42px", padding: "0 12px" } : { transform: "translateY(44px)", zIndex: 1, width: 36, height: 36, justifyContent: "center", padding: 0 },
3608
+ className: "docke2-btn" + (open ? " docke2-on" : "") + (wide ? "" : " docke2-rail"),
3329
3609
  title: "\u529F\u80FD\u575E",
3330
3610
  "aria-label": "\u529F\u80FD\u575E",
3331
3611
  "aria-expanded": open,
3332
3612
  onClick: () => setPanelOpen(!open)
3333
- }, import_react8.default.createElement(DockIcon, null), wide ? import_react8.default.createElement("span", { className: "docke2-label" }, "\u529F\u80FD\u575E") : null);
3613
+ }, import_react9.default.createElement(DockIcon, { size: wide ? 16 : 18 }), wide ? import_react9.default.createElement("span", { className: "docke2-label" }, "\u529F\u80FD\u575E") : null);
3334
3614
  }
3335
3615
  function DockModal() {
3336
- const [nav, setNav] = import_react8.default.useState({ open: panelNav.open, active: panelNav.active, params: panelNav.params });
3337
- import_react8.default.useEffect(() => subscribePanel(() => setNav({ open: panelNav.open, active: panelNav.active, params: panelNav.params })), []);
3616
+ const [nav, setNav] = import_react9.default.useState({ open: panelNav.open, active: panelNav.active, params: panelNav.params });
3617
+ import_react9.default.useEffect(() => subscribePanel(() => setNav({ open: panelNav.open, active: panelNav.active, params: panelNav.params })), []);
3338
3618
  const open = nav.open || typeof document === "undefined";
3339
3619
  const active = nav.active;
3340
3620
  const setActive = navigatePanel;
3341
3621
  const navParams = nav.params;
3342
- const [, force] = import_react8.default.useReducer((n) => n + 1, 0);
3622
+ const [, force] = import_react9.default.useReducer((n) => n + 1, 0);
3343
3623
  useExternalVersion();
3344
- const [win, setWin] = import_react8.default.useState(() => ({ mode: "normal", x: null, y: null, w: null, h: null }));
3345
- const dlgRef = import_react8.default.useRef(null);
3346
- import_react8.default.useEffect(() => {
3624
+ const [win, setWin] = import_react9.default.useState(() => ({ mode: "normal", x: null, y: null, w: null, h: null }));
3625
+ const dlgRef = import_react9.default.useRef(null);
3626
+ import_react9.default.useEffect(() => {
3347
3627
  if (lastGeom.w) setWin({ mode: "normal", x: lastGeom.x, y: lastGeom.y, w: lastGeom.w, h: lastGeom.h });
3348
3628
  }, []);
3349
3629
  function beginDrag(e, type) {
@@ -3381,13 +3661,13 @@ function DockModal() {
3381
3661
  const mod = isHome ? null : MODULES.find((m) => m.id === active) || MODULES[0];
3382
3662
  const st = mod ? stateOf(mod.id) : null;
3383
3663
  const View = mod ? mod.View : null;
3384
- const viewNode = mod && View ? import_react8.default.createElement(
3664
+ const viewNode = mod && View ? import_react9.default.createElement(
3385
3665
  "div",
3386
3666
  { className: "dockm-view" },
3387
- import_react8.default.createElement(
3388
- mod.external ? FeatureBoundary : import_react8.default.Fragment,
3667
+ import_react9.default.createElement(
3668
+ mod.external ? FeatureBoundary : import_react9.default.Fragment,
3389
3669
  null,
3390
- import_react8.default.createElement(View, { ctx: ctxRef.current, feature: mod, params: navParams })
3670
+ import_react9.default.createElement(View, { ctx: ctxRef.current, feature: mod, params: navParams })
3391
3671
  )
3392
3672
  ) : null;
3393
3673
  const enabledCount = MODULES.filter((m) => {
@@ -3401,10 +3681,10 @@ function DockModal() {
3401
3681
  width: win.w != null ? win.w : void 0,
3402
3682
  height: win.mode === "min" ? "auto" : win.h != null ? win.h : void 0
3403
3683
  } : null;
3404
- return import_react8.default.createElement(
3684
+ return import_react9.default.createElement(
3405
3685
  "div",
3406
3686
  { className: "dockm-backdrop", onClick: () => setPanelOpen(false) },
3407
- import_react8.default.createElement(
3687
+ import_react9.default.createElement(
3408
3688
  "div",
3409
3689
  {
3410
3690
  className: "dockm-dialog" + (win.mode === "max" ? " dockm-max" : "") + (win.mode === "min" ? " dockm-min" : ""),
@@ -3412,41 +3692,41 @@ function DockModal() {
3412
3692
  ref: dlgRef,
3413
3693
  onClick: (e) => e.stopPropagation()
3414
3694
  },
3415
- import_react8.default.createElement(
3695
+ import_react9.default.createElement(
3416
3696
  "div",
3417
3697
  {
3418
3698
  className: "dockm-head",
3419
3699
  onPointerDown: (e) => beginDrag(e, "move"),
3420
3700
  onDoubleClick: () => setWin((s) => Object.assign({}, s, { mode: s.mode === "max" ? "normal" : "max" }))
3421
3701
  },
3422
- import_react8.default.createElement(DockIcon, null),
3423
- import_react8.default.createElement("span", { className: "dockm-title" }, "\u529F\u80FD\u575E"),
3424
- import_react8.default.createElement("span", { className: "dockm-sub" }, "dsh-dock \xB7 \u4E5F\u53EF\u5728 \u8BBE\u7F6E \u2192 \u529F\u80FD\u575E \u6253\u5F00\u7BA1\u7406\u9875"),
3425
- import_react8.default.createElement(
3702
+ import_react9.default.createElement(DockIcon, null),
3703
+ import_react9.default.createElement("span", { className: "dockm-title" }, "\u529F\u80FD\u575E"),
3704
+ import_react9.default.createElement("span", { className: "dockm-sub" }, "dsh-dock \xB7 \u4E5F\u53EF\u5728 \u8BBE\u7F6E \u2192 \u529F\u80FD\u575E \u6253\u5F00\u7BA1\u7406\u9875"),
3705
+ import_react9.default.createElement(
3426
3706
  "span",
3427
3707
  { className: "dockm-ctrls" },
3428
- import_react8.default.createElement("button", {
3708
+ import_react9.default.createElement("button", {
3429
3709
  type: "button",
3430
3710
  className: "dockm-win",
3431
3711
  title: win.mode === "min" ? "\u8FD8\u539F" : "\u6700\u5C0F\u5316",
3432
3712
  onClick: () => setWin((s) => Object.assign({}, s, { mode: s.mode === "min" ? "normal" : "min" }))
3433
3713
  }, "\u2581"),
3434
- import_react8.default.createElement("button", {
3714
+ import_react9.default.createElement("button", {
3435
3715
  type: "button",
3436
3716
  className: "dockm-win",
3437
3717
  title: win.mode === "max" ? "\u8FD8\u539F" : "\u6700\u5927\u5316",
3438
3718
  onClick: () => setWin((s) => Object.assign({}, s, { mode: s.mode === "max" ? "normal" : "max" }))
3439
3719
  }, win.mode === "max" ? "\u2750" : "\u25A2"),
3440
- import_react8.default.createElement("button", { type: "button", className: "dockm-close", "aria-label": "\u5173\u95ED", title: "\u5173\u95ED", onClick: () => setPanelOpen(false) }, "\u2715")
3720
+ import_react9.default.createElement("button", { type: "button", className: "dockm-close", "aria-label": "\u5173\u95ED", title: "\u5173\u95ED", onClick: () => setPanelOpen(false) }, "\u2715")
3441
3721
  )
3442
3722
  ),
3443
- import_react8.default.createElement(
3723
+ import_react9.default.createElement(
3444
3724
  "div",
3445
3725
  { className: "dockm-body" },
3446
- import_react8.default.createElement(
3726
+ import_react9.default.createElement(
3447
3727
  "nav",
3448
3728
  { className: "dockm-nav", "aria-label": "\u529F\u80FD\u6A21\u5757" },
3449
- import_react8.default.createElement(
3729
+ import_react9.default.createElement(
3450
3730
  "button",
3451
3731
  {
3452
3732
  type: "button",
@@ -3454,10 +3734,10 @@ function DockModal() {
3454
3734
  className: "dockm-nav-item" + (isHome ? " on" : ""),
3455
3735
  onClick: () => setActive("home")
3456
3736
  },
3457
- import_react8.default.createElement("span", { className: "dockm-navhome" }, import_react8.default.createElement(DockIcon, null)),
3458
- import_react8.default.createElement("span", null, "\u9996\u9875")
3737
+ import_react9.default.createElement("span", { className: "dockm-navhome" }, import_react9.default.createElement(DockIcon, null)),
3738
+ import_react9.default.createElement("span", null, "\u9996\u9875")
3459
3739
  ),
3460
- MODULES.map((m) => import_react8.default.createElement(
3740
+ MODULES.map((m) => import_react9.default.createElement(
3461
3741
  "button",
3462
3742
  {
3463
3743
  type: "button",
@@ -3465,42 +3745,42 @@ function DockModal() {
3465
3745
  className: "dockm-nav-item" + (m.id === active ? " on" : ""),
3466
3746
  onClick: () => setActive(m.id)
3467
3747
  },
3468
- import_react8.default.createElement("span", { className: "dockm-dot", style: { background: m.accent } }),
3469
- import_react8.default.createElement("span", null, m.name),
3470
- m.planned ? import_react8.default.createElement("span", { className: "dockm-badge" }, "\u89C4\u5212\u4E2D") : null,
3471
- m.external ? import_react8.default.createElement("span", { className: "dockm-badge" }, "\u5916\u90E8") : null
3748
+ import_react9.default.createElement("span", { className: "dockm-dot", style: { background: m.accent } }),
3749
+ import_react9.default.createElement("span", null, m.name),
3750
+ m.planned ? import_react9.default.createElement("span", { className: "dockm-badge" }, "\u89C4\u5212\u4E2D") : null,
3751
+ m.external ? import_react9.default.createElement("span", { className: "dockm-badge" }, "\u5916\u90E8") : null
3472
3752
  ))
3473
3753
  ),
3474
- import_react8.default.createElement(
3754
+ import_react9.default.createElement(
3475
3755
  "div",
3476
3756
  { className: "dockm-content" },
3477
- import_react8.default.createElement(
3757
+ import_react9.default.createElement(
3478
3758
  "div",
3479
3759
  { className: "dockm-content-head" },
3480
- import_react8.default.createElement(
3760
+ import_react9.default.createElement(
3481
3761
  "div",
3482
3762
  { className: "dockm-name" },
3483
- isHome ? import_react8.default.createElement("span", { className: "dockm-navhome" }, import_react8.default.createElement(DockIcon, null)) : import_react8.default.createElement("span", { className: "dockm-dot", style: { background: mod.accent } }),
3763
+ isHome ? import_react9.default.createElement("span", { className: "dockm-navhome" }, import_react9.default.createElement(DockIcon, null)) : import_react9.default.createElement("span", { className: "dockm-dot", style: { background: mod.accent } }),
3484
3764
  isHome ? "\u9996\u9875" : mod.name,
3485
- !isHome && mod.planned ? import_react8.default.createElement("span", { className: "dockm-badge" }, "\u89C4\u5212\u4E2D") : null,
3486
- !isHome && mod.external ? import_react8.default.createElement("span", { className: "dockm-badge" }, "\u5916\u90E8\u5305" + (mod.package ? " \xB7 " + mod.package : "")) : null
3765
+ !isHome && mod.planned ? import_react9.default.createElement("span", { className: "dockm-badge" }, "\u89C4\u5212\u4E2D") : null,
3766
+ !isHome && mod.external ? import_react9.default.createElement("span", { className: "dockm-badge" }, "\u5916\u90E8\u5305" + (mod.package ? " \xB7 " + mod.package : "")) : null
3487
3767
  ),
3488
- import_react8.default.createElement(
3768
+ import_react9.default.createElement(
3489
3769
  "div",
3490
3770
  { className: "dockm-desc" },
3491
3771
  isHome ? "\u6240\u6709\u5B50\u529F\u80FD\u603B\u63FD\uFF1A\u8FD0\u884C\u72B6\u6001\u3001\u6982\u8981\u4E0E\u5FEB\u6377\u5F00\u5173\uFF0C\u70B9\u51FB\u5361\u7247\u8FDB\u5165\u5BF9\u5E94\u529F\u80FD\u9875\u3002" : mod.description
3492
3772
  )
3493
3773
  ),
3494
- isHome ? import_react8.default.createElement("div", { className: "dockm-view" }, import_react8.default.createElement(HomeView, { ctx: ctxRef.current, onOpen: setActive, onToggle: force })) : mod.planned ? import_react8.default.createElement("div", { className: "dockm-note" }, PLANNED_NOTES[mod.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : st && st.enabled && viewNode ? viewNode : st && st.error ? import_react8.default.createElement("div", { className: "dockm-note dockm-err" }, "\u529F\u80FD\u51FA\u9519\uFF1A" + st.error) : import_react8.default.createElement("div", { className: "dockm-note" }, "\u8BE5\u529F\u80FD\u5F53\u524D\u4E3A\u505C\u7528\u72B6\u6001\uFF08\u5F00\u5173\u5DF2\u6301\u4E45\u5316\uFF0C\u91CD\u542F\u540E\u4FDD\u6301\uFF09"),
3495
- import_react8.default.createElement(
3774
+ isHome ? import_react9.default.createElement("div", { className: "dockm-view" }, import_react9.default.createElement(HomeView, { ctx: ctxRef.current, onOpen: setActive, onToggle: force })) : mod.planned ? import_react9.default.createElement("div", { className: "dockm-note" }, PLANNED_NOTES[mod.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : st && st.enabled && viewNode ? viewNode : st && st.error ? import_react9.default.createElement("div", { className: "dockm-note dockm-err" }, "\u529F\u80FD\u51FA\u9519\uFF1A" + st.error) : import_react9.default.createElement("div", { className: "dockm-note" }, "\u8BE5\u529F\u80FD\u5F53\u524D\u4E3A\u505C\u7528\u72B6\u6001\uFF08\u5F00\u5173\u5DF2\u6301\u4E45\u5316\uFF0C\u91CD\u542F\u540E\u4FDD\u6301\uFF09"),
3775
+ import_react9.default.createElement(
3496
3776
  "div",
3497
3777
  { className: "dockm-foot" },
3498
- import_react8.default.createElement("span", null, isHome ? "\u529F\u80FD\u575E v" + DOCK_VERSION + " \xB7 \u5171 " + MODULES.length + " \u4E2A\u529F\u80FD\u6A21\u5757\uFF0C" + enabledCount + " \u4E2A\u5DF2\u542F\u7528" : "\u529F\u80FD\u575E v" + DOCK_VERSION + " \xB7 \u65B0\u529F\u80FD\u6309\u8DEF\u7EBF\u56FE\u8FFD\u52A0"),
3499
- !isHome && mod && !mod.planned && st ? import_react8.default.createElement(
3778
+ import_react9.default.createElement("span", null, isHome ? "\u529F\u80FD\u575E v" + DOCK_VERSION + " \xB7 \u5171 " + MODULES.length + " \u4E2A\u529F\u80FD\u6A21\u5757\uFF0C" + enabledCount + " \u4E2A\u5DF2\u542F\u7528" : "\u529F\u80FD\u575E v" + DOCK_VERSION + " \xB7 \u65B0\u529F\u80FD\u6309\u8DEF\u7EBF\u56FE\u8FFD\u52A0"),
3779
+ !isHome && mod && !mod.planned && st ? import_react9.default.createElement(
3500
3780
  "span",
3501
3781
  { className: "dockm-foot-sw" },
3502
- import_react8.default.createElement("span", { className: "dockm-foot-swlabel" + (st.enabled ? " on" : "") }, st.enabled ? "\u5DF2\u542F\u7528" : "\u5DF2\u505C\u7528"),
3503
- import_react8.default.createElement("button", {
3782
+ import_react9.default.createElement("span", { className: "dockm-foot-swlabel" + (st.enabled ? " on" : "") }, st.enabled ? "\u5DF2\u542F\u7528" : "\u5DF2\u505C\u7528"),
3783
+ import_react9.default.createElement("button", {
3504
3784
  type: "button",
3505
3785
  className: "dock-sw" + (st.enabled ? " on" : ""),
3506
3786
  role: "switch",
@@ -3513,11 +3793,11 @@ function DockModal() {
3513
3793
  }
3514
3794
  })
3515
3795
  ) : null,
3516
- !isHome && mod && typeof mod.Chip === "function" ? import_react8.default.createElement(
3796
+ !isHome && mod && typeof mod.Chip === "function" ? import_react9.default.createElement(
3517
3797
  "span",
3518
3798
  { className: "dockm-foot-sw" },
3519
- import_react8.default.createElement("span", { className: "dockm-foot-swlabel" + (chipShown(mod.id) ? " on" : "") }, "\u4F1A\u8BDD\u9875\u5C0F\u63A7\u4EF6"),
3520
- import_react8.default.createElement("button", {
3799
+ import_react9.default.createElement("span", { className: "dockm-foot-swlabel" + (chipShown(mod.id) ? " on" : "") }, "\u4F1A\u8BDD\u9875\u5C0F\u63A7\u4EF6"),
3800
+ import_react9.default.createElement("button", {
3521
3801
  type: "button",
3522
3802
  className: "dock-sw" + (chipShown(mod.id) ? " on" : ""),
3523
3803
  role: "switch",
@@ -3533,30 +3813,30 @@ function DockModal() {
3533
3813
  )
3534
3814
  )
3535
3815
  ),
3536
- win.mode === "normal" ? import_react8.default.createElement("div", { className: "dockm-resize", onPointerDown: (e) => beginDrag(e, "size") }) : null
3816
+ win.mode === "normal" ? import_react9.default.createElement("div", { className: "dockm-resize", onPointerDown: (e) => beginDrag(e, "size") }) : null
3537
3817
  )
3538
3818
  );
3539
3819
  }
3540
3820
  function HomeView(props) {
3541
3821
  const ctx = props && props.ctx;
3542
- const [, force] = import_react8.default.useReducer((n) => n + 1, 0);
3822
+ const [, force] = import_react9.default.useReducer((n) => n + 1, 0);
3543
3823
  useExternalVersion();
3544
3824
  const open = (id) => {
3545
3825
  if (props && typeof props.onOpen === "function") props.onOpen(id);
3546
3826
  };
3547
- return import_react8.default.createElement(
3827
+ return import_react9.default.createElement(
3548
3828
  "div",
3549
3829
  { className: "dockh-grid" },
3550
3830
  allModules().map((m) => {
3551
3831
  const st = stateOf(m.id);
3552
3832
  const enabled = !!(st && st.enabled);
3553
3833
  const Stat = m.HomeStat;
3554
- const statNode = m.planned ? import_react8.default.createElement("span", null, PLANNED_NOTES[m.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : enabled && Stat ? import_react8.default.createElement(
3555
- m.external ? FeatureBoundary : import_react8.default.Fragment,
3834
+ const statNode = m.planned ? import_react9.default.createElement("span", null, PLANNED_NOTES[m.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : enabled && Stat ? import_react9.default.createElement(
3835
+ m.external ? FeatureBoundary : import_react9.default.Fragment,
3556
3836
  null,
3557
- import_react8.default.createElement(Stat, { ctx })
3558
- ) : import_react8.default.createElement("span", null, "\u5DF2\u505C\u7528\uFF0C\u542F\u7528\u540E\u5728\u6B64\u5C55\u793A\u8FD0\u884C\u6982\u8981");
3559
- return import_react8.default.createElement(
3837
+ import_react9.default.createElement(Stat, { ctx })
3838
+ ) : import_react9.default.createElement("span", null, "\u5DF2\u505C\u7528\uFF0C\u542F\u7528\u540E\u5728\u6B64\u5C55\u793A\u8FD0\u884C\u6982\u8981");
3839
+ return import_react9.default.createElement(
3560
3840
  "div",
3561
3841
  {
3562
3842
  key: m.id,
@@ -3571,21 +3851,21 @@ function HomeView(props) {
3571
3851
  }
3572
3852
  }
3573
3853
  },
3574
- import_react8.default.createElement(
3854
+ import_react9.default.createElement(
3575
3855
  "div",
3576
3856
  { className: "dockh-head" },
3577
- import_react8.default.createElement("span", { className: "dockm-dot", style: { background: m.accent } }),
3578
- import_react8.default.createElement("span", { className: "dockh-name" }, m.name),
3579
- m.external ? import_react8.default.createElement("span", { className: "dockh-badge", title: m.package || void 0 }, "\u5916\u90E8") : null,
3857
+ import_react9.default.createElement("span", { className: "dockm-dot", style: { background: m.accent } }),
3858
+ import_react9.default.createElement("span", { className: "dockh-name" }, m.name),
3859
+ m.external ? import_react9.default.createElement("span", { className: "dockh-badge", title: m.package || void 0 }, "\u5916\u90E8") : null,
3580
3860
  // 状态标识:圆点 + 文字(纯展示,与开关视觉区分)
3581
- import_react8.default.createElement(
3861
+ import_react9.default.createElement(
3582
3862
  "span",
3583
3863
  { className: "dockh-status" + (m.planned ? " plan" : enabled ? "" : " off") },
3584
- import_react8.default.createElement("span", { className: "dockh-sdot" }),
3585
- import_react8.default.createElement("span", null, m.planned ? "\u89C4\u5212\u4E2D" : enabled ? "\u8FD0\u884C\u4E2D" : "\u5DF2\u505C\u7528")
3864
+ import_react9.default.createElement("span", { className: "dockh-sdot" }),
3865
+ import_react9.default.createElement("span", null, m.planned ? "\u89C4\u5212\u4E2D" : enabled ? "\u8FD0\u884C\u4E2D" : "\u5DF2\u505C\u7528")
3586
3866
  ),
3587
3867
  // 启停开关(规划中的功能不显示)
3588
- m.planned ? null : import_react8.default.createElement("button", {
3868
+ m.planned ? null : import_react9.default.createElement("button", {
3589
3869
  type: "button",
3590
3870
  className: "dock-sw" + (enabled ? " on" : ""),
3591
3871
  role: "switch",
@@ -3600,12 +3880,12 @@ function HomeView(props) {
3600
3880
  }
3601
3881
  })
3602
3882
  ),
3603
- import_react8.default.createElement("div", { className: "dockh-desc" }, m.description),
3604
- import_react8.default.createElement("div", { className: "dockh-stat" }, statNode),
3605
- import_react8.default.createElement(
3883
+ import_react9.default.createElement("div", { className: "dockh-desc" }, m.description),
3884
+ import_react9.default.createElement("div", { className: "dockh-stat" }, statNode),
3885
+ import_react9.default.createElement(
3606
3886
  "div",
3607
3887
  { className: "dockh-foot" },
3608
- import_react8.default.createElement("span", { className: "dockh-go" }, "\u67E5\u770B\u8BE6\u60C5 \u2192")
3888
+ import_react9.default.createElement("span", { className: "dockh-go" }, "\u67E5\u770B\u8BE6\u60C5 \u2192")
3609
3889
  )
3610
3890
  );
3611
3891
  })
@@ -3613,16 +3893,16 @@ function HomeView(props) {
3613
3893
  }
3614
3894
  function DockPanel() {
3615
3895
  const ctx = ctxRef.current;
3616
- const [, force] = import_react8.default.useReducer((n) => n + 1, 0);
3896
+ const [, force] = import_react9.default.useReducer((n) => n + 1, 0);
3617
3897
  useExternalVersion();
3618
3898
  const toggle = (id) => {
3619
3899
  toggleFeature(id);
3620
3900
  force();
3621
3901
  };
3622
- return import_react8.default.createElement(
3902
+ return import_react9.default.createElement(
3623
3903
  "div",
3624
3904
  { className: "dock-root" },
3625
- import_react8.default.createElement(
3905
+ import_react9.default.createElement(
3626
3906
  "div",
3627
3907
  { className: "dock-intro" },
3628
3908
  "\u529F\u80FD\u575E\uFF08dsh-dock\uFF09\xB7 \u6240\u6709\u5C0F\u529F\u80FD\u96C6\u4E2D\u5728\u8FD9\u4E00\u4E2A\u9762\u677F\u91CC\u7BA1\u7406\u3002v0.4.0 \u8D77\u6BCF\u4E2A\u529F\u80FD\u662F\u72EC\u7ACB\u6A21\u5757\uFF08features/<id>/\uFF09\uFF0C",
@@ -3631,25 +3911,25 @@ function DockPanel() {
3631
3911
  allModules().map((f) => {
3632
3912
  const st = stateOf(f.id);
3633
3913
  const View = f.View;
3634
- const viewNode = !f.planned && st.enabled && View ? import_react8.default.createElement(
3914
+ const viewNode = !f.planned && st.enabled && View ? import_react9.default.createElement(
3635
3915
  "div",
3636
3916
  { className: "dock-body" },
3637
- import_react8.default.createElement(
3638
- f.external ? FeatureBoundary : import_react8.default.Fragment,
3917
+ import_react9.default.createElement(
3918
+ f.external ? FeatureBoundary : import_react9.default.Fragment,
3639
3919
  null,
3640
- import_react8.default.createElement(View, { ctx, feature: f })
3920
+ import_react9.default.createElement(View, { ctx, feature: f })
3641
3921
  )
3642
3922
  ) : null;
3643
- return import_react8.default.createElement(
3923
+ return import_react9.default.createElement(
3644
3924
  "div",
3645
3925
  { className: "dock-card", key: f.id },
3646
- import_react8.default.createElement(
3926
+ import_react9.default.createElement(
3647
3927
  "div",
3648
3928
  { className: "dock-card-head" },
3649
- import_react8.default.createElement("span", { className: "dock-dot" + (st.error ? " err" : st.enabled ? " on" : "") }),
3650
- import_react8.default.createElement("span", { className: "dock-name" }, f.name),
3651
- import_react8.default.createElement("span", { className: "dock-desc" }, f.description + (f.external ? "\uFF08\u6765\u81EA\u5916\u90E8\u5305" + (f.package ? " " + f.package : "") + "\uFF09" : "")),
3652
- f.planned ? import_react8.default.createElement("span", { className: "dock-badge" }, "\u89C4\u5212\u4E2D") : import_react8.default.createElement("button", {
3929
+ import_react9.default.createElement("span", { className: "dock-dot" + (st.error ? " err" : st.enabled ? " on" : "") }),
3930
+ import_react9.default.createElement("span", { className: "dock-name" }, f.name),
3931
+ import_react9.default.createElement("span", { className: "dock-desc" }, f.description + (f.external ? "\uFF08\u6765\u81EA\u5916\u90E8\u5305" + (f.package ? " " + f.package : "") + "\uFF09" : "")),
3932
+ f.planned ? import_react9.default.createElement("span", { className: "dock-badge" }, "\u89C4\u5212\u4E2D") : import_react9.default.createElement("button", {
3653
3933
  type: "button",
3654
3934
  className: "dock-sw" + (st.enabled ? " on" : ""),
3655
3935
  role: "switch",
@@ -3658,11 +3938,11 @@ function DockPanel() {
3658
3938
  title: st.enabled ? "\u505C\u7528\u300C" + f.name + "\u300D" : "\u542F\u7528\u300C" + f.name + "\u300D",
3659
3939
  onClick: () => toggle(f.id)
3660
3940
  }),
3661
- !f.planned && typeof f.Chip === "function" ? import_react8.default.createElement(
3941
+ !f.planned && typeof f.Chip === "function" ? import_react9.default.createElement(
3662
3942
  "span",
3663
3943
  { className: "dockm-foot-sw" },
3664
- import_react8.default.createElement("span", { className: "dockm-foot-swlabel" + (chipShown(f.id) ? " on" : "") }, "\u4F1A\u8BDD\u9875\u5C0F\u63A7\u4EF6"),
3665
- import_react8.default.createElement("button", {
3944
+ import_react9.default.createElement("span", { className: "dockm-foot-swlabel" + (chipShown(f.id) ? " on" : "") }, "\u4F1A\u8BDD\u9875\u5C0F\u63A7\u4EF6"),
3945
+ import_react9.default.createElement("button", {
3666
3946
  type: "button",
3667
3947
  className: "dock-sw" + (chipShown(f.id) ? " on" : ""),
3668
3948
  role: "switch",
@@ -3676,19 +3956,19 @@ function DockPanel() {
3676
3956
  })
3677
3957
  ) : null
3678
3958
  ),
3679
- f.planned ? import_react8.default.createElement("div", { className: "dock-body" }, PLANNED_NOTES[f.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : st.error ? import_react8.default.createElement("div", { className: "dock-body dockm-err" }, "\u529F\u80FD\u51FA\u9519\uFF1A" + st.error) : null,
3959
+ f.planned ? import_react9.default.createElement("div", { className: "dock-body" }, PLANNED_NOTES[f.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : st.error ? import_react9.default.createElement("div", { className: "dock-body dockm-err" }, "\u529F\u80FD\u51FA\u9519\uFF1A" + st.error) : null,
3680
3960
  viewNode
3681
3961
  );
3682
3962
  })
3683
3963
  );
3684
3964
  }
3685
3965
  function DockChips(props) {
3686
- const [, force] = import_react8.default.useReducer((n) => n + 1, 0);
3687
- import_react8.default.useEffect(() => subscribeFeatureState(() => force()), []);
3966
+ const [, force] = import_react9.default.useReducer((n) => n + 1, 0);
3967
+ import_react9.default.useEffect(() => subscribeFeatureState(() => force()), []);
3688
3968
  const items = [];
3689
3969
  for (const f of allModules()) {
3690
3970
  if (f.planned || !stateOf(f.id).enabled || !chipShown(f.id) || typeof f.Chip !== "function") continue;
3691
- items.push(import_react8.default.createElement(f.Chip, {
3971
+ items.push(import_react9.default.createElement(f.Chip, {
3692
3972
  key: f.id,
3693
3973
  ctx: props.ctx,
3694
3974
  feature: f,
@@ -3698,23 +3978,23 @@ function DockChips(props) {
3698
3978
  }));
3699
3979
  }
3700
3980
  if (items.length === 0) return null;
3701
- return import_react8.default.createElement("div", { className: "dockchip-row" }, items);
3981
+ return import_react9.default.createElement("div", { className: "dockchip-row" }, items);
3702
3982
  }
3703
3983
  function FeatureOverlays() {
3704
- const [, force] = import_react8.default.useReducer((n) => n + 1, 0);
3984
+ const [, force] = import_react9.default.useReducer((n) => n + 1, 0);
3705
3985
  useExternalVersion();
3706
- import_react8.default.useEffect(() => subscribeFeatureState(() => force()), []);
3986
+ import_react9.default.useEffect(() => subscribeFeatureState(() => force()), []);
3707
3987
  const items = [];
3708
3988
  for (const f of allModules()) {
3709
3989
  if (f.planned || !stateOf(f.id).enabled || typeof f.Overlay !== "function") continue;
3710
- items.push(import_react8.default.createElement(
3990
+ items.push(import_react9.default.createElement(
3711
3991
  FeatureBoundary,
3712
3992
  { key: f.id },
3713
- import_react8.default.createElement(f.Overlay, { ctx: ctxRef.current, feature: f })
3993
+ import_react9.default.createElement(f.Overlay, { ctx: ctxRef.current, feature: f })
3714
3994
  ));
3715
3995
  }
3716
3996
  if (items.length === 0) return null;
3717
- return import_react8.default.createElement(import_react8.default.Fragment, null, items);
3997
+ return import_react9.default.createElement(import_react9.default.Fragment, null, items);
3718
3998
  }
3719
3999
  var ctxRef = { current: null };
3720
4000
  function apply(ctx) {
@@ -3725,23 +4005,23 @@ function apply(ctx) {
3725
4005
  if (slots === void 0) return;
3726
4006
  slots.inject("sidebar.footer.action", () => slots.register(
3727
4007
  { name: "sidebar.footer.action", id: "dsh-dock", order: 1, label: "\u529F\u80FD\u575E" },
3728
- (props) => import_react8.default.createElement(DockEntry, props)
4008
+ (props) => import_react9.default.createElement(DockEntry, props)
3729
4009
  ));
3730
4010
  slots.inject("shell.overlay", () => slots.register(
3731
4011
  { name: "shell.overlay", id: "dsh-dock-panel", order: 21, label: "\u529F\u80FD\u575E\u9762\u677F" },
3732
- () => import_react8.default.createElement(DockModal, null)
4012
+ () => import_react9.default.createElement(DockModal, null)
3733
4013
  ));
3734
4014
  slots.inject("shell.overlay", () => slots.register(
3735
4015
  { name: "shell.overlay", id: "dsh-dock-feature-overlays", order: 22, label: "\u529F\u80FD\u575E\u5168\u5C40\u6D6E\u5C42" },
3736
- () => import_react8.default.createElement(FeatureOverlays, null)
4016
+ () => import_react9.default.createElement(FeatureOverlays, null)
3737
4017
  ));
3738
4018
  slots.inject("settings.section", () => slots.register(
3739
4019
  { name: "settings.section", id: "dsh-dock", order: 90, label: "\u529F\u80FD\u575E" },
3740
- () => import_react8.default.createElement(DockPanel, null)
4020
+ () => import_react9.default.createElement(DockPanel, null)
3741
4021
  ));
3742
4022
  slots.inject("conversation.input.left", () => slots.register(
3743
4023
  { name: "conversation.input.left", id: "dsh-dock-chips", order: 10, label: "\u529F\u80FD\u575E" },
3744
- (zone) => import_react8.default.createElement(DockChips, Object.assign({}, zone, { ctx: ctxRef.current }))
4024
+ (zone) => import_react9.default.createElement(DockChips, Object.assign({}, zone, { ctx: ctxRef.current }))
3745
4025
  ));
3746
4026
  }
3747
4027
  var inject = ["timer"];