Skip to content

refactor(browser): rebuild browser tooling on official browser-use patterns - #209

Merged
Simpleyyt merged 3 commits into
mainfrom
cursor/browser-align-mainstream-af34
Aug 18, 2026
Merged

refactor(browser): rebuild browser tooling on official browser-use patterns#209
Simpleyyt merged 3 commits into
mainfrom
cursor/browser-align-mainstream-af34

Conversation

@Simpleyyt

@Simpleyyt Simpleyyt commented Aug 16, 2026

Copy link
Copy Markdown
Owner

背景

浏览器基础设施此前偏离主流做法:手写 CDP 鼠标事件、自定义 selector-map 格式化、针对单个网站的 icon-font hack(leaftools.net 计算器)、永远返回空的 window.console.logs 控制台读取,以及 Playwright 引擎每次 browser_view 都调用一次 LLM 做"页面抽取"。

改动

browser-use 引擎(默认):对照官方 Tools(browser_use/tools/service.py,0.13.7)重写

  • 动作走官方 event bus:NavigateToUrlEvent / ClickElementEvent / ClickCoordinateEvent / TypeTextEvent / ScrollEvent / SendKeysEvent / GetDropdownOptionsEvent / SelectDropdownOptionEvent / SwitchTabEvent,由库的 watchdog 处理等待、滚动到可见、<select> 校验与新标签页自动切换(与官方 _detect_new_tab_opened 一致)。
  • 状态用官方序列化:get_browser_state_summary() + dom_state.llm_representation()([index]<tag ... /> 树),并按官方 <browser_state> 消息格式补充 url/title/tabs/滚动位置与 [Start of page]/[End of page] 标记。
  • 正文抽取用官方 extract_clean_markdown(),纯函数、无 LLM 调用。
  • 控制台:通过 CDP Runtime.consoleAPICalled / Runtime.exceptionThrown 采集;browser_console_exec 改用 Runtime.evaluate,支持任意表达式并上报异常。
  • 删除站点特定 hack(_ICON_CLASS_SYMBOLS_get_node_hint)与自定义 _format_selector_map

Playwright 引擎:按主流模式(Playwright MCP 风格)重建并保留

  • 去掉每次 view 的 LLM 抽取调用,正文改用 markdownify 纯函数转换。
  • 可见交互元素快照输出与 browser-use 引擎相同的 1-based [index]<tag ... /> 行 + [Start of page]/[End of page] 标记 + 滚动位置,两个引擎载荷完全同构、可互换。
  • 控制台用 Playwright 原生 page.on("console"/"pageerror") 监听采集;console_exec 上报 JS 异常。
  • 点击开新标签自动切换;点 <select> 提示改用 browser_select_option,与 browser-use 引擎行为一致。
  • BROWSER_ENGINE 配置保留:browser_use(默认)/ playwright

其他

  • mockserver browser 场景改用 1-based 元素索引,并删掉过时的 update_plan 轮次(现在的 PlanActFlow 步骤成功后不再回访 Planner,这条会被 summarizer 收到并报 Unknown tool,导致场景提前中断)。

测试

真实 CDP 集成测试 — 两个引擎同一套 25 项检查全部通过(沙盒 Chrome,覆盖 navigate / view(元素树 + Markdown + 滚动位置)/ 按索引与坐标点击 / 输入 + Enter / 下拉选择 / 组合键 / 滚动 / 控制台采集与 JS 异常 / 截图 / 新标签自动切换 / <select> 提示 / restart):

engine: browser_use → 25 passed, 0 failed
engine: playwright  → 25 passed, 0 failed

[PASS] click by index | Clicked element [4]
[PASS] select_option | Selected option 2: Blue  → dropdown applied
[PASS] console_view captured logs | ["[log] page loaded", "[log] enter pressed with value: Manus Tester", ...]
[PASS] console_exec reports JS exceptions | ReferenceError: nonExistentFunction is not defined
[PASS] click link opening new tab | Automatically switched to new tab (.../second.html)
[PASS] clicking <select> advises browser_select_option

全栈 e2e(mockserver browser 场景):前端发起任务,11 个浏览器工具依次执行,Computer 面板显示 example.com 截图,最终输出 "Browser tool test finished.",无 UI 错误。

browser_tools_e2e_mock_scenario.mp4

后端 pytest(auth/file)与 main 基线结果完全一致(16 failed / 17 passed,均为预先存在的测试环境鉴权配置问题,与本改动无关)。

To show artifacts inline, enable in settings.

Open in Web Open in Cursor 

cursoragent and others added 3 commits August 16, 2026 15:28
…patterns

- Dispatch all actions through the browser-use event bus (ClickElementEvent,
  TypeTextEvent, ScrollEvent, SendKeysEvent, SelectDropdownOptionEvent,
  ClickCoordinateEvent, NavigateToUrlEvent, SwitchTabEvent) so library
  watchdogs handle waiting, scroll-into-view, new-tab switching and
  validation, instead of hand-rolled CDP calls
- Use the official DOM serializer (dom_state.llm_representation) for the
  element tree and extract_clean_markdown for page content (no LLM call)
- Report url/title/tabs/scroll position like the official <browser_state>
- Capture console output via CDP Runtime.consoleAPICalled/exceptionThrown
  (window.console.logs never existed); execute JS via Runtime.evaluate with
  real console semantics and exception reporting
- Drop site-specific icon-font hacks and the custom selector-map formatter
- Remove legacy PlaywrightBrowser engine (per-view LLM extraction), the
  BROWSER_ENGINE setting, and playwright/markdownify dependencies
- Fix mockserver browser scenario to use 1-based element indexes

Co-authored-by: Simpleyyt <simpleyyt@gmail.com>
PlanActFlow no longer round-trips to the Planner after a successful
complete_step, so the canned update_plan response was consumed by the
summarizer and surfaced as 'Unknown tool: update_plan', cutting the
scenario short before deliver_result.

Co-authored-by: Simpleyyt <simpleyyt@gmail.com>
…tterns

Restores BROWSER_ENGINE (browser_use default / playwright) with a rewritten
PlaywrightBrowser that emits the same tool payload shape as the browser-use
engine:

- Markdown content via markdownify (drops the per-view LLM extraction call)
- Visible interactive elements as 1-based [index]<tag ... /> lines with
  [Start of page]/[End of page] markers and scroll position in pages
- Console captured with native page.on('console'/'pageerror') listeners
  (window.console.logs never existed); console_exec surfaces JS exceptions
- New-tab auto-switch after clicks, and clicking a <select> advises
  browser_select_option, matching the browser-use engine behaviour

Co-authored-by: Simpleyyt <simpleyyt@gmail.com>
@Simpleyyt
Simpleyyt marked this pull request as ready for review August 18, 2026 17:18
@Simpleyyt
Simpleyyt merged commit 7c2a2ca into main Aug 18, 2026
4 checks passed
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