dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
Undo button and side ruler for DSH conversations: rewind to any earlier prompt and re-edit it via a fork.
Built on the Cordis reversibility paradigm — the session log is the context, and undoing a prompt recovers the context to an earlier prefix (a withdrawal) without ever mutating the original log.
From the plugin market entry, or directly:
dsh plugin --profile web add github:tofe98/dsh-undo
No host half, no build step, no RPC: everything is computed from the live conversation snapshot.
Notes:
chat.turnEnds) to compute each prompt's fork boundary (the turn/end seq of the previous turn).sessions.fork({ sessionId, atSeq: boundary }), opens the child, and prefills via inputActions.setDraft(text).conversation.session.header.actions (button) and shell.overlay (dropdown panel + side ruler).Undoing and resending the same prompt preserves the whole request prefix, so provider-side
prefix caching should reuse it. We measured it end to end (DeepSeek automatic prefix caching,
deepseek-v4-flash, reasoning effort High):
| run | raw usage (assistant/chunk) | per-request hit |
|---|---|---|
| msg 1 "ciao, mi piace deepseek" | input=8107, cacheRead=1792 | ~22% (shared system-prompt prefix only) |
| msg 2 "molto interessante, vorrei parlare con te" | input=134, cacheRead=9856 | 98.7% |
| undo msg 2 → resend identical | input=6, cacheRead=9984 | 99.94% |
The resend read 9 984 of 9 990 billed input tokens from cache — the undo+resend flow is effectively a full cache hit. The ~6 residual tokens are the reserialized tail of the new user message (it gets a fresh id in the fork).
Why the conversation's "Cache hit: 59%" line still showed ~59% in both runs:
(1792+9856)/(8107+134+1792+9856) ≈ 59% because the fork inherits the parent's msg-1
usage chunk and shares the same total.assistant/chunk events with
{"type":"usage","usage":{...}}, where
hit = cacheReadTokens / (cacheReadTokens + inputTokens). The Trajectory view also shows
per-cell cacheRead.inputTokens field is not uniform (msg 1 reports the total, later
chunks the new-only tokens), so the UI percentage can understate the real hit — the raw
chunks are the ground truth.Takeaways for cache-hit optimization:
lib/
index.js # node half — empty apply so the Loader has a host-side row
client.js # browser half — the whole feature (module-loader format)
cordis.patch.yml
package.json # dsh.bundle + dsh.client declarations
The plugin is plain JavaScript — no build step. To try it during development, either load lib/client.js through the harness's dynamic plugin system or install the package from a local path.
MIT