DeepSeek Harness(DSH / cordis plugin)插件:通过 Jev 或工具调用,让 Agent 根据任务场景自主切换模型预设和思考深度。
- 自动换档(Jev):接入 TypeSafe Jev 决策模型,每轮对话开局读一次你的最新指令判断任务类型,自动在声明的档位间换档——排查疑难升到高推理档位,改文案、跑测试回到日常档位,不用手动干预、也不必在提问时交代"用深度思考";档位只声明思考强度时,换档就是在同一个模型上自动调节思考深度;
- 自由调模工具:Agent 用
set_model/list_models按任务难度自主切换 provider、model 与 reasoningEffort; - 档位工具:部署声明一组「模型 + 思考强度」档位,Agent 只能在档位间切换(
switch_preset/list_presets);档位可以只声明思考强度而不绑定模型(provider/model留空 = 沿用当前模型),从而只调节思考深度;未声明presets时内置low/medium/high三档; - 自动换档与两个工具面开关彼此独立,可任意组合(只开 Jev、只开工具、都开、都关);
- 可配置一段策略提示词:同一份文本既告诉 Agent、也告诉 Jev 各阶段该用哪个档位;
- 插件把当前模型与档位注入运行时上下文,并随 Plan 模式自动升降级。
攻坚疑难问题时升到高推理档位,日常执行保持高性价比档位——开启 Jev 后这条策略每轮自动执行,不再需要用户手动改配置。
| 开关 | 默认 | 作用 |
|---|---|---|
enableModelTools |
true |
注入 set_model / list_models,Agent 可切换到任意已注册 provider / model / 思考强度 |
enablePresetTools |
false |
注入 switch_preset / list_presets,Agent 只能在 presets 声明的档位间切换(默认三档只调思考强度) |
jevEnabled |
false |
Jev 每轮自动决策档位,不依赖上面两个工具,也不受它们影响 |
档位工具约束的是 Agent 的工具面;你在 GUI 模型选择器里的手动切换不受限制(DSH 未提供拦截用户切模的插件接口),可作为人工兜底通道。三个开关都不影响 GUI 的既有行为。
policyPrompt 是这一份策略的唯一出处,有两个读者:
| 读者 | 何时读到 | 读到什么 |
|---|---|---|
| Agent | 两个工具开关至少开一个时 | 作为 ## Model policy 段落写进系统提示词 |
| Jev | jevEnabled 打开时 |
随每轮决策请求发出(state.policy),与当前指令、上一轮回复一同进入判定 |
两个读者都不在时(工具全关、Jev 也关)这段配置不被读取,插件只在日志里给一条 warning。
policyPrompt: |
规划与疑难排查一律先切 deep;日常实现、改文件、跑测试用 daily。开启档位工具后 Agent 实际看到的(档位清单由 presets 的 id/name/when 自动生成,无需手写):
## Model policy
规划与疑难排查一律先切 deep;日常实现、改文件、跑测试用 daily。
本部署只允许在下列模型档位之间切换;进入对应阶段时调用 switch_preset 换档:
- **daily(日常执行)** — deepseek/deepseek-chat · reasoning low — 适用:常规实现、修改、测试
- **deep(深度攻坚)** — deepseek/deepseek-reasoner · reasoning max — 适用:疑难排查、架构设计
档位的 when 同时也是 Jev 的判定依据(档位名与思考强度附在其后)。Jev 开启时缺 when 的档位只剩一个名字可判,插件会就此给一条 warning。
未配置任何策略时段落为空,不会在提示词里留下痕迹。
插件通过 systemPrompt.context 把当前活跃模型注册进每个 step 组装的 Runtime Context 快照(该快照仅在文本变化时才追加新的一条,内容相同则复用上一条,因此稳定轮次里只落一条 cache-safe 追加;模型随时自查、无需调用工具):
[Current active model: deepseek/deepseek-chat · reasoning: low · preset: daily]
处于 Plan 模式时附带状态标记:
[Current active model: deepseek/deepseek-reasoner · reasoning: max · preset: deep] [Plan Mode Active]
preset: xx 仅在当前模型命中某个档位时出现。
set_model({ provider?, model?, reasoningEffort?, reason }) —— reason 必填(每次切换都会使会话 KV cache 失效,工具说明要求 Agent 给出理由、避免频繁切换):
{ "model": "deepseek-reasoner", "reasoningEffort": "high", "reason": "疑难并发问题排查,需要深度推理" }list_models({ provider? }) 列出已注册 Providers 与模型能力(推理档位、上下文窗口):
# Available Providers & Models:
## Provider: deepseek
- **deepseek-reasoner** (DeepSeek Reasoner) | Reasoning: [low, high, max] | Context: 128000
- **deepseek-chat** (DeepSeek Chat) | Context: 128000
switch_preset({ preset, reason }) —— preset 是配置里的档位 id,reason 必填;id 不存在时返回可用档位清单:
Model preset switched to deep (深度攻坚) — deepseek/deepseek-reasoner · reasoning: max. Effective from the next step.
Reason: 疑难并发问题排查,需要深度推理
list_presets({}) 列出允许的档位、各自适用阶段与当前生效档位:
# Model presets
Mode: preset · Plan Mode active
Current: deepseek/deepseek-reasoner · reasoning max · preset deep
- **daily(日常执行)** — deepseek/deepseek-chat · reasoning low — 适用:常规实现、修改、测试
- **deep(深度攻坚)** — deepseek/deepseek-reasoner · reasoning max — 适用:疑难排查、架构设计 ← current
切换自下一个 step 生效:插件向会话写入 model/selection 事件(与 GUI 模型选择器同一机制),Web UI 状态同步。
插件监听 agent/pre-step 的 Plan 投影状态变迁,零人工干预:
- 进入 Plan 模式(
/plan on):暂存当前模型并自动切换——设置了planPreset时切到该档位(优先),否则切到planModel指定的模型; - 退出 Plan 模式(
exit_plan_mode批准 //plan off):自动恢复进入前的模型(autoRestorePlanModel,默认开启); - 自动切换失败仅 warn 降级,绝不打断 step。
开启 jevEnabled 后,插件在每轮对话的首个 step 问一次 TypeSafe Jev 决策模型:这条指令属于什么任务类型,该用哪个档位。判定过程如下:
- 取当前回合最新的用户指令(尚未提交进会话也取得到),拼上上一轮助手回复作为背景,尾部对齐截断到 2000 字符;
- 把
presets里每个档位(id/name/when)连同keep(保持现状)一起作为候选项,由 Jev 给出最佳档位与置信度; - 置信度低于
jevConfidenceThreshold(默认 0.7)就不动,避免无谓换档; - 命中则写入
model/selection事件切换模型,与 GUI 手动切模同一机制,Web UI 状态同步;切换只影响下一个 step 起的新请求。
"改一下这个按钮的颜色" 会留在日常档位;"线上订单偶发丢单,帮我定位" 会切到深度攻坚档位。命中时宿主日志里能看到实际判定:
dsh-set-model: [Jev] auto-switched session <id> to preset "deep" (deepseek/deepseek-reasoner · reasoning: max) with confidence 0.87
档位只声明 reasoningEffort(provider / model 留空)时,换档表现为在同一个模型上自动调整思考深度——例如日常 low、疑难 max,模型不变、思考预算自动变。
- 极低成本与高速度:基于 OpenRouter Decisions API,单次判定约 200~300ms,成本仅约 $0.000015 / 次;
- 通用凭据体系:设置页配置
jevApiKey/jevBaseUrl/jevModel,或走环境变量JEV_API_KEY/JEV_BASE_URL/JEV_MODEL;不绑定任何特定平台或本机密码本(api-vault),Base URL 与 API Key 由用户自主配置; - 稳健性保障:3 秒熔断超时、generation 竞态淘汰(新一轮指令作废在途判定)、Plan 模式期间主动避让不抢档;任何失败只写 warn 日志并保持当前档位,绝不阻塞本轮对话;
- 与工具开关解耦:
jevEnabled独立于enableModelTools/enablePresetTools,只开 Jev、不给 Agent 调模工具也能用。
-
Provider 白名单:
allowedProviders非空时,白名单外的切换请求直接拒绝;它同时约束档位(白名单外的档位会在加载时被丢弃并记录错误日志); -
上下文窗口护栏:当前会话 token 水位超过目标模型 contextWindow 时拒绝切换,并提示先压缩上下文(如 clear_mind):
Current session token pressure (70000 tokens) exceeds target model context window (65536 tokens). Please compact context (e.g. clear_mind) before switching to this model. -
路由校验与思考深度自适应:支持完整的 7 级思考深度(
off | minimal | low | medium | high | xhigh | max);当目标模型不支持所选档位时自动沿阶梯就近钳制(如xhigh/max→high),非推理模型自动剥离思考深度,再经 DSH 核心ctx.llm.resolveCallConfig校验路由; -
配置诊断不致命:重复档位 id、缺 provider/model、
planPreset指向不存在的档位等会写入宿主日志(dsh-set-model: ...)并跳过该条,插件照常加载——配置错误不会拖垮整棵插件树; -
仅根 Agent:工具只注册给根 Agent(subagent 不提供自主调模);把两个工具开关都关掉即可整体关闭。
插件自带 Web 设置页「动态模型」(设置 → 动态模型),可可视化维护:
- 档位表增删排序,provider / model / 思考强度均为下拉选择(数据取自当前模型目录),附
id、显示名、适用阶段; - 策略提示词;
- Agent 调模能力:两个工具开关与
allowedProviders; - Plan 目标(档位或模型)与
autoRestorePlanModel; - Jev 自动换档开关与高级选项(API Key / Base URL / 模型 / 置信度阈值),附「测试连接」按钮,探测 Decisions API 的可用性与时延。
保存后宿主即时重新应用插件配置,无需重启。字段需标记为 volatile 才会出现在设置表单里(DSH 设置系统的约定)。
Settings 命名空间为插件在 profile 里的 loader entry id:set-model(Web Settings UI 可视化配置,改动运行时动态生效)。
# profile 的 cordis.patch.yml(或设置页写入的用户层)
- id: set-model
name: dsh-set-model
config:
enableModelTools: true # 注入自由调模工具 set_model / list_models(默认 true)
enablePresetTools: false # 注入档位工具 switch_preset / list_presets(默认 false)
jevEnabled: false # Jev 自动切档位(默认 false,独立于上面两个开关)
presets: # 缺省为内置三档 low / medium / high(均不绑定模型)
- id: daily # 稳定标识,Agent 用它切换
name: 日常执行 # 展示名,缺省用 id
when: 常规实现、修改、测试 # 适用阶段:写进策略清单,也是 Jev 的判定依据
provider: deepseek # provider 与 model 同时留空 = 沿用当前模型,只调思考强度
model: deepseek-chat
reasoningEffort: low # off | minimal | low | medium | high | xhigh | max,缺省跟随模型默认
- id: deep
name: 深度攻坚
when: 疑难排查、架构设计
provider: deepseek
model: deepseek-reasoner
reasoningEffort: max
policyPrompt: | # 可选:策略文本,Agent(有工具时)与 Jev 共用
线上事故排查一律先切 deep。
planPreset: deep # 进入 Plan 模式使用的档位 id(优先)
planModel: # 未设 planPreset 时,进入 Plan 模式使用的模型
provider: deepseek
model: deepseek-reasoner
reasoningEffort: high
autoRestorePlanModel: true # 退出 Plan 模式自动恢复(默认 true)
allowedProviders: [] # 可选:可切换 Provider 白名单(空 = 不限制)
jevApiKey: "" # 可选:Jev API Key(缺省走 JEV_API_KEY 环境变量)
jevBaseUrl: "" # 可选:Jev Decisions API URL(缺省走 JEV_BASE_URL 或默认官方端点)
jevModel: "" # 可选:Jev 决策模型(缺省走 JEV_MODEL 或 typesafe/jev-1.13)
jevConfidenceThreshold: 0.7 # Jev 切换置信度阈值(0.0 ~ 1.0,默认 0.7)dsh plugin --profile web add dsh-set-model安装后无需手动改配置,插件自带的 cordis.patch.yml 自动挂载生效。
从 GitHub 直装(源码安装,pnpm ≥10 需允许构建脚本):
dsh plugin --profile web add github:john-walks-slow/dsh-set-model
# 首次 add 会被 pnpm 拦截:把 pnpm 提示的包名加入
# ~/.dsh/profiles/web/pnpm-workspace.yaml 的 allowBuilds 后重跑- 零直接副作用(常规路径)与轻量决策网络(Jev 路径):常规路径无外部服务、无插件自身网络请求(模型路由与能力查询均经由 DSH 核心
llm服务)、无直接文件系统写入;启用 Jev 自动切模后,仅在回合首步向用户配置的 Jev Decisions API 发送轻量任务摘要(当前指令与上一轮助手回复的尾部 2000 字符、策略提示词、档位清单,带 3 秒熔断超时保护,超时或网络异常仅 warn 降级,绝不阻塞主会话正常进行)。仅通过会话事件 API 写入model/selection事件(由 DSH 会话系统落盘)并注入一行 Runtime Context 与一段系统提示词 - 浏览器半:设置页以
lib/client.js(构建产物)注册settings.section,仅调用 DSH 的remote.settings/remote.sessionRPC,不发起自有网络请求 - 宿主版本要求:DSH
^0.1.7-rc.2 || ^0.2.0-rc.1(0.1.2~0.1.6 会得到明确的"插件与 dsh 版本不兼容"安装提示,请升级 DSH) - 依赖声明:DSH 运行时包(
cordis、dsh-agent、dsh-llm、dsh-session、dsh-tools,以及可选的dsh-settings)全部声明为peerDependencies——DSH 的模块解析层据此把插件内的@deepseek-ai/*import 路由到宿主自带副本,插件绝不携带、也不 hoist 这些包的副本;唯一运行时依赖是纯 schema 库@deepseek-ai/schemastery(react/esbuild/@types/react只用于构建浏览器半,运行时由 Web 壳提供 React)。Node ≥ 22.5 - 失败降级:Plan 模式自动切换失败只 warn 不打断 step;工具校验失败向 Agent 返回明确错误,不污染会话状态;设置页挂载失败只 console.error,不拖垮 GUI
npm install
npm run check # tsc(宿主) + tsc(浏览器半)
npm test # tsc(含 test) + node --test dist/test/*.test.js
npm run build # tsc → dist/src,esbuild → lib/client.js
npm run build:client # 只重建浏览器半需要图形界面验证时用 dsh-e2e 最小实例(见 scripts/dev-worktree.sh):
dsh-e2e start --wait-ready --patch e2e/fixture/cordis.patch.yml
dsh-e2e run e2e/verify-policy-page.mjse2e 的种子配置在 e2e/fixture/cordis.patch.yml(档位、Plan 目标与策略提示词的样例值),启动时通过 --patch 注入;playwright / camoufox 路径可用 DSH_E2E_PLAYWRIGHT / DSH_E2E_BROWSER 覆盖。
浏览器半改完务必重建 lib/client.js 并跑一次 node --check lib/client.js(构建脚本内已内置)。
MIT
改动入库后一条命令完成测试、版本号、打包(npm version 会自动 commit 并打 tag):
npm run release # patch;较大更新改用:npm version minor 或 major然后指纹发布并推送:
node ~/.agents/skills/npm-publish/scripts/publish-webauthn.cjs /tmp/dsh-set-model-<新版>.tgz
git push --follow-tags发布后 npm view dsh-set-model version 复验。批量发多个包时,在指纹页勾选“5 分钟内同 IP 不再挑战”,一次指纹即可连发。
发布后的暂存/扫描窗口(2026-10 起 npm 行为):
PUBLISHED_OK只是 PUT 被接受,版本随后进入暂存/扫描态, 期间npm view仍显示旧版本、/<pkg>/<version>与 tarball URL 都是 404,对同一版本重发会报 409Cannot publish over previously staged version。实测约 5 分钟后自动 promote(0.2.0:PUT 15:27:43Z → 上线 15:32:33Z)。 遇到 409 不要改版本号,等待并复查 registry 即可。落库判定用npm view dsh-set-model@<version> dist.shasum与本地 tgz 的sha1sum比对:一致即上线产物与本地产物字节相同。
- 感谢 LINUX DO 社区提供的交流环境。
