show mute status correctly when tab mute and add to get single tab status
Package Extension / package-extension (push) Successful in 17s
Build & Publish Package / publish (push) Successful in 29s
Testing / test (push) Failing after 26s

This commit is contained in:
2026-04-13 21:35:25 +02:00
parent c494e76fe2
commit edf9056430
6 changed files with 66 additions and 10 deletions
+7
View File
@@ -173,6 +173,13 @@ class BrowserCLI:
"""Switch browser focus to a tab by ID."""
self._cmd("tabs.active", {"tabId": tab_id})
def tabs_status(self, tab_id: int | None = None) -> Tab:
"""Return status for the active tab or a specific tab."""
data = self._cmd("tabs.status", {"tabId": tab_id})
if not isinstance(data, dict) or "id" not in data:
raise RuntimeError("No tab status returned")
return self._make_tab(data)
def tabs_mute(self, tab_id: int | None = None) -> int:
"""Mute the active tab or a specific tab. Returns the target tab ID."""
result = self._cmd("tabs.mute", {"tabId": tab_id})
+17
View File
@@ -125,6 +125,23 @@ def tabs_active(tab_id):
console.print(f"[green]Switched to tab {tab_id}[/green]")
@tabs_group.command("status")
@click.argument("tab_id", type=int, required=False)
def tabs_status(tab_id):
"""Show status for the active tab or a specific tab."""
tab = _handle("tabs.status", {"tabId": tab_id}) or {}
table = Table(show_header=False)
table.add_column("Field", style="bold cyan")
table.add_column("Value")
table.add_row("ID", str(tab.get("id", "")))
table.add_row("Window", str(tab.get("windowId", "")))
table.add_row("Active", "yes" if tab.get("active") else "no")
table.add_row("Muted", "yes" if tab.get("muted") else "no")
table.add_row("Title", tab.get("title") or "")
table.add_row("URL", tab.get("url") or "")
console.print(table)
@tabs_group.command("filter")
@click.argument("pattern")
def tabs_filter(pattern):
+22 -8
View File
@@ -134,6 +134,7 @@ async function dispatch(command, args) {
case "tabs.move": return tabsMove(args);
case "tabs.active": return tabsActive(args);
case "tabs.active_in_window": return tabsActiveInWindow(args);
case "tabs.status": return tabsStatus(args);
case "tabs.filter": return tabsFilter(args);
case "tabs.count": return tabsCount(args);
case "tabs.query": return tabsQuery(args);
@@ -275,15 +276,10 @@ async function tabsList() {
for (const w of windows) {
for (const t of w.tabs) {
tabs.push({
id: t.id,
windowId: t.windowId,
...tabInfo(t),
windowAlias: aliases[t.windowId] || null,
active: t.active,
pinned: t.pinned,
title: t.title,
url: t.url,
favIconUrl: t.favIconUrl,
groupId: t.groupId >= 0 ? t.groupId : null,
});
}
}
@@ -346,6 +342,11 @@ async function tabsActiveInWindow({ windowId }) {
return tabInfo(tab);
}
async function tabsStatus({ tabId }) {
const tab = tabId ? await chrome.tabs.get(tabId) : await getActiveTab();
return tabInfo(tab);
}
async function tabsFilter({ pattern }) {
const all = await chrome.tabs.query({});
return all.filter(t => t.url && t.url.includes(pattern)).map(tabInfo);
@@ -442,13 +443,13 @@ async function tabsMergeWindows() {
}
async function tabsMute({ tabId }) {
const tab = tabId ? await chrome.tabs.get(tabId) : await getActiveTab();
const tab = await resolveTabForDirectAction(tabId, "mute");
await chrome.tabs.update(tab.id, { muted: true });
return { tabId: tab.id, muted: true };
}
async function tabsUnmute({ tabId }) {
const tab = tabId ? await chrome.tabs.get(tabId) : await getActiveTab();
const tab = await resolveTabForDirectAction(tabId, "unmute");
await chrome.tabs.update(tab.id, { muted: false });
return { tabId: tab.id, muted: false };
}
@@ -1243,6 +1244,19 @@ async function getActiveTab() {
|| activeTabs[0];
}
async function resolveTabForDirectAction(tabId, actionName) {
if (tabId != null) {
return chrome.tabs.get(tabId);
}
const allTabs = await chrome.tabs.query({});
if (allTabs.length !== 1) {
throw new Error(
`Refusing to ${actionName} without explicit tab ID when ${allTabs.length} tabs are open`
);
}
return allTabs[0];
}
async function resolveGroupId(nameOrId) {
const asInt = parseInt(nameOrId);
if (!isNaN(asInt)) return asInt;
+1 -1
View File
@@ -1,7 +1,7 @@
{
"manifest_version": 3,
"name": "browser-cli",
"version": "0.5.10",
"version": "0.5.12",
"description": "Control your browser from the terminal via browser-cli",
"permissions": [
"tabs",
+1 -1
View File
@@ -1,6 +1,6 @@
[project]
name = "browser-cli"
version = "0.5.10"
version = "0.5.12"
description = "Control your real running browser from the terminal via a Chrome extension"
requires-python = ">=3.10"
dependencies = [
+18
View File
@@ -52,6 +52,13 @@ def test_tabs_active_in_window(browser):
assert result["windowId"] == active["windowId"]
def test_tabs_status(browser):
result = browser("tabs.status", {})
assert isinstance(result, dict)
assert "id" in result
assert "muted" in result
def test_tabs_html(browser, http_tab):
html = browser("tabs.html", {"tabId": http_tab["id"]})
assert isinstance(html, str)
@@ -133,3 +140,14 @@ def test_tabs_mute_and_unmute(browser, http_tab):
listed = browser("tabs.list")
listed_tab = next(t for t in listed if t["id"] == http_tab["id"])
assert listed_tab["muted"] is False
status = browser("tabs.status", {"tabId": http_tab["id"]})
assert status["muted"] is False
def test_tabs_mute_requires_explicit_tab_when_multiple_tabs_open(browser):
opened = browser("navigate.open", {"url": "https://example.com", "background": True})
try:
with pytest.raises(RuntimeError, match="Refusing to mute without explicit tab ID"):
browser("tabs.mute", {})
finally:
browser("tabs.close", {"tabId": opened["id"]})