refactor(bootstrap): consolidate ACP browser bootstrap into install.{sh,ps1} (#27851)

* refactor(bootstrap): consolidate ACP browser bootstrap into install.{sh,ps1}

Delete 687 lines of duplicated browser bootstrap code from
acp_adapter/bootstrap/. All browser installation now routes through
dep_ensure -> install.{sh,ps1} --ensure, using agent-browser install
for Chromium. install.sh gains ensure_browser() with macOS app-bundle
detection and per-distro guidance.

Tracking: #27826

* fix(install.sh): add --ignore-scripts to npm install for camofox

@askjo/camofox-browser has a dependency (impit) whose postinstall
script runs `npx only-allow pnpm`, which fails under npm. Adding
--ignore-scripts avoids the spurious failure without affecting
functionality.

Tracking: #27826

* fix: add explicit return in ensure_browser, narrow exception in entry.py

ensure_browser() now returns 0 explicitly on all success paths.
_run_setup_browser() catches OSError instead of broad Exception,
letting ImportError propagate as a real packaging bug.
This commit is contained in:
Siddharth Balyan
2026-05-18 16:36:26 +05:30
committed by GitHub
parent e3a254d65b
commit d9b6f75c0b
6 changed files with 140 additions and 831 deletions
+19 -44
View File
@@ -182,56 +182,31 @@ def _run_setup() -> None:
def _run_setup_browser(assume_yes: bool = False) -> int:
"""Bootstrap agent-browser + Playwright Chromium for the registry-install path.
"""Bootstrap agent-browser + Chromium.
Shells out to the bundled platform-specific bootstrap script
(acp_adapter/bootstrap/bootstrap_browser_tools.{sh,ps1}) so the install
logic lives in one place — readable, debuggable, and shareable with
install.sh / install.ps1 if we ever want to call it from there too.
Routes through dep_ensure -> install.{sh,ps1} --ensure, sharing code
with ``hermes postinstall`` and the runtime lazy installer.
Returns the script's exit code (0 on success).
Returns 0 on success, 1 on failure.
"""
import platform
import subprocess
from hermes_cli.dep_ensure import ensure_dependency
bootstrap_dir = Path(__file__).resolve().parent / "bootstrap"
if platform.system() == "Windows":
script = bootstrap_dir / "bootstrap_browser_tools.ps1"
if not script.is_file():
print(
f"Bootstrap script not found at {script} — wheel may be incomplete.",
file=sys.stderr,
)
return 1
cmd = [
"powershell.exe",
"-NoProfile",
"-ExecutionPolicy", "Bypass",
"-File", str(script),
]
if assume_yes:
cmd.append("-Yes")
else:
script = bootstrap_dir / "bootstrap_browser_tools.sh"
if not script.is_file():
print(
f"Bootstrap script not found at {script} — wheel may be incomplete.",
file=sys.stderr,
)
return 1
cmd = ["bash", str(script)]
if assume_yes:
cmd.append("--yes")
# stdio is inherited so the user sees the bootstrap's progress live.
try:
result = subprocess.run(cmd, check=False)
except FileNotFoundError as exc:
# bash / powershell.exe not on PATH
print(f"Could not launch browser bootstrap: {exc}", file=sys.stderr)
node_ok = ensure_dependency("node", interactive=not assume_yes)
if not node_ok:
print("Node.js installation failed — cannot proceed with browser tools.",
file=sys.stderr)
return 1
browser_ok = ensure_dependency("browser", interactive=not assume_yes)
if not browser_ok:
print("Browser tools installation failed.", file=sys.stderr)
return 1
return 0
except OSError as exc:
print(f"Browser bootstrap failed: {exc}", file=sys.stderr)
return 1
return result.returncode
def main(argv: list[str] | None = None) -> None: