@qzsy/dsh-bridge 3.4.4 → 3.5.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/CHANGELOG.md +14 -0
- package/README.md +1 -0
- package/client/client.js +152 -8
- package/client/mobile.js +152 -8
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# 更新日志
|
|
2
2
|
|
|
3
|
+
## [v3.5.0] - 2026-11-02
|
|
4
|
+
|
|
5
|
+
### ✨ 新增
|
|
6
|
+
|
|
7
|
+
- **模型 → 思考级别连招**:在模型 sheet 里选中任意模型后,不再直接关闭整个菜单,而是自动重新打开设置菜单并进入「推理等级」子菜单,以同一个底部 sheet 呈现 Off / Low / High / Max,选完才关闭。
|
|
8
|
+
- **无闪跳过渡**:选中模型时先把旧 sheet 快照留在原地,宿主菜单在背后切换,推理 sheet 滑入后再移除快照;中间宿主菜单隐藏,不会闪出桌面 popover。
|
|
9
|
+
- 模型选中、推理等级选中仍由宿主完成,插件只负责串联和 sheet 化;桌面端不变。
|
|
10
|
+
|
|
11
|
+
### 🧪 验证
|
|
12
|
+
|
|
13
|
+
- 独立宿主模拟:模型 sheet → 选模型 → 自动进入推理 sheet(Off/Low/High/Max)→ 选等级关闭并清理,4/4 通过。
|
|
14
|
+
- 运行中的 DSH:待 3.5.0 安装后验证完整链路。
|
|
15
|
+
|
|
16
|
+
|
|
3
17
|
## [v3.4.4] - 2026-11-02
|
|
4
18
|
|
|
5
19
|
### 🐛 修复
|
package/README.md
CHANGED
|
@@ -49,6 +49,7 @@ dsh plugin --profile <name> add @qzsy/dsh-bridge
|
|
|
49
49
|
- 内容区占满屏宽,左上角「菜单」按钮打开会话 / 工作区 / 插件入口;
|
|
50
50
|
- 支持手势:左缘向右滑打开、抽屉内向左滑关闭,拖动时跟手,松手吸附;
|
|
51
51
|
- 模型切换器在手机上改为底部 sheet:全宽、抓手、遮罩,支持下拉/点遮罩关闭;默认不弹键盘(搜索框 `readonly`),需要搜索时再点;
|
|
52
|
+
- 选完模型自动继续进入「推理等级」sheet,Off / Low / High / Max 选完才关闭,手机上和桌面菜单一样连贯;
|
|
52
53
|
- 全面屏自动避开安全区:刘海 / 状态栏 / 底部 home indicator 不遮挡内容;
|
|
53
54
|
- 点遮罩、点会话行、按 Esc 或转回桌面宽度都会自动收起;
|
|
54
55
|
- 桌面端保持 DSH 原生布局,不受影响。
|
package/client/client.js
CHANGED
|
@@ -463,6 +463,15 @@ var MOBILE_DRAWER_CSS = `
|
|
|
463
463
|
transition: transform 220ms ease, opacity 220ms ease !important;
|
|
464
464
|
animation: none !important;
|
|
465
465
|
}
|
|
466
|
+
/* \u9009\u4E2D\u6A21\u578B\u540E\u8FDB\u5165\u300C\u63A8\u7406\u7B49\u7EA7\u300D\u7684\u8FC7\u6E21\uFF1A\u65E7 sheet \u7684\u5FEB\u7167\u7559\u5728\u539F\u5730\uFF0C\u5BBF\u4E3B\u83DC\u5355\u5148\u9690\u85CF */
|
|
467
|
+
[data-qzsy-model-sheet-clone] {
|
|
468
|
+
z-index: 1199 !important;
|
|
469
|
+
pointer-events: none !important;
|
|
470
|
+
}
|
|
471
|
+
body.qzsy-model-advancing div[id$="-menu"]:not([data-qzsy-model-sheet]):not([data-qzsy-model-sheet-clone]) {
|
|
472
|
+
visibility: hidden !important;
|
|
473
|
+
pointer-events: none !important;
|
|
474
|
+
}
|
|
466
475
|
body.qzsy-model-sheet-dragging [data-qzsy-model-sheet] {
|
|
467
476
|
transform: translateY(var(--qzsy-model-sheet-y, 0px)) !important;
|
|
468
477
|
transition: none !important;
|
|
@@ -516,6 +525,10 @@ function setupMobileDrawer() {
|
|
|
516
525
|
let modelChainUntil = 0;
|
|
517
526
|
let modelDrag = null;
|
|
518
527
|
let modelDragHandlers = null;
|
|
528
|
+
let modelClone = null;
|
|
529
|
+
let modelAdvancing = false;
|
|
530
|
+
let reasoningStep = false;
|
|
531
|
+
let modelAdvanceToken = 0;
|
|
519
532
|
const preventDrawerScroll = (event) => {
|
|
520
533
|
if (!gesture || !event.cancelable) return;
|
|
521
534
|
const touch = event.touches?.[0];
|
|
@@ -633,7 +646,7 @@ function setupMobileDrawer() {
|
|
|
633
646
|
if (search) {
|
|
634
647
|
const menu = search.closest('[role="menu"]') || search.closest('[class*="_menu"]');
|
|
635
648
|
const portal = bodyPortalOf(menu || search);
|
|
636
|
-
if (portal && visiblePortal(portal)) {
|
|
649
|
+
if (portal && visiblePortal(portal) && !portal.hasAttribute("data-qzsy-model-sheet-clone")) {
|
|
637
650
|
const s = getComputedStyle(portal);
|
|
638
651
|
if ((s.position === "fixed" || s.position === "absolute") && portal.getBoundingClientRect().width > 120) return portal;
|
|
639
652
|
}
|
|
@@ -641,7 +654,8 @@ function setupMobileDrawer() {
|
|
|
641
654
|
const candidates = [];
|
|
642
655
|
for (const el of document.body.children) {
|
|
643
656
|
if (!(el instanceof HTMLElement)) continue;
|
|
644
|
-
if (el === modelBackdrop || el.classList.contains(HEADER_CLASS) || el.classList.contains(BACKDROP_CLASS)) continue;
|
|
657
|
+
if (el === modelBackdrop || el === modelClone || el.classList.contains(HEADER_CLASS) || el.classList.contains(BACKDROP_CLASS)) continue;
|
|
658
|
+
if (el.hasAttribute("data-qzsy-model-sheet-clone")) continue;
|
|
645
659
|
if (!visiblePortal(el)) continue;
|
|
646
660
|
const s = getComputedStyle(el);
|
|
647
661
|
if (s.position !== "fixed" && s.position !== "absolute") continue;
|
|
@@ -661,6 +675,26 @@ function setupMobileDrawer() {
|
|
|
661
675
|
candidates.sort((a, b) => Number(b.hasSearch) - Number(a.hasSearch) || Number(b.hasModelMarker) - Number(a.hasModelMarker) || b.rows - a.rows);
|
|
662
676
|
return candidates[0]?.el || null;
|
|
663
677
|
};
|
|
678
|
+
const findReasoningPortal = () => {
|
|
679
|
+
if (!isMobileViewport()) return null;
|
|
680
|
+
const candidates = [];
|
|
681
|
+
for (const el of document.body.children) {
|
|
682
|
+
if (!(el instanceof HTMLElement)) continue;
|
|
683
|
+
if (el === modelBackdrop || el === modelClone || el.classList.contains(HEADER_CLASS) || el.classList.contains(BACKDROP_CLASS)) continue;
|
|
684
|
+
if (el.hasAttribute("data-qzsy-model-sheet") || el.hasAttribute("data-qzsy-model-sheet-clone")) continue;
|
|
685
|
+
if (!visiblePortal(el)) continue;
|
|
686
|
+
const s = getComputedStyle(el);
|
|
687
|
+
if (s.position !== "fixed" && s.position !== "absolute") continue;
|
|
688
|
+
const menu = el.querySelector('[role="menu"]');
|
|
689
|
+
if (!menu) continue;
|
|
690
|
+
const radios = menu.querySelectorAll('button[role="menuitemradio"], [role="menuitemradio"], input[type="radio"]').length;
|
|
691
|
+
if (radios < 1) continue;
|
|
692
|
+
const text = menu.innerText || "";
|
|
693
|
+
if (/搜索模型|Search model|DeepSeek|claude|模型与推理等级/i.test(text)) continue;
|
|
694
|
+
candidates.push(el);
|
|
695
|
+
}
|
|
696
|
+
return candidates[candidates.length - 1] || null;
|
|
697
|
+
};
|
|
664
698
|
const hostBackdropPresent = () => {
|
|
665
699
|
for (const el of document.body.children) {
|
|
666
700
|
if (!(el instanceof HTMLElement)) continue;
|
|
@@ -700,7 +734,23 @@ function setupMobileDrawer() {
|
|
|
700
734
|
}, 450);
|
|
701
735
|
}, 120);
|
|
702
736
|
};
|
|
737
|
+
const dismissHostMenus = () => {
|
|
738
|
+
try {
|
|
739
|
+
document.body.dispatchEvent(new PointerEvent("pointerdown", { bubbles: true, cancelable: true }));
|
|
740
|
+
} catch {
|
|
741
|
+
}
|
|
742
|
+
try {
|
|
743
|
+
document.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape", bubbles: true, cancelable: true }));
|
|
744
|
+
} catch {
|
|
745
|
+
}
|
|
746
|
+
};
|
|
703
747
|
const closeModelSheetNow = () => {
|
|
748
|
+
if (modelAdvancing) {
|
|
749
|
+
cancelAdvanceOverlay();
|
|
750
|
+
clearModelSheet();
|
|
751
|
+
dismissHostMenus();
|
|
752
|
+
return;
|
|
753
|
+
}
|
|
704
754
|
const portal = modelPortal;
|
|
705
755
|
if (!portal) return;
|
|
706
756
|
document.body.classList.remove("qzsy-model-sheet-open");
|
|
@@ -709,6 +759,10 @@ function setupMobileDrawer() {
|
|
|
709
759
|
requestHostModelClose(portal);
|
|
710
760
|
};
|
|
711
761
|
const closeModelSheetAnimated = () => {
|
|
762
|
+
if (modelAdvancing) {
|
|
763
|
+
closeModelSheetNow();
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
712
766
|
const portal = modelPortal;
|
|
713
767
|
if (!portal) return;
|
|
714
768
|
portal.classList.add("qzsy-model-sheet-closing");
|
|
@@ -778,28 +832,42 @@ function setupMobileDrawer() {
|
|
|
778
832
|
portal.addEventListener("touchcancel", onEnd, { passive: true });
|
|
779
833
|
modelDragHandlers = { onStart, onMove, onEnd };
|
|
780
834
|
};
|
|
781
|
-
const clearModelSheet = () => {
|
|
835
|
+
const clearModelSheet = ({ keepChrome = false } = {}) => {
|
|
782
836
|
if (modelPortal) {
|
|
783
837
|
detachModelDrag();
|
|
784
838
|
modelPortal.removeAttribute("data-qzsy-model-sheet");
|
|
839
|
+
modelPortal.removeAttribute("data-qzsy-model-step");
|
|
785
840
|
modelPortal.classList.remove("qzsy-model-sheet", "qzsy-model-sheet-closing");
|
|
786
841
|
}
|
|
787
842
|
modelPortal = null;
|
|
788
843
|
modelDrag = null;
|
|
789
|
-
|
|
844
|
+
modelAdvanceToken += 1;
|
|
845
|
+
modelAdvancing = false;
|
|
846
|
+
reasoningStep = false;
|
|
847
|
+
if (modelClone) {
|
|
848
|
+
modelClone.remove();
|
|
849
|
+
modelClone = null;
|
|
850
|
+
}
|
|
851
|
+
document.body?.classList.remove("qzsy-model-advancing", "qzsy-model-sheet-dragging");
|
|
790
852
|
document.body?.style.removeProperty("--qzsy-model-sheet-y");
|
|
791
853
|
document.body?.style.removeProperty("--qzsy-model-sheet-progress");
|
|
792
|
-
if (
|
|
793
|
-
|
|
794
|
-
modelBackdrop
|
|
854
|
+
if (!keepChrome) {
|
|
855
|
+
document.body?.classList.remove("qzsy-model-sheet-open");
|
|
856
|
+
if (modelBackdrop) {
|
|
857
|
+
modelBackdrop.remove();
|
|
858
|
+
modelBackdrop = null;
|
|
859
|
+
}
|
|
795
860
|
}
|
|
796
861
|
};
|
|
797
862
|
const applyModelSheet = (portal) => {
|
|
798
863
|
if (modelPortal === portal) return;
|
|
799
|
-
|
|
864
|
+
const step = reasoningStep ? "reasoning" : "model";
|
|
865
|
+
const keepChrome = modelAdvancing && Boolean(modelClone);
|
|
866
|
+
clearModelSheet({ keepChrome });
|
|
800
867
|
modelPortal = portal;
|
|
801
868
|
modelChainUntil = 0;
|
|
802
869
|
portal.setAttribute("data-qzsy-model-sheet", "");
|
|
870
|
+
portal.setAttribute("data-qzsy-model-step", step);
|
|
803
871
|
portal.classList.add("qzsy-model-sheet");
|
|
804
872
|
attachModelDrag(portal);
|
|
805
873
|
ensureModelBackdrop();
|
|
@@ -838,12 +906,84 @@ function setupMobileDrawer() {
|
|
|
838
906
|
if (!disposed && modelPortal === portal) document.body.classList.add("qzsy-model-sheet-open");
|
|
839
907
|
});
|
|
840
908
|
};
|
|
909
|
+
const cancelAdvanceOverlay = () => {
|
|
910
|
+
modelAdvanceToken += 1;
|
|
911
|
+
modelAdvancing = false;
|
|
912
|
+
reasoningStep = false;
|
|
913
|
+
document.body?.classList.remove("qzsy-model-advancing");
|
|
914
|
+
if (modelClone) {
|
|
915
|
+
modelClone.remove();
|
|
916
|
+
modelClone = null;
|
|
917
|
+
}
|
|
918
|
+
};
|
|
919
|
+
const beginReasoningAdvance = (portal) => {
|
|
920
|
+
if (disposed || modelAdvancing) return;
|
|
921
|
+
if (portal.getAttribute("data-qzsy-model-step") !== "model") return;
|
|
922
|
+
if (!portal.querySelector('button[role="menuitemradio"], [role="menuitemradio"]')) return;
|
|
923
|
+
modelAdvancing = true;
|
|
924
|
+
const token = ++modelAdvanceToken;
|
|
925
|
+
document.body.classList.add("qzsy-model-advancing");
|
|
926
|
+
modelClone = portal.cloneNode(true);
|
|
927
|
+
modelClone.setAttribute("data-qzsy-model-sheet-clone", "");
|
|
928
|
+
modelClone.setAttribute("aria-hidden", "true");
|
|
929
|
+
for (const el of modelClone.querySelectorAll("[id]")) el.removeAttribute("id");
|
|
930
|
+
document.body.appendChild(modelClone);
|
|
931
|
+
window.setTimeout(() => {
|
|
932
|
+
if (disposed || token !== modelAdvanceToken || !modelAdvancing) return;
|
|
933
|
+
const trigger = document.querySelector(
|
|
934
|
+
'button[aria-haspopup="menu"][aria-label*="\u9009\u62E9\u6A21\u578B"], button[aria-haspopup="menu"][aria-label*="Select model"], button[aria-haspopup="menu"][aria-label*="\u6A21\u578B"]'
|
|
935
|
+
);
|
|
936
|
+
try {
|
|
937
|
+
trigger?.click();
|
|
938
|
+
} catch {
|
|
939
|
+
}
|
|
940
|
+
let attempts = 0;
|
|
941
|
+
const openReasonCell = () => {
|
|
942
|
+
if (disposed || token !== modelAdvanceToken || !modelAdvancing) return;
|
|
943
|
+
const cell = [...document.querySelectorAll('button[role="menuitem"]')].find((b) => /推理等级|Reasoning effort|Reasoning level|推理强度/i.test(b.innerText || ""));
|
|
944
|
+
if (cell) {
|
|
945
|
+
reasoningStep = true;
|
|
946
|
+
try {
|
|
947
|
+
cell.click();
|
|
948
|
+
} catch {
|
|
949
|
+
}
|
|
950
|
+
window.setTimeout(() => {
|
|
951
|
+
if (disposed || token !== modelAdvanceToken) return;
|
|
952
|
+
if (!modelPortal) {
|
|
953
|
+
cancelAdvanceOverlay();
|
|
954
|
+
clearModelSheet();
|
|
955
|
+
}
|
|
956
|
+
}, 900);
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
959
|
+
attempts += 1;
|
|
960
|
+
if (attempts > 16) {
|
|
961
|
+
cancelAdvanceOverlay();
|
|
962
|
+
clearModelSheet();
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
window.setTimeout(openReasonCell, 60);
|
|
966
|
+
};
|
|
967
|
+
window.setTimeout(openReasonCell, 120);
|
|
968
|
+
}, 140);
|
|
969
|
+
};
|
|
841
970
|
const syncModelSheet = () => {
|
|
842
971
|
if (disposed) return;
|
|
843
972
|
if (!isMobileViewport()) {
|
|
844
973
|
clearModelSheet();
|
|
845
974
|
return;
|
|
846
975
|
}
|
|
976
|
+
if (modelAdvancing) {
|
|
977
|
+
if (reasoningStep) {
|
|
978
|
+
const next = findReasoningPortal();
|
|
979
|
+
if (next) {
|
|
980
|
+
applyModelSheet(next);
|
|
981
|
+
return;
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
if (modelPortal && !visiblePortal(modelPortal)) modelPortal = null;
|
|
985
|
+
return;
|
|
986
|
+
}
|
|
847
987
|
if (modelPortal && !visiblePortal(modelPortal)) clearModelSheet();
|
|
848
988
|
const found = findModelPortal();
|
|
849
989
|
if (!found) {
|
|
@@ -872,6 +1012,10 @@ function setupMobileDrawer() {
|
|
|
872
1012
|
window.setTimeout(syncModelSheet, 30);
|
|
873
1013
|
window.setTimeout(syncModelSheet, 180);
|
|
874
1014
|
}
|
|
1015
|
+
const modelOption = target.closest('button[role="menuitemradio"], [role="menuitemradio"]');
|
|
1016
|
+
if (modelOption && modelPortal && modelPortal.getAttribute("data-qzsy-model-step") === "model" && modelPortal.contains(modelOption)) {
|
|
1017
|
+
beginReasoningAdvance(modelPortal);
|
|
1018
|
+
}
|
|
875
1019
|
if (!isOpen()) return;
|
|
876
1020
|
if (target.closest(`.${BACKDROP_CLASS}`)) {
|
|
877
1021
|
closeDrawer();
|
package/client/mobile.js
CHANGED
|
@@ -260,6 +260,15 @@ export const MOBILE_DRAWER_CSS = `
|
|
|
260
260
|
transition: transform 220ms ease, opacity 220ms ease !important;
|
|
261
261
|
animation: none !important;
|
|
262
262
|
}
|
|
263
|
+
/* 选中模型后进入「推理等级」的过渡:旧 sheet 的快照留在原地,宿主菜单先隐藏 */
|
|
264
|
+
[data-qzsy-model-sheet-clone] {
|
|
265
|
+
z-index: 1199 !important;
|
|
266
|
+
pointer-events: none !important;
|
|
267
|
+
}
|
|
268
|
+
body.qzsy-model-advancing div[id$="-menu"]:not([data-qzsy-model-sheet]):not([data-qzsy-model-sheet-clone]) {
|
|
269
|
+
visibility: hidden !important;
|
|
270
|
+
pointer-events: none !important;
|
|
271
|
+
}
|
|
263
272
|
body.qzsy-model-sheet-dragging [data-qzsy-model-sheet] {
|
|
264
273
|
transform: translateY(var(--qzsy-model-sheet-y, 0px)) !important;
|
|
265
274
|
transition: none !important;
|
|
@@ -322,6 +331,10 @@ export function setupMobileDrawer() {
|
|
|
322
331
|
let modelChainUntil = 0;
|
|
323
332
|
let modelDrag = null;
|
|
324
333
|
let modelDragHandlers = null;
|
|
334
|
+
let modelClone = null;
|
|
335
|
+
let modelAdvancing = false;
|
|
336
|
+
let reasoningStep = false;
|
|
337
|
+
let modelAdvanceToken = 0;
|
|
325
338
|
|
|
326
339
|
const preventDrawerScroll = (event) => {
|
|
327
340
|
if (!gesture || !event.cancelable) return;
|
|
@@ -451,7 +464,7 @@ export function setupMobileDrawer() {
|
|
|
451
464
|
if (search) {
|
|
452
465
|
const menu = search.closest('[role="menu"]') || search.closest('[class*="_menu"]');
|
|
453
466
|
const portal = bodyPortalOf(menu || search);
|
|
454
|
-
if (portal && visiblePortal(portal)) {
|
|
467
|
+
if (portal && visiblePortal(portal) && !portal.hasAttribute('data-qzsy-model-sheet-clone')) {
|
|
455
468
|
const s = getComputedStyle(portal);
|
|
456
469
|
if ((s.position === 'fixed' || s.position === 'absolute') && portal.getBoundingClientRect().width > 120) return portal;
|
|
457
470
|
}
|
|
@@ -460,7 +473,8 @@ export function setupMobileDrawer() {
|
|
|
460
473
|
const candidates = [];
|
|
461
474
|
for (const el of document.body.children) {
|
|
462
475
|
if (!(el instanceof HTMLElement)) continue;
|
|
463
|
-
if (el === modelBackdrop || el.classList.contains(HEADER_CLASS) || el.classList.contains(BACKDROP_CLASS)) continue;
|
|
476
|
+
if (el === modelBackdrop || el === modelClone || el.classList.contains(HEADER_CLASS) || el.classList.contains(BACKDROP_CLASS)) continue;
|
|
477
|
+
if (el.hasAttribute('data-qzsy-model-sheet-clone')) continue;
|
|
464
478
|
if (!visiblePortal(el)) continue;
|
|
465
479
|
const s = getComputedStyle(el);
|
|
466
480
|
if (s.position !== 'fixed' && s.position !== 'absolute') continue;
|
|
@@ -485,6 +499,28 @@ export function setupMobileDrawer() {
|
|
|
485
499
|
return candidates[0]?.el || null;
|
|
486
500
|
};
|
|
487
501
|
|
|
502
|
+
const findReasoningPortal = () => {
|
|
503
|
+
if (!isMobileViewport()) return null;
|
|
504
|
+
const candidates = [];
|
|
505
|
+
for (const el of document.body.children) {
|
|
506
|
+
if (!(el instanceof HTMLElement)) continue;
|
|
507
|
+
if (el === modelBackdrop || el === modelClone || el.classList.contains(HEADER_CLASS) || el.classList.contains(BACKDROP_CLASS)) continue;
|
|
508
|
+
if (el.hasAttribute('data-qzsy-model-sheet') || el.hasAttribute('data-qzsy-model-sheet-clone')) continue;
|
|
509
|
+
if (!visiblePortal(el)) continue;
|
|
510
|
+
const s = getComputedStyle(el);
|
|
511
|
+
if (s.position !== 'fixed' && s.position !== 'absolute') continue;
|
|
512
|
+
const menu = el.querySelector('[role="menu"]');
|
|
513
|
+
if (!menu) continue;
|
|
514
|
+
const radios = menu.querySelectorAll('button[role="menuitemradio"], [role="menuitemradio"], input[type="radio"]').length;
|
|
515
|
+
if (radios < 1) continue;
|
|
516
|
+
const text = menu.innerText || '';
|
|
517
|
+
// 推理等级菜单只含 Off / Low / High / Max 等档位,不含模型搜索与模型分组
|
|
518
|
+
if (/搜索模型|Search model|DeepSeek|claude|模型与推理等级/i.test(text)) continue;
|
|
519
|
+
candidates.push(el);
|
|
520
|
+
}
|
|
521
|
+
return candidates[candidates.length - 1] || null;
|
|
522
|
+
};
|
|
523
|
+
|
|
488
524
|
const hostBackdropPresent = () => {
|
|
489
525
|
for (const el of document.body.children) {
|
|
490
526
|
if (!(el instanceof HTMLElement)) continue;
|
|
@@ -517,7 +553,18 @@ export function setupMobileDrawer() {
|
|
|
517
553
|
}, 120);
|
|
518
554
|
};
|
|
519
555
|
|
|
556
|
+
const dismissHostMenus = () => {
|
|
557
|
+
try { document.body.dispatchEvent(new PointerEvent('pointerdown', { bubbles: true, cancelable: true })); } catch { /* 忽略 */ }
|
|
558
|
+
try { document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true, cancelable: true })); } catch { /* 忽略 */ }
|
|
559
|
+
};
|
|
560
|
+
|
|
520
561
|
const closeModelSheetNow = () => {
|
|
562
|
+
if (modelAdvancing) {
|
|
563
|
+
cancelAdvanceOverlay();
|
|
564
|
+
clearModelSheet();
|
|
565
|
+
dismissHostMenus();
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
521
568
|
const portal = modelPortal;
|
|
522
569
|
if (!portal) return;
|
|
523
570
|
document.body.classList.remove('qzsy-model-sheet-open');
|
|
@@ -527,6 +574,10 @@ export function setupMobileDrawer() {
|
|
|
527
574
|
};
|
|
528
575
|
|
|
529
576
|
const closeModelSheetAnimated = () => {
|
|
577
|
+
if (modelAdvancing) {
|
|
578
|
+
closeModelSheetNow();
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
530
581
|
const portal = modelPortal;
|
|
531
582
|
if (!portal) return;
|
|
532
583
|
portal.classList.add('qzsy-model-sheet-closing');
|
|
@@ -600,29 +651,43 @@ export function setupMobileDrawer() {
|
|
|
600
651
|
modelDragHandlers = { onStart, onMove, onEnd };
|
|
601
652
|
};
|
|
602
653
|
|
|
603
|
-
const clearModelSheet = () => {
|
|
654
|
+
const clearModelSheet = ({ keepChrome = false } = {}) => {
|
|
604
655
|
if (modelPortal) {
|
|
605
656
|
detachModelDrag();
|
|
606
657
|
modelPortal.removeAttribute('data-qzsy-model-sheet');
|
|
658
|
+
modelPortal.removeAttribute('data-qzsy-model-step');
|
|
607
659
|
modelPortal.classList.remove('qzsy-model-sheet', 'qzsy-model-sheet-closing');
|
|
608
660
|
}
|
|
609
661
|
modelPortal = null;
|
|
610
662
|
modelDrag = null;
|
|
611
|
-
|
|
663
|
+
modelAdvanceToken += 1;
|
|
664
|
+
modelAdvancing = false;
|
|
665
|
+
reasoningStep = false;
|
|
666
|
+
if (modelClone) {
|
|
667
|
+
modelClone.remove();
|
|
668
|
+
modelClone = null;
|
|
669
|
+
}
|
|
670
|
+
document.body?.classList.remove('qzsy-model-advancing', 'qzsy-model-sheet-dragging');
|
|
612
671
|
document.body?.style.removeProperty('--qzsy-model-sheet-y');
|
|
613
672
|
document.body?.style.removeProperty('--qzsy-model-sheet-progress');
|
|
614
|
-
if (
|
|
615
|
-
|
|
616
|
-
modelBackdrop
|
|
673
|
+
if (!keepChrome) {
|
|
674
|
+
document.body?.classList.remove('qzsy-model-sheet-open');
|
|
675
|
+
if (modelBackdrop) {
|
|
676
|
+
modelBackdrop.remove();
|
|
677
|
+
modelBackdrop = null;
|
|
678
|
+
}
|
|
617
679
|
}
|
|
618
680
|
};
|
|
619
681
|
|
|
620
682
|
const applyModelSheet = (portal) => {
|
|
621
683
|
if (modelPortal === portal) return;
|
|
622
|
-
|
|
684
|
+
const step = reasoningStep ? 'reasoning' : 'model';
|
|
685
|
+
const keepChrome = modelAdvancing && Boolean(modelClone);
|
|
686
|
+
clearModelSheet({ keepChrome });
|
|
623
687
|
modelPortal = portal;
|
|
624
688
|
modelChainUntil = 0;
|
|
625
689
|
portal.setAttribute('data-qzsy-model-sheet', '');
|
|
690
|
+
portal.setAttribute('data-qzsy-model-step', step);
|
|
626
691
|
portal.classList.add('qzsy-model-sheet');
|
|
627
692
|
attachModelDrag(portal);
|
|
628
693
|
ensureModelBackdrop();
|
|
@@ -664,12 +729,83 @@ export function setupMobileDrawer() {
|
|
|
664
729
|
});
|
|
665
730
|
};
|
|
666
731
|
|
|
732
|
+
const cancelAdvanceOverlay = () => {
|
|
733
|
+
modelAdvanceToken += 1;
|
|
734
|
+
modelAdvancing = false;
|
|
735
|
+
reasoningStep = false;
|
|
736
|
+
document.body?.classList.remove('qzsy-model-advancing');
|
|
737
|
+
if (modelClone) {
|
|
738
|
+
modelClone.remove();
|
|
739
|
+
modelClone = null;
|
|
740
|
+
}
|
|
741
|
+
};
|
|
742
|
+
|
|
743
|
+
// 选完模型后自动进入推理等级:保留旧 sheet 快照,宿主菜单在背后切换,再滑入推理 sheet
|
|
744
|
+
const beginReasoningAdvance = (portal) => {
|
|
745
|
+
if (disposed || modelAdvancing) return;
|
|
746
|
+
if (portal.getAttribute('data-qzsy-model-step') !== 'model') return;
|
|
747
|
+
if (!portal.querySelector('button[role="menuitemradio"], [role="menuitemradio"]')) return;
|
|
748
|
+
modelAdvancing = true;
|
|
749
|
+
const token = ++modelAdvanceToken;
|
|
750
|
+
document.body.classList.add('qzsy-model-advancing');
|
|
751
|
+
modelClone = portal.cloneNode(true);
|
|
752
|
+
modelClone.setAttribute('data-qzsy-model-sheet-clone', '');
|
|
753
|
+
modelClone.setAttribute('aria-hidden', 'true');
|
|
754
|
+
for (const el of modelClone.querySelectorAll('[id]')) el.removeAttribute('id');
|
|
755
|
+
document.body.appendChild(modelClone);
|
|
756
|
+
|
|
757
|
+
window.setTimeout(() => {
|
|
758
|
+
if (disposed || token !== modelAdvanceToken || !modelAdvancing) return;
|
|
759
|
+
const trigger = document.querySelector(
|
|
760
|
+
'button[aria-haspopup="menu"][aria-label*="选择模型"], button[aria-haspopup="menu"][aria-label*="Select model"], button[aria-haspopup="menu"][aria-label*="模型"]',
|
|
761
|
+
);
|
|
762
|
+
try { trigger?.click(); } catch { /* 忽略 */ }
|
|
763
|
+
let attempts = 0;
|
|
764
|
+
const openReasonCell = () => {
|
|
765
|
+
if (disposed || token !== modelAdvanceToken || !modelAdvancing) return;
|
|
766
|
+
const cell = [...document.querySelectorAll('button[role="menuitem"]')].find((b) => /推理等级|Reasoning effort|Reasoning level|推理强度/i.test(b.innerText || ''));
|
|
767
|
+
if (cell) {
|
|
768
|
+
reasoningStep = true;
|
|
769
|
+
try { cell.click(); } catch { /* 忽略 */ }
|
|
770
|
+
window.setTimeout(() => {
|
|
771
|
+
if (disposed || token !== modelAdvanceToken) return;
|
|
772
|
+
if (!modelPortal) {
|
|
773
|
+
// 推理菜单没出现:撤掉 overlay,避免卡在半路
|
|
774
|
+
cancelAdvanceOverlay();
|
|
775
|
+
clearModelSheet();
|
|
776
|
+
}
|
|
777
|
+
}, 900);
|
|
778
|
+
return;
|
|
779
|
+
}
|
|
780
|
+
attempts += 1;
|
|
781
|
+
if (attempts > 16) {
|
|
782
|
+
cancelAdvanceOverlay();
|
|
783
|
+
clearModelSheet();
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
window.setTimeout(openReasonCell, 60);
|
|
787
|
+
};
|
|
788
|
+
window.setTimeout(openReasonCell, 120);
|
|
789
|
+
}, 140);
|
|
790
|
+
};
|
|
791
|
+
|
|
667
792
|
const syncModelSheet = () => {
|
|
668
793
|
if (disposed) return;
|
|
669
794
|
if (!isMobileViewport()) {
|
|
670
795
|
clearModelSheet();
|
|
671
796
|
return;
|
|
672
797
|
}
|
|
798
|
+
if (modelAdvancing) {
|
|
799
|
+
if (reasoningStep) {
|
|
800
|
+
const next = findReasoningPortal();
|
|
801
|
+
if (next) {
|
|
802
|
+
applyModelSheet(next);
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
if (modelPortal && !visiblePortal(modelPortal)) modelPortal = null;
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
673
809
|
if (modelPortal && !visiblePortal(modelPortal)) clearModelSheet();
|
|
674
810
|
const found = findModelPortal();
|
|
675
811
|
if (!found) {
|
|
@@ -703,6 +839,14 @@ export function setupMobileDrawer() {
|
|
|
703
839
|
window.setTimeout(syncModelSheet, 180);
|
|
704
840
|
}
|
|
705
841
|
|
|
842
|
+
// 选完模型继续进入推理等级,而不是直接关掉整个菜单
|
|
843
|
+
const modelOption = target.closest('button[role="menuitemradio"], [role="menuitemradio"]');
|
|
844
|
+
if (modelOption && modelPortal
|
|
845
|
+
&& modelPortal.getAttribute('data-qzsy-model-step') === 'model'
|
|
846
|
+
&& modelPortal.contains(modelOption)) {
|
|
847
|
+
beginReasoningAdvance(modelPortal);
|
|
848
|
+
}
|
|
849
|
+
|
|
706
850
|
if (!isOpen()) return;
|
|
707
851
|
|
|
708
852
|
if (target.closest(`.${BACKDROP_CLASS}`)) {
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qzsy/dsh-bridge",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.5.0",
|
|
4
4
|
"description": "DSH 远程隧道云官方客户端插件:一条命令把本机 DeepSeek Harness 接入云端隧道(设备码绑定、短期令牌、本地门禁代理、HTTP/SSE/WebSocket 反向隧道)。",
|
|
5
|
-
"releaseNotes": "【v3.
|
|
5
|
+
"releaseNotes": "【v3.5.0】模型 → 思考级别连招\\n• 选完模型自动进入推理等级 sheet(Off / Low / High / Max),选完才关闭\\n• 旧 sheet 快照过渡,宿主菜单在背后切换,不闪桌面 popover\\n• 模型和推理等级仍由宿主选择;桌面端不变",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "lib/index.js",
|
|
8
8
|
"exports": {
|