Skip to content
Closed
Show file tree
Hide file tree
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
11 changes: 9 additions & 2 deletions hermes_cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -6269,17 +6269,24 @@ def _update_node_dependencies() -> None:
if not (path / "package.json").exists():
continue

# Stream npm output (no `--silent`, no `capture_output`) so optional
# dependency postinstall scripts — e.g. `@askjo/camofox-browser`'s
# `npx camoufox-js fetch` browser-binary download — print progress
# instead of appearing to hang silently for minutes (#18840). The
# `_UpdateOutputStream` wrapper installed by the updater mirrors
# streamed output to ``~/.hermes/logs/update.log`` so nothing is lost.
Comment on lines +6275 to +6277
result = _run_npm_install_deterministic(
npm,
path,
extra_args=("--silent", "--no-fund", "--no-audit", "--progress=false"),
extra_args=("--no-fund", "--no-audit", "--progress=false"),
capture_output=False,
)
if result.returncode == 0:
print(f" ✓ {label}")
continue

print(f" ⚠ npm install failed in {label}")
stderr = (result.stderr or "").strip()
stderr = (result.stderr or "").strip() if result.stderr else ""
if stderr:
print(f" {stderr.splitlines()[-1]}")

Expand Down
30 changes: 26 additions & 4 deletions tests/hermes_cli/test_cmd_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,21 +128,43 @@ def test_update_refreshes_repo_and_tui_node_dependencies(
# 1. repo root — slash-command / TUI bridge deps
# 2. ui-tui/ — Ink TUI deps
# 3. web/ — install + "npm run build" for the web frontend
full_flags = [
#
# Repo-root and ui-tui installs intentionally omit `--silent` and run
# without `capture_output` so optional postinstall scripts (e.g.
# `@askjo/camofox-browser`'s browser-binary fetch) print progress —
# otherwise long downloads look like a hang (#18840). The web/ install
# keeps `--silent` because its build step is short and noisy.
update_flags = [
"/usr/bin/npm",
"ci",
"--silent",
"--no-fund",
"--no-audit",
"--progress=false",
]
assert npm_calls == [
(full_flags, PROJECT_ROOT),
(full_flags, PROJECT_ROOT / "ui-tui"),
(update_flags, PROJECT_ROOT),
(update_flags, PROJECT_ROOT / "ui-tui"),
(["/usr/bin/npm", "ci", "--silent"], PROJECT_ROOT / "web"),
(["/usr/bin/npm", "run", "build"], PROJECT_ROOT / "web"),
]

# Regression for #18840: repo root + ui-tui installs must stream output
# (capture_output=False) so postinstall progress is visible to the user.
repo_and_tui_calls = [
call
for call in mock_run.call_args_list
if call.args
and call.args[0][0] == "/usr/bin/npm"
and call.args[0][1] == "ci"
and call.kwargs.get("cwd") in (PROJECT_ROOT, PROJECT_ROOT / "ui-tui")
]
assert len(repo_and_tui_calls) == 2
for call in repo_and_tui_calls:
assert call.kwargs.get("capture_output") is False, (
"repo-root / ui-tui npm install must stream output "
"(no capture_output) so Camofox postinstall progress is visible"
)

def test_update_non_interactive_skips_migration_prompt(self, mock_args, capsys):
"""When stdin/stdout aren't TTYs, config migration prompt is skipped."""
with patch("shutil.which", return_value=None), patch(
Expand Down
Loading