Ctrl K
ComunidadGuías…

scripts/bundle-server.mjs

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// Bundles each harness-server entry point into a self-contained ESM file: the
// packaged app ships no node_modules. Entry points keep their exact relative
// paths under dist-server, where the server locates each proxy by path.
import { build } from "esbuild";
import { copyFileSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { dirname, join } from "node:path";
import { serverLocalePlugin } from "./server-locale-plugin.mjs";

const root = join(dirname(fileURLToPath(import.meta.url)), "..");
const server = join(root, "server");

// yaml's Node export is CommonJS with dynamic requires that cannot run once
// inlined into ESM; its browser export is the same parser without them.
const yamlEsmPlugin = {
  name: "yaml-esm",
  setup(build) {
    build.onResolve({ filter: /^yaml$/ }, () => ({
      path: join(root, "node_modules", "yaml", "browser", "index.js"),
    }));
  },
};

// ws is CommonJS and requires Node's own modules, which an ESM bundle reaches
// only through a require of its own (esbuild otherwise throws "Dynamic require
// of "events" is not supported" when it loads).
const NODE_REQUIRE = {
  js: 'import { createRequire as __ombCreateRequire } from "node:module";\nconst require = __ombCreateRequire(import.meta.url);',
};

// Every file run as its own process.
const ENTRY_POINTS = [
  "index.ts",
  "message-search.worker.ts",
  // the `openmausbot` command
  "openmausbot.ts",
  "pair-cli.ts",
  "workspace-backup.worker.ts",
  // the OMB Cloud Pro home image's entry point
  "cloud-home-start.ts",
  // the container image's entry point
  "server-launcher.ts",
  // Imported directly by the packaged smoke probes. An explicit root sibling,
  // because tsc may emit its own copy under dist-server/server/.
  "proxy-paths.ts",
  "local-computer.ts",
  "local-computer-proxy.ts",
  // the hook helper Claude Code runs at PostToolUse/PreCompact/SessionStart/Stop
  "hooks/omb-hook.ts",
  "container-mcp.ts",
  "vps-container-mcp.ts",
  "permission-proxy.ts",
  "connector-proxy.ts",
  "mcp-gate.ts",
  "mcp-remote-proxy.ts",
  "harness-mcp-proxy.ts",
  "drivers/agents-proxy.ts",
  "drivers/dweb-proxy.ts",
  "drivers/phone-proxy.ts",
  "drivers/chatgpt-plan-token-command.ts",
  // the bot box (server/bot-box): the in-box bridge, the probe the self-check runs inside a box, and the check by hand
  "bot-box/box-bridge.ts",
  "bot-box/box-probe.ts",
  "bot-box/box-check.ts",
  // the meeting bot, copied to a cloud computer and run there with its own Node
  "meetings/meetbot.ts",
];

await build({
  entryPoints: ENTRY_POINTS.map((entry) => join(server, entry)),
  bundle: true,
  platform: "node",
  target: "node20",
  format: "esm",
  outbase: server,
  outdir: join(root, "dist-server"),
  // Function names stay in stack traces. Node prints a whole source line with an uncaught error, so no line may be long.
  minifyWhitespace: true,
  minifySyntax: true,
  lineLimit: 500,
  // Written after tsc, replacing its output for these entry points.
  allowOverwrite: true,
  logLevel: "info",
  plugins: [yamlEsmPlugin, serverLocalePlugin],
  banner: NODE_REQUIRE,
});

// External MCP clients launch this as an independent stdio process, so release
// users need no repository, TypeScript, pnpm or node_modules.
await build({
  entryPoints: [join(root, "scripts", "mcp-server.ts")],
  bundle: true,
  platform: "node",
  target: "node20",
  format: "esm",
  outfile: join(root, "dist-server", "mcp-server.js"),
  allowOverwrite: true,
  logLevel: "info",
  plugins: [serverLocalePlugin],
});

// `openmausbot serve --tunnel` spawns the connector guardian as its own
// process, so it must exist as a file beside the server.
await build({
  entryPoints: [join(root, "electron", "managed-companion-guardian-main.mjs")],
  bundle: true,
  platform: "node",
  target: "node20",
  format: "esm",
  outfile: join(root, "dist-server", "tunnel-guardian.js"),
  allowOverwrite: true,
  logLevel: "info",
});

// Runs itself when executed directly, so it must never be inlined into another
// entry.
await build({
  entryPoints: [join(root, "scripts", "prepare-cloudflared.mjs")],
  bundle: true,
  platform: "node",
  target: "node20",
  format: "esm",
  outfile: join(root, "dist-server", "prepare-cloudflared.js"),
  allowOverwrite: true,
  logLevel: "info",
});

// The enterprise layer (enterprise/LICENSE; delete the folder for pure OSS).
// Shipped bundled to dist-server/enterprise/server/index.js, where the server
// finds it; its own license travels with it.
if (existsSync(join(root, "enterprise", "server", "index.ts"))) {
  await build({
    entryPoints: [join(root, "enterprise", "server", "index.ts")],
    bundle: true,
    platform: "node",
    target: "node20",
    format: "esm",
    outfile: join(root, "dist-server", "enterprise", "server", "index.js"),
    allowOverwrite: true,
    logLevel: "info",
    plugins: [serverLocalePlugin],
  });
  copyFileSync(join(root, "enterprise", "LICENSE"), join(root, "dist-server", "enterprise", "LICENSE"));
}

// The packaged desktop and the container launcher run this bootstrap to turn on Node's compile cache.
// Copied, not bundled: esbuild would inline index.js into it.
copyFileSync(join(root, "scripts", "desktop-server-entry.mjs"), join(root, "dist-server", "desktop-entry.mjs"));

// The model catalog snapshot (server/model-catalog/catalog.ts) is read from
// disk, not inlined: 1.5 MB of JSON has no place in index.js. The bundle looks
// for it under model-catalog/ beside itself. Its MIT notice is inside the file.
const catalogSnapshot = join(root, "dist-server", "model-catalog", "models-dev.snapshot.json");
mkdirSync(dirname(catalogSnapshot), { recursive: true });
copyFileSync(join(server, "model-catalog", "models-dev.snapshot.json"), catalogSnapshot);

// Pi loads this through its own jiti and supplies TypeBox. Inline our local
// policy module so the extension also works without the source checkout;
// keep the Pi-owned dependency external and retain the .ts loading contract.
const piMcpExtSrc = join(server, "drivers", "pi-mcp-extension.ts");
const piMcpExtDest = join(root, "dist-server", "drivers", "pi-mcp-extension.ts");
mkdirSync(dirname(piMcpExtDest), { recursive: true });
await build({ entryPoints: [piMcpExtSrc], outfile: piMcpExtDest, bundle: true,
  platform: "node", target: "node24", format: "esm", external: ["typebox"], });

// Desktop resources live outside app.asar, so its package.json cannot mark
// these .js bundles as ESM. Do not inherit a user's CommonJS package scope.
// The version rides along: an image ships dist-server without the root
// package.json, and the server reports this one (server/environment.ts).
const { version } = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
writeFileSync(join(root, "dist-server", "package.json"), `${JSON.stringify({ type: "module", version })}\n`);

// tsc copies the language packs server/server-lines.ts imports (13 MB) beside its own output. The bundles above carry
// the server's keys, so nothing reads the copies.
rmSync(join(root, "dist-server", "src", "locales"), { recursive: true, force: true });