DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

Shift Router — DeepSeek Harness 插件(DSH Plugin)
DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins

dsh-shift-router

Shift Router

适用于 DeepSeek Harness 的双层模型路由器——通过 LLM Judge 自动进行执行/判断路由,支持多模型回退链和采用指数退避的运行时故障转移。pi-shift-router 的 DSH 适配版本。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add dsh-shift-router@0.6.0
README兼容性版本

兼容性与来源证明

Shift Router 以 dsh-shift-router 发布,当前版本为 0.6.0。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
npm
Registry 更新时间
2026/9/21

版本

0.6.0stable
2026/9/21

相关插件

正在加载相关插件…

最新版
0.6.0
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
999.1 kB
文件数
69
Surface
web
许可证
MIT
发布源
npm
GitHub
★ 2
周下载
0
最近提交
2026/9/23
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题

相关插件

继续浏览 models-usage 分类下经过校验的插件。

Usage@linxin666/dsh-usage用于 dsh Web GUI 的使用统计插件:检测各提供商的余额和编程套餐配额,并实时记录令牌使用情况;侧边栏 Settings 行上方显示紧凑的价格概览卡片Whale Widgetdsh-whale-widgetDSH Web 界面右下角的 DeepSeek 余额小鲸鱼挂件:余额/今日已用/峰谷定价、自定义泡泡点击序列(文本/余额/今日/峰谷/图片/随机语句与并列加权选择)、逐行样式与字体、悬浮快捷编辑、音效与每轮消耗、自定义角色/动图/音效、吸附与翻转自定义Cost Meterdsh-cost-meterDeepSeek Harness 会话费用统计插件:本会话成本、当日费用、历史记录与官方价格同步,支持多厂商多模型价格计费(内置 90+ 模型价格目录与自动匹配)、主流 Coding Plan 订阅额度查询与显示(11 家,含小米 MiMo Token Plan 控制台 Cookie 查询、SCNet Token Plan 本地 Credits 计量与火山方舟 Volcano Ark Coding Plan AK/SK 签名查询)、自定义 Provider 余额查询(可配任意 HTTP 端点)与余额进度条Commandcode Provider@mars-sea/dsh-commandcode-provider适用于 Command Code 的非官方 DeepSeek Harness LLM 提供商插件,移植自 pi-commandcode-provider(MIT)。注册“commandcode”提供商路由,并在 Models 页面添加卡片和实时模型目录。

README

English · 简体中文

dsh-shift-router

A two-tier model router for DeepSeek Harness — automatic execution/judgment routing with an LLM Judge, multi-model fallback chains, exponential-backoff runtime failover, and task-level orchestration.

A DSH adaptation of pi-shift-router. Ported from upstream v1.0.0; aligned with upstream v1.6.0 — see ROADMAP.md for the per-version table and SPEC.md for the contract.

Routine turns shouldn't cost flagship money. The turns that matter shouldn't be left to a cheap model.

Before every turn of a top-level agent, a small LLM Judge (running on your Fast-tier model chain) classifies the user's message as fast (routine) or smart (consequential). The chosen tier then drives the whole turn — thinking, tool calls, code edits — through the harness's own agent/request pipeline. The Judge only classifies; it never does the work.

🦾 [deepseek-v4-flash] → fix the failing test
🧭 judging…
🧠 [deepseek-v4-pro]   ← "design the auth flow" → upgraded instantly
⚠️ deepseek-v4-flash 429 → cooldown, retrying on glm-5.2 — retry in 1m
🦾 [glm-5.2]           ← same-tier failover

Features

  • Expected-cost routing — the turn runs Smart iff pSmart ≥ θ, with θ = 1/reworkPenalty: the bar is price-independent, so the one knob is how badly a wrong downgrade hurts. Upgrades are instant; coming back down needs downgradeMemory consecutive decisive fast turns. A Judge outage or an unsure verdict is a hold — the router keeps its position instead of guessing.
  • Cache-aware routing — when Fast and Smart share a provider, the decision bar is divided by sameFamilyPenalty (default 1.5) and downgrades are held off while the prompt cache is warm, so switching to a cheaper model never costs more than staying put.
  • Runtime failover — 429 / 402 / 5xx / quota / usage-limit / unsupported-model failures put the model into exponential-backoff cooldown (1m → 4m → 16m → 1h04m → 4h16m → 6h cap; client-side limits start at 16m) and re-resolve the same tier to the next healthy model — same-turn retry, never cross-tier.
  • Task-level orchestration — complex tasks run the Smart tier as a CTO that plans, delegates implementation to Fast engineer subagents via the harness's subagent tool, reviews each result, and iterates. The hard caps are enforced by the plugin, not just prompted: each delegation counts a round, consecutive worker failures count an escalation, and once a cap is hit the subagent tool is denied outright and the system prompt switches to a "wrap up now" notice.
  • Cost telemetry — per-tier token tracking and an optional USD pricing table (/router status shows "what this session would have cost on the Smart model").
  • Visible when it acts — a tier or model switch is written into the transcript as a [shift-router] Fast → Smart · … notice (the harness has no status-bar seat for plugins), so an enabled router is never silently invisible. Set ux.routerLogVerbose to get one notice per judged turn, not just per switch.
  • Zero-config startup — a no-op until you configure tiers; then routing just works. Configuration is editable live via the GUI settings panel and /router config commands (persisted, no restart).

Install

This package is a DSH bundle: its cordis.patch.yml inserts the plugin row into any profile that lists it. Every channel below ends in the same dsh plugin --profile <name> add …, which forwards to pnpm inside the profile directory.

From npm (recommended)

dsh plugin --profile web add dsh-shift-router

Installs the prebuilt artifact — no build script runs on your machine, so there is nothing to authorize.

From a tarball

npm pack      # or download the release tarball
dsh plugin --profile web add ./dsh-shift-router-0.6.0.tgz

Prebuilt as well, and the option to reach for when a registry is not available.

From git

dsh plugin --profile web add github:green-dalii/dsh-shift-router#v0.6.0

A git install fetches source, not artifacts, so the package's prepare script builds dist/. pnpm ≥ 10 refuses a git dependency's prepare until you allow it — if the first add fails, copy the exact key pnpm prints into the profile's pnpm-workspace.yaml and re-run:

allowBuilds:
  dsh-shift-router: true

This authorizes the package's code to execute on your machine at install time, outside the agent sandbox. Pin a tag or commit (…#v0.6.0, …#<sha>) so a later push cannot change what you actually run.

From a local checkout (development)

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

Verify the layer landed

dsh --profile web --dump-config | grep -A3 'id: shift-router'

The plugin loads with no configuration at all (every default is safe); tier models come from the settings card (SPEC §12) or from the profile's patch row. Later layers win, and a patch replaces the target row's whole config value — a row that overrides this one must restate every key it needs (SPEC §10).

Hot reload

DeepSeek Harness supports hot reload through @deepseek-ai/cordis-plugin-hmr, but two things are worth knowing:

  1. The official Web bundle ships the shared HMR row disabled (packages/bundle/web-app/cordis.patch.yml has - id: hmr, disabled: true, upstream TODO: "Re-enable shared HMR for Web after its reload lifecycle is tested"). Re-enable it in your profile patch — this is the documented override mechanism:

    # ~/.dsh/profiles/<name>/cordis.patch.yml
    - id: hmr
      disabled: false
    
  2. What hot-reloads and what doesn't (verified against the current implementation):

    • ✅ Configuration changes — editing this profile patch (or the home patch) re-runs the affected plugin's apply() with the new config, no restart. The plugin's own config is also hot through the settings namespace (/router config set and the GUI card apply live without HMR at all).
    • ❌ Module (code) changes — the HMR accepted-dependency graph currently covers the harness's own modules only; editing an external plugin's compiled files (e.g. dist/index.js) does not trigger a reload in the current release, so code changes still require a restart. This is the untested "reload lifecycle" the upstream TODO refers to, not a limitation of this plugin.
    • ❌ Client package metadata — the dsh.client manifest and exports["./client"] are cached in-process; adding/fixing them requires a profile restart (only dist/client.js content changes ride the client HMR rebuild chain).

    In practice: configure with /router config / the settings panel (always live), switch models by editing the patch (live once HMR is on), and restart only when you change plugin code.

Configuration

Configuration lives in the shift-router settings namespace: edit it in the GUI (Settings → Plugins → Plugin configuration — the "Shift-Router" card), with /router config commands, or via the profile patch row. All fields have safe defaults.

