DSH Plugins Marketplace

DSH Plugins

Plugins

/

Tools & Capabilities

/

dsh-loop-rescue

d

dsh-loop-rescue

Manifest valid

DSH plugin that cuts model repetition loops mid-stream, prunes the loop out of the committed message, and resumes automatically.

hasBundlePatch

dsh-loop-rescue

English · 简体中文

Release License: MIT DSH plugin

A loop-rescue plugin for DSH (DeepSeek Harness). When the model falls into repetition (Now. / OK. / Emit. / Producing. rotations, the same paragraph over and over), it cuts the stream from the inside, prunes the loop out of what gets written to the session log, and resumes automatically.

The difference from a plain cut-off: the interrupted message that goes into the next turn's context contains no loop, so the model never re-reads its own repetition and carries on repeating.

Requires DSH 0.1.7 or newer. Pure JS, no build step.

Quick start

Use this or @mrweicodes/dsh-loop-guard, not both: with both on, loops get cut twice.

  1. Install: sidebar Plugins → Add plugin, and give it
    https://github.com/citydirector/dsh-loop-rescue
    
    Switch it on.
  2. The defaults work as they are. To watch before it acts, set mode to observe (see Configuration).

From the command line:

dsh plugin --profile web remove @mrweicodes/dsh-loop-guard
dsh plugin --profile web add -w github:citydirector/dsh-loop-rescue#v0.1.0

Restart dsh web after a command-line install. No pnpm build scripts need approving.

Configuration

The defaults work as they are. To change them, write to the profile's cordis.patch.yml:

- set:
    - id: loop-rescue
      config:
        mode: rescue              # rescue: cut + prune + resume | cut: cut + prune | observe: log only
        watch: both               # both | reasoning | text
        marker: true              # leave a "〔N chars of repeated reasoning removed〕" line where it pruned
        maxConsecutiveRescues: 3  # cap on back-to-back rescues; one normal call resets it
        stallCalls: 3             # nudge after this many reasoning-only calls with no output; 0 = off
        stallMinReasoningChars: 1024
        retryTemperature: 1.0     # temperature for the resume request; unset = unchanged
        retryReasoningEffort: low # reasoning effort for the resume request; unset = unchanged
        retryRequests: 1          # how many requests after a resume use the two settings above
        language: auto            # auto | zh | en
        detector:                 # detection thresholds; rarely need changing
          poolWindow: 30
          poolMinCoverage: 0.75
          cycleMinChars: 600

Consider running mode: observe for a day or two first, check that every loop-rescue: ... loop detected line in the log is a real loop, then switch to rescue.

How it works

When the agent loop assembles an assistant/message, each block's final content comes from the block-end payload, not from the deltas streamed before it. The plugin wraps the model call in the llm/stream waterfall:

  1. It runs a streaming detector on every reasoning and text block.
  2. On a hit it closes every open block: the looping block is replaced by its content pruned back to where the loop started (optionally with a one-line marker), and the stream ends with stop.
  3. The message written to the log holds only the useful content before the loop. The raw stream is still kept in full in the event's stream record, where the trajectory view can show it.
  4. Once the turn has really ended (whenIdle()), it sends a resume message with a correction via followup().
  5. The first N requests after a resume can use a different set of sampling parameters.
  6. After the cap on back-to-back rescues it stops resuming and leaves a note.

Why not edit the session afterwards: an assistant/message cannot carry sourceEventSeqs, so the session surface's replace operation cannot swap one assistant message for another. Pruning at block-end is the only way that keeps message roles and tool-call pairing intact.

Detection rules

RuleCatchesPrunes from
Phrase pool pool≥75% of the last 30 sentences are a handful of recurring short phrases (in any order)Back to where that batch of phrases first appeared
Verbatim cycle cycleThe tail is the same text repeated verbatim, period 16–4000 chars, ≥3 repeats, ≥600 chars in totalKeeps the first copy, prunes from the second

