dsh-model-capability
给 DSH「设置 → 模型」页做 UI 增强:在现有的每个提供方卡片里,逐模型配置视觉、推理与容量。
以前这些只能手改 ~/.dsh/settings.yaml(input、reasoningEfforts、contextWindow、maxTokens 字段),而且 DSH 重启时会用内存状态重写配置、把这些字段丢掉——所以才有 restore-vision-thinking.ps1 那种打补丁脚本。本插件把这件事搬到界面上,写入走官方设置通道,改完立即生效、无需重启。
界面
每个提供方卡片里多一块「模型能力」(默认折叠,点「展开」使用),每个模型一组控件:
| 控件 | 形态 | 写入的字段 |
|---|---|---|
| 模态 | ☑ 视觉 勾选框 | input: [text, image] / [text] |
| 推理 | ☑ 推理模型 勾选框 | reasoningEfforts 字典 / false |
| 思考档位 | ☑ 7 个勾选框 | reasoningEfforts 的键 |
| 输入(上下文窗口) | 输入框 | contextWindow |
| 输出(最大 token) | 输入框 | maxTokens |
只有「输入」「输出」是输入框,其余全部是勾选框。
容量字段接受 8k / 1m 这类简写,也会自动用简写显示:存 800000 显示
800K,存 1000000 显示 1M。存储的始终是普通整数 token 数,简写只存在于
输入框文本里,不会丢精度——不是整千的 131072 就原样显示,因为换成 K 会丢精度。
词表与 DSH 自带编辑器完全一致(十进制:1k = 1000、1m = 1000000,
不是 1024 进制)。
- 推理模型勾选框取消时,档位区收起,
reasoningEfforts写成false(声明非推理模型)。 - 容量留空即删除该键,回到提供方默认值;输入框的灰色占位符显示当前生效值,让你看得见但不会误写。
- 改动累积成草稿,点保存才写入;顶部「未保存」标记提示有未落盘的改动。
安装
dsh plugin --profile desktop add "git+https://github.com/iuuuuuuuu/dsh-model-capability.git"
也可以克隆到本地后按目录安装:
git clone https://github.com/iuuuuuuuu/dsh-model-capability
dsh plugin --profile desktop add "file:<克隆下来的绝对路径>/dsh-model-capability"
装完刷新 DSH 页面即可。卸载:
dsh plugin --profile desktop remove dsh-model-capability
注意:
dsh plugin必须用dsh命令(桌面版dsh.cmd)。不要指望DSH_HOME环境变量能把它指到别的 profile——那个包装脚本把DSH_HOME写死成C:\Users\<你>\.dsh了。要在隔离 profile 上操作,直接跑node "<app>\node_modules\@deepseek-ai\dsh\lib\bin.js"。
写入规则
写入落在 settings.yaml 的 llm-pi-ai.providers.<路由>.models 数组里:
llm-pi-ai:
providers:
example-gateway:
models:
- id: example-model
name: example-model # 你手写的字段原样保留
contextWindow: 200000 # ← 输入框
maxTokens: 64000 # ← 输入框
input: # ← 视觉勾选框
- text
- image
reasoningEfforts: # ← 推理 + 档位勾选框
off: null
low: low
medium: medium
high: high
三条规则:
- 以用户层条目为基底。 你手写在
models里的name、compat等字段都会被保住。 - 继承值不物化。 模型来自已安装目录(你没写过该条目)时,只用
{ id }作基底;目录给的contextWindow、name只作为占位提示显示,不会写进你的配置。同理,档位处于「继承目录」态且你没勾过任何档位时,reasoningEfforts键不会被凭空创建。 off留空值。 pi-ai 把「off无值」读作「支持不思考,但不发送任何参数」,这是唯一允许空值的档位;其余档位写入同名拼写。
已知限制:数组内部注释会被替换
DSH 的 settings 写入是「叶子级 diff」,但它对数组整体替换——YAML 序列内部不是 map,无法逐键合并。因此任何对 models 数组的写入(本插件、以及 DSH 自带的 Models 页面都一样)都会丢掉写在数组元素内部的注释。
这正是本插件带备份看护的原因:每次写入之前的那一版都会被存进 ~/.dsh/model-capability-backups/settings-<时间戳>.yaml(保留最近 12 份)。注释丢了可以从备份里找回。
看护监视的是目录而不是文件——DSH 的写入是「写临时文件 + 原子替换」,文件级监视在替换后会盯着一个已失效的 inode。
想彻底不丢注释,可以把 models 数组改成 pi-ai 的 modelOverrides 字典(字典是 map,可逐键合并);但得先把现有数组整体移走,因为 pi-ai 明确禁止两者同时点名同一模型。
测试
cd dsh-model-capability
node test/logic.test.mjs # 客户端半:102 项
node test/host.test.mjs # 宿主半:16 项
node test/parity.test.mjs # 与宿主的容量词表对照:81 项
客户端测试要用到 DSH 桌面版自带的 react(宿主的种子模块),它会按「环境变量 → 常见安装位置」自动查找;装在非默认位置时显式指定:
$env:DSH_APP_MODULES = "$env:LOCALAPPDATA\Programs\DSHDesktop\DSH Desktop\resources\app\node_modules"
两个测试都完全隔离运行,不启动 DSH、不读写真实 ~/.dsh:
logic.test.mjs把lib/client.js装进一个最小window.__ModuleLoader__桩里(复刻 client-modules 的 factory 契约),用一个手写的极简 hooks 渲染器真实驱动组件,断言渲染结构、交互、写回形状、继承态与边界情况。host.test.mjs用临时目录当DSH_HOME,验证备份看护在原子替换下仍生效、备份保存的是变化前的版本、以及 watcher 出错时不会打挂宿主进程。parity.test.mjs把宿主 bundle 里真实的parseCapacity/formatCapacity抽出来求值,与本插件的实现逐例比对(43 个解析输入 + 21 个格式化输入 + 往返稳定性)。两个界面读写同一个字段,若词表漂移,用户在两处看到的数值就会对不上,且很难察觉。
架构
| 文件 | 职责 |
|---|---|
lib/index.js |
宿主半:settings.yaml 备份看护。不注册服务、工具或提示词。 |
lib/client.js |
浏览器半:把「模型能力」面板注册进 settings.models.provider-card 插槽。 |
cordis.patch.yml |
bundle patch,让安装后自动挂载。 |
插件不修改任何宿主源码。它用的是 dsh-client-ui-settings-models 自己声明的扩展插槽 settings.models.provider-card(keyed,以 entryKey = settingsNs 分发),因此按 llm-pi-ai 注册一次即可收到该家族的全部提供方卡片,含手工声明的路由。
读写都走既有的 settingsScope 服务(绑定 llm-pi-ai 命名空间),没有自定义传输层。
许可
MIT
No comments yet. Be the first to write one.