DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

Session Rescue — DSH Plugin for DeepSeek Harness
DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in
← Plugins
S

dsh-session-rescue

Session Rescue

Prevents the DeepSeek Harness cold-start turn stall: after a restart or session load the first turn can block forever while the token meter synchronously replays the whole session log; this plugin compacts the session before its size reaches that danger zone, so the replay stays cheap.

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add github:1622352030/dsh-session-rescue#b63803b3ddc1f855e34acc04b06c5b1057f41bd8
READMECompatibilityVersions

Compatibility and provenance

Session Rescue is published as dsh-session-rescue and currently resolves to version 0.2.0. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
any
Release source
github
Registry updated
9/24/2026

Versions

0.2.0stable
9/24/2026
0.1.0stable
9/24/2026

Related plugins

Loading related plugins…

Latest
0.2.0
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
Unavailable
Files
Unavailable
Surface
any
License
MIT
Source
github
GitHub
★ 0
Weekly downloads
0
Last push
9/24/2026
View source ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue

Related plugins

More verified plugins in memory-context.

Hindsight Coding Agents@vectorize-io/hindsight-coding-agentsReflect-only Hindsight long-term memory for coding agents (harness-pluggable: opencode, …), with automatic background ingestion (no setup CLI).Memory Plugin@openviking/dsh-memory-pluginOpenViking memory and context bundle for DeepSeek HarnessWeknora@wxg-prc-cpg/dsh-weknoraWeKnora knowledge retrieval tools for DeepSeek Harness (dsh): semantic search, document reading and RAG/agent answers over your own knowledge bases.Archive Manager@michengai/dsh-archive-managerNPM-installable DSH Web plugin for managing archived sessions.

README

dsh-session-rescue

Status: v0.2.0 — prevention, not detection. The stall was traced to a specific window and a specific code path (below), and the plugin logic is covered by 55 tests (55 pass / 0 fail). The plugin has been loaded and exercised in an isolated DSH_HOME, never against the running instance. Be careful reading the mechanism below: the code-level facts are verified, the causal link from the replay to the stall is NOT — there is counter-evidence, stated in docs/DESIGN.md → Open questions. The stall has not been reproduced under control, and the cold first turn's cost has not been attributed to a specific listener yet.

A DeepSeek Harness plugin that stops the cold-start turn stall: after a restart or a session load, the first turn can block forever with the UI spinning and nothing in the log. This plugin prevents that by compacting the session before its size reaches the zone where the stall becomes fatal.

The problem, precisely

⚠️ Read this first: the causal claim below was FALSIFIED by direct measurement. The code-level facts in the table are verified, but they are not the cause of the stall. tools/measure-replay.js runs the product's own TokenMeter._sync over a reconstruction of the real session and the entire 526,383-seq cold replay costs 47 ms — against a cold first turn measured at 16,008 ms and turns that never returned. The replay is ~340× too small. The cause is still unknown; what remains true is that cold first turns are far slower than warm ones, it grows with session size, and /compact was the only observed recovery. See docs/DESIGN.md → Measured falsification.

A stalled session log looks like this, with no error anywhere:

agent/inbox/spliced     ← the user message is accepted
turn/start              ← the turn is opened
                        ← and then nothing, forever: no step/start, no assistant frames

The silence sits exactly in the preStep window, between turn/start and step/start. The cause is not a missing timeout and not the network — it is a synchronous full replay of the whole session log that runs inside that window:

StepEvidence
A restart or session load creates a new Session object@deepseek-ai/dsh-session/lib/index.js:1322 appends session/end-seed on load
The token meter's replay state is a WeakMap<Session, state>@deepseek-ai/dsh-token-meter/lib/index.js:589
A new object ⇒ empty state ⇒ replay from 0dsh-token-meter/lib/index.js:679-697, while (state.consumedEvents < session.seq)
Something calls it on every pre-stepdsh-compaction-basic/lib/index.js:782 (agent/pre-step) → :862 meter.measure(session)
So the replay runs between turn/start and step/startdsh-agent-loop/lib/index.js:528 → :539 → :553

That loop is synchronous: it blocks the event loop, so step/start can never be written and while (await this.turn()) never returns. The UI spins forever.

Measured on one real session (session-db08f763, 5.9 MB, seq space ≈ 517 k):

Turnseq at startcold or warmpreStep duration
235,236warm (same process)231 ms
545,585cold (process just restarted)16,008 ms
7 / 28–30 / 34–3593 k / 389 k / 446 kcoldnever returned (user gave up after 20–47 s)
8 / 31 / 36same sizes, after /compactcold1.6 s / 10.1 s / 4.7 s ✅

Three properties follow from this, all confirmed against the real logs:

  • Restarting does not help — it makes it worse. Every restart is another cold replay of an ever-longer log.
  • /compact does help — it was the only thing that ever recovered these sessions.
  • Size alone is not the trigger — a turn at 232,878 tokens succeeded warm while one at the same size failed cold. When the replay happens is what decides the outcome.

How the plugin fixes it

Honest framing, given the falsification above: the plugin does not absorb the mystery cost. compactNow begins with measure(), which is cheap (47 ms for the whole session), so compacting at load does not pay whatever the slow listener charges. What the plugin actually delivers is the automation of the one operation observed to restore service — proactive compaction, at load when a session is already large and between turns as it grows. If the slow listener scales with the visible surface, keeping the surface small helps; that is a hypothesis, not a result.

