dsh-dock 0.9.2 → 0.9.5

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/README.md CHANGED
@@ -19,7 +19,7 @@
19
19
  | **用量记录** | 记录全部 LLM API 调用:秒级时间筛选、Token/费用统计(峰谷计价 + 官网价目自动同步)、分组汇总、明细检索与 CSV 导出 |
20
20
  | **模型设置** | 编辑各 Provider 模型目录:输入类型(文本/图片 + 标注)与思考强度档位;图片能力可由你手动声明,新增 Provider 自动刷新加载,写回官方配置热生效 |
21
21
  | **模型余额** | 展示所有模型 Provider 账户余额(5 分钟自动刷新) |
22
- | **任务动画** | 19 种任务运行动画(含星际远征、星云潮汐、曲速航道、量子雷达、星座网络、深海脉动、神经电路等)与完成通知(通知音、浏览器系统通知、钉钉/飞书群机器人推送),动画速度随任务活动联动,两组开关独立,配置全部持久化 |
22
+ | **任务动画** | 19 种任务运行动画(含星际远征、星云潮汐、曲速航道、量子雷达、星座网络、深海脉动、神经电路等)与完成/需确认通知(通知音、浏览器系统通知、钉钉/飞书群机器人推送),动画速度随任务活动联动,两组开关独立,配置全部持久化 |
23
23
 
24
24
  | **图片理解代理** | 图片识别等(visionproxy);原图候选默认折叠展示,图片能力以你的声明为准 |
25
25
  | **手机接力** | 手机扫码安全接入同一 DSH(反向代理 + 任务/备注同步);**局域网电脑直连(0.0.0.0)**——另起一个 0.0.0.0 绑定的完整 DSH 子实例,局域网电脑访问到的功能、交互与 127.0.0.1 完全一致(会话记录、工作区文件夹选择等) |
@@ -122,7 +122,8 @@ dsh plugin --profile web remove dsh-dock # 卸载
122
122
  - 代码雨:字符列沿屏幕缓落如数据流
123
123
  - 星野:细碎星点飘移闪烁,带弯月与流星
124
124
  - 极光:屏幕顶部柔光带缓慢呼吸流动
125
- - **完成通知**:任务结束时右上角弹出通知卡片(标题 / 模型 / 耗时 / 回合步骤 / Token / 结果摘要 / 结束原因),可分别开关「完成 / 异常」通知、选择停留时长、开启浏览器系统通知(仅页面后台时推送);**提示音** 6 种 WebAudio 合成音效可选(完成 / 异常各配一音,可单独试听)
125
+ - **完成通知**:任务结束时右上角弹出通知卡片(标题 / 模型 / 耗时 / 回合步骤 / Token / 结果摘要 / 结束原因),可分别开关「完成 / 异常」通知、选择停留时长、开启浏览器系统通知(仅页面后台时推送);**提示音** 6 种 WebAudio 合成音效可选(完成 / 异常 / 确认各配一音,可单独试听)
126
+ - **需确认提醒**:工具等待用户批准(如沙箱越界执行命令)时弹常驻通知卡片 + 确认音(页面后台时同步系统通知),人不在屏幕前任务也不会干等;等待 / 卡住状态卡片只对当前正在看的会话出现,停靠屏幕右上不挡正文
126
127
  2. 任务结束动效自动消失,完成瞬间一缕流光掠过;功能坞面板打开时环境动效自动隐藏避免重叠
127
128
 
128
129
  3. **钉钉推送**(可选):任务结束由宿主直发 markdown 消息到钉钉群机器人(浏览器关着也能推)——填入 Webhook 地址保存,「发送测试消息」验证连通;机器人安全设置选「自定义关键词」填「任务」或「dsh」;推送哪些事件跟随上方「完成 / 异常通知」开关
@@ -249,7 +250,8 @@ dsh plugin --profile web remove dsh-dock # 卸载
249
250
  - 代码雨:字符列沿屏幕缓落如数据流
250
251
  - 星野:细碎星点飘移闪烁,带弯月与流星
251
252
  - 极光:屏幕顶部柔光带缓慢呼吸流动
252
- - **完成通知**:任务结束时右上角弹出通知卡片(标题 / 模型 / 耗时 / 回合步骤 / Token / 结果摘要 / 结束原因),可分别开关「完成 / 异常」通知、选择停留时长、开启浏览器系统通知(仅页面后台时推送);**提示音** 6 种 WebAudio 合成音效可选(完成 / 异常各配一音,可单独试听)
253
+ - **完成通知**:任务结束时右上角弹出通知卡片(标题 / 模型 / 耗时 / 回合步骤 / Token / 结果摘要 / 结束原因),可分别开关「完成 / 异常」通知、选择停留时长、开启浏览器系统通知(仅页面后台时推送);**提示音** 6 种 WebAudio 合成音效可选(完成 / 异常 / 确认各配一音,可单独试听)
254
+ - **需确认提醒**:工具等待用户批准(如沙箱越界执行命令)时弹常驻通知卡片 + 确认音(页面后台时同步系统通知),人不在屏幕前任务也不会干等;等待 / 卡住状态卡片只对当前正在看的会话出现,停靠屏幕右上不挡正文
253
255
  2. 任务结束动效自动消失,完成瞬间一缕流光掠过;功能坞面板打开时环境动效自动隐藏避免重叠
254
256
 
255
257
  3. **钉钉推送**(可选):任务结束由宿主直发 markdown 消息到钉钉群机器人(浏览器关着也能推)——填入 Webhook 地址保存,「发送测试消息」验证连通;机器人安全设置选「自定义关键词」填「任务」或「dsh」;推送哪些事件跟随上方「完成 / 异常通知」开关
