Skip to content

feat(electron): add idle mode and task-driven sleep prevention - #1561

Open
ConradLu2740 wants to merge 2 commits into
proma-ai:mainfrom
ConradLu2740:feat/sleep-guard
Open

feat(electron): add idle mode and task-driven sleep prevention#1561
ConradLu2740 wants to merge 2 commits into
proma-ai:mainfrom
ConradLu2740:feat/sleep-guard

Conversation

@ConradLu2740

Copy link
Copy Markdown

PR 描述(中文版,覆盖两个功能:挂机模式 + 任务防休眠)

标题建议:feat(electron): add idle mode and task-driven sleep prevention
分支建议:feat/sleep-guard(基于 main 新建,重放本地 commit e2e0b44808b751


这个 PR 做了什么

面向「长任务无人值守」场景,新增两个睡眠管理能力(设置 → 通用):

  1. 任务防休眠(默认开启):只要 Proma 有任务在跑(Agent run / 自动化任务 / 飞书桥接任务),通过 powerSaveBlocker('prevent-app-suspension') 阻止系统休眠 —— 用户锁屏、息屏、甚至合上笔记本盖都不会中断任务;任务全部结束后自动恢复系统默认电源策略。
  2. 挂机模式(手动开关,默认关闭):开启后立即调用系统命令熄灭显示器并阻止系统休眠,适合睡觉前/离开时挂机跑任务;移动鼠标或按任意键唤醒屏幕,关闭开关或退出应用自动恢复。

两者相互独立(各自持有独立的 powerSaveBlocker id),可叠加使用。

为什么做

  • 长任务(过夜批量、长导出、飞书/钉钉镜像、自动化任务)需要「人离开、机器不睡」;此前唯一的防休眠(feishu-sleep-blocker)只服务于飞书会话镜像,且没有任何「任务运行期间防休眠」的能力。
  • 用户手动锁屏/息屏/合盖时,系统默认会休眠中断任务 —— 需要 Proma 在任务运行期间主动阻止,任务结束再放手。

实现方式

任务防休眠(默认开启)

  • 新增 apps/electron/src/main/lib/task-sleep-guard.ts —— 纯逻辑、不依赖 Electron,便于单测:
    • token 集合跟踪活跃任务:第 1 个任务开始时启动 powerSaveBlocker('prevent-app-suspension'),最后 1 个任务结束时释放;并发任务只持有一个 blocker。
    • 默认开启:settings.taskSleepGuard?.enabled !== false;设置关闭时立即释放(任务继续跑但不再阻止休眠),重新开启时若仍有任务在跑则自动恢复。
    • blocker 被系统回收时自动重建。
  • 新增 apps/electron/src/main/lib/task-sleep-guard-electron.ts —— Electron 接线层,导出 taskSleepGuard 单例与 syncTaskSleepGuard / stopTaskSleepGuard
  • apps/electron/src/main/lib/agent-service.ts —— 挂钩所有 run 入口:
    • runAgent(界面任务)与 runAgentHeadless(飞书 Bridge、自动化任务等外部调用)都在 onRunStartedbegin(token),在 onComplete / onError / 未处理异常时 end(token);token 用闭包引用,重复 end 安全。
  • 设置类型/持久化/UI:types/settings.tsTaskSleepGuardSettings)、settings-service.ts(默认 { enabled: true } + sanitize)、ipc.tsUPDATE / UPDATE_SYNC 同步)、index.ts(启动同步、退出释放)、GeneralSettings.tsx(开关,带 pending 串行化防连点乱序)。

挂机模式(手动,默认关闭)

  • 新增 apps/electron/src/main/lib/idle-mode.ts —— 平台无关核心:
    • buildDisplayOffCommand(platform):macOS pmset displaysleepnow / Windows 经 -EncodedCommand 的 PowerShell SendMessage(SC_MONITORPOWER) / Linux xset dpms force off;不支持的平台返回 null,自动降级为「仅防休眠」。
    • IdleModeManager:幂等启停 + generation 计数器,确保「关闭后仍在途的息屏命令」不产生误导反馈。
  • 新增 apps/electron/src/main/lib/idle-mode-electron.ts —— Electron 接线层。
  • 设置类型/持久化/IPC/主进程/UI 接线同任务防休眠(IdleModeSettings,默认 { enabled: false })。

