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.

Force Compact — DSH Plugin for DeepSeek Harness
← Plugins
F

@falling-ts/dsh-force-compact

Force Compact

DSH Cordis plugin: hooks the core model-request seam (agent/pre-step + agent/request) to force-compact a session's context and disable thinking per the "强制压缩配置" settings namespace (disableThinking, autoThresholdTokens, retainLatestTokens, turnEndForceCompactionEnabled). When the threshold fires (or

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

npx -y @deepseek-ai/dsh plugin --profile web add github:falling-ts/dsh-force-compact#15a5645fc8afb248274facd474d2da6b93c10df4
READMECompatibilityVersions
Settings panel — Force Compact section, all knobs live-editable

Description

DSH Cordis plugin: hooks the core model-request seam (agent/pre-step + agent/request) to force-compact a session's context and disable thinking per the "强制压缩配置" settings namespace (disableThinking, autoThresholdTokens, retainLatestTokens, turnEndForceCompactionEnabled). When the threshold fires (or /force-compact queues while busy), the latest `retainLatestTokens` of the conversation's surface tokens are KEPT VERBATIM and everything before that cutoff is COMPACTED INTO A SINGLE SUMMARY NODE in one LLM call (original span entries become shadowed/skipped). Also compacts at each turn/end and at each session/flush durability checkpoint. Host half is a pure listener; a web client half registers a settings.section (强制压缩 / Force Compact) that reads and writes the same settings namespace.

Compatibility and provenance

Force Compact is published as @falling-ts/dsh-force-compact and currently resolves to version 0.5.0. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
web
Release source
github
Registry updated
9/17/2026

Versions

0.5.0stable
9/17/2026
0.4.1stable
9/10/2026
0.4.0stable
9/9/2026
Show 10 more versionsCollapse versions
0.3.3stable
9/5/2026
0.3.2stable
9/5/2026
0.3.1stable
9/4/2026
0.3.0stable
8/31/2026
0.2.8stable
8/30/2026
0.2.7stable
8/30/2026
0.2.6stable
8/28/2026
0.2.5stable
8/27/2026
0.2.4stable
8/26/2026
0.2.3stable
8/25/2026

Related plugins

Loading related plugins…

Latest
0.5.0
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
Unavailable
Files
Unavailable
Surface
web
License
MIT
Source
github
GitHub
★ 7
Weekly downloads
0
Last push
9/16/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
DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in

Related plugins

More verified plugins in memory-context.

Memory Plugin@openviking/dsh-memory-pluginOpenViking memory and context bundle for DeepSeek HarnessContextdsh-contextA DeepSeek Harness plugin for context insight and management, with context dashboard and context command, for understanding how the context is made of, and how it evolves.Weknora@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.Memsearch Dsh@zilliz/memsearch-dshMemSearch plugin for DeepSeek Harness: shared markdown memory across agents, with capture, pre-step context injection, memory-recall skill, and a skill-candidate review panel.

README

dsh-force-compact

Aggressive, local-first context compaction for DeepSeek Harness agents.

A DSH Cordis function plugin that keeps the agent's working context lean by design: serve Qwen3.8‑27B on a self-hosted llama.cpp with a modest context, and the plugin shrinks the conversation itself — a large-window feel with no API cost and no data egress.

中文


Why

  • Self-hosted inference — the agent talks to a local OpenAI-compatible llama.cpp server through the standard DeepSeek adapter; no separate adapter needed.
  • Low context, high signal — instead of fighting a small cap, the plugin shrinks the conversation, so the agent reasons over a tight prompt while keeping deep memory in the compressed head.
  • Think off for compactions, passthrough everywhere else — disableThinking: true (default) turns thinking off on this plugin's own compaction summarization call only; every other model request rides the machine's configuration unchanged.
  • Private & free — no per-token billing, no egress.

What it does

Two compaction engines coexist behind one facade (resolveCompaction), transparent to callers:

EngineUsed whenNotes
Officialthe compaction service resolves in the agent realmPreferred; delegates to compaction/basic.
Builtinautomatic fallback (typical standard preset isolates the service)Self-contained persistent transaction on ctx.sessions / ctx.llm.stream / ctx.tokenMeter; reuses the official compaction/* event vocabulary, so it replays safely across builds.

No toggling — official wins when reachable, builtin takes over otherwise.

Trigger points

  • Per-request guard (agent/pre-step) — reads the session's projected context tokens (the exact number the harness renders bottom-right). At autoThresholdTokens it rejects the outgoing request and compacts the head instead, retaining the latest retainLatestTokens verbatim. Below the threshold the request proceeds.
  • Turn end / idle (agent/status → idle) — when the agent quiesces, optionally compacts via compactNow (gate: turnEndForceCompactionEnabled).
  • Manual /force-compact — immediate compactNow when idle; when busy it queues a process-local flag consumed at the next model step. Loaded lazily — see "Command availability" under Install.
  • session/flush — the awaited durability checkpoint.

Every path funnels into the single "compaction result landed in the session" boundary — the same point where the LiveUI signal fires.

Decision key is projectedTokens (provider-anchored, same figure as the UI corner), so the plugin never drifts from what you see; the threshold-aware shrink gate skips summarizer calls that provably cannot pull the session below the threshold (kills the low-threshold dead loop).

The builtin transaction bills shadowedTokenCount from the same tokenMeter.measure per-node prices the official engine uses, so the meter's collapse protocol settles the drop correctly — the bottom-right counter goes down after compaction.

Thinking control: scoped to compactions

Since the 2026-08 semantics revision, disableThinking controls one thing: whether this plugin's own summarization call (engine/builtin.js → engine/summarizer.js → ctx.llm.stream) carries reasoningEffort:'off'. Everything else is untouched:

Call siteWith disableThinking: true
Builtin-engine summarization callCarries reasoningEffort:'off'
Every other model request (business, sub-agents, tools, other plugins)Machine's LlmCallConfig unchanged
Official compaction service callsNot routed through any plugin seam — unaffected

When the target is a llama.cpp / OpenAI-compatible endpoint, the thinking: { type: 'disabled' } field the adapter emits is silently ignored there — so the summarizer ALSO stamps the llama.cpp-native top-level reasoning_effort: "none", gated on the exact same condition. One options object carries BOTH fields:

Endpoint familyReadsResult
Real DeepSeek APIreasoningEffort:'off' → thinking:{type:'disabled'}Thinking off ✅
llama.cpp / OAI-compatiblereasoning_effort:"none" (top-level)enable_thinking=false ✅

Each family tolerates-and-ignores the foreign key, so emitting both is harmless. The field is stamped in src/engine/summarizer.js (immediately before llm.stream(options)), NOT in the llm/stream waterfall — a prior draft injected there but proved ineffective structurally (middle-layer returns are discarded; in-place seed mutation crashes the host); see the src/hooks/wire-rewrite.js module header for the write-up. That hook now serves only the LiveUI watermark role.

Need thinking off on business calls too? Set your provider's reasoningEffort at the request-header level — the plugin deliberately stays out of that decision.

Observability: per-attempt audit lines

Every summarization attempt logs two lines (visible at the default debug: true) — the durable proof of the scoping decision and its wire fields, without capturing traffic:

[force-compact] <sessionId>: compaction thinking-policy — settings.disableThinking=true → extra.reasoningEffort='off' (this summarization call carries thinking-OFF)
[force-compact] <sessionId>: summarization wire-fields → <provider>/<model>: reasoningEffort='off' + reasoning_effort="none" (llama.cpp-native wire field)
  • Line 1 (engine/builtin.js) records where disableThinking is read and routed into the call options; with the setting off it records machine default.
  • Line 2 (engine/summarizer.js) records both wire fields exactly as they leave the options object, plus resolved provider/model; unstamped fields are labeled (absent…).

Empirically grounded: probed against a local llama.cpp endpoint, a baseline request returned populated reasoning_content (the model thinks by default), while the same request with top-level reasoning_effort:"none" returned none at all — the field genuinely disables thinking there, and business calls (which omit it) keep thinking.

LiveUI status

A tiny host→client messenger (the liveUi settings field mirrored live to the browser) pins a badge beside the turn:

  • Red "compressing" — just before a compaction commits;
  • Green "done" — the instant a compaction lands; 3 s later a fresh random working line takes over;
  • Blue "working" — otherwise a rotating playful one-liner;
  • Cleared at conversation end — when the agent goes idle (the turn is fully done), an empty text (isImportant) is pushed: the badge text is wiped and the phase color removed, restoring the official look. Replaces the former conversation-START forced working-pair override (removed 2026-09).

Badge text follows the app language: the host writes a locale-independent textId (phase name or working.N) alongside the canonical text, and the client half maps it to zh/en via its ctx.locale dictionaries — English UI shows English one-liners, Chinese UI shows the original Chinese.

Publishers are fail-safe: a messenger glitch can never disturb the actual compaction.


How it works

agent/request(payload, next)              # every model request
    return await next()                  # pure pass-through (thinking-off scopes
                                          # ONLY to the plugin's own summarizer)

agent/pre-step(payload, next)             # before each model step
    projectedTokens >= autoThresholdTokens?
        no  -> next()                     # let the request proceed
        yes -> compactRegion(head-before-retainLatestTokens, signal)
               return { kind: "reject" }  # no model request this step

agent/status({ agent, status })          # lifecycle transition
    status === "idle" && turnEndForceCompactionEnabled?
        -> compactNow(agent, freshSignal) # turn-end compaction

session/flush(session)                   # durability checkpoint
    select region -> project messages -> preview + shrink gate
    -> compaction.compactRegion(start, end, agent, signal)

Supporting modules:

  • src/hooks/guard.js — agent/request pure pass-through + pre-step threshold gate + process-local force flag (thinkingDisabled survives only as a legacy predicate).
  • src/hooks/command.js — the /force-compact command (lazily registered).
  • src/hooks/idle.js — turn-end forced compaction.
  • src/hooks/wire-rewrite.js — the llm/stream LiveUI watermark hook (no wire manipulation; historical note in the module header).
  • src/engine/region.js — head/tail-anchored region selection (with the official pairing ledger).
  • src/engine/summarizer.js — the one-shot LLM summarizer, fully aligned with official compaction-basic (target resolution, prefix-cache alignment, purpose:'compaction' tag, fail-closed finish classification, usage capture).
  • src/engine/builtin.js — the builtin persistent transaction (official compaction/* vocab).
  • src/engine/checkpoint.js — preview + shrink gate + delegation to the compaction service.
  • src/core/projected.js — provider-anchored projectedTokens.
  • src/core/ui-signal.js — the LiveUI messenger.

Install

As an installable package (recommended):

# from npm (published):
npm install @falling-ts/dsh-force-compact
# from git:
dsh plugin --profile web add github:falling-ts/dsh-force-compact
# from a local checkout:
dsh plugin --profile web add ./dsh-force-compact

Or, from a local checkout, as a --patch overlay without installing:

dsh web --patch dsh-force-compact/cordis.patch.yml

The plugin is loaded iff ~/.dsh/logs/dsh-force-compact.log gains:

[force-compact] debug logging enabled — writing [force-compact] lines to <absolute path>

Command availability — /force-compact loads lazily

The commands service arrives with the agent-presets plane, after the plugin's boot-time apply, so registration happens at the first guarded-listener activation (agent/request / agent/pre-step / agent/status / session/flush), settling permanently on the first success. Practical effect: after (re)starting the instance, a fresh session's / picker does NOT show /force-compact until that session makes its first model request — send any one message, then the command is registered process-wide.

  • Success: [force-compact] /force-compact command registered (deferred)
  • commands permanently absent: one … still UNREGISTERED 10 min … warn explains the empty picker. Until registered, the rest of the plugin works — degradation, not an install failure.

Verify a compaction happened:

idle compaction (builtin) shadowed N nodes (~M tokens)
builtin compaction OK — replaced span seq[A..B] (N nodes, ~K tokens) with a P-char checkpoint
compaction thinking-policy — settings.disableThinking=true → extra.reasoningEffort='off' (…)
summarization wire-fields → <provider>/<model>: reasoningEffort='off' + reasoning_effort="none" (…)

(The last two lines are the per-attempt audit pair described under "Observability".)


Settings

$DSH_HOME/settings.yaml, namespace falling-ts-force-compact:

keytypedefaultmeaning
disableThinkingbooleantrueOnly the plugin's own summarization call carries reasoningEffort:'off'; everything else unchanged.
autoThresholdTokensnumber ≥ 3200032000Projected-token trigger for the gate. Floor 32000 (clamps back up at read time).
retainLatestTokenspositive int ≥ 80008000Retain the latest N tokens verbatim; older history is summarized in one batch. Floor 8000. Drives both the auto gate and /force-compact.
turnEndForceCompactionEnabledbooleantrueCompact on the agent's idle transition.
debugbooleantrueEmit [force-compact] diagnostics to the plugin log.
logFilestring~/.dsh/logs/dsh-force-compact.logDiagnostics destination (~ expands to home dir).
compactionMode'realm' | 'global''realm'Official-service resolution strategy (priority-1 path).
builtinEnabledbooleantrueGate for the builtin engine fallback.
maxSummaryTokensinteger (1024–200000)1024Cap on the summarizer LLM maxTokens.
summarizationTimeoutMsinteger 5000–2147483647 (ms)90000Hard wall-clock cap for ONE summarization stream (hung-stream guard). Floor 5000 (a sub-5s cap would false-abort slow local endpoints); ceiling 2147483647 because the value is scheduled through AbortSignal.timeout, which throws on a fractional delay and silently degrades a 2^31..2^32-1 delay to 1 ms. Out-of-range values are clamped and fractions truncated.

Example — an aggressive local profile:

falling-ts-force-compact:
  disableThinking: true
  autoThresholdTokens: 40000   # compact sooner ⇒ keep the live prompt small
  retainLatestTokens: 8000
  turnEndForceCompactionEnabled: true

Without the settings service the plugin falls back to the same defaults and still compacts — the namespace is optional, never a hard dependency.

Tuning for low-context llama.cpp

Keep autoThresholdTokens comfortably below the served context: the live prompt stays small and latency flat, while the agent keeps deep memory through the compressed head. Pressure is measured in projected tokens (provider-anchored), so the threshold maps predictably onto the UI figure.


Behavior notes

  • Runtime dependency: the compaction service (preset plane agent-presets:compaction-basic), read live via ctx.get('compaction'); unreachable → the builtin engine takes over (or the request proceeds).
  • Optional dependencies: settings / tokenMeter / commands / llm / agents are read via ctx.get(...) with guards — a missing one degrades gracefully.
  • Per-request settings read: parameters are read every model request, so edits take effect on the next request without a restart.
  • Signals: agent/* Waterfalls forward the current turn's signal; the session/flush checkpoint and the agent/status idle listener each mint a fresh AbortController.
  • Persistence: durable output is the compaction/* bracket events + a surfaceOp:replace user/message checkpoint, replay-safe across builds.
  • Client half: web/client.js adds the settings section "Force Compact" (localized labels), live-editable without restart (uSES-safe mirror).
  • One intentional timer: the 3 s publishDone fallback (presentation-only, documented deviation). Otherwise the plugin is pure listeners + a process-local Map force flag.

Screenshots

Settings panel — Force Compact section, all knobs live-editable

Settings page — the Force Compact section; all nine fields above are editable live without a restart.

Conversation page — red "compressing" badge pinned beside an in-flight turn

Conversation page — the LiveUI signal paints three states (red: compressing / green: done / blue: working); the green banner fades after about 3 s back to a random working line; at conversation end the badge is cleared (empty text) back to the official look.


License

MIT (see LICENSE).