Newer
Older
cortex-hub / CaudeCodeSourceCode / cc-recovered-main / scripts / build.mjs
import { existsSync } from 'node:fs';
import { promises as fs } from 'node:fs';
import path from 'node:path';
import process from 'node:process';
import { fileURLToPath } from 'node:url';
import { transform } from 'esbuild';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const projectRoot = path.resolve(__dirname, '..');
const outDir = path.join(projectRoot, 'dist');
const sourceRoots = ['src', 'vendor'];
const codeExtensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'];
const rawTextExtensions = ['.md', '.txt'];
const macroDefinition = JSON.stringify({
  VERSION: '2.1.88',
  PACKAGE_URL: '@anthropic-ai/claude-code',
  README_URL: 'https://code.claude.com/docs/en/overview',
  FEEDBACK_CHANNEL: 'https://github.com/anthropics/claude-code/issues',
  BUILD_TIME: '2026-03-30T21:59:52Z',
  ISSUES_EXPLAINER: 'report the issue at https://github.com/anthropics/claude-code/issues',
  NATIVE_PACKAGE_URL: null,
  VERSION_CHANGELOG: null
});

const generatedFiles = new Set();
const rawAssetModules = new Map();
const missingModuleInfo = new Map();
const unavailableExternalInfo = new Map();

const generatedSpecMap = new Map([
  ['bun:bundle', '__generated__/bun-bundle.js'],
  ['bun:ffi', '__generated__/bun-ffi.js'],
  ['image-processor-napi', 'vendor/image-processor-src/index.js'],
  ['audio-capture-napi', 'vendor/audio-capture-src/index.js'],
  ['modifiers-napi', 'vendor/modifiers-napi-src/index.js'],
  ['url-handler-napi', 'vendor/url-handler-src/index.js'],
  ['color-diff-napi', 'src/native-ts/color-diff/index.js'],
  ['@ant/claude-for-chrome-mcp', '__generated__/externals/ant-claude-for-chrome-mcp.js'],
  ['@ant/computer-use-mcp', '__generated__/externals/ant-computer-use-mcp.js'],
  ['@ant/computer-use-mcp/sentinelApps', '__generated__/externals/ant-computer-use-mcp-sentinelApps.js'],
  ['@ant/computer-use-mcp/types', '__generated__/externals/ant-computer-use-mcp-types.js'],
  ['@ant/computer-use-input', '__generated__/externals/ant-computer-use-input.js'],
  ['@ant/computer-use-swift', '__generated__/externals/ant-computer-use-swift.js']
]);

const moduleSpecPattern =
  /\b(?:import|export)\s+(?:[^'"`]*?\s+from\s+)?(['"])([^'"`\n]+)\1|require\(\s*(['"])([^'"`\n]+)\3\s*\)|import\(\s*(['"])([^'"`\n]+)\5\s*\)/g;
const importFromPattern =
  /\b(import|export)\s+([^'"`\n]*?)\s+from\s+['"]([^'"`\n]+)['"]/g;
const requireMemberPattern = /require\(\s*['"]([^'"`\n]+)['"]\s*\)\.(\w+)/g;

await fs.rm(outDir, { recursive: true, force: true });

const sourceFiles = (await Promise.all(sourceRoots.map(root => walkDirectory(path.join(projectRoot, root))))).flat();

for (const sourceFile of sourceFiles) {
  const sourceRel = toPosix(path.relative(projectRoot, sourceFile));
  const sourceText = await fs.readFile(sourceFile, 'utf8');
  collectMissingModuleUsage(sourceRel, sourceText);
}

for (const sourceFile of sourceFiles) {
  const sourceRel = toPosix(path.relative(projectRoot, sourceFile));
  const sourceText = await fs.readFile(sourceFile, 'utf8');
  const rewritten = rewriteSourceText(sourceRel, sourceText);
  const outputRel = toOutputCodePath(sourceRel);
  const outputAbs = path.join(outDir, outputRel);

  await fs.mkdir(path.dirname(outputAbs), { recursive: true });
  const compiled = await transform(withRequireShim(rewritten), {
    format: 'esm',
    platform: 'node',
    target: 'node18',
    loader: getEsbuildLoader(sourceRel),
    define: {
      MACRO: macroDefinition
    },
    jsx: 'automatic',
    charset: 'utf8',
    legalComments: 'none'
  });
  await fs.writeFile(outputAbs, compiled.code, 'utf8');
  generatedFiles.add(outputRel);
}

for (const [assetSourceRel, assetModuleRel] of rawAssetModules) {
  if (generatedFiles.has(assetModuleRel)) {
    continue;
  }
  const assetAbs = path.join(projectRoot, assetSourceRel);
  let contents = '';
  try {
    contents = await fs.readFile(assetAbs, 'utf8');
  } catch {
    contents = '';
  }
  await writeGeneratedFile(
    assetModuleRel,
    `export default ${JSON.stringify(contents)};\n`
  );
}

await writeGeneratedFile(
  '__generated__/bun-bundle.js',
  `function isTruthy(value) {
  return ['1', 'true', 'yes', 'on'].includes(String(value).toLowerCase());
}

export function feature(name) {
  const envKey = 'CLAUDE_CODE_FEATURE_' + String(name).toUpperCase();
  if (process.env[envKey] != null) {
    return isTruthy(process.env[envKey]);
  }
  const list = process.env.CLAUDE_CODE_FEATURES;
  if (!list) {
    return false;
  }
  return list
    .split(',')
    .map(entry => entry.trim())
    .filter(Boolean)
    .includes(String(name));
}

export default { feature };
`
);

await writeGeneratedFile(
  '__generated__/bun-ffi.js',
  `function unsupported() {
  throw new Error('bun:ffi is not available in the npm rebuild. This code path requires Bun-specific FFI support.');
}

export const dlopen = unsupported;
export const suffix = process.platform === 'win32' ? '.dll' : process.platform === 'darwin' ? '.dylib' : '.so';
export default { dlopen, suffix };
`
);

await writeGeneratedFile(
  '__generated__/externals/ant-claude-for-chrome-mcp.js',
  `export const BROWSER_TOOLS = [];
export default { BROWSER_TOOLS };
`
);

await writeGeneratedFile(
  '__generated__/externals/ant-computer-use-mcp.js',
  `export const DEFAULT_GRANT_FLAGS = {};
export const API_RESIZE_PARAMS = {};
export function buildComputerUseTools() { return []; }
export function bindSessionContext(value) { return value ?? {}; }
export function targetImageSize() { return { width: 0, height: 0 }; }
export default {
  DEFAULT_GRANT_FLAGS,
  API_RESIZE_PARAMS,
  buildComputerUseTools,
  bindSessionContext,
  targetImageSize
};
`
);

await writeGeneratedFile(
  '__generated__/externals/ant-computer-use-mcp-sentinelApps.js',
  `export function getSentinelCategory() { return null; }
export default { getSentinelCategory };
`
);

await writeGeneratedFile(
  '__generated__/externals/ant-computer-use-mcp-types.js',
  `export const DEFAULT_GRANT_FLAGS = {};
export default { DEFAULT_GRANT_FLAGS };
`
);

for (const generatedRel of [
  '__generated__/externals/ant-computer-use-input.js',
  '__generated__/externals/ant-computer-use-swift.js'
]) {
  if (!generatedFiles.has(generatedRel)) {
    await writeGeneratedFile(generatedRel, createStubModuleSource({ defaultExport: true, names: [] }));
  }
}

for (const [targetRel, info] of unavailableExternalInfo) {
  if (generatedFiles.has(targetRel)) {
    continue;
  }
  await writeGeneratedFile(
    targetRel,
    createStubModuleSource({
      defaultExport: info.defaultExport,
      names: [...info.names]
    })
  );
}

for (const [targetRel, info] of missingModuleInfo) {
  if (generatedFiles.has(targetRel)) {
    continue;
  }
  await writeGeneratedFile(
    targetRel,
    createStubModuleSource({
      defaultExport: info.defaultExport,
      names: [...info.names]
    })
  );
}

await writeGeneratedFile(
  'cli.js',
  `#!/usr/bin/env node
import { main } from './src/main.js';

try {
  await main();
} catch (error) {
  console.error(error);
  process.exitCode = 1;
}
`
);
await fs.chmod(path.join(outDir, 'cli.js'), 0o755);

console.log(`Built ${sourceFiles.length} source files into ${path.relative(projectRoot, outDir)}.`);

function toPosix(value) {
  return value.split(path.sep).join('/');
}

function normalizeSpecifier(specifier) {
  return specifier.replace(/^src\/+/, 'src/');
}

function changeExtension(filePath, nextExtension) {
  return filePath.replace(/\.[^.\/]+$/, nextExtension);
}

function getEsbuildLoader(fileRel) {
  if (fileRel.endsWith('.tsx')) {
    return 'tsx';
  }
  if (fileRel.endsWith('.ts')) {
    return 'ts';
  }
  if (fileRel.endsWith('.jsx')) {
    return 'jsx';
  }
  return 'js';
}

function toOutputCodePath(sourceRel) {
  return changeExtension(sourceRel, '.js');
}

function toImportSpecifier(fromOutputRel, targetOutputRel) {
  const fromDir = path.posix.dirname(fromOutputRel);
  let relativePath = path.posix.relative(fromDir, targetOutputRel);
  if (!relativePath.startsWith('.')) {
    relativePath = `./${relativePath}`;
  }
  return relativePath;
}

function getCandidateFiles(baseAbs, extension) {
  if (extension && rawTextExtensions.includes(extension)) {
    return [baseAbs];
  }

  const stem = extension ? baseAbs.slice(0, -extension.length) : baseAbs;
  const candidates = [];

  if (extension && codeExtensions.includes(extension)) {
    for (const codeExtension of codeExtensions) {
      candidates.push(`${stem}${codeExtension}`);
    }
    for (const codeExtension of codeExtensions) {
      candidates.push(path.join(stem, `index${codeExtension}`));
    }
    return candidates;
  }

  for (const codeExtension of codeExtensions) {
    candidates.push(`${baseAbs}${codeExtension}`);
  }
  for (const codeExtension of codeExtensions) {
    candidates.push(path.join(baseAbs, `index${codeExtension}`));
  }
  return candidates;
}

async function walkDirectory(directory) {
  let entries = [];
  try {
    entries = await fs.readdir(directory, { withFileTypes: true });
  } catch {
    return [];
  }

  const files = [];
  for (const entry of entries) {
    if (entry.name === 'node_modules' || entry.name === 'dist' || entry.name === '.git') {
      continue;
    }
    const entryAbs = path.join(directory, entry.name);
    if (entry.isDirectory()) {
      files.push(...(await walkDirectory(entryAbs)));
      continue;
    }
    if (codeExtensions.includes(path.extname(entry.name))) {
      files.push(entryAbs);
    }
  }
  return files;
}

function resolveProjectSpecifier(sourceRel, rawSpecifier) {
  const specifier = normalizeSpecifier(rawSpecifier);

  if (generatedSpecMap.has(specifier)) {
    return {
      kind: generatedSpecMap.get(specifier).startsWith('__generated__/externals/')
        ? 'unavailable-external'
        : 'mapped',
      targetRel: generatedSpecMap.get(specifier)
    };
  }

  const isAlias = specifier.startsWith('src/');
  const isRelative = specifier.startsWith('./') || specifier.startsWith('../');

  if (!isAlias && !isRelative) {
    return { kind: 'external' };
  }

  const sourceDirAbs = path.join(projectRoot, path.posix.dirname(sourceRel));
  const resolvedBaseAbs = isAlias
    ? path.join(projectRoot, specifier)
    : path.resolve(sourceDirAbs, specifier);
  const extension = path.extname(specifier);

  if (rawTextExtensions.includes(extension)) {
    const assetSourceRel = toPosix(path.relative(projectRoot, resolvedBaseAbs));
    return {
      kind: 'asset',
      assetSourceRel,
      targetRel: `${assetSourceRel}.js`
    };
  }

  const candidates = getCandidateFiles(resolvedBaseAbs, extension);
  for (const candidate of candidates) {
    if (existsSync(candidate)) {
      const candidateRel = toPosix(path.relative(projectRoot, candidate));
      return {
        kind: 'code',
        targetRel: toOutputCodePath(candidateRel)
      };
    }
  }

  const missingRel = toPosix(path.relative(projectRoot, extension ? changeExtension(resolvedBaseAbs, '.js') : `${resolvedBaseAbs}.js`));
  return {
    kind: 'missing',
    targetRel: missingRel
  };
}

function rewriteSourceText(sourceRel, sourceText) {
  return sourceText.replace(moduleSpecPattern, (match, q1, s1, q2, s2, q3, s3) => {
    const specifier = s1 ?? s2 ?? s3;
    const quote = q1 ?? q2 ?? q3 ?? "'";
    const resolution = resolveProjectSpecifier(sourceRel, specifier);

    if (resolution.kind === 'asset') {
      rawAssetModules.set(resolution.assetSourceRel, resolution.targetRel);
      const nextSpecifier = toImportSpecifier(toOutputCodePath(sourceRel), resolution.targetRel);
      return match.replace(`${quote}${specifier}${quote}`, `${quote}${nextSpecifier}${quote}`);
    }

    if (resolution.kind === 'code' || resolution.kind === 'missing' || resolution.kind === 'mapped' || resolution.kind === 'unavailable-external') {
      if (resolution.kind === 'missing') {
        getMissingModuleRecord(missingModuleInfo, resolution.targetRel);
      }
      if (resolution.kind === 'unavailable-external') {
        getMissingModuleRecord(unavailableExternalInfo, resolution.targetRel);
      }
      const nextSpecifier = toImportSpecifier(toOutputCodePath(sourceRel), resolution.targetRel);
      return match.replace(`${quote}${specifier}${quote}`, `${quote}${nextSpecifier}${quote}`);
    }

    return match;
  });
}

function withRequireShim(sourceText) {
  if (!/\brequire\(/.test(sourceText) || /const require = __ccCreateRequire\(import\.meta\.url\)/.test(sourceText)) {
    return sourceText;
  }

  return `import { createRequire as __ccCreateRequire } from 'node:module';\nconst require = __ccCreateRequire(import.meta.url);\n${sourceText}`;
}

function getMissingModuleRecord(map, targetRel) {
  let record = map.get(targetRel);
  if (!record) {
    record = {
      defaultExport: false,
      names: new Set()
    };
    map.set(targetRel, record);
  }
  return record;
}

function collectNamesFromClause(clause, kind) {
  const result = {
    defaultExport: false,
    names: new Set()
  };

  const trimmed = clause.trim();
  if (!trimmed || trimmed.startsWith('type ')) {
    return result;
  }

  const braceStart = trimmed.indexOf('{');
  const braceEnd = trimmed.lastIndexOf('}');

  if (kind === 'import') {
    if (braceStart === -1 && !trimmed.includes('* as')) {
      result.defaultExport = true;
      return result;
    }

    if (braceStart > 0) {
      const prefix = trimmed.slice(0, braceStart).replace(/,/g, '').trim();
      if (prefix) {
        result.defaultExport = true;
      }
    }
  }

  if (braceStart !== -1 && braceEnd > braceStart) {
    const inside = trimmed.slice(braceStart + 1, braceEnd);
    for (const part of inside.split(',')) {
      const entry = part.trim().replace(/^type\s+/, '');
      if (!entry) {
        continue;
      }
      const [sourceName] = entry.split(/\s+as\s+/);
      if (sourceName) {
        result.names.add(sourceName.trim());
      }
    }
  }

  return result;
}

function collectMissingModuleUsage(sourceRel, sourceText) {
  for (const match of sourceText.matchAll(importFromPattern)) {
    const kind = match[1];
    const clause = match[2] ?? '';
    const rawSpecifier = match[3];
    const resolution = resolveProjectSpecifier(sourceRel, rawSpecifier);
    if (resolution.kind !== 'missing' && resolution.kind !== 'unavailable-external') {
      continue;
    }

    const targetMap = resolution.kind === 'unavailable-external' ? unavailableExternalInfo : missingModuleInfo;
    const record = getMissingModuleRecord(targetMap, resolution.targetRel);
    const usage = collectNamesFromClause(clause, kind);
    if (usage.defaultExport) {
      record.defaultExport = true;
    }
    for (const name of usage.names) {
      record.names.add(name);
    }
  }

  for (const match of sourceText.matchAll(requireMemberPattern)) {
    const rawSpecifier = match[1];
    const memberName = match[2];
    const resolution = resolveProjectSpecifier(sourceRel, rawSpecifier);
    if (resolution.kind !== 'missing' && resolution.kind !== 'unavailable-external') {
      continue;
    }
    const targetMap = resolution.kind === 'unavailable-external' ? unavailableExternalInfo : missingModuleInfo;
    const record = getMissingModuleRecord(targetMap, resolution.targetRel);
    record.names.add(memberName);
  }
}

async function writeGeneratedFile(outputRel, contents) {
  const outputAbs = path.join(outDir, outputRel);
  await fs.mkdir(path.dirname(outputAbs), { recursive: true });
  await fs.writeFile(outputAbs, contents, 'utf8');
  generatedFiles.add(outputRel);
}

function createStubModuleSource({ defaultExport, names }) {
  const exportLines = [
    `function __ccPlaceholder(label) {`,
    `  const fn = function () { return __ccPlaceholder(label + '()'); };`,
    `  return new Proxy(fn, {`,
    `    get(_target, prop) {`,
    `      if (prop === 'then') return undefined;`,
    `      if (prop === Symbol.toPrimitive) return () => label;`,
    `      if (prop === 'toString') return () => label;`,
    `      if (prop === 'valueOf') return () => label;`,
    `      if (prop === Symbol.iterator) return function* () {};`,
    `      if (prop === 'length') return 0;`,
    `      return __ccPlaceholder(label + '.' + String(prop));`,
    `    },`,
    `    apply() { return __ccPlaceholder(label + '()'); },`,
    `    construct() { return __ccPlaceholder('new ' + label); }`,
    `  });`,
    `}`
  ];

  if (defaultExport) {
    exportLines.push(`export default __ccPlaceholder('default');`);
  }

  for (const name of names.sort()) {
    if (!name || name === 'default') {
      continue;
    }
    exportLines.push(`export const ${name} = __ccPlaceholder(${JSON.stringify(name)});`);
  }

  if (!defaultExport && names.length === 0) {
    exportLines.push(`export default __ccPlaceholder('default');`);
  }

  return `${exportLines.join('\n')}\n`;
}