Skip to content

Consistent Tab IDs & Global Tag Targeting#892

Open
DJRHails wants to merge 7 commits intovercel-labs:mainfrom
DJRHails:patch/tab-targeting
Open

Consistent Tab IDs & Global Tag Targeting#892
DJRHails wants to merge 7 commits intovercel-labs:mainfrom
DJRHails:patch/tab-targeting

Conversation

@DJRHails
Copy link

  • replace positional tab indices with tab IDs across tab commands and response payloads
  • add global --tab <id> so page-scoped commands can target a tab directly
  • scope --tab routing so commands restore the previous active tab when they temporarily target a different tab
  • Fix the tab_list fallback which can be a bit confusing (especially when LLMs hallucinate a tab switch functionality).

Personally I'm not in love with the incrementing integer as the id; but it's a pretty significant refactor otherwise. I've still currently made one breaking change by renaming 'index' -> 'tabId' but that seems worth it for the clarity of code.

Motivation

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.ts
  • pnpm exec tsc --noEmit
  • cargo test --manifest-path cli/Cargo.toml tab_
  • cargo test --manifest-path cli/Cargo.toml parse_tab_flag
  • cargo test --manifest-path cli/Cargo.toml clean_args_removes_tab_flag

@vercel
Copy link
Contributor

vercel bot commented Mar 17, 2026

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

A member of the Team first needs to authorize it.

@DJRHails
Copy link
Author

Hey @mvanhorn - just saw #883 - let me know what you think. Had this in a fork.

@patch-stack-bot patch-stack-bot bot force-pushed the patch/tab-targeting branch from ad6eaca to 654c33c Compare March 17, 2026 23:50
patch-stack-bot bot pushed a commit to DJRHails/agent-browser that referenced this pull request Mar 17, 2026
@DJRHails DJRHails force-pushed the patch/tab-targeting branch 2 times, most recently from 9d2cff6 to ceb7451 Compare March 18, 2026 00:56
@patch-stack-bot patch-stack-bot bot force-pushed the patch/tab-targeting branch from ceb7451 to 29b2ee1 Compare March 18, 2026 04:40
patch-stack-bot bot added a commit to DJRHails/agent-browser that referenced this pull request Mar 18, 2026
@mvanhorn
Copy link
Contributor

Hey @DJRHails - the stable tab ID approach looks solid. My #883 uses positional indexes which is simpler but less robust. I'd defer to @ctate on which direction to go - happy to close mine if the ID-based approach is preferred.

@DJRHails DJRHails force-pushed the patch/tab-targeting branch from 29b2ee1 to ceb7451 Compare March 18, 2026 15:35
@patch-stack-bot patch-stack-bot bot force-pushed the patch/tab-targeting branch from ceb7451 to 656ff18 Compare March 18, 2026 15:45
patch-stack-bot bot added a commit to DJRHails/agent-browser that referenced this pull request Mar 18, 2026
@patch-stack-bot patch-stack-bot bot force-pushed the patch/tab-targeting branch from 656ff18 to b251966 Compare March 19, 2026 04:39
patch-stack-bot bot added a commit to DJRHails/agent-browser that referenced this pull request Mar 19, 2026
@patch-stack-bot patch-stack-bot bot force-pushed the patch/tab-targeting branch from b251966 to a10a668 Compare March 20, 2026 04:34
patch-stack-bot bot added a commit to DJRHails/agent-browser that referenced this pull request Mar 20, 2026
@patch-stack-bot patch-stack-bot bot force-pushed the patch/tab-targeting branch 2 times, most recently from 915231e to e909a8e Compare March 22, 2026 04:38
patch-stack-bot bot added a commit to DJRHails/agent-browser that referenced this pull request Mar 22, 2026
@mvanhorn
Copy link
Contributor

Interesting approach with persistent tab IDs - that's a cleaner foundation than positional indices. Happy to rebase #883 on top of yours if @ctate prefers your approach, or we can coordinate to merge the concepts.

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)".
@patch-stack-bot patch-stack-bot bot force-pushed the patch/tab-targeting branch from e909a8e to 58b773d Compare March 23, 2026 04:45
patch-stack-bot bot added a commit to DJRHails/agent-browser that referenced this pull request Mar 23, 2026
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