package/client.js CHANGED
@@ -2174,7 +2174,7 @@ function persistFeatureEnabled() {
2174
2174
  function initFeatureState(defs) {
2175
2175
  for (const f of defs) {
2176
2176
  if (featureState.has(f.id)) continue;
2177
- let enabled = !f.planned && f.defaultEnabled !== false;
2177
+ let enabled = !f.planned && f.defaultEnabled === true;
2178
2178
  const saved = featurePersist.map[f.id];
2179
2179
  if (typeof saved === "boolean") enabled = saved;
2180
2180
  featureState.set(f.id, { enabled, error: null });
@@ -3391,6 +3391,7 @@ var feature3 = {
3391
3391
  order: 140,
3392
3392
  accent: "#34d399",
3393
3393
  description: "\u793A\u4F8B\u529F\u80FD\uFF1A\u9762\u677F\u4FA7\u8FD0\u884C\u65F6\u957F\u5FC3\u8DF3\uFF08\u7EAF Client\uFF09",
3394
+ defaultEnabled: false,
3394
3395
  View: HeartbeatView,
3395
3396
  HomeStat: HeartbeatStat
3396
3397
  };
@@ -3449,6 +3450,7 @@ var feature4 = {
3449
3450
  order: 150,
3450
3451
  accent: "#a78bfa",
3451
3452
  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",
3453
+ defaultEnabled: false,
3452
3454
  View: ThemeView,
3453
3455
  HomeStat: ThemeStat
3454
3456
  };
@@ -3876,6 +3878,13 @@ var PHASE_COLORS = { think: "#2f6fed", write: "#0d9488", code: "#b45309", search
3876
3878
  function phaseColor(p) {
3877
3879
  return PHASE_COLORS[p] || "#2f6fed";
3878
3880
  }
3881
+ function toolLabel(name) {
3882
+ const n = String(name || "").toLowerCase();
3883
+ if (/bash|shell|terminal|cmd|pwsh|powershell|exec/.test(n)) return "\u6267\u884C\u547D\u4EE4";
3884
+ if (/write|edit|patch|apply|create|mkdir|remove|delete/.test(n)) return "\u4FEE\u6539\u6587\u4EF6";
3885
+ if (/web|fetch|browser|navigate|search/.test(n)) return "\u8BBF\u95EE\u7F51\u9875";
3886
+ return "";
3887
+ }
3879
3888
  var END_LABELS = {
3880
3889
  completed: { label: "\u5B8C\u6210", cls: "ok" },
3881
3890
  error: { label: "\u51FA\u9519", cls: "err" },
@@ -4109,12 +4118,12 @@ function RobotScene(props) {
4109
4118
  ] });
4110
4119
  }
4111
4120
  var SOUND_LIBRARY = {
4112
- chime: { name: "\u6E05\u8106\u53CC\u97F3", notes: { done: [[659.25, 0, 0.14], [880, 0.13, 0.24]], err: [[220, 0, 0.16], [164.81, 0.15, 0.3]] } },
4113
- ding: { name: "\u53EE", notes: { done: [[987.77, 0, 0.35]], err: [[246.94, 0, 0.4]] } },
4114
- coin: { name: "\u91D1\u5E01", notes: { done: [[988, 0, 0.08], [1319, 0.08, 0.35], [988, 0, 0.08, "square"], [1319, 0.08, 0.3, "square"]], err: [[196, 0, 0.12], [147, 0.11, 0.35]] } },
4115
- bell: { name: "\u949F\u58F0", notes: { done: [[523.25, 0, 0.5], [659.25, 0.02, 0.45], [783.99, 0.04, 0.4]], err: [[174.61, 0, 0.5], [130.81, 0.05, 0.5]] } },
4116
- pulse: { name: "\u8109\u51B2", notes: { done: [[440, 0, 0.09], [440, 0.14, 0.09], [440, 0.28, 0.16]], err: [[174.61, 0, 0.1], [174.61, 0.14, 0.1], [174.61, 0.28, 0.18]] } },
4117
- arp: { name: "\u7436\u97F3", notes: { done: [[523.25, 0, 0.12], [659.25, 0.09, 0.12], [783.99, 0.18, 0.12], [1046.5, 0.27, 0.3]], err: [[392, 0, 0.12], [329.63, 0.1, 0.12], [261.63, 0.2, 0.12], [196, 0.3, 0.32]] } }
4121
+ chime: { name: "\u6E05\u8106\u53CC\u97F3", notes: { done: [[659.25, 0, 0.14], [880, 0.13, 0.24]], err: [[220, 0, 0.16], [164.81, 0.15, 0.3]], ask: [[587.33, 0, 0.16], [880, 0.19, 0.34]] } },
4122
+ ding: { name: "\u53EE", notes: { done: [[987.77, 0, 0.35]], err: [[246.94, 0, 0.4]], ask: [[783.99, 0, 0.18], [1174.66, 0.2, 0.42]] } },
4123
+ coin: { name: "\u91D1\u5E01", notes: { done: [[988, 0, 0.08], [1319, 0.08, 0.35], [988, 0, 0.08, "square"], [1319, 0.08, 0.3, "square"]], err: [[196, 0, 0.12], [147, 0.11, 0.35]], ask: [[880, 0, 0.09], [1108.73, 0.1, 0.12], [1318.51, 0.22, 0.3]] } },
4124
+ bell: { name: "\u949F\u58F0", notes: { done: [[523.25, 0, 0.5], [659.25, 0.02, 0.45], [783.99, 0.04, 0.4]], err: [[174.61, 0, 0.5], [130.81, 0.05, 0.5]], ask: [[659.25, 0, 0.4], [523.25, 0.05, 0.55]] } },
4125
+ pulse: { name: "\u8109\u51B2", notes: { done: [[440, 0, 0.09], [440, 0.14, 0.09], [440, 0.28, 0.16]], err: [[174.61, 0, 0.1], [174.61, 0.14, 0.1], [174.61, 0.28, 0.18]], ask: [[523.25, 0, 0.09], [523.25, 0.15, 0.09], [659.25, 0.3, 0.22]] } },
4126
+ arp: { name: "\u7436\u97F3", notes: { done: [[523.25, 0, 0.12], [659.25, 0.09, 0.12], [783.99, 0.18, 0.12], [1046.5, 0.27, 0.3]], err: [[392, 0, 0.12], [329.63, 0.1, 0.12], [261.63, 0.2, 0.12], [196, 0.3, 0.32]], ask: [[440, 0, 0.11], [554.37, 0.12, 0.11], [659.25, 0.24, 0.11], [880, 0.36, 0.34]] } }
4118
4127
  };
4119
4128
  var soundCtx = null;
4120
4129
  function playTone(seq) {
@@ -4146,6 +4155,10 @@ function playDoneSound(success, effect) {
4146
4155
  const lib = SOUND_LIBRARY[effect] || SOUND_LIBRARY.chime;
4147
4156
  playTone(success ? lib.notes.done : lib.notes.err);
4148
4157
  }
4158
+ function playAskSound(effect) {
4159
+ const lib = SOUND_LIBRARY[effect] || SOUND_LIBRARY.chime;
4160
+ playTone(lib.notes.ask || lib.notes.done);
4161
+ }
4149
4162
  function previewSound(effect) {
4150
4163
  const lib = SOUND_LIBRARY[effect] || SOUND_LIBRARY.chime;
4151
4164
  playTone(lib.notes.done);
@@ -4168,11 +4181,14 @@ function Toast(props) {
4168
4181
  const timer = setTimeout(() => props.onClose(t.id), 240);
4169
4182
  return () => clearTimeout(timer);
4170
4183
  }, [closing]);
4171
- const markColor = t.kind === "success" ? "var(--dk-ok)" : t.kind === "error" ? "var(--dk-err)" : "var(--dk-warn)";
4172
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-toast" + (closing ? " out" : ""), children: [
4184
+ const markColor = t.kind === "success" ? "var(--dk-ok)" : t.kind === "error" ? "var(--dk-err)" : t.kind === "confirm" ? "var(--dk-warn)" : "var(--dk-warn)";
4185
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-toast" + (t.kind === "confirm" ? " dkan-toast-confirm" : "") + (closing ? " out" : ""), children: [
4173
4186
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-toast-head", children: [
4174
4187
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-toast-mark", style: { background: markColor } }),
4175
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-toast-title", title: t.title, children: t.title }),
4188
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-toast-title", title: t.title, children: [
4189
+ t.kind === "confirm" ? "\u270B " : "",
4190
+ t.title
4191
+ ] }),
4176
4192
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "dkan-toast-close", "aria-label": "\u5173\u95ED", onClick: close, children: "\u2715" })
4177
4193
  ] }),
4178
4194
  t.body ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-toast-body", children: t.body }) : null
@@ -4376,6 +4392,24 @@ function visibleRect(el) {
4376
4392
  const r = el.getBoundingClientRect();
4377
4393
  return r.width > 0 && r.height > 0 && r.bottom > 0 && r.top < window.innerHeight ? r : null;
4378
4394
  }
4395
+ function currentSessionTitle() {
4396
+ if (typeof document === "undefined") return "";
4397
+ for (const el of document.querySelectorAll('[role="treeitem"][aria-selected="true"]')) {
4398
+ const r = el.getBoundingClientRect();
4399
+ if (r.width > 0 && r.height > 0 && r.right <= window.innerWidth * 0.35) {
4400
+ const text = (el.textContent || "").trim();
4401
+ if (text) return text;
4402
+ }
4403
+ }
4404
+ return "";
4405
+ }
4406
+ function taskOnScreen(task, titleCache) {
4407
+ const title = task && (task.title || "");
4408
+ if (!title) return true;
4409
+ const current = titleCache !== void 0 ? titleCache : currentSessionTitle();
4410
+ if (!current) return true;
4411
+ return current === title || current.indexOf(title) !== -1 || title.indexOf(current) !== -1;
4412
+ }
4379
4413
  var COMPOSER_SEND_SELECTOR = 'button[aria-label="Send message"],button[aria-label*="\u53D1\u9001"],button[data-testid*="send"],button[data-testid*="submit"],button[type="submit"]';
4380
4414
  function conversationComposer() {
4381
4415
  if (typeof document === "undefined" || typeof window === "undefined") return null;
@@ -4445,7 +4479,6 @@ function useSpaceDocks(enabled) {
4445
4479
  let frame = 0;
4446
4480
  let idle = 0;
4447
4481
  let timer = 0;
4448
- let pollTimer = 0;
4449
4482
  let retries = 0;
4450
4483
  let pending = false;
4451
4484
  let observedComposer = null;
@@ -4501,7 +4534,25 @@ function useSpaceDocks(enabled) {
4501
4534
  }) : null;
4502
4535
  if (mutationObserver && document.body) mutationObserver.observe(document.body, { childList: true, subtree: true });
4503
4536
  schedule(0, true);
4504
- pollTimer = window.setInterval(() => schedule(), 700);
4537
+ let calibrationInterval = 700;
4538
+ let lastActivityAt = Date.now();
4539
+ const markActivity = () => {
4540
+ lastActivityAt = Date.now();
4541
+ if (calibrationInterval !== 700) {
4542
+ calibrationInterval = 700;
4543
+ restartPoll();
4544
+ }
4545
+ };
4546
+ const unsubscribeActivity = animationStore.subscribe(markActivity);
4547
+ let pollTimer = 0;
4548
+ function restartPoll() {
4549
+ if (pollTimer) window.clearInterval(pollTimer);
4550
+ pollTimer = window.setInterval(() => {
4551
+ if (Date.now() - lastActivityAt > 2e4 && calibrationInterval !== 5e3) calibrationInterval = 5e3;
4552
+ schedule();
4553
+ }, calibrationInterval);
4554
+ }
4555
+ restartPoll();
4505
4556
  const onResize = () => {
4506
4557
  if (idle && typeof window.cancelIdleCallback === "function") window.cancelIdleCallback(idle);
4507
4558
  if (timer) window.clearTimeout(timer);
@@ -4517,6 +4568,7 @@ function useSpaceDocks(enabled) {
4517
4568
  if (pollTimer) window.clearInterval(pollTimer);
4518
4569
  if (mutationObserver) mutationObserver.disconnect();
4519
4570
  if (resizeObserver) resizeObserver.disconnect();
4571
+ unsubscribeActivity();
4520
4572
  window.removeEventListener("resize", onResize);
4521
4573
  };
4522
4574
  }, [enabled]);
@@ -4597,13 +4649,14 @@ function MissionDeparture(props) {
4597
4649
  }, "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(FreighterHull, { units: 3, empty: true }) });
4598
4650
  }
4599
4651
  function ProgrammingStuck(props) {
4600
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-space-stuck", "aria-hidden": "true", children: [
4652
+ const waiting = !!props.waiting;
4653
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-space-stuck" + (waiting ? " waiting" : ""), "aria-hidden": "true", children: [
4601
4654
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(FreighterHull, { units: 3, empty: true }),
4602
4655
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-stuck-code", children: [
4603
4656
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
4604
4657
  `{ }`
4605
4658
  ] }),
4606
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: "\u7F16\u7A0B\u7B49\u5F85\u4E2D" }),
4659
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: waiting ? "\u7B49\u5F85\u786E\u8BA4" : "\u7F16\u7A0B\u7B49\u5F85\u4E2D" }),
4607
4660
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("small", { children: truncate(props.task && props.task.title || "\u5DE5\u5177\u6682\u65E0\u65B0\u54CD\u5E94", 28) })
4608
4661
  ] });
4609
4662
  }
@@ -4725,6 +4778,56 @@ function AnimationOverlay(props) {
4725
4778
  }
4726
4779
  prevActiveRef.current = st2.active.slice();
4727
4780
  }, [snap.status]);
