Auto-continue for DeepSeek Harness
English | 中文
A pure-client composer plugin for DeepSeek Harness (DSH): when a reply is cut off at the model's output-token cap, it sends continue as a normal user message so the model can pick the work back up.
It is deliberately lighter than a host-side retry service:
- no HTTP routes, no polling, no host-side settings file;
- one event subscription for the active conversation;
- bounded in-memory state and persisted counters in
localStorage.
Status: local developer preview, tested against DSH
0.2.1-rc.3. The public npm name is chosen at release time; see PUBLISHING.md.There is an unrelated community plugin also named
dsh-auto-continue(spix18) that focuses on rate-limit/quota retries. This repository focuses on output-token truncation, context compaction recovery, loop guards, and statistics.
Features
| Truncation continuation | turn/end with reason.kind === 'max-tokens' sends "继续" / "continue" after a short delay. |
| Chunk-aware fallback | If the truncated turn's latest assistant message has no completed tool call, the follow-up asks for a skeleton and chunked writes instead of a bare “continue”. |
| Optional error-code retries | RATE_LIMIT, QUOTA / ACCOUNT_QUOTA, EMPTY_RESPONSE, plus user-defined codes. Built-in codes are matched exactly; custom codes are matched against the whole error payload. |
| Context recovery | CONTEXT_WINDOW_EXCEEDED runs /compact once (configurable), then continues; turning this off stops instead of retrying. |
| Loop guards | Consecutive limit, “no new output” limit, and auto-compaction budget. A normally completed turn resets the chain. A stop stays visible in the tooltip. |
| Composer switch | Lucide toggle-left / toggle-right pair next to the model selector, plus a per-conversation count badge. |
| Tooltip | On/off meaning, current state (waiting, compacting, stopped, error), stop reason, and per-conversation/all-conversation counts. |
| Settings page | Settings → Auto-continue: enable, hide the composer switch, trigger toggles, custom codes, context strategy, limits, continuation text, statistics, reset. |
| Statistics | Cumulative and per-conversation counts, counts by reason, successful compactions, conversations tracked. |
| Bounded memory | 128 session states, 200 stat entries, 7-day claim cleanup; no polling and no retained event objects. |
Install (local checkout)
dsh plugin --profile <profile> add /absolute/path/to/auto-continue
For the Desktop profile, install through Plugins → Add plugin or use the Desktop-managed command. After installation, open Settings → Auto-continue or click the compact switch beside the model selector.
A published release will use:
dsh plugin --profile <profile> add <published-package>
Install from GitHub
# latest main — review the current commit first
dsh plugin --profile <profile> add github:tkctly/dsh-auto-continue
# or pin a commit (recommended)
dsh plugin --profile <profile> add github:tkctly/dsh-auto-continue#<40-hex-commit>
The repository is a developer preview and currently keeps the local package name @local/dsh-auto-continue; the public npm name is chosen at release. The plugin has no build step, so Git installs do not need allowBuilds.
Usage
- Open a conversation and click the compact switch to the left of the model selector (gray = off, blue = on).
- When a reply hits the output-token cap, the plugin sends
"继续"(or"continue"in an English UI) as a normal user message. - Hover the switch to see the state, stop reason, and counts.
- Tune behavior under Settings → Auto-continue.
The switch and settings are shared across conversations. Settings and counters live in localStorage; they are not written to the session log or the Host.
Safety and loop guards
The plugin only acts on a completed turn boundary:
- the turn must be the latest turn;
- the session must be idle, open, not blank, not removed, with no queued submission and no prompt error;
- the truncation must have happened after the switch was enabled;
- each turn is claimed once, so reloads and multiple tabs do not send twice.
It stops instead of retrying when:
- the consecutive continuation limit is reached (
1–100, default20); - N consecutive continuations produce no assistant text, reasoning, or tool call (
1–10, default3); - the context-window compaction budget is exhausted (default
1); /compactis unavailable or fails;- credentials are invalid;
- the user stops the task.
A normally completed turn resets the chain. Turn the switch off and on, or send a normal message that completes, to resume after a stop.
Permissions and data
- Reads the session's committed event stream through the public Client
sessionsservice. - Sends a normal user message (
prompt(..., 'queue')) and, for context recovery, the official/compactcommand. - Stores settings/statistics in
localStorage. - No network requests, telemetry, child processes, filesystem writes, or credential access.
- No DOM scraping or clicks; the switch and settings page are React slot registrations.
Troubleshooting
The model keeps saying it will write a file but never calls a tool
This is usually the model's output budget, not the plugin. Inspect the session log's assistant/message events: if usage.outputTokens equals the model cap and source.replayState.response.stopReason is length, the model ran out of output tokens while reasoning or while filling a large tool-call argument. An incomplete tool call is dropped, so the settled message can look like reasoning-only.
Fixes, in order:
- Raise the model's output cap (
maxTokens/defaultMaxTokens) in the local provider config if the server supports it. - Lower the model's reasoning effort, or choose a less reasoning-heavy model.
- Ask for chunked writes: create a skeleton file first, then append or edit sections; keep one tool call under the output limit.
- Start a fresh session with a direct, chunked instruction. Repeating “继续” in a long, cluttered session often reinforces the loop.
The plugin detects a max-tokens turn whose latest assistant message has no completed tool call and switches to a chunking-aware follow-up automatically. It cannot enlarge the model's output cap by itself.
It stopped after a few continues
A normally completed turn ends the chain by design. If the model ends the turn while only claiming it will write a file, the plugin cannot know the file is missing. Hover the switch to see the stop reason; the session log's turn/end reason distinguishes completed, max-tokens, and guard stops.
Compatibility
- DSH
>=0.2.1-rc.3 <0.3.0(engines.dsh). - Node
>=20for development/tests. - The plugin uses the public Client services
sessions,locale, andslots. DSH is in developer preview; slot names and event shapes may change between minor versions.
Development
npm test # Node tests for classification, backoff, guards, stores, and the engine
npm run check # syntax + tests
npm pack --dry-run
The tests install a small window.__ModuleLoader__ capture shim, import the real client.js, and exercise its exported __test functions with fake event sources and timers. No React renderer, DOM, or Harness runtime is required.
License
MIT for this plugin. The composer switch uses Lucide toggle-left / toggle-right under the ISC license; see NOTICE.md for the required attribution. The bundle icon (icon.svg) is original artwork.
No comments yet. Be the first to write one.