FieldDefaultDescription
enabledtrueMaster switch
tiers.fast.models[]Fast-tier chain (provider/model + priority); also the Judge's model chain
tiers.smart.models[]Smart-tier chain
routing.modeautoauto (default): judge + routing + failover + orchestration; manual: no judge, only explicit /route-force overrides; off: fully passive for model selection (commands/telemetry still work)
routing.judgeTimeout5000Judge call timeout (ms)
routing.judgeMaxTokens4000Max output tokens for a single Judge call
routing.judgePromptCap6000Max prompt characters sent to the Judge (bounds Judge cost)
routing.economics.reworkPenalty3R — how many price-deltas a wrong downgrade costs. The turn runs Smart iff pSmart ≥ θ, where θ = 1/R: higher R → lower θ → stickier on Smart
routing.economics.downgradeMemory2Consecutive decisive fast turns required before Smart → Fast (a hold or a smart verdict resets the streak)
routing.economics.mode(unset)Named gear preset, authoritative over reworkPenalty: eco (R=2, θ=0.5) / default (R=3, θ≈0.33) / sport (R=5, θ=0.2)
routing.window.size5Decision-memory window size
routing.window.threshold(unset)Legacy raw-θ override. The pre-EV default 0.6 is inert; only a different value is honoured (and flagged in )

All numeric fields are range-validated by the schema (e.g. window.minConfidence must be in [0,1], window.size a positive integer); invalid values are rejected at load / on set, never silently accepted.

Upgrading from v0.5.0: routing decisions change immediately with no config edit — the decision rule went from counting window votes to weighing expected cost, and two legacy knobs changed meaning. See SPEC.md §15 and the [0.6.0] section of CHANGELOG.md.

GUI configuration card

The package ships a browser-side (client) module that registers a "Shift-Router" card in the GUI settings page:

  • Where: Settings → Plugins → Plugin configuration (that page is provided by the official dsh-client-ui-settings-plugins; the card registers into the settings.plugin.item slot).
  • What: a form over every scalar leaf field (booleans, numbers, enums) plus the two tier model chains, grouped into seven sections (General / Models / Routing / Orchestration / Failover / Telemetry / Logs & UX) with sub-groups for the routing section (Judge / Decision window / Cache-aware). Scalar fields use the compact settings-row pattern — label + hint on the left, control right-aligned on the same line — so each field is one tight row instead of three stacked lines. Controls use the host-plane design tokens: toggle switches (contrast-safe in light and dark themes), a styled select for enums, unit suffixes inside numeric inputs (ms, tokens, 0–1, …), and an ordered row editor for model chains — the row order is the in-tier fallback order, so the first available model wins and the rest are its fallbacks. The provider/model dropdowns are auto-loaded from DSH's runtime model catalog (llm.models — the same catalog the DSH settings surface reads): only providers with a currently advertised model list appear, no dormant-directory noise, and nothing is hardcoded, so the card works with any deployment's configured models. A "Custom…" escape covers values outside the catalog. Staged saving, per-field reset to default, and override markers work exactly like the official cards.
  • Boundary: only pricing (the optional USD cost table) stays with /router config and the profile patch; the tier model chains are editable in the card.
  • Build: npm run build emits both the host artifact (dist/index.js) and the client bundle (dist/client.js). The client module is discovered through the dsh.client manifest by dsh-client-modules, which requires the plugin to be mounted by package name (dsh-shift-router) — a source-checkout patch (name: '/path/dist/index.js') does not serve the card.

Legacy harnesses only: the Web settings whitelist (≤ 0.1.0-rc.x)

Harness builds up to 0.1.0-rc.x filtered a third-party settings namespace out of the browser's settings.describe response unless it appeared in WEB_SETTINGS_NAMESPACES — which is why scripts/expose-gui-settings.mjs exists: it patches the profile's installed dsh-host-apiproxy (idempotent; re-run after a dependency upgrade). From 0.1.5-rc.2, this project's baseline, that package and its whitelist are gone and the namespace is exposed natively, so the script reports "not needed" and exits 0. It is not part of the published package (files), so it is only reachable from a source checkout.

Commands

