dsh-auto-update
A DeepSeek Harness (cordis) plugin that makes the harness update itself.
It periodically checks npm for a newer version of @deepseek-ai/dsh than the currently installed one; when an update is found it downloads the tarball and stages it; when the harness process exits, a detached helper process runs npm install -g to replace the global installation with the new version; and optionally it can relaunch dsh with the original startup arguments. By default the web panel shows a small "Check for updates" pill in the bottom-right corner (click to expand the full panel), which displays version status and offers "Check for updates", "Update and restart", and "Cancel staged update".
How it works
1. Install discovery — derives the global install root from process.argv[1] (the npm shim launches …/node_modules/@deepseek-ai/dsh/lib/bin.js); can also be set explicitly via config.installRoot. If the harness is running from source (pnpm dsh), auto-update is unavailable and logs a note. 2. Version check — calls npm view @deepseek-ai/dsh@<distTag> version --json, reusing your configured registry / mirror / proxy. Includes a minimal built-in semver comparison (handles prereleases such as 1.2.3-rc.1). 3. Staging — npm pack downloads the exact version's tarball into $DSH_HOME/updates/ and writes pending-update.json (with from/to, install root, process pid, whether to relaunch, etc.). This step never touches the running installation. 4. Applying — on the harness's process.on('exit') it detaches bin/apply-update.js: it waits for the old process to actually exit (on Windows a running process locks native modules such as sharp/koffi/node-pty, so installation must happen after exit) → npm install -g <tarball> → verifies the installed version → records the result → optionally relaunches dsh <original args>.
Installation
Install the plugin in your profile directory (same as dsh-session-stats-panel):
corepack pnpm --dir "%USERPROFILE%\.dsh\profiles\web" add "C:\Users\baiyec\Desktop\Harness\plugins\dsh-auto-update"Or, install directly from GitHub using the bundled manifest:
dsh plugin add github:a1113622001/dsh-auto-update> When installing manually, you must register the [cordis.patch.yml](cordis.patch.yml) > bundle at the repo root with the harness so the plugin starts with it. > dsh plugin add already carries that bundle, so no manual patching is needed — > the YAML block below is exactly the content of cordis.patch.yml.
Then append this to %USERPROFILE%\.dsh\profiles\web\cordis.patch.yml:
# dsh-auto-update: lets the harness update itself (check npm → stage → apply on exit)
- insert:
- id: auto-update
name: 'dsh-auto-update'
config:
distTag: latest
checkOnStart: true
checkIntervalMinutes: 240
autoStage: true
applyOnExit: true
relaunch: falseAfter saving, the running harness hot-reloads the host plugin (cordis.patch.yml is watched); refresh the page once and the "Check for updates" pill appears in the bottom-right corner (collapsed by default; click to expand the panel).
Configuration
| Field | Default | Description |
|---|---|---|
distTag | latest | npm dist-tag to track (e.g. latest / next) |
registry | "" | npm registry override; empty uses your configured registry |
checkOnStart | true | check once at startup |
checkIntervalMinutes | 240 | periodic check interval (minutes); 0 disables periodic checks |
autoStage | true | download and stage automatically once an update is found |
applyOnExit | true | run the detached apply process when the harness exits |
relaunch | false | relaunch dsh with the original args after applying ("Update and restart" in the panel always relaunches) |
installRoot | "" | explicitly specify the harness install root (used when auto-discovery fails) |
updateDir | "" | updates directory; defaults to $DSH_HOME/updates (C:\Users\<you>\.dsh\updates) |
Behavior details
- Safe defaults: by default it only "stages + applies on exit" — it never
kills the process mid-session. For a fully automatic loop set relaunch to true, or click "Update and restart" in the panel.
- Panel buttons:
/autoUpdateis a loopback-only RPC channel; the browser
calls status / check / stage / cancel / applyRestart via POST /autoUpdate/<endpoint>.
- Manual trigger:
applyRestartforces a check first, stages if needed, then
writes relaunch: true to the manifest; ~0.8s after responding it exits the process, and the exit hook starts the apply process and relaunches.
- Crash tolerance: if the process is force-killed (no
exitevent), the
staged manifest is preserved; on next start the plugin recovers it and re-checks, then applies as usual.
- Update history:
$DSH_HOME/updates/update-history.jsonlrecords the outcome
of each apply; update-result.json holds the most recent result.
Verification / manual testing
# 1) Plugin syntax
node --check lib/index.js
node --check lib/updater.js
node --check bin/apply-update.js
# 2) Host RPC mounted (harness running)
curl -s -X POST http://127.0.0.1:3080/autoUpdate/status -H "content-type: application/json" -d '{"type":"client-request","rpcId":"t1","method":"status","payload":{}}'
# 3) Force a check
curl -s -X POST http://127.0.0.1:3080/autoUpdate/check -H "content-type: application/json" -d '{"type":"client-request","rpcId":"t2","method":"check","payload":{}}'Known limitations
- Only supports harnesses installed as a global npm package (the
dshCLI in
%APPDATA%\npm). Source runs (pnpm dsh / a dev checkout) are not updated.
- Applying happens after exit: if the process never exits gracefully (e.g. a
hard kill or power loss), the update is deferred to the next exit.
- On Windows, native modules (sharp/koffi/node-pty) can still hold file handles
open after the process exits, occasionally causing EBUSY during npm install -g. The helper waits until the recorded process has truly exited, then retries with backoff, so a single lingering handle does not fail the update.
npm install -grequires write access to the npm global directory and cache
(normal user permissions are enough).
- If the plugin source directory is moved away, the
helperpath recorded in a
staged manifest becomes stale; re-checking re-stages a fresh manifest.