[Feature][更新重启] 有运行中任务时先执行有界优雅退出
- Dominant language
- TypeScript
- Stars
- 2.7k
- Forks
- 395
- Avg merge
- 21h 48m
- Merged PRs (30d)
- 776
Description
## 背景
Cindy 当前更新重启路径会在 updater 启动后调用 `forceQuit()`,直接销毁窗口并执行 `process.exit(0)`,有意绕过统一的 `before-quit` disposer chain。
这个设计可以避免异步清理异常或原生弹窗阻塞 updater,但当用户在任务运行中点击升级时,Maker session、Codex app-server 等也会被直接中断,和用户主动退出时的行为不一致。
本机 Cindy 0.1.16 日志可观察到两条不同路径:
```text
更新重启:
[updateService] forceQuit() — destroying windows and exiting
[lifecycle] process exit without lifecycle disposal code=0
用户主动退出:
[lifecycle] before-quit received
[lifecycle] beginShutdown timeoutMs=6000 reason=before-quit
[lifecycle] runQuitDisposers completed
```
相关但独立的问题:#660 处理了重启后 `thread/resume` 历史载荷超过 16 MiB 的恢复失败;它不改变更新器的强制退出策略。
## 建议
更新流程不要直接无条件强退,而是增加一个“有界优雅退出”阶段:
1. 点击“立即更新”时检查是否存在运行中的 session / turn。
2. 若存在,明确提示用户选择:
- 等待任务完成后更新;
- 停止任务并立即更新;
- 取消本次更新。
3. 用户确认立即更新后,执行与正常主动退出一致的必要清理,例如:
- 冻结/保存 interrupted-turn 标记;
- shutdown Maker sessions 与 agent hosts;
- flush 必要的本地状态。
4. 清理必须有总超时(例如沿用当前 6 秒生命周期上限)。清理完成或超时后,再进入 `process.exit(0)` 强退兜底,保证 updater 不会无限等待。
具体实现可以是 updateService 调用 lifecycle 暴露的专用 `requestUpdateShutdown()`,也可以由维护者选择更合适的边界;核心诉求是保留“升级一定能退出”的保证,同时避免正常情况下跳过全部 disposer。
## 期望行为 / 验收建议
- 无运行中任务:升级流程和当前一样快速。
- 有运行中任务:不会无提示地直接终止,用户能选择等待、停止或取消。
- 选择立即更新:必要状态先落盘/标记,随后可靠退出并完成安装。
- 任一 disposer 卡住或报错:达到总超时后仍会强制退出,不阻塞 updater。
- macOS 与 Windows 都覆盖更新重启测试;Windows 仍能可靠回收可能锁住安装目录的子进程。
## 类型说明
更适合作为 `enhancement / feature request` 讨论,因为当前 `forceQuit()` 是有意设计,不宜在未确认 updater 约束前直接按普通 bug 修改。
Contributor guide
Assessment
This issue has not been assessed yet.