Guarding against false positives:

  • A Chinese full stop always ends a sentence; an English period only when followed by whitespace.
  • Symbol-only lines (|---|, }) are not counted.
  • List items, table rows and quote lines in the text are not counted.
  • The inside of ``` code blocks in the text is skipped entirely.
  • The phrase pool needs at least two different phrases rotating.
  • It never cuts while an open block holds a tool call: closing a half-written tool call would make the host run it with incomplete arguments.

Offline scan

Replay past sessions through the same detector the plugin uses, to see where it would cut:

node tools/scan-session.mjs <session file or directory>          # hits only
node tools/scan-session.mjs <session file or directory> --all    # hits and misses
node tools/scan-session.mjs <session file> --json

Reads plain jsonl and zstd-compressed session files (zstd needs Node 22.15+). The script only depends on src/detector.js and runs on plain node.

Cleaning loops already in the history

The plugin only stops new loops; loops already committed to the history keep being imitated by the model. What DSH sends the model is a frozen projection of the session log, which a plugin cannot change, so the session files have to be cleaned offline with DSH fully closed. This works for old sessions that never had the plugin too.

The recommended tool is dsh-session-manager (dsm loops, a single-file exe on Windows): the same detection rules, plus upgrading, archiving and repairing broken sessions.

This repository also ships a lightweight script (Node 22.15+, v4 sessions only):

node tools/clean-session.mjs            # list sessions with loops, pick by number; Enter = newest
node tools/clean-session.mjs --dry-run  # show what would change
node tools/clean-session.mjs --undo     # restore from the backup
  • On Windows you can also double-click tools\clean-session.cmd, or drop a session folder onto it; if it cannot find the data directory, pass --data <data directory>.
  • Only matching assistant/message events change: text and reasoning are cut back to where the loop started, data.stream is cut to match, and the message's source.replayState is removed. Every other line stays byte-for-byte the same.
  • It backs up to <data directory>\sessions-loop-rescue-backup\ first, and refuses while DSH is running (--force skips that check; not recommended).
  • Versions before 2026-10-17 read only the first frame of a compressed log and wrote the result as a single frame, which DSH treats as corrupt and hides. That is fixed; dsm repair brings hidden sessions back.

Known limitations

  • Loop text already streamed into the chat is replaced by the pruned version once the message is committed, but exactly how it redraws depends on the DSH front-end version.
  • Loops that span steps (every step is "say a line → call the same tool") are out of scope; that is the job of the built-in guard/repeat-tool-reminder.
  • retryTemperature needs an adapter that supports temperature. DSH has no generic field for Ollama's repetition penalty and similar parameters, so they cannot be set from here.

Development

npm install
npm test

Related projects

License

MIT

Comments

Loading…

From the same category

reactive-resume

DeepSeek Harness plugin for Reactive Resume: bridges your resumes and job applications into a Harness session over MCP.

Tools & CapabilitiesManifest valid

★ 41.7k

↓ 164/wk

MIT

Aug 24, 2026

dsh plugin --profile web add dsh-plugin-reactive-resume

by Tencent

Let AI agents use your real, logged-in browser without interrupting your work. CLI + extension for browser automation across any shell-capable AI agent.

Tools & CapabilitiesManifest valid

★ 9.2k

↓ 6.2k/wk

MIT

TypeScript

Oct 15, 2026

dsh plugin --profile terminal add @wxg-prc-cpg/browser-skill-dsh-plugin

by dsh-market

The plugin market inside DeepSeek Harness — browse, search, one-click install · DSH 可视化插件市场

Tools & CapabilitiesManifest valid

★ 7.3k

↓ 117.7k/wk

MIT

TypeScript

Oct 18, 2026

dsh plugin --profile web add dshmarket

by yjh051108

dsh-routing-suite — injector + router-standard kit: install the runtime injector first, then the task-aware reasoning-mode router preset (measured P1-P23).

Tools & CapabilitiesManifest valid

★ 7k

MIT

JavaScript

Sep 18, 2026

dsh plugin --profile web add @dsh-external/dsh-super-injector

by Q00

Agent OS: the agent gets smarter on its own. We just hold the line: Interview-gated, staged evaluation, budgeted evolution loop. MCP server, 14 runtimes: Claude Code, Codex CLI, Gemini CLI, OpenCode,

Tools & CapabilitiesManifest valid

★ 6.2k

MIT

Python

Oct 19, 2026

Index only — not installable

by superdesigndev

OpenRouter for agent tools. Join community here: https://discord.gg/6mQYYfFMAn

Tools & CapabilitiesManifest valid

★ 5.8k

NOASSERTION

Python

Oct 19, 2026

dsh plugin --profile web add treg-dsh