Summary
agent-comms@1.24.0 (current latest on npm) crashes on every invocation, before doing any work. The web UI server module reads its static assets from disk at module-load time, but those files are never copied into the published package. Because the reads happen at the top level of server.js, the crash occurs on import, taking down even unrelated commands like bare agent-comms (setup).
Reproduction
$ npm i -g agent-comms # 1.24.0
$ agent-comms
node:fs:539
return binding.readFileSync(path, stringToFlags(options.flag));
^
Error: ENOENT: no such file or directory, open '/opt/homebrew/lib/node_modules/agent-comms/dist/bridges/user/web/frontend/index.html'
at Module.readFileSync (node:fs:539:20)
at file:///opt/homebrew/lib/node_modules/agent-comms/dist/bridges/user/web/server.js:30:23
...
errno: -2, code: 'ENOENT', syscall: 'open',
path: '.../dist/bridges/user/web/frontend/index.html'
npx agent-comms fails identically.
Root cause — a missing build step, not a code bug
server.ts correctly reads the frontend assets at module scope:
const INDEX_HTML = fs.readFileSync(path.join(__dirname, "frontend", "index.html"), "utf-8");
const BUNDLE_JS = fs.readFileSync(path.join(__dirname, "dist", "bundle.js"), "utf-8");
const SW_JS = fs.readFileSync(path.join(__dirname, "dist", "sw.js"), "utf-8");
const MANIFEST_JSON = fs.readFileSync(path.join(__dirname, "dist", "manifest.json"), "utf-8");
const ICONS = { ... loadIcon("icon-96x96.svg") ... }; // dist/icons/*
At runtime __dirname is dist/bridges/user/web/, so it expects:
dist/bridges/user/web/frontend/index.html
dist/bridges/user/web/dist/{bundle.js, sw.js, manifest.json, mesh-worker.js, relay-worker.js}
dist/bridges/user/web/dist/icons/*
None of these exist in the published tarball. Here's why:
index.html is a static source file at src/bridges/user/web/frontend/index.html.
build:frontend (tsx src/bridges/user/web/build.ts, esbuild) emits the bundles + copies the manifest/icons into src/bridges/user/web/dist/.
tsc has rootDir: src, outDir: dist and only emits JS/.d.ts from .ts inputs. It does not copy .html, esbuild-produced .js, .json, or .svg assets into dist/.
So the assets are built under src/… but never make it into the compiled dist/… tree that ships. "files": ["dist", …] then publishes a dist/ that is missing them.
Confirmation the assets are absent from the installed package:
$ ls dist/bridges/user/web/dist
ls: .../dist/bridges/user/web/dist: No such file or directory
$ find node_modules/agent-comms -name index.html
# (nothing)
Note on generated-html.ts
The package also ships dist/bridges/user/web/generated-html.js, which exports the whole frontend inlined as a single FRONTEND_HTML constant — but nothing imports it, and it appears to be a stale artifact predating the current Preact frontend (its inlined UI differs from frontend/index.html + main.tsx). It's a tempting fallback for INDEX_HTML, but using it would serve an outdated UI, so it is not the right fix.
Fix
Copy the web assets into the compiled dist/ tree after tsc, so the current frontend ships intact. Minimal change: a post-tsc copy step wired into the build script.
// scripts/copy-web-assets.ts — copies:
// src/bridges/user/web/frontend/index.html -> dist/bridges/user/web/frontend/index.html
// src/bridges/user/web/dist/** -> dist/bridges/user/web/dist/**
Verified locally: after this change pnpm run build produces all assets under dist/bridges/user/web/, import('./dist/bridges/user/web/server.js') no longer throws, and npm pack --dry-run includes frontend/index.html, dist/bundle.js, dist/sw.js, dist/manifest.json, and dist/icons/*.
PR to follow.
Environment
- agent-comms 1.24.0 (npm
latest)
- Node.js v26.4.0
- macOS (arm64), global install via Homebrew npm prefix
Summary
agent-comms@1.24.0(currentlateston npm) crashes on every invocation, before doing any work. The web UI server module reads its static assets from disk at module-load time, but those files are never copied into the published package. Because the reads happen at the top level ofserver.js, the crash occurs onimport, taking down even unrelated commands like bareagent-comms(setup).Reproduction
npx agent-commsfails identically.Root cause — a missing build step, not a code bug
server.tscorrectly reads the frontend assets at module scope:At runtime
__dirnameisdist/bridges/user/web/, so it expects:dist/bridges/user/web/frontend/index.htmldist/bridges/user/web/dist/{bundle.js, sw.js, manifest.json, mesh-worker.js, relay-worker.js}dist/bridges/user/web/dist/icons/*None of these exist in the published tarball. Here's why:
index.htmlis a static source file atsrc/bridges/user/web/frontend/index.html.build:frontend(tsx src/bridges/user/web/build.ts, esbuild) emits the bundles + copies the manifest/icons intosrc/bridges/user/web/dist/.tschasrootDir: src,outDir: distand only emits JS/.d.tsfrom.tsinputs. It does not copy.html, esbuild-produced.js,.json, or.svgassets intodist/.So the assets are built under
src/…but never make it into the compileddist/…tree that ships."files": ["dist", …]then publishes adist/that is missing them.Confirmation the assets are absent from the installed package:
Note on
generated-html.tsThe package also ships
dist/bridges/user/web/generated-html.js, which exports the whole frontend inlined as a singleFRONTEND_HTMLconstant — but nothing imports it, and it appears to be a stale artifact predating the current Preact frontend (its inlined UI differs fromfrontend/index.html+main.tsx). It's a tempting fallback forINDEX_HTML, but using it would serve an outdated UI, so it is not the right fix.Fix
Copy the web assets into the compiled
dist/tree aftertsc, so the current frontend ships intact. Minimal change: a post-tsccopy step wired into thebuildscript.Verified locally: after this change
pnpm run buildproduces all assets underdist/bridges/user/web/,import('./dist/bridges/user/web/server.js')no longer throws, andnpm pack --dry-runincludesfrontend/index.html,dist/bundle.js,dist/sw.js,dist/manifest.json, anddist/icons/*.PR to follow.
Environment
latest)