fix that the cli still used the DEFAULT_SOCKET Const, give better error message when no browser found adding test for client and update cli test, and update version and readme
This commit is contained in:
@@ -122,7 +122,7 @@ browser-cli/
|
|||||||
|
|
||||||
All commands are run with `uv run browser-cli [--browser ALIAS] <command>`.
|
All commands are run with `uv run browser-cli [--browser ALIAS] <command>`.
|
||||||
|
|
||||||
Use `--browser ALIAS` when multiple browser instances are connected. You can inspect the active instances with `browser-cli clients` and assign a persistent profile alias from inside the target browser with `browser-cli rename-profile --browser <current-alias> <new-alias>`.
|
If exactly one browser instance is connected, commands auto-target it. Use `--browser ALIAS` when multiple browser instances are connected. You can inspect the active instances with `browser-cli clients` and assign a persistent profile alias from inside the target browser with `browser-cli rename-profile --browser <current-alias> <new-alias>`.
|
||||||
|
|
||||||
Important: profile aliases are browser-instance aliases, not window aliases. Window aliases created with `windows rename` are only for targeting windows in commands like `nav open --window work`. If a browser instance has no explicit profile alias set, the native host gives it a generated UUID alias so multiple unaliased browsers stay distinct.
|
Important: profile aliases are browser-instance aliases, not window aliases. Window aliases created with `windows rename` are only for targeting windows in commands like `nav open --window work`. If a browser instance has no explicit profile alias set, the native host gives it a generated UUID alias so multiple unaliased browsers stay distinct.
|
||||||
|
|
||||||
@@ -268,7 +268,7 @@ browser-cli session auto-save off
|
|||||||
### Misc
|
### Misc
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
browser-cli clients # show connected browser info
|
browser-cli clients # show connected browser info from the registry
|
||||||
browser-cli rename-profile --browser abcd1234 work # rename one connected browser instance
|
browser-cli rename-profile --browser abcd1234 work # rename one connected browser instance
|
||||||
browser-cli --browser abcd1234 rename-profile work # equivalent global form
|
browser-cli --browser abcd1234 rename-profile work # equivalent global form
|
||||||
browser-cli install brave # (re)register the native host
|
browser-cli install brave # (re)register the native host
|
||||||
|
|||||||
+3
-5
@@ -124,7 +124,7 @@ main.add_command(search_group)
|
|||||||
def cmd_clients():
|
def cmd_clients():
|
||||||
"""Show connected browser clients."""
|
"""Show connected browser clients."""
|
||||||
import json as _json
|
import json as _json
|
||||||
from browser_cli.client import REGISTRY_PATH, DEFAULT_SOCKET
|
from browser_cli.client import REGISTRY_PATH
|
||||||
|
|
||||||
# Build a map of profile → socket path from the registry
|
# Build a map of profile → socket path from the registry
|
||||||
profiles: dict[str, str] = {}
|
profiles: dict[str, str] = {}
|
||||||
@@ -133,8 +133,6 @@ def cmd_clients():
|
|||||||
profiles = _json.loads(REGISTRY_PATH.read_text())
|
profiles = _json.loads(REGISTRY_PATH.read_text())
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
if not profiles:
|
|
||||||
profiles = {"default": DEFAULT_SOCKET}
|
|
||||||
|
|
||||||
all_clients = []
|
all_clients = []
|
||||||
for profile_name, sock_path in profiles.items():
|
for profile_name, sock_path in profiles.items():
|
||||||
@@ -148,7 +146,7 @@ def cmd_clients():
|
|||||||
all_clients.append({"profile": profile_name, "name": "—", "version": "—", "platform": "disconnected"})
|
all_clients.append({"profile": profile_name, "name": "—", "version": "—", "platform": "disconnected"})
|
||||||
|
|
||||||
if not all_clients:
|
if not all_clients:
|
||||||
console.print("[yellow]No browser clients found[/yellow]")
|
console.print("[yellow]No browser clients found. Start a browser with the extension enabled first.[/yellow]")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
from rich.table import Table
|
from rich.table import Table
|
||||||
@@ -158,7 +156,7 @@ def cmd_clients():
|
|||||||
table.add_column("Version")
|
table.add_column("Version")
|
||||||
table.add_column("Platform")
|
table.add_column("Platform")
|
||||||
for c in all_clients:
|
for c in all_clients:
|
||||||
table.add_row(c.get("profile", "default"), c.get("name", ""), c.get("version", ""), c.get("platform", ""))
|
table.add_row(c.get("profile", ""), c.get("name", ""), c.get("version", ""), c.get("platform", ""))
|
||||||
console.print(table)
|
console.print(table)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ Profile selection order:
|
|||||||
1. Explicit `profile` argument to send_command()
|
1. Explicit `profile` argument to send_command()
|
||||||
2. BROWSER_CLI_PROFILE environment variable
|
2. BROWSER_CLI_PROFILE environment variable
|
||||||
3. First entry in /tmp/.browser_cli/registry.json
|
3. First entry in /tmp/.browser_cli/registry.json
|
||||||
4. Fallback: /tmp/.browser_cli/default.sock
|
4. Otherwise, no browser can be resolved automatically
|
||||||
"""
|
"""
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
@@ -18,7 +18,6 @@ from typing import Any
|
|||||||
|
|
||||||
SOCKET_DIR = Path("/tmp/.browser_cli")
|
SOCKET_DIR = Path("/tmp/.browser_cli")
|
||||||
REGISTRY_PATH = SOCKET_DIR / "registry.json"
|
REGISTRY_PATH = SOCKET_DIR / "registry.json"
|
||||||
DEFAULT_SOCKET = str(SOCKET_DIR / "default.sock")
|
|
||||||
|
|
||||||
|
|
||||||
class BrowserNotConnected(Exception):
|
class BrowserNotConnected(Exception):
|
||||||
@@ -64,7 +63,11 @@ def _resolve_socket(profile: str | None = None) -> str:
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return DEFAULT_SOCKET
|
raise BrowserNotConnected(
|
||||||
|
"Cannot resolve a browser socket automatically.\n"
|
||||||
|
"Make sure the browser is running with the browser-cli extension enabled,\n"
|
||||||
|
"or pass --browser <alias> / set BROWSER_CLI_PROFILE to a known alias."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def send_command(command: str, args: dict | None = None, profile: str | None = None) -> Any:
|
def send_command(command: str, args: dict | None = None, profile: str | None = None) -> Any:
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "browser-cli"
|
name = "browser-cli"
|
||||||
version = "0.4.0"
|
version = "0.4.1"
|
||||||
description = "Control your real running browser from the terminal via a Chrome extension"
|
description = "Control your real running browser from the terminal via a Chrome extension"
|
||||||
requires-python = ">=3.10"
|
requires-python = ">=3.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
|||||||
@@ -47,3 +47,10 @@ def test_install_help_lists_supported_browsers():
|
|||||||
|
|
||||||
assert result.exit_code == 0
|
assert result.exit_code == 0
|
||||||
assert "[chrome|chromium|brave|edge|vivaldi]" in result.output
|
assert "[chrome|chromium|brave|edge|vivaldi]" in result.output
|
||||||
|
|
||||||
|
def test_clients_exits_cleanly_when_registry_is_missing():
|
||||||
|
with patch("browser_cli.client.REGISTRY_PATH", Path("/nonexistent/browser-cli-registry.json")):
|
||||||
|
result = CliRunner().invoke(main, ["clients"])
|
||||||
|
|
||||||
|
assert result.exit_code == 1
|
||||||
|
assert "No browser clients found" in result.output
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from browser_cli.client import BrowserNotConnected, _resolve_socket
|
||||||
|
|
||||||
|
def test_resolve_socket_raises_when_registry_missing(monkeypatch):
|
||||||
|
monkeypatch.delenv("BROWSER_CLI_PROFILE", raising=False)
|
||||||
|
monkeypatch.setattr("browser_cli.client.REGISTRY_PATH", Path("/nonexistent/browser-cli-registry.json"))
|
||||||
|
|
||||||
|
with pytest.raises(BrowserNotConnected, match="Cannot resolve a browser socket automatically"):
|
||||||
|
_resolve_socket()
|
||||||
|
|
||||||
|
def test_resolve_socket_uses_only_active_registry_entry(monkeypatch, tmp_path):
|
||||||
|
monkeypatch.delenv("BROWSER_CLI_PROFILE", raising=False)
|
||||||
|
|
||||||
|
socket_path = tmp_path / "browser.sock"
|
||||||
|
socket_path.write_text("")
|
||||||
|
registry_path = tmp_path / "registry.json"
|
||||||
|
registry_path.write_text(json.dumps({"abc-uuid": str(socket_path)}))
|
||||||
|
|
||||||
|
monkeypatch.setattr("browser_cli.client.REGISTRY_PATH", registry_path)
|
||||||
|
|
||||||
|
assert _resolve_socket() == str(socket_path)
|
||||||
|
|
||||||
|
def test_resolve_socket_raises_when_multiple_active_entries(monkeypatch, tmp_path):
|
||||||
|
monkeypatch.delenv("BROWSER_CLI_PROFILE", raising=False)
|
||||||
|
|
||||||
|
first_socket = tmp_path / "one.sock"
|
||||||
|
second_socket = tmp_path / "two.sock"
|
||||||
|
first_socket.write_text("")
|
||||||
|
second_socket.write_text("")
|
||||||
|
registry_path = tmp_path / "registry.json"
|
||||||
|
registry_path.write_text(json.dumps({"uuid-1": str(first_socket), "uuid-2": str(second_socket)}))
|
||||||
|
|
||||||
|
monkeypatch.setattr("browser_cli.client.REGISTRY_PATH", registry_path)
|
||||||
|
|
||||||
|
with pytest.raises(BrowserNotConnected, match="Multiple browser instances are active: uuid-1, uuid-2"):
|
||||||
|
_resolve_socket()
|
||||||
Reference in New Issue
Block a user