Skip to content

fix(cli): skip web UI rebuild when dist/ is present and sources are unchanged#14914

Closed
nftpoetrist wants to merge 1 commit into
NousResearch:mainfrom
nftpoetrist:fix/issue-14898-web-ui-skip-rebuild-when-fresh
Closed

fix(cli): skip web UI rebuild when dist/ is present and sources are unchanged#14914
nftpoetrist wants to merge 1 commit into
NousResearch:mainfrom
nftpoetrist:fix/issue-14898-web-ui-skip-rebuild-when-fresh

Conversation

@nftpoetrist

Copy link
Copy Markdown
Contributor

What does this PR do?

`_build_web_ui()` ran `npm install` + `npm run build` unconditionally on every `hermes dashboard` startup. On low-memory hosts (≤1GB RAM) the Node build process peaked at ~388MB and was OOM-killed by systemd before the server could start. Docker installs hit the same root cause when overlayfs blocked `npm install` on a read-only layer.

Parity fix: adds `_web_ui_build_needed()` that mirrors the mtime-based staleness check already used by `_tui_build_needed()` for the TUI. The Vite manifest (`dist/.vite/manifest.json`) is used as the sentinel — it is written last and therefore has the newest mtime of any build artifact. Falls back to `dist/index.html` for older builds. Rebuild is triggered when any tracked source file (`.ts`, `.tsx`, `.js`, `.jsx`, `.css`, `.html`, `.vue`) or dependency manifest (`package.json`, `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, `vite.config.*`) is newer than the sentinel. When `dist/` is absent the existing build path runs unchanged.

Related Issue

Fixes #14898
Fixes #12243

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor
  • 🎯 New skill

Changes Made

  • `hermes_cli/main.py`: add `_web_ui_build_needed(web_dir)` (+33 lines); add early-return guard in `_build_web_ui()` (+2 lines)
  • `tests/hermes_cli/test_web_ui_build.py`: 9 tests covering missing dist, stale sources, fresh dist, sentinel fallback, lockfile changes, vite config changes, node_modules exclusion, npm skip, npm run (+110 lines, new file)

How to Test

pytest tests/hermes_cli/test_web_ui_build.py -v

All 9 tests pass. To verify end-to-end: run `hermes dashboard` once to build, then run again — the second startup should skip the npm build entirely.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix
  • I've run pytest tests/hermes_cli/test_web_ui_build.py -v and all 9 tests pass
  • I've added tests for my changes
  • I've tested on my platform: macOS

Documentation & Housekeeping

  • I've updated relevant documentation — or N/A
  • I've updated `cli-config.yaml.example` — or N/A
  • I've updated `CONTRIBUTING.md` or `AGENTS.md` — or N/A
  • I've considered cross-platform impact — fix uses `os.walk` + `pathlib.Path`, cross-platform safe
  • I've updated tool descriptions/schemas — or N/A

…nchanged

_build_web_ui() ran npm install + npm run build unconditionally on every
hermes dashboard startup. On low-memory hosts (≤1GB RAM) the Node build
process peaked at ~388MB and was OOM-killed by systemd before the server
could start. Docker installs hit the same root cause when overlayfs
blocked the npm install on a read-only layer.

Adds _web_ui_build_needed() that mirrors the mtime-based staleness check
already used by _tui_build_needed() for the TUI. The Vite manifest
(dist/.vite/manifest.json) is used as the sentinel — it is written last
and therefore has the newest mtime of any build artifact. Falls back to
dist/index.html for older builds. Rebuild is triggered when any tracked
source file (.ts, .tsx, .js, .jsx, .css, .html, .vue) or dependency
manifest (package.json, package-lock.json, yarn.lock, pnpm-lock.yaml,
vite.config.*) is newer than the sentinel.

Fixes NousResearch#14898
Fixes NousResearch#12243
@alt-glitch alt-glitch added type/perf Performance improvement or optimization P2 Medium — degraded but workaround exists comp/cli CLI entry point, hermes_cli/, setup wizard labels Apr 24, 2026
teknium1 pushed a commit that referenced this pull request Apr 27, 2026
_web_ui_build_needed() in PR #14914 checked web_dir/"dist" as the
sentinel, but vite.config.ts sets outDir: "../hermes_cli/web_dist" so
the build output lands in hermes_cli/web_dist/, never in web/dist/.
The sentinel was therefore always missing → _web_ui_build_needed always
returned True → npm install + Vite build ran on every startup → OOM on
low-memory VPS persisted unchanged.

Fix: derive dist_dir as web_dir.parent / "hermes_cli" / "web_dist" so
the sentinel points to the actual build output directory.

Fixes #14898
@teknium1

Copy link
Copy Markdown
Contributor

Superseded by #16292 (salvaged @georgeglessner's #15863). Your PR had the right idea — the mtime-based staleness check is exactly the approach — but the sentinel path was web/dist/ while Vite's outDir is ../hermes_cli/web_dist, so the check always returned True and the rebuild still ran every startup. #15863 fixed the path and added a dedicated regression test. Credit acknowledged in the salvage PR body. Thanks!

@teknium1 teknium1 closed this Apr 27, 2026
ulasbilgen pushed a commit to ulasbilgen/hermes-adhd-agent that referenced this pull request May 1, 2026
_web_ui_build_needed() in PR NousResearch#14914 checked web_dir/"dist" as the
sentinel, but vite.config.ts sets outDir: "../hermes_cli/web_dist" so
the build output lands in hermes_cli/web_dist/, never in web/dist/.
The sentinel was therefore always missing → _web_ui_build_needed always
returned True → npm install + Vite build ran on every startup → OOM on
low-memory VPS persisted unchanged.

Fix: derive dist_dir as web_dir.parent / "hermes_cli" / "web_dist" so
the sentinel points to the actual build output directory.

Fixes NousResearch#14898
donald131 pushed a commit to donald131/hermes-agent that referenced this pull request May 2, 2026
_web_ui_build_needed() in PR NousResearch#14914 checked web_dir/"dist" as the
sentinel, but vite.config.ts sets outDir: "../hermes_cli/web_dist" so
the build output lands in hermes_cli/web_dist/, never in web/dist/.
The sentinel was therefore always missing → _web_ui_build_needed always
returned True → npm install + Vite build ran on every startup → OOM on
low-memory VPS persisted unchanged.

Fix: derive dist_dir as web_dir.parent / "hermes_cli" / "web_dist" so
the sentinel points to the actual build output directory.

Fixes NousResearch#14898
02356abc pushed a commit to 02356abc/hermes-agent that referenced this pull request May 14, 2026
_web_ui_build_needed() in PR NousResearch#14914 checked web_dir/"dist" as the
sentinel, but vite.config.ts sets outDir: "../hermes_cli/web_dist" so
the build output lands in hermes_cli/web_dist/, never in web/dist/.
The sentinel was therefore always missing → _web_ui_build_needed always
returned True → npm install + Vite build ran on every startup → OOM on
low-memory VPS persisted unchanged.

Fix: derive dist_dir as web_dir.parent / "hermes_cli" / "web_dist" so
the sentinel points to the actual build output directory.

Fixes NousResearch#14898
dannyJ848 pushed a commit to dannyJ848/hermes-agent that referenced this pull request May 17, 2026
_web_ui_build_needed() in PR NousResearch#14914 checked web_dir/"dist" as the
sentinel, but vite.config.ts sets outDir: "../hermes_cli/web_dist" so
the build output lands in hermes_cli/web_dist/, never in web/dist/.
The sentinel was therefore always missing → _web_ui_build_needed always
returned True → npm install + Vite build ran on every startup → OOM on
low-memory VPS persisted unchanged.

Fix: derive dist_dir as web_dir.parent / "hermes_cli" / "web_dist" so
the sentinel points to the actual build output directory.

Fixes NousResearch#14898
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
_web_ui_build_needed() in PR NousResearch#14914 checked web_dir/"dist" as the
sentinel, but vite.config.ts sets outDir: "../hermes_cli/web_dist" so
the build output lands in hermes_cli/web_dist/, never in web/dist/.
The sentinel was therefore always missing → _web_ui_build_needed always
returned True → npm install + Vite build ran on every startup → OOM on
low-memory VPS persisted unchanged.

Fix: derive dist_dir as web_dir.parent / "hermes_cli" / "web_dist" so
the sentinel points to the actual build output directory.

Fixes NousResearch#14898
Egavasyug pushed a commit to Egavasyug/hermes-agent that referenced this pull request Jun 10, 2026
_web_ui_build_needed() in PR NousResearch#14914 checked web_dir/"dist" as the
sentinel, but vite.config.ts sets outDir: "../hermes_cli/web_dist" so
the build output lands in hermes_cli/web_dist/, never in web/dist/.
The sentinel was therefore always missing → _web_ui_build_needed always
returned True → npm install + Vite build ran on every startup → OOM on
low-memory VPS persisted unchanged.

Fix: derive dist_dir as web_dir.parent / "hermes_cli" / "web_dist" so
the sentinel points to the actual build output directory.

Fixes NousResearch#14898
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 P2 Medium — degraded but workaround exists type/perf Performance improvement or optimization

Projects

None yet

3 participants