面向 DeepSeek Harness 的双层模型路由器 —— LLM 裁判按期望成本把每一轮交给便宜的 Fast…
32.1/100
综合分
3
GitHub 星标
302
npm 周下载
—/5
用户评分
数据截至 2026/10/19 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add dsh-shift-routernpm 源 · dsh-shift-router 的发布者账号已校验与本仓库一致
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · model
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 17 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✓npm 包dsh-shift-router @ 0.7.5
✓Node 引擎要求 ^22.19.0 || >=24.0.0 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/22 11:44:15
安全扫描自动 · 静态分析源码v2.7.0🟢 扫描:未发现敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描未发现敏感能力:最多只发网络请求、读取自身元数据或只读文件,未发现执行命令、文件写入或敏感信息读取。
扫描于 2026/11/3(1 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/cordis-plugin-loader@deepseek-ai/dsh-app-boot@deepseek-ai/dsh-agent@deepseek-ai/dsh-api-remotes@deepseek-ai/dsh-api-session-controller@deepseek-ai/dsh-client-connection@deepseek-ai/dsh-client-locale@deepseek-ai/dsh-client-store@deepseek-ai/dsh-client-ui-plugin-manager@deepseek-ai/dsh-client-ui-renderer@deepseek-ai/dsh-client-ui-settings给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- LLM裁判路由
- 多模型回退链
- 指数退避故障转移
DeepSeek Harness 双层模型路由器——LLM-Judge 路由、多模型回退链、指数退避故障转移,以及任务级编排(pi-shift-router 的 DSH 适配版)
README
由 DeepSeek 最新模型翻译生成English · 简体中文
dsh-shift-router
面向 DeepSeek Harness 的双层模型路由器 —— LLM 裁判按期望成本把每一轮交给便宜的 Fast 层或 Smart 层,并配以多模型回退链、指数退避故障转移、缓存感知切换,以及「Smart 规划、Fast 执行」的任务级编排。
由 pi-shift-router 适配到 DSH 的版本。
本项目分叉自上游 v1.0.0(本仓库首个提交与上游该 tag 同日,均为 2026-08-14,因此上游若干版本的内容在此本就存在),此后重新对齐到上游 v1.6.0 —— 逐版本状态(已对齐/已适配/刻意不移植)见 ROADMAP.md 的 Upstream alignment 表,契约见 SPEC.md。
日常对话不该花旗舰模型的钱;真正重要的对话也不该交给便宜模型。
在每个顶层 Agent 的每一轮开始之前,一个轻量的 LLM 裁判(默认运行在你的 Fast 层模型链上,见 routing.judge.mode)会把用户消息判定为 fast(日常)或 smart(重要)。被选中的层随后通过 harness 自身的 agent/request 管线驱动整轮——思考、工具调用、代码编辑。裁判只做判定,从不干活。
展开完整文档(README 剩余 1 节)
English · 简体中文
dsh-shift-router
面向 DeepSeek Harness 的双层模型路由器 —— LLM 裁判按期望成本把每一轮交给便宜的 Fast 层或 Smart 层,并配以多模型回退链、指数退避故障转移、缓存感知切换,以及「Smart 规划、Fast 执行」的任务级编排。
由 pi-shift-router 适配到 DSH 的版本。
本项目分叉自上游 v1.0.0(本仓库首个提交与上游该 tag 同日,均为 2026-08-14,因此上游若干版本的内容在此本就存在),此后重新对齐到上游 v1.6.0 —— 逐版本状态(已对齐/已适配/刻意不移植)见 ROADMAP.md 的 Upstream alignment 表,契约见 SPEC.md。
日常对话不该花旗舰模型的钱;真正重要的对话也不该交给便宜模型。
在每个顶层 Agent 的每一轮开始之前,一个轻量的 LLM 裁判(默认运行在你的 Fast 层模型链上,见 routing.judge.mode)会把用户消息判定为 fast(日常)或 smart(重要)。被选中的层随后通过 harness 自身的 agent/request 管线驱动整轮——思考、工具调用、代码编辑。裁判只做判定,从不干活。
🦾 [deepseek-flash] → fix the failing test
🧭 judging…
🧠 [deepseek-v4-pro] ← "design the auth flow" → 立即升级
⚠️ deepseek-flash 429 → 冷却中,同层故障转移 — 1 分钟后重试
🦾 [deepseek-v4-flash] ← Fast 链中的下一个健康模型
特性
- 期望成本路由(EV) —— 当且仅当 pSmart ≥ θ 时走 Smart,其中 θ = 1/reworkPenalty:这条门槛与模型价格无关,所以唯一的旋钮就是"错误降级有多痛"。升级是即时的;降回来需要 downgradeMemory 次连续的决定性 fast 判定。判定不确信时一律保持原位,绝不猜测。
- 可插拔的裁判来源 —— 判定默认来自 Fast 链;routing.judge.mode 可以把它指向一条专用裁判链(custom),或指向决策模型(decision —— TypeSafe Jev / System One 这一类,Beta):它返回的是带类型的选项与概率而不是散文,因此没有回复解析步骤,也不存在"回复格式坏了"这一类失败。本部署对真实端点的实测:协议正确、每次判定 1.4–5.7 秒(15 秒下限是实测需要——5 秒默认值会把其中两次直接掐断),且 4 个 prompt 的档位判定全部是完全确定的结果,所以请把它当作硬分类器而不是细腻的连续判断;只有编排信号是连续的(0.10–0.83)。任何已配置的来源不可用时都会回落 Fast 链;而完全没有裁判时路由器就停止路由——本轮改用你自己选定的模型、编排被清除,且每个会话只提示一次。
- 缓存感知路由 —— 当 Fast 与 Smart 共享同一 provider 时,决策门槛会除以 sameFamilyPenalty(默认 1.5),并在 prompt 缓存仍热时抑制降级,避免切到便宜模型反而更贵。
- 运行时故障转移 —— 429 / 402 / 5xx / 配额 / 用量上限 / 模型下线 等失败会把模型置入指数退避冷却(1m → 4m → 16m → 1h04m → 4h16m,上限 6h;客户端侧限流从 16m 起步),并在同一层内重新解析到下一个健康模型——同一轮内重试,绝不跨层。
- 任务级编排 —— 复杂任务会让 Smart 层担任 CTO:规划、通过 harness 的 subagent 工具把实现委派给 Fast 层工程师子代理、逐个审查结果并迭代。硬上限由插件强制执行而非仅靠提示词:每次委派计一轮、连续工作代理失败计一次升级,一旦触顶 subagent 工具会被直接拒绝、系统提示词切换为"立即收尾"通知。
- 成本遥测 —— 按层统计 token,可选的 USD 计价表(/router status 会显示"本次会话若全程使用 Smart 模型将花费多少")。吞吐速率不在此列:DSH 原生已在消息页脚与 trajectory 面板显示 tok/s,且按解码时间计算,口径更准。
- 动作可见 —— 切换档位或模型时会往对话里写一条 [shift-router] Fast → Smart · … 通知(harness 没有给插件预留状态栏座位),所以插件启用后不会"静默地什么都没发生"。把 ux.routerLogVerbose 打开,则每一轮判定都会有一条通知,而不只是切换时。
- 零配置启动 —— 未配置分层前完全无操作;配置完成后路由立即生效。配置可通过 GUI 设置面板 和 /router config 命令实时编辑(持久化,无需重启)。
安装
本包是一个 DSH bundle:cordis.patch.yml 会把插件行插入任何声明了它的 profile。下面每条通道最后都是同一条 dsh plugin --profile <name> add …——它在 profile 目录里转发给 pnpm。
从 npm 安装(推荐)
dsh plugin --profile web add dsh-shift-router
安装的是预构建产物:不会在你的机器上运行任何构建脚本,因此无需任何授权。
从 tarball 安装
npm pack # 或下载 release 里的 tarball
dsh plugin --profile web add ./dsh-shift-router-0.7.0.tgz
同样是预构建产物;无法访问 registry 时用这条。
从 git 安装
dsh plugin --profile web add github:green-dalii/dsh-shift-router#v0.7.0
git 安装拉到的是源码而非构建产物,因此由包的 prepare 脚本构建 dist/。pnpm ≥ 10 默认拒绝 git 依赖的 prepare——若第一次 add 失败,把 pnpm 打印的确切包键复制进 profile 的 pnpm-workspace.yaml 后重新执行:
allowBuilds:
dsh-shift-router: true
这等于允许该包的代码在安装时于你的机器上执行,且不在 agent 沙箱内。请锁定 tag 或 commit(…#v0.7.0、…#<sha>),避免后续 push 悄悄改变你实际运行的内容。
从本地检出安装(开发用)
git clone https://github.com/green-dalii/dsh-shift-router.git
cd dsh-shift-router && npm install && npm run build
dsh plugin --profile web add /path/to/dsh-shift-router
确认这一层已生效
dsh --profile web --dump-config | grep -A3 'id: shift-router'
插件无需任何配置即可加载(所有默认值都安全);分层模型来自设置卡片(SPEC §12)或 profile 的 patch 行。后应用的层胜出,且 patch 会替换目标行的整个 config 值——覆盖本行的 patch 必须重述它需要的每一个键(SPEC §10)。
热重载
DeepSeek Harness 通过 @deepseek-ai/cordis-plugin-hmr 支持热重载,但有两点需要了解:
1. 官方 Web bundle 默认禁用了共享 HMR 行(packages/bundle/web-app/cordis.patch.yml 中是 - id: hmr, disabled: true,上游 TODO:"在 Web 的重载生命周期测试通过后重新启用共享 HMR")。在 profile patch 中重新启用它——这是文档化的覆盖机制:
~/.dsh/profiles/<name>/cordis.patch.yml
- id: hmr
disabled: false
2. 哪些能热重载、哪些不能(已对照当前实现实测):
- ✅ 配置改动 —— 编辑 profile patch(或 home patch)会以新配置重新执行受影响插件的 apply(),无需重启。插件自身配置也通过 settings 命名空间热生效(/router config set 与 GUI 卡片本来就不依赖 HMR)。
- ❌ 模块(代码)改动 —— 当前 HMR 的 accepted 依赖图只覆盖 harness 自身模块;修改外部插件的编译产物(如 dist/index.js)在现行版本中不会触发重载,因此代码改动仍需重启。这正是上游 TODO 所指的未经测试的 "reload lifecycle",不是本插件的局限。
- ❌ client 包元数据 —— dsh.client manifest 与 exports["./client"] 在进程内缓存,新增/修正后必须重启 profile;仅 dist/client.js 内容变化可走 client HMR 重建链。
实践建议:用 /router config / 设置面板做配置(始终实时);改模型就编辑 patch(开启 HMR 后实时);只有改动插件代码时才需要重启。
配置
配置位于 shift-router settings 命名空间:可在 GUI 的 左侧栏「插件」 → dsh-shift-router → shift-router 行 → 配置中编辑、用 /router config 命令修改,或通过 profile patch 行配置。所有字段都有安全的默认值。
唯一必须由你决定的是档位模型:docs/MODELS.zh-CN.md 说明如何挑选 Fast 与 Smart 模型(Fast 链默认同时充当裁判链)、什么样的模型适合做回退、以及哪些模型能接收图片。
| 字段 | 默认值 | 说明 |
| enabled | true | 总开关 |
| tiers.fast.models | [] | Fast 层模型链(provider/model + priority);同时也是裁判的默认来源 |
| tiers.smart.models | [] | Smart 层模型链 |
| routing.mode | auto | auto(默认):裁判 + 路由 + 故障转移 + 编排;manual:无裁判,仅显式 /route-force 覆盖;off:模型选择完全被动(命令/遥测仍可用) |
| routing.judgeTimeout | 5000 | 裁判调用超时(毫秒)。decision 模式下下限被抬高到 15000——实测一次决策判定需要 1.4–6.6 秒 |
| routing.judgeMaxTokens | 4000 | 单次裁判调用最大输出 token |
| routing.judgePromptCap | 6000 | 发送给裁判的最大 prompt 字符数(限制裁判成本) |
| routing.judge.mode | fast-chain | 判定来自哪里:fast-chain(Fast 链)、custom(routing.judge.models)、decision(决策模型)。只写了 models 而没有 mode 时会迁移为 custom;无法识别的取值回落 fast-chain 并记日志 |
| routing.judge.models | [] | custom 模式下的专用裁判链(provider/model + priority,priority 升序)。绝不用更便宜的模型替代——链不可用时回落到 Fast 链 |
| routing.judge.decision.baseUrl | '' | 决策模型的基础 URL,会拼接 /v1/systemone。空 = 未配置 |
| routing.judge.decision.model | jev-latest | 向决策端点请求的模型。响应会回报解析后的真实 id,变化时会记日志——别名正是这样才能保持可观测 |
| routing.judge.decision.apiKeyRef | '' | 保存该端点密钥的凭据名,每次调用都通过 harness 凭据 seam 解析(轮换后的密钥下一次判定即可生效)。空 = 使用环境自带认证 |
| routing.economics.reworkPenalty | 3 | R —— 一次错误降级的返工代价(以价差为倍数)。当且仅当 pSmart ≥ θ 时走 Smart,θ = 1/R:R 越大 θ 越小,越黏在 Smart |
| routing.economics.downgradeMemory | 2 | Smart → Fast 所需的连续决定性 fast 判定次数(hold 或 smart 判定都会打断连击) |
| routing.economics.mode | (未设置) | 命名档位预设,优先级高于 reworkPenalty:eco(R=2, θ=0.5) / default(R=3, θ≈0.33) / sport(R=5, θ=0.2) |
| routing.window.size | 5 | 决策记忆窗口大小 |
| routing.window.threshold | (未设置) | 遗留原始 θ 覆盖值。EV 之前的默认值 0.6 已失效;只有不同取值才生效(并在 /router status 标记 ⚠ legacy) |
| routing.window.minConfidence | 0.5 | 低于此置信度的判定按 hold 处理(不切换、不计入连击) |
| routing.cacheAware.enabled | true | 同 provider 缓存保护 |
| routing.cacheAware.sameFamilyPenalty | 1.5 | 两层共享 provider 时对 θ 的除数——门槛更低意味着降级更少,热缓存存活更久 |
| routing.cacheAware.idleBoundaryMs | 300000 | 热缓存被认为变冷前的空闲间隔 |
| routing.cacheAware.sameFamilyThreshold | (未设置) | 遗留哨兵。EV 之前的默认值 0.9 已失效;不同取值等价于 sameFamilyPenalty = 3.0 |
| orchestration.mode | auto | auto:复杂任务 → Smart CTO;off:仅普通双层路由 |
| orchestration.maxRounds | 3 | 委派→审查轮次硬上限(强制执行:每次 subagent 委派计一轮;触顶后拒绝 subagent 工具) |
| orchestration.escalationThreshold | 2 | 连续工作代理失败计一次升级;工作代理成功会清零连击。达到上限后 Smart 必须亲自接管,且 subagent 工具被拒绝(强制执行) |
| orchestration.maxSpendUsd | 0 | 单个编排任务的硬预算(USD);0 表示不启用。它是 capHit 的一部分,触顶即拒绝继续委派。需要 pricing 才有意义——未配置定价时花费合理地保持为 0 |
| orchestration.workerLedgerCap | 20 | 状态报告保留的每 worker 成本行数(超出丢最旧)。任务总额是权威值、不受影响 |
| orchestration.audit.enabled | true | 在一次确实委派过的运行结束后审计验收声明:每个 worker 是否都回报、是否存在 CTO 总结,以及(一次小的 Fast 档调用)声明是否有 worker 结果支撑 |
| orchestration.audit.timeoutMs | 5000 | 审计调用预算。免费的确定性检查总会执行 |
| orchestration.audit.promptCap | 6000 | 审计提示词字符上限——既是成本上限,也决定保留多少 worker 证据 |
| failover.baseMs | 60000 | 5xx 失败的冷却基础延迟(1 分钟) |
| failover.maxMs | 21600000 | 退避阶梯硬上限(6 小时) |
| failover.startAttempts4xx | 3 | 4xx(429/402/配额)失败从该尝试次数起步(16 分钟),客户端限流通常比服务端抖动更持久 |
| telemetry.callLogCap | 1000 | 基线成本计算保留的最大逐条消息归属记录数 |
| ux.routerLogVerbose | false | 把路由决策打印到本插件的 ctx.logger,并在每一轮判定后写一条路由通知(包括保持原位的轮次;而 release——完全没有裁判——每个会话只通知一次,不是每轮一次)。DSH 自带 profile 未挂载任何日志导出器,所以日志只在额外挂载导出器的部署可见;通知与 /router status 才是始终可用的界面 |
| ux.promptSectionOrder | 150 | 编排器系统提示词段落的排序位置。DSH 集中分配提示词顺序(SECTION_ORDERS),未给第三方段落预留槽位,因此这是配置项而非常量 |
| pricing | [] | 可选 {provider, model, input, output, cacheRead?, cacheWrite?} 每百万 token 的 USD 计价表,用于成本遥测 |
所有数字字段都经 schema 范围校验(如 window.minConfidence 必须在 [0,1]、window.size 必须是正整数);非法值在加载 / set 时被拒绝,绝不静默接受。
从 v0.5.0 升级: 路由决策会立即发生变化(无需改配置)——决策规则从"数窗口票数"改为"权衡期望成本",另有两个遗留旋钮的含义变更。详见 SPEC.md §15 与 CHANGELOG.md 的 [0.6.0] 段。
GUI 配置卡片
插件随包构建一个浏览器端(client)模块,在 GUI 的设置页注册一张 「Shift-Router」 卡片:
- 位置(DSH 0.2.0-rc.2 及以后):左侧栏 「插件」 页 → dsh-shift-router 卡片 → shift-router 行 → 该行的「配置」按钮。完整表单同时出现在 bundle 自己的页面上,两条路径都能到。卡片注册进 plugins.row.config(键 dsh-shift-router#shift-router)与 plugins.bundle.config(键 dsh-shift-router),两者都由官方 dsh-client-ui-plugin-manager 声明(0.2.1-rc.2 仍原样保留);设置传输用 ctx.configForms。
- 位置(≤ 0.1.5-rc.x):设置 → 内置插件 → 可配置页;卡片占用 keyed 的 settings.plugin.item 单元格(key: 'shift-router'),传输用 ctx.settingsScope。每一代只声明三个槽位里的一个,所以面向另一代的注册保持静止。
- 支持的 DSH 范围:engines.dsh = ">=0.2.0-rc.2 <0.3.0-rc.0"。0.2.1 起该字段单独决定兼容性(上游 evaluatePluginCompatibility:engines.dsh 声明后 peer 不再参与门禁);单元门禁直接调用上游评估器,见 tests/engines-dsh-compat.test.ts。
- 能力:以表单编辑全部标量叶子字段(开关、数字、枚举)以及模型链(两层,外加一条专用裁判链),分七个分组(通用 / 模型 / 路由 / 编排 / 故障转移 / 遥测 / 日志与体验),路由分组下再分子组(裁判 / 裁判来源 / 决策窗口 / 缓存感知)。控件只在与当前选择相关时出现——选定裁判来源就只显示该来源自己的设置,其余隐藏——且任何下拉都不会出现原始配置取值。标量字段采用紧凑的「设置行」版式——左侧标签 + 说明,右侧同行右对齐控件——每个字段只占一行,不再上下堆叠三层。控件全部使用宿主平面设计令牌:开关用拨动开关(浅色/深色主题下对比度都清晰)、枚举用带箭头的下拉、数字输入框内嵌单位后缀(ms、tokens、0–1 等)、模型链用有序行编辑器——行的顺序就是层内回退顺序:优先命中排在最前的可用模型,其余作为后备。provider/model 下拉自动载入 DSH 运行时模型目录(llm.models,与设置页模型目录同源):只列出当前有模型清单的 provider,无休眠目录噪音,且插件不硬编码任何模型,跟随任何部署的 DSH 实际配置。另有「自定义…」入口填写目录之外的取值。分段保存、单字段恢复默认与覆盖标记与官方卡片完全一致。
- 边界:仅 pricing(可选的 USD 计价表)仍由 /router config 或 patch 行编辑;模型链——两层以及裁判那条——都可以在卡片中直接编辑。
- 构建:npm run build 会同时产出 host 产物(dist/index.js)与 client 产物(dist/client.js)。client 模块通过 dsh.client manifest 被 dsh-client-modules 扫描,要求插件以包名(dsh-shift-router)挂载——源码检出式 patch(name: '/path/dist/index.js')不会提供卡片。
仅旧版 harness 需要:Web 设置白名单(≤ 0.1.0-rc.x)
0.1.0-rc.x 及更早的 harness 会把第三方 settings 命名空间从浏览器的 settings.describe 响应里过滤掉,除非它出现在 WEB_SETTINGS_NAMESPACES 中——这正是 scripts/expose-gui-settings.mjs 存在的原因:它修改 profile 里已安装的 dsh-host-apiproxy(幂等;升级依赖后重跑)。从本项目的基线 0.1.5-rc.2 起,该包与白名单 均已移除,命名空间原生暴露,脚本会输出「不需要」并以 0 退出。该脚本不在发布包内(files),只能从源码检出获得。
命令
| 命令 | 作用 |
| /router | 简洁状态 |
| /router status / /router stats | 完整状态:档位(R → θ)、分层、决策窗口(hold 显示为 h)、上一次判定及其原因、实际运行的模型 vs 路由器意图、切换记录、冷却、token、成本遥测 |
| /router on / /router off | 启用 / 停用(会话级) |
| /router verbose / /router log | 详细日志开关 |
| /router orchestrate auto\|off | 编排模式 |
| /router allow-workers [on\|off] | 把本插件的 Fast 链写入 harness 的 subagent-model-selection-settings 白名单,使 worker 可被固定到 Fast(off 只撤销授权、保留路由)。会如实回报写入内容或失败原因 |
| /router eco / /router default / /router sport | 档位预设:设置 routing.economics.mode(持久化)——更省 ↔ 更黏在 Smart |
| /router config | 交互式编辑器:带编号的字段列表(含当前值)+ 可用 providers + 用法 |
| /router config get <N\|path> | 显示单个字段当前值,如 get 4 或 get routing.judgeTimeout |
| /router config set <N\|path> <value> | 设置单个字段(持久化),如 set 4 8000、set tiers.fast.models [...](JSON 值自动解析) |
| /router config unset <N\|path> | 清除用户覆盖——字段回退到组合默认值 |
| /router config diff | 列出用户层当前持有的覆盖项 |
| /router config set-fast <provider/model> | 用单个模型替换 Fast 层模型链 |
| /router config set-smart <provider/model> | 用单个模型替换 Smart 层模型链 |
| /router config reset | 恢复组合默认值 |
| /route-force <fast\|smart\|auto\|provider/model> | 强制下一轮走某层/某模型(一次性) |
工作原理(DSH 集成)
机制到机制的逐项映射是规范,只在 SPEC.md §1.1。这里有两点值得单独说明,因为它们不在那张表里:
- 吞吐速率刻意不在此列。 DSH 原生渲染 tok/s(消息页脚、trajectory 面板),口径是解码时间;路由器负责路由决策与花费,不负责速率展示。
- 子代理永不被路由。 subagent 工具派生出的 worker 带 session.header.origin === 'subagent' 并保持其被钉住的模型;路由器只驱动顶层 agent 的轮次。
任务级编排
轮次级路由决定用哪个模型跑这一轮;任务级编排决定复杂任务怎么执行。当裁判判定 smart 且 orchestration.mode 为 auto(默认)时,路由器把这一轮交给 Smart 层担任 CTO:它制定计划、通过 harness 的 subagent 工具把实现委派给 Fast 层 worker、逐个审查结果并迭代——最后由一次独立的验收审计核对它的说法。fast 判定永远不会触发这些。
一轮编排是怎么跑的
1. 进入 —— 决策档位是 Smart、subagent 工具存在、模式为 auto;编排器指令以系统提示词段落注入(SPEC §7.2)。
2. 委派 —— CTO 调用 subagent;每次调用算一轮,且在派发时计数(派发出去的委派已经花掉了预算,这样 maxRounds 才是真正的上限)。
3. 审查与迭代 —— worker 失败会推进失败连击;收敛协议要求每次重派都携带结构化的 ## Failure report(什么失败、在哪、用哪个验收测试复测),重复同一反馈即触发接管(SPEC §7.2.1)。
4. 停止 —— 触顶后 tools/pre-execute 直接拒绝 subagent 工具、提示词段落切换为「立即收尾」;agent/turn-stopping 释放状态。编排是单轮的:不跨轮,泄漏的运行会在下一轮开始时清扫。
硬上限(由路由器强制执行,而非仅写在提示词里)
| 设置 | 默认值 | 作用 |
| orchestration.maxRounds | 3 | 每个任务的委派轮数 |
| orchestration.escalationThreshold | 2 | 连续多少轮 worker 失败后,Smart 层自己接管该阶段 |
| orchestration.maxSpendUsd | 0(不设闸) | 达到 USD 预算即停止委派,按 pricing 表计价 |
| orchestration.workerLedgerCap | 20 | 保留用于展示的每 worker 成本行数 |
验收审计(安全网,从不是门禁)
硬上限能防止跑飞,防不住 CTO 声称验收了却其实没核对。因此真正委派过的运行会被审计:确定性检查总是跑(每个派发出去的 worker 都回报了、存在 CTO 总结、没有被上限截断),并在 orchestration.audit.enabled 时追加一次小的 Fast 层复核,读取目标、总结与 worker 结果。它从不阻塞轮次:LLM 那一半是分离执行的,结论以 Last audit: 出现在 /router status。
worker 的模型需要授权
上游把「每 worker 的模型钉定」称为强制:worker 若继承父会话的模型,编排中途那已是 Smart,经济学前提直接崩塌。DSH 里这个钉定居于宿主持有的白名单之后(subagent-model-selection-settings,默认 关闭)。/router allow-workers 帮你把 Fast 链写进去;未授权时路由器会在 Worker delegation: 行里如实说明,而不是假装可以(SPEC §7.4)。
怎么知道它发生了
/router status 会显示 🪄 active (round x/y, esc a/b, fail streak n),worker 回报后追加 Orchestration spend: $X · N/M workers reported,审计结束后还有 Last audit: …。进入编排时还会往对话里写一条路由通知(SPEC §13.1),所以不必去读计数器也能看出这一轮的形态。
什么时候不触发
fast 判定;orchestration.mode: off(或 /router orchestrate off);组合里没有 subagent 工具;或解析不到 Smart 模型——这些情况下这一轮就只是跑在 Smart 上,没有委派、也没有审计。
开发
npm run build # tsc(host → dist/)+ tsc client + tsdown(client bundle → dist/client.js)
npm test # vitest(24 个文件、429 个测试:EV 路由 / 故障转移签名 / 裁判解析与提示词契约 / 裁判来源与可用性阶梯与决策协议 / 编排 / 配置 schema 与迁移 / 遥测 / 路由通知 / release 装配 / 配置注册表与 GUI 表单模型 + 卡片 UX + 模型目录 / 打包安装契约)
npm run typecheck
端到端测试(无需凭证)
npm run test:e2e
该脚本会建一个临时 DSH_HOME,把本检出作为 bundle 装进派生出的 headless profile,用假适配器跑一轮,并断言:
- ROUTER-E2E: turn ran on fake/fake-smart notice=yes —— 裁判确实跑了、EV 规则确实升级了、真的切换了上线模型到 Smart 层,并且 [shift-router] 路由通知确实进入了模型请求(SPEC §13.1);
- 在 e2e/legacy-config-overlay.yml 下(对齐前配置:遗留旋钮处于旧默认值 + 已被移除的 requireSmartModel 键)结果相同 —— 覆盖的是升级路径,不只是全新安装;
- 在 e2e/orchestration-overlay.yml 下结果相同 —— 使用插件的默认编排模式(auto),并挂载 web 专属的 subagent-model-selection-settings 行,即曾经导致启动失败的那个组合;
- shift-router settings 命名空间能完成一次写入并读回,且 Host 模型目录确实广告出该部署配置的路由(e2e/settings-probe.mjs);
- 打包产物安装(npm pack → tarball → 第二个 scratch profile)能带着插件启动,浏览器端被提供给 client 模块加载器,且 profile 里没有任何 @deepseek-ai/* 副本 —— 那里没有 devDependencies,因此"运行时导入了未向消费者声明的包"会在 e2e 失败,而不是在用户机器上失败。
它不会碰你真实的 DSH_HOME,跑完自行清理(加 --keep 可保留现场)。手工复现:
DSH_HOME=/tmp/scratch dsh plugin --profile tmp add /path/to/dsh-shift-router
DSH_HOME=/tmp/scratch dsh --profile tmp --patch e2e/overlay.yml "design a migration plan"
架构
仓库结构与模块地图(纯逻辑/接线分工、测试分层)以 CONTRIBUTING.md 的 Repository layout 一节 为唯一权威,这里只留指针:src/ 是 host 半边(纯决策模块 + index.ts 里的 DSH 接线),src/client/ 是浏览器半边(设置卡片),tests/ 覆盖两者,e2e/ 启动 scratch profile——包括打包产物。
另见
- pi-shift-router —— 本插件所适配的上游项目:同一套双层架构(LLM 裁判、回退链、指数退避故障转移、任务级编排),面向 pi-coding-agent。
行为对齐与刻意不对齐之处记录在 ALIGNMENT.md。
- dsh-plugin-dev-skill —— 开发 DSH 插件的 Agent 技能:工具(defineTool)、LLM 适配器、服务、事件、配置与打包,含 Cordis 心智模型与验证清单。本项目遵循它;可在 DSH、Claude Code 或 Codex 中安装。
- obsidian-llm-wiki —— 把笔记与 PDF 变成互链、可查询知识库的 Obsidian 插件(实体页与概念页、图检索问答、本地优先、无后端)。同一作者的另一条产品线。
许可证
MIT © 2026 green-dalii and contributors.预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
green-dalii/dsh-shift-router
面向 DeepSeek Harness 的双层模型路由器 —— LLM 裁判按期望成本把每一轮交给便宜的 Fast…
相关插件 · 模型接入
API 中继安全审计toby-bridges/api-relay-audit
面向 AI API 中转与 LLM 代理的本地安全审计。
★ 897已汉化DSH
69.4
免费搜索插件DDDMUC/dsh-free-search
DeepSeek Harness 免费搜索插件 —— 无需 API key,零成本,多引擎可切换。 一个插件,给…
★ 850已汉化DSH
68.9
免费联网搜索liustack/modsearch
在官方 App 里模型能联网,切到 API 就不能了。ModSearch 把联网补回来:网页搜索、X…
★ 863已汉化DSH
68.5
OpenCode 免费模型FishBottle7/opencode2dsh
在 DSHDeepSeek Harness里原生使用 OpenCode Zen 的免费匿名模型。
★ 385已汉化DSH
67.9
AI 模型网关tingly-dev/tingly-box
Tingly Box Web UI 演示
★ 373已汉化DSH
67.4
WorkBuddy 账号池XDTrees/dsh-xdpool
把你能白嫖的模型额度接进 DSH 同一个池:WorkBuddy 多账号自动容错、十三家扫码登录、76…
★ 359已汉化DSH
67.1
这是你的仓库?认领条目