平台支持

平台 挂机模式息屏 防休眠(两者共用)
macOS pmset displaysleepnow powerSaveBlocker('prevent-app-suspension')合盖实测有效
Windows PowerShell SendMessage(SC_MONITORPOWER)-EncodedCommand(规避 cmd.exe 引号剥离) 同上(阻止空闲/合盖睡眠)
Linux xset dpms force off(尽力而为,Wayland 可能静默失败) 同上
其他 降级为仅防休眠 同上

息屏命令失败仅记录日志,绝不影响防休眠生效。唤醒屏幕是系统默认行为(鼠标/键盘)。

测试

  • bun test 相关用例:
    • task-sleep-guard.test.ts —— 11 个用例:并发任务、部分结束保持、重复 end 安全、设置关闭/重开恢复、退出清理、默认开启判断。
    • idle-mode.test.ts —— 14 个用例:启停 / 幂等 / blocker 失效重建 / 息屏失败兜底 / 竞态 / 平台命令字符串(含 Windows 脚本 Base64 解码校验)。
    • 回归:feishu 防休眠、settings 类型全部通过;全量 396 测试无新增失败(5 个既有环境失败与本次无关)。
  • bun run typecheck —— 无错误。
  • macOS 真机实测
    • 任务防休眠:真实 Electron 运行时下 powerSaveBlocker 生效/释放正常;合盖实测:合盖 10-15 秒期间系统零睡眠事件pmset -g log 佐证),开盖正常,任务不中断。
    • 挂机模式:pmset displaysleepnow 真实熄灭显示器,鼠标/键盘唤醒正常;息屏后防休眠断言保持、停止后正确释放。
  • Windows 关屏命令已完成静态验证(Base64 往返),最终确认需在真实 Windows 机器跑一次。

备注 / 后续

  • Linux 息屏依赖 xset;Wayland 用户可能需要 wlr-randr 等,暂不纳入本次范围。
  • 挂机模式开启后应用每次启动会自动恢复(启动同步)——为无人值守场景设计;任务防休眠默认开启,可在设置中关闭。
  • 后续可加:托盘菜单快捷开关 / 全局快捷键 / 任务运行中的状态提示。

Made with Proma · GitHub

魔仙堡 added 2 commits August 12, 2026 10:58
新增「挂机模式(息屏 + 防休眠)」:开启后立即熄灭显示器
(macOS pmset displaysleepnow / Windows SendMessage SC_MONITORPOWER /
Linux xset dpms force off),并通过 powerSaveBlocker
('prevent-app-suspension') 阻止系统休眠但允许息屏,适合挂机跑任务。
设置页新增开关,应用启动时同步、退出时自动释放。

Made-with: Proma
新增「任务防休眠」(默认开启):只要 Proma 有任务在跑(Agent run /
自动化任务 / 飞书桥接任务),通过 powerSaveBlocker
('prevent-app-suspension') 阻止系统休眠 —— 用户锁屏、息屏甚至合上
笔记本盖都不会中断任务;任务全部结束后自动恢复系统默认电源策略。

- task-sleep-guard.ts:token 集合跟踪活跃任务,纯逻辑可单测;
  设置关闭时立即释放,重新开启时若仍有任务在跑则恢复
- agent-service.ts:runAgent / runAgentHeadless 挂钩 onRunStarted
  begin / onComplete / onError / catch end,覆盖所有 run 入口
- 设置页新增开关(默认开启),与手动「挂机模式」相互独立
- macOS 合盖实测:任务运行期间合盖无睡眠事件,任务不中断

Made-with: Proma
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant