@deepseek-ai/dsh-client-ui-model-selection 0.1.3-alpha.2 → 0.1.5-alpha.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/README.i18n.yaml +2 -2
- package/README.md +1 -1
- package/README.zh.md +1 -1
- package/lib/client.js +57 -6
- package/package.json +17 -15
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/client/ui-model-selection/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: b050f1fa7e680b7669e208d88851754aa72f09e2
|
|
6
|
+
README.zh.md: 85b4d44a1beb45a5a11fa946d2f36d83f9201e29
|
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
|
|
|
9
9
|
|
|
10
10
|
## Summary
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
The Web GUI lets users switch the model and reasoning effort for an existing session through either the `/model` popup or the composer's model control. Both surfaces present the same provider-grouped choices, and the selected model determines the available effort names and default. A complete selection applies to the next request; a running step keeps the model and effort it started with. If no adapter can serve the session's route, the composer remains disabled until routing becomes available.
|
|
13
13
|
|
|
14
14
|
## Table of Contents
|
|
15
15
|
|
package/README.zh.md
CHANGED
|
@@ -9,7 +9,7 @@ kind: "package-reference"
|
|
|
9
9
|
|
|
10
10
|
## 概述
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
Web GUI 允许用户通过 `/model` 弹窗或 composer 模型控件切换既有会话使用的模型与推理强度。两个界面呈现同一组按提供方分组的选择;所选模型决定可用的推理强度名称与默认值。完整选择从下一次请求开始生效;运行中的步骤保留其启动时的模型与推理强度。如果没有适配器可以服务会话路由,composer 会保持停用,直至路由恢复可用。
|
|
13
13
|
|
|
14
14
|
## 目录
|
|
15
15
|
|
package/lib/client.js
CHANGED
|
@@ -8,6 +8,7 @@ window.__ModuleLoader__.load({
|
|
|
8
8
|
let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
|
|
9
9
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
10
10
|
let react = require("react");
|
|
11
|
+
let react_dom = require("react-dom");
|
|
11
12
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
12
13
|
//#region lib/types/client/catalog.js
|
|
13
14
|
/** One Host-generation model catalog shared by every Session selector. */
|
|
@@ -341,7 +342,7 @@ window.__ModuleLoader__.load({
|
|
|
341
342
|
}
|
|
342
343
|
//#endregion
|
|
343
344
|
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-model-selection/src/client/ModelSelect.module.css.mjs
|
|
344
|
-
const css = "._7KE1Ra_root{min-width:0;position:relative}._7KE1Ra_trigger{min-width:0;max-width:min(360px,45cqw);height:28px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:24px;outline:none;align-items:center;gap:4px;padding:0 4px 0 8px;font-size:13px;font-weight:500;line-height:20px;display:flex}._7KE1Ra_trigger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}._7KE1Ra_trigger:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3)}._7KE1Ra_trigger:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}._7KE1Ra_triggerLabel{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}._7KE1Ra_triggerEffort{color:var(--dsw-alias-label-caption);flex:none}._7KE1Ra_chevron{color:var(--dsw-alias-label-caption);flex:none;transition:transform .12s}._7KE1Ra_chevronOpen{transform:rotate(180deg)}._7KE1Ra_menu{z-index:
|
|
345
|
+
const css = "._7KE1Ra_root{min-width:0;position:relative}._7KE1Ra_trigger{min-width:0;max-width:min(360px,45cqw);height:28px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:24px;outline:none;align-items:center;gap:4px;padding:0 4px 0 8px;font-size:13px;font-weight:500;line-height:20px;display:flex}._7KE1Ra_trigger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}._7KE1Ra_trigger:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3)}._7KE1Ra_trigger:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}._7KE1Ra_triggerLabel{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}._7KE1Ra_triggerEffort{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-caption);flex-shrink:1000;overflow:hidden}._7KE1Ra_triggerIcon{flex:none;display:none}@container (width<=360px){._7KE1Ra_triggerIcon{display:block}._7KE1Ra_triggerLabel,._7KE1Ra_triggerEffort{display:none}}._7KE1Ra_chevron{color:var(--dsw-alias-label-caption);flex:none;transition:transform .12s}._7KE1Ra_chevronOpen{transform:rotate(180deg)}._7KE1Ra_menu{z-index:1100;background:var(--dsw-specific-menu);--dsw-elevation-stroke-color:var(--dsw-alias-border-l1);width:max-content;min-width:min(240px,100vw - 32px);max-width:min(420px,100vw - 32px);max-height:min(360px,100vh - 96px);box-shadow:var(--dsw-elevation-prominent);color:var(--dsw-alias-label-primary);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border:0;border-radius:20px;flex-direction:column;padding:4px;display:flex;position:fixed;overflow:hidden}._7KE1Ra_status,._7KE1Ra_empty{color:var(--dsw-alias-label-tertiary);padding:10px;font-size:13px;line-height:20px}._7KE1Ra_error,._7KE1Ra_warning{background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary);border-radius:8px;justify-content:space-between;align-items:flex-start;gap:8px;margin-bottom:4px;padding:7px 8px;font-size:12px;line-height:18px;display:flex}._7KE1Ra_warning{background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-state-warn-label)}._7KE1Ra_retry{color:inherit;font:inherit;cursor:pointer;background:0 0;border:none;flex:none;padding:0;font-weight:600}._7KE1Ra_groups{min-height:0;overflow-y:auto}._7KE1Ra_group+._7KE1Ra_group{margin-top:4px}._7KE1Ra_groupTitle{z-index:1;background:var(--dsw-specific-menu);color:var(--dsw-alias-label-tertiary);padding:5px 8px 3px;font-size:12px;font-weight:500;line-height:18px;position:sticky;top:0}._7KE1Ra_option{box-sizing:border-box;width:auto;min-width:100%;min-height:38px;color:inherit;text-align:left;cursor:pointer;background:0 0;border:none;border-radius:10px;outline:none;align-items:center;gap:8px;padding:6px 8px;display:flex}._7KE1Ra_option:hover:not(:disabled),._7KE1Ra_option:focus-visible{background:var(--dsw-alias-interactive-bg-hover)}._7KE1Ra_selected{background:0 0}._7KE1Ra_option:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}._7KE1Ra_optionCopy{flex-direction:column;flex:1;min-width:0;display:flex}._7KE1Ra_modelName{color:inherit;text-overflow:ellipsis;white-space:nowrap;font-size:14px;font-weight:500;line-height:20px;overflow:hidden}._7KE1Ra_check{color:var(--dsw-alias-label-primary);flex:0 0 18px;place-items:center;display:grid}._7KE1Ra_cell{box-sizing:border-box;width:auto;min-width:100%;height:40px;color:var(--dsw-alias-label-primary);cursor:pointer;text-align:left;background:0 0;border:none;border-radius:10px;align-items:center;gap:8px;padding:0 10px;font-size:14px;line-height:22px;display:flex}._7KE1Ra_cell:hover{background:var(--dsw-alias-interactive-bg-hover)}._7KE1Ra_cellLabel{white-space:nowrap;flex:none}._7KE1Ra_cellValue{text-overflow:ellipsis;white-space:nowrap;text-align:right;min-width:0;color:var(--dsw-alias-label-tertiary);flex:auto;overflow:hidden}._7KE1Ra_cellChevron{color:var(--dsw-alias-label-tertiary);flex:none}";
|
|
345
346
|
const tagId = "@deepseek-ai/dsh-client-ui-model-selection/ModelSelect.module.css";
|
|
346
347
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
347
348
|
const tag = document.createElement("style");
|
|
@@ -373,6 +374,7 @@ window.__ModuleLoader__.load({
|
|
|
373
374
|
"status": "_7KE1Ra_status",
|
|
374
375
|
"trigger": "_7KE1Ra_trigger",
|
|
375
376
|
"triggerEffort": "_7KE1Ra_triggerEffort",
|
|
377
|
+
"triggerIcon": "_7KE1Ra_triggerIcon",
|
|
376
378
|
"triggerLabel": "_7KE1Ra_triggerLabel",
|
|
377
379
|
"warning": "_7KE1Ra_warning"
|
|
378
380
|
};
|
|
@@ -391,6 +393,12 @@ window.__ModuleLoader__.load({
|
|
|
391
393
|
* announces through the shared transient Toast anchored to the composer
|
|
392
394
|
* card; the in-menu strip with Retry remains the catalog-load surface.
|
|
393
395
|
*/
|
|
396
|
+
/** Unplaced portal card: hidden but laid out at a fixed origin so offsetWidth/offsetHeight are real (Menu primitive's measure pass). */
|
|
397
|
+
const MEASURE_STYLE = {
|
|
398
|
+
visibility: "hidden",
|
|
399
|
+
left: 0,
|
|
400
|
+
top: 0
|
|
401
|
+
};
|
|
394
402
|
/**
|
|
395
403
|
* Render the composer model seat.
|
|
396
404
|
* @param props - owner share (locked) + injected face (shared directory
|
|
@@ -406,6 +414,8 @@ window.__ModuleLoader__.load({
|
|
|
406
414
|
const toastSeq = (0, react.useRef)(0);
|
|
407
415
|
const rootRef = (0, react.useRef)(null);
|
|
408
416
|
const triggerRef = (0, react.useRef)(null);
|
|
417
|
+
const menuRef = (0, react.useRef)(null);
|
|
418
|
+
const [menuPos, setMenuPos] = (0, react.useState)(null);
|
|
409
419
|
const itemRefs = (0, react.useRef)([]);
|
|
410
420
|
const id = (0, react.useId)();
|
|
411
421
|
const choices = (0, react.useMemo)(() => state.groups.flatMap((group) => group.models.map((model) => ({
|
|
@@ -438,13 +448,48 @@ window.__ModuleLoader__.load({
|
|
|
438
448
|
(0, react.useEffect)(() => {
|
|
439
449
|
if (!open) return;
|
|
440
450
|
const closeOutside = (event) => {
|
|
441
|
-
if (
|
|
451
|
+
if (rootRef.current?.contains(event.target) === true) return;
|
|
452
|
+
if (menuRef.current?.contains(event.target) === true) return;
|
|
453
|
+
setOpen(false);
|
|
442
454
|
};
|
|
443
455
|
document.addEventListener("mousedown", closeOutside);
|
|
444
456
|
return () => {
|
|
445
457
|
document.removeEventListener("mousedown", closeOutside);
|
|
446
458
|
};
|
|
447
459
|
}, [open]);
|
|
460
|
+
(0, react.useLayoutEffect)(() => {
|
|
461
|
+
if (!open) {
|
|
462
|
+
setMenuPos(null);
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
const place = () => {
|
|
466
|
+
/* v8 ignore next 2 -- the trigger ref is attached whenever the menu is open. */
|
|
467
|
+
const rect = triggerRef.current?.getBoundingClientRect();
|
|
468
|
+
if (rect === void 0) return;
|
|
469
|
+
const MARGIN = 12;
|
|
470
|
+
const lw = menuRef.current?.offsetWidth ?? 0;
|
|
471
|
+
const lh = menuRef.current?.offsetHeight ?? 0;
|
|
472
|
+
let x = rect.right - lw;
|
|
473
|
+
let y = rect.top - 8 - lh;
|
|
474
|
+
if (lw > 0) x = Math.min(Math.max(x, MARGIN), window.innerWidth - lw - MARGIN);
|
|
475
|
+
if (lh > 0) y = Math.min(Math.max(y, MARGIN), window.innerHeight - lh - MARGIN);
|
|
476
|
+
setMenuPos({
|
|
477
|
+
left: x,
|
|
478
|
+
top: y
|
|
479
|
+
});
|
|
480
|
+
};
|
|
481
|
+
place();
|
|
482
|
+
window.addEventListener("scroll", place, true);
|
|
483
|
+
window.addEventListener("resize", place);
|
|
484
|
+
return () => {
|
|
485
|
+
window.removeEventListener("scroll", place, true);
|
|
486
|
+
window.removeEventListener("resize", place);
|
|
487
|
+
};
|
|
488
|
+
}, [
|
|
489
|
+
open,
|
|
490
|
+
pane,
|
|
491
|
+
state
|
|
492
|
+
]);
|
|
448
493
|
if (!available) return null;
|
|
449
494
|
const show = () => {
|
|
450
495
|
setPane("root");
|
|
@@ -478,7 +523,7 @@ window.__ModuleLoader__.load({
|
|
|
478
523
|
}
|
|
479
524
|
};
|
|
480
525
|
const onBlur = (event) => {
|
|
481
|
-
if (event.relatedTarget instanceof Node && rootRef.current?.contains(event.relatedTarget)) return;
|
|
526
|
+
if (event.relatedTarget instanceof Node && (rootRef.current?.contains(event.relatedTarget) === true || menuRef.current?.contains(event.relatedTarget) === true)) return;
|
|
482
527
|
close();
|
|
483
528
|
};
|
|
484
529
|
const settleSelection = (accepted) => {
|
|
@@ -553,6 +598,10 @@ window.__ModuleLoader__.load({
|
|
|
553
598
|
else show();
|
|
554
599
|
},
|
|
555
600
|
children: [
|
|
601
|
+
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconDataOutline16, {
|
|
602
|
+
className: ModelSelect_module_css_default.triggerIcon,
|
|
603
|
+
size: 16
|
|
604
|
+
}),
|
|
556
605
|
(0, react_jsx_runtime.jsx)("span", {
|
|
557
606
|
className: ModelSelect_module_css_default.triggerLabel,
|
|
558
607
|
children: modelLabel
|
|
@@ -564,9 +613,11 @@ window.__ModuleLoader__.load({
|
|
|
564
613
|
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { className: clsx(ModelSelect_module_css_default.chevron, open && ModelSelect_module_css_default.chevronOpen) })
|
|
565
614
|
]
|
|
566
615
|
}),
|
|
567
|
-
open && (0, react_jsx_runtime.jsxs)("div", {
|
|
616
|
+
open && (0, react_dom.createPortal)((0, react_jsx_runtime.jsxs)("div", {
|
|
617
|
+
ref: menuRef,
|
|
568
618
|
id: `${id}-menu`,
|
|
569
619
|
className: ModelSelect_module_css_default.menu,
|
|
620
|
+
style: menuPos ?? MEASURE_STYLE,
|
|
570
621
|
role: "menu",
|
|
571
622
|
"aria-label": t("menu.aria"),
|
|
572
623
|
"aria-busy": state.status === "loading" || busy,
|
|
@@ -717,7 +768,7 @@ window.__ModuleLoader__.load({
|
|
|
717
768
|
})]
|
|
718
769
|
}, level.key))] })
|
|
719
770
|
]
|
|
720
|
-
}),
|
|
771
|
+
}), document.body),
|
|
721
772
|
toast !== null && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Toast, {
|
|
722
773
|
text: toast.text,
|
|
723
774
|
icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconWarningOutline16, {}),
|
|
@@ -852,7 +903,7 @@ window.__ModuleLoader__.load({
|
|
|
852
903
|
const sessions = scope.sessions;
|
|
853
904
|
scope.effect(() => command.register({
|
|
854
905
|
name: "model",
|
|
855
|
-
description: t("command.description"),
|
|
906
|
+
description: () => t("command.description"),
|
|
856
907
|
available: (session) => sessions.subagentAddress(session.sessionId) === void 0,
|
|
857
908
|
ui: {
|
|
858
909
|
kind: "popupSelect",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-client-ui-model-selection",
|
|
3
3
|
"description": "Model selection over the shared model catalog, Session projection, and session.selectModel",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.5-alpha.1",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -43,21 +43,23 @@
|
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/react": "~18.3.1",
|
|
45
45
|
"react": "^18.2.0",
|
|
46
|
-
"
|
|
47
|
-
"@
|
|
48
|
-
"@deepseek-ai/dsh-
|
|
49
|
-
"@deepseek-ai/dsh-
|
|
50
|
-
"@deepseek-ai/dsh-client-
|
|
51
|
-
"@deepseek-ai/dsh-client-
|
|
52
|
-
"@deepseek-ai/dsh-client-ui-
|
|
53
|
-
"@deepseek-ai/dsh-client-ui-
|
|
54
|
-
"@deepseek-ai/dsh-client-ui-
|
|
55
|
-
"@deepseek-ai/dsh-
|
|
46
|
+
"react-dom": "^18.2.0",
|
|
47
|
+
"@types/react-dom": "~18.3.0",
|
|
48
|
+
"@deepseek-ai/dsh-api-remotes": "^0.1.5-alpha.1",
|
|
49
|
+
"@deepseek-ai/dsh-api-session-controller": "^0.1.5-alpha.1",
|
|
50
|
+
"@deepseek-ai/dsh-client-locale": "^0.1.5-alpha.1",
|
|
51
|
+
"@deepseek-ai/dsh-client-test-runtime": "^0.1.5-alpha.1",
|
|
52
|
+
"@deepseek-ai/dsh-client-ui-commands": "^0.1.5-alpha.1",
|
|
53
|
+
"@deepseek-ai/dsh-client-ui-conversation": "^0.1.5-alpha.1",
|
|
54
|
+
"@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.5-alpha.1",
|
|
55
|
+
"@deepseek-ai/dsh-client-ui-primitives": "^0.1.5-alpha.1",
|
|
56
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.5-alpha.1",
|
|
57
|
+
"@deepseek-ai/dsh-typert-protocol": "^0.1.5-alpha.1",
|
|
56
58
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
57
|
-
"@deepseek-ai/dsh-
|
|
58
|
-
"@deepseek-ai/dsh-
|
|
59
|
-
"@deepseek-ai/dsh-client-ui-renderer": "^0.1.
|
|
60
|
-
"@deepseek-ai/dsh-client-ui-session": "^0.1.
|
|
59
|
+
"@deepseek-ai/dsh-client-store": "^0.1.5-alpha.1",
|
|
60
|
+
"@deepseek-ai/dsh-session": "^0.1.5-alpha.1",
|
|
61
|
+
"@deepseek-ai/dsh-client-ui-renderer": "^0.1.5-alpha.1",
|
|
62
|
+
"@deepseek-ai/dsh-client-ui-session": "^0.1.5-alpha.1"
|
|
61
63
|
},
|
|
62
64
|
"files": [
|
|
63
65
|
"lib/index.js",
|