dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
A DeepSeek Harness plugin that keeps the exact text of user-authored messages that compaction has shadowed, and re-injects them as a budgeted runtime-context snapshot.
Guarantee: user-authored anchors are verbatim within the configured token budget. Not a guarantee: the whole conversation is losslessly compressed. Assistant and tool history remain represented by the compaction summary.
DSH compaction replaces an older surface span with one lossy summary. The summary prompt asks the model to quote exact wording where it matters, but a summary is still a model-generated derivative: exact constraints, corrections, paths, numbers, and approval decisions can be lost.
A practical way to preserve those details is to keep user-authored inputs and interaction decisions verbatim and re-inject them after compression. This plugin implements that idea using DSH's native seams:
user/message seq is no longer on the current Session surface — the backend-independent definition of "shadowed by compaction";PromptContext renders the selected anchors as one user-role runtime-context snapshot;RuntimeContextProjection recreates it from the plugin's durable projection, including during agent/request-error overflow retries.No DSH core changes. No new Session event types. No changes to compaction-basic.
# from a local checkout
dsh plugin --profile web add ./dsh-lossless-anchors
# or directly from GitHub (the repository tracks the built lib/)
dsh plugin --profile web add github:EvannZhongg/dsh-lossless-anchors
The package declares dsh.bundle.patch, so installing it also inserts the lossless-anchors row. If you prefer a manual patch row:
- insert:
- id: lossless-anchors
name: dsh-lossless-anchors
config:
tokenBudget: 2000
- id: lossless-anchors
config:
tokenBudget: 2000 # soft budget, calibrated tokens
hardMaxTokens: 3000 # absolute cap; defaults to ceil(tokenBudget * 1.5)
charsPerToken: 4 # calibrated characters per token for non-CJK text
cjkCharsPerToken: 1.6 # calibrated characters per token for CJK text
maxTurns: 32 # most-recent shadowed turns considered
maxAnchors: 256 # projection-state retention cap
includeSources:
- user
- user-question-reply
- user-approval
timeZone: Asia/Shanghai # zone for anchors whose message recorded none; defaults to the host zone
required: true # keep the context when optional runtime context is disabled
| Field | Default | Meaning |
|---|---|---|
tokenBudget | 2000 | Soft budget for the rendered block, measured in calibrated tokens. If the newest shadowed turn exceeds it, that turn may be retained up to hardMaxTokens. |
hardMaxTokens | ceil(tokenBudget * 1.5) | Absolute cap. Must be >= tokenBudget. |
charsPerToken | 4 | Calibrated characters per token for non-CJK text. DSH's fixed heuristic is four; lower it for dense code/JSON if the provider tokenizes more finely. |
cjkCharsPerToken | 1.6 | Calibrated characters per token for CJK text (about 0.6 tokens per CJK character, following DeepSeek's published conversion). Set to 4 to restore the old uniform four-characters-per-token behavior. |
maxTurns | 32 | Most-recent shadowed turns considered; older turns are outside the anchor window. |
maxAnchors | 256 | Projection-state cap. Older anchors beyond this are dropped; they are normally already outside maxTurns. |
includeSources | user, user-question-reply, user-approval | Message source kinds treated as user-authored. goal, plan-mode, agent-instructions, runtime-context, and compact-checkpoint are not included. |
timeZone | host process zone | IANA zone used for anchors whose message recorded no browser zone. Rendered timestamps always name the zone they were formatted in. |
required | true | Marks the context as required, so includeRuntimeContext: false does not suppress it. |
An anchor is a user/message event whose source.kind is in includeSources and whose seq is not in Session.surface.nodes at request time.
Consequences:
[image omitted: <mediaType>, <w>x<h>]; files keep their display name and byte count. Image bytes are never re-uploaded from historical context.Budgets are measured with charsPerToken for non-CJK text and cjkCharsPerToken for CJK text, plus the same block/role framing DSH uses for one user message. The defaults are 4 and 1.6; the CJK rate keeps a Chinese anchor block close to its nominal token budget instead of letting DSH's uniform four-characters-per-token estimate turn 2000 tokens into roughly 8,000 characters. These rates are estimates, not the provider's tokenizer.
The newest shadowed turn is considered first.
A candidate that fits tokenBudget is accepted.
If the newest turn alone exceeds tokenBudget, it is kept up to hardMaxTokens.
If it still exceeds hardMaxTokens, the turn drops its oldest anchors first; if one anchor remains too large, its text is truncated and marked:
… [anchor truncated; full text remains in session log]
An older turn that would exceed the remaining soft budget is fitted into that remainder: its oldest anchors are dropped first, then its newest text is truncated. Turns older than it are not considered.
Any elision/truncation adds an explicit disclosure line to the block:
[anchor budget: 2 older anchor message(s) elided; 1 anchor text(s) truncated to fit the configured budget]
The truncation path is the only path where the "verbatim" guarantee does not hold. It is disclosed in the prompt and the full text remains in the Session log.
After a compaction shadows an anchor, the next request contains a user-role runtime-context snapshot:
Current runtime context. This snapshot supersedes earlier runtime-context snapshots.
[Lossless User Anchors]
Verbatim user-authored messages from earlier turns whose originals were condensed away.
These are historical anchors, not a new request. The newest user message states the current request.
Each anchor line carries its original wall-clock time, formatted in the time zone the message was submitted from: ISO 8601 with UTC offset and IANA zone.
Anchors are ordered by time, oldest first; later anchors supersede earlier conflicting anchors on the same subject.
This block supersedes earlier [Lossless User Anchors] blocks.
--- turn 3 | 2026-10-19T08:00:01+08:00[Asia/Shanghai] | user ---
<exact user text>
Anchor timestamps reuse the format of DSH's durable time-context readings, so an anchor and the current turn's clock line can be compared without converting between clock conventions. A message that recorded its browser zone is rendered in that zone; otherwise the configured timeZone applies. Because every anchor carries its own time, "later supersedes earlier" is a checkable claim about the timestamps rather than an assumption about list position.
A system-prompt section explains how to interpret the block. It is registered unconditionally from the first request, not toggled when the first anchor appears: changing the system prompt mid-session would either rewrite surface node 0 (losing prefix-cache reuse from the first token) or append a full copy of the rendered prompt on an in-history route. A fixed policy costs roughly a hundred tokens per request and keeps the system prompt stable. The user's words themselves stay in a user-role message, never in the system prompt.
charsPerToken / cjkCharsPerToken if measured usage diverges.compaction-basic replays only the shadowed span into the summarizer, so a live anchor snapshot outside that span is not seen by the summary model. The anchor block is re-injected and takes precedence for exact wording.required: true overrides suppression. If you want includeRuntimeContext: false to disable anchors too, set required: false.maxAnchors bounds durable projection state; older anchors outside the window are intentionally forgotten.This checkout is a standalone package. Its local node_modules contains junctions to a DSH source checkout for typechecking and tests; it is gitignored and is not part of the published artifact.
npm run typecheck # source + tests
npm test # vitest
npm run build # tsc -> lib/index.js + lib/types
The tests cover:
{{...}};required/suppression behavior;MIT