@klarkxy/dsh-model-hub 0.1.4 → 0.1.6
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.md +6 -6
- package/docs/README.zh-CN.md +8 -8
- package/lib/client.inner.cjs +62 -26
- package/lib/client.inner.cjs.map +1 -1
- package/lib/client.js +62 -26
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
[简体中文](docs/README.zh-CN.md)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
View and change the models your DeepSeek Harness plugins use, control which models subagents may use, and track the model and reasoning effort of each running subagent — all on one page.
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
@@ -18,16 +18,16 @@ Replace `web` with your profile name and restart the profile.
|
|
|
18
18
|
|
|
19
19
|
Open **Plugins → Model Hub**.
|
|
20
20
|
|
|
21
|
-
- **Fields**: every model setting exposed by installed plugins, such as Auto Title, Git Commit, and Safe Auto. Search by plugin, purpose, or current model, then pick a new model.
|
|
22
|
-
- **Subagent Cast**:
|
|
21
|
+
- **Fields**: every model setting exposed by installed plugins, such as Auto Title, Git Commit, and Safe Auto. Search by plugin, purpose, or current model, then pick a new model. The plugin that owns the setting saves the change.
|
|
22
|
+
- **Subagent Cast**: toggle the subagent model allowlist and add, replace, or remove models. When enabled with at least one model, it guides the agent to discover the models available in the current conversation and pick one explicitly when delegating. For independent reviews and alternative approaches it favors a different model when suitable, but allows the same one when it fits better. Per-model task tendencies you add are optional hints; none are supplied by default. Below the list, a live view shows each running subagent with its current model and reasoning effort; an effort marked adapter default comes from the adapter, not an explicit choice.
|
|
23
23
|
|
|
24
24
|
## Limits
|
|
25
25
|
|
|
26
26
|
- Only plugins that expose model settings appear.
|
|
27
27
|
- Changes made elsewhere update the page automatically. If an edit conflicts with a newer change, refresh and choose again.
|
|
28
|
-
- If the model list cannot load, use **Retry**. The last available list stays visible; warnings
|
|
29
|
-
-
|
|
30
|
-
- Guidance
|
|
28
|
+
- If the model list cannot load, use **Retry**. The last available list stays visible; warnings name providers that failed while others stay usable.
|
|
29
|
+
- Selection guidance needs host tools that support choosing a subagent model. List changes apply to new conversations; existing conversations and their subagents keep their saved lists. Refreshing the settings page does not change a conversation's list. Omitting an explicit model can still inherit the parent model.
|
|
30
|
+
- Guidance never forces a model choice or adds subtasks just for variety.
|
|
31
31
|
- Remote subagents and finished runs have no readable route; the live list covers only live local subagents.
|
|
32
32
|
- No usage statistics.
|
|
33
33
|
|
package/docs/README.zh-CN.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
[English](../README.md)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
在一个页面查看并修改各 DeepSeek Harness 插件使用的模型,管理子代理可用的模型,并跟踪运行中子代理的模型与思考强度。
|
|
8
8
|
|
|
9
9
|
## 安装
|
|
10
10
|
|
|
@@ -18,16 +18,16 @@ dsh plugin --profile web add @klarkxy/dsh-model-hub
|
|
|
18
18
|
|
|
19
19
|
打开「插件 → 模型枢纽」。
|
|
20
20
|
|
|
21
|
-
- **字段总览**:列出已安装插件提供的模型设置,例如自动标题、Git
|
|
22
|
-
-
|
|
21
|
+
- **字段总览**:列出已安装插件提供的模型设置,例如自动标题、Git 提交和安全自动。可按插件、用途或当前模型搜索,再选择新模型;改动由对应插件保存。
|
|
22
|
+
- **子代理阵容**:开关子代理模型白名单,添加、替换或移除模型。开启且至少有一个模型时,会引导智能体发现当前会话可用的模型,并在派发时显式选择。独立复核和方案对比会优先考虑合适的不同模型,同模型更适合时仍可使用。自填的模型「任务倾向」只作可选参考,插件不预置任何倾向。列表下方实时显示运行中的子代理及其当前模型和思考强度;标注「适配器默认」的强度来自适配器,而非显式选择。
|
|
23
23
|
|
|
24
24
|
## 限制
|
|
25
25
|
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
26
|
+
- 只显示提供模型设置的插件。
|
|
27
|
+
- 别处改动设置时页面自动更新;编辑与较新的改动冲突时,刷新后重新选择。
|
|
28
|
+
- 模型列表读取失败时点「重试」。上次可用的列表保留;部分提供方读取失败会显示提示,其余提供方仍可用。
|
|
29
|
+
- 选模引导需要宿主工具支持选择子代理模型。名单修改对新建会话生效,已有会话及其子代理沿用原名单;刷新设置页面不会更新会话名单。不显式指定模型时仍可继承父代理模型。
|
|
30
|
+
- 引导不强制选模,也不为增加模型种类而新增子任务。
|
|
31
31
|
- 远程子代理和已结束的子代理没有可读取的路由;运行列表只覆盖存活的本地子代理。
|
|
32
32
|
- 不提供用量统计。
|
|
33
33
|
|
package/lib/client.inner.cjs
CHANGED
|
@@ -197,7 +197,14 @@ function groupModelMenuChoices(choices, query) {
|
|
|
197
197
|
}
|
|
198
198
|
//#endregion
|
|
199
199
|
//#region ../dsh-model-route/src/catalog-ui.tsx
|
|
200
|
-
/**
|
|
200
|
+
/**
|
|
201
|
+
* Also accepts a mapped state from a caller that owns broader async orchestration.
|
|
202
|
+
*
|
|
203
|
+
* The dsh-ui-* classes carry the styling and resolve through the consuming
|
|
204
|
+
* plugin's own officialUiCss scope (every consumer mounts its root class, so
|
|
205
|
+
* e.g. `.dsh-model-hub .dsh-ui-loading` paints this); dsh-model-catalog-status
|
|
206
|
+
* stays as a structural hook for tests and layout, never a colour source.
|
|
207
|
+
*/
|
|
201
208
|
function ModelCatalogStatus({ state, locale }) {
|
|
202
209
|
const zh = locale?.toLowerCase().startsWith("zh") === true;
|
|
203
210
|
const copy = zh ? {
|
|
@@ -213,15 +220,17 @@ function ModelCatalogStatus({ state, locale }) {
|
|
|
213
220
|
};
|
|
214
221
|
if (!state.loading && !state.error && state.failures.length === 0) return null;
|
|
215
222
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
216
|
-
className: "dsh-model-catalog-status",
|
|
223
|
+
className: "dsh-model-catalog-status dsh-ui-stack",
|
|
217
224
|
lang: zh ? "zh" : "en",
|
|
218
225
|
children: [
|
|
219
226
|
state.loading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
220
227
|
role: "status",
|
|
228
|
+
className: "dsh-ui-loading",
|
|
221
229
|
children: copy.loading
|
|
222
230
|
}) : null,
|
|
223
231
|
state.error ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
224
232
|
role: "alert",
|
|
233
|
+
className: "dsh-ui-error dsh-ui-wrap",
|
|
225
234
|
children: [
|
|
226
235
|
copy.error,
|
|
227
236
|
": ",
|
|
@@ -230,20 +239,27 @@ function ModelCatalogStatus({ state, locale }) {
|
|
|
230
239
|
}) : null,
|
|
231
240
|
state.failures.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
232
241
|
role: "status",
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
failure.
|
|
237
|
-
|
|
242
|
+
className: "dsh-ui-meta",
|
|
243
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: copy.partial }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
244
|
+
className: "dsh-ui-list",
|
|
245
|
+
children: state.failures.map((failure, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", { children: [
|
|
246
|
+
failure.name || failure.id,
|
|
247
|
+
": ",
|
|
248
|
+
failure.message
|
|
249
|
+
] }, `${failure.id}:${index}`))
|
|
250
|
+
})]
|
|
238
251
|
}) : null,
|
|
239
|
-
state.error || state.failures.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
state.
|
|
245
|
-
|
|
246
|
-
|
|
252
|
+
state.error || state.failures.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
253
|
+
className: "dsh-ui-actions",
|
|
254
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
255
|
+
type: "button",
|
|
256
|
+
size: "sm",
|
|
257
|
+
disabled: state.loading,
|
|
258
|
+
onClick: () => {
|
|
259
|
+
state.refresh();
|
|
260
|
+
},
|
|
261
|
+
children: copy.retry
|
|
262
|
+
})
|
|
247
263
|
}) : null
|
|
248
264
|
]
|
|
249
265
|
});
|
|
@@ -263,7 +279,8 @@ function ModelCatalogStatus({ state, locale }) {
|
|
|
263
279
|
* Sticky group headings, subsequence ranking, highlight walking and focus
|
|
264
280
|
* hand-back all match the host. SYNC POINT: when the host's ModelSelect or
|
|
265
281
|
* ModelSelect.module.css changes, this copy must be re-transcribed; styles
|
|
266
|
-
* below may only reference
|
|
282
|
+
* below may only reference allowlisted theme tokens (the --dsw-* set plus the
|
|
283
|
+
* host's --ds-* motion tokens), never literal colors.
|
|
267
284
|
*
|
|
268
285
|
* It statically imports the primitives, so only browser clients should load
|
|
269
286
|
* this entry; host code and node tests use the core entry (`./index.ts`).
|
|
@@ -771,7 +788,8 @@ function ModelMenu(props) {
|
|
|
771
788
|
* sticky group headings (MenuGroup's own CSS), and the l1-stroke prominent
|
|
772
789
|
* elevation at portal z-index 1100. The trigger mirrors the composer's 28px
|
|
773
790
|
* model pill, chevron rotating open. MenuSurface paints fill and backdrop.
|
|
774
|
-
* Only --dsw
|
|
791
|
+
* Only allowlisted --dsw- and --ds- theme tokens may appear here — a literal
|
|
792
|
+
* color is a bug.
|
|
775
793
|
*/
|
|
776
794
|
const modelMenuCss = `
|
|
777
795
|
.dsh-model-menu-root { min-width: 0; position: relative; display: inline-flex; }
|
|
@@ -794,12 +812,14 @@ const modelMenuCss = `
|
|
|
794
812
|
display: flex;
|
|
795
813
|
}
|
|
796
814
|
.dsh-model-menu-trigger:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); }
|
|
797
|
-
.dsh-model-menu-trigger:focus-visible:not([data-selection-focus]) { box-shadow: 0 0 0
|
|
815
|
+
.dsh-model-menu-trigger:focus-visible:not([data-selection-focus]) { box-shadow: 0 0 0 var(--dsw-focus-ring-width) var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary)); }
|
|
798
816
|
.dsh-model-menu-trigger:disabled { color: var(--dsw-alias-label-dimmed); cursor: default; }
|
|
799
817
|
.dsh-model-menu-triggerLabel { text-overflow: ellipsis; white-space: nowrap; min-width: 0; overflow: hidden; }
|
|
800
818
|
.dsh-model-menu-triggerEffort { text-overflow: ellipsis; white-space: nowrap; min-width: 0; color: var(--dsw-alias-label-caption); flex-shrink: 1000; overflow: hidden; }
|
|
801
|
-
.dsh-model-menu-chevron { color: var(--dsw-alias-label-caption); flex: none; transition: transform
|
|
819
|
+
.dsh-model-menu-chevron { color: var(--dsw-alias-label-caption); flex: none; transition: transform var(--ds-transition-duration) var(--ds-ease-in-out); }
|
|
802
820
|
.dsh-model-menu-chevronOpen { transform: rotate(180deg); }
|
|
821
|
+
/* Portal overlay: the host publishes no z-index token, so the card keeps the
|
|
822
|
+
* native menu layer's 1100 verbatim. */
|
|
803
823
|
.dsh-model-menu-menu {
|
|
804
824
|
z-index: 1100;
|
|
805
825
|
--dsw-elevation-stroke-color: var(--dsw-alias-border-l1);
|
|
@@ -825,6 +845,8 @@ const modelMenuCss = `
|
|
|
825
845
|
.dsh-model-menu-searchWithQuery { padding-right: 34px; }
|
|
826
846
|
.dsh-model-menu-searchRow .dsh-model-menu-search input { padding: 0; font-size: 12px; line-height: normal; }
|
|
827
847
|
.dsh-model-menu-searchRow .dsh-model-menu-search input::placeholder { color: var(--dsw-alias-label-caption); }
|
|
848
|
+
/* The clear button is a circle by geometry (border-radius: 50%), a shape the
|
|
849
|
+
* radius token scale does not describe. */
|
|
828
850
|
.dsh-model-menu-searchClear {
|
|
829
851
|
width: 24px;
|
|
830
852
|
height: 24px;
|
|
@@ -1072,6 +1094,17 @@ ${scope} {
|
|
|
1072
1094
|
/* --- Layout scaffolding. --- */
|
|
1073
1095
|
& .dsh-ui-stack { display: flex; flex-direction: column; gap: 12px; }
|
|
1074
1096
|
& .dsh-ui-stack-lg { display: flex; flex-direction: column; gap: 20px; }
|
|
1097
|
+
/* Plugin detail pages share one reading column. These are layout recipes;
|
|
1098
|
+
* controls keep their own primitive styles. Form spacing follows the host's
|
|
1099
|
+
* settings-form/fields.module.css and SettingsForm.module.css. */
|
|
1100
|
+
& .dsh-ui-page { display: flex; flex-direction: column; gap: 16px; width: 100%; max-width: 760px; min-width: 0; }
|
|
1101
|
+
& .dsh-ui-form { display: flex; flex-direction: column; gap: 0; min-width: 0; }
|
|
1102
|
+
&.dsh-ui-form > .dsh-ui-field, & .dsh-ui-form > .dsh-ui-field { padding: 12px 0; }
|
|
1103
|
+
& .dsh-ui-form-footer { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; padding-top: 16px; min-width: 0; }
|
|
1104
|
+
& .dsh-ui-fields-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 20px; min-width: 0; margin: 0; padding: 0; border: 0; }
|
|
1105
|
+
@media (max-width: 560px) {
|
|
1106
|
+
& .dsh-ui-fields-grid { grid-template-columns: minmax(0, 1fr); }
|
|
1107
|
+
}
|
|
1075
1108
|
& .dsh-ui-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
|
|
1076
1109
|
& .dsh-ui-row-wrap { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
|
|
1077
1110
|
& .dsh-ui-spacer { flex: 1; min-width: 0; }
|
|
@@ -1099,6 +1132,9 @@ ${scope} {
|
|
|
1099
1132
|
* official primitive, so this only owns the vertical rhythm. --- */
|
|
1100
1133
|
& .dsh-ui-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
|
|
1101
1134
|
& .dsh-ui-field + .dsh-ui-field { border-top: 0.5px solid var(--dsw-alias-border-l2); padding-top: 12px; }
|
|
1135
|
+
/* Grid fields share a row, so the stacked-field divider must not win later in
|
|
1136
|
+
* the cascade. Reset it here, after the field recipe. */
|
|
1137
|
+
& .dsh-ui-fields-grid > .dsh-ui-field { padding: 0; border: 0; }
|
|
1102
1138
|
& .dsh-ui-label { display: flex; align-items: center; gap: 6px; font-size: 13px; line-height: 20px; font-weight: 500; color: var(--dsw-alias-label-primary); }
|
|
1103
1139
|
& .dsh-ui-label-row { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
|
|
1104
1140
|
& .dsh-ui-help { font-size: 12px; line-height: 1.6; color: var(--dsw-alias-label-secondary); }
|
|
@@ -1289,7 +1325,7 @@ ${scope} {
|
|
|
1289
1325
|
& *, & *::before, & *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
|
|
1290
1326
|
}
|
|
1291
1327
|
}
|
|
1292
|
-
`.replace(/^& (\.dsh-ui-[a-z0-9-]+)(
|
|
1328
|
+
`.replace(/^& (\.dsh-ui-[a-z0-9-]+)(?=\s*\{)/gm, (_match, className) => `&${className}, & ${className}`);
|
|
1293
1329
|
}
|
|
1294
1330
|
//#endregion
|
|
1295
1331
|
//#region ../dsh-plugin-kit/src/contracts.ts
|
|
@@ -1660,12 +1696,12 @@ const TEXT$1 = {
|
|
|
1660
1696
|
zh: {
|
|
1661
1697
|
title: "子代理阵容",
|
|
1662
1698
|
enabledLabel: "启用子代理阵容",
|
|
1663
|
-
enabledHint: "
|
|
1699
|
+
enabledHint: "此名单限制子代理的显式选模;不指定模型时仍可继承父会话。名单修改对新建会话生效,已有会话及其子代理沿用原名单。任务倾向供委派时参考。",
|
|
1664
1700
|
loading: "正在读取…",
|
|
1665
1701
|
failed: (message) => `读取失败:${message}`,
|
|
1666
1702
|
syncFailed: (message) => `自动同步不可用:${message}`,
|
|
1667
1703
|
writeFailed: (message) => `未保存:${message}。请刷新后重试。`,
|
|
1668
|
-
saved: "
|
|
1704
|
+
saved: "已保存。名单修改对新建会话生效。",
|
|
1669
1705
|
savedRefreshFailed: (message) => `已保存;阵容刷新失败:${message}。请刷新以读取最新设置。`,
|
|
1670
1706
|
conflict: "阵容设置已在别处修改,当前输入保留。请刷新核对后重试。",
|
|
1671
1707
|
tendencyFailed: (message) => `任务倾向不可用:${message}。原文件已保留;修复后刷新。`,
|
|
@@ -1697,12 +1733,12 @@ const TEXT$1 = {
|
|
|
1697
1733
|
en: {
|
|
1698
1734
|
title: "Subagent Cast",
|
|
1699
1735
|
enabledLabel: "Enable subagent cast",
|
|
1700
|
-
enabledHint: "
|
|
1736
|
+
enabledHint: "This list limits explicit subagent model choices; omitting a model can still inherit the parent session. List changes apply to new conversations. Existing conversations and their subagents keep their saved lists. Task tendencies guide delegation.",
|
|
1701
1737
|
loading: "Loading…",
|
|
1702
1738
|
failed: (message) => `Load failed: ${message}`,
|
|
1703
1739
|
syncFailed: (message) => `Live sync unavailable: ${message}`,
|
|
1704
1740
|
writeFailed: (message) => `Not saved: ${message}. Refresh, then try again.`,
|
|
1705
|
-
saved: "Saved
|
|
1741
|
+
saved: "Saved. List changes apply to new conversations.",
|
|
1706
1742
|
savedRefreshFailed: (message) => `Saved; cast refresh failed: ${message}. Refresh to read the latest settings.`,
|
|
1707
1743
|
conflict: "Cast settings changed elsewhere; your draft is preserved. Refresh, review, then try again.",
|
|
1708
1744
|
tendencyFailed: (message) => `Task tendencies unavailable: ${message}. The original file is preserved; repair it, then refresh.`,
|
|
@@ -1991,7 +2027,7 @@ function CastPage({ api, locale }) {
|
|
|
1991
2027
|
refresh: refreshNow
|
|
1992
2028
|
};
|
|
1993
2029
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1994
|
-
className: "cast-root dsh-ui-stack",
|
|
2030
|
+
className: "cast-root dsh-model-hub dsh-ui-stack",
|
|
1995
2031
|
"aria-label": t("title"),
|
|
1996
2032
|
"aria-busy": saving !== "" || refreshing,
|
|
1997
2033
|
children: [
|
|
@@ -2421,7 +2457,7 @@ function HubPage({ view, api, locale, initialEntries = null, initialCatalog = nu
|
|
|
2421
2457
|
refresh: refreshNow
|
|
2422
2458
|
};
|
|
2423
2459
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
2424
|
-
className: "dsh-model-hub dsh-ui-
|
|
2460
|
+
className: "dsh-model-hub dsh-ui-page",
|
|
2425
2461
|
lang: t.language,
|
|
2426
2462
|
"aria-label": t("title"),
|
|
2427
2463
|
"aria-busy": writing !== "" || refreshing,
|