dsh-context-keeper
看护 DeepSeek Harness 会话的上下文预算:每轮回复底部一个颜色点(绿<50%、黄50-65%、橙65-80%、红≥80%,读官方 contextPressure 投影),橙/红档在输入框下方出现提醒与「一键开新会话」交接按钮,另有 /context-watch 与 /handoff 命令和一个静态思考规则提示段。预算与交接只读本地会话文件,徽章和提醒不点按钮不花 token。
安装
dsh plugin --profile web add dsh-context-keeper
沙箱测试
这个插件还没测过。提交测试 →
README
dsh-context-keeper
Two things for a DeepSeek Harness agent:
- A host plugin that teaches it how to reason well — one persistent
system-prompt section, visible on every request.
- An offline analyzer that reads what it actually thought, from the session
files on disk.
It does not cut reasoning short. That was the original goal; measurement
killed it. See [Why this does not reduce thinking](#why-this-does-not-reduce-thinking).
What v0.4 adds: a context badge & reminder
A colour dot in every turn's footer (the conversation.chat.turnTail
seat — the same place and shape as dsh-cost-meter's usage chip). It reads the
official contextPressure projection and paints the band — **green (<50%) /
yellow (50–65%) / orange (65–80%) / red (≥80%)** — with the occupancy percent;
the action hint ("建议交接" / "该交接了") only appears from orange up. Hover shows
the full sentence.
A reminder panel under the input (conversation.composer.dock) that appears
at orange/red only. It states the band and offers an 开新会话 button: it
calls the client Remote session.create + session.prompt to make a fresh
session in the same workspace and seed it with "read the latest handoff package
under .context-keeper/handoff and continue". The new session is a full agent,
so it reads the package itself — the button does not inline the package (that
would spend tokens again).
Both are pure presentation plus one explicit user click. They never enter the
model input on their own and cost zero tokens until you press the button.
Honest limits (verified against this build's source):
- DSH's ReasoningRow header (above the thinking block) is hard-wired with no
extension seat, so the footer is the nearest always-visible open spot.
- After creating the new session the button cannot switch you to it — the
slot API has no navigation; open it from the sidebar. The panel says so.
- Command names must match ^[a-z][a-z0-9_-]*$ and third-party commands
render their name (no separate displaylabel), so/handoffand
/context-watchcannot be shown asHandoff/Context-Watchin the menu.
Readability goes into the Chinese one-line description shown next to
each name instead.
The client half is plugin/client.js (declared under dsh.client in
package.json); the host half is unchanged. No config path needed.
What v0.3 adds: context budget & handoff
v0.2 taught the agent how to think. v0.3 handles *whether the window can hold
it*. Two human commands, both reading the session file DSH already writes and
calling a model zero times:
/context-watch— occupancy, band (green/yellow/orange/red), headroom,
growth per turn, and the last compaction's reclaim.
/handoff— write a portable handoff package plus a full faithful archive
to <workspace>/.context-keeper/handoff/, so a fresh session can continue
without re-deriving anything. It reuses DSH's own compaction/summary
checkpoint as the "early context" (free multi-level distillation) and quotes
the recent tail verbatim.
A short, static context-budget line is added to the system prompt. It holds
no numbers on purpose: a changing number in the system prompt would invalidate
the provider's prefix cache on every request, which costs more than it saves.
The design and the two references it distils are in
[docs/distill-design-v3.md](docs/distill-design-v3.md).
Install
As a DSH plugin
dsh plugin --profile <your-profile> add dsh-context-keeper
Then restart the profile. The plugin registers one prompt section named
context-keeper:how-to-reason at order 650, which places it with the other policy
sections — after the deployment persona, before the tool catalog.
To turn it off without uninstalling, either set enabled: false in the config
block, or add a patch row:
- id: context-keeper disabled: true
Config options:
Option · Default · Meaning
enabled · true · false registers nothing
text · built-in rule · Replace the rule text entirely
order · 650 · Section position in the assembled prompt
maxChars · 2000 · Truncate at a paragraph boundary
As a CLI
git clone https://github.com/Orliba/dsh-context-keeper cd dsh-context-keeper node bin/cli.mjs --help
No build step, no dependencies, Node >= 22 (uses built-in zlib.zstdDecompressSync).
The plugin: what it puts in the prompt
The rule is five lines, each naming an observable behaviour rather than a
virtue:
Decide before acting. Before the first tool call, settle what you are
doing, why, and how you will know it worked. Once you state a plan, execute
it; do not reopen the plan mid-execution.
Change a conclusion only with a reason. …
When reasoning stalls, gather evidence instead of thinking harder. …
Match depth to risk. Read-only exploration may be quick. Irreversible
actions deserve a second look. …
Say what you do not know. …
Full text and the reasoning behind each line: [plugin/rule.mjs](plugin/rule.mjs)
and [docs/rule-text.md](docs/rule-text.md).
Why a prompt section and not a stream interceptor
The first design watched the reasoning stream and reacted — lower the effort
tier when a trace looked wasteful, stop a turn that ran away. Three
measurements, on real sessions, removed the target:
Hypothesis · Measured · Result
Looping traces repeat sentences · 0.1% sentence repetition · dead
Nearby steps re-derive earlier steps · 0.3% of step pairs above Jaccard 0.35 · dead
Early commitment + long tail = waste · top candidates read by hand: both productive · dead
It also depended on two fragile places: llm/stream (no in-tree consumer) and
agent/turn-stopping (fires only after the turn already ended).
A prompt section is the opposite kind of intervention. It is declared once,
…(truncated)
以上内容来自 npm 上的 README,我们只做格式化,不改内容。
版本
npm 上共发布:2,最后更新 2026-10-30