@klarkxy/dsh-model-hub 0.1.4 → 0.1.5

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 CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  [简体中文](docs/README.zh-CN.md)
6
6
 
7
- See and change the models used by your DeepSeek Harness plugins from one page, manage which models subagents may use, and watch which model and reasoning effort each running subagent is on.
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. Changes are saved by the plugin that owns the setting.
22
- - **Subagent Cast**: turn the subagent model allowlist on or off 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 explicitly choose one when delegating. For independent reviews and alternative approaches, it encourages a different model when suitable, while allowing the same model when it fits better. You can add your own task tendencies for individual models; they remain optional hints, and no model-specific tendencies are supplied by default. Below the list, a live view shows each running subagent with the model and reasoning effort it is currently using; an effort marked as adapter default comes from the adapter rather than an explicit choice.
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 identify providers that could not be loaded while other providers remain usable.
29
- - Model selection guidance requires host tools that support choosing a subagent model. Existing conversations retain their saved model lists; start a new conversation to use an updated list.
30
- - Guidance does not force a model choice or add extra subtasks solely for variety.
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. Existing conversations keep their saved lists; start a new one to use an updated list.
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
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  [English](../README.md)
6
6
 
7
- 在一个页面查看并修改各个 DeepSeek Harness 插件使用的模型,管理子代理可用的模型,并查看运行中子代理当前使用的模型与思考强度。
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
 
@@ -197,7 +197,14 @@ function groupModelMenuChoices(choices, query) {
197
197
  }
198
198
  //#endregion
199
199
  //#region ../dsh-model-route/src/catalog-ui.tsx
200
- /** Also accepts a mapped state from a caller that owns broader async orchestration. */
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
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: copy.partial }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", { children: state.failures.map((failure, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", { children: [
234
- failure.name || failure.id,
235
- ": ",
236
- failure.message
237
- ] }, `${failure.id}:${index}`)) })]
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)(_deepseek_ai_dsh_client_ui_primitives.Button, {
240
- type: "button",
241
- size: "sm",
242
- disabled: state.loading,
243
- onClick: () => {
244
- state.refresh();
245
- },
246
- children: copy.retry
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 --dsw-* theme tokens, never literal colors.
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-* theme tokens may appear here — a literal color is a bug.
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 2px var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary)); }
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 0.12s; }
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-]+)(?![+>~])/gm, (_match, className) => `&${className}, & ${className}`);
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
@@ -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-stack",
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,