窗口都最小化了,风扇还在转:Hermes 桌面端停掉了后台窗口的空转

你按下“发送”,然后切到浏览器去查资料。Hermes 的窗口留在后台,回合一字一字地在流式输出。二十分钟后你把电脑合上、拔掉电源出门,回来发现电量掉得比预期多,风扇还转了一阵。
后台窗口不该这样工作。它没有人在看,却在以和前台一样的速度绘制每一个字符。
旧的行为:一个对话在流,所有窗口都醒着
原来的实现里,“某个对话正在流式输出”这个状态会让桌面端每个窗口都保持完全唤醒:绘制循环照常跑,预览页也为了“随时能自动化和截图标注”而保持唤醒。
单窗口时这不算问题。多窗口、长时间任务、笔记本电池的场景里,它就是一个持续的背景功耗。
预览页那一半更隐蔽:即使页面完全空闲,它也不会进入 Chromium 的后台节流状态,因为标注和自动化随时可能要用它。
现在:绘制跟着可见性走
改动之后,流式绘制的范围被收窄到两类窗口:可见的窗口,以及自己正在跑语音对话的那个窗口(即使它不可见,语音需要它活着)。其余窗口和最小化的窗口被允许节流。
需要注意的是,“打开朗读回复”这个选项不再给所有窗口发免死金牌:它曾经意味着每个窗口都得醒着才能念出内容,现在最小化的窗口保持节流,但完成进度和最终回复依然会念一次。
与此同时,几件不该依赖“有没有在画”的事情被解耦了:流式投递、停止按钮、回合日志、崩溃后的恢复,全部不再以动画帧为前提。恢复一个窗口时它显示的是最新状态,而不是把积压的每一帧重放一遍。
部分文本的更新会被合并;完成的进度和最终回复则不等下一帧,立刻发布——这就是隐藏窗口也能朗读、而且只念一次的原因。两个窗口同时有回复时,它们共享同一个待处理回合的所有权,不会丢叙述,也不会念两遍。
预览页:空闲就交还给浏览器
第二个改动针对内置预览:页面空闲时允许使用 Chromium 自带的后台节流,而不是一直自持唤醒。
只有真的有活要干时才唤醒页面和它所属的窗口,而且“唤醒”是按操作持有的:多个操作重叠时各自持有自己的那份,先完成的那一个不能把另一个挂起。导航之后会重新申请唤醒,即使当时已经有一个操作还没派发新脚本。
几处容易出错的边界也补上了:
- 被导航抛弃的工作会被取消,但脚本返回值、插件授权、可信输入、沙箱和 CSP 都保持不变。
- 标注绘制和图片捕获共用一个可取消的八秒上限;等待用户放下一个标注时,不持有任何唤醒。
- 标注的安装与拆除按会话加栅栏,取消之后不会留下一个看不见的点击拦截面,也不会把替换上去的浮层拆掉。
- 插件脚本的完成语义不变:它持有唤醒直到结算或被取消,哪怕返回的是一个永远不结算的 Promise。插件脚本和长输入动作不继承上面那个八秒上限。
没有新增依赖、权限或 CSP 变更,也没有对对话记录和滚动历史做任何截断。
你可以自己验证
官方的验收路径是这样设计的:
- 把同一个对话在两个窗口打开,其中一个最小化,然后流式输出一段长回复。在可见窗口里输入点什么,再恢复另一个窗口——两边都应该是完整回复。
- 从可见窗口点停止,确认被取消的输出不会在恢复窗口时继续出现。
- 两个窗口都打开“朗读回复”:最小化的那个保持节流,但完成进度和最终回复仍然只念一次。
- 只在其中一个窗口开语音对话:另一个窗口的流式输出不应打断它的录音或播放。
- 流式输出中途刷新页面:恢复后应该保留最新文本,包括提供方停止发送之后那段安静的尾巴。
什么时候你会真的感觉到
三种场景最明显:笔记本只看不动的长时间任务、习惯把同一对话开两三个窗口对照的人、以及用内置预览页查资料并顺手做标注的人。
它不会让你的模型更快,也不会让回复更短。它只是让“没人看的窗口”真正闲下来。
现在能用吗
这两批改动 11 月 4 日合并进 main,晚于 v0.22.7 的发布点,写这篇时还没进正式版本——v0.22.7 那篇里有这次发布的完整范围。桌面端的打字延迟问题另有一篇专门的分析;如果你更关心“有事怎么找到我”,那部分是通知与提醒指南。