dsh-self-restart
DSH self-restart plugin (Windows): reliable elevated restart via schtasks, transparent front-end recovery, auto-detect and resume in-progress sessions across reboots, business gate prevents wake self-excitation loops.
- Stars
- 0
- Language
- JavaScript
- Created
- Aug 29, 2026
- Updated
- Aug 29, 2026
Introduction
dsh-self-restart
DSH 自助重启插件:把「提权强杀进程树 → 端口释放确认 → 拉起服务 → 存活探测」固化为随时可调用的能力,并让前端自动恢复——用户几乎感受不到重启的存在。
背景(为什么需要它)
DSH 的 host 跑在进程内,改插件/改配置后必须重启进程。而 DSH 进程往往运行在提权上下文,普通权限的 Stop-Process 杀不掉它且会静默失败。2026-08-26 实战验证的唯一可靠路径:
schtasks /create /rl HIGHEST注册一次性计划任务(提权上下文由系统提供)- 任务内
taskkill /F /T /PID树杀端口监听进程 - 等待端口释放 →
Start-ScheduledTask dsh-web-service拉起服务 - 循环探测端口恢复 → 写日志收尾
本插件把这条链路参数化、自动化。
能力
v0.3.4 业务门·防自激环(2026-08-29)
自动发现(log-active 信号)存在自激环:checkpoint 唤醒后的自检回复本身会写会话日志刷新 mtime,且旧去重只看 pending 队列(已 resumed 的任务脱离视野)→ 同一会话在活跃窗口内被连环登记、连环唤醒自检(实证:单会话 15 分钟内三连发,其余会话同批空转)。纯浪费 token 与用户注意力。
修复 = 登记判据从「日志新鲜」升级为「上次自动唤醒之后有新的业务输入」:
latestBusinessInputMs(logPath):逐帧解压会话 zstd 日志,从尾部取最后一条业务user/message的时间戳。排除一切系统自注入:本插件唤醒消息(source.plugin==='dsh-self-restart')、每 turn 伴随指令注入(form==='instructions',如 dsh-mnemon reminder)、运行时上下文快照与 checkpoint 摘要(固定文本前缀)。autoWakeWatermark():账本里各会话 auto-scan 任务的最近resumedAt水位线。- 判据:
wake >= biz→ 丢弃(活跃是自检刷的,任务早已闭环);日志不可读 / 软 Deadline(6s)超时 → 保守放行(宁可误醒一次,不可漏掉真中断)。 - 回退开关:
config.json置"verifyBusinessActivity": false恢复 v0.3.0 行为。 scan干跑返回gate/dropped字段(含 wakeAgeMin/bizAgeMin),可直接观察门效。- schedule 的 scan 总时限 8s→15s(业务门解压是同步成本,给足预算)。
已知边界:wake>=biz 对从未唤醒、从未业务输入的纯系统会话(biz=null→0、wake=0)也成立 → 不登记,符合预期(无人在等它)。
v0.3.0 零登记·自动发现续跑(2026-08-28)
重启最大的次生灾害不再是"起不回",而是重启前正在跑的任务全断、要逐个人工通知继续。v0.3.0 把这件事自动化:
- 重启前(
schedule触发时、进程还活着):自动扫描三路信号,把"重启会打断的工作"写入任务账本(source:'auto-scan'):agents.list()中status==='running'的内存 agent(最强信号)- 会话日志
session.jsonl.zstd的 mtime 在活跃窗口内(默认 15 分钟) jobs.list()中 running 的后台作业(防御式字段读取)
- 重启后(开机 8 秒):手动任务优先、auto-scan 任务按
maxAutoResume(默认 5)上限,逐个错峰(staggerMs,默认 8s)followup回原会话;auto 任务的消息自带"先自查恢复点再继续"指令,防止凭记忆瞎续。 - 配置项:
autoResume/activeWindowMs/maxAutoRegister/maxAutoResume/staggerMs/excludeSessions(子串匹配排除名单)。 - 干跑观察:
POST {method:'scan'}只发现不登记,验收/调参用。 - 会话 id 双向归一:
session-<uuid>与 bare<uuid>两种磁盘/内存形态都接受(2026-08-28 动态探针实测两种并存)。 - 续跑失败自动计数,同一任务最多重试 3 次(防僵尸任务每次开机空转)。
诚实边界:中断瞬间的模型流无法断点续流(续跑=让 agent 自查后从断点继续,可能重复少量已做工作);后台命令类 job 进程无法复活,只能语义重发;goal 自动续轮重启后保持挂起,需用户人工恢复(续跑消息会提醒)。
Host(POST /__dsh-restart/api,body {method,args})
| method | 说明 |
|---|---|
ping | 探活;返回 {ok, t, pending}(不限 loopback) |
status | 当前待执行重启与配置 |
schedule | 调度一次重启(先自动扫描登记任务)。⚠️ 仅限 loopback(127.0.0.1/::1),远程一律 403 |
scan | 干跑自动发现(只看不登记) |
task.add / task.done / task.list | 手动任务账本(sessionId 建议带 session- 前缀) |
schedule 参数:delayMs(默认 12000,最小 3000——给触发方的响应留出落地时间)、reason(写入日志)。
重复调度有防抖:已有排队中的重启时返回 already:true。
安全说明:host-auth 准入守卫只包
/api前缀,自定义前缀路由不在守卫内;本插件对危险操作自建 loopback 围栏。
Client(无 UI 面板,纯后台循环)
每 4 秒 ping 一次 host:
- 连续 ≥2 次失败 → 全屏遮罩「DSH 重启中… 服务恢复后将自动刷新」
- 失联后首次成功 →
location.reload()自动刷新
于是:agent 触发重启 → 用户看到遮罩 → 页面自己回来 → 继续对话验证。
配置(可选)
~/.dsh/self-restart/config.json:
{ "port": 3080, "startTask": "dsh-web-service", "delaySec": 12,
"autoResume": true, "activeWindowMs": 900000,
"maxAutoRegister": 12, "maxAutoResume": 5, "staggerMs": 8000,
"excludeSessions": [] }
port:DSH 监听端口(用于定位要杀的进程)startTask:拉起 DSH 的 Windows 计划任务名delaySec:默认延迟秒数
日志:~/.dsh/self-restart/restart.log
agent 触发方式(任何会话可用)
Invoke-RestMethod http://127.0.0.1:3080/__dsh-restart/api -Method Post `
-ContentType 'application/json' `
-Body '{"method":"schedule","args":{"delayMs":15000,"reason":"host 插件更新"}}'
安装
npm 包形态:npm i dsh-self-restart 后把包目录复制进 profile 的
node_modules\dsh-self-restart\(或按 DSH 插件管理器流程装载),在 profile package.json
的 dsh.profile.bundles 追加 "dsh-self-restart",重启 DSH 一次(最后一次手动重启 🎉)。
Git 形态:git clone https://github.com/jiang12345-code/dsh-self-restart.git → 同上复制 +
登记 bundle + 重启。
依赖环境:Windows + 已配置拉起任务(默认计划任务 dsh-web-service,端口 3080,可在
~/.dsh/self-restart/config.json 覆写)。
License
MIT