Skip to content

fix(cli): fall back to prebuilt TUI bundle when npm fails - #40694

Closed
chronikion wants to merge 1 commit into
NousResearch:mainfrom
chronikion:fix/tui-prebuilt-fallback
Closed

fix(cli): fall back to prebuilt TUI bundle when npm fails#40694
chronikion wants to merge 1 commit into
NousResearch:mainfrom
chronikion:fix/tui-prebuilt-fallback

Conversation

@chronikion

@chronikion chronikion commented Jun 6, 2026

Copy link
Copy Markdown

What changes:

Make hermes --tui launch from the prebuilt dist/entry.js bundle when npm install fails on certain Linux environments.

Why would it change:

After hermes update, npm install fails with "Exit handler never called!". The crash causes npm to return non-zero. The existing launcher prints "npm install failed" and calls sys.exit(1).

At first iteration, fix tried a different approach — modifying _tui_need_npm_install() to skip npm when the prebuilt bundle existed and .package-lock.json was missing. That failed: hermes update writes .package-lock.json during its own npm install, before npm crashes on teardown. After next hermes update, hermes --tui, .package-lock.json was present, npm was called again, npm failed again, and the fix's filesystem heuristic never engaged.

How does it change?:

A single targeted change in hermes_cli/main.py, inside _make_tui_argv's existing result.returncode != 0 branch — no heuristics, no guessing. Let npm install run normally. When it actually fails:

  • dist/entry.js exists → print "npm install failed; falling back to prebuilt bundle" with the npm error preview, set npm_install_failed = True, continue.
  • dist/entry.js missing → print "npm install failed" and sys.exit(1) (historical fail-fast, unchanged).

A follow-up guard if should_build and npm_install_failed: should_build = False skips the esbuild rebuild (which would also fail — node_modules/esbuild was never installed).

The new branch only fires when result.returncode != 0 — npm actually failed. Observation-based, not prediction-based:

  • Fresh git clone: npm install runs normally, succeeds, esbuild rebuild runs. Unchanged.
  • Up-to-date install: _tui_need_npm_install() returns False, no npm install, only esbuild rebuild. Unchanged.
  • Termux cold start: termux_need_rebuild check and Termux-specific paths run as before. Unchanged.
  • npm crashes (Rocky 9): was sys.exit(1), now falls back to prebuilt bundle and skips esbuild. New behaviour, gated on actual failure.

How to verify:

  1. Before this fix: On Rocky Linux 9 (or any environment where npm teardown crashes), hermes --tui fails with "npm install failed" after every hermes update.
  2. After this fix: hermes --tui launches from the prebuilt bundle. The user sees "npm install failed; falling back to prebuilt bundle" with the npm error preview, then the TUI starts.

Tests:

  • tests/hermes_cli/test_tui_npm_install.py28 passed, 0 failed (3 new: fallback fires on npm fail, no fallback without prebuilt, build still runs when npm succeeds)
  • tests/hermes_cli/test_tui_resume_flow.py45 passed, 0 failed
  • All 73 tests across both suites pass.

Platforms tested:

  • Rocky Linux 9.7 (kernel 5.14, glibc 2.34), Python 3.11.15

Related:

  • PR #37923 — Docker counterpart (merged): sets HERMES_TUI_DIR for prebuilt path. Author explicitly deferred bare-metal "launcher hardening" as "tracked independently." This PR is that deferred work.
  • PR #18036 — esbuild bundle foundation (merged): the prebuilt dist/entry.js that makes this fallback possible.
  • PR #40543 — npm install workspace scoping (merged): complementary fix that avoids pulling apps/desktop.
  • Issue #30271 — WSL Windows npm resolution failure (open): same failure class. The prebuilt-fallback mechanism would also recover this case.
  • Issue #34312 — post-update node_modules breakage (open): same pattern of npm producing a broken tree after update.
  • Issue #20739 — Docker TUI bugs (open): overlapping failure surface, especially the staleness-check bug (Fix terminal interactivity #4).

@chronikion
chronikion force-pushed the fix/tui-prebuilt-fallback branch from d77cd01 to 1c03422 Compare June 6, 2026 18:03
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/cli CLI entry point, hermes_cli/, setup wizard comp/tui Terminal UI (ui-tui/ + tui_gateway/) labels Jun 6, 2026
@chronikion
chronikion force-pushed the fix/tui-prebuilt-fallback branch from 1c03422 to 2a9f0ca Compare June 8, 2026 22:45
When hermes update leaves npm in a crashed state (e.g. Rocky 9 teardown
crash), the launcher's only recovery was to print the error and exit 1.
That made the TUI permanently unavailable on environments where npm
itself is broken.

The prebuilt dist/entry.js is rebuilt during hermes update, so it is
current in the common update-then-crash case.  When the install fails AND
the prebuilt bundle exists, launch it directly instead of dying.  When
the bundle is missing, keep the historical fail-fast behaviour.

Doctrine: only diverge from the historical desktop path when npm is
actually failing (result.returncode != 0).  Fresh checkouts, working
installs, and Termux cold starts are unchanged.

PR body: /home/tsu/Documents/pr-body-tui-prebuilt-fallback.md
@chronikion chronikion closed this Jun 24, 2026
@chronikion
chronikion deleted the fix/tui-prebuilt-fallback branch June 24, 2026 11:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard comp/tui Terminal UI (ui-tui/ + tui_gateway/) P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants