Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions hermes_cli/tools_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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)})
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Instead of calling _sanitize_subprocess_env(os.environ.copy()) multiple times throughout _pip_install, we can sanitize the environment once at the beginning of the function and reuse it. This avoids redundant environment copying and blocklist filtering overhead.

Suggested change
uv_env = _sanitize_subprocess_env(os.environ.copy(), {"VIRTUAL_ENV": str(venv_root)})
base_env = _sanitize_subprocess_env(os.environ.copy())
uv_env = {**base_env, "VIRTUAL_ENV": str(venv_root)}


uv_bin = shutil.which("uv")
if uv_bin:
Expand All @@ -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()),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Reuse the base_env dictionary defined at the start of the function to avoid redundant sanitization overhead.

Suggested change
env=_sanitize_subprocess_env(os.environ.copy()),
env=base_env,

)
if probe.returncode != 0:
raise FileNotFoundError("pip not in venv")
Expand All @@ -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()),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Reuse the base_env dictionary defined at the start of the function to avoid redundant sanitization overhead.

Suggested change
env=_sanitize_subprocess_env(os.environ.copy()),
env=base_env,

)
except (subprocess.CalledProcessError, subprocess.TimeoutExpired) as e:
# Synthesize a result so callers see a clean failure path.
Expand All @@ -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()),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Reuse the base_env dictionary defined at the start of the function to avoid redundant sanitization overhead.

Suggested change
env=_sanitize_subprocess_env(os.environ.copy()),
env=base_env,

)


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")
Expand All @@ -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")
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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:
Expand All @@ -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:")
Expand Down
Loading