browser pane 断连:长驻 SSE 页面期间 pane consumer 心跳丢失,agent 侧 browser_open/navigate 连续失败(desktop 0.28.0) #8

Closed
opened 2026-10-14 17:50:28 +08:00 by fourbroad · 3 comments
Owner

环境

  • Octopus Beta 桌面端 0.28.0(Windows 10/11,x64)
  • 会话内 browser pane 长驻一个带 SSE 长连接(EventSource)的本地页面(http://127.0.0.1:8765/,FastAPI uvicorn 服务)
  • 会话已持续较长时间,期间多次 snapshot/evaluate/console_messages 均正常

断连时间线(同一会话内连续发生)

  1. browser_take_screenshot 失败:"guest webview is gone or invalid"——consumer 在线但 guest webview 无法执行操作(提示 page-spawned new tab / renderer wedge / pane closing 都可能)
  2. 紧接 browser_open 同 URL 成功(输出还提示 "the pane's guest webview was unavailable before this open. The open re-bound the session")——重新绑定后一切正常
  3. 约数分钟后(期间无浏览器操作,页面 SSE 持续推送):browser_navigate 失败:"no pane consumer acknowledged the request within the surface window (10s)",surface 翻转为 pane-offline
  4. 随后 browser_open 失败:"No connected client can show a browser pane for this session"(提示 presence heartbeat may have lapsed transiently)
  5. 此期间 browser_capabilities 仍报告 surface=desktop-panel、pane-bound(会话状态与实际可达性不一致)
  6. 数分钟后自愈:未做任何干预,browser_open 重新加载成功

观察到的矛盾点

  • 步骤 5:capabilities/会话绑定状态认为 pane 在线,但所有 pane 操作无 consumer 应答——绑定状态与 presence 心跳似乎不是同一真相源
  • 断连发生时桌面端并非被用户关闭(Locator/进程仍在,且最终自愈)

假设(未证实,供排查)

  • pane 内页面持有 SSE 长连接;当 pane tab 被切到后台/桌面最小化时,Electron 的 backgroundThrottling 可能冻结 renderer 定时器 → guest→sidecar 的 presence/heartbeat 级心跳停发 → 服务端判定 consumer 离线;恢复前台/解除节流后心跳恢复即"自愈"
  • 若成立,希望 heartbeat 走不受 renderer 节流影响的通道(main process 定时器/独立 worker),或将 SSE 等长连接页面排除出节流(backgroundThrottling: false 或 webPreferences 调整)

影响

  • agent 侧连续 2-3 次 pane 操作失败,只能等自愈或让用户手动切前台;期间错误指引(retry once / newTab / pane_release)都无法立即恢复

复现建议

桌面端开一个带 new EventSource('/api/events') 长连接的页面驻留 pane,切走 tab 或最小化窗口数分钟,观察 agent 会话的 pane 操作与 presence 状态。

—— 来自 ai-quant 项目会话的实测记录(2026-10-14),可提供会话日志细节。

## 环境 - Octopus Beta 桌面端 **0.28.0**(Windows 10/11,x64) - 会话内 browser pane 长驻一个**带 SSE 长连接(EventSource)的本地页面**(http://127.0.0.1:8765/,FastAPI uvicorn 服务) - 会话已持续较长时间,期间多次 snapshot/evaluate/console_messages 均正常 ## 断连时间线(同一会话内连续发生) 1. `browser_take_screenshot` 失败:**"guest webview is gone or invalid"**——consumer 在线但 guest webview 无法执行操作(提示 page-spawned new tab / renderer wedge / pane closing 都可能) 2. 紧接 `browser_open` 同 URL **成功**(输出还提示 "the pane's guest webview was unavailable before this open. The open re-bound the session")——重新绑定后一切正常 3. 约数分钟后(期间无浏览器操作,页面 SSE 持续推送):`browser_navigate` 失败:**"no pane consumer acknowledged the request within the surface window (10s)"**,surface 翻转为 pane-offline 4. 随后 `browser_open` 失败:**"No connected client can show a browser pane for this session"**(提示 presence heartbeat may have lapsed transiently) 5. 此期间 `browser_capabilities` 仍报告 surface=desktop-panel、pane-bound(会话状态与实际可达性不一致) 6. **数分钟后自愈**:未做任何干预,`browser_open` 重新加载成功 ## 观察到的矛盾点 - 步骤 5:capabilities/会话绑定状态认为 pane 在线,但所有 pane 操作无 consumer 应答——**绑定状态与 presence 心跳似乎不是同一真相源** - 断连发生时桌面端并非被用户关闭(Locator/进程仍在,且最终自愈) ## 假设(未证实,供排查) - pane 内页面持有 SSE 长连接;当 pane tab 被切到后台/桌面最小化时,Electron 的 backgroundThrottling 可能冻结 renderer 定时器 → guest→sidecar 的 presence/heartbeat 级心跳停发 → 服务端判定 consumer 离线;恢复前台/解除节流后心跳恢复即"自愈" - 若成立,希望 heartbeat 走不受 renderer 节流影响的通道(main process 定时器/独立 worker),或将 SSE 等长连接页面排除出节流(`backgroundThrottling: false` 或 webPreferences 调整) ## 影响 - agent 侧连续 2-3 次 pane 操作失败,只能等自愈或让用户手动切前台;期间错误指引(retry once / newTab / pane_release)都无法立即恢复 ## 复现建议 桌面端开一个带 `new EventSource('/api/events')` 长连接的页面驻留 pane,切走 tab 或最小化窗口数分钟,观察 agent 会话的 pane 操作与 presence 状态。 —— 来自 ai-quant 项目会话的实测记录(2026-10-14),可提供会话日志细节。
fourbroad self-assigned this 2026-10-14 20:47:18 +08:00
Author
Owner

claim — session ses_ec594d15bfferekxLpsDFSua1A · branch workflow/session/pane-sse-heartbeat-8 · account fourbroad (atomic claim via script/claim.sh, #3327)

**claim** — session `ses_ec594d15bfferekxLpsDFSua1A` · branch `workflow/session/pane-sse-heartbeat-8` · account `fourbroad` (atomic claim via script/claim.sh, #3327)
Author
Owner

RCA + 修复 PR

根因链(与工单假设方向一致,已代码证实):

pane consumer 的全部出站通道(presence ping POST 与 SSE 驱动的 engage/settle POST)都在 session 页面 renderer 内执行。长驻 SSE 页面 + 窗口后台/最小化 → Chromium intensive throttling 把 30s 链式定时器拉到 ~1/min,烧穿 60s presence TTL:

  1. #5338 的 25s 主进程 nudge 无法兑现——nudge 的 IPC 处理器仍在被节流的 renderer 里执行 POST
  2. presence 死亡 → browser_open D-3 降级 + 宽限耗尽 → no-browser-surface(0.28.0 仍带 8s 宽限;#5733 的 45s 修复 PR 一直未合并)
  3. SSE 事件处理延迟 → 10s surface window 耗尽 → pane-offline(工单时间线 3)
  4. guest webview 失效后 open 重绑(时间线 1-2)、数分钟后自愈(时间线 6)均为同一节流的伴随现象
  5. 矛盾点 5 证实:pane binding(无 TTL)与 presence liveness 本就是两个真相源,capabilities 只读前者

修复(主仓 PR Octopus/octopus#6042,分支 workflow/session/pane-sse-heartbeat-8):

  • 主进程直发 presence ping(25s 主定时器 net.fetch + Basic 凭据,renderer 节流免疫)+ presence:declare 声明通道
  • 主窗口 backgroundThrottling: false(工单建议的直接落地——SSE 页面驻留不再冻结 renderer 定时器)
  • 宽限窗 8s→45s(承接未合并的 #5733)
  • capabilities face 行叠加 presence liveness,binding 活/心跳死时如实披露 presence-offline

测试红先行→全绿(direct-ping 8 + declare-ipc 9 + sv 4 + app 6 + capabilities 7 + grace 6 + 周边回归),三包 lint/typecheck 通过。PR 合并后本工单可关闭。

## RCA + 修复 PR **根因链**(与工单假设方向一致,已代码证实): pane consumer 的全部出站通道(presence ping POST 与 SSE 驱动的 engage/settle POST)都在 session 页面 renderer 内执行。长驻 SSE 页面 + 窗口后台/最小化 → Chromium intensive throttling 把 30s 链式定时器拉到 ~1/min,烧穿 60s presence TTL: 1. #5338 的 25s 主进程 nudge 无法兑现——nudge 的 IPC 处理器仍在被节流的 renderer 里执行 POST 2. presence 死亡 → browser_open D-3 降级 + 宽限耗尽 → `no-browser-surface`(0.28.0 仍带 8s 宽限;#5733 的 45s 修复 PR 一直未合并) 3. SSE 事件处理延迟 → 10s surface window 耗尽 → `pane-offline`(工单时间线 3) 4. guest webview 失效后 open 重绑(时间线 1-2)、数分钟后自愈(时间线 6)均为同一节流的伴随现象 5. 矛盾点 5 证实:pane binding(无 TTL)与 presence liveness 本就是两个真相源,capabilities 只读前者 **修复**(主仓 PR Octopus/octopus#6042,分支 `workflow/session/pane-sse-heartbeat-8`): - 主进程直发 presence ping(25s 主定时器 net.fetch + Basic 凭据,renderer 节流免疫)+ `presence:declare` 声明通道 - 主窗口 `backgroundThrottling: false`(工单建议的直接落地——SSE 页面驻留不再冻结 renderer 定时器) - 宽限窗 8s→45s(承接未合并的 #5733) - capabilities face 行叠加 presence liveness,binding 活/心跳死时如实披露 presence-offline 测试红先行→全绿(direct-ping 8 + declare-ipc 9 + sv 4 + app 6 + capabilities 7 + grace 6 + 周边回归),三包 lint/typecheck 通过。PR 合并后本工单可关闭。
Author
Owner

verify 收敛:PASS(管线全部完成)

修复 PR Octopus/octopus#6042 已走完 implement → review-code(round 1 收敛 PASS:0 BLOCKER,10 项 FIX 已落地)→ verify(iteration 1 PASS)。报告:主仓 .octopus/runs/pane-sse-heartbeat-8/05-verify-iteration-1.md。

  • DoD D1-D5 全绿(主进程直发 ping / 节流免疫 / 宽限 45s / capabilities liveness 叠加 / 零回归),D6 standing-cost 不可自动验证(带复活触发器)
  • 全量套件:desktop 636/636、app 6709 ran 0 fail、octopus test:parallel 3306 pass(44 失败全部归因 baseline/环境——与 main 逐一比对相同,零 diff 交集)

待 PR #6042 合并后(人工通道 script/pr-merge.sh 6042)即可关闭本工单。

## verify 收敛:**PASS**(管线全部完成) 修复 PR Octopus/octopus#6042 已走完 implement → review-code(round 1 收敛 PASS:0 BLOCKER,10 项 FIX 已落地)→ verify(iteration 1 PASS)。报告:主仓 `.octopus/runs/pane-sse-heartbeat-8/05-verify-iteration-1.md`。 - DoD D1-D5 全绿(主进程直发 ping / 节流免疫 / 宽限 45s / capabilities liveness 叠加 / 零回归),D6 standing-cost 不可自动验证(带复活触发器) - 全量套件:desktop 636/636、app 6709 ran 0 fail、octopus test:parallel 3306 pass(44 失败全部归因 baseline/环境——与 main 逐一比对相同,零 diff 交集) 待 PR #6042 合并后(人工通道 `script/pr-merge.sh 6042`)即可关闭本工单。
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Octopus/octopus-release#8