add multi browser mode to arragate data from all browsers by tabs list, tabs count, group list, group count and windows list
Package Extension / package-extension (push) Successful in 12s
Build & Publish Package / publish (push) Successful in 22s

remove (unnamed) into the group names just leave it a empty string, remove Focused on windows how should the browser know what windows are focused
This commit is contained in:
2026-04-10 12:49:51 +02:00
parent 6979f2ef30
commit 61b774a7a4
14 changed files with 578 additions and 79 deletions
+42 -17
View File
@@ -13,6 +13,7 @@ import os
import socket
import struct
import uuid
from dataclasses import dataclass
from pathlib import Path
from typing import Any
@@ -24,11 +25,37 @@ class BrowserNotConnected(Exception):
"""Raised when the native host socket is not available."""
@dataclass(frozen=True)
class BrowserTarget:
profile: str
display_name: str
socket_path: str
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 display_browser_name(profile_name: str, sock_path: str) -> str:
if profile_name != "default":
return profile_name
return Path(sock_path).stem or profile_name
def active_browser_targets() -> list[BrowserTarget]:
if not REGISTRY_PATH.exists():
return []
try:
reg = json.loads(REGISTRY_PATH.read_text())
except Exception:
return []
return [
BrowserTarget(profile=profile, display_name=display_browser_name(profile, sock_path), socket_path=sock_path)
for profile, sock_path in _active_sockets(reg).items()
]
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")
@@ -45,23 +72,21 @@ def _resolve_socket(profile: str | None = None) -> str:
return str(SOCKET_DIR / f"{safe}.sock")
# Auto-detect: error when multiple browser instances are active
if REGISTRY_PATH.exists():
try:
reg = json.loads(REGISTRY_PATH.read_text())
active = _active_sockets(reg)
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:
pass
try:
active = active_browser_targets()
if len(active) > 1:
aliases = [target.profile for target in active]
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 active[0].socket_path
except BrowserNotConnected:
raise
except Exception:
pass
raise BrowserNotConnected(
"Cannot resolve a browser socket automatically.\n"