@bittersmilezzz/dsh-model-selector 0.1.18

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.
@@ -0,0 +1,20 @@
1
+ /**
2
+ * dsh-model-selector — browser half.
3
+ *
4
+ * Replaces the shipped `conversation.input.model` seat with an enhanced one
5
+ * (provider-group collapse + name search) while keeping the exact shared
6
+ * per-session directory (`ctx.modelDirectories`) the /model popup reads, so
7
+ * both entries stay in sync. Shadowing is the sanctioned seam: the slot is
8
+ * `single`, so a registration at a LOWER priority than the shipped occupant
9
+ * (default 0) becomes the rendered winner.
10
+ */
11
+ import type { Context as ClientContext } from '@deepseek-ai/cordis';
12
+ /** Required services: the registry, session lookup, locale, the slot seat, and the model directory's Remote faces. */
13
+ export declare const inject: string[];
14
+ /**
15
+ * Client plugin body: register the dictionaries and stylesheet, then take the
16
+ * model seat over the shared directory once `modelDirectories` appears.
17
+ * @param ctx - client root context.
18
+ */
19
+ export declare function apply(ctx: ClientContext): void;
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAoBnE,sHAAsH;AACtH,eAAO,MAAM,MAAM,UAOlB,CAAA;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CA8C9C"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * `modelSelector` namespace dictionaries for the enhanced model seat.
3
+ *
4
+ * Simplified Chinese is the key-set source of truth; the English dictionary is
5
+ * checked complete against it. Product copy is Chinese-first per repo style.
6
+ */
7
+ export declare const zh: {
8
+ "trigger.fallback": string;
9
+ "trigger.loading": string;
10
+ "trigger.selectAria": string;
11
+ "trigger.aria": string;
12
+ "trigger.ariaEffort": string;
13
+ "menu.aria": string;
14
+ "menu.effort": string;
15
+ "search.placeholder": string;
16
+ "search.clearAria": string;
17
+ "search.noMatch": string;
18
+ "search.status": string;
19
+ "search.more": string;
20
+ "group.toggleAria": string;
21
+ "effort.providerDefault": string;
22
+ "status.loading": string;
23
+ "error.action": string;
24
+ "action.reload": string;
25
+ "warning.groupLoad": string;
26
+ "empty.models": string;
27
+ "empty.efforts": string;
28
+ "effort.failed": string;
29
+ "effort.timeout": string;
30
+ "notice.already": string;
31
+ "notice.selectFailed": string;
32
+ "toast.effortAuto": string;
33
+ "badge.reasoning": string;
34
+ "badge.reasoningHint": string;
35
+ };
36
+ export declare const en: {
37
+ "trigger.fallback": string;
38
+ "trigger.loading": string;
39
+ "trigger.selectAria": string;
40
+ "trigger.aria": string;
41
+ "trigger.ariaEffort": string;
42
+ "menu.aria": string;
43
+ "menu.effort": string;
44
+ "search.placeholder": string;
45
+ "search.clearAria": string;
46
+ "search.noMatch": string;
47
+ "search.status": string;
48
+ "search.more": string;
49
+ "group.toggleAria": string;
50
+ "effort.providerDefault": string;
51
+ "status.loading": string;
52
+ "error.action": string;
53
+ "action.reload": string;
54
+ "warning.groupLoad": string;
55
+ "empty.models": string;
56
+ "empty.efforts": string;
57
+ "effort.failed": string;
58
+ "effort.timeout": string;
59
+ "notice.already": string;
60
+ "notice.selectFailed": string;
61
+ "toast.effortAuto": string;
62
+ "badge.reasoning": string;
63
+ "badge.reasoningHint": string;
64
+ };
65
+ declare module '@deepseek-ai/dsh-client-ui-slots' {
66
+ interface LocaleNamespaceMap {
67
+ /** The enhanced model seat copy. */
68
+ modelSelector: keyof typeof zh;
69
+ }
70
+ }
71
+ //# sourceMappingURL=locales.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4Bd,CAAC;AAGF,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4Bd,CAAC;AACF,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,kBAAkB;QAC1B,oCAAoC;QACpC,aAAa,EAAE,MAAM,OAAO,EAAE,CAAA;KAC/B;CACF"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * dsh-model-selector — 菜单弹出方向与高度钳位的纯函数。
3
+ *
4
+ * 从 ModelSelect.tsx 原样搬出(无 JSX、无 DOM、无模块级副作用),以便用
5
+ * node --test 直接跑源码:方向决策(向上 vs 向下弹)和向下弹的高度钳位都是
6
+ * 用户可见且曾在矮窗口/滚动场景出过 bug 的逻辑,留在 .tsx 里则无法脱离
7
+ * 浏览器测试。
8
+ */
9
+ /** 菜单设计最大高度(px);实际由 useAnchoredMaxHeight 按视口可用空间钳位。
10
+ * 调法:调大允许更高菜单(矮视口下仍会被钳到视口内),调小菜单更矮。 */
11
+ export declare const MENU_MAX_HEIGHT = 420;
12
+ /** 与视口边缘保留的距离;对齐 primitives 里未导出的 MARGIN。
13
+ * 改动同时影响向上/向下弹与水平钳位的边距,需与官方 MARGIN 意图保持一致。 */
14
+ export declare const MENU_VIEWPORT_MARGIN = 12;
15
+ /**
16
+ * 向上弹当且仅当 trigger 上方可用空间不小于下方可用空间:
17
+ * 取上下两侧中空间更大的一侧,避免矮窗口把面板挤到视口下沿外面。
18
+ */
19
+ export declare function dmsMenuAbove(triggerTop: number, triggerBottom: number, viewportHeight: number): boolean;
20
+ /** 向下弹时按 trigger 下方空间钳位菜单高度(top-anchored,不能复用向上弹的 fit)。 */
21
+ export declare function dmsBelowMaxHeight(triggerBottom: number, viewportHeight: number, cap: number): number;
22
+ /**
23
+ * 菜单水平钳位:默认右锚定(right:0,与 seat 右缘对齐);seat 右缘左侧放不下
24
+ * 整幅菜单(seat 靠输入区左下 + 窄窗口)、或 seat 右缘本身已越出视口右缘
25
+ * (页面横向溢出/缩放时 rect.right 可大于 innerWidth,右锚定会把整幅菜单
26
+ * 拖出屏外)时,返回钳到视口内的 left 值,调用方改用 left 锚定。
27
+ * 返回 undefined 表示保持默认右锚定。
28
+ * menuWidth 传菜单实际渲染宽度(offsetWidth),与 CSS `min(280px, 100vw-32px)` 解耦。
29
+ */
30
+ export declare function dmsMenuLeft(rootRight: number, menuWidth: number, viewportWidth: number, margin: number): number | undefined;
31
+ //# sourceMappingURL=menuFit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menuFit.d.ts","sourceRoot":"","sources":["../../../src/client/menuFit.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;uCACuC;AACvC,eAAO,MAAM,eAAe,MAAM,CAAC;AACnC;8CAC8C;AAC9C,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAEvG;AAED,2DAA2D;AAC3D,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEpG;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAM3H"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * dsh-model-selector — 菜单 roving tabindex 的纯决策逻辑(node 可测)。
3
+ *
4
+ * 模型列表可达数百行,若每行都是 Tab 停靠点,Tab 键会陷入行海;roving
5
+ * tabindex(WAI-ARIA menu 模式的通行做法)只让「活动行」留在 Tab 序里,
6
+ * 其余行 tabindex=-1、仅方向键可达。本模块只负责一件事:给定当前渲染的
7
+ * 行集合与选中行,算出 Tab 从搜索框进入列表时应停靠的默认行键。
8
+ */
9
+ export interface RovingRowSet {
10
+ /** 搜索命中行键(渲染顺序);null = 非搜索态(分组视图)。 */
11
+ hitKeys: readonly string[] | null;
12
+ /** 分组视图中可见(未折叠)的模型行键(渲染顺序)。 */
13
+ modelKeys: readonly string[];
14
+ /** 分组视图中全部组头键(组头始终渲染,即使组被折叠)。 */
15
+ headerKeys: readonly string[];
16
+ /** 当前选中行键;null = 尚无选中。 */
17
+ selectedKey: string | null;
18
+ }
19
+ /**
20
+ * Tab 默认落点:搜索态取「选中行若在命中集内,否则首个命中」;分组态取
21
+ * 「选中行若可见,否则首个可见模型行」;全部折叠(无可见模型行)时回退到
22
+ * 首个组头。返回 null 表示当前没有任何可聚焦行(空态由菜单外的 role=status
23
+ * 播报,列表容器不渲染)。
24
+ */
25
+ export declare function dmsDefaultRowKey(set: RovingRowSet): string | null;
26
+ //# sourceMappingURL=roving.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roving.d.ts","sourceRoot":"","sources":["../../../src/client/roving.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAA;IACjC,+BAA+B;IAC/B,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;IAC5B,iCAAiC;IACjC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;IAC7B,0BAA0B;IAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI,CASjE"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Stylesheet for the enhanced model seat.
3
+ *
4
+ * Injected as one `<style data-plugin="@bittersmilezzz/dsh-model-selector">` tag by the client
5
+ * apply and removed again on unload. Class names are prefixed `dms-` so they
6
+ * cannot collide with CSS-module hashes from other plugins. Colors come only
7
+ * from `--dsw-*` theme tokens, matching the shipped Menu material.
8
+ */
9
+ export declare const CSS = "\n.dms-root {\n position: relative;\n min-width: 0;\n}\n\n.dms-trigger {\n display: flex;\n align-items: center;\n gap: 4px;\n min-width: 0;\n max-width: min(420px, calc(100vw - 48px));\n height: 28px;\n padding: 0 4px 0 8px;\n border: none;\n border-radius: 24px;\n outline: none;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n font-size: 13px;\n line-height: 20px;\n font-weight: 500;\n cursor: pointer;\n}\n.dms-trigger:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); }\n.dms-trigger:focus-visible { box-shadow: 0 0 0 2px var(--dsw-alias-border-l3); }\n.dms-trigger:disabled { color: var(--dsw-alias-label-dimmed); cursor: default; }\n\n.dms-triggerLabel {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n line-height: 20px;\n}\n.dms-triggerEffort {\n flex: 0 0 auto;\n line-height: 20px;\n color: var(--dsw-alias-label-caption);\n}\n.dms-triggerProvider {\n flex: 0 0 auto;\n max-width: 88px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--dsw-alias-label-caption);\n font-size: 11px;\n line-height: 20px;\n font-weight: 400;\n}\n\n.dms-chevron,\n.dms-groupChevron {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n line-height: 0;\n}\n.dms-chevron {\n color: var(--dsw-alias-label-caption);\n transition: transform 120ms ease;\n}\n.dms-chevronOpen { transform: rotate(180deg); }\n.dms-groupChevron {\n color: var(--dsw-alias-label-tertiary);\n transition: transform 120ms ease;\n}\n.dms-groupChevronClosed { transform: rotate(-90deg); }\n.dms-model-check svg { display: block; }\n\n.dms-menu {\n position: absolute;\n right: 0;\n bottom: calc(100% + 8px);\n z-index: 20;\n display: flex;\n flex-direction: column;\n width: min(280px, calc(100vw - 32px));\n overflow: hidden;\n padding: 4px 0 4px 4px;\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-inverted);\n border-radius: 12px;\n background: var(--dsw-specific-menu);\n box-shadow: var(--dsw-shadow-lv3);\n color: var(--dsw-alias-label-primary);\n animation: dms-menu-in 150ms cubic-bezier(.22,1,.36,1);\n --dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2);\n --dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2);\n}\n.dms-menuModel { border-right: none; }\n.dms-menuBelow {\n bottom: auto;\n top: calc(100% + 8px);\n animation-name: dms-menu-in-below;\n}\n\n.dms-status,\n.dms-empty {\n flex: 0 0 auto;\n padding: 10px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 13px;\n line-height: 20px;\n}\n\n.dms-more {\n flex: 0 0 auto;\n padding: 8px 12px;\n border-top: 1px solid var(--dsw-alias-border-l1, transparent);\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n line-height: 18px;\n}\n\n/* Provider-load failure strip: capped and scrollable so a long list of failed\n groups can never squeeze the model list out of the menu (E4). */\n.dms-failures {\n flex: 0 0 auto;\n max-height: 96px;\n min-height: 0;\n overflow-y: auto;\n}\n\n.dms-error,\n.dms-warning {\n flex: 0 0 auto;\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 8px;\n margin-bottom: 4px;\n padding: 7px 8px;\n border-radius: 8px;\n background: var(--dsw-alias-interactive-bg-hover-danger);\n color: var(--dsw-alias-state-error-primary);\n font-size: 12px;\n line-height: 18px;\n}\n.dms-warning {\n background: var(--dsw-alias-bg-module-platform);\n color: var(--dsw-alias-state-warn-label);\n}\n.dms-retry {\n flex: 0 0 auto;\n padding: 0;\n border: none;\n border-radius: 4px;\n background: transparent;\n color: inherit;\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n}\n.dms-retry:focus-visible { box-shadow: 0 0 0 2px var(--dsw-alias-border-l3); }\n\n/* Search box pinned above the scrollable list. */\n.dms-search {\n position: relative;\n margin-bottom: 4px;\n margin-right: 4px;\n flex: 0 0 auto;\n}\n.dms-searchInput {\n box-sizing: border-box;\n width: 100%;\n height: 30px;\n padding: 0 30px 0 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n outline: none;\n background: var(--dsw-alias-bg-input);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n line-height: 18px;\n}\n.dms-searchInput::placeholder { color: var(--dsw-alias-label-tertiary); }\n.dms-searchInput:focus-visible { box-shadow: 0 0 0 2px var(--dsw-alias-border-l3); }\n.dms-searchClear {\n position: absolute;\n top: 0;\n right: 0;\n display: grid;\n place-items: center;\n width: 30px;\n height: 30px;\n padding: 0;\n border: none;\n background: transparent;\n color: var(--dsw-alias-label-tertiary);\n cursor: pointer;\n}\n.dms-searchClear:hover { color: var(--dsw-alias-label-primary); }\n/* \u952E\u76D8\u7126\u70B9\u6B64\u524D\u5728\u8FD9\u4E09\u4E2A\u53EF\u805A\u7126\u63A7\u4EF6\u4E0A\u5B8C\u5168\u9690\u8EAB\uFF08\u4E0A\u8F6E\u53EA\u8865\u4E86\u6A21\u578B\u884C\uFF09\u3002 */\n.dms-searchClear:focus-visible {\n border-radius: 8px;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n/* \u56FE\u6807\u7EC4\u4EF6\u53EA\u6536 size/className\uFF0C\u88C5\u9970\u6027 aria-hidden \u53EA\u80FD\u5305\u4E00\u5C42 span\uFF1Bcontents \u8BA9\u5B83\u4E0D\u5360\u5E03\u5C40\u3002 */\n.dms-icon-slot { display: contents; }\n\n.dms-groups { flex: 1 1 auto; min-height: 0; overflow-y: auto; contain: content; }\n/* \u7A7A\u6001\u5360\u4F4D\uFF1A\u7A7A\u6001\u64AD\u62A5\u8282\u70B9\u5728 role=menu \u5BB9\u5668\u5916\uFF0C\u7528\u4E0E .dms-groups \u540C\u6B3E\u5F39\u6027\u5E03\u5C40\n \u8865\u56DE\u5217\u8868\u533A\u672C\u6765\u7684\u4F4D\u7F6E\uFF08\u4E0D\u6324\u538B\u5176\u4F59\u680F\uFF0C\u6D88\u606F\u4E5F\u4E0D\u4F1A\u8D34\u5230\u83DC\u5355\u9876\u90E8\uFF09\u3002 */\n.dms-groupsFill { flex: 1 1 auto; min-height: 0; overflow-y: auto; contain: content; }\n.dms-group + .dms-group { margin-top: 4px; }\n\n/* Collapsible provider header: a full-width toggle button. */\n.dms-groupHeader {\n position: sticky;\n top: 0;\n z-index: 1;\n display: flex;\n align-items: center;\n gap: 4px;\n width: 100%;\n padding: 5px 8px 3px;\n border: none;\n outline: none;\n background: var(--dsw-specific-menu);\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n text-align: left;\n cursor: pointer;\n}\n.dms-groupHeader:hover { color: var(--dsw-alias-label-primary); }\n.dms-groupHeader:focus-visible { box-shadow: inset 0 0 0 2px var(--dsw-alias-border-l3); }\n.dms-groupName {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dms-groupCount { flex: 0 0 auto; color: var(--dsw-alias-label-dimmed); font-weight: 400; }\n\n.dms-nameRow {\n display: flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n}\n.dms-badge {\n flex: 0 0 auto;\n padding: 0 6px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 999px;\n color: var(--dsw-alias-label-caption);\n font-size: 10px;\n line-height: 16px;\n font-weight: 500;\n}\n.dms-notice {\n flex: 0 0 auto;\n margin: 4px 0 0;\n padding: 6px 10px;\n border-radius: 8px;\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n line-height: 18px;\n}\n.dms-effort {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n width: 100%;\n min-width: 0;\n min-height: 32px;\n color: var(--dsw-alias-label-secondary);\n user-select: none;\n box-sizing: border-box;\n}\n/* \u6863\u4F4D\u8BFB\u6570\uFF1A\u62D6\u52A8\u65F6\u5B9E\u65F6\u8DDF\u968F preview\uFF0C\u66FF\u4EE3\u6B64\u524D\u53EA\u6709\u8BFB\u5C4F\u80FD\u770B\u5230\u7684 aria-valuetext\u3002 */\n.dms-effort-value {\n flex: 0 0 auto;\n margin-left: 8px;\n min-width: 3.2em;\n color: var(--dsw-alias-label-primary);\n font-size: 11px;\n line-height: 16px;\n text-align: right;\n}\n/* \u5B98\u65B9\u5951\u7EA6\u7684 efforts[].description\uFF0C\u6574\u884C\u5C55\u793A\u5728\u6ED1\u6746\u4E0B\u65B9\u3002 */\n.dms-effort-desc {\n flex: 1 0 100%;\n margin-top: 2px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n line-height: 14px;\n}\n.dms-effort-slider {\n --dms-progress: 50%;\n position: relative;\n width: 100%;\n height: 30px;\n flex: 1 1 0;\n min-width: 0;\n border-radius: 999px;\n isolation: isolate;\n transition: filter 180ms ease;\n}\n.dms-effort-track {\n position: absolute;\n inset: 0;\n overflow: hidden;\n border-radius: inherit;\n background: linear-gradient(100deg, #03040a 0%, #071126 22%, #101d4c 45%, #302262 70%, #5d35a0 100%);\n box-shadow:\n inset 0 1px 0 rgba(189, 199, 255, .15),\n inset 0 -1px 0 rgba(0, 0, 0, .55),\n 0 3px 10px rgba(12, 17, 55, .34);\n}\n.dms-effort-track::after {\n content: \"\";\n position: absolute;\n inset: 0;\n background:\n radial-gradient(circle at 18% 45%, rgba(82, 130, 255, .12), transparent 24%),\n linear-gradient(90deg, rgba(0, 0, 0, .28), transparent 42%, rgba(168, 113, 255, .12));\n pointer-events: none;\n}\n.dms-effort-fx {\n position: absolute;\n z-index: 1;\n inset: 0;\n overflow: hidden;\n border-radius: inherit;\n pointer-events: none;\n}\n.dms-effort-canvas {\n position: absolute;\n z-index: 2;\n inset: 0;\n width: 100%;\n height: 100%;\n opacity: 1;\n image-rendering: pixelated;\n mix-blend-mode: screen;\n transition: filter 140ms ease;\n}\n.dms-effort-flare {\n position: absolute;\n z-index: 3;\n transition: left 70ms linear, filter 140ms ease;\n top: 50%;\n left: var(--dms-progress);\n width: 78px;\n height: 46px;\n border-radius: 50%;\n background: radial-gradient(ellipse at 100% 50%, rgba(255,255,255,.96) 0 4%, rgba(188,189,255,.8) 11%, rgba(106,87,255,.5) 28%, rgba(105,31,255,.2) 49%, transparent 74%);\n filter: blur(2px) saturate(1.25);\n mix-blend-mode: screen;\n transform: translate(-100%, -50%);\n pointer-events: none;\n}\n.dms-effort-flare::before,\n.dms-effort-flare::after {\n content: \"\";\n position: absolute;\n inset: 50% auto auto 100%;\n border-radius: 999px;\n transform: translate(-50%, -50%);\n}\n.dms-effort-flare::before {\n width: 52px;\n height: 1px;\n background: linear-gradient(90deg, transparent, rgba(100,160,255,.42), #f1ecff, rgba(193,82,255,.65), transparent);\n box-shadow: 0 0 7px #9b7cff, 0 0 13px rgba(72,132,255,.64);\n}\n.dms-effort-flare::after {\n width: 1px;\n height: 20px;\n background: linear-gradient(180deg, transparent, rgba(196,190,255,.84), transparent);\n box-shadow: 0 0 7px #9c7cff;\n}\n.dms-effort-knob {\n position: absolute;\n z-index: 4;\n top: 50%;\n left: clamp(14px, var(--dms-progress), calc(100% - 14px));\n width: 28px;\n height: 28px;\n border: 1px solid rgba(255,255,255,.94);\n border-radius: 50%;\n background: #fff;\n box-shadow:\n 0 0 0 2px rgba(92,105,255,.12),\n 0 0 14px rgba(121,82,255,.48),\n 0 2px 7px rgba(0,0,0,.3);\n transform: translate(-50%, -50%);\n transition: left 240ms cubic-bezier(.22,1,.36,1), transform 160ms ease, box-shadow 180ms ease;\n pointer-events: none;\n}\n.dms-effort-input {\n position: absolute;\n z-index: 5;\n inset: -5px 0;\n width: 100%;\n height: calc(100% + 10px);\n margin: 0;\n opacity: 0;\n cursor: grab;\n touch-action: none;\n}\n.dms-effort-input:active { cursor: grabbing; }\n.dms-effort-input:focus-visible + .dms-effort-knob {\n outline: 2px solid var(--dsw-static-blue-400);\n outline-offset: 2px;\n}\n.dms-effort.is-dragging .dms-effort-canvas {\n filter: saturate(1.45) brightness(1.28) contrast(1.06);\n}\n.dms-effort.is-dragging .dms-effort-flare {\n filter: blur(1.5px) saturate(1.6) brightness(1.42);\n transition: none;\n}\n.dms-effort.is-dragging .dms-effort-knob {\n transform: translate(-50%, -50%) scale(1.07);\n transition: none;\n box-shadow:\n 0 0 0 3px rgba(113,115,255,.25),\n 0 0 20px rgba(74,145,255,.86),\n 0 0 31px rgba(171,53,255,.66),\n 0 3px 8px rgba(0,0,0,.32);\n}\n.dms-effort.is-error .dms-effort-slider {\n outline: 1px solid var(--dsw-alias-state-error-secondary);\n outline-offset: 2px;\n}\n.dms-effort.is-busy { opacity: .72; }\n.dms-effort-error { flex: 1 0 100%; margin-top: 8px; padding: 6px 10px; border-radius: 8px; color: var(--dsw-alias-state-error-primary, #c83e4d); background: var(--dsw-alias-state-error-tertiary, rgba(220,55,70,.08)); font-size: 11px; line-height: 1.5; }\n/* \u89C6\u89C9\u9690\u85CF\u5DE5\u5177\u7C7B\uFF08SR \u64AD\u62A5/\u9519\u8BEF\u539F\u6587\uFF1A\u4E0D\u5360\u5E03\u5C40\u4F46\u53EF\u88AB\u8BFB\u5C4F\u8BFB\u5230\uFF09\u3002 */\n.dms-sr {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n.dms-model-option {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 20px;\n align-items: center;\n gap: 8px;\n width: 100%;\n min-height: 38px;\n padding: 7px 9px;\n border: 0;\n border-radius: 9px;\n color: inherit;\n background: transparent;\n font: inherit;\n text-align: left;\n cursor: pointer;\n}\n.dms-model-option:hover { background: var(--dsw-alias-fill-tertiary, rgba(120,125,140,.09)); }\n.dms-model-option-copy { min-width: 0; }\n.dms-model-option-name { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; }\n/* \u641C\u7D22\u547D\u4E2D\u7247\u6BB5\uFF1A\u540D\u79F0\u5185\u6807\u4E0B\u5212\u7EBF\uFF08\u547D\u4E2D\u63CF\u8FF0/\u4F9B\u5E94\u5546\u65F6\u4E0D\u6807\uFF0C\u89C1 nameHit\uFF09\u3002 */\n.dms-hit {\n text-decoration: underline;\n text-decoration-color: var(--dsw-static-blue-400, #4d70ff);\n text-decoration-thickness: 2px;\n text-underline-offset: 3px;\n}\n.dms-model-option-desc { display: block; margin-top: 3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--dsw-alias-label-tertiary, #9296a0); font-size: 10px; }\n.dms-model-check { color: var(--dsw-static-deepseek-500, #4d70ff); font-size: 15px; text-align: center; }\n/* \u65B9\u5411\u952E\u5BFC\u822A\u628A\u7126\u70B9\u843D\u5728\u9009\u9879\u4E0A\uFF0C\u6B64\u524D\u6CA1\u6709\u4EFB\u4F55\u7126\u70B9\u6307\u793A\u3002 */\n.dms-model-option:focus-visible { background: var(--dsw-alias-interactive-bg-hover); }\n/* \u5F53\u524D\u9009\u4E2D\u884C\uFF1A\u4EC5\u9760\u52FE\u53F7\u4E0D\u8DB3\u4EE5\u5728\u5BC6\u96C6\u5217\u8868\u91CC\u5B9A\u4F4D\u3002 */\n.dms-model-optionSelected { background: var(--dsw-alias-interactive-bg-hover); }\n.dms-model-optionSelected .dms-model-option-name { font-weight: 600; }\n/* select \u8FDB\u884C\u4E2D\uFF1A\u5B98\u65B9\u4EE5 disabled \u53D8\u7070\u8868\u8FBE\uFF0C\u8FD9\u91CC\u7528 aria-busy \u9A71\u52A8\u540C\u6837\u7684\u89C6\u89C9\u3001\n \u4E0D\u593A\u952E\u76D8\u7126\u70B9\uFF08aria-disabled \u4FDD\u8FDE\u7EED\u6027\uFF0C\u89C1 ModelOption\uFF09\u3002 */\n.dms-menu[aria-busy=\"true\"] .dms-model-option { color: var(--dsw-alias-label-dimmed); }\n/* \u641C\u7D22\u7ED3\u679C\u91CC\u7684\u4F9B\u5E94\u5546\u6807\u662F\u533A\u5206\u8DE8\u4F9B\u5E94\u5546\u540C\u540D\u6A21\u578B\u7684\u552F\u4E00\u7EBF\u7D22\uFF0C\u4E4B\u524D\u65E0\u4EFB\u4F55\u6837\u5F0F\u3002 */\n.dms-model-option-provider {\n display: block;\n margin-top: 2px;\n overflow: hidden;\n color: var(--dsw-alias-label-dimmed, #9296a0);\n font-size: 10px;\n line-height: 14px;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n@keyframes dms-menu-in {\n from { opacity: 0; transform: translateY(5px) scale(.98); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n}\n@keyframes dms-menu-in-below {\n from { opacity: 0; transform: translateY(-5px) scale(.98); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n}\nbody:not([data-ds-dark-theme]) .dms-effort-slider {\n filter: none;\n}\nbody:not([data-ds-dark-theme]) .dms-effort-track {\n background: var(--dsw-static-blue-75, #e5f0ff);\n box-shadow:\n inset 0 1px 0 rgba(255,255,255,.9),\n inset 0 0 0 1px rgba(80,133,194,.14),\n 0 3px 10px rgba(48,101,165,.13);\n}\nbody:not([data-ds-dark-theme]) .dms-effort-track::before {\n content: \"\";\n position: absolute;\n z-index: 0;\n inset: 0 auto 0 0;\n width: var(--dms-progress);\n border-radius: inherit;\n background: linear-gradient(90deg, #fff 0%, #e2f0ff 20%, #a8d0fb 57%, #438fdf 100%);\n transition: width 240ms cubic-bezier(.22,1,.36,1);\n}\nbody:not([data-ds-dark-theme]) .dms-effort.is-dragging .dms-effort-track::before {\n transition: none;\n}\nbody:not([data-ds-dark-theme]) .dms-effort-track::after {\n z-index: 1;\n background: linear-gradient(90deg, rgba(255,255,255,.48), transparent 34%, rgba(23,101,201,.07));\n}\nbody:not([data-ds-dark-theme]) .dms-effort-canvas {\n opacity: .78;\n mix-blend-mode: multiply;\n}\nbody:not([data-ds-dark-theme]) .dms-effort-flare {\n background: radial-gradient(ellipse at 100% 50%, rgba(255,255,255,.98) 0 5%, rgba(204,231,255,.88) 13%, rgba(91,162,241,.48) 31%, rgba(37,111,207,.16) 53%, transparent 75%);\n filter: blur(2px) saturate(1.12);\n}\nbody:not([data-ds-dark-theme]) .dms-effort-flare::before {\n background: linear-gradient(90deg, transparent, rgba(116,177,244,.34), #fff, rgba(66,139,225,.58), transparent);\n box-shadow: 0 0 7px rgba(58,133,222,.5), 0 0 13px rgba(104,176,255,.38);\n}\nbody:not([data-ds-dark-theme]) .dms-effort-flare::after {\n background: linear-gradient(180deg, transparent, rgba(255,255,255,.94), transparent);\n box-shadow: 0 0 7px rgba(64,137,224,.44);\n}\nbody:not([data-ds-dark-theme]) .dms-effort-knob {\n border-color: rgba(126,160,197,.32);\n box-shadow:\n 0 0 0 2px rgba(58,124,207,.09),\n 0 0 13px rgba(48,118,207,.3),\n 0 3px 8px rgba(39,77,119,.18);\n}\nbody:not([data-ds-dark-theme]) .dms-effort.is-dragging .dms-effort-knob {\n box-shadow:\n 0 0 0 3px rgba(36,105,192,.15),\n 0 0 20px rgba(25,100,201,.45),\n 0 3px 8px rgba(39,77,119,.18);\n}\n@media (prefers-reduced-motion: reduce) {\n .dms-chevron,\n .dms-groupChevron,\n .dms-effort-slider,\n .dms-effort-canvas,\n .dms-effort-knob,\n .dms-effort-flare,\n body:not([data-ds-dark-theme]) .dms-effort-track::before { transition: none; }\n .dms-menu { animation: none; }\n}\n\n/* Inline effort footer pinned below the scrollable model list (single-pane\n menu: switching models and adjusting effort both live in one surface). */\n.dms-effortFooter {\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 4px 4px 0 0;\n padding: 6px 10px;\n border-top: 1px solid var(--dsw-alias-border-l2);\n}\n.dms-effortFooterLabel {\n flex: 0 0 auto;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n line-height: 18px;\n white-space: nowrap;\n}\n.dms-effortFooter .dms-effort { flex: 1 1 auto; min-width: 0; }\n\n";
10
+ //# sourceMappingURL=styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../src/client/styles.ts"],"names":[],"mappings":"AAAA;;;;;;;EAOE;AACF,eAAO,MAAM,GAAG,24kBA8kBf,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * dsh-model-selector — host half.
3
+ *
4
+ * Pure UI plugin: the empty apply exists so the plugin appears in the host
5
+ * Loader (and its `dsh.client` declaration is scanned into the browser
6
+ * roster); the browser half ships via `exports["./client"]`.
7
+ */
8
+ import type { Context } from '@deepseek-ai/cordis';
9
+ export declare const name = "dsh-model-selector";
10
+ export declare const inject: string[];
11
+ /** Host plugin body — no host-side behavior for this surface plugin. */
12
+ export declare function apply(_ctx: Context): void;
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAElD,eAAO,MAAM,IAAI,uBAAuB,CAAA;AAExC,eAAO,MAAM,MAAM,EAAE,MAAM,EAAO,CAAA;AAElC,wEAAwE;AACxE,wBAAgB,KAAK,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAG"}
package/package.json ADDED
@@ -0,0 +1,126 @@
1
+ {
2
+ "name": "@bittersmilezzz/dsh-model-selector",
3
+ "version": "0.1.18",
4
+ "description": "DeepSeek Harness 的增强模型选择器:单层菜单(搜索 + 分组)+ 底部内联推理强度(Effort)滑杆。",
5
+ "type": "module",
6
+ "main": "lib/index.js",
7
+ "types": "lib/types/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./lib/types/index.d.ts",
11
+ "default": "./lib/index.js"
12
+ },
13
+ "./client": {
14
+ "types": "./lib/types/client/index.d.ts",
15
+ "default": "./lib/client.js"
16
+ },
17
+ "./cordis.patch.yml": "./cordis.patch.yml",
18
+ "./package.json": "./package.json"
19
+ },
20
+ "files": [
21
+ "lib",
22
+ "cordis.patch.yml",
23
+ "README.md",
24
+ "LICENSE",
25
+ "assets"
26
+ ],
27
+ "scripts": {
28
+ "build": "tsc -p tsconfig.host.json && tsdown && tsc -p tsconfig.client.build.json",
29
+ "bundle": "tsdown",
30
+ "watch": "tsdown --watch",
31
+ "typecheck": "tsc -p tsconfig.host.json --noEmit && tsc -p tsconfig.client.json --noEmit",
32
+ "test": "node --test test/*.test.mjs"
33
+ },
34
+ "license": "MIT",
35
+ "keywords": [
36
+ "dsh",
37
+ "dsh-plugin",
38
+ "deepseek-harness",
39
+ "ui",
40
+ "model-selector",
41
+ "reasoning",
42
+ "effort"
43
+ ],
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "git+https://github.com/bitterSmilezzz/dsh-model-selector.git"
47
+ },
48
+ "homepage": "https://github.com/bitterSmilezzz/dsh-model-selector#readme",
49
+ "bugs": {
50
+ "url": "https://github.com/bitterSmilezzz/dsh-model-selector/issues"
51
+ },
52
+ "publishConfig": {
53
+ "access": "public",
54
+ "registry": "https://registry.npmjs.org/"
55
+ },
56
+ "dsh": {
57
+ "bundle": {
58
+ "patch": "./cordis.patch.yml"
59
+ },
60
+ "searchTerms": [
61
+ "模型选择",
62
+ "模型",
63
+ "推理强度",
64
+ "effort",
65
+ "model selector"
66
+ ],
67
+ "client": {
68
+ "platform": "web",
69
+ "inject": [
70
+ "@deepseek-ai/dsh-client-ui-slots",
71
+ "@deepseek-ai/dsh-client-ui-conversation",
72
+ "@deepseek-ai/dsh-client-locale",
73
+ "@deepseek-ai/dsh-client-ui-model-selection",
74
+ "@deepseek-ai/dsh-client-ui-primitives"
75
+ ]
76
+ }
77
+ },
78
+ "peerDependencies": {
79
+ "@deepseek-ai/cordis": "^4.0.2",
80
+ "@deepseek-ai/dsh-api-session-controller": "^0.1.5-rc.2",
81
+ "@deepseek-ai/dsh-client-locale": "^0.1.5-rc.2",
82
+ "@deepseek-ai/dsh-client-ui-conversation": "^0.1.5-rc.2",
83
+ "@deepseek-ai/dsh-client-ui-model-selection": "^0.1.5-rc.2",
84
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.5-rc.2",
85
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.1.5-rc.2",
86
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.5-rc.2",
87
+ "react": "^18.2.0",
88
+ "react-dom": "^18.2.0",
89
+ "@deepseek-ai/dsh-client-store": "^0.1.5-rc.2",
90
+ "@deepseek-ai/dsh-session": "^0.1.5-rc.2"
91
+ },
92
+ "peerDependenciesMeta": {
93
+ "@deepseek-ai/dsh-client-ui-primitives": {
94
+ "optional": true
95
+ },
96
+ "@deepseek-ai/dsh-client-ui-slots": {
97
+ "optional": true
98
+ },
99
+ "react": {
100
+ "optional": true
101
+ },
102
+ "react-dom": {
103
+ "optional": true
104
+ },
105
+ "@deepseek-ai/dsh-client-store": {
106
+ "optional": true
107
+ }
108
+ },
109
+ "devDependencies": {
110
+ "@deepseek-ai/cordis": "^4.0.2",
111
+ "@deepseek-ai/dsh-api-session-controller": "^0.1.5-rc.2",
112
+ "@deepseek-ai/dsh-client-locale": "^0.1.5-rc.2",
113
+ "@deepseek-ai/dsh-client-store": "^0.1.5-rc.2",
114
+ "@deepseek-ai/dsh-client-ui-conversation": "^0.1.5-rc.2",
115
+ "@deepseek-ai/dsh-client-ui-model-selection": "^0.1.5-rc.2",
116
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.5-rc.2",
117
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.1.5-rc.2",
118
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.5-rc.2",
119
+ "@deepseek-ai/dsh-session": "^0.1.5-rc.2",
120
+ "@types/node": "^26.2.0",
121
+ "@types/react": "~18.3.31",
122
+ "@types/react-dom": "~18.3.7",
123
+ "tsdown": "^0.22.14",
124
+ "typescript": "^6.0.3"
125
+ }
126
+ }