The replay is unavoidable — but where you pay for it is not. Paid inside the user's first turn it is a permanent hang; paid while the agent sits idle after a load it is just a slow start. And once compaction has run, the following cold starts stay cheap.

  1. GUARD — when a session is loaded into this process and its seq is already past the danger threshold, compact it before the user's first turn (agent/status → idle). This moves the unavoidable cost out of the turn and shrinks the surface at the same time.
  2. COMPACT — between turns, while the agent is idle, compact whenever the session has grown by a configured amount. This keeps future cold starts in the seconds range.
  3. Report — /rescue status shows the per-session seq, whether this process has already paid the replay ("warm") or not ("cold"), and the plugin's own measurement of the preStep window (turn/start → first step/start) for both cold and warm turns.

Only one API is used to act: the official compaction seam, ctx.compaction.compactNow(agent, signal, commandId) (@deepseek-ai/dsh-command-compact/lib/index.js:8,54). The service is fetched with ctx.get('compaction') rather than injected, so the plugin still loads and reports in compositions that have no compaction.

Anti-thrash (why the trigger is a growth delta)

Compaction does not shrink session.seq — the log is append-only and compaction appends its own records. A plain "compact when seq >= threshold" rule would therefore re-fire on every idle forever. The trigger is instead "grown by at least minGrowthSeq since the last compaction", and a successful compaction pushes that baseline to the current seq. Both are property-tested in test/guard.test.js.

busy is also treated specially: it means the core refused the call because a compaction is already running or the agent is not idle. No replay was paid, so the plugin does not mark that session warm (otherwise the cold session would miss its GUARD and the next user turn would hang again). Retries are throttled by a cooldown and a consecutive-busy cap.

Configuration

- insert:
    - id: session-rescue
      name: dsh-session-rescue
      config:
        enabled: true        # false = observe and report only, never compact
        warnSeq: 40000       # start warning/compacting from here
        dangerSeq: 80000     # cold first turn may never return past here
        minGrowthSeq: 20000  # compact only after this much growth since the last compaction
        cooldownMs: 60000
        maxAttemptsPerSession: 6
        maxBusyStreak: 5
        pollMs: 30000
        compactionTimeoutMs: 600000

The default thresholds are calibrated from the table above (40 k is where a cold first turn is already ~16 s; 80 k is inside the "never returned" range). They are machine- and session-dependent — measure your own with /rescue status and adjust.

What is in the repository

PathWhat it is
src/host.jsHost plugin entry: session/event + agent/status wiring, GUARD/COMPACT execution, /rescue.
src/guard.jsPure decision state machine — when to guard, when to compact, cooldown, caps, busy handling.
src/size.jsSize metric and thresholds for the danger zone, with the calibration data in comments.
src/detect.jsOffline only. Stall-signature detector over session events (used by the replay tool).
src/frames.jsOffline only. Read-only session-log analysis: per-frame zstd decode, synthetic-closer detection.
bin/dsh-session-rescue.mjsRead-only scan CLI — usable without installing the plugin.
tools/replay.jsReplays a real session log through the detector to check hit/miss rates.
tools/measure-replay.jsRuns the product's own TokenMeter._sync over a reconstruction of a real session log — the measurement that falsified the replay hypothesis (47 ms for 526,383 seqs).
test/*.test.js55 unit and integration tests (node --test), run against a fake cordis context.
tools/Install-Plugin.ps1Idempotent install / rollback for a DSH profile — dry-run by default, snapshot-based.
docs/DESIGN.mdDesign notes: the mechanism with source citations, the fix, bounds and open questions.

Limitations stated up front

  • Verified in an isolated DSH_HOME, not end-to-end against the stall. A real headless Harness run loaded the plugin, fired its agent/status hook, resolved ctx.get('compaction'), and opened a real compaction transaction (compaction/start carrying sourceCommandId: "session-rescue-guard-1") — reproduced twice. The stall itself was not reproduced, and the "compact before the first turn" ordering is covered by unit tests only. See docs/DESIGN.md → Verification performed.
  • The size threshold is a proxy. What actually costs time is the replay's per-event work, which cannot be measured from outside without paying for it. seq is the driver of the loop and is free to read, so it is used as the proxy — calibrated, not derived.
  • One link is unproven. Compaction demonstrably made the next cold start cheap in all three observed episodes (never-returning → 1.6–10 s), but why is not established: it cannot be by shortening the replay, since seq does not shrink. The plugin relies on the measured effect, and docs/DESIGN.md records the question as open.
  • Compaction costs an LLM call (15–20 s on the observed 300 k-token sessions) and rewrites history into a summary. That is a real change to your conversation, by design — the same operation /compact performs. Set enabled: false for report-only mode.
  • The earlier v0.1 approach (detect a stalled turn → cancel → cold rebuild) has been removed: the stall is a synchronous CPU loop, so signal.throwIfAborted() never gets a chance to run and cancellation cannot interrupt it.

Read-only scan CLI (no install required)

node bin/dsh-session-rescue.mjs scan --stalled-only     # sessions that stalled or have an unclosed turn
node bin/dsh-session-rescue.mjs scan --all --json       # every workspace bucket, machine readable

It reads session logs (read-only, tail window only, never prints message bodies).

Development

node --test test/size.test.js test/guard.test.js test/host.test.js
node --test test/detect.test.js test/frames.test.js   # offline forensics

Compatibility

Developed against DSH Desktop 0.8.2 with @deepseek-ai/dsh@0.1.2-rc.1 — every line reference above was read from that installed build.

License

MIT