CommandEffect
/routerCompact status
/router status / /router statsFull status: gear (R → θ), tiers, decision window (holds shown as h), the last decision and why, the model that actually ran vs the router's intent, worker delegation (Worker delegation:), transitions, cooldowns, tokens, cost telemetry
/router on / /router offEnable / disable (session-scoped)
/router verbose / /router logToggle verbose router logging
/router orchestrate auto|offOrchestration mode
/router allow-workers [on|off]Authorise this plugin's Fast-tier routes in the harness subagent-model-selection allowlist, so workers can be pinned to Fast (off revokes, keeping the routes). Reports exactly what it wrote, or why it could not
/router eco / /router default / /router sportGear presets: set routing.economics.mode (persisted) — cheaper ↔ stickier on Smart
/router configInteractive editor: numbered field list with current values + available providers + usage
/router config get <N|path>Show one field's current value, e.g. get 4 or get routing.judgeTimeout
/router config set <N|path> <value>Set one field (persisted), e.g. set 4 8000, set tiers.fast.models [...] (JSON values auto-parsed)
/router config unset <N|path>Clear a user override — the field reverts to its composition default
/router config diffList the overrides the user layer currently holds
/router config set-fast <provider/model>Replace the Fast tier chain with one model
/router config set-smart <provider/model>Replace the Smart tier chain with one model
/router config resetRestore the composition default

How it works (DSH integration)

The mechanism-by-mechanism mapping is normative and lives in SPEC.md §1.1. Two things are worth stating here because they are not in that table:

  • Throughput is deliberately absent. DSH renders tok/s natively (chat footer, trajectory panel) from decode time; the router owns routing decisions and spend, not rate display.
  • Subagents are never routed. Workers spawned by the subagent tool carry session.header.origin === 'subagent' and keep their pinned model; the router drives top-level agent turns only.

Orchestration and the DSH subagent tool

Upstream calls the per-worker model pin mandatory: without it a worker inherits the parent's model — Smart mid-orchestration — and the economics collapse. In DSH that pin sits behind a host-owned allowlist (subagent-model-selection, default off), so instead of asserting a guarantee it cannot keep, the router:

  1. writes the Fast chain into that allowlist for you (/router allow-workers — the one step it cannot take at composition time);
  2. says so where you can read it when the allowlist is absent: a Worker delegation: line in /router status (the ctx.logger copy is visible only where a log exporter is mounted);
  3. tells the CTO, factually, where a worker's model comes from.

The caps (maxRounds, consecutive-failure escalation, maxSpendUsd) are enforced by the router, not merely prompted: at the cap the subagent tool is denied and the prompt section switches to a wrap-up notice, with live counters in /router status. A run that actually delegated is also audited — deterministic checks always, one detached Fast-tier review when enabled, never blocking a turn — surfacing as Last audit:. Contracts: SPEC §7.3, §7.4, §7.4.1.

Development

npm run build       # tsc (host → dist/) + tsc client + tsdown (client bundle → dist/client.js)
npm test            # vitest (336 tests across 18 files: EV routing / failover signatures / judge parsing + prompt contract / orchestration / config schema + migration / telemetry / route notices / config registries + GUI form model + card UX + model catalog / packaged-install contract)
npm run typecheck

End-to-end test (no credentials)

e2e/ contains a fake LLM adapter that registers the fake provider, so the whole routing pipeline can be exercised without any API key:

npm run test:e2e

