Sessions & Messages
dsh-model-compat-guard
782042369/dsh-model-compat-guard · ★ 0
DSH compatibility guard: repairs auto-compaction failures for GPT/reasoning models (raises the summary token cap and lowers reasoning effort on purpose=compaction requests), strips doomed
Manifest details
安装
dsh plugin --profile web add 'github:782042369/dsh-model-compat-guard#3cb882246ec840c5a5f9ed274e6fb5f395b09ff3'GitHub 源码安装:首次需按提示配置 allowBuilds 构建授权后重试
For install and environment setup, plus plugin development tutorials, see DSH community docs ↗
README
Table of contents
A compatibility guard plugin for DeepSeek Harness (DSH) that repairs four frequent failure modes when driving DSH with non-DeepSeek models (GPT, Qwen-thinking, self-hosted reasoning models, ...). Zero-config out of the box; every fix can be toggled in ~/.dsh/compat-guard.json.
1. Reasoning-model auto-compaction failure
Symptom: summarization truncated at the token cap (incomplete checkpoint) — compaction aborts on every attempt
(upstream Discussion #3465).
Root cause: dsh-compaction-basic summarizes with a hard maxTokens cap (default 8192) and fails closed when the
summary hits it. Reasoning models spend invisible thinking tokens inside that same output budget, so any model that
thinks heavily truncates and compaction aborts.
Fix: intercepts purpose === "compaction" LLM requests on the llm/stream waterfall and
- raises
maxTokensto 32768 (configurable); clamps only when a provider explicitly exposeshardMaxTokens, never from DSH'sdefaultMaxTokens; - drops the reasoning effort to the cheapest level the model supports (prefer
off>minimal>low); - never forces an effort on models without reasoning support (avoids
UNSUPPORTED_REASONING_EFFORT).
2. Doomed sandbox-escalation requests fail-closing tool calls
Symptom (upstream Discussion #3877):
Error: sandbox escalation to "danger-full-access" is not strictly wider than this call's current "danger-full-access" mode
Error: invalid justification: expected a non-empty sentence
Root cause: when a sandbox executor is attached, the bash/write/edit tool schemas advertise a
sandbox_permissions field globally, but the effective mode is resolved per session. Execution requires the request to
be strictly wider plus a non-empty justification, otherwise the whole call fails closed. GPT/Claude-class models attach
the field speculatively and blow up in danger-full-access sessions.
Fix: the tools/execute hook resolves the session's standing mode and strips sandbox_permissions +
justification when the request is doomed (same mode / narrower / no sandbox service / unknown mode), executing at
the standing mode — semantically identical, because the model already has what it asked for. Strictly-wider requests are
preserved and go through the normal approval flow.
stripEscalation: "redundant" (default — only strip doomed requests) | "always" (strip even legal escalations,
for sessions with approval prompts disabled) | "off".
3. missing required property "description"
Root cause: bash / run_code / subagent declare a required description argument (used as the UI label);
strict JSON-Schema validation rejects the whole call when the model omits it.
Fix: on tools/execute, before strict validation, synthesize the description from the call payload when required
and missing:
bash→ first line of the command (Run: cd /tmp && rm -rf build)run_code→ first effective code line (comments / braces skipped)subagent/subagent_fork→ first line of the promptworkflow→ fills the nestedmeta.descriptiontoo
Calls that already carry a usable description are untouched.
4. Code Mode (PTC) run_code failures
Symptom (upstream Discussion #1605):
Error: code run failed (exception): Expected ',', got '<eof>'
Error: code run failed (exception): TypeError: b.stdout.slice is not a function
Root cause: (a) the model emits a syntactically incomplete TypeScript program — unbalanced quotes/backticks/brackets or truncated code, so the type-stripping parser (amaro/SWC) hits end-of-file while expecting a comma; (b) the model treats the bash result's stdout as a string — it is a structured object { text, truncated, spillPath? }; the correct read is res.stdout.text. Both stem from models unadapted to PTC's "call every tool from TypeScript" convention, amplified by the harness reporting only a one-line error with no position.
Fix: the llm/stream hook detects code-mode requests (when run_code is the single wired tool) and appends a compact discipline block to the end of the system prompt: tool results are plain JSON values (no .result() wrapper), the correct bash result shapes, and closure hygiene for complete programs. Appending at the end keeps every provider prefix (and prompt cache) intact.
codeDiscipline: "off" (default — use native AGENTS.md) | "auto" / "always" for legacy mutable request objects; frozen requests skip safely.
Configuration (optional)
~/.dsh/compat-guard.json:
{
"compactionMaxTokens": 32768,
"compactionEffort": "auto",
"compactionStripTools": false,
"compactionPurposes": ["compaction"],
"fillDescription": true,
"descriptionTools": ["bash", "run_code", "subagent", "subagent_fork", "workflow"],
"codeDiscipline": "off",
"stripEscalation": "redundant",
"unknownPolicy": "preserve",
"modelInfoTtlMs": 300000,
"modelInfoTimeoutMs": 5000,
"logFixes": true
}
compactionEffort:"auto"(cheapest level) |"keep"(leave untouched) | an explicit effort id.compactionStripTools: whentrue, drops the tools list from compaction requests (prevents the model from calling tools mid-summary; costs the prefix KV cache).codeDiscipline:"off"(default; native AGENTS.md is preferred) |"auto"|"always"for legacy mutable-request compatibility.- Same-named fields passed as cordis plugin config override the file.
Apply config changes with systemctl restart dsh-web (or restart your dsh web process). Look for
compat-guard: lines in the logs to see every applied fix.
Install
From the marketplace (Settings → Plugins → Marketplace, searchable as dsh-model-compat-guard) or directly:
dsh plugin --profile web add github:782042369/dsh-model-compat-guard#v0.4.0
Restart dsh web afterwards. Uninstall: dsh plugin --profile web remove dsh-model-compat-guard.
Test
node test/smoke.mjs # mock-driven assertions for all four fixes