dsh-restart-handoff
改完东西必须重启?它替你重启,再把对话接回原来的会话。
简体中文 · English
普通的「重启」只是关掉再打开:你正在做的事全没了,得从头解释一遍自己在哪一步。 这个插件补上缺的那一半——为什么重启、重启后第一步做什么,跟着进程一起活下来。
A plain restart throws the work away. This plugin keeps the "why" and the "what next" alive across the relaunch.

它解决什么
Agent 改完插件代码,宿主会回一句 application: "restart-required"——改动只有重启才生效。于是你手动关掉 App、重新打开、想起来刚才做到哪、再打一遍需求。
这个插件把这三步接了起来:
- 不用你记得——重启前先把「下一步做什么」写成交接话存到磁盘,重启后它作为会话的第一条消息出现;
- 不打断回答——重启排到这一轮说完之后才执行,不会把句子截断在半路;
- 不连环重启——冷却时间、尝试次数上限、一次性续跑,撞车时也只重启一次。
三种开始方式
| 触发源 | 谁发起 | 什么时候 |
|---|---|---|
| 自动 | 宿主监听 plugin_manager 的工具结果 |
结果里出现 restart-required,即改动必须重启才生效 |
| 工具 | agent 主动调 restart_and_continue |
agent 知道自己刚改了什么,顺手把交接话写掉 |
| 手动 | 设置 →「重启并交接」→ 立即重启 | 你现在就想重启(这一种不续跑) |
两条自动路径撞车时,后到的会让位(日志里是 hand-off request dropped),已排程或已在等待时返回 already-scheduled / already-deferred。
重启后会收到什么
不是模板,是模型自己写的一段话——插件只负责搬运,原样投递:
🔄 DSH 已自动重启完成,接着做未完成的部分
发生了什么:触发原因是
plugin-manager: host-module,上一轮是等回答说完、结果落盘之后才退出的(不是崩溃),上下文完整。接下来怎么做:① 从这句话中断的地方继续:把
client.js的新开关接上;② 先确认上一步有没有只做了一半。
模板只在三种情况下兜底:没给交接话、交接超时(2 分钟)、拿不到会话 id。
安装
前提:DSH 桌面版(Electron)。宿主这一半要重启 App,纯 web / CLI 宿主会拿到 status: "unsupported"。
从 Release 的 tarball 装(不需要 npm 账号):
plugin_manager: { action: "install_bundle", target: "/绝对路径/saolence-dsh-restart-handoff-0.1.0.tgz" }
从 npm 装(发布后):
plugin_manager: { action: "install_bundle", target: "@saolence/dsh-restart-handoff" }
从本地仓库装:
plugin_manager: { action: "install_bundle", target: "/绝对路径/dsh-restart-handoff" }
package.json 声明了 dsh.bundle.patch,bundle 自带的 cordis.patch.yml 会自动插入 restart-handoff 这一条。之后停用 / 启用:
plugin_manager: { action: "set_plugin", target: "include:restart-handoff", enabled: false }
⚠️ 改这个包本身不会热重载。 profile 指向它的是符号链接,HMR 收不到通知;改完
index.js/client.js要 toggle 一次(或重启一次)才生效。
设置面板
设置 →「重启并交接」:
- 检测到需要重启时自动重启——盯着
plugin_manager的结果找restart-required; - 允许 agent 主动重启——开放
restart_and_continue工具; - 等本轮回答结束后再重启——默认开;关掉就是立刻重启,会打断正在作答的这一轮;
- 重启后自动继续——重启后把交接话投回去;不勾选就只是重启,等你开口;
- 立即重启——现在重启,不续跑;
- 倒计时可取消,下面是最近几次事件的时间线。
![]() |
![]() |
设置存在 ~/.dsh/restart-handoff/settings.json,事件在 history.jsonl,完整日志在 ~/.dsh/restart-handoff.log。
一次重启的完整路径
改动需要重启
│
├── 自动:宿主看到 restart-required → 用 steer 问模型
│ 「写交接话,然后调 restart_and_continue」
│ └── 2 分钟没回音:用内置文案照常重启
└── 工具:agent 调 restart_and_continue({ continuation })
│
▼
挂起请求 pending.json ← { sessionId, continuation, reason, requestedAt, attempts }
▼
等这一轮说完
▼
1.5 秒倒计时(可取消)→ detached 的 sh helper
│ 退出 App · 清理 Electron 的 Singleton 锁 · open -n · 确认新主进程真的活着
▼
新宿主启动,插件加载,2.5 秒后:
resolveAgent(sessionId) → prompt({ mode: "queue", content: [交接话] }) → 删掉 pending.json
▼
同一个会话收到的下一条消息,就是那段交接话
工具:restart_and_continue
{
"reason": "换了侧边栏插件",
"continuation": "## 为什么重启\n…\n## 刚才做到哪\n…\n## 下一步\n…",
"delay_ms": 1500
}
工具立刻返回,不等重启,也不阻塞这一轮:
| 返回 | 含义 |
|---|---|
deferred |
已挂起,这一轮说完再重启 |
scheduled |
倒计时已经在跑 |
already-deferred / already-scheduled |
已经有一次在排队了 |
cooldown / disabled / unsupported |
冷却中 / 功能被关 / 不是桌面宿主 |
「重启完成」永远不会从这个工具返回——完成证据就是那段交接话本身,它作为下一条消息到达。
next_step 仍然接受,但已弃用,请用 continuation。
写入的文件
~/.dsh/restart-handoff/
├── pending.json # 跨重启保留;交接话投递成功后删除
├── settings.json # 第一次改设置时创建;没有文件 = 默认值
└── history.jsonl # 面板时间线用的追加式事件日志
~/.dsh/restart-handoff.log # 完整文本日志,含 helper 脚本自己的输出
已知边界
- 只有桌面版。其它宿主拿到
status: "unsupported"。 - 只有 macOS:重启 helper 是
/bin/sh脚本,用osascript退出 App、open -n重开。 - 重启仍然会打断正在跑的那一步:shell 命令没法接着跑,只能重跑。交接话说的是「从哪继续」,不是「当时手里有什么」。
- GUI 端口会变:重启后请用 App 打印出来的地址,别用书签。
- 「立即重启」按钮不续跑,因为不写 pending。
- 冷却时间存在内存里,重启后归零;但
pending.json带着尝试次数和 10 分钟有效期,成不了无限重启循环。
开发
node --check index.js && node --check client.js
node test/smoke.mjs # 状态读写往返 + helper 脚本断言,不需要装进 Harness
不装进 App 也能看面板长什么样(自带一个极简 React 替身 + 静态页):
cd test/preview && cp ../../client.js . && python3 -m http.server 8781
# 打开 http://127.0.0.1:8781/preview.html?s=idle
s 可选 idle / countdown / waiting / handoff / empty。
目录
.
├── index.js # 宿主:排程、工具、post-execute 监听、HTTP 路由
├── client.js # 设置面板(__ModuleLoader__ + settings.section)
├── lib/relaunch.js # sh helper:退出 → 清锁 → open -n → 确认活着
├── lib/state.js # pending / settings / history / log
├── cordis.patch.yml # 一条 insert
├── locale/{en,zh}.json # 插件列表里的名字与简介
├── icon.svg
├── docs/ # 面板截图
└── test/ # 冒烟测试 + 面板预览台
许可
MIT
English · 简体中文


No comments yet. Be the first to write one.