feat(tabs): reuse an open tab instead of duplicating a page
- Add browser_cli/url_match.py with a canonical URL key for tab matching - Canonicalize scheme, host, default ports, www., trailing slash, query order - Support reuse modes none, exact, similar and origin via normalize_mode() - Pick the closest match when several tabs qualify, preferring identical URLs - Skip the reload when the reused tab already shows the requested page - Expose nav.reusable_tab() so callers can look up a tab without side effects - Accept reuse/reuse_domain/reuse_title in tabs.open(), not just nav.open() - Add --reuse-exact to nav open and nav open-wait; --reuse is now fuzzy - Default MCP tabs_open to reuse="similar" and return a reused flag - Tell MCP agents in the server instructions to reuse before opening - Document the reuse modes in README for MCP, CLI and Python API - Cover url_match, SDK reuse paths and MCP reuse behaviour with new tests - Bump package and extension version to 0.16.9 - Refresh uv.lock for the updated dependency set
This commit is contained in:
@@ -179,6 +179,21 @@ optional `tab_id` and act on the active tab when it is omitted, so a caller
|
||||
does not need a preceding `browser_tabs_list` round trip. `browser_tabs_close`
|
||||
reports the tab it closed.
|
||||
|
||||
`browser_tabs_open` does not duplicate pages. It takes over an already-open tab
|
||||
whose URL is nearly the same and reports `reused` next to the tab metadata, so
|
||||
an agent that re-opens a page keeps working in the tab the user already has.
|
||||
The `reuse` argument selects the match:
|
||||
|
||||
| `reuse` | Matches |
|
||||
|---------|---------|
|
||||
| `similar` (default) | Same site and page, ignoring fragment, trailing slash, query order, `www.` and default ports — plus any tab of the site when the requested URL is its root |
|
||||
| `exact` | Only a character-for-character identical URL |
|
||||
| `origin` | Any tab of the same site, whatever its path |
|
||||
| `none` | Never reuse, always open a new tab |
|
||||
|
||||
A reused tab is only navigated when it is not already on the requested page, so
|
||||
no reload throws away page state.
|
||||
|
||||
Available tools:
|
||||
- `browser_tabs_list`, `browser_tabs_open`, `browser_tabs_close`
|
||||
- `browser_navigate`, `browser_page_info`
|
||||
@@ -244,6 +259,12 @@ browser-cli nav open https://example.com --focus # bring opened tab/w
|
||||
browser-cli nav open https://example.com --window work # into a named window
|
||||
browser-cli nav open https://example.com --group research # into a tab group (name or ID)
|
||||
|
||||
# Reuse an open tab instead of duplicating a page
|
||||
browser-cli nav open https://example.com/app --reuse # nearly identical URL (fragment, trailing slash, query order, www)
|
||||
browser-cli nav open https://example.com/app --reuse-exact # only a character-for-character match
|
||||
browser-cli nav open https://example.com/app --reuse-domain # any tab of the same site
|
||||
browser-cli nav open https://example.com/app --reuse-title "App" # tab whose title contains the text
|
||||
|
||||
# Reload
|
||||
browser-cli nav reload # reload active tab
|
||||
browser-cli nav reload 1234 # reload tab by ID
|
||||
@@ -456,6 +477,9 @@ b.nav.search("google", "python asyncio")
|
||||
tabs = b.tabs.list() # list[Tab]; in multi-browser mode each tab.browser is set
|
||||
tab = b.tabs.open("https://example.com") # returns a bound Tab object
|
||||
tab = b.tabs.open("https://example.com", wait=True, timeout=10)
|
||||
tab = b.tabs.open("https://example.com/app", reuse=True) # reuse a tab with a nearly identical URL
|
||||
tab = b.tabs.open("https://example.com/app", reuse="origin") # reuse any tab of that site
|
||||
existing = b.nav.reusable_tab("https://example.com/app", reuse=True) # Tab or None, without touching the browser
|
||||
active = b.tabs.active() # active Tab object
|
||||
tab = b.tabs.get(1234) # tab by ID
|
||||
tab = b.tabs.first("github") # first matching tab or None
|
||||
|
||||
Reference in New Issue
Block a user