packages/dsh-task-board
zhu1090093659/dsh-web侧边栏多列任务看板:卡片交给真实 DSH 智能体会话执行,支持 cron 定时(Host 侧到点执行,关浏览器也生效)。
dsh-auto-continue
Recover interrupted DSH sessions automatically, with an optional loop to continue after successful turns.
English · 中文 · Changelog
Automatic recovery for DeepSeek Harness, in the Web UI and desktop app. When a recoverable failure interrupts a session, the plugin sends your configured continuation prompt through DSH. The engine runs inside the host process, so it keeps watching while browser tabs are closed; all tabs share that engine. Recovery is enabled by default. Continuing after successful turns is a separate, opt-in autonomous loop.
Smart recovery (all configurable):
en and zh are supported; other languages fall back to Chinese. Switching languages updates built-in defaults without overwriting custom textcontinueText supports {code} {message} {status} {tool} {turn} {errorCount} {elapsed} placeholders, so the resume message can carry the failure context ("Continue ({tool} failed: {code})"); a separate template fires on max-tokens (e.g. "Continue the output without repeating anything already generated")git push that may have gone through), the resume message tells the model to check state first and not to rerun; if the tool is confirmed done, it says so and asks not to repeat it; a failed tool gets no guard (retrying it is the point). Both guard texts are configurable ({tool} / {result} placeholders)no-visible-output markers also recover after restart. Disabling Resume silent turns cancels queued silent sends; silent turns never reset the retry cap, even while the option is off.resumeCompletedTurns). When enabled, normally completed turns continue after the grace period, without the recovery cooldown or attempt cap. Reasoning-only turns and explicit no-visible-output endings still consume the recovery budget and obey backoff. Global pause, a session pause, manual Stop or changing that session to Recovery only / Off stops the loop. The profile default only affects sessions using Follow default. Its prompt is separate from the loop guard’s prompt (continueTextLoop, default Continue).It watches the live event streams and reacts to:
Event · Meaning turn/end → error · Turn failed (model / network / timeout, …) turn/end → interrupted · Crash-orphaned turn left behind by a host restart (recovered by the startup scan) turn/end → max-tokens · Output token ceiling reached turn/end → completed / no-visible-output with no visible output · Observed model activity without visible output, or an explicit silent-ending marker turn/end → completed · Continue a normal completion only when autonomous loop is enabled
Recovery stops for: manual Stop, policy rejection (blocked), paused sessions, subagent sessions and the consecutive-attempt cap. A new turn or manual user message cancels a queued continuation. Live interrupted markers are left to the startup recovery scan. Recoverable failures during cooldown are deferred, not discarded. If an interrupted session already has queued turns, the continuation runs first and the existing turns retain their order behind it. The loop guard can separately cancel and restart a running turn that is repeating itself.
Subagent sessions stay under their parent agent's control. The plugin skips them during live recovery and startup scanning, ignores Resume now for them, and leaves them out of loop-guard cancellation. Any queued recovery is cancelled when a session is identified as a subagent.
The host-side engine subscribes to the session event firehose inside the dsh host process — one engine shared by every browser tab. On an interruption it waits a grace period (default 3 s) — if the host starts a new turn by itself (turn/start), the auto-continue is cancelled — then sends the configured text through the agent registry (agent.followup, the same queue the Send button uses). When that queue already contains turns, the engine promotes only its newly inserted continuation before the host wakes the agent; it does not remove or reorder the queued user turns.
On host boot it also scans the live sessions: a session whose last turn ended with a non-human reason within the scan window (default 15 minutes), with no later turn/start or user message, gets resumed automatically too (e.g. the host crashed while the browser was closed — the agent-loop resumes the session and the engine picks it up). Persisted sessions the host never reloaded are enumerated from session storage and materialized into the registry first; a journal that stopped mid-turn is completed with an interrupted marker on read, so restart-orphaned turns are recovered the same way.
Storage scanning runs separately from live-session recovery. Each storage read has a five-second timeout, and the scan yields every 16 observations without waiting for the next polling interval. This lets recently interrupted sessions deep in the storage listing be reached within the startup window. Recovery restores the session's preset and recorded model; stopping the plugin cancels pending storage work.
Startup recovery isolates failures per session. If history cannot be read or contains invalid events, that session is skipped for the current startup scan and an error is logged; other sessions can still recover, without losing a recovery slot. Invalid entries are not silently removed, since they could hide a manual stop or a newer turn. Valid empty histories and a registry that is still loading remain retryable within the scan window. Reloading a repaired session as a new session object also makes it eligible for scanning again. See #58.
The browser provides the settings card and the composer switch and mode menu, plus a status bridge that shows notifications (with Resume now / Pause this session 1h buttons, routed back to the host engine) and feeds the card's stats / paused-sessions panels.
The diagram summarizes the automatic recovery path, the loop-guard restart path, and the exit to human intervention. Click it to open the full-size version.
DSH plugins install into a profile (dsh web → web profile). The commands below install into the web profile; restart dsh web after installation. In the desktop app, install through its Plugins page instead.
DSH runtime · Plugin version · Configuration entry point 0.2.1-rc.2 · 0.17.0 verified · Plugins → dsh-client-auto-continue 0.2.1-alpha.1 · 0.17.0 verified · Plugins → dsh-client-auto-continue 0.2.0-rc.1 · 0.12.1 or newer · Plugins → dsh-client-auto-continue 0.1.7-rc.2 · 0.11.9 or newer · Same Plugins page Older hosts with the legacy settings API · Legacy UI retained · Settings → Plugins → Plugin configuration
DSH 0.1.0-rc.6 and earlier are unsupported. Automated settings and compatibility checks cover 0.1.7-rc.2, 0.2.0-rc.1, 0.2.1-alpha.1 and 0.2.1-rc.2; startup failure isolation is also checked against 0.2.0-rc.2 and 0.2.1-alpha.1. Desktop app versions and embedded DSH runtime versions are different; use the runtime version when checking compatibility. For the CLI, run dsh --version; see official DSH releases for available versions.
Plugins 0.11.9 and 0.12.0 are rejected by DSH 0.2.0-rc.1’s version check. Upgrade the plugin to 0.12.1 or newer; its existing configuration-form integration works on this runtime. See #50.
On current DSH, Settings → Built-in plugins is a component inventory, not the configuration editor. Use the main Plugins page. The screenshots below show plugin 0.14.0 on DSH 0.2.1-alpha.1. If you previously installed with a symlink or hand-written loader entry, see Migrating an older installation.
Published as dsh-client-auto-continue:
dsh plugin --profile web add dsh-client-auto-continue@latest
dsh webLet active work finish and stop DSH. Run the npm command above again to replace the installed version with @latest, then restart DSH and reload the browser. Existing configuration overrides remain in the profile. For a desktop installation, update the plugin from that app’s Plugins page and restart the app; updating the CLI’s web profile does not update the desktop profile.
Installs straight from the repository's default branch — built artifacts are committed, so no local clone or build step:
dsh plugin --profile web add github:HsiangNianian/dsh-auto-continue
dsh webThis tracks themainbranch rather than released tags — great for trying the latest changes, while the npm method above is the stable choice. Switching between install sources is just re-runningdsh plugin --profile web add; the profile dependency is replaced in place.
Use Node.js 22, the version used by CI.
git clone https://github.com/HsiangNianian/dsh-auto-continue.git
cd dsh-auto-continue
npm ci
npm run build
# the package carries its own cordis.patch.yml (dsh.bundle.patch),
# so the plugin row registers itself
dsh plugin --profile web add "link:$(pwd)"
dsh webA manual loader entry can start the engine without registering a bundle in the Plugins page. Use the profile's package manager to install the bundle; a symlink and insert entry alone are no longer the recommended setup.
dsh web. Back up package.json, cordis.patch.yml and pnpm-lock.yaml in ~/.dsh/profiles/web/, plus ~/.dsh/settings.yaml if it exists. If you set DSH_HOME, use that directory instead of ~/.dsh.auto-continue row inside an `insert` list (and the list if it becomes empty). The installed bundle supplies that row. A top-level - id: auto-continue with config: is a configuration override: keep it.package.json, dsh.profile.bundles should now include dsh-client-auto-continue, alongside the existing DSH bundles. If it already does and the plugin appears in Plugins, this part is already complete.settings.yaml → auto-continue section or the removed row's config into the profile's cordis.patch.yml. For example, a custom cooldown becomes:- id: auto-continue
config:
cooldownMs: 45000 # example: preserve your own saved valueMerge into an existing override instead of adding another one. Keep unrelated settings intact. DSH 0.1.7 / 0.2 reads this entry config; editing the old settings.yaml section will not update the new form.
dsh web again and reload the browser. Open Plugins → dsh-client-auto-continue, select the appropriate settings category, and check that your values are present. Save a change and reload to confirm it persists.The include:auto-continue label in Built-in plugins is a normal loader prefix. It does not, by itself, indicate a legacy install or a duplicate engine.
For hosts that expose both modern profile config and the legacy settings API (#64), the plugin uses profile config without registering a second settings namespace. It imports the auto-continue section of $DSH_HOME/settings-legacy.yaml once per profile, including the saved pause and custom prompts. Existing profile values take precedence. The original file and other plugins' sections stay untouched; completion is recorded separately from editable settings so even a whole-config reset stays reset after restarting.
Recovery and the loop guard wait while this import is pending. If the legacy file cannot be read or validated, or the profile cannot be saved, the host logs an import error and keeps both held. Repair the file or profile permissions and restart the host. Hosts that only support the legacy API continue using their existing settings store.
dsh --profile web --dump-config | grep -A 4 'id: auto-continue'The composed config should contain one id: auto-continue entry. In Plugins → dsh-client-auto-continue, check that the component is Running and that the General category shows editable fields. With verbose logging enabled, engine activity appears in the terminal running DSH.
dsh plugin --profile web remove dsh-client-auto-continue # npm / repo install
# also remove this plugin's config override from cordis.patch.yml, if present
dsh webThe Auto-continue switch beside the input applies only to the current conversation and saves immediately
Turning it off selects Off, and turning it back on selects Follow default Use the mode menu next to the switch to choose a mode:
Mode · Behavior Follow default · Use Default session mode from the plugin settings, initially Recovery only Off · No automatic followups or loop-guard interruptions in this conversation Recovery only · Recover eligible failures and silent turns; leave normal completions alone Autonomous loop · Also continue normally completed turns, using the loop prompt
For example, keep A looping, B recovering failures and C off. Each conversation's choice is saved in the host's profile settings (sessionModes), shared across tabs and retained after a host restart. Choosing Follow default explicitly removes that conversation's independent policy, including an inherited override.
Enable auto-continue globally in General remains the master control. Turning it off pauses all automatic followups without replacing individual choices; turning it back on restores those choices. Switching a conversation off cancels pending grace, cooldown and loop-guard retries. It leaves any current turn running. Switching Loop to Recovery only cancels pending autonomous followups. Re-enabling does not resurrect cancelled sends.
The notification's Pause this session 1h still temporarily suspends one conversation. Resume now requests a single send even while paused or Off, without changing the stored mode. The global loop-guard setting remains independent of global pause, but a conversation set to Off is excluded from the guard too.
To hide the controls, open Plugins → dsh-client-auto-continue → General, turn off Show auto-continue switch in the composer, then Save. This only changes visibility (showComposerToggle, default true). Hosts without the composer slot retain the settings card. A failed save surfaces as a DSH toast instead of inline red text, and a host that stays unavailable for three seconds announces itself once without flashing on a normal load. The switch and mode menu stay disabled while the host bridge or writable settings service is unavailable. When the composer row narrows, the same container query used by the native permission picker collapses the label to its icon and the mode menu to its arrow, keeping the switch and menu on one line.
On DSH 0.1.7 / 0.2, open Plugins from the main sidebar, choose dsh-client-auto-continue, then select a settings category. This is separate from Settings → Built-in plugins, which only lists component status. Older DSH versions use Settings → Plugins → Plugin configuration.
Use General, Retry strategy, Startup recovery, Continue text, Safety, and Status and logs to find controls. Switching categories preserves unsaved changes. Status and logs contains today's activity, recent recovery attempts and paused sessions.
Recent recovery attempts groups the last 20 recovery prompts across the host by session, showing each session's count in that window, latest cause, time and consecutive count at the last send. It works with browser notifications off. Causes distinguish silent output, output limits, request errors, restart interruptions, loop-guard recovery and manual resume. Normal autonomous continuations are excluded. These are sent prompts, not proof of completion or a model-health score; repeated recovery is a reason to inspect the conversation and consider a handoff. The history contains no message text and resets when the plugin restarts.
The settings card starts with a compact GitHub invitation row, then the category navigation; its fields, switches and default-mode selector use DSH's native settings primitives. The plugin manager above already shows the localized plugin name, version and enabled state. Edits take effect when you click Save.
With Browser notifications enabled, each successful save sends one confirmation from the tab where you saved. Turning notifications off sends a final confirmation if browser permission is already granted; later saves stay quiet. Discarded changes, invalid values, an