Back to home@lc23313

dsh-autoupdate

dsh 内置自动更新插件 — Auto-update for DeepSeek Harness: safe version detection, exit-time apply, health check, auto-rollback & circuit breaker.

Stars
0
Language
JavaScript
Created
Aug 23, 2026
Updated
Aug 23, 2026
GitHub repo

Introduction

dsh-autoupdate

A built-in auto-update plugin for dsh (DeepSeek Harness). It adds a 检查更新 (Check for Updates) section to the dsh Settings page: one click checks npm for a new @deepseek-ai/dsh release, a confirm dialog schedules it, and a guarded update transaction — exit-time install, health verification, automatic rollback — does the rest.

中文文档 (Chinese README)

Highlights

  • Settings-page UI (v1.1.0): 检查更新 button under Settings → 自动更新; modal shows version info with 确认更新 / 取消, or "当前已是最新版本,暂无可用更新"
  • Manual by default (v1.1.0): no silent periodic checks — detection runs only on the button click (autoCheck: true restores the v1.0.0 periodic mode)
  • Update channel: any npm dist-tag (latest, rc, …)
  • Exit-time application: a detached helper waits for the dsh process to exit before touching the global install — avoids Windows file locks and survives even a killed dsh
  • Targeted install: resolves the running dsh's own npm prefix (from process.argv[1]) and installs into it with --prefix — immune to multi-Node PATH confusion
  • Transaction safety: exact-version install → dual verification (manifest + actually running the new binary) → automatic rollback to the previous version on any failure
  • Circuit breaker: consecutive failures degrade auto → notify → off; any success restores full automation
  • Optional profile refresh: after a CLI update, user plugins in your profiles can be refreshed via dsh plugin --profile <p> update (with manifest backup/restore)
  • Breaking-update survivability: zero runtime dependencies, no dsh internal API calls on the backend; the UI uses only the settings-section slot, a generic RPC channel, and plain same-origin fetch — see docs/COMPATIBILITY.zh.md and docs/UI.zh.md

Install

Install into any dsh profile through the official plugin channel:

# from npm
dsh plugin --profile web add dsh-autoupdate

# from GitHub
dsh plugin --profile web add github:lc23313/dsh-autoupdate

# from a local tarball (offline sharing)
dsh plugin --profile web add /path/to/dsh-autoupdate-1.1.0.tgz

Verify it was registered as a profile layer, then restart dsh:

dsh --dump-config --profile web   # should list the auto-update row (name: dsh-autoupdate)

The plugin starts checking 30 s after boot, then every 6 hours. State and logs live in $DSH_HOME/plugins-data/dsh-autoupdate/ (default ~/.dsh/).

Configuration

Defaults live in the package's own cordis.patch.yml; override them per profile in ~/.dsh/profiles/<name>/cordis.patch.yml (a user-layer row replaces the row's whole config; omitted keys fall back to schema defaults):

- id: auto-update
  config:
    channel: rc               # track the rc dist-tag
    checkIntervalMs: 3600000  # check hourly
OptionDefaultDescription
enabledtrueMaster switch; false = no-op
channel"latest"npm dist-tag to track; falls back to latest
autoApplytruefalse = detect + notify only (prints a manual command)
autoCheckfalsev1.1.0: false = manual mode (Settings button only); true = v1.0.0 periodic checks
checkIntervalMs21600000Check interval when autoCheck: true (6 h; floor 5 min)
startupDelayMs30000Delay before the first check after boot
maxConsecutiveFailures3N failures → notify, 2N → off
cooldownMs86400000Pause auto-apply after an apply failure
npmTimeoutMs30000Timeout for npm queries
installTimeoutMs300000Timeout for npm install / pnpm update
npmCommand / dshCommandnpm / dshCommand overrides (absolute paths allowed)
registry""npm registry override (mirrors)
updateProfilePluginstrueRefresh user plugins in profiles after a CLI update
profiles[]Which profiles to refresh; empty = auto-detect profiles depending on this plugin
logToConsoletrueMirror log lines to the dsh console

How the update transaction works

detect new version X
  └─ arm: spawn detached helper (polls this dsh process by pid)
       └─ dsh exits (gracefully or killed)
            └─ helper re-confirms the arm in state.json (stale arms abort)
                 └─ npm install -g @deepseek-ai/dsh@X --prefix <running dsh's prefix>
                      └─ on failure: retry ×3 → verify old version intact → stop
                 └─ verify: manifest version == X AND `node <bin> --version` prints X
                      └─ mismatch → reinstall previous version → re-verify → record rollback
                 └─ (optional) per-profile: backup manifests → dsh plugin --profile <p> update
                 └─ write helper-result.json + update state.json
next dsh boot → consume the result → feed the circuit breaker → log the outcome

Security & trust

Before installing any plugin that can run package installs, you should know exactly what this one does:

  • It spawns only npm (version queries, npm install -g @deepseek-ai/dsh@<exact version> into the prefix dsh itself runs from) and, optionally, dsh plugin --profile <p> update|install for profiles that depend on this plugin.
  • It never writes to dsh-owned files (settings.yaml, cordis.patch.yml, profile manifests). All state/logs are confined to $DSH_HOME/plugins-data/dsh-autoupdate/.
  • It never reads or transmits credentials; npm runs under your own environment and registry configuration.
  • Every decision is logged with full detail to autoupdate.log — audit it any time.
  • All installs pin an exact version resolved at check time; rollbacks reinstall the previous exact version.

Manual operations

TaskHow
Inspect statecat $DSH_HOME/plugins-data/dsh-autoupdate/state.json
Read the logcat $DSH_HOME/plugins-data/dsh-autoupdate/autoupdate.log
Reset the breakerdelete state.json
Roll back manuallynpm install -g @deepseek-ai/dsh@<old-version>
Disable auto-applyset autoApply: false (detection + notification remain)
Diagnosticsboot dsh with DSH_AUTOUPDATE_DOCTOR=1
Uninstalldsh plugin --profile <name> remove dsh-autoupdate

Known limitations

  1. Concurrent dsh instances: the helper waits only for the arming process; if another instance still holds locks, npm fails and retries ×3, then defers to the next cycle (circuit breaker counts it).
  2. Long offline periods: 6 consecutive check failures silence the plugin (off); the first successful check after reconnect restores auto.
  3. One-shot headless runs may exit before the first check; lower startupDelayMs for those workflows.

Development

node --check lib/*.js scripts/*.mjs   # syntax check
node scripts/dev-smoke.mjs            # end-to-end smoke test (real detection, autoApply forced off, zero side effects)

Design notes on surviving dsh breaking updates: docs/COMPATIBILITY.zh.md (Chinese).

License

MIT