From 2944e517259c67d348215580750ff7f0946336d0 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 17 Mar 2026 10:57:16 -0700 Subject: [PATCH] Copilot using vscode's ripgrep (#302323) --- build/darwin/create-universal-app.ts | 8 +------- build/darwin/verify-macho.ts | 4 +--- build/gulpfile.vscode.ts | 16 ++-------------- .../agentHost/node/copilot/copilotAgent.ts | 10 ++++++++++ 4 files changed, 14 insertions(+), 24 deletions(-) diff --git a/build/darwin/create-universal-app.ts b/build/darwin/create-universal-app.ts index c3de9766a05..46544b0c4d9 100644 --- a/build/darwin/create-universal-app.ts +++ b/build/darwin/create-universal-app.ts @@ -61,8 +61,6 @@ async function main(buildDir?: string) { crossCopyPlatformDir(x64AppPath, arm64AppPath, path.join(base, '@github', `copilot-${plat}`)); // @github/copilot/prebuilds/{platform} (pty.node, spawn-helper) crossCopyPlatformDir(x64AppPath, arm64AppPath, path.join(base, '@github', 'copilot', 'prebuilds', plat)); - // @github/copilot/ripgrep/bin/{platform} (rg binary) - crossCopyPlatformDir(x64AppPath, arm64AppPath, path.join(base, '@github', 'copilot', 'ripgrep', 'bin', plat)); } } @@ -76,12 +74,8 @@ async function main(buildDir?: string) { '**/node_modules.asar.unpacked/@github/copilot-darwin-arm64/**', '**/node_modules/@github/copilot/prebuilds/darwin-x64/**', '**/node_modules/@github/copilot/prebuilds/darwin-arm64/**', - '**/node_modules/@github/copilot/ripgrep/bin/darwin-x64/**', - '**/node_modules/@github/copilot/ripgrep/bin/darwin-arm64/**', '**/node_modules.asar.unpacked/@github/copilot/prebuilds/darwin-x64/**', '**/node_modules.asar.unpacked/@github/copilot/prebuilds/darwin-arm64/**', - '**/node_modules.asar.unpacked/@github/copilot/ripgrep/bin/darwin-x64/**', - '**/node_modules.asar.unpacked/@github/copilot/ripgrep/bin/darwin-arm64/**', ]; await makeUniversalApp({ @@ -91,7 +85,7 @@ async function main(buildDir?: string) { outAppPath, force: true, mergeASARs: true, - x64ArchFiles: '{*/kerberos.node,**/extensions/microsoft-authentication/dist/libmsalruntime.dylib,**/extensions/microsoft-authentication/dist/msal-node-runtime.node,**/node_modules/@github/copilot-darwin-*/copilot,**/node_modules/@github/copilot/prebuilds/darwin-*/*,**/node_modules/@github/copilot/ripgrep/bin/darwin-*/*,**/node_modules.asar.unpacked/@github/copilot-darwin-*/copilot,**/node_modules.asar.unpacked/@github/copilot/prebuilds/darwin-*/*,**/node_modules.asar.unpacked/@github/copilot/ripgrep/bin/darwin-*/*}', + x64ArchFiles: '{*/kerberos.node,**/extensions/microsoft-authentication/dist/libmsalruntime.dylib,**/extensions/microsoft-authentication/dist/msal-node-runtime.node,**/node_modules/@github/copilot-darwin-*/copilot,**/node_modules/@github/copilot/prebuilds/darwin-*/*,**/node_modules.asar.unpacked/@github/copilot-darwin-*/copilot,**/node_modules.asar.unpacked/@github/copilot/prebuilds/darwin-*/*}', filesToSkipComparison: (file: string) => { for (const expected of filesToSkip) { if (minimatch(file, expected)) { diff --git a/build/darwin/verify-macho.ts b/build/darwin/verify-macho.ts index 8443ca51641..bec37b2dd8e 100644 --- a/build/darwin/verify-macho.ts +++ b/build/darwin/verify-macho.ts @@ -31,11 +31,9 @@ const FILES_TO_SKIP = [ '**/node_modules/@github/copilot-darwin-arm64/**', '**/node_modules.asar.unpacked/@github/copilot-darwin-x64/**', '**/node_modules.asar.unpacked/@github/copilot-darwin-arm64/**', - // Copilot prebuilds and ripgrep: single-arch binaries in per-platform directories + // Copilot prebuilds: single-arch binaries in per-platform directories '**/node_modules/@github/copilot/prebuilds/darwin-*/**', - '**/node_modules/@github/copilot/ripgrep/bin/darwin-*/**', '**/node_modules.asar.unpacked/@github/copilot/prebuilds/darwin-*/**', - '**/node_modules.asar.unpacked/@github/copilot/ripgrep/bin/darwin-*/**', ]; function isFileSkipped(file: string): boolean { diff --git a/build/gulpfile.vscode.ts b/build/gulpfile.vscode.ts index 7a6f6e41ba7..35f0d93a6e9 100644 --- a/build/gulpfile.vscode.ts +++ b/build/gulpfile.vscode.ts @@ -714,14 +714,13 @@ function patchWin32DependenciesTask(destinationFolderName: string) { } /** - * Copies VS Code's own node-pty and ripgrep binaries into the copilot SDK's + * Copies VS Code's own node-pty binaries into the copilot SDK's * expected locations so the copilot CLI subprocess can find them at runtime. - * The copilot-bundled prebuilds and ripgrep are stripped by .moduleignore; + * The copilot-bundled prebuilds are stripped by .moduleignore; * this replaces them with the same binaries VS Code already ships, avoiding * new system dependency requirements. * * node-pty: `prebuilds/{platform}-{arch}/` (pty.node + spawn-helper) - * ripgrep: `ripgrep/bin/{platform}-{arch}/` (rg binary) */ function copyCopilotNativeDepsTask(platform: string, arch: string, destinationFolderName: string) { const outputDir = path.join(path.dirname(root), destinationFolderName); @@ -749,28 +748,17 @@ function copyCopilotNativeDepsTask(platform: string, arch: string, destinationFo const platformArch = `${platform === 'win32' ? 'win32' : platform}-${arch}`; const nodePtySource = path.join(nodeModulesDir, 'node-pty', 'build', 'Release'); - const rgBinary = platform === 'win32' ? 'rg.exe' : 'rg'; - const ripgrepSource = path.join(nodeModulesDir, '@vscode', 'ripgrep', 'bin', rgBinary); // Fail-fast: source binaries must exist on non-stable builds. if (!fs.existsSync(nodePtySource)) { throw new Error(`[copyCopilotNativeDeps] node-pty source not found at ${nodePtySource}`); } - if (!fs.existsSync(ripgrepSource)) { - throw new Error(`[copyCopilotNativeDeps] ripgrep source not found at ${ripgrepSource}`); - } // Copy node-pty (pty.node + spawn-helper) into copilot prebuilds const copilotPrebuildsDir = path.join(copilotBase, 'prebuilds', platformArch); fs.mkdirSync(copilotPrebuildsDir, { recursive: true }); fs.cpSync(nodePtySource, copilotPrebuildsDir, { recursive: true }); console.log(`[copyCopilotNativeDeps] Copied node-pty from ${nodePtySource} to ${copilotPrebuildsDir}`); - - // Copy ripgrep (rg binary) into copilot ripgrep - const copilotRipgrepDir = path.join(copilotBase, 'ripgrep', 'bin', platformArch); - fs.mkdirSync(copilotRipgrepDir, { recursive: true }); - fs.copyFileSync(ripgrepSource, path.join(copilotRipgrepDir, rgBinary)); - console.log(`[copyCopilotNativeDeps] Copied ripgrep from ${ripgrepSource} to ${copilotRipgrepDir}`); }; } diff --git a/src/vs/platform/agentHost/node/copilot/copilotAgent.ts b/src/vs/platform/agentHost/node/copilot/copilotAgent.ts index 368079ac0a3..b05f45307f7 100644 --- a/src/vs/platform/agentHost/node/copilot/copilotAgent.ts +++ b/src/vs/platform/agentHost/node/copilot/copilotAgent.ts @@ -8,7 +8,9 @@ import { DeferredPromise } from '../../../../base/common/async.js'; import { Emitter } from '../../../../base/common/event.js'; import { Disposable, DisposableMap } from '../../../../base/common/lifecycle.js'; import { FileAccess } from '../../../../base/common/network.js'; +import { delimiter, dirname } from '../../../../base/common/path.js'; import { URI } from '../../../../base/common/uri.js'; +import { rgPath } from '@vscode/ripgrep'; import { generateUuid } from '../../../../base/common/uuid.js'; import { ILogService } from '../../../log/common/log.js'; import { IAgentCreateSessionConfig, IAgentModelInfo, IAgentProgressEvent, IAgentMessageEvent, IAgent, IAgentSessionMetadata, IAgentToolStartEvent, IAgentToolCompleteEvent, AgentSession, IAgentDescriptor, IAgentAttachment } from '../../common/agentService.js'; @@ -101,11 +103,19 @@ export class CopilotAgent extends Disposable implements IAgent { } } env['COPILOT_CLI_RUN_AS_NODE'] = '1'; + env['USE_BUILTIN_RIPGREP'] = '0'; // Resolve the CLI entry point from node_modules. We can't use require.resolve() // because @github/copilot's exports map blocks direct subpath access. // FileAccess.asFileUri('') points to the `out/` directory; node_modules is one level up. const cliPath = URI.joinPath(FileAccess.asFileUri(''), '..', 'node_modules', '@github', 'copilot', 'index.js').fsPath; + + // Add VS Code's built-in ripgrep to PATH so the CLI subprocess can find it. + // If @vscode/ripgrep is in an .asar file, the binary is unpacked. + const rgDiskPath = rgPath.replace(/\bnode_modules\.asar\b/, 'node_modules.asar.unpacked'); + const rgDir = dirname(rgDiskPath); + const currentPath = env['PATH']; + env['PATH'] = currentPath ? `${currentPath}${delimiter}${rgDir}` : rgDir; this._logService.info(`[Copilot] Resolved CLI path: ${cliPath}`); const client = new CopilotClient({