dsh-model-accordion 0.1.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/LICENSE +21 -0
- package/README.md +54 -0
- package/cordis.patch.yml +4 -0
- package/lib/client.js +223 -0
- package/lib/index.js +8 -0
- package/package.json +62 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dsh-model-accordion contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# dsh-model-accordion
|
|
2
|
+
|
|
3
|
+
Provider-folded model selector for the DeepSeek Harness Web composer.
|
|
4
|
+
|
|
5
|
+
## What it does
|
|
6
|
+
|
|
7
|
+
- Replaces the single composer model seat with a provider-folded selector.
|
|
8
|
+
- Keeps provider groups collapsed by default and opens models on demand.
|
|
9
|
+
- Reads reasoning-effort choices from each model's resolved catalog metadata instead of maintaining a hard-coded effort list.
|
|
10
|
+
- Sends model and reasoning-effort selections through DSH's shared model-directory service.
|
|
11
|
+
- Wraps vision-router mirror providers in one collapsed `识图镜像(带图会话)` section when those providers are present.
|
|
12
|
+
- Keeps the popup height-bounded with an internal scroll area and wraps effort controls below the model name.
|
|
13
|
+
- Uses DSH semantic theme tokens for colors and supports light/dark theme changes.
|
|
14
|
+
|
|
15
|
+
## Requirements
|
|
16
|
+
|
|
17
|
+
- DeepSeek Harness Web `0.1.0-rc.8` or newer.
|
|
18
|
+
- A Web profile with the official model-selection package and model-directory service.
|
|
19
|
+
- React 18 supplied by the DSH Web runtime.
|
|
20
|
+
|
|
21
|
+
This is a Web UI plugin. It does not add a Host service, model provider, vision backend, or model catalog. Provider availability and image-session admission remain controlled by DSH and any installed provider/vision plugins.
|
|
22
|
+
|
|
23
|
+
## Install from a package or repository
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
dsh plugin --profile web add dsh-model-accordion
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
For a local checkout during development:
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
dsh plugin --profile web add file:/absolute/path/to/dsh-model-accordion
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Refresh the Web UI after installation. The package declares a `dsh.bundle` patch and a Web client entry, so it is installed and loaded as a persistent profile bundle rather than a temporary runtime extension.
|
|
36
|
+
|
|
37
|
+
## Behavior and limitations
|
|
38
|
+
|
|
39
|
+
- The selector submits the exact provider, model, and catalog-declared reasoning effort returned by the DSH model directory.
|
|
40
|
+
- A selection can still be rejected by the DSH host when the session contains images and the selected model does not declare image input. That is a host/model-capability rule, not a UI override.
|
|
41
|
+
- The optional `识图镜像(带图会话)` section is shown when provider names identify vision-router mirror routes. It is kept collapsed to avoid duplicating every provider in the main list.
|
|
42
|
+
- The plugin currently uses English fallback status text and a Chinese label for the vision-mirror section; full locale integration is planned for a later release.
|
|
43
|
+
|
|
44
|
+
## Development checks
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
node --check lib/client.js
|
|
48
|
+
node --check lib/index.js
|
|
49
|
+
npm pack --dry-run --ignore-scripts
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## License
|
|
53
|
+
|
|
54
|
+
MIT
|
package/cordis.patch.yml
ADDED
package/lib/client.js
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "dsh-model-accordion",
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
var module = { exports: {} };
|
|
5
|
+
var exports = module.exports;
|
|
6
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
const React = require("react");
|
|
8
|
+
|
|
9
|
+
// CSS is self-contained and theme-token driven (mirrors the shipped
|
|
10
|
+
// model-selection geometry). The popup scroll region carries its own
|
|
11
|
+
// max-height so the menu is ALWAYS height-bounded and scrolls internally,
|
|
12
|
+
// independent of any ancestor flex/layout context.
|
|
13
|
+
const CSS = `
|
|
14
|
+
.dshma-root{position:relative;min-width:0}
|
|
15
|
+
.dshma-trigger{box-sizing:border-box;display:flex;align-items:center;gap:4px;height:28px;max-width:min(360px,45cqw);padding:0 4px 0 8px;border:none;border-radius:24px;background:transparent;color:var(--dsw-alias-label-secondary);font-size:13px;font-weight:500;line-height:20px;cursor:pointer;outline:none;min-width:0}
|
|
16
|
+
.dshma-trigger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}
|
|
17
|
+
.dshma-trigger:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3)}
|
|
18
|
+
.dshma-trigger:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}
|
|
19
|
+
.dshma-trigger-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
|
|
20
|
+
.dshma-trigger-effort{color:var(--dsw-alias-label-caption);flex:none}
|
|
21
|
+
.dshma-chevron{color:var(--dsw-alias-label-caption);flex:none;transition:transform .12s}
|
|
22
|
+
.dshma-chevron-open{transform:rotate(180deg)}
|
|
23
|
+
.dshma-menu{box-sizing:border-box;z-index:50;position:absolute;bottom:calc(100% + 8px);right:0;width:max-content;min-width:min(240px,100vw - 32px);max-width:min(420px,100vw - 32px);padding:4px;border:1px solid var(--dsw-alias-border-inverted);background:var(--dsw-specific-menu);border-radius:12px;box-shadow:var(--dsw-shadow-lv3);color:var(--dsw-alias-label-primary);display:flex;flex-direction:column;overflow:hidden}
|
|
24
|
+
.dshma-menu-scroll{box-sizing:border-box;max-height:min(340px,calc(100vh - 120px));overflow-y:auto;display:flex;flex-direction:column;min-width:0;-webkit-overflow-scrolling:touch}
|
|
25
|
+
.dshma-status,.dshma-empty{color:var(--dsw-alias-label-tertiary);padding:10px;font-size:13px;line-height:20px}
|
|
26
|
+
.dshma-error{background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary);border-radius:8px;margin-bottom:4px;padding:7px 8px;font-size:12px;line-height:18px}
|
|
27
|
+
.dshma-provider{border-radius:10px;overflow:hidden;flex:none}
|
|
28
|
+
.dshma-vision{margin-top:4px;border-top:1px solid var(--dsw-alias-border-l3);padding-top:4px}
|
|
29
|
+
.dshma-provider-head{box-sizing:border-box;width:100%;display:flex;align-items:center;gap:7px;padding:8px;border:none;border-radius:10px;background:transparent;color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:600;line-height:18px;text-align:left;cursor:pointer;font-family:inherit}
|
|
30
|
+
.dshma-provider-head:hover{background:var(--dsw-alias-interactive-bg-hover)}
|
|
31
|
+
.dshma-provider-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
32
|
+
.dshma-count{color:var(--dsw-alias-label-caption);font-size:11px;font-weight:500;flex:none}
|
|
33
|
+
.dshma-provider-chevron{color:var(--dsw-alias-label-caption);flex:none;transition:transform .12s}
|
|
34
|
+
.dshma-provider-chevron-open{transform:rotate(180deg)}
|
|
35
|
+
.dshma-models{padding:0 4px 4px}
|
|
36
|
+
.dshma-option{box-sizing:border-box;width:100%;padding:7px 8px;border:none;border-radius:8px;background:transparent;color:var(--dsw-alias-label-primary);text-align:left;cursor:pointer;display:block}
|
|
37
|
+
.dshma-option:hover{background:var(--dsw-alias-interactive-bg-hover)}
|
|
38
|
+
.dshma-option-selected{background:var(--dsw-alias-interactive-bg-hover)}
|
|
39
|
+
.dshma-option-row{display:flex;align-items:center;gap:8px;min-width:0;width:100%;border:none;background:transparent;padding:0;color:inherit;cursor:pointer;font-family:inherit;text-align:left}
|
|
40
|
+
.dshma-option-main{flex:1;min-width:0}
|
|
41
|
+
.dshma-option-name{font-size:13px;font-weight:500;line-height:18px;overflow-wrap:anywhere;display:block}
|
|
42
|
+
.dshma-option-desc{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px;overflow-wrap:anywhere;display:block}
|
|
43
|
+
.dshma-check{color:var(--dsw-alias-label-secondary);flex:none;font-size:14px}
|
|
44
|
+
.dshma-efforts{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px;padding-left:0}
|
|
45
|
+
.dshma-effort{box-sizing:border-box;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:var(--dsw-alias-bg-module-platform);border:1px solid var(--dsw-alias-border-l3);border-radius:8px;padding:2px 7px;font-size:11px;line-height:16px;font-family:inherit}
|
|
46
|
+
.dshma-effort:hover{color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-interactive-bg-hover)}
|
|
47
|
+
.dshma-effort-selected{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-secondary)}
|
|
48
|
+
.dshma-failure{color:var(--dsw-alias-label-tertiary);border-radius:8px;padding:7px 8px;font-size:12px;line-height:18px}
|
|
49
|
+
`;
|
|
50
|
+
|
|
51
|
+
function Chevron(props) {
|
|
52
|
+
return React.createElement("svg", { className: props.className || "dshma-chevron", width: 14, height: 14, viewBox: "0 0 14 14", fill: "none", "aria-hidden": "true" },
|
|
53
|
+
React.createElement("path", { d: "M3.5 5.25 7 8.75l3.5-3.5", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round" })
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function useStore(store) {
|
|
58
|
+
return React.useSyncExternalStore(
|
|
59
|
+
(fn) => store.subscribe(fn),
|
|
60
|
+
() => store.getSnapshot(),
|
|
61
|
+
() => store.getSnapshot()
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function effortOptions(model) {
|
|
66
|
+
const es = model && model.reasoning && Array.isArray(model.reasoning.efforts) ? model.reasoning.efforts : [];
|
|
67
|
+
return es.filter((e) => e && typeof e.id === "string");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function Accordion(props) {
|
|
71
|
+
const state = useStore(props.directory);
|
|
72
|
+
const [open, setOpen] = React.useState(false);
|
|
73
|
+
const [expanded, setExpanded] = React.useState({});
|
|
74
|
+
const [busy, setBusy] = React.useState(false);
|
|
75
|
+
const [failure, setFailure] = React.useState(null);
|
|
76
|
+
const groups = Array.isArray(state.groups) ? state.groups : [];
|
|
77
|
+
const rootRef = React.useRef(null);
|
|
78
|
+
const [visionOpen, setVisionOpen] = React.useState(false);
|
|
79
|
+
// Vision-router twin detection: only treat a group as the auto-vision
|
|
80
|
+
// wrapper when its display name carries the 自动识图 token or its provider
|
|
81
|
+
// id ends in "-vision" (official vision-router uses route id
|
|
82
|
+
// "deepseek-vision" + display "DeepSeek + 自动识图").
|
|
83
|
+
const isTwin = (g) => /自动识图/.test(g.name || "") || /(?:-|\b)vision$/i.test((g.id || "").trim());
|
|
84
|
+
const mainGroups = groups.filter((g) => !isTwin(g));
|
|
85
|
+
const visionGroups = groups.filter(isTwin);
|
|
86
|
+
|
|
87
|
+
React.useEffect(() => {
|
|
88
|
+
if (!open) return;
|
|
89
|
+
const onDown = (e) => { if (rootRef.current && !rootRef.current.contains(e.target)) setOpen(false); };
|
|
90
|
+
const onKey = (e) => { if (e.key === "Escape") setOpen(false); };
|
|
91
|
+
document.addEventListener("mousedown", onDown);
|
|
92
|
+
document.addEventListener("keydown", onKey);
|
|
93
|
+
return () => { document.removeEventListener("mousedown", onDown); document.removeEventListener("keydown", onKey); };
|
|
94
|
+
}, [open]);
|
|
95
|
+
|
|
96
|
+
React.useEffect(() => { if (open && props.available) props.load(); }, [open, props.available]);
|
|
97
|
+
|
|
98
|
+
const select = (group, model, effort) => {
|
|
99
|
+
if (!props.available || busy) return;
|
|
100
|
+
setBusy(true);
|
|
101
|
+
setFailure(null);
|
|
102
|
+
const sel = { provider: group.id, model: model.id };
|
|
103
|
+
if (effort !== void 0) sel.reasoningEffort = effort;
|
|
104
|
+
props.select(sel).then((ok) => {
|
|
105
|
+
if (!ok) throw new Error("model selection failed");
|
|
106
|
+
setOpen(false);
|
|
107
|
+
}).catch((e) => {
|
|
108
|
+
setFailure(e && e.message ? e.message : "model selection failed");
|
|
109
|
+
}).finally(() => setBusy(false));
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const current = state.current;
|
|
113
|
+
const curGroup = groups.find((g) => g.id === current?.provider);
|
|
114
|
+
const curModel = curGroup ? curGroup.models.find((m) => m.id === current?.model) : void 0;
|
|
115
|
+
const label = curModel ? curModel.name : (current ? `${current.provider}/${current.model}` : "Select model");
|
|
116
|
+
const curEffort = curModel && current && current.provider === curGroup.id && current.model === curModel.id
|
|
117
|
+
? (current.reasoningEffort || (curModel.reasoning && curModel.reasoning.defaultEffort))
|
|
118
|
+
: void 0;
|
|
119
|
+
|
|
120
|
+
const renderGroup = (group) => {
|
|
121
|
+
const isOpen = expanded[group.id] === true;
|
|
122
|
+
return React.createElement("div", { className: "dshma-provider", key: group.id },
|
|
123
|
+
React.createElement("button", { type: "button", className: "dshma-provider-head", onClick: () => setExpanded((old) => ({ ...old, [group.id]: !isOpen })), "aria-expanded": isOpen },
|
|
124
|
+
React.createElement(Chevron, { className: `dshma-provider-chevron${isOpen ? " dshma-provider-chevron-open" : ""}` }),
|
|
125
|
+
React.createElement("span", { className: "dshma-provider-name" }, group.name || group.id),
|
|
126
|
+
React.createElement("span", { className: "dshma-count" }, `${group.models.length}`)
|
|
127
|
+
),
|
|
128
|
+
isOpen ? React.createElement("div", { className: "dshma-models" }, group.models.map((model) => {
|
|
129
|
+
const selected = current && current.provider === group.id && current.model === model.id;
|
|
130
|
+
const efforts = effortOptions(model);
|
|
131
|
+
const defEffort = model.reasoning && model.reasoning.defaultEffort;
|
|
132
|
+
// A "provider default" chip clears a pinned effort so the provider's
|
|
133
|
+
// built-in default applies again (mirrors the official provider-default
|
|
134
|
+
// entry in dsh-client-ui-model-selection @315-324).
|
|
135
|
+
const defaultChip = defEffort !== void 0 ? [{ id: "__provider_default__", name: "默认" }] : [];
|
|
136
|
+
const chips = defaultChip.concat(efforts);
|
|
137
|
+
// reason about the currently active effort: a pinned explicit effort
|
|
138
|
+
// wins over the provider's default; otherwise provider default applies.
|
|
139
|
+
const pinnedEffort = selected ? current.reasoningEffort : void 0;
|
|
140
|
+
return React.createElement("div", { className: `dshma-option${selected ? " dshma-option-selected" : ""}`, key: model.id },
|
|
141
|
+
React.createElement("button", { type: "button", className: "dshma-option-row", onClick: () => {
|
|
142
|
+
// Re-clicking the already-selected model must NOT re-submit and
|
|
143
|
+
// thereby wipe a custom (pinned) effort — just close the menu.
|
|
144
|
+
// Mirrors dsh-client-ui-model-selection @397-400 / @718.
|
|
145
|
+
if (selected) { setOpen(false); return; }
|
|
146
|
+
select(group, model, defEffort);
|
|
147
|
+
}, disabled: busy },
|
|
148
|
+
React.createElement("span", { className: "dshma-option-main" },
|
|
149
|
+
React.createElement("span", { className: "dshma-option-name" }, model.name || model.id),
|
|
150
|
+
model.description ? React.createElement("span", { className: "dshma-option-desc" }, model.description) : null
|
|
151
|
+
),
|
|
152
|
+
selected ? React.createElement("span", { className: "dshma-check", "aria-label": "selected" }, "✓") : null
|
|
153
|
+
),
|
|
154
|
+
chips.length ? React.createElement("div", { className: "dshma-efforts", "aria-label": "Reasoning effort" }, chips.map((it) => React.createElement("button", { type: "button", key: it.id, className: `dshma-effort${selected && (it.id === "__provider_default__" ? !current.reasoningEffort : pinnedEffort === it.id) ? " dshma-effort-selected" : ""}`, onClick: () => select(group, model, it.id === "__provider_default__" ? void 0 : it.id), disabled: busy }, it.name || it.id))) : null
|
|
155
|
+
);
|
|
156
|
+
})) : null
|
|
157
|
+
);
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
return React.createElement("div", { className: "dshma-root", ref: rootRef },
|
|
161
|
+
React.createElement("button", { type: "button", className: "dshma-trigger", disabled: props.locked || !props.available || busy, onClick: () => setOpen((v) => !v), "aria-expanded": open, "aria-haspopup": "menu" },
|
|
162
|
+
React.createElement("span", { className: "dshma-trigger-label" }, label),
|
|
163
|
+
curEffort ? React.createElement("span", { className: "dshma-trigger-effort" }, `· ${curEffort}`) : null,
|
|
164
|
+
React.createElement(Chevron, { className: `dshma-chevron${open ? " dshma-chevron-open" : ""}` })
|
|
165
|
+
),
|
|
166
|
+
open ? React.createElement("div", { className: "dshma-menu", role: "menu" },
|
|
167
|
+
React.createElement("div", { className: "dshma-menu-scroll" },
|
|
168
|
+
failure ? React.createElement("div", { className: "dshma-error" }, failure) : null,
|
|
169
|
+
state.error ? React.createElement("div", { className: "dshma-error" }, state.error) : null,
|
|
170
|
+
state.status === "loading" ? React.createElement("div", { className: "dshma-status" }, "Loading models…") : null,
|
|
171
|
+
(state.status === "selecting" || busy) ? React.createElement("div", { className: "dshma-status" }, "Selecting…") : null,
|
|
172
|
+
state.status !== "loading" && mainGroups.length === 0 && visionGroups.length === 0 ? React.createElement("div", { className: "dshma-empty" }, "No models available") : null,
|
|
173
|
+
mainGroups.map(renderGroup),
|
|
174
|
+
visionGroups.length ? React.createElement("div", { className: "dshma-vision", key: "__vision__" },
|
|
175
|
+
React.createElement("button", { type: "button", className: "dshma-provider-head", onClick: () => setVisionOpen((v) => !v), "aria-expanded": visionOpen },
|
|
176
|
+
React.createElement(Chevron, { className: `dshma-provider-chevron${visionOpen ? " dshma-provider-chevron-open" : ""}` }),
|
|
177
|
+
React.createElement("span", { className: "dshma-provider-name" }, "识图镜像(带图会话)"),
|
|
178
|
+
React.createElement("span", { className: "dshma-count" }, `${visionGroups.length}`)
|
|
179
|
+
),
|
|
180
|
+
visionOpen ? React.createElement("div", { className: "dshma-models" }, visionGroups.map(renderGroup)) : null
|
|
181
|
+
) : null
|
|
182
|
+
)
|
|
183
|
+
) : null
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const inject = ["slots", "modelDirectories", "sessions"];
|
|
188
|
+
|
|
189
|
+
function injectCss() {
|
|
190
|
+
if (typeof document === "undefined") return () => {};
|
|
191
|
+
const prev = document.querySelector('style[data-dshma-css]');
|
|
192
|
+
if (prev) prev.remove();
|
|
193
|
+
const tag = document.createElement("style");
|
|
194
|
+
tag.setAttribute("data-dshma-css", "1");
|
|
195
|
+
tag.textContent = CSS;
|
|
196
|
+
document.head.appendChild(tag);
|
|
197
|
+
return () => tag.remove();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function apply(ctx) {
|
|
201
|
+
const cssDispose = ctx.effect(injectCss, "dsh-model-accordion: styles");
|
|
202
|
+
ctx.slots.inject("conversation.input.model", () => ctx.slots.register({
|
|
203
|
+
name: "conversation.input.model",
|
|
204
|
+
priority: -1,
|
|
205
|
+
inject: (sessionId) => {
|
|
206
|
+
const directory = ctx.modelDirectories.directoryFor(sessionId);
|
|
207
|
+
const available = ctx.sessions.subagentAddress(sessionId) === void 0;
|
|
208
|
+
return {
|
|
209
|
+
available,
|
|
210
|
+
directory: directory.store,
|
|
211
|
+
load: () => { if (available) directory.load().catch(() => {}); },
|
|
212
|
+
select: (selection) => available ? directory.select(selection).then(() => true, () => false) : Promise.resolve(false)
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
}, Accordion));
|
|
216
|
+
return cssDispose;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
exports.apply = apply;
|
|
220
|
+
exports.inject = inject;
|
|
221
|
+
return module.exports;
|
|
222
|
+
}
|
|
223
|
+
});
|
package/lib/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dsh-model-accordion",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Provider-folded model selector for the DSH Web composer with catalog-driven reasoning effort choices.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"deepseek-harness",
|
|
7
|
+
"dsh",
|
|
8
|
+
"dsh-plugin",
|
|
9
|
+
"model-selector",
|
|
10
|
+
"reasoning-effort"
|
|
11
|
+
],
|
|
12
|
+
"type": "module",
|
|
13
|
+
"main": "lib/index.js",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": "./lib/index.js",
|
|
16
|
+
"./client": "./lib/client.js",
|
|
17
|
+
"./package.json": "./package.json"
|
|
18
|
+
},
|
|
19
|
+
"dsh": {
|
|
20
|
+
"bundle": {
|
|
21
|
+
"patch": "./cordis.patch.yml"
|
|
22
|
+
},
|
|
23
|
+
"client": {
|
|
24
|
+
"inject": [
|
|
25
|
+
"@deepseek-ai/dsh-client-runtime",
|
|
26
|
+
"@deepseek-ai/dsh-client-locale",
|
|
27
|
+
"@deepseek-ai/dsh-client-ui-theme",
|
|
28
|
+
"@deepseek-ai/dsh-client-ui-model-selection"
|
|
29
|
+
],
|
|
30
|
+
"platform": "web"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"react": "^18.2.0"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"lib",
|
|
38
|
+
"cordis.patch.yml",
|
|
39
|
+
"README.md",
|
|
40
|
+
"LICENSE",
|
|
41
|
+
"package.json"
|
|
42
|
+
],
|
|
43
|
+
"license": "MIT",
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=22"
|
|
46
|
+
},
|
|
47
|
+
"repository": {
|
|
48
|
+
"type": "git",
|
|
49
|
+
"url": "https://github.com/lakabuji-arch/dsh-model-accordion.git"
|
|
50
|
+
},
|
|
51
|
+
"homepage": "https://github.com/lakabuji-arch/dsh-model-accordion#readme",
|
|
52
|
+
"bugs": {
|
|
53
|
+
"url": "https://github.com/lakabuji-arch/dsh-model-accordion/issues"
|
|
54
|
+
},
|
|
55
|
+
"publishConfig": {
|
|
56
|
+
"registry": "https://registry.npmjs.org/"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"check": "node --check lib/client.js && node --check lib/index.js",
|
|
60
|
+
"test": "node --test tests/package.test.js"
|
|
61
|
+
}
|
|
62
|
+
}
|