fix(client): validate active browser endpoints
Testing / remote-protocol-compat (0.9.3) (push) Successful in 42s
Testing / remote-protocol-compat (0.9.5) (push) Successful in 41s
Testing / test (push) Successful in 50s
Package Extension / package-extension (push) Successful in 29s
Build & Publish Package / publish (push) Successful in 33s

- Check Unix socket reachability with a real connection attempt instead of treating any existing path as active.
- Report ambiguous host-only remote aliases with actionable --remote/--browser examples.
- Update client tests to use listening Unix sockets and cover ambiguous remote alias errors.
- Bump package and extension versions to 0.10.2.
This commit is contained in:
2026-05-25 17:19:17 +02:00
parent 93f8994f6a
commit d2f2a99f3d
5 changed files with 86 additions and 19 deletions
+30 -2
View File
@@ -79,13 +79,24 @@ class BrowserTarget:
socket_path: str
remote: str | None = None
def _is_reachable_unix_endpoint(endpoint: str) -> bool:
"""Return True when a Unix socket path exists and accepts connections."""
path = Path(endpoint)
if not path.exists():
return False
try:
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock:
sock.settimeout(0.2)
sock.connect(endpoint)
return True
except OSError:
return False
def _active_endpoints(reg: dict) -> dict:
"""Return only entries whose endpoint appears reachable."""
if is_windows():
return dict(reg)
return {k: v for k, v in reg.items() if Path(v).exists()}
return {k: v for k, v in reg.items() if _is_reachable_unix_endpoint(v)}
def display_browser_name(profile_name: str, sock_path: str) -> str:
if profile_name != "default":
@@ -198,6 +209,23 @@ def remote_target_for_alias(alias: str | None) -> BrowserTarget | None:
endpoint_matches.append(target)
if len(endpoint_matches) == 1:
return endpoint_matches[0]
if len(endpoint_matches) > 1:
aliases = [target.profile for target in endpoint_matches]
endpoint = endpoint_matches[0].remote or alias
examples = "\n".join(
f" browser-cli --remote {endpoint} --browser {a} ..."
for a in aliases
)
display_aliases = [target.display_name for target in endpoint_matches]
shorthand_examples = "\n".join(
f" browser-cli --browser {a} ..."
for a in display_aliases
)
raise BrowserNotConnected(
f"Multiple remote browser instances are active on {alias}: {', '.join(aliases)}\n"
f"Use --browser <alias> with --remote to select one:\n{examples}\n"
f"Or use the full remote browser alias:\n{shorthand_examples}"
)
return None