Copilot using vscode's ripgrep (#302323)

This commit is contained in:
Rob Lourens
2026-03-17 10:57:16 -07:00
committed by GitHub
parent d7a9278817
commit 2944e51725
4 changed files with 14 additions and 24 deletions

View File

@@ -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)) {

View File

@@ -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 {

View File

@@ -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}`);
};
}

View File

@@ -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({