dsh-context-offload
Context offloading for DeepSeek Harness (dsh).
A coding agent re-sends its whole history on every step, and most of that history is tool output it already used: the file it read, the command it ran, the diff it applied. This plugin releases that content from the model-visible history once it is no longer needed, replacing each consumed tool call and its results with a one-line stub. Every original stays in the session log, so nothing is lost — only the model's view shrinks.
Install
dsh plugin --profile web add dsh-context-offload
Restart dsh web. The plugin mounts into the profile composition and covers every
agent in that profile.
To switch it off without uninstalling, add to the profile's own cordis.patch.yml:
- id: context-offload
disabled: true
What the model sees
A tool unit — the assistant message that issued the calls plus every result
answering them — is shadowed by a single user/message stub:
[tool context offloaded — 2 tool call(s) removed from model context; 39,045 characters released]
- bash(command=cd /Users/me/proj && ls -la && for d in */; do echo …)
- read(path=src/harness/loop.ts)
The original arguments and results remain in the session log. Re-read a file or re-run a command if you need the content again.
Two paths produce that stub:
- Between steps — a policy on
agent/pre-stepreleases complete tool units once more thanretainUnitsnewer ones exist, and the accumulated backlog reachesflushChars. It flushes at most once perflushEverySteps, because every replacement moves the first divergence point of the request prefix and flushing on every step would defeat the provider's KV cache on every step. - On request — the
offload_contexttool lets the model unload calls it has finished with. The request is recorded during the tool call and applied at the next step boundary, which is the sanctioned surface-mutation point; a tool body runs mid-step and must not rewrite the surface.
Units whose calls are not all answered — an in-flight or interrupted step — are never touched, and the system prompt at surface node 0 is never inside a range.
Configuration
All fields are optional.
| Field | Default | Meaning |
|---|---|---|
enabled |
true |
Set false to keep only the model-facing tool. |
retainUnits |
8 |
Most recent complete tool units kept verbatim. Counted in units, not steps — step restarts at 1 for every turn, so a step delta across a turn boundary is meaningless. |
minUnitChars |
4000 |
A unit smaller than this many text characters is not worth a replacement. |
flushChars |
20000 |
Do not break the request prefix for less than this much releasable backlog. |
flushEverySteps |
10 |
At most one automatic flush per this many steps. |
maxUnitsPerFlush |
40 |
Upper bound on replacements appended in a single flush. |
Where it sits in the composition
This package ships a host-plane bundle: dsh.bundle.patch mounts one row into
the profile composition, which is the only channel a published package has. A
preset-plane mount is possible but must be made by hand — an installed package
cannot contribute an agent-preset root (package.json.dsh carries no preset
field, and a patch cannot compute a path relative to its own package). To scope
this to one preset instead of the whole profile, do not enable the bundle row:
install the package so node_modules can resolve it, and add the row to your own
preset copy:
- id: context-offload
name: dsh-context-offload
Enable exactly one of the two, never both.
compaction-basic remains authoritative for context pressure; this plugin is a
complement. Both append logged surface replacements and both listen on
agent/pre-step, and ordering between them does not matter because each only ever
shadows complete tool units or its own balanced range.
Why you cannot see it in the transcript
Surface replacements are model-only. The human transcript is rendered from append-origin events on purpose, so a landed replacement never erases conversation you already read. To observe the effect, watch the context-occupancy ring beside the composer: it stops climbing and enters a sawtooth, and its click-open panel shows the conversation segment flattening.
License
MIT
No comments yet. Be the first to write one.