dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
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.
| 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 |
| 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.
Through the plugin page — the only channel that keeps the plugin visible in the inventory with its own toggle:
isAbsolute() before any npm-spec parsing and never touches a registry, so
the registry chooser in that dialog is irrelevant.package.json, requires a name and a dsh.bundle, adds
the dependency to the profile, then reconciles dsh.profile.bundles
automatically ("new bundle dependencies activate automatically"). The plugin
then appears under 已安装 with a toggle.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
# 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.
requireBackgroundTools
is for, and what the shell maxTimeoutMs cap already handles for commands.ask_user_question is deliberately never banned: blocking on a human is the
feature.workflow and a synchronous subagent are 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]
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.