That builds a throwaway DSH_HOME, installs this checkout as a bundle into a derived headless profile, runs one turn through the fake adapter, and asserts:

  • ROUTER-E2E: turn ran on fake/fake-smart notice=yes — the Judge ran, the EV rule escalated, the wire model was actually switched to the Smart tier, and the [shift-router] route notice reached the model request (SPEC §13.1);
  • the same outcome under e2e/legacy-config-overlay.yml, a profile patched with the pre-alignment config (the legacy knobs at their old defaults plus the removed requireSmartModel key) — i.e. the upgrade path, not just a fresh install;
  • the same outcome under e2e/orchestration-overlay.yml, which uses the plugin's default orchestration mode (auto) and mounts the web-only subagent-model-selection-settings row beside it — the composition that once aborted the boot;
  • the shift-router settings namespace round-trips a write, and the Host model catalog advertises the deployment's configured routes (e2e/settings-probe.mjs);
  • a packed install (npm pack → tarball → second scratch profile) boots with the plugin loaded, its browser half offered to the client module loader, and no @deepseek-ai/* copy installed into the profile — devDependencies are absent there, so a runtime import that is not declared for the consumer fails in the e2e instead of in a user's install.

It never touches your real DSH_HOME and cleans up after itself (--keep to inspect). To run the same thing by hand, install the bundle into a scratch profile and apply the overlay:

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"

Architecture

src/
├── index.ts        # plugin entry: event wiring, per-agent state, judge, route notices
├── config.ts       # Schemastery schema + deep-merge normalization
├── types.ts        # shared types + defaults
├── router.ts       # pure routing engine (upgrade/downgrade/window/cache-aware)
├── judge.ts        # LLM Judge via ctx.llm.stream() + reply parsing
├── failover.ts     # exponential-backoff cooldown state machine
├── tier.ts         # tier model resolution + display
├── notice.ts       # pure: route-notice text + summary (SPEC §13.1)
├── orchestrate.ts  # orchestrator prompt + lifecycle + caps
├── audit.ts        # non-blocking acceptance audit of delegated runs
├── stats.ts        # telemetry snapshot (tokens / cost estimate / savings baseline)
├── commands.ts     # /router and /route-force
└── client/         # browser half (GUI settings card)
    ├── index.tsx       # client entry: registers into the settings.plugin.item slot
    ├── controller.ts   # staged form → settings-scope writes (one per section)
    ├── form-model.ts   # pure logic: field registry / draft parsing / save plan
    ├── card-ux.ts      # pure logic: thresholds, chain problems, header summary
    ├── model-catalog.ts# Host model catalog → provider/model options
    ├── ShiftRouterCard.tsx  # card component (DSW design tokens)
    └── locales.ts      # zh/en dictionaries

Pure logic (router / failover / judge parsing / orchestration / audit / route notices / the form model, card UX and catalog loader) is unit-tested in isolation. Wiring is tested in two layers: tests/plugin-load.test.ts loads the plugin through a real Cordis context and drives the real agent/pre-step waterfall (so an undeclared service read, an invalid prompt-section order, or a missing route notice fails fast), and the e2e boots scratch profiles — including the packed artifact and the plugin's default orchestration mode.

License

MIT © 2026 green-dalii and contributors.

⚠ legacy
/router status
routing.window.minConfidence0.5Verdicts below this are treated as a hold (never a switch, never a streak entry)
routing.cacheAware.enabledtrueSame-provider cache protection
routing.cacheAware.sameFamilyPenalty1.5Divisor applied to θ when both tiers share a provider — a smaller bar means fewer downgrades, so the warm prompt cache survives longer
routing.cacheAware.idleBoundaryMs300000Idle gap before a warm cache is considered cold
routing.cacheAware.sameFamilyThreshold(unset)Legacy sentinel. The pre-EV default 0.9 is inert; a different value implies sameFamilyPenalty = 3.0
orchestration.modeautoauto: complex → Smart CTO; off: plain two-tier routing
orchestration.maxRounds3Delegate→review rounds hard cap (enforced: each subagent delegation counts one round; at the cap the subagent tool is denied)
orchestration.escalationThreshold2Consecutive worker failures that count as one escalation; a successful worker result resets the streak. At the cap Smart must take over and the subagent tool is denied (enforced)
orchestration.maxSpendUsd0Hard budget for one orchestrated task, in USD; 0 disables it. It is part of capHit, so reaching it denies further delegation. Needs a pricing entry to be meaningful — with no pricing the spend is legitimately 0
orchestration.workerLedgerCap20Per-worker cost rows kept for the status report (oldest dropped). The task total is authoritative and unaffected
orchestration.audit.enabledtrueAfter a run that actually delegated, audit the acceptance claim: every worker reported, a CTO summary exists, and (one small Fast-tier call) the claim is grounded in the worker results
orchestration.audit.timeoutMs5000Auditor call budget. The free deterministic checks always run
orchestration.audit.promptCap6000Character cap for the auditor prompt — the cost bound, and the cap that bounds how much worker evidence is kept
failover.baseMs60000Cooldown base delay for 5xx failures (1m)
failover.maxMs21600000Hard cap on the backoff ladder (6h)
failover.startAttempts4xx34xx (429/402/quota) failures start at this attempt (16m), client limits usually outlive server blips
telemetry.callLogCap1000Max per-message attribution records kept for baseline cost computation
ux.routerLogVerbosefalsePrint router decisions to the plugin's ctx.logger, and emit a route notice on every judged turn (including one that holds position). The stock DSH profiles register no log exporter, so the log lines are visible only where a deployment mounts one — the notice and /router status are the surfaces that always work
ux.promptSectionOrder150Sort position of the orchestrator system-prompt section. DSH allocates prompt order centrally (SECTION_ORDERS) and reserves no slot for third-party sections, so this is a setting, not a constant
pricing[]Optional {provider, model, input, output, cacheRead?, cacheWrite?} USD-per-1M-token table for cost telemetry
/route-force <fast|smart|auto|provider/model>Force the next turn to a tier/model (one-shot)