@d86e/dsh-doctor
dsh-doctor: self-healing watchdog for the DeepSeek Harness web profile. Recovers from plugin-induced boot failures within 60s, runs an unbounded CLI doctor, captures every tool error, and watches all live sessions for stuck turns.
安装
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:d86e/dsh-doctor说明文档
阅读完整 README ↗Usage
After install, you can ask the agent:
> dsh_doctor_status
> dsh_doctor_diagnose
> dsh_doctor_watch_list
> dsh_doctor_safe_mode_enter
> dsh_doctor_drain_deferred
From a shell:
dsh doctor # unbounded CLI doctor (foreground)
dsh doctor --dry-run # triage only, no writes
To uninstall:
> dsh_doctor_uninstall
Configuration
All knobs can be set either in cordis.patch.yml (under config:) or via DSH_DOCTOR_* environment variables.
| Field | Env var | Default | Description |
|---|---|---|---|
healthIntervalMs | DSH_DOCTOR_HEALTH_INTERVAL | 30000 | Health probe period |
healthFailuresToRecover | DSH_DOCTOR_HEALTH_FAILURES | 3 | Failures before triage |
recoveryBudgetMs | DSH_DOCTOR_BUDGET_MS | 60000 | Hard ceiling per incident (watchdog) |
logMaxBytes | — | 5242880 | Per-log rotation size |
logBackups | — | 3 | Rotated log files kept |
safeModeBundles | — | ["dsh-core"] | Bundles kept in safe mode |
toolErrorCapture | DSH_DOCTOR_TOOL_ERROR_CAPTURE | true | Subscribe to tools/* |
toolErrorMaxQueue | DSH_DOCTOR_TOOL_ERROR_QUEUE | 500 | Per-session queue cap |
watchEnabled | DSH_DOCTOR_WATCH_ENABLED | true | Master switch for session watch |
watchIdleThresholdMs | DSH_DOCTOR_WATCH_IDLE_MS | 600000 | Idle timeout (10 min) |
watchNudgeCooldownMs | DSH_DOCTOR_WATCH_COOLDOWN_MS | 300000 | Min interval between nudges |
watchMaxNudgesPerSession | DSH_DOCTOR_WATCH_MAX_NUDGES | 3 | Cap before giving up |
watchContinueText | DSH_DOCTOR_WATCH_TEXT | "继续" | Text to inject (supports {elapsed}, {turn}, {sessionId}) |
watchTickIntervalMs | DSH_DOCTOR_WATCH_TICK_MS | 30000 | Idle-check period |
Tool error classifier — replace it
If the default classification (network/5xx/429 → transient, 401/403/quota/context-overflow → agent, else → business) is wrong for your stack, pass your own classifier / policy when you register the plugin from a wrapper bundle. Both functions receive the full ToolErrorContext and return synchronously.
Session watch text — localize it
watchContinueText accepts the placeholders {elapsed} (seconds since last event), {turn} (current turn number), {sessionId}. So "已经过去 {elapsed} 了,请继续第 {turn} 步" works.