@qzsy/dsh-bridge 3.4.0 → 3.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # 更新日志
2
2
 
3
+ ## [v3.4.1] - 2026-11-02
4
+
5
+ ### 🐛 修复
6
+
7
+ - **模型 sheet 识别收紧**:模型菜单被改造成 sheet 后立刻清空触发链,并优先用 `data-model-id` 等模型标记定位;关闭模型面板后紧接着打开账号等其它菜单,不会误套用底部 sheet。
8
+ - **无搜索框宿主兜底**:触发链窗口从 6 秒收紧到 2.5 秒,只对「模型触发后出现、且行数 > 2」的菜单生效。
9
+
10
+ ### 🧪 验证
11
+
12
+ - 实测:第一层「模型 / 推理等级」popover 不改造;二级模型菜单 sheet 化;关闭后再开账号菜单,`data-qzsy-model-sheet` 数量为 0,无残留遮罩。
13
+
14
+
3
15
  ## [v3.4.0] - 2026-11-02
4
16
 
5
17
  ### ✨ 新增
package/client/client.js CHANGED
@@ -624,7 +624,6 @@ function setupMobileDrawer() {
624
624
  if ((s.position === "fixed" || s.position === "absolute") && portal.getBoundingClientRect().width > 120) return portal;
625
625
  }
626
626
  }
627
- if (Date.now() > modelChainUntil) return null;
628
627
  const candidates = [];
629
628
  for (const el of document.body.children) {
630
629
  if (!(el instanceof HTMLElement)) continue;
@@ -637,13 +636,15 @@ function setupMobileDrawer() {
637
636
  const text = menu.innerText || "";
638
637
  const rows = menu.querySelectorAll('[role="menuitem"], [role="option"], button, a, [tabindex]').length;
639
638
  const hasSearch = Boolean(el.querySelector('input[placeholder*="\u641C\u7D22\u6A21\u578B"], input[placeholder*="Search model"]'));
639
+ const hasModelMarker = Boolean(el.querySelector("[data-model-id], [data-provider-id], [data-model], [data-model-name]"));
640
640
  if (/推理等级|Reasoning effort|推理强度/i.test(text) && rows <= 2) continue;
641
641
  const rect = el.getBoundingClientRect();
642
642
  const alreadySheet = rect.width >= window.innerWidth - 2 && Math.abs(rect.bottom - window.innerHeight) < 2 && rect.height > 120;
643
643
  if (alreadySheet && !hasSearch) continue;
644
- if (hasSearch || rows > 2) candidates.push({ el, rows, hasSearch });
644
+ const chained = Date.now() < modelChainUntil && rows > 2;
645
+ if (hasSearch || hasModelMarker || chained) candidates.push({ el, rows, hasSearch, hasModelMarker });
645
646
  }
646
- candidates.sort((a, b) => Number(b.hasSearch) - Number(a.hasSearch) || b.rows - a.rows);
647
+ candidates.sort((a, b) => Number(b.hasSearch) - Number(a.hasSearch) || Number(b.hasModelMarker) - Number(a.hasModelMarker) || b.rows - a.rows);
647
648
  return candidates[0]?.el || null;
648
649
  };