4781
+ const remindedApprovalsRef = (0, import_react8.useRef)(/* @__PURE__ */ new Map());
4782
+ (0, import_react8.useEffect)(() => {
4783
+ const st2 = snap.status;
4784
+ if (!st2 || !st2.active) return;
4785
+ const cfg2 = st2.config || {};
4786
+ const activeIds = new Set(st2.active.map((x) => x.sessionId));
4787
+ for (const [sid, seen] of remindedApprovalsRef.current) {
4788
+ if (!activeIds.has(sid)) remindedApprovalsRef.current.delete(sid);
4789
+ }
4790
+ for (const task of st2.active) {
4791
+ const approvals = Array.isArray(task.approvals) ? task.approvals : [];
4792
+ if (approvals.length === 0) continue;
4793
+ let seen = remindedApprovalsRef.current.get(task.sessionId);
4794
+ if (!seen) {
4795
+ seen = /* @__PURE__ */ new Set();
4796
+ remindedApprovalsRef.current.set(task.sessionId, seen);
4797
+ }
4798
+ const fresh = approvals.filter((a) => a && !seen.has(a.id));
4799
+ if (fresh.length === 0) continue;
4800
+ for (const a of fresh) seen.add(a.id);
4801
+ if (!cfg2.notifyEnabled || cfg2.notifyOnConfirm === false) continue;
4802
+ const toolName = fresh[0].toolName || "";
4803
+ const scene = toolLabel(toolName);
4804
+ const lines = [
4805
+ "\u4EFB\u52A1\uFF1A" + (task.title || "(\u65E0\u6807\u9898)"),
4806
+ "\u5DE5\u5177\uFF1A" + (toolName || "\u672A\u77E5") + (scene ? "\uFF08" + scene + "\uFF09" : "")
4807
+ ];
4808
+ if (fresh[0].reason) lines.push("\u8BF4\u660E\uFF1A" + truncate(fresh[0].reason, 140));
4809
+ lines.push(fresh.length > 1 ? "\u5171 " + fresh.length + " \u9879\u7B49\u5F85\u4F60\u7684\u786E\u8BA4" : "\u8BF7\u5728\u4F1A\u8BDD\u91CC\u786E\u8BA4\u540E\u7EE7\u7EED");
4810
+ const toast = {
4811
+ id: Date.now() + Math.random(),
4812
+ kind: "confirm",
4813
+ title: "\u4EFB\u52A1\u9700\u8981\u786E\u8BA4",
4814
+ body: lines.join("\n"),
4815
+ // 需确认常驻到用户处理(notifyStayMs=0 同款语义),关掉开关的间隙也不会自动消失
4816
+ stayMs: 0
4817
+ };
4818
+ setToasts((prev) => prev.concat([toast]).slice(-4));
4819
+ if (cfg2.soundNotify !== false) playAskSound(cfg2.soundEffect);
4820
+ if (cfg2.systemNotify && typeof document !== "undefined" && document.hidden && typeof Notification !== "undefined" && Notification.permission === "granted") {
4821
+ try {
4822
+ new Notification("dsh \u4EFB\u52A1\u9700\u8981\u786E\u8BA4", {
4823
+ body: (task.title || "(\u65E0\u6807\u9898)") + " \xB7 " + (toolName || "\u5DE5\u5177") + " \u7B49\u5F85\u786E\u8BA4",
4824
+ tag: "dsh-dock-approval-" + task.sessionId
4825
+ });
4826
+ } catch {
4827
+ }
4828
+ }
4829
+ }
4830
+ }, [snap.status]);
4728
4831
  const handleTaskEnd = (task, record, cfg2) => {
4729
4832
  const reason = record && record.endReason || "";
4730
4833
  const success = isSuccessReason(reason);
@@ -4795,6 +4898,18 @@ function AnimationOverlay(props) {
4795
4898
  const animOn = !!(cfg && cfg.animationEnabled && active.length > 0);
4796
4899
  const mode = cfg && cfg.effectMode ? cfg.effectMode : "flow";
4797
4900
  const phase = active.length > 0 ? active.reduce((best, x) => !best || (x.phaseAt || 0) > (best.phaseAt || 0) ? x : best, null).phase : "think";
4901
+ const waitingTask = active.find((x) => Array.isArray(x.approvals) && x.approvals.length > 0) || null;
4902
+ const sessionTitleRef = (0, import_react8.useRef)({ at: 0, title: "" });
4903
+ const currentTitle = (0, import_react8.useMemo)(() => {
4904
+ const c = sessionTitleRef.current;
4905
+ if (typeof window === "undefined") return "";
4906
+ if (Date.now() - c.at < 1e3) return c.title;
4907
+ c.at = Date.now();
4908
+ c.title = currentSessionTitle();
4909
+ return c.title;
4910
+ }, [snap.status]);
4911
+ const onScreenTasks = (0, import_react8.useMemo)(() => active.filter((x) => taskOnScreen(x, currentTitle)), [active, currentTitle]);
4912
+ const waitingTaskOnScreen = onScreenTasks.find((x) => Array.isArray(x.approvals) && x.approvals.length > 0) || null;
4798
4913
  useTicker(ctx, animOn);
4799
4914
  const now = Date.now();
4800
4915
  const elapsed = active.length > 0 ? fmtClock(now - Math.min(...active.map((x) => x.startTime || now))) : "";
@@ -4828,7 +4943,7 @@ function AnimationOverlay(props) {
4828
4943
  const spaceModeOn = !!(cfg && cfg.animationEnabled && mode === "space" && !panelOpen);
4829
4944
  const spaceDocks = useSpaceDocks(spaceModeOn);
4830
4945
  const spaceGalaxies = spaceModeOn && spaceDocks ? spaceGalaxyLayout() : null;
4831
- const stuckTask = active.find((task) => task.phase === "code" && now - (task.lastActivityAt || task.phaseAt || now) >= 18e3) || null;
4946
+ const stuckTask = onScreenTasks.find((task) => task.phase === "code" && now - (task.lastActivityAt || task.phaseAt || now) >= 18e3) || null;
4832
4947
  const robotScaleFromConfig = Math.max(0.85, Math.min(2.2, Number(cfg && cfg.robotScale) || 1.35));
4833
4948
  const speedStyle = { "--dkan-speed": Number(speed).toFixed(2) };
4834
4949
  const saveRobotScale = (0, import_react8.useCallback)((robotScale) => {
@@ -4943,7 +5058,7 @@ function AnimationOverlay(props) {
4943
5058
  ambientOn && mode === "flow" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-line", style: speedStyle, "aria-hidden": "true" }) : null,
4944
5059
  ambientOn && AMBIENT_EFFECT_MODES.has(mode) && (mode !== "space" || spaceGalaxies) ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AmbientLayer, { mode, phase, speed: Number(speed).toFixed(2), tasks: active, galaxies: spaceGalaxies }) : null,
4945
5060
  spaceModeOn && spaceDocks && active.length === 0 && deliveries.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ReadyFreighter, { dock: spaceDocks.ready }) : null,
4946
- spaceModeOn && stuckTask ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ProgrammingStuck, { task: stuckTask }) : null,
5061
+ spaceModeOn && stuckTask ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ProgrammingStuck, { task: stuckTask, waiting: !!(stuckTask.approvals && stuckTask.approvals.length) }) : null,
4947
5062
  !panelOpen ? departures.map((departure) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MissionDeparture, { departure }, departure.id)) : null,
4948
5063
  ambientOn && mode === "orbit" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-orbit", style: speedStyle, "aria-hidden": "true" }) : null,
4949
5064
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BurstLayer, { bursts }),
@@ -4953,8 +5068,8 @@ function AnimationOverlay(props) {
4953
5068
  className: "dkan-botcard",
4954
5069
  role: "button",
4955
5070
  tabIndex: 0,
4956
- style: botCardStyle,
4957
- title: active.length + " \u4E2A\u4EFB\u52A1 \xB7 " + phaseLabel(phase) + " \xB7 \u70B9\u51FB\u67E5\u770B\u4EFB\u52A1\u52A8\u753B\u9875 \xB7 \u53EF\u62D6\u52A8\u5230\u4EFB\u610F\u4F4D\u7F6E",
5071
+ style: Object.assign({}, botCardStyle, waitingTask ? { "--dkan-phase": "#b45309" } : null),
5072
+ title: active.length + " \u4E2A\u4EFB\u52A1 \xB7 " + (waitingTask ? "\u7B49\u5F85\u786E\u8BA4" : phaseLabel(phase)) + " \xB7 \u70B9\u51FB\u67E5\u770B\u4EFB\u52A1\u52A8\u753B\u9875 \xB7 \u53EF\u62D6\u52A8\u5230\u4EFB\u610F\u4F4D\u7F6E",
4958
5073
  onPointerDown: onBotPointerDown,
4959
5074
  onPointerMove: onBotPointerMove,
4960
5075
  onPointerUp: onBotPointerUp,
@@ -4973,7 +5088,7 @@ function AnimationOverlay(props) {
4973
5088
  " \u4E2A\u4EFB\u52A1",
4974
5089
  elapsed ? " \xB7 " + elapsed : "",
4975
5090
  " \xB7 ",
4976
- phaseLabel(phase)
5091
+ waitingTask ? "\u7B49\u5F85\u786E\u8BA4" : phaseLabel(phase)
4977
5092
  ] }),
4978
5093
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4979
5094
  "button",
@@ -5004,8 +5119,8 @@ function AnimationOverlay(props) {
5004
5119
  {
5005
5120
  type: "button",
5006
5121
  className: "dkan-badge" + (mode === "breathe" ? " dkan-badge-breathe" : ""),
5007
- style: Object.assign({}, speedStyle, { "--dkan-phase": phaseColor(phase) }),
5008
- title: active.length + " \u4E2A\u4EFB\u52A1\u8FDB\u884C\u4E2D \xB7 " + phaseLabel(phase) + " \xB7 \u70B9\u51FB\u67E5\u770B\u4EFB\u52A1\u52A8\u753B\u9875",
5122
+ style: Object.assign({}, speedStyle, { "--dkan-phase": phaseColor(waitingTask ? "code" : phase) }),
5123
+ title: active.length + " \u4E2A\u4EFB\u52A1\u8FDB\u884C\u4E2D \xB7 " + (waitingTask ? "\u7B49\u5F85\u786E\u8BA4" : phaseLabel(phase)) + " \xB7 \u70B9\u51FB\u67E5\u770B\u4EFB\u52A1\u52A8\u753B\u9875",
5009
5124
  onClick: () => openPanel("animation"),
5010
5125
  children: [
5011
5126
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-dotwrap", children: [
@@ -5018,7 +5133,7 @@ function AnimationOverlay(props) {
5018
5133
  " \u4E2A\u4EFB\u52A1",
5019
5134
  elapsed ? " \xB7 " + elapsed : "",
5020
5135
  " \xB7 ",
5021
- phaseLabel(phase)
5136
+ waitingTask ? "\u7B49\u5F85\u786E\u8BA4" : phaseLabel(phase)
5022
5137
  ] })
5023
5138
  ]
