Back to home@jiang12345-code

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
GitHub repo

Introduction

dsh-self-restart

npm version CI License: MIT

DSH 自助重启插件:把「提权强杀进程树 → 端口释放确认 → 拉起服务 → 存活探测」固化为随时可调用的能力,并让前端自动恢复——用户几乎感受不到重启的存在。

背景(为什么需要它)

DSH 的 host 跑在进程内,改插件/改配置后必须重启进程。而 DSH 进程往往运行在提权上下文,普通权限的 Stop-Process 杀不掉它且会静默失败。2026-08-26 实战验证的唯一可靠路径:

  1. schtasks /create /rl HIGHEST 注册一次性计划任务(提权上下文由系统提供)
  2. 任务内 taskkill /F /T /PID 树杀端口监听进程
  3. 等待端口释放 → Start-ScheduledTask dsh-web-service 拉起服务
  4. 循环探测端口恢复 → 写日志收尾

本插件把这条链路参数化、自动化。

能力

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'):
    1. agents.list()status==='running' 的内存 agent(最强信号)
    2. 会话日志 session.jsonl.zstd 的 mtime 在活跃窗口内(默认 15 分钟)
    3. 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.jsondsh.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