Consistent Tab IDs & Global Tag Targeting (#892)

Introduces stable per-tab IDs and a global `--tab <id>` flag for scoping individual commands to a specific tab.

Breaking change: response payloads for `tab_list`, `tab_new`, `tab_switch`, `tab_close`, and `window_new` now use `tabId` instead of `index`. `tab_close` returns `{tabId, closed: true}` instead of `{closed, activeIndex}`. `agent-browser tab <unknown>` now errors instead of silently listing tabs.

Follow-up PR to land immediately after this fixes a compile error on the provider direct-page path, clears per-tab daemon state around scoped switches, and implements active-tab restoration so `--tab N` is non-intrusive as intended.
This commit is contained in:
Daniel Hails
2026-04-16 12:02:55 -05:00
committed by GitHub
parent c691b269cb
commit 67dc631977
7 changed files with 618 additions and 45 deletions
+105 -6
View File
@@ -406,7 +406,11 @@ pub fn print_response_with_opts(resp: &Response, action: Option<&str>, opts: &Ou
}
// Tabs
if let Some(tabs) = data.get("tabs").and_then(|v| v.as_array()) {
for (i, tab) in tabs.iter().enumerate() {
for tab in tabs {
let tab_id = tab
.get("tabId")
.and_then(|v| v.as_i64())
.unwrap_or_default();
let title = tab
.get("title")
.and_then(|v| v.as_str())
@@ -418,10 +422,47 @@ pub fn print_response_with_opts(resp: &Response, action: Option<&str>, opts: &Ou
} else {
" ".to_string()
};
println!("{} [{}] {} - {}", marker, i, title, url);
println!("{} [{}] {} - {}", marker, tab_id, title, url);
}
return;
}
// Tab switch
if action == Some("tab_switch") {
if let Some(tab_id) = data.get("tabId").and_then(|v| v.as_i64()) {
if let Some(url) = data.get("url").and_then(|v| v.as_str()) {
println!(
"{} Switched to tab [{}] ({})",
color::success_indicator(),
tab_id,
url
);
} else {
println!(
"{} Switched to tab [{}]",
color::success_indicator(),
tab_id
);
}
return;
}
}
// New tab/window
if let Some(tab_id) = data.get("tabId").and_then(|v| v.as_i64()) {
if let Some(total) = data.get("total").and_then(|v| v.as_i64()) {
let label = match action {
Some("window_new") => "Window opened",
_ => "Tab opened",
};
println!(
"{} {} [{}] ({} total)",
color::success_indicator(),
label,
tab_id,
total
);
return;
}
}
// Console logs
if let Some(logs) = data.get("messages").and_then(|v| v.as_array()) {
if opts.content_boundaries {
@@ -562,7 +603,13 @@ pub fn print_response_with_opts(resp: &Response, action: Option<&str>, opts: &Ou
// Closed (browser or tab)
if data.get("closed").is_some() {
let label = match action {
Some("tab_close") => "Tab closed",
Some("tab_close") => {
if let Some(closed_id) = data.get("tabId").and_then(|v| v.as_i64()) {
println!("{} Tab [{}] closed", color::success_indicator(), closed_id);
return;
}
"Tab closed"
}
_ => "Browser closed",
};
println!("{} {}", color::success_indicator(), label);
@@ -1010,6 +1057,7 @@ Aliases: goto, navigate
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
--headers <json> Set HTTP headers (scoped to this origin)
--headed Show browser window
@@ -1033,6 +1081,7 @@ the browser's back button.
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser back
@@ -1050,6 +1099,7 @@ the browser's forward button.
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser forward
@@ -1067,6 +1117,7 @@ the browser's reload button.
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser reload
@@ -1090,6 +1141,7 @@ Options:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser click "#submit-button"
@@ -1111,6 +1163,7 @@ or triggering double-click handlers.
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser dblclick "#editable-text"
@@ -1129,6 +1182,7 @@ This replaces any existing content in the field.
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser fill "#email" "user@example.com"
@@ -1148,6 +1202,7 @@ Unlike fill, this does not clear existing content first.
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser type "#search" "hello"
@@ -1171,6 +1226,7 @@ triggering hover states or dropdown menus.
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser hover "#dropdown-trigger"
@@ -1188,6 +1244,7 @@ Sets keyboard focus to the specified element.
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser focus "#input-field"
@@ -1205,6 +1262,7 @@ Checks a checkbox element. If already checked, no action is taken.
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser check "#terms-checkbox"
@@ -1222,6 +1280,7 @@ Unchecks a checkbox element. If already unchecked, no action is taken.
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser uncheck "#newsletter-opt-in"
@@ -1239,6 +1298,7 @@ Selects one or more options in a <select> dropdown by value.
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser select "#country" "US"
@@ -1257,6 +1317,7 @@ Drags an element from source to target location.
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser drag "#draggable" "#drop-zone"
@@ -1274,6 +1335,7 @@ Uploads one or more files to a file input element.
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser upload "#file-input" ./document.pdf
@@ -1295,6 +1357,7 @@ Arguments:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser download "#download-btn" ./file.pdf
@@ -1326,6 +1389,7 @@ Modifiers (combine with +):
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser press Enter
@@ -1347,6 +1411,7 @@ Useful for holding modifier keys.
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser keydown Shift
@@ -1364,6 +1429,7 @@ Releases a key that was pressed with keydown.
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser keyup Shift
@@ -1392,6 +1458,7 @@ directly — it already operates on the current focus.
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser keyboard type "Hello, World!"
@@ -1426,6 +1493,7 @@ Options:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser scroll
@@ -1448,6 +1516,7 @@ Aliases: scrollinto
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser scrollintoview "#footer"
@@ -1485,6 +1554,7 @@ Wait for text to disappear:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser wait "#loading-spinner"
@@ -1526,6 +1596,7 @@ Options:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser screenshot
@@ -1549,6 +1620,7 @@ Saves the current page as a PDF file.
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser pdf ./page.pdf
@@ -1577,6 +1649,7 @@ Options:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser snapshot
@@ -1603,6 +1676,7 @@ Options:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser eval "document.title"
@@ -1635,6 +1709,7 @@ Options:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser close
@@ -1686,6 +1761,7 @@ Subcommands:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser get text @e1
@@ -1718,6 +1794,7 @@ Subcommands:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser is visible "#modal"
@@ -1757,6 +1834,7 @@ Options:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser find role button click --name Submit
@@ -1787,6 +1865,7 @@ Subcommands:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser mouse move 100 200
@@ -1820,6 +1899,7 @@ Settings:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser set viewport 1920 1080
@@ -1860,6 +1940,7 @@ Subcommands:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser network route "**/api/*" --abort
@@ -1897,6 +1978,7 @@ Operations:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser storage local
@@ -1936,6 +2018,7 @@ for the current page URL.
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
# Simple cookie for current page
@@ -1971,14 +2054,15 @@ Usage: agent-browser tab [operation] [args]
Manage browser tabs in the current window.
Operations:
list List all tabs (default)
list List all tabs with tab IDs (default)
new [url] Open new tab
close [index] Close tab (current if no index)
<index> Switch to tab by index
close [id] Close tab by ID (current if no ID)
<id> Switch to tab by ID
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser tab
@@ -2006,6 +2090,7 @@ Operations:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser window new
@@ -2028,6 +2113,7 @@ Arguments:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser frame "#embed-iframe"
@@ -2115,6 +2201,7 @@ Operations:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser dialog accept
@@ -2140,6 +2227,7 @@ Operations:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser trace start
@@ -2171,6 +2259,7 @@ Start Options:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
# Basic profiling
@@ -2210,6 +2299,7 @@ Operations:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
# Record from current page (preserves login state)
@@ -2242,6 +2332,7 @@ Options:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser console
@@ -2262,6 +2353,7 @@ Options:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser errors
@@ -2281,6 +2373,7 @@ Visually highlights an element on the page for debugging.
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser highlight "#target-element"
@@ -2306,6 +2399,7 @@ Operations:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser clipboard read
@@ -2345,6 +2439,7 @@ State Encryption:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser state save ./auth-state.json
@@ -2377,6 +2472,7 @@ Environment:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser session
@@ -2474,6 +2570,7 @@ Supported URL formats:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
# Connect to local Chrome with remote debugging
@@ -2635,6 +2732,7 @@ URL Diff:
Global Options:
--json Output as JSON
--session <name> Use specific session
--tab <id> Target specific tab ID
Examples:
agent-browser diff snapshot
@@ -2929,6 +3027,7 @@ Authentication:
Options:
--session <name> Isolated session (or AGENT_BROWSER_SESSION env)
--tab <id> Target specific tab ID for the command
--executable-path <path> Custom browser executable (or AGENT_BROWSER_EXECUTABLE_PATH)
--extension <path> Load browser extensions (repeatable)
--args <args> Browser launch args, comma or newline separated (or AGENT_BROWSER_ARGS)