6fa931aa36
Testing / remote-protocol-compat (0.9.5) (push) Successful in 56s
Testing / remote-protocol-compat (0.9.3) (push) Successful in 59s
Testing / test (push) Successful in 1m1s
Build & Publish Package / publish (push) Successful in 33s
Package Extension / package-extension (push) Successful in 36s
- Gate TCP serve commands with safe-by-default policies, per-key allow tokens, per-key rate limiting, and audit labels. - Reuse authenticated encrypted remote sessions and parallelize/caches multi-browser fanout to reduce repeated handshake roundtrips. - Increase paged native-host batch size with extension-side byte budgeting to speed large tab listings safely. - Point install output at public Chrome Web Store / Firefox AMO listings by default, with --dev preserving unpacked workflows. - Share search-engine metadata between CLI and SDK and bump the package/extension version to 0.16.0. - Cover the new security, pooling, paging, install, and fanout behavior with expanded Python and extension tests.
74 lines
3.0 KiB
Python
74 lines
3.0 KiB
Python
from __future__ import annotations
|
|
|
|
import shutil
|
|
import click
|
|
from rich.console import Console
|
|
from rich.table import Table
|
|
|
|
from browser_cli.commands import handle_errors, client_from_ctx
|
|
from browser_cli.client import active_browser_targets
|
|
from browser_cli.constants import NATIVE_HOST_DIRS, NATIVE_HOST_NAME
|
|
from browser_cli.platform import is_windows
|
|
from browser_cli.version_manager import project_version
|
|
|
|
console = Console()
|
|
|
|
def _status(ok: bool) -> str:
|
|
return "[green]OK[/green]" if ok else "[red]FAIL[/red]"
|
|
|
|
@click.command("doctor")
|
|
@click.option("--remote", "check_remote", is_flag=True, help="Also probe the configured remote endpoint")
|
|
@handle_errors
|
|
def cmd_doctor(check_remote):
|
|
"""Diagnose browser-cli installation, extension, and connection health."""
|
|
rows: list[tuple[str, bool, str]] = []
|
|
version = project_version()
|
|
rows.append(("Python package", version != "unknown", version))
|
|
rows.append(("browser-cli executable", shutil.which("browser-cli") is not None, shutil.which("browser-cli") or "not on PATH"))
|
|
|
|
manifest_notes = []
|
|
if not is_windows():
|
|
import sys
|
|
platform = "darwin" if sys.platform == "darwin" else "linux"
|
|
for browser, by_platform in NATIVE_HOST_DIRS.items():
|
|
for directory in by_platform.get(platform, []):
|
|
path = directory / f"{NATIVE_HOST_NAME}.json"
|
|
if path.exists():
|
|
manifest_notes.append(f"{browser}: {path}")
|
|
rows.append(("Native host manifest", bool(manifest_notes), "; ".join(manifest_notes) or "not found for common browsers"))
|
|
|
|
try:
|
|
targets = active_browser_targets(include_remotes=check_remote)
|
|
rows.append(("Browser registry", bool(targets), f"{len(targets)} active target(s)"))
|
|
except Exception as exc:
|
|
rows.append(("Browser registry", False, str(exc)))
|
|
|
|
client = client_from_ctx()
|
|
try:
|
|
clients = client.clients()
|
|
rows.append(("Connection", True, f"{len(clients)} client(s) responded"))
|
|
ext_versions = sorted({str(c.get("extensionVersion", "unknown")) for c in clients if isinstance(c, dict)})
|
|
if ext_versions:
|
|
rows.append(("Extension version", version in ext_versions, ", ".join(ext_versions)))
|
|
except Exception as exc:
|
|
rows.append(("Connection", False, str(exc)))
|
|
|
|
try:
|
|
info = client.extension.info()
|
|
caps = info.get("capabilities") or []
|
|
rows.append(("Extension info", True, f"v{info.get('version', 'unknown')} · {len(caps)} capabilities"))
|
|
except Exception as exc:
|
|
rows.append(("Extension info", False, f"not available ({exc})"))
|
|
|
|
table = Table(show_header=True, header_style="bold cyan")
|
|
table.add_column("Check")
|
|
table.add_column("Status")
|
|
table.add_column("Details")
|
|
for name, ok, detail in rows:
|
|
table.add_row(name, _status(ok), detail)
|
|
console.print(table)
|
|
|
|
failed = [name for name, ok, _ in rows if not ok and name in {"Connection", "Browser registry"}]
|
|
if failed:
|
|
raise SystemExit(1)
|