dsh-ban-wait
Manifest valid拒绝会把智能体循环钉住的工具参数:阻塞等待、临场延长超时,以及可选的同步长任务。
dsh-ban-wait
One Host plugin that refuses tool arguments which would park the DSH agent loop.
It exists because the shell command timeout is not a ceiling. pwsh-sandbox's
timeoutMs: 1000 promotes a long command to a background job, but the model can
pass timeoutMs: 180000 on the call itself and the executor honors it up to
maxTimeoutMs (600000 ms by default) — three minutes inside one tool call. The
same class of leak is job_output { wait: true }, clamped only by a 10-minute
default. This plugin makes "no single call parks the loop" a property of the
tool registry instead of a property of the model's discipline.
Files
| File | Role |
|---|---|
index.js | the plugin: policy + global ctx.tools.guard() |
check.mjs | offline self-check of the policy (30 assertions, no DSH process) |
bundle-check.mjs | pre-install check: replays what the plugin page inspects, with the harness's own patch loader |
cordis.patch.yml | the bundle's patch: inserts the Host-plane row |
package.json | dsh.bundle.patch → cordis.patch.yml; no dependencies |
Policy
| Config field | Default | Meaning |
|---|---|---|
maxBlockingMs | 1000 | ceiling for any per-call blocking hint the model supplies |
denyWaitTools | ["job_output"] | tools whose wait: true is refused |
timeoutHintTools | ["pwsh", "bash"] | tools whose timeoutMs / timeout_ms is checked against maxBlockingMs |
requireBackgroundTools | [] | tools that must be called with run_in_background: true |
A refusal is a Error: … tool result that names the ban, clears the background
job of blame, and states how to re-issue the call, so the model recovers in one
step. An unusable config value is logged and replaced by its default rather than
thrown: a typo here must not fail the instance's boot.
Install
Through the plugin page — the only channel that keeps the plugin visible in the inventory with its own toggle:
- 添加插件 → paste the absolute project directory
(the checkout you just cloned). A local directory is recognised by
isAbsolute()before any npm-spec parsing and never touches a registry, so the registry chooser in that dialog is irrelevant. - The manager reads
package.json, requires anameand adsh.bundle, adds the dependency to the profile, then reconcilesdsh.profile.bundlesautomatically ("new bundle dependencies activate automatically"). The plugin then appears under 已安装 with a toggle. - If the result reports that a restart is required, restart the instance: a new Host module generation is not loaded into a running process.
Do not also add a raw loader row for this plugin to the profile patch. The
bundle's cordis.patch.yml inserts row id ban-wait, and two rows sharing that
id make id-targeted patches — the toggle, any override — reach only one of them.
Companion configuration, without which the guard is the only thing standing between the model and a three-minute call:
- id: pwsh-sandbox
name: "@deepseek-ai/dsh-pwsh-sandbox"
config:
timeoutMs: 1000 # default for a command
maxTimeoutMs: 1000 # ceiling for the model's timeoutMs argument — the line that matters
maxOutputBytes: 10000
Verify
# the policy itself (30 assertions)
node check.mjs
# the package the plugin page will inspect: path, package.json, name, dsh.bundle,
# `files` coverage, and a real parse of cordis.patch.yml by the harness loader
node bundle-check.mjs
Neither proves activation — that happens when the profile mounts the bundle's layer, which the plugin page reports in its install result.
Live probes (each returns a refusal instead of executing):
job_output { job_id: "pwsh-1", wait: true } → Error: … (ban-wait): job_output was called with wait: true
pwsh { command: "ok", timeoutMs: 180000 } → Error: … caps how long one tool call may hold the agent loop at 1000 ms
pwsh { command: "ok" } → runs normally
workflow { script: "return 1" } → runs synchronously (not banned by default)
Verified on instance 3080: both refusals fire, plain calls and non-blocking job reads behave exactly as before, and the row mounts and unmounts live — no restart was needed for any of it.
Boundaries
- The guard sees arguments, not duration. A tool with no blocking argument
that simply runs long is out of its reach; that is what
requireBackgroundToolsis for, and what the shellmaxTimeoutMscap already handles for commands. ask_user_questionis deliberately never banned: blocking on a human is the feature.workflowand a synchronoussubagentare not banned by default. They do real work inside the call, so backgrounding them changes how the result is consumed. Enable per tool when that trade is wanted:requireBackgroundTools: [workflow, subagent]
Superseded
This plugin began as a single-rule ban that refused only job_output { wait: true };
that early version has been folded into the policy shipped here, so there is nothing
left to install separately.
Comments
Loading…
Similar plugins
by cglyvip
DeepSeek Harness 插件:模型请求失败导致本轮停止时,先在原模型重试数次,再沿兜底链循环切换并注入「继续」,免手动干预。
★ 0
MIT
JavaScript
Oct 2, 2026
dsh plugin --profile web add dsh-auto-continueby J0ss077
Stop. Confirm. Run. A DeepSeek Harness plugin that pauses selected tools and waits for your explicit approval before every execution.
★ 3
↓ 93/wk
MIT
TypeScript
Sep 6, 2026
dsh plugin --profile web add @j0ss077/dsh-always-require-tools-approvalby MyRemme
多智能体监工:一个独立模型实时审阅推理文本与工具调用,检测死循环 / 空转 / 偷懒,并按 WARN / BLOCK / STOP 三档落地。DSH 宿主插件 + 浏览器设置界面。
★ 0
JavaScript
Oct 1, 2026
dsh plugin --profile web add dsh-loop-guardby inmny
为 DeepSeek Harness 增加一个直接续跑按钮。当会话异常结束时,可以从现有上下文继续执行,不会引入其他提示词。
★ 3
MIT
JavaScript
Sep 11, 2026
dsh plugin --profile web add dsh-plugin-continueby Tim-ReJet
Durable subagent execution for DeepSeek Harness: a `durable` provider and a model-facing tool that drive pi-durable-subagents, so a crashed delegation converges on its first outcome instead of running twice.
★ 0
MIT
TypeScript
Oct 14, 2026
dsh plugin --profile web add dsh-plugin-durable-subagentby 173787247
Hard-stop consecutive identical tool calls after a configurable streak so the agent cannot spin in place.
★ 2
MIT
JavaScript
Sep 30, 2026
dsh plugin --profile web add dsh-repeat-stop