Consistent Tab IDs & Global Tag Targeting#892
Merged
ctate merged 7 commits intovercel-labs:mainfrom Apr 16, 2026
Merged
Conversation
Contributor
|
@DJRHails is attempting to deploy a commit to the Vercel Labs Team on Vercel. A member of the Team first needs to authorize it. |
Contributor
Author
ad6eaca to
654c33c
Compare
patch-stack-bot Bot
pushed a commit
to DJRHails/agent-browser
that referenced
this pull request
Mar 17, 2026
Patch-Stack-Branch: patch/tab-targeting Upstream PR: vercel-labs#892
9d2cff6 to
ceb7451
Compare
ceb7451 to
29b2ee1
Compare
patch-stack-bot Bot
added a commit
to DJRHails/agent-browser
that referenced
this pull request
Mar 18, 2026
Patch-Stack-Branch: patch/tab-targeting Upstream PR: vercel-labs#892
Contributor
29b2ee1 to
ceb7451
Compare
ceb7451 to
656ff18
Compare
patch-stack-bot Bot
added a commit
to DJRHails/agent-browser
that referenced
this pull request
Mar 18, 2026
Patch-Stack-Branch: patch/tab-targeting Upstream PR: vercel-labs#892
656ff18 to
b251966
Compare
patch-stack-bot Bot
added a commit
to DJRHails/agent-browser
that referenced
this pull request
Mar 19, 2026
Patch-Stack-Branch: patch/tab-targeting Upstream PR: vercel-labs#892
b251966 to
a10a668
Compare
patch-stack-bot Bot
added a commit
to DJRHails/agent-browser
that referenced
this pull request
Mar 20, 2026
Patch-Stack-Branch: patch/tab-targeting Upstream PR: vercel-labs#892
915231e to
e909a8e
Compare
patch-stack-bot Bot
added a commit
to DJRHails/agent-browser
that referenced
this pull request
Mar 22, 2026
Patch-Stack-Branch: patch/tab-targeting Upstream PR: vercel-labs#892
Contributor
e909a8e to
58b773d
Compare
patch-stack-bot Bot
added a commit
to DJRHails/agent-browser
that referenced
this pull request
Mar 23, 2026
Patch-Stack-Branch: patch/tab-targeting Upstream PR: vercel-labs#892
58b773d to
a2e3e67
Compare
patch-stack-bot Bot
pushed a commit
to DJRHails/agent-browser
that referenced
this pull request
Mar 24, 2026
Patch-Stack-Branch: patch/tab-targeting Upstream PR: vercel-labs#892
a2e3e67 to
f8e67fd
Compare
patch-stack-bot Bot
added a commit
to DJRHails/agent-browser
that referenced
this pull request
Mar 25, 2026
Patch-Stack-Branch: patch/tab-targeting Upstream PR: vercel-labs#892
f8e67fd to
76f1192
Compare
patch-stack-bot Bot
pushed a commit
to DJRHails/agent-browser
that referenced
this pull request
Mar 26, 2026
Patch-Stack-Branch: patch/tab-targeting Upstream PR: vercel-labs#892
00c2a67 to
c2247ec
Compare
patch-stack-bot Bot
added a commit
to DJRHails/agent-browser
that referenced
this pull request
Apr 10, 2026
Patch-Stack-Branch: patch/tab-targeting Upstream PR: vercel-labs#892
patch-stack-bot Bot
added a commit
to DJRHails/agent-browser
that referenced
this pull request
Apr 11, 2026
Patch-Stack-Branch: patch/tab-targeting Upstream PR: vercel-labs#892
patch-stack-bot Bot
added a commit
to DJRHails/agent-browser
that referenced
this pull request
Apr 12, 2026
Patch-Stack-Branch: patch/tab-targeting Upstream PR: vercel-labs#892
c2247ec to
6ad989f
Compare
patch-stack-bot Bot
added a commit
to DJRHails/agent-browser
that referenced
this pull request
Apr 13, 2026
Patch-Stack-Branch: patch/tab-targeting Upstream PR: vercel-labs#892
6ad989f to
eec479d
Compare
patch-stack-bot Bot
pushed a commit
to DJRHails/agent-browser
that referenced
this pull request
Apr 14, 2026
Patch-Stack-Branch: patch/tab-targeting Upstream PR: vercel-labs#892
patch-stack-bot Bot
added a commit
to DJRHails/agent-browser
that referenced
this pull request
Apr 15, 2026
Patch-Stack-Branch: patch/tab-targeting Upstream PR: vercel-labs#892
Replace positional indices with stable integer tab IDs throughout the browser tab management system. Tab IDs are monotonically increasing (starting at 1) and persist across tab open/close operations, making them reliable identifiers for AI agents. Changes: - browser.rs: Add tab_id field to PageInfo, next_tab_id counter to BrowserManager, tab_switch_by_id/tab_close_by_id methods - actions.rs: Read tabId instead of index for tab_switch/tab_close, assign tab IDs in window_new and target-created event handlers - commands.rs: Emit tabId instead of index in tab switch/close commands - flags.rs: Add --tab <id> flag to Config and Flags structs - main.rs: Inject tabId from --tab flag into commands - output.rs: Display tab IDs in list/new/close output, add --tab to all command help Global Options sections
Add pre-dispatch tab switch in execute_command so any command with a tabId field (injected by --tab CLI flag) runs against the specified tab. Previously only tab_switch and tab_close honoured tabId. Add e2e tests for tab ID non-reuse after close and global targeting.
`tab select 3` and other unknown subcommands silently fell through to `tab_list`, making it appear the tab switch succeeded when it didn't. Now errors with valid subcommand suggestions, matching the pattern used by `window` and other commands. Bare `tab` (no args) still defaults to `tab_list`.
Tests snapshot returns correct content when targeting a specific tab via tabId, including non-contiguous tab IDs after closing a tab.
The condition `data.get("tabId").is_some()` matched any response
containing tabId, including tab_switch. Now only checks for
`data.get("closed").is_some()` and adds a dedicated tab_switch
output handler showing "Switched to tab [id] (url)".
eec479d to
d504478
Compare
patch-stack-bot Bot
added a commit
to DJRHails/agent-browser
that referenced
this pull request
Apr 16, 2026
Patch-Stack-Branch: patch/tab-targeting Upstream PR: vercel-labs#892
ctate
added a commit
that referenced
this pull request
Apr 16, 2026
PR #892 added a required `tab_id: u32` field to `PageInfo` but missed two initializer sites, which broke the build on the PR branch. CI never caught this because the external-contributor workflow status was `action_required` and never ran. - `cli/src/native/browser.rs:395` — the `direct_page` branch of `connect_cdp_inner` used by the cloud providers (Browserbase, Browserless, Browser Use, Kernel, AgentCore). Use `assign_tab_id()` to get a fresh id. - `cli/src/native/browser.rs:1580` — a unit test initializer. Use `tab_id: 1` since the test doesn't exercise id assignment.
ctate
added a commit
that referenced
this pull request
Apr 16, 2026
Follow-up on PR #892's `--tab <id>` flag. The original implementation called `tab_switch_by_id` directly from the pre-dispatch block in `execute_command` but didn't touch the daemon's per-tab state, and never restored the previously-active tab. Two concrete issues this fixes: 1. `state.ref_map`, `state.iframe_sessions`, and `state.active_frame_id` were left intact across the pre-dispatch switch, so `--tab N click @e1` would try to resolve `@e1` against the scoped tab's DOM using a backend-node id from the outer tab. In practice the click handler's role+name fallback hid this as "element not found" errors, but on pages where both tabs have similarly-labelled elements it could click the wrong one. 2. The PR description promised scoped routing would "restore the previous active tab", but the implementation permanently switched. `--tab 3 snapshot` would leave tab 3 as the active tab even after the command returned, surprising subsequent non-scoped commands. This change: - Saves the current tab's stable `tab_id` (not its array index, which would shift if the scoped command closed other tabs) before switching. - Clears per-tab daemon state before the switch so refs/iframes/frame context can't leak between tabs. - After the action runs, restores the original active tab (also via stable id) unless that tab was closed during the scoped command, in which case we leave the scoped tab active. - Adds `BrowserManager::active_tab_id()` and `has_tab_id()` accessors to support the above without exposing the internal `pages` vector.
ctate
added a commit
that referenced
this pull request
Apr 16, 2026
Per AGENTS.md, changes that users or agents would need to know about must land in every doc surface. Fills the gaps PR #892 left: - `README.md` — new `--tab <id>` row in the Options table, rewrite the tab command examples to use `<id>` instead of `<n>`, add a paragraph explaining stable tab IDs and `--tab` peek semantics. - `docs/src/app/commands/page.mdx` — same command-example rewrite plus a new "Stable tab IDs and `--tab`" subsection. - `docs/src/app/configuration/page.mdx` — add `tab` row to the config options table so JSON config users can discover it. - `agent-browser.schema.json` — add `tab` property with description, matching the config schema. - `skills/agent-browser/references/commands.md` — same command-example rewrite plus a short paragraph for agents on when to use `--tab`.
Collaborator
|
Thanks @DJRHails - this is a solid implementation |
ctate
added a commit
that referenced
this pull request
Apr 16, 2026
PR #892 added a required `tab_id: u32` field to `PageInfo` but missed two initializer sites, which broke the build on the PR branch. CI never caught this because the external-contributor workflow status was `action_required` and never ran. - `cli/src/native/browser.rs:395` — the `direct_page` branch of `connect_cdp_inner` used by the cloud providers (Browserbase, Browserless, Browser Use, Kernel, AgentCore). Use `assign_tab_id()` to get a fresh id. - `cli/src/native/browser.rs:1580` — a unit test initializer. Use `tab_id: 1` since the test doesn't exercise id assignment.
ctate
added a commit
that referenced
this pull request
Apr 16, 2026
Follow-up on PR #892's `--tab <id>` flag. The original implementation called `tab_switch_by_id` directly from the pre-dispatch block in `execute_command` but didn't touch the daemon's per-tab state, and never restored the previously-active tab. Two concrete issues this fixes: 1. `state.ref_map`, `state.iframe_sessions`, and `state.active_frame_id` were left intact across the pre-dispatch switch, so `--tab N click @e1` would try to resolve `@e1` against the scoped tab's DOM using a backend-node id from the outer tab. In practice the click handler's role+name fallback hid this as "element not found" errors, but on pages where both tabs have similarly-labelled elements it could click the wrong one. 2. The PR description promised scoped routing would "restore the previous active tab", but the implementation permanently switched. `--tab 3 snapshot` would leave tab 3 as the active tab even after the command returned, surprising subsequent non-scoped commands. This change: - Saves the current tab's stable `tab_id` (not its array index, which would shift if the scoped command closed other tabs) before switching. - Clears per-tab daemon state before the switch so refs/iframes/frame context can't leak between tabs. - After the action runs, restores the original active tab (also via stable id) unless that tab was closed during the scoped command, in which case we leave the scoped tab active. - Adds `BrowserManager::active_tab_id()` and `has_tab_id()` accessors to support the above without exposing the internal `pages` vector.
ctate
added a commit
that referenced
this pull request
Apr 16, 2026
Per AGENTS.md, changes that users or agents would need to know about must land in every doc surface. Fills the gaps PR #892 left: - `README.md` — new `--tab <id>` row in the Options table, rewrite the tab command examples to use `<id>` instead of `<n>`, add a paragraph explaining stable tab IDs and `--tab` peek semantics. - `docs/src/app/commands/page.mdx` — same command-example rewrite plus a new "Stable tab IDs and `--tab`" subsection. - `docs/src/app/configuration/page.mdx` — add `tab` row to the config options table so JSON config users can discover it. - `agent-browser.schema.json` — add `tab` property with description, matching the config schema. - `skills/agent-browser/references/commands.md` — same command-example rewrite plus a short paragraph for agents on when to use `--tab`.
This was referenced Apr 16, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
--tab <id>so page-scoped commands can target a tab directly--tabrouting so commands restore the previous active tab when they temporarily target a different tabMotivation
Shared-browser CDP workflows break down when tabs are addressed by positional index because unrelated tab churn changes what a given index points to.
Example:
$ agent-browser tab list [0] App - https://app.example.com [1] Docs - https://docs.example.com → [2] Google - https://www.google.com/ # Another workflow closes a different tab $ agent-browser tab close 1 ✓ Tab 1 closed $ agent-browser tab list [0] App - https://app.example.com → [1] Google - https://www.google.com/ (should be [2])Or another page opens a popup/new tab:
$ agent-browser tab list → [0] App - https://app.example.com [1] Google - https://www.google.com/ # Another workflow opens a popup (you expect it at tab 11) $ agent-browser tab list [0] App - https://app.example.com [1] Google - https://www.google.com/ [2] Popup - https://accounts.example.com/With tab IDs, existing tabs keep the same identifier even when other tabs are closed or popups appear, so agents can continue targeting the same tab across commands.
Testing
pnpm exec vitest run src/browser.test.ts src/protocol.test.ts src/daemon.test.tspnpm exec tsc --noEmitcargo test --manifest-path cli/Cargo.toml tab_cargo test --manifest-path cli/Cargo.toml parse_tab_flagcargo test --manifest-path cli/Cargo.toml clean_args_removes_tab_flag