mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-09 08:21:50 +00:00
fix(install): scope npm installs/audits to avoid pulling in apps/desktop
Root package.json uses apps/* workspaces glob which unconditionally
includes apps/desktop (Electron + node-pty@1.1.0, ~200MB, requires
make/g++ to build) in every unscoped npm command run from the repo root.
This commit addresses the core problem by adding explicit workspace
scoping to all internal npm calls:
hermes_cli/main.py (_build_web_ui):
- Add --workspace web to the npm install call so only the web
workspace deps are resolved, never apps/desktop.
hermes_cli/tools_config.py:
- Add --workspaces=false to agent-browser and Camofox root installs
so only root-level deps (agent-browser, @streamdown/math) are
installed, bypassing the workspace graph entirely.
hermes_cli/doctor.py (run_doctor npm audit):
- Replace the single unscoped 'npm audit --json' at PROJECT_ROOT with
three scoped invocations:
* --workspaces=false for root deps (Browser tools)
* --workspace web for the web workspace
* --workspace ui-tui for the TUI workspace
- Update remediation hints to use matching scoped 'npm audit fix'
commands so users don't accidentally trigger a desktop rebuild.
package.json:
- Add convenience scripts for scoped operations:
npm run install:root / install:web / install:tui / install:desktop
npm run audit:root / audit:web / audit:tui
npm run audit:fix:root / audit:fix:web / audit:fix:tui
These give developers and CI a safe, explicit interface for the
most common per-workspace tasks without accidentally pulling desktop.
Fixes #38772
This commit is contained in:
parent
d165933c56
commit
1c0437dfc5
4 changed files with 50 additions and 13 deletions
|
|
@ -1454,18 +1454,29 @@ def run_doctor(args):
|
|||
# npm audit for all Node.js packages
|
||||
_npm_bin = _safe_which("npm")
|
||||
if _npm_bin:
|
||||
npm_dirs = [
|
||||
(PROJECT_ROOT, "Browser tools (agent-browser)"),
|
||||
(PROJECT_ROOT / "scripts" / "whatsapp-bridge", "WhatsApp bridge"),
|
||||
# Each entry: (cwd, label, extra_audit_args)
|
||||
# PROJECT_ROOT is audited with --workspaces=false so that the apps/*
|
||||
# glob (which pulls in Electron, node-pty, etc.) is never resolved
|
||||
# for a routine security check. The web and ui-tui workspaces are
|
||||
# audited separately via --workspace flags. See #38772.
|
||||
npm_audit_targets = [
|
||||
(PROJECT_ROOT, "Browser tools (agent-browser)", ["--workspaces=false"]),
|
||||
(PROJECT_ROOT, "web workspace", ["--workspace", "web"]),
|
||||
(PROJECT_ROOT, "ui-tui workspace", ["--workspace", "ui-tui"]),
|
||||
(PROJECT_ROOT / "scripts" / "whatsapp-bridge", "WhatsApp bridge", []),
|
||||
]
|
||||
for npm_dir, label in npm_dirs:
|
||||
if not (npm_dir / "node_modules").exists():
|
||||
for npm_dir, label, audit_extra in npm_audit_targets:
|
||||
# For workspace-scoped audits run from PROJECT_ROOT the
|
||||
# node_modules check must use the workspace root; standalone dirs
|
||||
# (whatsapp-bridge) check their own node_modules.
|
||||
check_dir = npm_dir if audit_extra else npm_dir
|
||||
if not (check_dir / "node_modules").exists():
|
||||
continue
|
||||
try:
|
||||
# Use resolved absolute path so Windows can execute
|
||||
# npm.cmd (CreateProcessW can't run bare .cmd names).
|
||||
audit_result = subprocess.run(
|
||||
[_npm_bin, "audit", "--json"],
|
||||
[_npm_bin, "audit", "--json", *audit_extra],
|
||||
cwd=str(npm_dir),
|
||||
capture_output=True, text=True, timeout=30,
|
||||
)
|
||||
|
|
@ -1476,12 +1487,20 @@ def run_doctor(args):
|
|||
high = vuln_count.get("high", 0)
|
||||
moderate = vuln_count.get("moderate", 0)
|
||||
total = critical + high + moderate
|
||||
# Determine a scoped fix command for the remediation hint.
|
||||
if audit_extra and audit_extra[0] == "--workspace":
|
||||
fix_scope = " ".join(audit_extra)
|
||||
fix_cmd = f"cd {npm_dir} && npm audit fix {fix_scope}"
|
||||
elif audit_extra == ["--workspaces=false"]:
|
||||
fix_cmd = f"cd {npm_dir} && npm audit fix --workspaces=false"
|
||||
else:
|
||||
fix_cmd = f"cd {npm_dir} && npm audit fix"
|
||||
if total == 0:
|
||||
check_ok(f"{label} deps", "(no known vulnerabilities)")
|
||||
elif critical > 0 or high > 0:
|
||||
check_warn(
|
||||
f"{label} deps",
|
||||
f"({critical} critical, {high} high, {moderate} moderate — run: cd {npm_dir} && npm audit fix)"
|
||||
f"({critical} critical, {high} high, {moderate} moderate — run: {fix_cmd})"
|
||||
)
|
||||
issues.append(
|
||||
f"{label} has {total} npm "
|
||||
|
|
|
|||
|
|
@ -7090,7 +7090,11 @@ def _build_web_ui(web_dir: Path, *, fatal: bool = False) -> bool:
|
|||
_say(text)
|
||||
|
||||
npm_cwd = _workspace_root(web_dir)
|
||||
npm_workspace_args: tuple[str, ...] = ()
|
||||
# Scope the install to the web workspace only so that the full workspace
|
||||
# graph (including apps/desktop with its Electron + node-pty deps) is never
|
||||
# resolved here. Without --workspace the root package.json's apps/* glob
|
||||
# would pull in desktop on every web build. See #38772.
|
||||
npm_workspace_args: tuple[str, ...] = ("--workspace", "web")
|
||||
if _is_termux_startup_environment():
|
||||
npm_cwd, npm_workspace_args = _termux_workspace_install_context(web_dir)
|
||||
r1 = _run_npm_install_deterministic(
|
||||
|
|
|
|||
|
|
@ -846,14 +846,17 @@ def _run_post_setup(post_setup_key: str):
|
|||
# batch shims). On POSIX npm_bin is the plain path — same
|
||||
# behaviour as before.
|
||||
result = subprocess.run(
|
||||
[npm_bin, "install", "--silent"],
|
||||
# --workspaces=false restricts the install to the repo root
|
||||
# only, avoiding the apps/* glob which would pull in
|
||||
# apps/desktop (Electron + node-pty) unnecessarily. See #38772.
|
||||
[npm_bin, "install", "--silent", "--workspaces=false"],
|
||||
capture_output=True, text=True, cwd=str(PROJECT_ROOT)
|
||||
)
|
||||
if result.returncode == 0:
|
||||
_print_success(" Node.js dependencies installed")
|
||||
else:
|
||||
from hermes_constants import display_hermes_home
|
||||
_print_warning(f" npm install failed - run manually: cd {display_hermes_home()}/hermes-agent && npm install")
|
||||
_print_warning(f" npm install failed - run manually: cd {display_hermes_home()}/hermes-agent && npm install --workspaces=false")
|
||||
if result.stderr:
|
||||
_print_info(f" {result.stderr.strip()[:200]}")
|
||||
elif not node_modules.exists():
|
||||
|
|
@ -951,13 +954,14 @@ def _run_post_setup(post_setup_key: str):
|
|||
import subprocess
|
||||
# Absolute npm path so .cmd shim executes on Windows.
|
||||
result = subprocess.run(
|
||||
[_npm_bin, "install", "--silent"],
|
||||
# --workspaces=false avoids resolving apps/desktop. See #38772.
|
||||
[_npm_bin, "install", "--silent", "--workspaces=false"],
|
||||
capture_output=True, text=True, cwd=str(PROJECT_ROOT)
|
||||
)
|
||||
if result.returncode == 0:
|
||||
_print_success(" Camofox installed")
|
||||
else:
|
||||
_print_warning(" npm install failed - run manually: npm install")
|
||||
_print_warning(" npm install failed - run manually: npm install --workspaces=false")
|
||||
if camofox_dir.exists():
|
||||
_print_info(" Start the Camofox server:")
|
||||
_print_info(" npx @askjo/camofox-browser")
|
||||
|
|
|
|||
12
package.json
12
package.json
|
|
@ -10,7 +10,17 @@
|
|||
"web"
|
||||
],
|
||||
"scripts": {
|
||||
"postinstall": "echo '✅ Browser tools ready. Run: python run_agent.py --help'"
|
||||
"postinstall": "echo '✅ Browser tools ready. Run: python run_agent.py --help'",
|
||||
"install:root": "npm install --workspaces=false",
|
||||
"install:web": "npm install --workspace web",
|
||||
"install:tui": "npm install --workspace ui-tui",
|
||||
"install:desktop": "npm install --workspace apps/desktop",
|
||||
"audit:root": "npm audit --workspaces=false",
|
||||
"audit:web": "npm audit --workspace web",
|
||||
"audit:tui": "npm audit --workspace ui-tui",
|
||||
"audit:fix:root": "npm audit fix --workspaces=false",
|
||||
"audit:fix:web": "npm audit fix --workspace web",
|
||||
"audit:fix:tui": "npm audit fix --workspace ui-tui"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue