Skip to content

feat(vom): discover canvas visual surfaces in observations | 在 observation 中发现 canvas 可视区域 - #138

Draft
Ljy-0827 wants to merge 4 commits into
mainfrom
fix/vom-canvas-observation
Draft

feat(vom): discover canvas visual surfaces in observations | 在 observation 中发现 canvas 可视区域#138
Ljy-0827 wants to merge 4 commits into
mainfrom
fix/vom-canvas-observation

Conversation

@Ljy-0827

@Ljy-0827 Ljy-0827 commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

问题

当前 VOM 对于 Canvas 渲染的表格、白板、图表等内容,页面虽然视觉上存在大块有效信息,但语义树中通常没有对应内容。对于 Canvas,目前浏览器提供的结构信息通常只能描述 Canvas 元素本身,无法表示其中实际渲染的可视内容。

这会导致:

  • Agent 无法从 Observation 中判断页面存在需要视觉理解的 Canvas 区域。
  • Canvas 与页面中的普通 DOM/AX 内容之间缺少明确边界。
  • Agent 不知道应该对哪个区域截图。
  • 不具备多模态或读图能力的模型,可能继续猜测 Canvas 内容或目标坐标。
  • Canvas 位于 iframe、嵌套 frame 或不同进程 frame 时,其可视区域更难被稳定发现和定位。

解决方案

observe 链路中增加 Canvas Rendered Surface discovery:

  • 发现当前视口内有效且可见的 Canvas 渲染区域。
  • 过滤隐藏、零尺寸、完全离开视口或被完全裁剪的 Canvas。
  • 支持主页面、same-origin iframe、嵌套 frame 和 OOPIF 中的 Canvas,并将区域投影到顶层视口坐标。
  • 对重叠且属于同一视觉区域的 Canvas 进行合并,同时避免错误合并独立的 Canvas。
  • 在 VOM Observation 中将这些区域输出为带有 @eN ref 的 visual-only Surface:
    @eN surface "..." [visual-only; requires=image-understanding; ...]
    
  • Surface ref 只允许用于区域截图:
    bsk screenshot --ref @eN --session <id>
  • Surface ref 不作为普通 DOM 交互目标;click、fill、hover 和 select 会拒绝 screenshot-only ref。
  • 支持图片输入的模型可以接收裁剪后的 Canvas 图片并进行视觉理解。
  • 不具备多模态或读图能力的模型会被明确要求:不得假装理解 Canvas 内容;不得猜测目标坐标;告知用户需要切换到支持图像理解的模型。

这个 PR 解决的是 Canvas 区域“不可感知、无观察入口”的问题;Canvas 内部的结构化理解和交互能力不在本 PR 范围内。

测试

通过浏览器能力测试语料库测试。

@Ljy-0827 Ljy-0827 self-assigned this Aug 25, 2026
@Ljy-0827
Ljy-0827 force-pushed the fix/vom-canvas-observation branch from eeba301 to e141f27 Compare August 26, 2026 07:28
Base automatically changed from feat/vom-functional-refactor to main August 28, 2026 03:24
@iuyo5678
iuyo5678 force-pushed the fix/vom-canvas-observation branch from e141f27 to 73ad0ac Compare August 28, 2026 03:24
@Ljy-0827
Ljy-0827 force-pushed the fix/vom-canvas-observation branch 5 times, most recently from 39ada87 to d660da8 Compare August 31, 2026 06:03
@Ljy-0827 Ljy-0827 changed the title feat(vom): make canvas-rendered content observable | 支持在 observe 中发现并截图 canvas 视觉区域 feat(vom): discover canvas visual surfaces in observations | 在 observation 中发现 canvas 可视区域 Aug 31, 2026
@Ljy-0827
Ljy-0827 marked this pull request as ready for review August 31, 2026 06:18
@Ljy-0827
Ljy-0827 requested review from iuyo5678 and shnpd August 31, 2026 06:43
@iuyo5678

iuyo5678 commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

先说结论:现在问题不是"漏了过滤",而是 keeps tiny canvases as individually addressable exact discoveries 这个设计目标,和 observation 的注意力预算之间的冲突。
在图标 canvas、地图 tile、表格内嵌 sparkline 这类页面上,当前策略会产出几十个 surface。具体后果有三个,按严重程度排序:

1. surface 行会硬截断整个 observation

emitVisualEntries 里:

const nextTokens = state.tokens + estimateTokens(line);
if (nextTokens > state.maxTokens) {
  state.truncated = true;
  state.stopped = true;
  return;
}

state.stopped = true 会终止整棵树的后续渲染。也就是说 canvas 密集页面上,一批无意义的 surface 行有可能把后面真正的 DOM 内容整段挤出 observation。这个后果比"多花一些 token"严重得多。

2. 无 label 的 surface 之间对 Agent 完全不可区分

const label = cleaned(surface.label) ?? `${surface.renderingKind} visual surface`;

没有 aria-label/title 时统一 fallback 成 "canvas visual surface"。30 个地图 tile 会渲染成 30 行完全相同的 @eN surface "canvas visual surface" [...; use: bsk screenshot --ref @eN],Agent 除了 ref 编号之外没有任何依据判断该截哪一个 —— 这等于往上下文里塞了 30 个无法排序的等价选项。

3. 后续 DOM ref 编号整体偏移

emitVisualEntries 每输出一个 surface 就 state.nextRef += 1,且是在 DFS 中间插入的,所以 surface 出现在哪,后面所有 @eN 就往后移多少。
另外,地图 tile 这类场景当前不会被 cluster 合并:sameVisualStack 要求 IoU ≥ 0.9,而 tile 是相邻而非重叠,IoU ≈ 0,所以每个 tile 各成一组。同理,一个表格里 20 个 sparkline 图表就是 20 个 surface。

测试:建议增加如下的情况测试,。

  • same-origin iframe 内的 canvas,经过 iframe 偏移投影后 visibleRect 是否正确
  • OOPIF 场景下 frameId 与 CDP session 路由是否正确
  • canvas 被 overflow:hidden 容器裁掉一半时,screenshot --ref 产出的 PNG 是否等于裁剪后区域,而不是整块 canvas
  • 同一页面分别在 dpr=1 和 dpr=2 下运行,CSS 空间的结果是否一致

最后一条测试对 #143 很重要,坐标换算完全依赖"PNG 像素尺寸 ÷ CSS 矩形"这个比值自洽,一旦 parsePngDimensions 回退到 Math.round(rect.width),映射就会整体偏移,而这在 mock 测试里暴露不出来。

@Ljy-0827
Ljy-0827 force-pushed the fix/vom-canvas-observation branch from d660da8 to 22bffeb Compare September 2, 2026 03:20
@Ljy-0827
Ljy-0827 marked this pull request as draft September 2, 2026 03:20
@Ljy-0827
Ljy-0827 force-pushed the fix/vom-canvas-observation branch from 22bffeb to 28892ea Compare September 2, 2026 09:28
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.

2 participants