5024
5139
  }
@@ -5093,10 +5208,11 @@ function ModePreview({ id }) {
5093
5208
  function TaskRow(props) {
5094
5209
  const t = props.t;
5095
5210
  const info = endInfo(t.endReason);
5211
+ const waiting = !props.done && Array.isArray(t.approvals) && t.approvals.length > 0;
5096
5212
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-task", children: [
5097
5213
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-task-head", children: [
5098
5214
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-task-title", title: t.title, children: t.title || "(\u65E0\u6807\u9898)" }),
5099
- props.done ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-tag " + info.cls, children: info.label }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-tag on", children: phaseLabel(t.phase) })
5215
+ props.done ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-tag " + info.cls, children: info.label }) : waiting ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-tag warn", children: "\u7B49\u5F85\u786E\u8BA4" }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-tag on", children: phaseLabel(t.phase) })
5100
5216
  ] }),
5101
5217
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-task-meta", children: [
5102
5218
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: (t.models && t.models.length ? t.models.join(", ") : "\u672A\u77E5") + (t.provider ? "\uFF08" + t.provider + "\uFF09" : "") }),
@@ -5105,6 +5221,7 @@ function TaskRow(props) {
5105
5221
  t.totalTokens ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u21A7" + fmtCompact2(t.inputTokens) + " \u21A5" + fmtCompact2(t.outputTokens) }) : null,
5106
5222
  props.done && t.endTime ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: fmtTime2(t.endTime) }) : null
5107
5223
  ] }),
5224
+ waiting ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-task-err", children: t.approvals.map((a, i) => (a && a.toolName ? a.toolName : "\u672A\u77E5\u5DE5\u5177") + (a && a.reason ? "\uFF1A" + truncate(a.reason, 80) : "")).join("\uFF1B") }) : null,
5108
5225
  props.done && t.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-task-err", children: truncate(t.errorMessage, 120) }) : null
5109
5226
  ] });
5110
5227
  }
@@ -5232,6 +5349,7 @@ function AnimationView(props) {
5232
5349
  if (!cfg) {
5233
5350
  rows.push(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note", children: snap.error ? "\u72B6\u6001\u4E0D\u53EF\u7528\uFF1A" + snap.error : snap.loading ? "\u6B63\u5728\u62C9\u53D6\u4EFB\u52A1\u72B6\u6001\u2026" : "\u7B49\u5F85\u4EFB\u52A1\u72B6\u6001" }, "load"));
5234
5351
  } else {
5352
+ const waitingCount2 = active.reduce((n, t) => n + (Array.isArray(t.approvals) ? t.approvals.length : 0), 0);
5235
5353
  rows.push(
5236
5354
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec", children: [
5237
5355
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec-head", children: [
@@ -5351,6 +5469,19 @@ function AnimationView(props) {
5351
5469
  ),
5352
5470
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-sub", children: "\u51FA\u9519 / \u4E2D\u6B62 / \u8FBE\u8F93\u51FA\u4E0A\u9650\u65F6\u901A\u77E5" })
5353
5471
  ] }),
5472
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-row", children: [
5473
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-label", children: "\u9700\u786E\u8BA4\u63D0\u9192" }),
5474
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
5475
+ "button",
5476
+ {
5477
+ type: "button",
5478
+ className: "dkm-miniswitch" + (cfg.notifyOnConfirm !== false ? " on" : ""),
5479
+ onClick: () => patch({ notifyOnConfirm: cfg.notifyOnConfirm === false }),
5480
+ children: cfg.notifyOnConfirm !== false ? "\u5F00" : "\u5173"
5481
+ }
5482
+ ),
5483
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-sub", children: "\u5DE5\u5177\u7B49\u5F85\u4F60\u6279\u51C6\u65F6\u5F39\u5361\u7247\u5E76\u54CD\u786E\u8BA4\u97F3\uFF08\u5E38\u9A7B\u4E0D\u81EA\u52A8\u6D88\u5931\uFF09" })
5484
+ ] }),
5354
5485
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-row", children: [
5355
5486
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-label", children: "\u505C\u7559\u65F6\u957F" }),
5356
5487
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
@@ -5393,7 +5524,7 @@ function AnimationView(props) {
5393
5524
  children: cfg.soundNotify !== false ? "\u5F00" : "\u5173"
5394
5525
  }
5395
5526
  ),
5396
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-sub", children: "\u4EFB\u52A1\u7ED3\u675F\u65F6\u64AD\u653E\uFF08\u8BD5\u542C\u4E3A\u5148\u64AD\u5B8C\u6210\u97F3\u3001\u540E\u64AD\u5F02\u5E38\u97F3\uFF09" })
5527
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-sub", children: "\u4EFB\u52A1\u7ED3\u675F/\u9700\u786E\u8BA4\u65F6\u64AD\u653E\uFF08\u8BD5\u542C\u4E3A\u5148\u64AD\u5B8C\u6210\u97F3\u3001\u540E\u64AD\u5F02\u5E38\u97F3\uFF09" })
5397
5528
  ] }),
5398
5529
  cfg.soundNotify !== false ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-sounds", children: Object.keys(SOUND_LIBRARY).map((key) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
5399
5530
  "button",
@@ -5558,7 +5689,7 @@ function AnimationView(props) {
5558
5689
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec", children: [
5559
5690
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec-head", children: [
5560
5691
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-title", children: "\u8FD0\u884C\u72B6\u6001" }),
5561
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-sub", children: snap.error ? "\u72B6\u6001\u62C9\u53D6\u5931\u8D25\uFF1A" + snap.error : active.length > 0 ? active.length + " \u4E2A\u4EFB\u52A1\u8FDB\u884C\u4E2D" : recent.length > 0 ? "\u7A7A\u95F2 \xB7 \u663E\u793A\u6700\u8FD1\u5B8C\u6210" : "\u7A7A\u95F2 \xB7 \u6682\u65E0\u4EFB\u52A1\u8BB0\u5F55" }),
5692
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-sub", children: snap.error ? "\u72B6\u6001\u62C9\u53D6\u5931\u8D25\uFF1A" + snap.error : waitingCount > 0 ? waitingCount + " \u9879\u7B49\u5F85\u786E\u8BA4 \xB7 " + active.length + " \u4E2A\u4EFB\u52A1\u8FDB\u884C\u4E2D" : active.length > 0 ? active.length + " \u4E2A\u4EFB\u52A1\u8FDB\u884C\u4E2D" : recent.length > 0 ? "\u7A7A\u95F2 \xB7 \u663E\u793A\u6700\u8FD1\u5B8C\u6210" : "\u7A7A\u95F2 \xB7 \u6682\u65E0\u4EFB\u52A1\u8BB0\u5F55" }),
5562
5693
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "dkan-refresh", onClick: () => animationStore.refresh(), children: snap.loading ? "\u5237\u65B0\u4E2D\u2026" : "\u5237\u65B0" })
5563
5694
  ] }),
5564
5695
  active.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-tasks", children: active.map((t) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(TaskRow, { t }, t.sessionId)) }) : null,
@@ -5630,7 +5761,9 @@ var css2 = [
5630
5761
  ".dkan-delivery-label{position:absolute;left:21px;top:58px;display:flex;align-items:baseline;gap:6px;padding:4px 8px;border:1px solid color-mix(in srgb,#93c5fd 30%,var(--dsw-alias-border-l1));border-radius:999px;background:color-mix(in srgb,var(--dsw-alias-bg-layer-2) 82%,transparent);backdrop-filter:blur(10px);color:var(--dsw-alias-label-secondary);font:10px/1.2 var(--ds-font-family,system-ui,sans-serif);white-space:nowrap;}.dkan-delivery-label b{color:var(--dsw-alias-label-primary);font-weight:650}.dkan-delivery-label span{color:var(--dk-accent);}",
5631
5762
  "@media (max-width:1100px){.dkan-space-system,.dkan-space-runner{display:none}}",
5632
5763
  ".dkan-ready-freighter{position:fixed;width:210px;height:88px;z-index:9994;pointer-events:none;filter:drop-shadow(0 10px 14px rgb(0 0 0 / .18));}.dkan-ready-freighter>span:last-child{position:absolute;left:21px;top:58px;padding:4px 8px;border:1px solid color-mix(in srgb,#93c5fd 28%,var(--dsw-alias-border-l1));border-radius:999px;background:color-mix(in srgb,var(--dsw-alias-bg-layer-2) 80%,transparent);backdrop-filter:blur(10px);color:var(--dsw-alias-label-secondary);font:10px/1.2 var(--ds-font-family,system-ui,sans-serif);white-space:nowrap;}.dkan-departure{position:fixed;left:0;top:0;width:210px;height:88px;z-index:9994;pointer-events:none;will-change:transform,opacity;contain:layout paint style;isolation:isolate;animation:dkan-departure-flight var(--dkan-departure-duration,8600ms) cubic-bezier(.42,0,.85,.45) forwards;}@keyframes dkan-departure-flight{0%{opacity:0;transform:translate3d(var(--dkan-from-x),var(--dkan-from-y),0) scale(1) rotate(var(--dkan-flight-angle,0deg))}6%{opacity:1;transform:translate3d(var(--dkan-from-x),var(--dkan-from-y),0) scale(1) rotate(var(--dkan-flight-angle,0deg))}100%{opacity:0;transform:translate3d(var(--dkan-to-x),var(--dkan-to-y),0) scale(.24) rotate(var(--dkan-flight-angle,0deg))}}",
5633
- ".dkan-space-stuck{position:fixed;left:50%;top:50%;width:244px;height:160px;z-index:9993;pointer-events:none;transform:translate(-50%,-50%);border:1px solid color-mix(in srgb,#f59e0b 48%,var(--dsw-alias-border-l1));border-radius:20px;background:color-mix(in srgb,var(--dsw-alias-bg-layer-2) 88%,transparent);backdrop-filter:blur(16px);box-shadow:0 18px 54px rgb(0 0 0 / .28),0 0 30px color-mix(in srgb,#f59e0b 15%,transparent);}.dkan-space-stuck .dkan-freighter{left:37px;top:11px;transform:scale(.9);transform-origin:top left;}.dkan-stuck-code{position:absolute;left:17px;right:17px;top:60px;height:36px;border-radius:7px;background:linear-gradient(90deg,color-mix(in srgb,#f59e0b 18%,transparent),transparent);color:var(--dk-warn);font:700 14px/36px var(--ds-font-family-code,monospace);letter-spacing:.12em;text-align:center;overflow:hidden;}.dkan-stuck-code::after{content:'';position:absolute;inset:0;background:linear-gradient(90deg,transparent,color-mix(in srgb,#fef3c7 70%,transparent),transparent);transform:translateX(-110%);animation:dkan-stuck-scan 1.25s linear infinite;}.dkan-stuck-code i{display:inline-block;width:7px;height:7px;margin-right:8px;border-radius:50%;background:#f59e0b;box-shadow:0 0 9px #f59e0b;animation:dkan-stuck-pulse .8s ease-in-out infinite alternate;}.dkan-space-stuck strong{position:absolute;left:0;right:0;top:108px;color:var(--dsw-alias-label-primary);font:650 13px/1.2 var(--ds-font-family,system-ui,sans-serif);text-align:center;}.dkan-space-stuck small{position:absolute;left:18px;right:18px;top:128px;color:var(--dsw-alias-label-secondary);font:11px/1.25 var(--ds-font-family,system-ui,sans-serif);text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}@keyframes dkan-stuck-scan{to{transform:translateX(110%)}}@keyframes dkan-stuck-pulse{to{transform:scale(.55);opacity:.45}}",
5764
+ ".dkan-space-stuck{position:fixed;right:20px;top:88px;width:244px;height:160px;z-index:9993;pointer-events:none;border:1px solid color-mix(in srgb,#f59e0b 48%,var(--dsw-alias-border-l1));border-radius:20px;background:color-mix(in srgb,var(--dsw-alias-bg-layer-2) 88%,transparent);backdrop-filter:blur(16px);box-shadow:0 18px 54px rgb(0 0 0 / .28),0 0 30px color-mix(in srgb,#f59e0b 15%,transparent);}.dkan-space-stuck .dkan-freighter{left:37px;top:11px;transform:scale(.9);transform-origin:top left;}.dkan-stuck-code{position:absolute;left:17px;right:17px;top:60px;height:36px;border-radius:7px;background:linear-gradient(90deg,color-mix(in srgb,#f59e0b 18%,transparent),transparent);color:var(--dk-warn);font:700 14px/36px var(--ds-font-family-code,monospace);letter-spacing:.12em;text-align:center;overflow:hidden;}.dkan-stuck-code::after{content:'';position:absolute;inset:0;background:linear-gradient(90deg,transparent,color-mix(in srgb,#fef3c7 70%,transparent),transparent);transform:translateX(-110%);animation:dkan-stuck-scan 1.25s linear infinite;}.dkan-stuck-code i{display:inline-block;width:7px;height:7px;margin-right:8px;border-radius:50%;background:#f59e0b;box-shadow:0 0 9px #f59e0b;animation:dkan-stuck-pulse .8s ease-in-out infinite alternate;}.dkan-space-stuck strong{position:absolute;left:0;right:0;top:108px;color:var(--dsw-alias-label-primary);font:650 13px/1.2 var(--ds-font-family,system-ui,sans-serif);text-align:center;}.dkan-space-stuck small{position:absolute;left:18px;right:18px;top:128px;color:var(--dsw-alias-label-secondary);font:11px/1.25 var(--ds-font-family,system-ui,sans-serif);text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}@keyframes dkan-stuck-scan{to{transform:translateX(110%)}}@keyframes dkan-stuck-pulse{to{transform:scale(.55);opacity:.45}}",
5765
+ // 窄屏(手机/分屏)贴右会溢出:回落到水平居中、屏幕上方,避开正文重心
5766
+ "@media (max-width:760px){.dkan-space-stuck{right:50%;transform:translateX(50%);top:64px;}}",
5634
5767
  // 极光:顶部柔光带呼吸流动(加浓)
5635
5768
  ".dkan-aurora i{position:absolute;top:-40%;left:-20%;width:70%;height:80%;border-radius:50%;filter:blur(50px);opacity:.32;animation:dkan-aurora ease-in-out infinite alternate;}",
5636
5769
  ".dkan-aurora i:nth-child(1){background:#4d9fff;}",
@@ -5719,6 +5852,9 @@ var css2 = [
5719
5852
  ".dkan-toast-close{cursor:pointer;flex:none;border:none;background:transparent;color:var(--dsw-alias-label-tertiary);border-radius:6px;width:22px;height:22px;font-size:11px;line-height:1;display:inline-flex;align-items:center;justify-content:center;font-family:inherit;}",
5720
5853
  ".dkan-toast-close:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);}",
5721
5854
  ".dkan-toast-body{font-size:12px;color:var(--dsw-alias-label-secondary);line-height:1.7;white-space:pre-line;word-break:break-word;}",
5855
+ // 需确认卡片:琥珀描边 + 缓慢呼吸光晕,常驻提醒直到用户处理
5856
+ ".dkan-toast-confirm{border-color:color-mix(in srgb,var(--dk-warn) 55%,transparent);animation:dkan-toast-in .32s var(--ds-ease-in-out),dkan-confirm-glow 2.4s ease-in-out 0.4s infinite;}",
5857
+ "@keyframes dkan-confirm-glow{0%,100%{box-shadow:0 10px 36px rgb(0 0 0 / .22),0 0 0 0 color-mix(in srgb,var(--dk-warn) 30%,transparent)}50%{box-shadow:0 10px 36px rgb(0 0 0 / .22),0 0 14px 2px color-mix(in srgb,var(--dk-warn) 32%,transparent)}}",
5722
5858
  // 面板页布局
5723
5859
  ".dkan-root{display:flex;flex-direction:column;gap:10px;}",
5724
5860
  ".dkan-note{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.6;}",
@@ -9531,7 +9667,7 @@ var feature7 = {
9531
9667
  order: 135,
9532
9668
  accent: "#a78bfa",
9533
9669
  description: "\u4EFB\u52A1\u7B49\u5F85\u65F6\u53EF\u73A9\u7684\u5341\u6B3E\u5C0F\u6E38\u620F\uFF1A\u4E94\u5B50\u68CB\u3001\u4E2D\u56FD\u8C61\u68CB\uFF08\u4F60 vs AI\uFF09\u3001\u4FC4\u7F57\u65AF\u65B9\u5757\u3001\u63A8\u7BB1\u5B50\u3001\u8D2A\u5403\u86C7\u3001\u6253\u7816\u5757\u3001\u6781\u901F\u8D5B\u8F66\u3001\u5766\u514B\u5927\u6218\u3001\u661F\u9645\u8EB2\u907F\u3001\u53CD\u5E94\u5806\u70B9\u4EAE\u3002\u6D6E\u52A8\u7A97\u53E3\u8FD0\u884C\uFF08\u53EF\u62D6\u52A8\u3001\u53EF\u8C03\u5927\u5C0F\u3001\u53EF\u6700\u5927\u5316\u6700\u5C0F\u5316\uFF0C\u4E0D\u906E\u6321\u4F1A\u8BDD\uFF09\uFF0C\u5C4F\u5E55\u4FA7\u8FB9\u78C1\u5438\u5FEB\u6377\u5165\u53E3\u8D34\u5728\u5DE6\u4FA7\u8FB9\u680F\u53F3\u7F18\uFF08\u4E0D\u6321\u5DE5\u4F5C\u533A\u76EE\u5F55\uFF09\uFF0C\u53EF\u4E0A\u4E0B\u632A\u4F4D\u3001\u5DE6\u53F3\u6362\u8FB9\uFF1B\u5747\u652F\u6301\u952E\u76D8",
9534
- defaultEnabled: true,
9670
+ defaultEnabled: false,
9535
9671
  css: css3,
9536
9672
  View: GamesView,
9537
9673
  HomeStat: GamesHomeStat,
@@ -9837,6 +9973,112 @@ function RemoteCard() {
9837
9973
  function MobileRelayView() {
9838
9974
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(RemoteCard, {});
9839
9975
  }
9976
+ function MobileRelayOverlay() {
9977
+ (0, import_react19.useEffect)(() => {
9978
+ if (typeof window === "undefined" || typeof document === "undefined") return void 0;
9979
+ if (window.__dshDockMobileDrawer) return void 0;
9980
+ const mq = window.matchMedia ? window.matchMedia("(max-width:700px)") : null;
9981
+ if (!mq) return void 0;
9982
+ window.__dshDockMobileDrawer = "client";
9983
+ const narrow = () => mq.matches;
9984
+ const frameEl = () => document.querySelector('[class$="frame"]');
9985
+ const sidebarCollapsed = () => {
9986
+ const f = frameEl();
9987
+ return !!f && f.hasAttribute("data-sidebar-collapsed");
9988
+ };
9989
+ const dialogOpen = () => !!document.querySelector('[role="dialog"][class*="panel"]');
9990
+ const collapse = () => {
9991
+ const b = document.querySelector('button[aria-label="\u6536\u8D77\u4FA7\u8FB9\u680F"],button[aria-label="Collapse sidebar"]');
9992
+ if (b) b.click();
9993
+ };
9994
+ const expand = () => {
9995
+ const b = document.querySelector('button[aria-label="\u6253\u5F00\u4FA7\u8FB9\u680F"],button[aria-label="Open sidebar"]');
9996
+ if (b) b.click();
9997
+ };
9998
+ const closeDetails = () => {
9999
+ const d = document.querySelector('[class*="detailsCol"]');
10000
+ if (!d || !d.getBoundingClientRect().width) return;
10001
+ const c = d.querySelector('button[aria-label="\u5173\u95ED\u8BE6\u60C5"]');
10002
+ if (c) c.click();
10003
+ };
10004
+ const fab = document.createElement("button");
10005
+ fab.type = "button";
10006
+ fab.className = "dsh-mobile-drawer-btn";
10007
+ fab.setAttribute("aria-label", "\u6253\u5F00\u4F1A\u8BDD\u5217\u8868");
10008
+ fab.innerHTML = '<svg viewBox="0 0 24 24"><path d="M4 7h16M4 12h16M4 17h10"/></svg>';
10009
+ fab.addEventListener("click", expand);
10010
+ const scrim = document.createElement("div");
10011
+ scrim.className = "dsh-mobile-scrim";
10012
+ document.body.appendChild(fab);
10013
+ document.body.appendChild(scrim);
10014
+ const place = () => {
10015
+ const vh = window.innerHeight;
10016
+ let top = null;
10017
+ const g = document.querySelector(".dgfab");
10018
+ if (g && !g.classList.contains("dgfab-hide") && g.getBoundingClientRect) {
10019
+ const r = g.getBoundingClientRect();
10020
+ if (r && r.height > 0 && r.top > 0) {
10021
+ top = r.top - fab.offsetHeight - 8;
10022
+ if (top < 64) top = r.bottom + 8;
10023
+ if (top + fab.offsetHeight > vh - 16) top = null;
10024
+ }
10025
+ }
10026
+ if (top == null) top = Math.round(vh * 0.38);
10027
+ fab.style.top = top + "px";
10028
+ };
10029
+ const sync = () => {
10030
+ const on = narrow() && !!frameEl() && !dialogOpen();
10031
+ const collapsed = sidebarCollapsed();
10032
+ const showFab = on && collapsed;
10033
+ fab.style.display = showFab ? "" : "none";
10034
+ if (showFab) place();
10035
+ scrim.style.display = on && !collapsed ? "" : "none";
10036
+ };
10037
+ sync();
10038
+ const observer = typeof MutationObserver !== "undefined" ? new MutationObserver(sync) : null;
10039
+ if (observer) observer.observe(document.documentElement, { attributes: true, attributeFilter: ["data-sidebar-collapsed"], subtree: true });
10040
+ const timer = setInterval(sync, 1500);
10041
+ const onMq = () => sync();
10042
+ if (mq.addEventListener) mq.addEventListener("change", onMq);
10043
+ else if (mq.addListener) mq.addListener(onMq);
10044
+ window.addEventListener("resize", place);
10045
+ const onClick = (e) => {
10046
+ if (!narrow()) return;
10047
+ const t = e.target;
10048
+ if (!t || !t.closest) return;
10049
+ if (t.closest(".dsh-mobile-drawer-btn")) return;
10050
+ const expanded = !!document.querySelector('button[aria-label="\u6536\u8D77\u4FA7\u8FB9\u680F"],button[aria-label="Collapse sidebar"]');
10051
+ const col = document.querySelector('[class*="sidebarCol"]');
10052
+ const inSidebar = col && col.contains(t);
10053
+ if (!expanded && !inSidebar) return;
10054
+ if (inSidebar) {
10055
+ const row = t.closest('[role="treeitem"]');
10056
+ const leaf = row && !row.querySelector('[role="treeitem"]') && row.closest('[role="tree"]');
10057
+ const fresh = t.closest('[class*="newSession"]');
10058
+ if (leaf || fresh) setTimeout(() => {
10059
+ collapse();
10060
+ closeDetails();
10061
+ }, 300);
10062
+ return;
10063
+ }
10064
+ if (t.closest('[role="dialog"],[class*="dockm"],[class*="dgfab"],[class*="dgwin"],[class*="dgame"],[class*="detailsCol"]')) return;
10065
+ collapse();
10066
+ };
10067
+ document.addEventListener("click", onClick, true);
10068
+ return () => {
10069
+ document.removeEventListener("click", onClick, true);
10070
+ if (observer) observer.disconnect();
10071
+ clearInterval(timer);
10072
+ if (mq.removeEventListener) mq.removeEventListener("change", onMq);
10073
+ else if (mq.removeListener) mq.removeListener(onMq);
10074
+ window.removeEventListener("resize", place);
10075
+ fab.remove();
10076
+ scrim.remove();
10077
+ if (window.__dshDockMobileDrawer === "client") delete window.__dshDockMobileDrawer;
10078
+ };
10079
+ }, []);
10080
+ return null;
10081
+ }
9840
10082
  function MobileRelayHomeStat() {
9841
10083
  const [summary, setSummary] = (0, import_react19.useState)("\u672A\u5F00\u542F\uFF0C\u5F00\u542F\u540E\u53EF\u8FDC\u7A0B\u767B\u5F55");
9842
10084
  (0, import_react19.useEffect)(() => {
@@ -9853,15 +10095,19 @@ var feature8 = {
9853
10095
  order: 80,
9854
10096
  accent: "#38bdf8",
9855
10097
  description: "\u8D26\u53F7\u5BC6\u7801\u767B\u5F55\u7684\u8FDC\u7A0B\u5165\u53E3\uFF1A\u6240\u6709\u8BBE\u5907\u8BBF\u95EE\u540C\u4E00\u4E2A DSH\uFF0C\u4EFB\u52A1\u8FDB\u5EA6\u5B9E\u65F6\u4E00\u81F4",
9856
- defaultEnabled: true,
10098
+ defaultEnabled: false,
9857
10099
  css: `
9858
- .dmr{--dmr-accent:var(--dk-accent,#2f6fed);--dmr-accent-soft:color-mix(in srgb,var(--dmr-accent) 13%,transparent);display:flex;flex-direction:column;gap:16px;max-width:720px;color:var(--dsw-alias-label-primary);font-size:13px;line-height:1.5}.dmr h3,.dmr h4,.dmr p{margin:0}.dmr h3{font-size:17px;line-height:1.25;letter-spacing:-.01em}.dmr h4{font-size:13px}.dmr-hero,.dmr-status-head{display:flex;align-items:flex-start;gap:12px}.dmr-hero>div,.dmr-status-head>div{min-width:0;display:flex;flex-direction:column;gap:4px}.dmr-hero p,.dmr-status-head p,.dmr-field small,.dmr-share small,.dmr-overview-card small,.dmr-task small,.dmr-note p{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.55}.dmr-hero-icon{width:42px;height:42px;display:inline-flex;align-items:center;justify-content:center;flex:none;border-radius:14px;background:var(--dmr-accent-soft);color:var(--dmr-accent);border:1px solid color-mix(in srgb,var(--dmr-accent) 35%,var(--dsw-alias-border-l1))}.dmr-steps{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;margin:0;padding:0;list-style:none}.dmr-steps li{display:flex;gap:9px;padding:11px;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:12px}.dmr-steps li>span{width:21px;height:21px;display:inline-flex;align-items:center;justify-content:center;flex:none;border-radius:50%;font-size:11px;font-weight:700;color:var(--dmr-accent);background:var(--dmr-accent-soft)}.dmr-steps div{display:flex;flex-direction:column;gap:3px;min-width:0}.dmr-steps strong{font-size:12px}.dmr-steps small{font-size:11px;color:var(--dsw-alias-label-secondary);line-height:1.45}.dmr-field{display:flex;flex-direction:column;gap:6px;font-weight:600}.dmr-field input,.dmr-field select,.dmr-note textarea{box-sizing:border-box;width:100%;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border-radius:10px;padding:10px 12px;min-height:44px;font:inherit;outline:none;transition:border-color .18s ease,box-shadow .18s ease}.dmr-field input:focus,.dmr-field select:focus,.dmr-note textarea:focus{border-color:var(--dmr-accent);box-shadow:0 0 0 3px var(--dmr-accent-soft)}.dmr-field small{font-weight:400}.dmr-network-grid{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(150px,.6fr);gap:12px}.dmr-security{padding:12px 13px;border:1px solid color-mix(in srgb,var(--dk-warn) 48%,var(--dsw-alias-border-l1));border-radius:12px;background:color-mix(in srgb,var(--dk-warn) 9%,transparent)}.dmr-security strong{display:block;margin-bottom:4px;color:var(--dk-warn);font-size:12px}.dmr-security p{font-size:12px;color:var(--dsw-alias-label-secondary);line-height:1.55}.dmr-primary,.dmr-secondary,.dmr-text-button,.dmr-icon-button{font:inherit;touch-action:manipulation;cursor:pointer;transition:transform .15s ease,background .18s ease,border-color .18s ease,opacity .18s ease}.dmr-primary,.dmr-secondary{min-height:44px;display:inline-flex;align-items:center;justify-content:center;gap:8px;border-radius:10px;padding:9px 13px;font-weight:600}.dmr-primary{align-self:flex-start;border:1px solid var(--dmr-accent);background:var(--dmr-accent);color:#fff}.dmr-primary:hover{filter:brightness(1.05)}.dmr-secondary{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary)}.dmr-secondary:hover{border-color:var(--dmr-accent);background:var(--dmr-accent-soft)}.dmr-primary:active,.dmr-secondary:active,.dmr-icon-button:active{transform:scale(.98)}.dmr-primary:disabled,.dmr-secondary:disabled,.dmr-text-button:disabled,.dmr-icon-button:disabled{cursor:not-allowed;opacity:.5}.dmr-message{display:flex;align-items:flex-start;gap:7px;padding:10px 12px;border-radius:10px;font-size:12px}.dmr-message.success{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 10%,transparent)}.dmr-message.error{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent)}.dmr-status-head{justify-content:space-between}.dmr-eyebrow{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:600;color:var(--dmr-accent)}.dmr-eyebrow i{width:7px;height:7px;border-radius:50%;background:currentColor;box-shadow:0 0 0 4px var(--dmr-accent-soft)}.dmr-icon-button{display:inline-flex;align-items:center;justify-content:center;flex:none;width:44px;height:44px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:transparent;color:var(--dsw-alias-label-secondary)}.dmr-icon-button:hover{color:var(--dsw-alias-state-error-primary);border-color:currentColor}.dmr-share{display:flex;flex-direction:column;gap:9px;padding:13px;border:1px solid color-mix(in srgb,var(--dmr-accent) 32%,var(--dsw-alias-border-l1));border-radius:13px;background:var(--dmr-accent-soft)}.dmr-share-layout{display:grid;grid-template-columns:196px minmax(0,1fr);gap:16px;align-items:center}.dmr-qr-card{box-sizing:border-box;display:flex;flex-direction:column;align-items:center;gap:5px;padding:10px;border-radius:12px;background:#fff;color:#111827;text-align:center}.dmr-qr-card img{display:block;width:176px;height:176px;max-width:100%;object-fit:contain}.dmr-qr-card strong{font-size:12px}.dmr-qr-card small{color:#4b5563;font-size:10px}.dmr-qr-loading{display:grid;place-items:center;width:176px;height:176px;color:#64748b;font-size:12px}.dmr-share-detail{min-width:0;display:flex;flex-direction:column;gap:10px}.dmr-share-detail>div:first-child{display:flex;flex-direction:column;gap:4px}.dmr-link{padding:10px 11px;border-radius:8px;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);font:12px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;word-break:break-all;color:var(--dsw-alias-label-secondary)}.dmr-share-actions{display:flex;gap:8px;flex-wrap:wrap}.dmr-share-actions .dmr-primary{align-self:auto}.dmr-overview{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.dmr-overview-card{display:flex;flex-direction:column;gap:3px;padding:12px;border:1px solid var(--dsw-alias-border-l1);border-radius:12px;background:var(--dsw-alias-bg-layer-1)}.dmr-overview-card>span{font-size:11px;color:var(--dsw-alias-label-tertiary)}.dmr-overview-card strong{font-size:16px;letter-spacing:-.01em}.dmr-section{display:flex;flex-direction:column;gap:9px}.dmr-section-head{display:flex;align-items:center;justify-content:space-between;gap:10px}.dmr-section-head small{font-size:11px;color:var(--dsw-alias-label-tertiary)}.dmr-text-button{border:0;background:transparent;color:var(--dmr-accent);padding:8px;min-height:36px;font-weight:600}.dmr-task-list{display:flex;flex-direction:column;gap:8px}.dmr-task{display:flex;align-items:flex-start;gap:9px;padding:10px 11px;border:1px solid var(--dsw-alias-border-l1);border-radius:10px;background:var(--dsw-alias-bg-layer-1)}.dmr-task>div{display:flex;min-width:0;flex:1;flex-direction:column;gap:2px}.dmr-task strong{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dmr-phase{flex:none;border-radius:999px;padding:3px 8px;font-size:11px;background:var(--dmr-accent-soft);color:var(--dmr-accent)}.dmr-phase.write{color:var(--dsw-alias-state-success-primary)}.dmr-phase.code{color:var(--dk-warn)}.dmr-phase.search{color:#0d9488}.dmr-empty{padding:18px 12px;text-align:center;border:1px dashed var(--dsw-alias-border-l2);border-radius:10px;color:var(--dsw-alias-label-secondary);font-size:12px}.dmr-note{display:flex;flex-direction:column;gap:9px;padding-top:2px}.dmr-note blockquote{margin:0;padding:10px 12px;border-left:3px solid var(--dmr-accent);border-radius:0 9px 9px 0;background:var(--dmr-accent-soft);white-space:pre-wrap;font-size:12px}.dmr-note textarea{min-height:88px;resize:vertical;line-height:1.5}.dmr-note .dmr-secondary{align-self:flex-start}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@media (max-width:680px){.dmr{gap:14px;font-size:14px}.dmr h3{font-size:18px}.dmr-steps{grid-template-columns:1fr;gap:8px}.dmr-steps li{padding:10px}.dmr-steps small,.dmr-hero p,.dmr-status-head p,.dmr-field small,.dmr-share small,.dmr-overview-card small,.dmr-task small,.dmr-note p{font-size:12px}.dmr-network-grid{grid-template-columns:1fr;gap:10px}.dmr-field input,.dmr-field select{font-size:16px}.dmr-primary,.dmr-secondary{width:100%;font-size:14px}.dmr-share-layout{grid-template-columns:1fr;gap:12px}.dmr-qr-card{width:min(240px,100%);margin:0 auto}.dmr-qr-card img,.dmr-qr-loading{width:210px;height:210px}.dmr-share-actions{flex-direction:column}.dmr-share-actions .dmr-primary{width:100%}.dmr-overview{gap:8px}.dmr-overview-card{padding:11px}.dmr-status-head{gap:8px}.dmr-link{font-size:11px}.dmr-note textarea{font-size:16px;min-height:104px}.dmr-note .dmr-secondary{align-self:stretch}.dmr-compact .dmr-hero-icon{width:40px;height:40px;border-radius:13px}}@media (prefers-reduced-motion:reduce){.dmr-primary,.dmr-secondary,.dmr-text-button,.dmr-icon-button,.dmr-field input,.dmr-field select,.dmr-note textarea{transition:none}}.dmr-lan{flex:none;margin-top:6px;padding-top:16px;border-top:1px solid var(--dsw-alias-border-l1)}.dmr-lan-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.dmr-lan-title{min-width:0;display:flex;flex-direction:column;gap:4px}.dmr-lan-title p{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.55}.dmr-lan-badge{flex:none;display:inline-flex;align-items:center;gap:6px;border-radius:999px;padding:5px 10px;font-size:11px;font-weight:700;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-tertiary)}.dmr-lan-badge.on{border-color:color-mix(in srgb,var(--dmr-accent) 45%,transparent);background:var(--dmr-accent-soft);color:var(--dmr-accent)}.dmr-lan-active,.dmr-lan-idle{display:flex;flex-direction:column;gap:12px}.dmr-lan-active .dmr-share-detail small strong{color:var(--dsw-alias-state-error-primary)}.dmr-danger{border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 45%,var(--dsw-alias-border-l2));color:var(--dsw-alias-state-error-primary)}.dmr-danger:hover{border-color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent)}`,
10100
+ .dmr{--dmr-accent:var(--dk-accent,#2f6fed);--dmr-accent-soft:color-mix(in srgb,var(--dmr-accent) 13%,transparent);display:flex;flex-direction:column;gap:16px;max-width:720px;color:var(--dsw-alias-label-primary);font-size:13px;line-height:1.5}.dmr h3,.dmr h4,.dmr p{margin:0}.dmr h3{font-size:17px;line-height:1.25;letter-spacing:-.01em}.dmr h4{font-size:13px}.dmr-hero,.dmr-status-head{display:flex;align-items:flex-start;gap:12px}.dmr-hero>div,.dmr-status-head>div{min-width:0;display:flex;flex-direction:column;gap:4px}.dmr-hero p,.dmr-status-head p,.dmr-field small,.dmr-share small,.dmr-overview-card small,.dmr-task small,.dmr-note p{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.55}.dmr-hero-icon{width:42px;height:42px;display:inline-flex;align-items:center;justify-content:center;flex:none;border-radius:14px;background:var(--dmr-accent-soft);color:var(--dmr-accent);border:1px solid color-mix(in srgb,var(--dmr-accent) 35%,var(--dsw-alias-border-l1))}.dmr-steps{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;margin:0;padding:0;list-style:none}.dmr-steps li{display:flex;gap:9px;padding:11px;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:12px}.dmr-steps li>span{width:21px;height:21px;display:inline-flex;align-items:center;justify-content:center;flex:none;border-radius:50%;font-size:11px;font-weight:700;color:var(--dmr-accent);background:var(--dmr-accent-soft)}.dmr-steps div{display:flex;flex-direction:column;gap:3px;min-width:0}.dmr-steps strong{font-size:12px}.dmr-steps small{font-size:11px;color:var(--dsw-alias-label-secondary);line-height:1.45}.dmr-field{display:flex;flex-direction:column;gap:6px;font-weight:600}.dmr-field input,.dmr-field select,.dmr-note textarea{box-sizing:border-box;width:100%;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border-radius:10px;padding:10px 12px;min-height:44px;font:inherit;outline:none;transition:border-color .18s ease,box-shadow .18s ease}.dmr-field input:focus,.dmr-field select:focus,.dmr-note textarea:focus{border-color:var(--dmr-accent);box-shadow:0 0 0 3px var(--dmr-accent-soft)}.dmr-field small{font-weight:400}.dmr-network-grid{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(150px,.6fr);gap:12px}.dmr-security{padding:12px 13px;border:1px solid color-mix(in srgb,var(--dk-warn) 48%,var(--dsw-alias-border-l1));border-radius:12px;background:color-mix(in srgb,var(--dk-warn) 9%,transparent)}.dmr-security strong{display:block;margin-bottom:4px;color:var(--dk-warn);font-size:12px}.dmr-security p{font-size:12px;color:var(--dsw-alias-label-secondary);line-height:1.55}.dmr-primary,.dmr-secondary,.dmr-text-button,.dmr-icon-button{font:inherit;touch-action:manipulation;cursor:pointer;transition:transform .15s ease,background .18s ease,border-color .18s ease,opacity .18s ease}.dmr-primary,.dmr-secondary{min-height:44px;display:inline-flex;align-items:center;justify-content:center;gap:8px;border-radius:10px;padding:9px 13px;font-weight:600}.dmr-primary{align-self:flex-start;border:1px solid var(--dmr-accent);background:var(--dmr-accent);color:#fff}.dmr-primary:hover{filter:brightness(1.05)}.dmr-secondary{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary)}.dmr-secondary:hover{border-color:var(--dmr-accent);background:var(--dmr-accent-soft)}.dmr-primary:active,.dmr-secondary:active,.dmr-icon-button:active{transform:scale(.98)}.dmr-primary:disabled,.dmr-secondary:disabled,.dmr-text-button:disabled,.dmr-icon-button:disabled{cursor:not-allowed;opacity:.5}.dmr-message{display:flex;align-items:flex-start;gap:7px;padding:10px 12px;border-radius:10px;font-size:12px}.dmr-message.success{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 10%,transparent)}.dmr-message.error{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent)}.dmr-status-head{justify-content:space-between}.dmr-eyebrow{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:600;color:var(--dmr-accent)}.dmr-eyebrow i{width:7px;height:7px;border-radius:50%;background:currentColor;box-shadow:0 0 0 4px var(--dmr-accent-soft)}.dmr-icon-button{display:inline-flex;align-items:center;justify-content:center;flex:none;width:44px;height:44px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:transparent;color:var(--dsw-alias-label-secondary)}.dmr-icon-button:hover{color:var(--dsw-alias-state-error-primary);border-color:currentColor}.dmr-share{display:flex;flex-direction:column;gap:9px;padding:13px;border:1px solid color-mix(in srgb,var(--dmr-accent) 32%,var(--dsw-alias-border-l1));border-radius:13px;background:var(--dmr-accent-soft)}.dmr-share-layout{display:grid;grid-template-columns:196px minmax(0,1fr);gap:16px;align-items:center}.dmr-qr-card{box-sizing:border-box;display:flex;flex-direction:column;align-items:center;gap:5px;padding:10px;border-radius:12px;background:#fff;color:#111827;text-align:center}.dmr-qr-card img{display:block;width:176px;height:176px;max-width:100%;object-fit:contain}.dmr-qr-card strong{font-size:12px}.dmr-qr-card small{color:#4b5563;font-size:10px}.dmr-qr-loading{display:grid;place-items:center;width:176px;height:176px;color:#64748b;font-size:12px}.dmr-share-detail{min-width:0;display:flex;flex-direction:column;gap:10px}.dmr-share-detail>div:first-child{display:flex;flex-direction:column;gap:4px}.dmr-link{padding:10px 11px;border-radius:8px;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);font:12px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;word-break:break-all;color:var(--dsw-alias-label-secondary)}.dmr-share-actions{display:flex;gap:8px;flex-wrap:wrap}.dmr-share-actions .dmr-primary{align-self:auto}.dmr-overview{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.dmr-overview-card{display:flex;flex-direction:column;gap:3px;padding:12px;border:1px solid var(--dsw-alias-border-l1);border-radius:12px;background:var(--dsw-alias-bg-layer-1)}.dmr-overview-card>span{font-size:11px;color:var(--dsw-alias-label-tertiary)}.dmr-overview-card strong{font-size:16px;letter-spacing:-.01em}.dmr-section{display:flex;flex-direction:column;gap:9px}.dmr-section-head{display:flex;align-items:center;justify-content:space-between;gap:10px}.dmr-section-head small{font-size:11px;color:var(--dsw-alias-label-tertiary)}.dmr-text-button{border:0;background:transparent;color:var(--dmr-accent);padding:8px;min-height:36px;font-weight:600}.dmr-task-list{display:flex;flex-direction:column;gap:8px}.dmr-task{display:flex;align-items:flex-start;gap:9px;padding:10px 11px;border:1px solid var(--dsw-alias-border-l1);border-radius:10px;background:var(--dsw-alias-bg-layer-1)}.dmr-task>div{display:flex;min-width:0;flex:1;flex-direction:column;gap:2px}.dmr-task strong{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dmr-phase{flex:none;border-radius:999px;padding:3px 8px;font-size:11px;background:var(--dmr-accent-soft);color:var(--dmr-accent)}.dmr-phase.write{color:var(--dsw-alias-state-success-primary)}.dmr-phase.code{color:var(--dk-warn)}.dmr-phase.search{color:#0d9488}.dmr-empty{padding:18px 12px;text-align:center;border:1px dashed var(--dsw-alias-border-l2);border-radius:10px;color:var(--dsw-alias-label-secondary);font-size:12px}.dmr-note{display:flex;flex-direction:column;gap:9px;padding-top:2px}.dmr-note blockquote{margin:0;padding:10px 12px;border-left:3px solid var(--dmr-accent);border-radius:0 9px 9px 0;background:var(--dmr-accent-soft);white-space:pre-wrap;font-size:12px}.dmr-note textarea{min-height:88px;resize:vertical;line-height:1.5}.dmr-note .dmr-secondary{align-self:flex-start}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@media (max-width:680px){.dmr{gap:14px;font-size:14px}.dmr h3{font-size:18px}.dmr-steps{grid-template-columns:1fr;gap:8px}.dmr-steps li{padding:10px}.dmr-steps small,.dmr-hero p,.dmr-status-head p,.dmr-field small,.dmr-share small,.dmr-overview-card small,.dmr-task small,.dmr-note p{font-size:12px}.dmr-network-grid{grid-template-columns:1fr;gap:10px}.dmr-field input,.dmr-field select{font-size:16px}.dmr-primary,.dmr-secondary{width:100%;font-size:14px}.dmr-share-layout{grid-template-columns:1fr;gap:12px}.dmr-qr-card{width:min(240px,100%);margin:0 auto}.dmr-qr-card img,.dmr-qr-loading{width:210px;height:210px}.dmr-share-actions{flex-direction:column}.dmr-share-actions .dmr-primary{width:100%}.dmr-overview{gap:8px}.dmr-overview-card{padding:11px}.dmr-status-head{gap:8px}.dmr-link{font-size:11px}.dmr-note textarea{font-size:16px;min-height:104px}.dmr-note .dmr-secondary{align-self:stretch}.dmr-compact .dmr-hero-icon{width:40px;height:40px;border-radius:13px}}@media (prefers-reduced-motion:reduce){.dmr-primary,.dmr-secondary,.dmr-text-button,.dmr-icon-button,.dmr-field input,.dmr-field select,.dmr-note textarea{transition:none}}.dmr-lan{flex:none;margin-top:6px;padding-top:16px;border-top:1px solid var(--dsw-alias-border-l1)}.dmr-lan-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.dmr-lan-title{min-width:0;display:flex;flex-direction:column;gap:4px}.dmr-lan-title p{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.55}.dmr-lan-badge{flex:none;display:inline-flex;align-items:center;gap:6px;border-radius:999px;padding:5px 10px;font-size:11px;font-weight:700;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-tertiary)}.dmr-lan-badge.on{border-color:color-mix(in srgb,var(--dmr-accent) 45%,transparent);background:var(--dmr-accent-soft);color:var(--dmr-accent)}.dmr-lan-active,.dmr-lan-idle{display:flex;flex-direction:column;gap:12px}.dmr-lan-active .dmr-share-detail small strong{color:var(--dsw-alias-state-error-primary)}.dmr-danger{border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 45%,var(--dsw-alias-border-l2));color:var(--dsw-alias-state-error-primary)}.dmr-danger:hover{border-color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent)}
10101
+ /* \u62BD\u5C49\u628A\u624B\uFF1A\u8D34\u5DE6\u8FB9\u7F18\uFF08\u540C\u8DA3\u5473\u6E38\u620F\u6D6E\u6807\u7684\u8FB9\u7F18\u5438\u9644\u8BED\u8A00\uFF09\uFF0Ctop \u7531 place() \u52A8\u6001\u8BBE\u5B9A\uFF1B
10102
+ * z \u5E8F 70 < \u906E\u7F69 75 < \u4FA7\u680F 80 < overlayLayer 90\uFF0C\u9762\u677F/\u5F39\u7A97\u6253\u5F00\u65F6\u81EA\u7136\u88AB\u76D6\u3002 */
10103
+ @media (max-width:700px){.dsh-mobile-drawer-btn{position:fixed;left:0;top:38vh;z-index:70;box-sizing:border-box;width:30px;height:48px;padding:0;display:flex;align-items:center;justify-content:center;border:1px solid var(--dsw-alias-border-l1,rgba(127,139,161,.35));border-left:none;border-radius:0 12px 12px 0;background:color-mix(in srgb,var(--dsw-alias-bg-layer-2,#1c2230) 88%,transparent);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);color:var(--dsw-alias-label-primary,#e6eaf2);box-shadow:4px 0 18px rgba(0,0,0,.28);cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent}.dsh-mobile-drawer-btn:active{transform:scale(.94)}.dsh-mobile-drawer-btn svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}.dsh-mobile-scrim{position:fixed;inset:0;z-index:75;background:rgba(8,10,14,.45);backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);touch-action:none}}`,
9859
10104
  View: MobileRelayView,
9860
- HomeStat: MobileRelayHomeStat
10105
+ HomeStat: MobileRelayHomeStat,
10106
+ Overlay: MobileRelayOverlay
9861
10107
  };
9862
10108
 
9863
10109
  // src/client.jsx
9864
- var DOCK_VERSION = "0.9.1";
10110
+ var DOCK_VERSION = "0.9.5";
9865
10111
  var BUILTIN_FEATURES = [feature, feature2, feature3, feature4, feature5, feature6, feature7, feature8];
9866
10112
  var PLANNED_FEATURES = [];
9867
10113
  var PLANNED_NOTES = {};