esbuild.mjs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. import * as esbuild from "esbuild"
  2. import * as fs from "fs"
  3. import * as path from "path"
  4. import { fileURLToPath } from "url"
  5. import { createRequire } from "module"
  6. import process from "node:process"
  7. import * as console from "node:console"
  8. import { copyPaths, copyWasms, copyLocales, setupLocaleWatcher } from "@roo-code/build"
  9. const __filename = fileURLToPath(import.meta.url)
  10. const __dirname = path.dirname(__filename)
  11. async function main() {
  12. const name = "extension"
  13. const production = process.argv.includes("--production")
  14. const watch = process.argv.includes("--watch")
  15. const minify = production
  16. const sourcemap = true // Always generate source maps for error handling.
  17. /**
  18. * @type {import('esbuild').BuildOptions}
  19. */
  20. const buildOptions = {
  21. bundle: true,
  22. minify,
  23. sourcemap,
  24. logLevel: "silent",
  25. format: "cjs",
  26. sourcesContent: false,
  27. platform: "node",
  28. // kilocode_change start: for ps-list
  29. banner: {
  30. js: "const __importMetaUrl = typeof __filename !== 'undefined' ? require('url').pathToFileURL(__filename).href : undefined;",
  31. },
  32. // kilocode_change end
  33. }
  34. const srcDir = __dirname
  35. const buildDir = __dirname
  36. const distDir = path.join(buildDir, "dist")
  37. if (fs.existsSync(distDir)) {
  38. console.log(`[${name}] Cleaning dist directory: ${distDir}`)
  39. fs.rmSync(distDir, { recursive: true, force: true })
  40. }
  41. /**
  42. * @type {import('esbuild').Plugin[]}
  43. */
  44. const plugins = [
  45. // kilocode_change start
  46. {
  47. name: "import-meta-url-plugin",
  48. setup(build) {
  49. build.onLoad({ filter: /\.js$/ }, async (args) => {
  50. const fs = await import("fs")
  51. let contents = await fs.promises.readFile(args.path, "utf8")
  52. // Replace import.meta.url with our polyfill
  53. if (contents.includes("import.meta.url")) {
  54. contents = contents.replace(/import\.meta\.url/g, "__importMetaUrl")
  55. }
  56. return { contents, loader: "js" }
  57. })
  58. },
  59. },
  60. // kilocode_change end
  61. {
  62. name: "copyFiles",
  63. setup(build) {
  64. build.onEnd(() => {
  65. copyPaths(
  66. [
  67. ["../README.md", "README.md"],
  68. ["../CHANGELOG.md", "CHANGELOG.md"],
  69. ["../LICENSE", "LICENSE"],
  70. ["../.env", ".env", { optional: true }],
  71. ["node_modules/vscode-material-icons/generated", "assets/vscode-material-icons"],
  72. ["../webview-ui/audio", "webview-ui/audio"],
  73. ],
  74. srcDir,
  75. buildDir,
  76. )
  77. // Copy walkthrough files to dist directory
  78. copyPaths([["walkthrough", "walkthrough"]], srcDir, distDir)
  79. // Copy tree-sitter files to dist directory
  80. copyPaths([["services/continuedev/tree-sitter", "tree-sitter"]], srcDir, distDir)
  81. // Copy JSDOM xhr-sync-worker.js to fix runtime resolution
  82. const jsdomWorkerDest = path.join(distDir, "xhr-sync-worker.js")
  83. try {
  84. const require = createRequire(import.meta.url)
  85. const jsdomModulePath = require.resolve("jsdom/package.json")
  86. const jsdomDir = path.dirname(jsdomModulePath)
  87. const jsdomWorkerSource = path.join(jsdomDir, "lib/jsdom/living/xhr/xhr-sync-worker.js")
  88. if (fs.existsSync(jsdomWorkerSource)) {
  89. fs.copyFileSync(jsdomWorkerSource, jsdomWorkerDest)
  90. console.log(`[${name}] Copied JSDOM xhr-sync-worker.js to dist from: ${jsdomWorkerSource}`)
  91. }
  92. } catch (error) {
  93. console.error(`[${name}] Failed to copy JSDOM xhr-sync-worker.js:`, error.message)
  94. }
  95. })
  96. },
  97. },
  98. {
  99. name: "copyWasms",
  100. setup(build) {
  101. build.onEnd(() => copyWasms(srcDir, distDir))
  102. },
  103. },
  104. {
  105. name: "copyLocales",
  106. setup(build) {
  107. build.onEnd(() => copyLocales(srcDir, distDir))
  108. },
  109. },
  110. {
  111. name: "esbuild-problem-matcher",
  112. setup(build) {
  113. build.onStart(() => console.log("[esbuild-problem-matcher#onStart]"))
  114. build.onEnd((result) => {
  115. result.errors.forEach(({ text, location }) => {
  116. console.error(`✘ [ERROR] ${text}`)
  117. if (location && location.file) {
  118. console.error(` ${location.file}:${location.line}:${location.column}:`)
  119. }
  120. })
  121. console.log("[esbuild-problem-matcher#onEnd]")
  122. })
  123. },
  124. },
  125. ]
  126. /**
  127. * @type {import('esbuild').BuildOptions}
  128. */
  129. const extensionConfig = {
  130. ...buildOptions,
  131. plugins,
  132. entryPoints: ["extension.ts"],
  133. outfile: "dist/extension.js",
  134. // global-agent must be external because it dynamically patches Node.js http/https modules
  135. // which breaks when bundled. It needs access to the actual Node.js module instances.
  136. // undici must be bundled because our VSIX is packaged with `--no-dependencies`.
  137. external: ["vscode", "esbuild", "global-agent", "@lancedb/lancedb"], // kilocode_change: add @lancedb/lancedb
  138. }
  139. /**
  140. * @type {import('esbuild').BuildOptions}
  141. */
  142. const workerConfig = {
  143. ...buildOptions,
  144. entryPoints: ["workers/countTokens.ts"],
  145. outdir: "dist/workers",
  146. }
  147. // kilocode_change start - agent-runtime process bundle
  148. /**
  149. * Agent Runtime Process Bundle
  150. *
  151. * This bundles the agent-runtime process.ts into a standalone file that can be
  152. * forked by the Agent Manager. fork() requires a physical .js file on disk,
  153. * so we bundle it separately from the main extension.
  154. *
  155. * @type {import('esbuild').BuildOptions}
  156. */
  157. const agentRuntimeDir = path.join(srcDir, "..", "packages/agent-runtime")
  158. const agentRuntimeProcessConfig = {
  159. ...buildOptions,
  160. entryPoints: [path.join(agentRuntimeDir, "src/process.ts")],
  161. outfile: "dist/agent-runtime-process.js",
  162. // The agent-runtime process loads the main extension bundle dynamically,
  163. // so vscode APIs come from the extension, not from direct imports
  164. external: ["vscode"],
  165. // Use CJS format - works reliably with fork() and dynamic require() in dependencies
  166. format: "cjs",
  167. // Ensure we can resolve workspace packages
  168. plugins: [
  169. {
  170. name: "resolve-workspace-packages",
  171. setup(build) {
  172. // Resolve @roo-code/types and other workspace packages
  173. build.onResolve({ filter: /^@roo-code\// }, (args) => {
  174. const packageName = args.path
  175. const packagePath = path.join(srcDir, "..", "packages", packageName.replace("@roo-code/", ""))
  176. return { path: path.join(packagePath, "src/index.ts") }
  177. })
  178. build.onResolve({ filter: /^@kilocode\// }, (args) => {
  179. const packageName = args.path
  180. const packagePath = path.join(srcDir, "..", "packages", packageName.replace("@kilocode/", ""))
  181. return { path: path.join(packagePath, "src/index.ts") }
  182. })
  183. },
  184. },
  185. ],
  186. }
  187. // kilocode_change end
  188. const [extensionCtx, workerCtx, agentRuntimeCtx] = await Promise.all([ // kilocode_change
  189. esbuild.context(extensionConfig),
  190. esbuild.context(workerConfig),
  191. esbuild.context(agentRuntimeProcessConfig), // kilocode_change
  192. ])
  193. if (watch) {
  194. await Promise.all([extensionCtx.watch(), workerCtx.watch(), agentRuntimeCtx.watch()]) // kilocode_change
  195. copyLocales(srcDir, distDir)
  196. setupLocaleWatcher(srcDir, distDir)
  197. } else {
  198. await Promise.all([extensionCtx.rebuild(), workerCtx.rebuild(), agentRuntimeCtx.rebuild()]) // kilocode_change
  199. await Promise.all([extensionCtx.dispose(), workerCtx.dispose(), agentRuntimeCtx.dispose()]) // kilocode_change
  200. }
  201. }
  202. main().catch((e) => {
  203. console.error(e)
  204. process.exit(1)
  205. })