Path: blob/main/extensions/copilot/script/postinstall.ts
13383 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import * as fs from 'fs';6import * as path from 'path';7import { compressTikToken } from './build/compressTikToken';8import { copyStaticAssets } from './build/copyStaticAssets';910export interface ITreeSitterGrammar {11name: string;12/**13* A custom .wasm filename if the grammar node module doesn't follow the standard naming convention14*/15filename?: string;16/**17* The path where we should spawn `tree-sitter build-wasm`18*/19projectPath?: string;20}2122const treeSitterGrammars: ITreeSitterGrammar[] = [23{24name: 'tree-sitter-c-sharp',25filename: 'tree-sitter-c_sharp.wasm' // non-standard filename26},27{28name: 'tree-sitter-cpp',29},30{31name: 'tree-sitter-go',32},33{34name: 'tree-sitter-javascript', // Also includes jsx support35},36{37name: 'tree-sitter-python',38},39{40name: 'tree-sitter-ruby',41},42{43name: 'tree-sitter-typescript',44projectPath: 'tree-sitter-typescript/typescript', // non-standard path45},46{47name: 'tree-sitter-tsx',48projectPath: 'tree-sitter-typescript/tsx', // non-standard path49},50{51name: 'tree-sitter-java',52},53{54name: 'tree-sitter-rust',55},56{57name: 'tree-sitter-php'58}59];6061const REPO_ROOT = path.join(__dirname, '..');6263async function removeCopilotCLIShim() {64const shimsPath = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'shims.txt');65await fs.promises.rm(shimsPath, { force: true }).catch(() => { /* ignore */ });66}6768/**69* @github/copilot/sdk/index.js depends on @github/copilot/worker/*.js files.70* We need to copy these files into the sdk directory to ensure they are available at runtime.71*/72async function copyCopilotCliWorkerFiles() {73const sourceDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'worker');74const targetDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'sdk', 'worker');7576await copyCopilotCLIFolders(sourceDir, targetDir);77}7879async function copyCopilotCliSharpFiles() {80const sourceDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'sharp');81const targetDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'sdk', 'sharp');8283await copyCopilotCLIFolders(sourceDir, targetDir);84}8586async function copyCopilotCliDefinitionFiles() {87const sourceDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'definitions');88const targetDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'sdk', 'definitions');8990await copyCopilotCLIFolders(sourceDir, targetDir);91}9293async function copyCopilotCliSkillsFiles() {94const sourceDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'builtin-skills');95const targetDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'sdk', 'builtin-skills');9697await copyCopilotCLIFolders(sourceDir, targetDir);98}99100async function copyCopilotCliQueryFiles() {101const sourceDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'queries');102const targetDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'sdk', 'queries');103104await copyCopilotCLIFolders(sourceDir, targetDir);105}106107async function copyCopilotCliPrebuildFiles() {108const sourceDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'prebuilds');109const targetDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'sdk', 'prebuilds');110111await fs.promises.rm(targetDir, { recursive: true, force: true });112await fs.promises.mkdir(targetDir, { recursive: true });113await fs.promises.cp(sourceDir, targetDir, {114recursive: true, force: true, filter: (src) => {115try {116// Only copy computer.node and win32.node files117if (fs.statSync(src).isFile()) {118return src.endsWith('computer.node') || src.endsWith('win32.node');119}120return true;121} catch {122return true;123}124}125});126}127128async function copyCopilotCLIFolders(sourceDir: string, targetDir: string) {129await fs.promises.rm(targetDir, { recursive: true, force: true });130await fs.promises.mkdir(targetDir, { recursive: true });131await fs.promises.cp(sourceDir, targetDir, { recursive: true, force: true });132}133134/**135* Creates symlinks so that `.claude/` mirrors canonical locations (for testing Claude Agent harness):136* .claude/CLAUDE.md → .github/copilot-instructions.md137* .claude/skills → .agents/skills138*/139async function createClaudeSymlinks() {140if (process.platform === 'win32') {141// Creating symlinks on Windows may fail without Developer Mode or admin privileges.142// Skip this step to avoid postinstall failures on environments where symlinks are not available.143return;144}145146console.log('Creating symlinks for Claude session storage and instructions...');147const claudeDir = path.join(REPO_ROOT, '.claude');148await fs.promises.mkdir(claudeDir, { recursive: true });149150const symlinks: { link: string; target: string }[] = [151{ link: path.join(claudeDir, 'CLAUDE.md'), target: path.join('..', '.github', 'copilot-instructions.md') },152{ link: path.join(claudeDir, 'skills'), target: path.join('..', '.agents', 'skills') },153];154155for (const { link, target } of symlinks) {156if (!fs.existsSync(link)) {157await fs.promises.symlink(target, link);158}159}160}161162async function main() {163await fs.promises.mkdir(path.join(REPO_ROOT, '.build'), { recursive: true });164165await createClaudeSymlinks();166167const vendoredTiktokenFiles = ['src/platform/tokenizer/node/cl100k_base.tiktoken', 'src/platform/tokenizer/node/o200k_base.tiktoken'];168169for (const tokens of vendoredTiktokenFiles) {170await compressTikToken(tokens, `dist/${path.basename(tokens)}`);171}172173// copy static assets to dist174await copyStaticAssets([175...treeSitterGrammars.map(grammar => `node_modules/@vscode/tree-sitter-wasm/wasm/${grammar.name}.wasm`),176'node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter.wasm',177'node_modules/@github/blackbird-external-ingest-utils/pkg/nodejs/external_ingest_utils_bg.wasm',178], 'dist');179180await removeCopilotCLIShim();181await copyCopilotCliWorkerFiles();182await copyCopilotCliSharpFiles();183await copyCopilotCliDefinitionFiles();184await copyCopilotCliSkillsFiles();185await copyCopilotCliQueryFiles();186await copyCopilotCliPrebuildFiles();187188// Check if the base cache file exists (dev-only sanity check, non-fatal in CI)189const baseCachePath = path.join('test', 'simulation', 'cache', 'base.sqlite');190if (!fs.existsSync(baseCachePath)) {191console.warn(`Warning: Base cache file does not exist at ${baseCachePath}. Please ensure that you have git lfs installed and initialized before the repository is cloned.`);192}193194await copyStaticAssets([195`node_modules/@anthropic-ai/claude-agent-sdk/cli.js`,196], 'dist');197}198199main();200201202