Skip to content

fix: stabilize tab IDs to prevent index drift when tabs are closed externally#1230

Open
yangyaofei wants to merge 1 commit intovercel-labs:mainfrom
yangyaofei:feat/lazy-attach
Open

fix: stabilize tab IDs to prevent index drift when tabs are closed externally#1230
yangyaofei wants to merge 1 commit intovercel-labs:mainfrom
yangyaofei:feat/lazy-attach

Conversation

@yangyaofei
Copy link
Copy Markdown

Summary

Stabilize tab identifiers when connecting to an existing browser via CDP (--cdp). Currently tab list, tab switch, and tab close use volatile array indices that shift when tabs are opened or closed by the user (or any external actor), causing the agent to operate on the wrong tab.

Example

Before (unstable): 1 2 3 4 5 → close tab 3 → 1 2 3 4 (all indices after 3 shift)

After (stable): 1 2 3 4 5 → close tab 3 → 1 2 4 5 → new tab → 1 2 4 5 6

Problem

When agent-browser connects to a user's Chrome via CDP, it discovers all open tabs and stores them in a Vec<PageInfo>. The tab index exposed to the agent is simply the array position (enumerate). If the user closes or opens tabs in the browser while the agent is working, the array shifts and all subsequent tab_switch/tab_close calls target the wrong tab.

This is especially critical for the CDP use case where the agent shares the browser with a human user.

Solution

Introduce a monotonically increasing, never-reused tab ID mapping (tab_ids: HashMap<String, usize>) keyed by CDP target_id. Each tab is assigned an ID on first discovery, and that ID persists until the tab is destroyed. Deleted IDs are never recycled.

  • tab_list returns stable IDs instead of array indices
  • tab_switch/tab_close resolve the stable ID back to the internal array position via the mapping
  • CLI output (output.rs) reads the index field from the daemon response instead of using its own enumerate

Files Changed

  • cli/src/native/browser.rsBrowserManager gains tab_ids + next_tab_id; all tab operations use stable IDs
  • cli/src/output.rs — Tab display reads index from daemon response instead of local enumerate

## 问题/错误
当用户在浏览器中手动关闭或新建 tab 时,agent-browser 内部的 tab index(数组下标)会整体变化。
这导致 AI agent 使用旧的 index 操作时,会操作到错误的 tab 页面。

## 发现过程
- tab_list 返回的 index 是 pages 数组的 enumerate 下标
- 用户关闭 tab 后 pages.remove(pos) 导致后续所有 tab 的 index 前移
- 例如:关闭 tab[3] 后,原来的 tab[4] 变成 tab[3],agent 用旧 index 4 会操作到错误页面

## 实现方案
引入稳定的 tab_id 映射机制:
- BrowserManager 新增 tab_ids (HashMap<String, usize>) 和 next_tab_id (usize)
- 每个 tab 在创建时分配一个只增不减的 ID(1-based)
- tab_list 返回的 index 改为 tab_id
- tab_switch/tab_close 改为通过 tab_id 查找 target_id 再定位数组下标
- output.rs 的 tab 显示改为使用 daemon 返回的 index 字段而非本地 enumerate

## 实现过程
- browser.rs: 新增 tab_ids/next_tab_id 字段,修改所有 BrowserManager 构造点
- browser.rs: add_page/remove_page_by_target_id 维护 tab_id 映射
- browser.rs: tab_list 用 tab_id 替代 enumerate index
- browser.rs: tab_new 返回 tab_id,tab_switch/tab_close 接受 tab_id
- browser.rs: 新增 resolve_tab_index/active_tab_id 辅助方法
- output.rs: tab 显示使用 daemon 返回的 index 字段

## 总结
tab ID 只增不复用,关闭 tab 后其他 tab 的 ID 保持不变,新建 tab 获取新 ID。
例如:1 2 3 4 5 6 关闭 3 后新建 → 1 2 4 5 6 7
@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Apr 13, 2026

@yangyaofei is attempting to deploy a commit to the Vercel Labs Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Copy Markdown
Contributor

@vercel vercel bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Suggestion:

The e2e_tabs test uses 0-based array indices for tab operations, but the tab system was changed to use 1-based stable IDs, causing three assertion/runtime failures.

Fix on Vercel

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