前言¶
DeepSeek Harness(DSH)把模型选择保存在单个会话里。自带的默认模型设置只影响还没选择过模型的会话,/model 也只改变当前这个会话。当你有成片的历史会话想整体切到同一个模型和思考强度时,没有内置入口。下面介绍的 elfgzp/dsh-unified-model 就是补这个位置的插件:在 composer 行加一个控件,批量写入所有可写会话,并且把 reasoningEffort 一起带上。
插件定位是模型推理助手,由 elfgzp 维护,当前星标 0,版本 0.1.0,许可证 MIT。
这控制在哪、怎么用¶
控件挂在 composer 行,和官方模型选择器并列,不替换它:
[⇉ All sessions] [ deepseek-v4.1-flash ▾ ]
^ 官方模型选择器,保持原样
窗口窄时按钮收成图标:
[⇉] [ deepseek-v4.1-flash ▾ ]
完整名称仍写在按钮的 title 和 aria-label 里,不以按钮变图标就变成无标签控件。
打开面板后依次选 provider、model、thinking effort 和作用范围:
| 选项 | 效果 |
|---|---|
| Every session | 写入每一个能保存独立选择的会话 |
| Every other session | 同上,但不动当前正在看的会话 |
| Also make this the default | 额外写 deployment default,之后新建的会话从它开始 |
批量执行过程中有一个实时的 done/total 计数,结束后报告哪些改了、哪些本来就一致、哪些失败。
为什么连 effort 一起做¶
大多数「给所有会话换模型」的尝试停在模型层面,因为思考强度看起来像另一个层。实际不是:
sessionController.selectModel()接受{ provider, model, reasoningEffort? }。- 提交的选择会以
model/selection事件追加到会话日志,该事件的 schema 带reasoningEffort。 modelSelectionprojection 重新读取它,selectionFor()在重启后恢复它,因此 effort 能存活。
README 里给出的实测日志片段:
{"type":"model/selection","seq":4,"data":{"provider":"tencent-intranet","model":"deepseek-v4.1-flash-ioa","reasoningEffort":"max"}}
所以插件判断会话是否已匹配时,比较的是 provider、model 和 reasoningEffort 三项。只比较前两项的实现会显示成功,却悄悄少写了 effort。
作用范围与失败处理¶
| 情况 | 行为 |
|---|---|
| 普通会话 | 更新,是该控件的目标 |
| 子代理会话 | 不动;它们跟随父级路由,host 拒绝给它们单独选择;结果里单独计数,不当作失败 |
| 已携带目标选择的会话 | 跳过,不写;对已统一的历史重复点击在毫秒级完成 |
| 日志损坏或被其他进程锁住 | 按失败上报,附 host 给出的原因,批次其余部分继续 |
批量任务跑在 Host 上,不在浏览器里,关掉标签页不会中断;客户端只负责启动和轮询进度。
实现方式与接口¶
插件不修补自带插件、不改会话日志、不编辑 projection 缓存,直接调用内置 /model 对话框所用的公开 host API:
sessionController.list({}) → 全部会话及其当前选择
sessionController.selectModel({ sessionId, provider, model, reasoningEffort })
sessionController.modelCatalog() → provider 分组和每个模型公开的 effort
agentDefaultModel.saveSelection({ … }) → 需要时写 deployment default
写入走的是官方路径,会话状态保持官方格式,卸载不留下改动,未来 Harness 改名这些方法也只损失这个插件。
路由有三个,都在 composition 的连接信任栅栏之后:
GET /unified-model/state → catalog、default、各会话选择、当前 run
POST /unified-model/apply → { provider, model, reasoningEffort?, scope, excludeSessionId? } → { runId }
GET /unified-model/status → 当前或最近一次 run
POST /unified-model/default → 写 deployment default
两个性能与安全上的处理¶
先读后写。selectModel 会恢复每个冷会话,这是全程最贵的部分,所以插件先用 list() 读出所有会话的选择,跳过已一致的。README 在 55 会话 profile 上测得:首次跑写入了 36 个会话,耗时 2.7 s;紧接着的重复跑跳过 53 个,56 ms 完成。
写之前做校验。模型名或 effort 不被该模型公开时,适配器会拒绝请求,两项都在碰第一个会话前对照 modelCatalog() 检查,拼错会让请求整体失败,而不是逐个失败 60 个会话:
400 model-unknown catalog 没有列出这个 p/m
400 effort-unsupported p/m 公开 low/medium/high/xhigh/max,ultra999 不是其中之一
客户端也只提供模型实际公开的档位,两边不会对不上。
安装与启用¶
官方安装命令如下,profile 换成你自己的:
dsh plugin --profile <your-profile> add dsh-unified-model
如果已有 checkout,也可以从本地链接安装:
dsh plugin --profile <your-profile> add link:/path/to/dsh-unified-model
装好后要重启应用:bundle patch layer 和 client bundle 都在启动时加载。
配置项为空,控件直接出现在 composer 行,没有需要设置的东西。
适用场景与注意¶
适合需要把成片历史会话统一到同一模型和 effort 档位的 DSH 使用者,尤其是会话数量较多、手动逐个切换成本高的场景。子代理会话不会被动,这一点要提前知晓。
几点提醒:
- 插件以当前 dsh 进程的权限运行,安装前应检查源码和许可证(MIT)。
- 要求 DeepSeek Harness
0.2.0或更新版本,且需要 Web UI(控件在 composer slot 里)。 - 目录页
https://www.skillhub.cn/plugins/elfgzp/dsh-unified-model是社区站点,与 DeepSeek / 幻方无官方从属关系。
源码和文档见 https://github.com/elfgzp/dsh-unified-model。