mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-09 08:21:50 +00:00
A packaged desktop app launches to a blank page with a bare ERR_FILE_NOT_FOUND when dist/index.html isn't in the bundle (#39484). This happens when the build step fails (e.g. a stale checkout that fails typecheck) but electron-builder packages anyway, shipping an empty dist/. - build-time: scripts/assert-dist-built.cjs runs at the tail of the `build` script and aborts before electron-builder if dist/index.html or the vite JS bundle is missing/empty. Every packaging path (pack, dist*) inherits it via `npm run build &&`. - runtime: resolveRendererIndex() now logs a clear 'packaged without a renderer bundle — rebuild with hermes desktop --force-build' message when no index.html exists, instead of silently loading a missing path. - runtime: resolveWebDist() logs when it falls back to an asar-internal dist that isn't a real directory (the dashboard 404 class, #41327/#39472), rather than returning an unservable path silently. Adds scripts/assert-dist-built.test.cjs (node:test) covering the guard.
70 lines
2.7 KiB
JavaScript
70 lines
2.7 KiB
JavaScript
"use strict"
|
|
|
|
// Build-time guard: refuse to hand a half-built renderer to electron-builder.
|
|
//
|
|
// `npm run pack` / `npm run dist*` are `npm run build && npm run builder`.
|
|
// If the `build` step (tsc -b && vite build) fails but packaging proceeds
|
|
// anyway — a stale checkout that fails typecheck, an interrupted vite build,
|
|
// or npm not short-circuiting `&&` in some shells — electron-builder happily
|
|
// packages an app with an empty or missing `dist/`. The result launches but
|
|
// blank-pages with `ERR_FILE_NOT_FOUND` for dist/index.html, with no clue why.
|
|
//
|
|
// This runs at the tail of `build`, after vite build, so any packaging path
|
|
// inherits it. It fails loud and early instead of shipping a broken bundle.
|
|
// See issues #39484 (renderer blank page) and #41327 / #39472 (dashboard 404).
|
|
|
|
const fs = require("fs")
|
|
const path = require("path")
|
|
|
|
// Pure check — returns { ok: true } or { ok: false, error: "..." }.
|
|
// Kept side-effect-free so it can be unit tested without spawning a process.
|
|
function checkDistBuilt(distDir) {
|
|
if (!fs.existsSync(distDir) || !fs.statSync(distDir).isDirectory()) {
|
|
return { ok: false, error: `no dist directory at ${distDir}` }
|
|
}
|
|
|
|
const indexHtml = path.join(distDir, "index.html")
|
|
if (!fs.existsSync(indexHtml) || !fs.statSync(indexHtml).isFile()) {
|
|
return { ok: false, error: `dist/index.html is missing at ${indexHtml}` }
|
|
}
|
|
if (fs.statSync(indexHtml).size === 0) {
|
|
return { ok: false, error: `dist/index.html is empty at ${indexHtml}` }
|
|
}
|
|
|
|
// index.html alone isn't enough — vite emits hashed JS into dist/assets.
|
|
// An index.html with no script bundle still blank-pages.
|
|
const assetsDir = path.join(distDir, "assets")
|
|
const hasAssets =
|
|
fs.existsSync(assetsDir) &&
|
|
fs.statSync(assetsDir).isDirectory() &&
|
|
fs.readdirSync(assetsDir).some(name => name.endsWith(".js"))
|
|
if (!hasAssets) {
|
|
return { ok: false, error: `dist/assets has no built JS bundle (expected vite output under ${assetsDir})` }
|
|
}
|
|
|
|
return { ok: true }
|
|
}
|
|
|
|
function main() {
|
|
const desktopRoot = path.resolve(__dirname, "..")
|
|
const distDir = path.join(desktopRoot, "dist")
|
|
const result = checkDistBuilt(distDir)
|
|
|
|
if (!result.ok) {
|
|
console.error(`\n✗ assert-dist-built: ${result.error}`)
|
|
console.error(" The renderer bundle is missing or incomplete, so packaging")
|
|
console.error(" would produce an app that launches to a blank page.")
|
|
console.error(" Re-run the build and check the tsc/vite output above for the")
|
|
console.error(" real failure, then package again:")
|
|
console.error(` cd ${desktopRoot} && npm run build\n`)
|
|
process.exit(1)
|
|
}
|
|
|
|
console.log("✓ assert-dist-built: dist/index.html + assets present")
|
|
}
|
|
|
|
if (require.main === module) {
|
|
main()
|
|
}
|
|
|
|
module.exports = { checkDistBuilt }
|