diff --git a/packages/opencode/script/build.ts b/packages/opencode/script/build.ts index 4999a3ec7b3..3880ed40e72 100755 --- a/packages/opencode/script/build.ts +++ b/packages/opencode/script/build.ts @@ -287,10 +287,24 @@ for (const item of targets) { const bunfsRoot = item.os === "win32" ? "B:/~BUN/root/" : "/$bunfs/root/" const workerRelativePath = path.relative(dir, parserWorker).replaceAll("\\", "/") + // kilocode_change start - redirect @morphllm/morphsdk ESM barrel to self-contained CJS bundle + // Bun 1.3.14 (with conditions:["browser"]) resolves via the "import" condition, pulling in the + // pre-split ESM barrel (client.js) whose 52 chunk-*.js side-imports make the ESM splitter emit + // invalid minified output: SyntaxError: Exported binding 'G9' needs to refer to a top-level... + // Redirecting onResolve to client.cjs (2300-line self-contained CJS bundle) bypasses the splitter. + const morphsdkCjsPlugin: import("bun").BunPlugin = { + name: "morphsdk-cjs", + setup(build) { + build.onResolve({ filter: /^@morphllm\/morphsdk\/tools\/warp-grep\/client$/ }, () => ({ + path: require.resolve("@morphllm/morphsdk/dist/tools/warp_grep/client.cjs"), + })) + }, + } + // kilocode_change end await Bun.build({ conditions: ["browser"], tsconfig: "./tsconfig.json", - plugins: [plugin], // kilocode_change + plugins: [plugin, morphsdkCjsPlugin], // kilocode_change // kilocode_change start - skip sourcemaps for release builds (each .js.map adds ~50 MB per target → ~600 MB total) sourcemap: Script.release ? "none" : "external", // kilocode_change end diff --git a/packages/opencode/src/kilocode/compat/morphsdk.ts b/packages/opencode/src/kilocode/compat/morphsdk.ts index 10e0822f01e..9ae1f5ef73d 100644 --- a/packages/opencode/src/kilocode/compat/morphsdk.ts +++ b/packages/opencode/src/kilocode/compat/morphsdk.ts @@ -1,42 +1,29 @@ -import { createRequire } from "module" - -// Force Bun to load @morphllm/morphsdk/tools/warp-grep/client via its self-contained -// CJS bundle instead of the pre-split ESM barrel. -// -// WHY THIS EXISTS -// --------------- -// @morphllm/morphsdk ships a pre-split ESM distribution: -// dist/tools/warp_grep/client.js (805 bytes, barrel) -// └─ imports from ../../chunk-P7G3CJB2.js -// └─ side-effects ../../chunk-63VHBANJ.js ... (12 more chunks, 52 total) -// -// When Bun bundles the CLI with `splitting: true + minify: true`, it merges -// these external pre-split chunks into its own chunk graph. Bun 1.3.14 intermittently -// generates invalid minified ESM in that process: -// +// kilocode_change - new file +// Re-exports from @morphllm/morphsdk/tools/warp-grep/client. +// +// WHY THIS INDIRECTION EXISTS +// ---------------------------- +// @morphllm/morphsdk ships a pre-split ESM distribution for this path: +// dist/tools/warp_grep/client.js (805-byte barrel) +// └─ imports from ../../chunk-P7G3CJB2.js ... (52 total pre-split chunks) +// +// Bun 1.3.14 bundling with `conditions: ["browser"]` resolves via the "import" condition +// (ESM barrel) even inside createRequire() calls. When its ESM splitter merges those +// external pre-split chunks into the bundle, it generates invalid minified output: // SyntaxError: Exported binding 'G9' needs to refer to a top-level declared variable. // -// The error is non-deterministic (Bun's parallel bundler uses different orderings -// per run), so the build sometimes succeeds and sometimes fails on Windows x64. -// -// The CJS bundle (client.cjs, ~2300 lines) is fully self-contained with no external -// chunk imports. `createRequire` lets Bun inline the CJS module directly without -// running it through the ESM splitter. +// FIX: script/build.ts adds a morphsdkCjsPlugin (onResolve) that redirects this module +// specifier to client.cjs — a fully self-contained CJS bundle (~2300 lines, no chunk-*.js +// imports). The plugin runs at bundle time before the ESM splitter is invoked. // // HOW TO DETECT THIS FOR FUTURE DEPS -// ----------------------------------- -// If a new dependency causes `SyntaxError: Exported binding '...' needs to refer to -// a top-level declared variable` in release builds, check whether its ESM entry point -// is a barrel that re-imports from internal `chunk-*.js` files: +// ------------------------------------ +// If a new dependency causes the SyntaxError above in release builds, check whether its +// ESM entry point is a barrel that re-imports from internal `chunk-*.js` files: // // head -5 node_modules//dist/index.js // → imports { ... } from "./chunk-XYZ123.js" ← pre-split ESM // -// If so, add a CJS bridge here and re-export from it instead of importing the package -// directly. Always verify there is a `.cjs` (or CJS `main`) alternative. -const req = createRequire(import.meta.url) - -// Type-cast via the package's own .d.ts so callers get full type safety. -const mod = req("@morphllm/morphsdk/tools/warp-grep/client") as typeof import("@morphllm/morphsdk/tools/warp-grep/client") +// If so, add a matching onResolve redirect to the CJS counterpart in build.ts. -export const WarpGrepClient = mod.WarpGrepClient +export { WarpGrepClient } from "@morphllm/morphsdk/tools/warp-grep/client"