move socket path into /tmp/.browser_cli subfolder with registry
This commit is contained in:
+9
-1
@@ -41,8 +41,16 @@ NATIVE_HOST_DIRS = {
|
|||||||
|
|
||||||
|
|
||||||
@click.group()
|
@click.group()
|
||||||
def main():
|
@click.option(
|
||||||
|
"--browser", default=None, metavar="ALIAS",
|
||||||
|
help="Browser profile alias to target (required when multiple browsers are active).",
|
||||||
|
)
|
||||||
|
@click.pass_context
|
||||||
|
def main(ctx, browser):
|
||||||
"""Control your running browser from the terminal via a Chrome extension."""
|
"""Control your running browser from the terminal via a Chrome extension."""
|
||||||
|
ctx.ensure_object(dict)
|
||||||
|
if browser:
|
||||||
|
os.environ["BROWSER_CLI_PROFILE"] = browser
|
||||||
|
|
||||||
|
|
||||||
# ── Sub-command groups ─────────────────────────────────────────────────────────
|
# ── Sub-command groups ─────────────────────────────────────────────────────────
|
||||||
|
|||||||
+24
-8
@@ -5,8 +5,8 @@ Used by both the CLI and the public Python API.
|
|||||||
Profile selection order:
|
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. Fallback: /tmp/.browser_cli/default.sock
|
||||||
"""
|
"""
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
@@ -16,14 +16,20 @@ import uuid
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
REGISTRY_PATH = Path("/tmp/browser-cli-registry.json")
|
SOCKET_DIR = Path("/tmp/.browser_cli")
|
||||||
DEFAULT_SOCKET = "/tmp/browser-cli-default.sock"
|
REGISTRY_PATH = SOCKET_DIR / "registry.json"
|
||||||
|
DEFAULT_SOCKET = str(SOCKET_DIR / "default.sock")
|
||||||
|
|
||||||
|
|
||||||
class BrowserNotConnected(Exception):
|
class BrowserNotConnected(Exception):
|
||||||
"""Raised when the native host socket is not available."""
|
"""Raised when the native host socket is not available."""
|
||||||
|
|
||||||
|
|
||||||
|
def _active_sockets(reg: dict) -> dict:
|
||||||
|
"""Return only entries whose socket file exists on disk."""
|
||||||
|
return {k: v for k, v in reg.items() if Path(v).exists()}
|
||||||
|
|
||||||
|
|
||||||
def _resolve_socket(profile: str | None = None) -> str:
|
def _resolve_socket(profile: str | None = None) -> str:
|
||||||
"""Return the socket path for the given profile (or auto-detect)."""
|
"""Return the socket path for the given profile (or auto-detect)."""
|
||||||
target = profile or os.environ.get("BROWSER_CLI_PROFILE")
|
target = profile or os.environ.get("BROWSER_CLI_PROFILE")
|
||||||
@@ -37,14 +43,24 @@ def _resolve_socket(profile: str | None = None) -> str:
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
safe = target.replace(" ", "_").replace("/", "_")
|
safe = target.replace(" ", "_").replace("/", "_")
|
||||||
return f"/tmp/browser-cli-{safe}.sock"
|
return str(SOCKET_DIR / f"{safe}.sock")
|
||||||
|
|
||||||
# Auto-detect: use first registered entry
|
# Auto-detect: error when multiple browser instances are active
|
||||||
if REGISTRY_PATH.exists():
|
if REGISTRY_PATH.exists():
|
||||||
try:
|
try:
|
||||||
reg = json.loads(REGISTRY_PATH.read_text())
|
reg = json.loads(REGISTRY_PATH.read_text())
|
||||||
if reg:
|
active = _active_sockets(reg)
|
||||||
return next(iter(reg.values()))
|
if len(active) > 1:
|
||||||
|
aliases = list(active.keys())
|
||||||
|
examples = "\n".join(f" browser-cli --browser {a} ..." for a in aliases)
|
||||||
|
raise BrowserNotConnected(
|
||||||
|
f"Multiple browser instances are active: {', '.join(aliases)}\n"
|
||||||
|
f"Use --browser <alias> to select one:\n{examples}"
|
||||||
|
)
|
||||||
|
if active:
|
||||||
|
return next(iter(active.values()))
|
||||||
|
except BrowserNotConnected:
|
||||||
|
raise
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ import threading
|
|||||||
import uuid
|
import uuid
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
REGISTRY_PATH = Path("/tmp/browser-cli-registry.json")
|
SOCKET_DIR = Path("/tmp/.browser_cli")
|
||||||
|
REGISTRY_PATH = SOCKET_DIR / "registry.json"
|
||||||
DEFAULT_ALIAS = "default"
|
DEFAULT_ALIAS = "default"
|
||||||
|
|
||||||
SOCKET_PATH: str = "" # set after hello handshake
|
SOCKET_PATH: str = "" # set after hello handshake
|
||||||
@@ -71,7 +72,7 @@ def _registry_remove(alias: str) -> None:
|
|||||||
|
|
||||||
def _socket_path_for(alias: str) -> str:
|
def _socket_path_for(alias: str) -> str:
|
||||||
safe = alias.replace(" ", "_").replace("/", "_")
|
safe = alias.replace(" ", "_").replace("/", "_")
|
||||||
return f"/tmp/browser-cli-{safe}.sock"
|
return str(SOCKET_DIR / f"{safe}.sock")
|
||||||
|
|
||||||
|
|
||||||
# --- Thread A: read messages from extension (stdin) ---
|
# --- Thread A: read messages from extension (stdin) ---
|
||||||
@@ -202,6 +203,7 @@ def main():
|
|||||||
PENDING[msg_id] = q
|
PENDING[msg_id] = q
|
||||||
write_native_message(sys.stdout.buffer, first_msg)
|
write_native_message(sys.stdout.buffer, first_msg)
|
||||||
|
|
||||||
|
SOCKET_DIR.mkdir(mode=0o700, exist_ok=True)
|
||||||
sock_path = _socket_path_for(alias)
|
sock_path = _socket_path_for(alias)
|
||||||
_registry_add(alias, sock_path)
|
_registry_add(alias, sock_path)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user