diff --git a/hermes_cli/tools_config.py b/hermes_cli/tools_config.py index 614e79b43d4e..6a0672392f27 100644 --- a/hermes_cli/tools_config.py +++ b/hermes_cli/tools_config.py @@ -567,6 +567,7 @@ def _pip_install( timeout: int = 300, capture_output: bool = True, ): + from tools.environments.local import _sanitize_subprocess_env """Install Python packages from a post-setup hook. Strategy (in order): @@ -584,7 +585,7 @@ def _pip_install( (or the last failure for the caller to inspect). """ venv_root = Path(sys.executable).parent.parent - uv_env = {**os.environ, "VIRTUAL_ENV": str(venv_root)} + uv_env = _sanitize_subprocess_env(os.environ.copy(), {"VIRTUAL_ENV": str(venv_root)}) uv_bin = shutil.which("uv") if uv_bin: @@ -607,6 +608,7 @@ def _pip_install( probe = subprocess.run( pip_cmd + ["--version"], capture_output=True, text=True, timeout=15, + env=_sanitize_subprocess_env(os.environ.copy()), ) if probe.returncode != 0: raise FileNotFoundError("pip not in venv") @@ -615,6 +617,7 @@ def _pip_install( subprocess.run( [sys.executable, "-m", "ensurepip", "--upgrade", "--default-pip"], capture_output=True, text=True, timeout=120, check=True, + env=_sanitize_subprocess_env(os.environ.copy()), ) except (subprocess.CalledProcessError, subprocess.TimeoutExpired) as e: # Synthesize a result so callers see a clean failure path. @@ -626,12 +629,14 @@ def _pip_install( return subprocess.run( pip_cmd + ["install", *args], capture_output=capture_output, text=True, timeout=timeout, + env=_sanitize_subprocess_env(os.environ.copy()), ) def _run_post_setup(post_setup_key: str): """Run post-setup hooks for tools that need extra installation steps.""" import shutil + from tools.environments.local import _sanitize_subprocess_env if post_setup_key in {"agent_browser", "browserbase"}: node_modules = PROJECT_ROOT / "node_modules" / "agent-browser" npm_bin = shutil.which("npm") @@ -646,7 +651,8 @@ def _run_post_setup(post_setup_key: str): # behaviour as before. result = subprocess.run( [npm_bin, "install", "--silent"], - capture_output=True, text=True, cwd=str(PROJECT_ROOT) + capture_output=True, text=True, cwd=str(PROJECT_ROOT), + env=_sanitize_subprocess_env(os.environ.copy()), ) if result.returncode == 0: _print_success(" Node.js dependencies installed") @@ -722,6 +728,7 @@ def _run_post_setup(post_setup_key: str): result = subprocess.run( install_cmd, capture_output=True, text=True, cwd=str(PROJECT_ROOT), timeout=600, + env=_sanitize_subprocess_env(os.environ.copy()), ) if result.returncode == 0: _print_success(" Chromium installed") @@ -751,7 +758,8 @@ def _run_post_setup(post_setup_key: str): # Absolute npm path so .cmd shim executes on Windows. result = subprocess.run( [_npm_bin, "install", "--silent"], - capture_output=True, text=True, cwd=str(PROJECT_ROOT) + capture_output=True, text=True, cwd=str(PROJECT_ROOT), + env=_sanitize_subprocess_env(os.environ.copy()), ) if result.returncode == 0: _print_success(" Camofox installed") @@ -779,6 +787,7 @@ def _run_post_setup(post_setup_key: str): version = subprocess.run( ["cua-driver", "--version"], capture_output=True, text=True, timeout=5, + env=_sanitize_subprocess_env(os.environ.copy()), ).stdout.strip() _print_success(f" cua-driver already installed: {version or 'unknown version'}") except Exception: @@ -798,7 +807,12 @@ def _run_post_setup(post_setup_key: str): "https://raw.githubusercontent.com/trycua/cua/main/" "libs/cua-driver/scripts/install.sh)\"" ) - result = subprocess.run(install_cmd, shell=True, timeout=300) + result = subprocess.run( + install_cmd, + shell=True, + timeout=300, + env=_sanitize_subprocess_env(os.environ.copy()), + ) if result.returncode == 0 and shutil.which("cua-driver"): _print_success(" cua-driver installed.") _print_info(" IMPORTANT — grant macOS permissions now:")