dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
Language: English | 中文(GitHub default)
Context Compaction plugin for DeepSeek Harness (dsh). Built natively on cordis4 (ESM), targeting dsh 0.1.2-alpha.3+ (fully verified compatible on dsh 0.1.2-alpha.4, dsh 0.1.3-alpha.1 and dsh 0.1.5-rc.2).
In long sessions, the model input consists of the entire message history: user prompts, assistant replies, tool calls and raw tool results. Tool results (search hits, file contents, command output) usually dominate the context, yet most of their detail is useless for later reasoning; repeated tool calls and "car-wheel" looping replies keep inflating the context and can even trigger dead loops.
This plugin operates in three layers without ever mutating the dsh append-only session log:
tool/result) enter the event stream they are pruned by fixed policies (search keeps title/link/short snippet; files keep a preview; command output keeps exit code and key lines)./restore can fully roll back at any time.An anti dead-loop guard observes the tool/call stream: when the same tool is called with identical arguments ≥3 times an anti-loop reminder is injected as context; at ≥5 calls a cancellation decision is recorded (cancelledCount) plus an in-session notice, for the host toolRuntime to consume.
| Engine | Trigger | Dependencies | Notes |
|---|---|---|---|
| API summary | automatic threshold / ctx.compactor.compactSession() | DEEPSEEK_API_KEY | Calls deepseek-chat (temperature 0.1) for skeleton-preserving summaries; falls back to an offline extractive mode automatically when no key is set |
| Local rules compaction | /local-compact command / ctx.compactor.localCompactSession() | None (zero network, zero extra deps) | Fixed rules + regex: collapse repeated sentences, keep top-K search hits, head/tail file lines, error-only command output, merged debug attempts, hard summary cap. Requires a one-time user confirmation |
Both engines emit a structured result report to the user: every compressed scope listed individually (e.g. "raw tool results — web_search ×2, ~4600 chars original"), per-span and overall compression ratio, tokens before → after, the estimated input-token saving on the next request, whether keyword retention meets the quality bar, and a reminder that /restore can undo everything. Automatic compaction writes the same report to dsh logs (ctx.logger.info).
session/event (dispatched by tool/result / assistant/message / tool/call), service injection via static inject = ['sessions', 'commands'], config schema via @deepseek-ai/schemastery, periodic scans managed by ctx.effect lifecycle./compact is not re-registered (dsh 0.1.2-alpha.3 ships @deepseek-ai/dsh-command-compact; verified registrable on 0.1.2-alpha.4, 0.1.3-alpha.1 and 0.1.5-rc.2); this plugin adds /local-compact, /su-compact and /restore.
⚠️ A plain
dsh-web-appprofile disablescommand-compact(disabled: true) on the host plane, so typing/shows no built-in/compact. This plugin's bundle patch explicitly re-enablescompaction-basic,command-compactandtool-result-pruner(applied after web-app), so after installing it/compact,/local-compactand/su-compactare all available (verified on dsh 0.1.2-alpha.4, 0.1.3-alpha.1 and 0.1.5-rc.2 web profiles:compact,local-compact,restoreandsu-compactare all registered on the command surface).
ctx.compactor: project() / compactSession() / localCompactSession() / suCompactSession() / restore() / prune().| Command | Effect |
|---|---|
/local-compact | First call only prints the risk notice and asks for confirmation — nothing is compressed |
/local-compact confirm | After confirmation, runs offline rules compaction and prints the report (confirm / yes / 确认 all accepted) |
/su-compact | Semantic-understanding compaction: runs the local rules judgement first, then feeds the LLM the span's intent ("what this does / why it matters") to keep only intent + working strategy + final conclusion (needs DEEPSEEK_API_KEY; auto-falls back to local extractive without a key) |
/restore | Restores the pre-compression originals from the archive (works for all engines) |
# Option A (recommended, most reliable): local directory file: install (no git build scripts)
git clone https://github.com/lionwill/dsh-compactor.git
cd dsh-compactor
npm install && npm run build # lib/ is a build artifact (git-ignored); file: installs do not build
dsh plugin add "dsh-compactor@file:$PWD"
# Option B: install from GitHub (pnpm checks out and runs prepare to build; see allowBuilds below)
dsh plugin add "github:lionwill/dsh-compactor" # default main branch
# To pin a version tag, tag the repo first, then:
dsh plugin add "github:lionwill/dsh-compactor#v0.4.1"
Troubleshooting
link:github.com/lionwill/dsh-compactor / non-existent directory / declares no dsh.bundle
→ the command is missing the github: prefix. dsh plugin add github.com/lionwill/dsh-compactor is
treated by pnpm as a local relative path (link:github.com/...); that directory does not exist, so
dsh cannot read package.json and reports "declares no dsh.bundle" (the repo does declare it).
Correct form: dsh plugin add "github:lionwill/dsh-compactor".ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED
→ pnpm ≥10 blocks prepare (compile) scripts on git dependencies by default. The error prints an
exact allowBuilds key; add it verbatim to $DSH_HOME/profiles/<profile>/pnpm-workspace.yaml
and re-run:
allowBuilds:
"dsh-compactor@git+https://github.com/lionwill/dsh-compactor#<commit>": true
The key is commit-bound (replace it with the newly printed key after repo updates). You can also set
dangerouslyAllowAllBuilds: true to allow every dependency build script (security trade-off).
A bare package name (dsh-compactor: true) does NOT work for git deps (verified). Option A
(file: local pre-built directory) avoids git build scripts entirely.Could not resolve v0.4.1 to a commit
→ the repo has no v0.4.1 tag yet; use the tagless github:lionwill/dsh-compactor, or tag first.package.json declares dsh.bundle.patch (pointing to
cordis.patch.yml). dsh 0.1.2-alpha.3+ activates a package as a profile layer only when it declares
dsh.bundle; if you see "declares no dsh.bundle", fix the two points above first.cordis.patch.yml (a dsh bundle patch — a YAML array; the package ships the correct
one. Override by id in your own profile if needed):
- insert:
- id: dsh-compactor
name: dsh-compactor
config:
thresholdTokens: 32768 # token threshold that triggers compaction
targetTokens: 8192 # compaction target token count (reference)
compressInterval: 300 # periodic scan interval (seconds)
retainRecentRounds: 3 # most recent N messages are never compressed
summaryModel: deepseek-chat
enablePruning: true # realtime tool-result pruning
enableSummary: true # API summarization (auto offline fallback without a key)
exemptTools: [write, edit, task] # tools never touched by pruning/guard/local compaction
qualityThreshold: 0.85 # keyword-retention warning threshold
# localRulesPath: /path/to/my-rules.json # optional: custom local-rules file
The API engine needs a key: export DEEPSEEK_API_KEY=sk-... (without it the API path falls back to the offline extractive summarizer automatically).
local-rules.json)All rules/regex for /local-compact live in local-rules.json at the package root. Loading order (deep merge, later wins):
built-in defaults ← package local-rules.json ← env DSH_COMPACTOR_RULES=<path> ← config localRulesPath (a read failure on the explicit path raises).
{
"maxSummaryChars": 1200, // hard cap for local summaries (truncated with a marker)
"maxKeptSentences": 8, // max sentences kept from verbose replies (dedupe first)
"userLineMaxChars": 200, // user question lines kept up to this size (skeleton priority)
"callArgsMaxChars": 80, // truncation for tool-call argument lines
"fallback": { "headChars": 300, "tailChars": 160 },
"toolRules": {
"web_search": { "keepTopResults": 5, "relevanceField": "relevance_score", "titleField": "title", "urlField": "url", "linkField": "link", "dropFields": ["snippet", "description"] },
"read_file": { "headLines": 20, "tailLines": 5 },
"code_execution": { "maxStdoutLines": 30, "maxStderrLines": 10, "errorPattern": "error|exception|failed|traceback|panic|错误|失败|异常|报错" }
},
"patternRules": {
"research_chain": { "mergeUrls": true, "maxMergedUrls": 8 },
"code_debug": { "attemptPattern": "第\\s*\\d+\\s*次|attempt\\s+\\d+|retry|重试|再次", "keepLast": true }
}
}
/local-compact is a test-and-development rule implementation; its quality is generally below the API engine.qualityThreshold, the report flags ⚠️ explicitly — review the result or simply /restore./local-compact run only asks for confirmation and touches no data. If the result is unsatisfactory, run /restore to recover the originals completely./restore only undoes compressions made by this plugin (API summaries and /local-compact). Rollback of the dsh built-in /compact follows dsh's own semantics.$DSH_DATA_DIR/archive/ (or ./.dsh-compactor-archive/ if unset). Ensure the directory is writable and never hand-edit archive files (append-only).exemptTools (defaults: write / edit / task) are never pruned, guarded or locally compacted. Do not remove them if your workflow depends on their results./local-compact reloads on every run./compact — it is dsh's built-in command (@deepseek-ai/dsh-command-compact) which this plugin only explicitly re-enables via its bundle patch, so it never duplicates dsh's built-in registration. Note: "no conflict" applies only to dsh's built-in. If another plugin you installed also registers /compact (e.g. the third-party dsh-compact), the command surface gets a duplicate-registration conflict and /compact stops working. In practice, after uninstalling that third-party plugin which duplicated dsh's built-in /compact, this plugin + the built-in /compact work directly; just keep a single provider of /compact.dsh-compactor/
├── package.json # npm manifest (ESM; cordis/schemastery are peerDependencies provided by the dsh host)
├── tsconfig.json # NodeNext ESM build config (prepare hook compiles on git install)
├── local-rules.json # /local-compact rules & regex config (standalone file, overridable)
├── cordis.patch.yml # sample plugin configuration (merged into dsh config)
├── LICENSE # MIT
├── README.md # Chinese documentation (shown first on the GitHub homepage)
├── README.en.md # this file (English)
└── src/
├── index.ts # Compactor Service: event wiring, compaction pipeline, periodic scan, guard, reporting
├── config.ts # schemastery config schema and defaults
├── report.ts # compaction result report (scopes / ratio / estimated savings / retention / conclusion)
├── adapter.ts # dsh Session (surface.nodes + events) ↔ flat message projection
├── estimator.ts # token estimation (CJK-aware heuristic, injectable real tokenizer)
├── segmenter.ts # compressible-span detection with tool-call↔tool-result boundary alignment, block merging
├── pruner.ts # realtime tool-result pruning policies (web_search/read_file/code_execution/default)
├── summarizer.ts # API summarization call (injectable transport) + offline extractive fallback
├── local.ts # /local-compact rules engine (deterministic, zero network) + rules loading
├── patterns.ts # span pattern detection (research_chain/code_debug/normal_conversation)
├── store.ts # append-only original archive (JSONL, source for /restore)
├── monitor.ts # compaction event monitoring and keyword-retention stats
├── guard.ts # dead-loop guard (identical-call counter: ≥3 reminder / ≥5 cancellation)
├── commands.ts # /restore and /local-compact (two-step confirmation) registration
├── events.ts # cordis4 event type declarations
└── types.ts # shared types