From 6f2ef986b81430042538d73b9787f6d5e910f6b4 Mon Sep 17 00:00:00 2001 From: zico-io Date: Tue, 7 Jul 2026 13:23:08 -0400 Subject: [PATCH] fix(build): publish web frontend assets so the CLI doesn't crash on launch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The web server reads its frontend assets (frontend/index.html and the esbuild bundles under dist/) from disk at module load. Those assets are built under src/bridges/user/web/, but tsc (rootDir: src) only emits from .ts inputs, so they were never copied into the published dist/ tree. As a result every invocation — including bare `agent-comms` (setup) — crashed with ENOENT before doing any work. Add a post-tsc copy step (scripts/copy-web-assets.ts) that copies index.html and the esbuild output into dist/bridges/user/web/, and clean the esbuild output dir at the start of build:frontend so stale artifacts can't be swept into the package. Fixes #18 Co-Authored-By: Claude Opus 4.8 (1M context) --- package.json | 2 +- scripts/copy-web-assets.ts | 35 +++++++++++++++++++++++++++++++++++ src/bridges/user/web/build.ts | 4 ++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 scripts/copy-web-assets.ts diff --git a/package.json b/package.json index 08b0ebf..ef28ef1 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "scripts": { "prepare": "husky", "build:frontend": "tsx src/bridges/user/web/build.ts", - "build": "pnpm build:frontend && tsc && printf '#!/usr/bin/env node\n' | cat - dist/cli.js > dist/cli.tmp && mv dist/cli.tmp dist/cli.js", + "build": "pnpm build:frontend && tsc && tsx scripts/copy-web-assets.ts && printf '#!/usr/bin/env node\n' | cat - dist/cli.js > dist/cli.tmp && mv dist/cli.tmp dist/cli.js", "generate:server-json": "tsx scripts/sync-release-metadata.ts", "publish:mcp-registry": "tsx scripts/publish-mcp-registry.ts", "lint": "eslint .", diff --git a/scripts/copy-web-assets.ts b/scripts/copy-web-assets.ts new file mode 100644 index 0000000..d9c2210 --- /dev/null +++ b/scripts/copy-web-assets.ts @@ -0,0 +1,35 @@ +/** + * Copy the built web frontend assets into the compiled output tree. + * + * `build:frontend` (esbuild) emits the bundles into + * `src/bridges/user/web/dist/`, and `index.html` lives alongside the frontend + * sources. `tsc` only emits JS/d.ts from `.ts` inputs, so these non-TS assets + * are never copied into the top-level `dist/`. Without this step the published + * package is missing `frontend/index.html`, `dist/bundle.js`, `dist/sw.js`, + * `dist/manifest.json` and `dist/icons/*`, and the web server crashes with + * ENOENT at module load — taking down every command, including setup. See #18. + * + * Usage: node/tsx scripts/copy-web-assets.ts (run after `tsc`) + */ + +import * as fs from "node:fs"; +import * as path from "node:path"; +import { fileURLToPath } from "node:url"; + +const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +const webSrc = path.join(root, "src", "bridges", "user", "web"); +const webOut = path.join(root, "dist", "bridges", "user", "web"); + +// Frontend shell (loaded by the server as INDEX_HTML). cpSync creates the +// destination parent dir itself. +fs.cpSync( + path.join(webSrc, "frontend", "index.html"), + path.join(webOut, "frontend", "index.html"), +); + +// esbuild bundles + web app manifest + PWA icons. +fs.cpSync(path.join(webSrc, "dist"), path.join(webOut, "dist"), { + recursive: true, +}); + +console.log(`Copied web assets to ${webOut}`); diff --git a/src/bridges/user/web/build.ts b/src/bridges/user/web/build.ts index 71f7d2e..753c5d9 100644 --- a/src/bridges/user/web/build.ts +++ b/src/bridges/user/web/build.ts @@ -44,6 +44,10 @@ const inlineCssPlugin: esbuild.Plugin = { }; async function main(): Promise { + // Start from a clean output dir so stale artifacts (e.g. renamed bundles, + // leftover sourcemaps) can't linger and get swept into the published + // package by the copy-web-assets step. + fs.rmSync(DIST_DIR, { recursive: true, force: true }); fs.mkdirSync(DIST_DIR, { recursive: true }); await esbuild.build({