feat(tabs): batch-close tabs by id list
Testing / remote-protocol-compat (0.9.5) (push) Successful in 44s
Testing / remote-protocol-compat (0.9.3) (push) Successful in 45s
Testing / test (push) Successful in 52s
Build & Publish Package / publish (push) Successful in 32s
Package Extension / package-extension (push) Successful in 35s

Closing many tabs previously meant one IPC round-trip per tab
(tab.close() in a loop). Add a single batched path so callers can
close N tabs in one command, reusing the existing large-operation
throttle so the browser UI stays responsive.

- extension: tabs.close accepts tabIds: number[]; new branch feeds
  the array through processInBatches/chrome.tabs.remove
- sdk: tabs_close(tab_ids=...) takes tab IDs or Tab objects; the
  payload always carries "tabIds" (null when unused)
- tests: cover id-list and Tab-object batch close in test_api.py
- bump 0.10.3 -> 0.10.4 (pyproject.toml, manifest.json)
This commit is contained in:
2026-06-11 10:31:53 +02:00
parent 6c90837414
commit 0813ae2de9
6 changed files with 51 additions and 10 deletions
+23 -3
View File
@@ -308,9 +308,29 @@ class BrowserCLI:
]
return [self._make_tab(t) for t in (self._cmd("tabs.list", {}) or [])]
def tabs_close(self, tab_id: int | None = None, *, inactive: bool = False, duplicates: bool = False) -> int:
"""Close tab(s). Returns the number of tabs closed."""
result = self._cmd("tabs.close", {"tabId": tab_id, "inactive": inactive, "duplicates": duplicates})
def tabs_close(
self,
tab_id: int | None = None,
*,
tab_ids: Iterable[int | Tab] | None = None,
inactive: bool = False,
duplicates: bool = False,
) -> int:
"""Close tab(s). Returns the number of tabs closed.
Pass ``tab_ids`` to close many tabs in a single round-trip instead of
calling :meth:`close_tab` per tab. Accepts tab IDs or :class:`Tab`
objects. The extension throttles large batches automatically.
"""
ids = None
if tab_ids is not None:
ids = [t.id if isinstance(t, Tab) else t for t in tab_ids]
result = self._cmd("tabs.close", {
"tabId": tab_id,
"tabIds": ids,
"inactive": inactive,
"duplicates": duplicates,
})
return result.get("closed", 1) if isinstance(result, dict) else 1
def tabs_move(