Resumes an agent turn that ended after narrating its next action without calling a tool: the guard replays the turn log on agent/turn-stopping, asks a judge model one true/false question, and steers the same turn to run one more step.
Install
# from npm (prebuilt)
dsh plugin --profile web add dsh-loop-continue
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:yunxiyang/dsh-loop-continue
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
Continue a DeepSeek Harness agent turn when the model only narrated its next action and forgot the tool call.
The agent loop closes a turn as completed the moment a step emits text and no
tool call. A model that writes "now I will re-apply the change" and stops looks
finished to the loop, even though the work is half done.
This plugin listens on agent/turn-stopping, replays the current turn's own
session log, and only asks a judge model one strict true/false question
when the shape matches that failure mode. true steers the same turn to run one
more step; false (or an unparseable answer) lets the turn close.
Install
Install into a profile with the dsh CLI. Its plugin subcommand forwards to
pnpm inside the profile directory, so add/remove behave as usual:
dsh plugin --profile <profile> add dsh-loop-continue
Then restart the profile. The profile's package.json gains the dependency and
dsh.profile.bundles entry, and the bundled cordis.patch.yml inserts the
guard into the layer stack — no manual patch editing is required.
To remove it:
dsh plugin --profile <profile> remove dsh-loop-continue
Working from a local checkout instead? Point the profile at the directory:
dsh plugin --profile <profile> add link:/path/to/dsh-loop-continue
Source edits under lib/ are picked up only on restart.
Config
| field | default | in card | meaning |
|---|---|---|---|
maxContinuations |
10 | yes | hard cap on steering per turn (no infinite loop) |
maxSteps |
10 | yes | newest steps shown to the judge |
maxTailChars |
2000 | yes | trailing-text budget split across the first and last halves |
judgePrompt |
built-in | yes | instruction telling the judge what counts as unfinished |
steerText |
built-in | yes | message injected when the guard steers |
debug |
false | yes | log every evaluation (needs a restart) |
judgeProvider |
null | no | override provider; null/unset = derive from the session route |
judgeModel |
null | no | override model; null/unset = derive from the session route |
judgeMaxTokens |
64 | no | judge output cap |
judgeTemperature |
0 | no | judge sampling temperature |
Deterministic gates
No model call runs unless the turn both:
- ended on a text-only step (no tool call), and
- called at least one tool earlier (so a plain one-shot answer is untouched).
This keeps the extra judge call off ordinary finished turns and only spends it where the model plausibly dropped a pending action.
Stopping early
Steering is not free: each continuation costs a judge round-trip plus one more agent step. So the guard also watches whether a steer worked.
When it steers, it records how far the session log had grown. The next time the same turn stops, it checks whether any assistant step in between actually called a tool. If the model only narrated again, the steer was ignored and the turn is closed instead of spending the remaining budget on the same refusal. A model that answers the steer with a real tool call keeps its normal budget.
Configuring the guard
The guard resolves its config on every evaluation rather than freezing it at mount, so a change reaches the very next turn-stopping check. Two ways to set values:
- the user settings file,
~/.dsh/settings.yaml, under aloop-continue:key, or - the profile's own
cordis.patch.yml.
Prefer leaving judgeProvider/judgeModel unset. The guard then judges with
the model the current conversation is already running, which is by definition a
working route; set them only to judge with a different model on purpose.
Editing the prompts
Both prompt texts ship as defaults and are plain config fields, so you can retune the guard without touching code. The package ships a browser half, so the editor is a card under Settings > Plugins > plugin config. It starts collapsed like every other plugin card; click the header to open it:
Loop Continue - resume an unfinished turn
judgePrompt - decision policy [textarea]
steerText - resume message [textarea]
max steering per turn [3] 0..100
steps in the summary [10] 1..100
trailing-text budget (chars) [2000] 100..20000
debug - log every verdict [ ]
The prompts save on blur, not per keystroke: the Host validates and
persists the whole document on every write, and one write per keystroke of a
740-character policy paragraph is wasteful. The numeric fields and the toggle
save immediately. Every change except debug applies to the next
turn-stopping check with no restart; debug is read when the plugin is
loaded, so it needs one.
The same fields are editable in ~/.dsh/settings.yaml, which is also the
surface to use when the plugin runs headless with no browser half loaded:
loop-continue:
judgePrompt: >-
You inspect one coding-agent turn that just ended. Reply with exactly one
word: true if the trailing text promises work that no tool call performed,
false otherwise.
steerText: >-
You described an action but did not call any tool. Emit the tool call now.
Both surfaces write the same namespace, so a value set in the card shows up in the file and vice versa.
What each field controls:
judgePrompt— the judge's whole decision policy. The judge sees a deterministic summary (tool calls per step, trailing text, the human request) and must answer one word. Tighten it if the guard steers turns that were actually finished; loosen it if it misses dropped actions.steerText— what the model is told when a turn is steered. This is the message the model acts on, so phrase it as an instruction to emit the call.
To revert, delete the fields; the built-ins come back.
Hot mount
cordis.patch.yml ships a plain insert — only id + name, no config
and no !!js expressions — so a market hot-mount can add or remove this plugin
as a minimal row. No user-specific endpoint, provider, or key is baked into the
patch: policy is resolved at runtime as described above.
A patch-layer change is replayed in full on every reload
(applyEntryPatches clones the entry list before applying), so a row adds and
removes cleanly and never accumulates.
Whether a patch edit takes effect without a restart depends on the host:
- Under the CLI (
dsh profile),runProfileinstalls an HMR service and registers the profile and user patch files with it, so patch edits are applied live. - Under DSH Desktop 2.0.3 that path is not taken — the desktop shell
composes the profile itself (
dsh-app-boothelpers) and never loadscordis-plugin-hmr, so acordis.patch.ymledit needs a profile restart.
Edits to lib/*.js always need a restart: the dsh HMR service is created with
root: [], so no source directory is watched for module replacement.
Links
More in this category
FuRongJun-1999/dsh-memory★ 176
White-box AGI architecture exploration: metacognition (self-cognition loop), continual learning (knowledge flywheel), world model (condition space, spatiotemporal memory graph), self-improvement (bootstrap discipline), zero-LLM white-box pipeline, and auditable trust guardrails.
Jonah-Wu23/dsh-gungnir#dsh-plugin★ 3
Evidence-driven goal verification plugin for DeepSeek Harness. Locks goals via /ultragoal and verifies completion against command exit codes and generated artifacts, preventing the model from falsely reporting task completion.
kenz1117/dsh-engram★ 2
Cross-session long-term memory under the "memory palace" metaphor: dual-scope SQLite stores (user + per-git-origin project), hybrid FTS5 + local-vector retrieval with RRF fusion and recency/proof ranking boost, automatic capture from the session log (including the final turn), provenance audit chains, consolidation distillation and decay forgetting, and a settings-page Memory Library panel with corridor topology, tour butler, and refurb list.
dsh-answer-reviewer★ 1
Agentic answer reviewer for DeepSeek Harness: each final assistant turn is re-reviewed by a separate LLM graded 1-100; below-threshold scores steer the agent back with concrete feedback. Live config over a 127.0.0.1 HTTP server, plus a right-sidebar config tab via dsh-better-sidebar.
CAI-MH/dsh-quality-review★ 1
Audit each finished assistant turn with an independent reviewer model and steer the agent to fix failed output, with at most 2 review rounds per turn and SOP-folder standards injected as an extra review dimension.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.