649
650
  const hostBackdropPresent = () => {
@@ -783,6 +784,7 @@ function setupMobileDrawer() {
783
784
  if (modelPortal === portal) return;
784
785
  clearModelSheet();
785
786
  modelPortal = portal;
787
+ modelChainUntil = 0;
786
788
  portal.setAttribute("data-qzsy-model-sheet", "");
787
789
  portal.classList.add("qzsy-model-sheet");
788
790
  attachModelDrag(portal);
@@ -821,7 +823,7 @@ function setupMobileDrawer() {
821
823
  return;
822
824
  }
823
825
  if (isModelTrigger(target)) {
824
- modelChainUntil = Date.now() + 6e3;
826
+ modelChainUntil = Date.now() + 2500;
825
827
  window.setTimeout(syncModelSheet, 30);
826
828
  window.setTimeout(syncModelSheet, 180);
827
829
  }
package/client/mobile.js CHANGED
@@ -440,8 +440,7 @@ export function setupMobileDrawer() {
440
440
  if ((s.position === 'fixed' || s.position === 'absolute') && portal.getBoundingClientRect().width > 120) return portal;
441
441
  }
442
442
  }
443
- // 无搜索框的宿主(如移动端版本)用「模型触发链 + 菜单行数」兜底
444
- if (Date.now() > modelChainUntil) return null;
443
+ // 无搜索框的宿主(如移动端版本)用「模型标记 / 模型触发链 + 菜单行数」兜底
445
444
  const candidates = [];
446
445
  for (const el of document.body.children) {
447
446
  if (!(el instanceof HTMLElement)) continue;
@@ -454,15 +453,19 @@ export function setupMobileDrawer() {
454
453
  const text = menu.innerText || '';
455
454
  const rows = menu.querySelectorAll('[role="menuitem"], [role="option"], button, a, [tabindex]').length;
456
455
  const hasSearch = Boolean(el.querySelector('input[placeholder*="搜索模型"], input[placeholder*="Search model"]'));
456
+ const hasModelMarker = Boolean(el.querySelector('[data-model-id], [data-provider-id], [data-model], [data-model-name]'));
457
457
  // 排除「模型 / 推理等级」两行的第一层 popover
458
458
  if (/推理等级|Reasoning effort|推理强度/i.test(text) && rows <= 2) continue;
459
459
  // 已经是全宽底部 sheet 的宿主菜单不再重复改造
460
460
  const rect = el.getBoundingClientRect();
461
461
  const alreadySheet = rect.width >= window.innerWidth - 2 && Math.abs(rect.bottom - window.innerHeight) < 2 && rect.height > 120;
462
462
  if (alreadySheet && !hasSearch) continue;
463
- if (hasSearch || rows > 2) candidates.push({ el, rows, hasSearch });
463
+ const chained = Date.now() < modelChainUntil && rows > 2;
464
+ if (hasSearch || hasModelMarker || chained) candidates.push({ el, rows, hasSearch, hasModelMarker });
464
465
  }
465
- candidates.sort((a, b) => Number(b.hasSearch) - Number(a.hasSearch) || b.rows - a.rows);
466
+ candidates.sort((a, b) => Number(b.hasSearch) - Number(a.hasSearch)
467
+ || Number(b.hasModelMarker) - Number(a.hasModelMarker)
468
+ || b.rows - a.rows);
466
469
  return candidates[0]?.el || null;
467
470
  };
468
471
 
@@ -602,6 +605,7 @@ export function setupMobileDrawer() {
602
605
  if (modelPortal === portal) return;
603
606
  clearModelSheet();
604
607
  modelPortal = portal;
608
+ modelChainUntil = 0;
605
609
  portal.setAttribute('data-qzsy-model-sheet', '');
606
610
  portal.classList.add('qzsy-model-sheet');
607
611
  attachModelDrag(portal);
@@ -645,7 +649,7 @@ export function setupMobileDrawer() {
645
649
 
646
650
  // 模型切换器:记录触发链,等宿主把二级菜单 portal 挂到 body 后再改造成 sheet
647
651
  if (isModelTrigger(target)) {
648
- modelChainUntil = Date.now() + 6000;
652
+ modelChainUntil = Date.now() + 2500;
649
653
  window.setTimeout(syncModelSheet, 30);
650
654
  window.setTimeout(syncModelSheet, 180);
651
655
  }
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@qzsy/dsh-bridge",
3
- "version": "3.4.0",
3
+ "version": "3.4.1",
4
4
  "description": "DSH 远程隧道云官方客户端插件:一条命令把本机 DeepSeek Harness 接入云端隧道(设备码绑定、短期令牌、本地门禁代理、HTTP/SSE/WebSocket 反向隧道)。",
5
- "releaseNotes": "【v3.4.0】移动端模型切换器改为底部 sheet\\n• 模型二级菜单全宽贴底:圆角、抓手、遮罩、滚动区、safe-area 底部留白\\n• 支持点遮罩关闭、顶部下拉关闭(跟手 + 松手吸附)\\n• 兼容有/无「搜索模型」输入框的宿主版本,不依赖宿主哈希\\n• 桌面端模型 popover 完全不变",
5
+ "releaseNotes": "【v3.4.1】模型 sheet 识别收紧\\n• 模型菜单改造后立即清空触发链,关闭后再开账号菜单不会误套底部 sheet\\n• 优先按 data-model-id 等模型标记定位;无搜索框宿主的兜底窗口收紧到 2.5 秒\\n• 第一层「模型 / 推理等级」popover 保持不变",
6
6
  "type": "module",
7
7
  "main": "lib/index.js",
8
8
  "exports": {