add moveing of tabs and groups, multi browser support, auto complite into terminal, extract html and adding testing
This commit is contained in:
+44
-5
@@ -1,22 +1,59 @@
|
||||
"""
|
||||
Unix socket client — sends commands to the native host relay socket.
|
||||
Used by both the CLI and the public Python API.
|
||||
|
||||
Profile selection order:
|
||||
1. Explicit `profile` argument to send_command()
|
||||
2. BROWSER_CLI_PROFILE environment variable
|
||||
3. First entry in /tmp/browser-cli-registry.json
|
||||
4. Fallback: /tmp/browser-cli-default.sock
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import socket
|
||||
import struct
|
||||
import uuid
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
SOCKET_PATH = "/tmp/browser-cli.sock"
|
||||
REGISTRY_PATH = Path("/tmp/browser-cli-registry.json")
|
||||
DEFAULT_SOCKET = "/tmp/browser-cli-default.sock"
|
||||
|
||||
|
||||
class BrowserNotConnected(Exception):
|
||||
"""Raised when the native host socket is not available."""
|
||||
|
||||
|
||||
def send_command(command: str, args: dict | None = None) -> Any:
|
||||
def _resolve_socket(profile: str | None = None) -> str:
|
||||
"""Return the socket path for the given profile (or auto-detect)."""
|
||||
target = profile or os.environ.get("BROWSER_CLI_PROFILE")
|
||||
|
||||
if target:
|
||||
if REGISTRY_PATH.exists():
|
||||
try:
|
||||
reg = json.loads(REGISTRY_PATH.read_text())
|
||||
if target in reg:
|
||||
return reg[target]
|
||||
except Exception:
|
||||
pass
|
||||
safe = target.replace(" ", "_").replace("/", "_")
|
||||
return f"/tmp/browser-cli-{safe}.sock"
|
||||
|
||||
# Auto-detect: use first registered entry
|
||||
if REGISTRY_PATH.exists():
|
||||
try:
|
||||
reg = json.loads(REGISTRY_PATH.read_text())
|
||||
if reg:
|
||||
return next(iter(reg.values()))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return DEFAULT_SOCKET
|
||||
|
||||
|
||||
def send_command(command: str, args: dict | None = None, profile: str | None = None) -> Any:
|
||||
"""Send a command to the browser and return the response data."""
|
||||
sock_path = _resolve_socket(profile)
|
||||
msg = {
|
||||
"id": str(uuid.uuid4()),
|
||||
"command": command,
|
||||
@@ -27,16 +64,18 @@ def send_command(command: str, args: dict | None = None) -> Any:
|
||||
|
||||
try:
|
||||
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock:
|
||||
sock.connect(SOCKET_PATH)
|
||||
sock.connect(sock_path)
|
||||
sock.sendall(framed)
|
||||
response = _recv_all(sock)
|
||||
except (FileNotFoundError, ConnectionRefusedError, OSError):
|
||||
profile_hint = f" (profile: {profile})" if profile else ""
|
||||
raise BrowserNotConnected(
|
||||
"Cannot connect to browser.\n"
|
||||
f"Cannot connect to browser{profile_hint}.\n"
|
||||
"Make sure:\n"
|
||||
" 1. The browser-cli extension is installed and enabled\n"
|
||||
" 2. The native host is registered: uv run browser-cli install chrome\n"
|
||||
" 3. Your browser is running"
|
||||
" 3. Your browser is running\n"
|
||||
" Tip: use BROWSER_CLI_PROFILE=<name> to select a specific profile"
|
||||
)
|
||||
|
||||
result = json.loads(response)
|
||||
|
||||
Reference in New Issue
Block a user