Skip to content

agent-comms crashes on launch (ENOENT): web frontend assets are built under src/ but never copied into the published dist/ #18

Description

@zico-io

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.

// package.json
"build": "pnpm build:frontend && tsc && tsx scripts/copy-web-assets.ts && printf ... "
// 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions