deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
INSTALL REFERENCE
dsh plugin --profile web add github:tianji-qingtian/dsh-model-router
该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。
PROJECT README
Model Router & Cost Optimizer for DeepSeek Harness (dsh). Answers simple questions directly on the cheap model (zero prefix, no cache tax), degrades gracefully on transient provider failures, and shows live per-session token / cache-hit / cost figures right under the composer.
The harness is in developer preview and iterates quickly — expect compatibility-breaking changes.
中文说明见 README.zh.md。
SIMPLE / AGENTIC, one word, 64-token cap, thinking off). The judge also sees the last assistant reply, so context-dependent follow-ups (它 / 这个 / 继续 …) are never misrouted to a context-free answer.⚡ 快速回答 / Quick answer · <model> marker (matched to the question language), the main model never runs for it, and no subagent sessions, relay cards, or toasts are created. The main session's model and prefix cache are never touched.deepseek-v4-flash-vision-exp), including the quick-answer judge/stream; without an image-capable model they fall back to the main model instead of being answered blind on a text-only flash.selectModel, including relay/proxy providers (e.g. kabuai): agent/request passes the harness's requested config through unchanged, and quick answers always run on the session provider's own cheap model. (No drift healing — its original cause, a forged request/header, was removed at the root in v0.9.2.)/router auto|off (plus the route_model tool) simply enable or disable quick-answering for the session. There is no per-request model flipping to configure.RATE_LIMIT, SERVER, TIMEOUT, EMPTY_RESPONSE) degrade the turn to the cheap model and retry once; anything else delegates to the provider's own retry policy.miss/out/cache%/≈$ line, a QA×N quick-answer counter (with a brief inline highlight on each direct answer), and a per-model usage breakdown. Reactively driven by useProjection; the toggle reuses the built-in commands remote — no custom wire protocol. UI strings are localized through the harness locale service.Quick answers land as ordinary chat messages with a ⚡ 快速回答 / Quick answer marker:

The router dock under the composer — Auto / 关闭 toggle, current model, live token / cache-hit / cost figures, and the per-model usage breakdown:

The dsh CLI must be on your PATH. If you only ever ran the harness through npx, dsh is not installed and you will get zsh: command not found: dsh — install it globally first. This release targets harness 0.2.0-rc.1 (for an older harness use tag v0.9.4):
npm install -g @deepseek-ai/dsh
pnpm add -g @deepseek-ai/dsh also works if your pnpm global bin dir is on PATH (otherwise pnpm asks you to run pnpm setup first). Alternatively skip the global install and prefix the commands below with npx @deepseek-ai/dsh ….
# 1. add the bundle to your web profile (pnpm-backed; the built lib/ artifacts
# are committed in this repo, so no build script runs at install time).
# Prefer a release tag (#v0.9.5); #main tracks the latest commit.
dsh plugin --profile web add "github:tianji-qingtian/dsh-model-router#v0.9.5"
# 2. restart the harness with that profile — `add` only edits the profile
# files; a running instance does not hot-load the new bundle
dsh --profile web
After the restart the ⚡Router panel appears under the composer in the Web UI, and the /router command plus the route_model tool are registered once the host half loads. Verify under Settings → Plugins that dsh-model-router is listed.
A dynamic (session-only) prototype with the same name may already be running inside one session; it is unrelated to the installed bundle and disappears with the harness process.
| Piece | Mechanism |
|---|---|
| Step classification | agent/pre-step waterfall — strong-keyword fast path, then a zero-prefix flash judge call (SIMPLE / AGENTIC) with the last assistant reply for reference detection |
| Quick answers | agent/pre-step rejects the step after a zero-prefix llm.stream on the cheap model; the question + answer are appended to the session log (user/message + a forged step/start…assistant/message…step/end envelope) — the main model never runs |
| Model picker / relay | agent/request passes the harness's requested config through unchanged — the composer picker, selectModel, and relay providers (e.g. kabuai) all work mid-session |
| Failure fallback | agent/request-error waterfall — returns { kind: 'retry' } after flagging the turn; the retry re-enters agent/request and lands on the cheap model |
| Stats | sessionProjections.register('modelRouter', …) folded over request/header (current/changes only), command/run, and assistant/message events — usage is attributed via each message's own source.model |
| Dock UI | conversation.composer.dock slot + standard useProjection prop + locale service for zh/en text |
| Manual control | /router auto|off command (commands service) + route_model tool (tools registry) |
The cheap/strong model pair is discovered at runtime from the provider's catalog (llm.listModels): ids matching flash|chat|mini|turbo|haiku|lite|air|nano are cheap candidates, pro|reasoner|opus|sonnet|max|ultra|premium|r1 are strong. With the stock DeepSeek adapter that is deepseek-v4-flash ↔ deepseek-v4-pro.
Built and verified against harness 0.2.0-rc.1. The peerDependencies ranges are
checked by the harness at install and at profile startup — a plugin whose declared
range does not cover the running dsh --version is refused (or skipped with
skipping profile bundle …), so an older plugin silently disappears from the UI
after a harness upgrade.
What 0.2.0 changed for this plugin (v0.9.4 → v0.9.5):
| Change | Effect here |
|---|---|
assistant/message must embed its exact model stream (data.stream) |
The forged quick-answer settlement now carries stream (block start, text delta, closed block, usage, finish). Without it the harness refuses the settlement at the seed/load boundary, so the session log would no longer open after a restart |
tool-result content blocks removed (tool results are their own tool-role messages now) |
The agent/pre-step fast path scores the current block vocabulary |
commands registration races with a bare ctx.get('commands') |
commands is now a hard injection, like the sibling dsh-composer-polish plugin |
Legacy 0.1.x harnesses keep working through tag v0.9.4; this release intentionally
does not declare them, because the settlement shape differs.
The price table is a model-class estimate (USD per 1M tokens) living at the top of src/index.js:
const PRICE_TABLE = [
{ test: CHEAP_RE, input: 0.27, output: 1.10, cacheHit: 0.07 },
{ test: STRONG_RE, input: 0.55, output: 2.19, cacheHit: 0.14 },
]
Edit it to match your account's actual pricing; the panel always labels the number with ≈. Cache hits are billed at the cache-hit price, not the input price.
Counting semantics: harness TokenUsage fields are disjoint — inputTokens already excludes cache reads (DeepSeek reports prompt_tokens = hit + miss; the adapter subtracts hits out). The panel therefore shows miss … · cache N% where the hit rate is hit / (hit + miss); a healthy long conversation typically sits in the high 90s.
command/run events, so it survives restarts), while the transient-failure degradation flag is process-local and resets with the harness.useProjection-driven stats reflect the whole session log — history recorded before installation is included, which is intentional.source.model; no fake request/header is written since v0.9.2 — it would persist across restarts and mis-attribute the first real call after resume). This satisfies the current session invariants (the step is appended before the real step starts), but it is the most harness-coupled part of the plugin — worth re-checking after harness upgrades.MIT
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。