gen-code-runtime-runner.ts 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. /** Generate the subprocess Code Runtime's dependency-free runner bundle. */
  2. import { existsSync, readFileSync, writeFileSync } from 'node:fs'
  3. import { resolve } from 'node:path'
  4. import { build } from 'tsdown'
  5. const root = resolve(import.meta.dirname, '..')
  6. const ENTRY = 'packages/code-runtime/code-runtime-subprocess/src/runner.ts'
  7. const OUT = 'packages/code-runtime/code-runtime-subprocess/src/runner-source.generated.ts'
  8. /**
  9. * Bundle the typed runner and shared worker implementation into one source literal.
  10. * @returns generated TypeScript module consumed by the subprocess backend.
  11. */
  12. export async function renderCodeRuntimeRunner(): Promise<string> {
  13. const bundles = await build({
  14. config: false,
  15. entry: [resolve(root, ENTRY)],
  16. format: ['esm'],
  17. platform: 'node',
  18. target: 'es2024',
  19. write: false,
  20. dts: false,
  21. clean: false,
  22. minify: true,
  23. logLevel: 'silent',
  24. report: false,
  25. deps: { alwaysBundle: ['@deepseek-ai/dsh-code-runtime-worker'] },
  26. })
  27. try {
  28. const chunks = bundles.flatMap(bundle => bundle.chunks).filter(chunk => chunk.type === 'chunk')
  29. if (chunks.length !== 1) throw new Error(`gen-code-runtime-runner: expected one chunk, received ${chunks.length}`)
  30. const chunk = chunks[0]
  31. if (chunk === undefined) throw new Error('gen-code-runtime-runner: runner chunk is missing')
  32. const external = chunk.imports.filter(specifier => !specifier.startsWith('node:'))
  33. if (external.length > 0) {
  34. throw new Error(`gen-code-runtime-runner: runner retained external imports: ${external.join(', ')}`)
  35. }
  36. return [
  37. '/**',
  38. ' * Generated dependency-free execution-world runner.',
  39. ' * Do not edit by hand; run `pnpm run gen-code-runtime-runner`.',
  40. ' */',
  41. '',
  42. `export const CODE_RUNNER_SOURCE = ${JSON.stringify(chunk.code)}`,
  43. '',
  44. ].join('\n')
  45. } finally {
  46. await Promise.all(bundles.map(async (bundle) => { await bundle[Symbol.asyncDispose]() }))
  47. }
  48. }
  49. async function main(): Promise<void> {
  50. const content = await renderCodeRuntimeRunner()
  51. const output = resolve(root, OUT)
  52. if (process.argv.includes('--check')) {
  53. const committed = existsSync(output) ? readFileSync(output, 'utf8') : null
  54. if (committed === content) {
  55. console.log(`gen-code-runtime-runner: ${OUT} is up to date.`)
  56. return
  57. }
  58. console.error(`gen-code-runtime-runner: ${OUT} is stale. Run \`pnpm run gen-code-runtime-runner\` and commit it.`)
  59. process.exitCode = 1
  60. return
  61. }
  62. writeFileSync(output, content)
  63. console.log(`gen-code-runtime-runner: wrote ${OUT}.`)
  64. }
  65. if (process.argv[1] && import.meta.filename === resolve(process.argv[1])) await main()