/*---------------------------------------------------------------------------------------------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';78/**9* The platforms that @github/copilot ships platform-specific packages for.10* These are the `@github/copilot-{platform}` optional dependency packages.11*/12export const copilotPlatforms = [13'darwin-arm64', 'darwin-x64',14'linux-arm64', 'linux-x64',15'win32-arm64', 'win32-x64',16];1718/**19* Converts VS Code build platform/arch to the values that Node.js reports20* at runtime via `process.platform` and `process.arch`.21*22* The copilot SDK's `loadNativeModule` looks up native binaries under23* `prebuilds/${process.platform}-${process.arch}/`, so the directory names24* must match these runtime values exactly.25*/26function toNodePlatformArch(platform: string, arch: string): { nodePlatform: string; nodeArch: string } {27// alpine is musl-linux; Node still reports process.platform === 'linux'28let nodePlatform = platform === 'alpine' ? 'linux' : platform;29let nodeArch = arch;3031if (arch === 'armhf') {32// VS Code build uses 'armhf'; Node reports process.arch === 'arm'33nodeArch = 'arm';34} else if (arch === 'alpine') {35// Legacy: { platform: 'linux', arch: 'alpine' } means alpine-x6436nodePlatform = 'linux';37nodeArch = 'x64';38}3940return { nodePlatform, nodeArch };41}4243/**44* Returns a glob filter that strips @github/copilot platform packages45* for architectures other than the build target.46*47* For platforms the copilot SDK doesn't natively support (e.g. alpine, armhf),48* ALL platform packages are stripped - that's fine because the copilot CLI SDK49* resolves `node-pty` from the embedder (VS Code) first via `hostRequire`,50* falling back to its bundled copy only if the embedder can't provide it.51*/52export function getCopilotExcludeFilter(platform: string, arch: string): string[] {53const { nodePlatform, nodeArch } = toNodePlatformArch(platform, arch);54const targetPlatformArch = `${nodePlatform}-${nodeArch}`;55const nonTargetPlatforms = copilotPlatforms.filter(p => p !== targetPlatformArch);5657// Strip wrong-architecture @github/copilot-{platform} packages.58// All copilot prebuilds are stripped by .moduleignore; the copilot CLI SDK59// resolves `node-pty` from VS Code's own node_modules via `hostRequire`.60const excludes = nonTargetPlatforms.map(p => `!**/node_modules/@github/copilot-${p}/**`);6162return ['**', ...excludes];63}6465/**66* Materializes the copilot CLI ripgrep shim directly inside the built-in copilot extension.67*68* This is used when copilot is shipped as a built-in extension so startup does69* not need to create the shim at runtime. The destination layout matches the70* runtime shim logic in the copilot extension:71* - ripgrep: node_modules/@github/copilot/sdk/ripgrep/bin/{platform-arch}72* - marker: node_modules/@github/copilot/shims.txt73*74* Note: `node-pty` is no longer shimmed. The copilot CLI SDK resolves75* `node-pty` from the embedder (VS Code) via `hostRequire` and falls back to76* its bundled copy only if that fails.77*78* Failures throw to fail the build because built-in packaging must guarantee79* this artifact is present.80*/81export function prepareBuiltInCopilotRipgrepShim(platform: string, arch: string, builtInCopilotExtensionDir: string, appNodeModulesDir: string): void {82const { nodePlatform, nodeArch } = toNodePlatformArch(platform, arch);83const platformArch = `${nodePlatform}-${nodeArch}`;8485const extensionNodeModules = path.join(builtInCopilotExtensionDir, 'node_modules');86const copilotBase = path.join(extensionNodeModules, '@github', 'copilot');87const copilotSdkBase = path.join(copilotBase, 'sdk');88if (!fs.existsSync(copilotSdkBase)) {89throw new Error(`[prepareBuiltInCopilotRipgrepShim] Copilot SDK directory not found at ${copilotSdkBase}`);90}9192const ripgrepSource = path.join(appNodeModulesDir, '@vscode', 'ripgrep', 'bin');93if (!fs.existsSync(ripgrepSource)) {94throw new Error(`[prepareBuiltInCopilotRipgrepShim] ripgrep source not found at ${ripgrepSource}`);95}9697const ripgrepDest = path.join(copilotSdkBase, 'ripgrep', 'bin', platformArch);98const shimMarkerPath = path.join(copilotBase, 'shims.txt');99100try {101fs.mkdirSync(ripgrepDest, { recursive: true });102fs.cpSync(ripgrepSource, ripgrepDest, { recursive: true });103104fs.writeFileSync(shimMarkerPath, 'Shims created successfully');105console.log(`[prepareBuiltInCopilotRipgrepShim] Materialized ripgrep shim for ${platformArch} in ${builtInCopilotExtensionDir}`);106} catch (err) {107throw new Error(`[prepareBuiltInCopilotRipgrepShim] Failed to materialize ripgrep shim for ${platformArch}: ${err}`);108}109}110111112