dsh-model-cascade
Manifest validDSH 插件:模型选择三级级联菜单(供应商→系列→完整模型名)
dsh-model-cascade · 三级级联模型选择器
把输入框(composer)右下角的模型座位换成三级级联菜单:供应商 → 系列 → 完整模型。 内置座位是一层扁平长列表,模型一多就得靠滚动和记忆找;这里先选供应商、再选系列, 最后才落到具体模型 id,并在同一菜单里给出「思考强度」入口。
纯 UI 插件:宿主半是空的
apply()(只为在 Loader 里占一行), 真正干活的是浏览器半lib/client.js,它注册到conversation.input.model座位, 以priority: -1遮蔽内置的两级列表。
特性
- 三级级联:第 1 级是 harness 供应商分组(
group.name,即配置里那条 API 路由), 第 2 级是从模型 id 推断出的系列,第 3 级是完整模型 id。各级顺序沿用模型目录自己的顺序。 - 面包屑 + 返回:菜单顶部显示当前层级路径,可逐级返回;Esc 也是「退一级」。
- 思考强度(effort)独立一屏:当前模型支持 reasoning 时,根部多一行「思考强度」,
进入后列出该模型的 effort 列表(含「默认」项),选择会提交
{ provider, model, reasoningEffort }。 - 复用同一份 ModelDirectory:
modelDirectories.directoryFor(sessionId)拿到的是内置座位 用的那个 per-session 目录 store,因此选中态、连接重置、composer 阻塞等行为与内置座位一致。 - 状态可见:加载中提示、整体加载失败(带「重新加载」)、分组级失败逐条告警、 选择失败弹 Toast。
- 纯中英双语:注册
model-cascade命名空间字典(zh / en),无其它配置。
启用方式
cordis.patch.yml 是 bundle patch 层,内容就是一行挂载:
- insert:
- id: dsh-model-cascade
name: dsh-model-cascade
- 宿主半:
lib/index.js的apply() {}是空函数,不注册服务、不读配置、不占端口。 它的存在只是让插件在 Loader 里有一个dsh-model-cascade条目。 - 浏览器半发现:靠
package.json的dsh.bundle.patch与dsh.client(platform: "web"),浏览器半从exports["./client"]载入。 - 依赖的服务(客户端
inject):slots、modelDirectories、sessions、locale、remote、remote.session。 后两个不是可选装饰:ui-model-selection的directoryFor在铸造 per-session 目录时会解引用this.ctx["remote.session"],缺了就会抛 "without inject",座位被错误边界摘掉、内置座位重新生效 (这段原因写在代码注释里)。 - 把包放进 profile 的
node_modules并追加上面的 insert 行后,浏览器半随实例加载; 客户端半的发现链路需要实例重启 + 浏览器硬刷新(与同仓dsh-qq-bridge同类,本插件代码内未体现)。 - 遮蔽机制:同一 slot 单占用,最低 priority 渲染;本插件注册
priority: -1, 压过内置的两级列表。内置座位的 priority 约定若变化,遮蔽可能失效。
配置项
无配置。宿主半没有 settings.register(...),客户端半只注册 locale 字典:
ctx.effect(() => ctx.locale.register('model-cascade', { zh, en }), 'dsh-model-cascade: dictionaries')
档位、开关、默认模型等都不由本插件提供;它只改写选择器的交互形态。
主要能力
注册的 Slot
| 项 | 值 |
|---|---|
| slot 名 | conversation.input.model |
locale | model-cascade |
priority | -1(遮蔽内置座位) |
| 组件入参 | locked、available、directory、load、select、t |
available = sessions.subagentAddress(sessionId) === undefined:子代理会话里座位不渲染(return null)。load()调目录 store 的load();select(selection)调directory.select(...), 成功/失败折成布尔,失败时用目录快照里的error弹 Toast。- 数据来自
directory.subscribe/directory.getSnapshot(),读groups/current/status(loading/ready/selecting)/error/failures。
交互
- 触发按钮显示「当前模型名」+「思考强度名」(有 effort 时以
·连接),locked时禁用;aria-haspopup="menu"/aria-expanded/aria-label齐备。 - 键盘:↑/↓ 在当前面板的可用按钮间循环聚焦;Esc = 退出 effort 屏 → 退一级 → 关闭并回焦触发按钮
(Esc 同时挂文档级监听,因为点行会卸载该按钮、焦点落回
<body>)。 - 鼠标:点击菜单外部关闭,焦点离开根节点关闭;菜单底部固定显示「当前供应商 / 当前模型」。
菜单内容
- 第 1 级:供应商行(右侧显示该供应商下的模型总数)。
- 第 2 级:系列行(右侧显示系列内模型数);系列名 = 模型 id 中最后一个
/之后、 第一个-之前的字符串(如deepseek/deepseek-chat→deepseek);无-时退化为整段。 - 第 3 级:完整模型 id(可选描述副标题,选中项打勾)。点模型即直接选中, 需要调思考强度时再走根部的「思考强度」行分开设置。
文件结构
dsh-model-cascade/
├── README.md # 本文件
├── package.json # name/version 0.1.2;dsh.bundle.patch 指向 cordis.patch.yml;dsh.client(web)
├── cordis.patch.yml # bundle patch 层:一行 insert 挂载 id/name = dsh-model-cascade
└── lib/
├── index.js # 宿主半:空 apply(),只为让插件出现在 Loader 里
└── client.js # 浏览器半(预构建产物,window.__ModuleLoader__.load 工厂):三级级联座位组件 + 字典
备注 / 已知限制
- 声明依赖与实际 require 不一致:
package.json的dsh.client.inject声明了@deepseek-ai/dsh-client-locale与@deepseek-ai/dsh-client-ui-model-selection; 而lib/client.js实际require的是react、react/jsx-runtime、@deepseek-ai/dsh-client-ui-primitives(用到Toast、IconCheckOutline16、IconChevronRightOutline14、IconChevronDownOutline14、IconChevronLeftOutline14、IconWarningOutline16)。也就是说:真正被 require 的ui-primitives未声明, 声明的ui-model-selection从未被 require(它只作为被遮蔽的服务提供方间接存在)。 lib/client.js是预构建产物(window.__ModuleLoader__.load工厂 +react/jsx-runtime编译后的jsx/jsxs调用),不是可直接阅读的 ESM/JSX 源码;源码形态未随包提供。- 系列分组是启发式的:完全按 id 文本切分,不看模型元数据。同一系列命名不统一
(例如带版本号的
-v4前缀差异)会裂成多个系列;这仅是显示层的分组,选择时提交的始终是 供应商分组 id + 完整模型 id。 - CSS 与锚点硬编码:样式只注入一次,判重键是
data-plugin-css="dsh-model-cascade/ModelCascadeSelect.module.css";Toast 的anchor依赖[data-composer-card]这个属性选择器;宽度/高度用的是min(280px, 100vw - 32px)与min(420px, 100vh - 96px)固定值。 - 宿主半没有任何行为:无服务、无 model 工具、无命令、无事件监听、无 HTTP 路由、无设置命名空间——
想通过它暴露能力需要另行扩展
lib/index.js。 modelDirectories/sessions.subagentAddress/remote.session等都是 DSH 0.1.5-rc.1 服务层的内部契约;服务重命名或签名变化时,本插件会在注册阶段或首次directoryFor时失败。
Comments
Loading…
Similar plugins
by qgx1992
DSH web 插件:把输入框模型选择控件替换为两个独立按钮(供应商 + 模型两级联动,支持推理等级调节)
★ 0
JavaScript
Aug 27, 2026
dsh plugin --profile web add dsh-model-select-styleby bitterSmilezzz
DeepSeek Harness (DSH) 的增强模型选择器:单层菜单(搜索 + 分组)+ 底部内联推理强度(Effort)滑杆。
★ 1
↓ 69/wk
MIT
TypeScript
Sep 17, 2026
dsh plugin --profile web add dsh-model-selectorby sxy-kumako
DSH 插件:模型列表跟随 provider API 实时更新 + 各 provider 用量徽标 (GLM/MiniMax coding plan, DeepSeek/OpenRouter/Kimi balance)
★ 0
MIT
JavaScript
Sep 4, 2026
dsh plugin --profile web add dsh-better-model-selectby cKNKSnd
DeepSeek Harnes 输入框当前模型提供商名称
★ 0
MIT
JavaScript
Aug 19, 2026
dsh plugin --profile web add dsh-model-provider-badgeby DeepVite
梁文谷插件 · DeepSeek Harness 模型选择器升级:一级菜单模型/思考档位选择 + 自定义模型别名 + 高峰低谷计价倒计时。Apache-2.0
★ 0
Apache-2.0
TypeScript
Aug 29, 2026
dsh plugin --profile web add dsh-model-selectorProvider-first three-level model selector for the DSH Web model seat: pick a provider, then a model from that provider, with inline search on both levels, failed-provider retry rows, and a Model · Pro
★ 0
dsh plugin --profile web add dsh-model-provider