mirror of
https://github.com/coder/code-server.git
synced 2026-04-16 03:48:16 -05:00
Optimize builtin copilot extension (#7757)
This commit is contained in:
@@ -108,7 +108,7 @@ EOF
|
||||
) > product.json
|
||||
|
||||
|
||||
VSCODE_QUALITY=stable npm run gulp compile-copilot-extension-build
|
||||
VSCODE_QUALITY=stable npm run gulp compile-copilot-extension-full-build
|
||||
|
||||
npm run gulp core-ci
|
||||
npm run gulp "vscode-reh-web-$VSCODE_TARGET${MINIFY:+-min}-ci"
|
||||
|
||||
163
patches/copilot.diff
Normal file
163
patches/copilot.diff
Normal file
@@ -0,0 +1,163 @@
|
||||
Index: code-server/lib/vscode/build/gulpfile.extensions.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/build/gulpfile.extensions.ts
|
||||
+++ code-server/lib/vscode/build/gulpfile.extensions.ts
|
||||
@@ -287,6 +287,29 @@ export const compileCopilotExtensionBuil
|
||||
gulp.task(compileCopilotExtensionBuildTask);
|
||||
|
||||
/**
|
||||
+ * Compiles the built-in copilot extension with proper `.vscodeignore` filtering
|
||||
+ * and materializes native dependency shims (`node-pty`, `ripgrep`).
|
||||
+ * Produces output equivalent to what CI ships from the pre-built VSIX.
|
||||
+ *
|
||||
+ * The result is placed in `.build/extensions/copilot/` and can be copied
|
||||
+ * directly into a VS Code Insiders installation at:
|
||||
+ * `<insiders>/resources/app/extensions/copilot/`
|
||||
+ */
|
||||
+export const compileCopilotExtensionFullBuildTask = task.define('compile-copilot-extension-full-build', task.series(
|
||||
+ // Step 1: Clean previous copilot build output
|
||||
+ task.define('clean-copilot-build', util.rimraf('.build/extensions/copilot')),
|
||||
+ // Step 2: Build and package with proper `.vscodeignore` filtering
|
||||
+ task.define('package-copilot-extension-full', () => ext.packageCopilotExtensionFullStream().pipe(gulp.dest('.build'))),
|
||||
+ // Step 3: Materialize native dependency shims (`node-pty`, `ripgrep`)
|
||||
+ task.define('copilot-extension-native-shims', () => {
|
||||
+ const copilotExtDir = path.join(root, '.build', 'extensions', 'copilot');
|
||||
+ ext.prepareCopilotExtensionNativeShims(copilotExtDir);
|
||||
+ return Promise.resolve();
|
||||
+ })
|
||||
+));
|
||||
+gulp.task(compileCopilotExtensionFullBuildTask);
|
||||
+
|
||||
+/**
|
||||
* Compiles the extensions for the build.
|
||||
* This is essentially a helper task that combines {@link cleanExtensionsBuildTask}, {@link compileNonNativeExtensionsBuildTask} and {@link compileNativeExtensionsBuildTask}
|
||||
*/
|
||||
Index: code-server/lib/vscode/build/lib/extensions.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/build/lib/extensions.ts
|
||||
+++ code-server/lib/vscode/build/lib/extensions.ts
|
||||
@@ -24,6 +24,7 @@ import { getProductionDependencies } fro
|
||||
import { type IExtensionDefinition, getExtensionStream } from './builtInExtensions.ts';
|
||||
import { fetchUrls, fetchGithub } from './fetch.ts';
|
||||
import { createTsgoStream, spawnTsgo } from './tsgo.ts';
|
||||
+import { prepareBuiltInCopilotExtensionShims } from './copilot.ts';
|
||||
import vzip from 'gulp-vinyl-zip';
|
||||
|
||||
import { createRequire } from 'module';
|
||||
@@ -482,6 +483,116 @@ export function packageCopilotExtensionS
|
||||
).pipe(util2.setExecutableBit(['**/*.sh']));
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * Package the built-in copilot extension as a properly filtered VSIX-equivalent.
|
||||
+ * Unlike {@link packageCopilotExtensionStream}, this uses vsce.listFiles with
|
||||
+ * PackageManager.Npm so that .vscodeignore is respected for dependency filtering,
|
||||
+ * producing output equivalent to what CI ships from the pre-built VSIX.
|
||||
+ */
|
||||
+export function packageCopilotExtensionFullStream(): Stream {
|
||||
+ const vsce = require('@vscode/vsce') as typeof import('@vscode/vsce');
|
||||
+ const extensionPath = path.join(root, 'extensions', 'copilot');
|
||||
+ if (!fs.existsSync(extensionPath)) {
|
||||
+ return es.readArray([]);
|
||||
+ }
|
||||
+
|
||||
+ const esbuildConfigFileName = '.esbuild.ts';
|
||||
+ const esbuildScript = path.join(extensionPath, esbuildConfigFileName);
|
||||
+ if (!fs.existsSync(esbuildScript)) {
|
||||
+ throw new Error(`Copilot esbuild script not found at ${esbuildScript}`);
|
||||
+ }
|
||||
+
|
||||
+ const result = es.through();
|
||||
+
|
||||
+ // Step 1: Run esbuild to compile the extension
|
||||
+ new Promise<void>((resolve, reject) => {
|
||||
+ const proc = cp.execFile(process.argv[0], [esbuildScript], { cwd: extensionPath }, (error, _stdout, stderr) => {
|
||||
+ if (error) {
|
||||
+ return reject(error);
|
||||
+ }
|
||||
+ const matches = (stderr || '').match(/\> (.+): error: (.+)?/g);
|
||||
+ fancyLog(`Bundled extension: ${ansiColors.yellow(path.join('copilot', esbuildConfigFileName))} with ${matches ? matches.length : 0} errors.`);
|
||||
+ for (const match of matches || []) {
|
||||
+ fancyLog.error(match);
|
||||
+ }
|
||||
+ return resolve();
|
||||
+ });
|
||||
+ proc.stdout!.on('data', (data) => {
|
||||
+ fancyLog(`${ansiColors.green('esbuilding copilot')}: ${data.toString('utf8')}`);
|
||||
+ });
|
||||
+ }).then(() => {
|
||||
+ // Step 2: Use `vsce.listFiles` with Npm package manager so `.vscodeignore`
|
||||
+ // is applied to both source files AND `node_modules` dependencies.
|
||||
+ // This is the key difference from `packageCopilotExtensionStream` which
|
||||
+ // uses `PackageManager.None` and then blindly merges all production deps.
|
||||
+ return vsce.listFiles({ cwd: extensionPath, packageManager: vsce.PackageManager.Npm });
|
||||
+ }).then(fileNames => {
|
||||
+ const files = fileNames
|
||||
+ .map(fileName => path.join(extensionPath, fileName))
|
||||
+ .map(filePath => new File({
|
||||
+ path: filePath,
|
||||
+ stat: fs.statSync(filePath),
|
||||
+ base: extensionPath,
|
||||
+ contents: fs.createReadStream(filePath)
|
||||
+ }));
|
||||
+
|
||||
+ es.readArray(files).pipe(result);
|
||||
+ }).catch(err => {
|
||||
+ console.error('Failed to package copilot extension:', err);
|
||||
+ result.emit('error', err);
|
||||
+ });
|
||||
+
|
||||
+ // Apply the same package.json cleanup as bundled extensions get
|
||||
+ const cleaned = updateExtensionPackageJSON(
|
||||
+ result.pipe(rename(p => p.dirname = `extensions/copilot/${p.dirname}`)),
|
||||
+ (data: any) => {
|
||||
+ delete data.scripts;
|
||||
+ delete data.dependencies;
|
||||
+ delete data.devDependencies;
|
||||
+ if (data.main) {
|
||||
+ data.main = data.main.replace('/out/', '/dist/');
|
||||
+ }
|
||||
+ return data;
|
||||
+ }
|
||||
+ );
|
||||
+
|
||||
+ return minifyExtensionResources(cleaned)
|
||||
+ .pipe(util2.setExecutableBit(['**/*.sh']));
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * Materializes native dependency shims (`node-pty`, `ripgrep`) into the copilot
|
||||
+ * extension output at {@link outputDir}. Uses the root `node_modules` as the
|
||||
+ * source for native binaries, targeting the current platform/arch.
|
||||
+ *
|
||||
+ * This is the equivalent of what {@link copyCopilotNativeDepsTask} in
|
||||
+ * `gulpfile.vscode.ts` does during a full product build, but scoped to
|
||||
+ * just the standalone copilot extension output.
|
||||
+ *
|
||||
+ * Failures are logged as warnings rather than throwing, since the copilot
|
||||
+ * extension can still create shims at runtime if they are missing.
|
||||
+ */
|
||||
+export function prepareCopilotExtensionNativeShims(outputDir: string): void {
|
||||
+ const platform = process.platform;
|
||||
+ const arch = process.arch;
|
||||
+ const appNodeModulesDir = path.join(root, 'node_modules');
|
||||
+
|
||||
+ if (!fs.existsSync(outputDir)) {
|
||||
+ fancyLog.warn('[prepareCopilotExtensionNativeShims] Copilot extension not found at', outputDir, '- skipping shims');
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ try {
|
||||
+ prepareBuiltInCopilotExtensionShims(platform, arch, outputDir, appNodeModulesDir);
|
||||
+ fancyLog(`[prepareCopilotExtensionNativeShims] Materialized native shims for ${platform}-${arch}`);
|
||||
+ } catch (err) {
|
||||
+ // Downgrade to a warning for local builds since the extension
|
||||
+ // can still function without shims (it creates them at runtime).
|
||||
+ fancyLog.warn(`[prepareCopilotExtensionNativeShims] Failed to materialize shims: ${err}`);
|
||||
+ fancyLog.warn('[prepareCopilotExtensionNativeShims] The extension will still work but will create shims at runtime.');
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
export function packageMarketplaceExtensionsStream(forWeb: boolean): Stream {
|
||||
const marketplaceExtensionsDescriptions = [
|
||||
...builtInExtensions.filter(({ name }) => (forWeb ? !marketplaceWebExtensionsExclude.has(name) : true)),
|
||||
@@ -22,3 +22,4 @@ clipboard.diff
|
||||
display-language.diff
|
||||
trusted-domains.diff
|
||||
signature-verification.diff
|
||||
copilot.diff
|
||||
|
||||
Reference in New Issue
Block a user