|
| 1 | +Index: code-server/lib/vscode/build/gulpfile.extensions.ts |
| 2 | +=================================================================== |
| 3 | +--- code-server.orig/lib/vscode/build/gulpfile.extensions.ts |
| 4 | ++++ code-server/lib/vscode/build/gulpfile.extensions.ts |
| 5 | +@@ -287,6 +287,29 @@ export const compileCopilotExtensionBuil |
| 6 | + gulp.task(compileCopilotExtensionBuildTask); |
| 7 | + |
| 8 | + /** |
| 9 | ++ * Compiles the built-in copilot extension with proper `.vscodeignore` filtering |
| 10 | ++ * and materializes native dependency shims (`node-pty`, `ripgrep`). |
| 11 | ++ * Produces output equivalent to what CI ships from the pre-built VSIX. |
| 12 | ++ * |
| 13 | ++ * The result is placed in `.build/extensions/copilot/` and can be copied |
| 14 | ++ * directly into a VS Code Insiders installation at: |
| 15 | ++ * `<insiders>/resources/app/extensions/copilot/` |
| 16 | ++ */ |
| 17 | ++export const compileCopilotExtensionFullBuildTask = task.define('compile-copilot-extension-full-build', task.series( |
| 18 | ++ // Step 1: Clean previous copilot build output |
| 19 | ++ task.define('clean-copilot-build', util.rimraf('.build/extensions/copilot')), |
| 20 | ++ // Step 2: Build and package with proper `.vscodeignore` filtering |
| 21 | ++ task.define('package-copilot-extension-full', () => ext.packageCopilotExtensionFullStream().pipe(gulp.dest('.build'))), |
| 22 | ++ // Step 3: Materialize native dependency shims (`node-pty`, `ripgrep`) |
| 23 | ++ task.define('copilot-extension-native-shims', () => { |
| 24 | ++ const copilotExtDir = path.join(root, '.build', 'extensions', 'copilot'); |
| 25 | ++ ext.prepareCopilotExtensionNativeShims(copilotExtDir); |
| 26 | ++ return Promise.resolve(); |
| 27 | ++ }) |
| 28 | ++)); |
| 29 | ++gulp.task(compileCopilotExtensionFullBuildTask); |
| 30 | ++ |
| 31 | ++/** |
| 32 | + * Compiles the extensions for the build. |
| 33 | + * This is essentially a helper task that combines {@link cleanExtensionsBuildTask}, {@link compileNonNativeExtensionsBuildTask} and {@link compileNativeExtensionsBuildTask} |
| 34 | + */ |
| 35 | +Index: code-server/lib/vscode/build/lib/extensions.ts |
| 36 | +=================================================================== |
| 37 | +--- code-server.orig/lib/vscode/build/lib/extensions.ts |
| 38 | ++++ code-server/lib/vscode/build/lib/extensions.ts |
| 39 | +@@ -24,6 +24,7 @@ import { getProductionDependencies } fro |
| 40 | + import { type IExtensionDefinition, getExtensionStream } from './builtInExtensions.ts'; |
| 41 | + import { fetchUrls, fetchGithub } from './fetch.ts'; |
| 42 | + import { createTsgoStream, spawnTsgo } from './tsgo.ts'; |
| 43 | ++import { prepareBuiltInCopilotExtensionShims } from './copilot.ts'; |
| 44 | + import vzip from 'gulp-vinyl-zip'; |
| 45 | + |
| 46 | + import { createRequire } from 'module'; |
| 47 | +@@ -482,6 +483,116 @@ export function packageCopilotExtensionS |
| 48 | + ).pipe(util2.setExecutableBit(['**/*.sh'])); |
| 49 | + } |
| 50 | + |
| 51 | ++/** |
| 52 | ++ * Package the built-in copilot extension as a properly filtered VSIX-equivalent. |
| 53 | ++ * Unlike {@link packageCopilotExtensionStream}, this uses vsce.listFiles with |
| 54 | ++ * PackageManager.Npm so that .vscodeignore is respected for dependency filtering, |
| 55 | ++ * producing output equivalent to what CI ships from the pre-built VSIX. |
| 56 | ++ */ |
| 57 | ++export function packageCopilotExtensionFullStream(): Stream { |
| 58 | ++ const vsce = require('@vscode/vsce') as typeof import('@vscode/vsce'); |
| 59 | ++ const extensionPath = path.join(root, 'extensions', 'copilot'); |
| 60 | ++ if (!fs.existsSync(extensionPath)) { |
| 61 | ++ return es.readArray([]); |
| 62 | ++ } |
| 63 | ++ |
| 64 | ++ const esbuildConfigFileName = '.esbuild.ts'; |
| 65 | ++ const esbuildScript = path.join(extensionPath, esbuildConfigFileName); |
| 66 | ++ if (!fs.existsSync(esbuildScript)) { |
| 67 | ++ throw new Error(`Copilot esbuild script not found at ${esbuildScript}`); |
| 68 | ++ } |
| 69 | ++ |
| 70 | ++ const result = es.through(); |
| 71 | ++ |
| 72 | ++ // Step 1: Run esbuild to compile the extension |
| 73 | ++ new Promise<void>((resolve, reject) => { |
| 74 | ++ const proc = cp.execFile(process.argv[0], [esbuildScript], { cwd: extensionPath }, (error, _stdout, stderr) => { |
| 75 | ++ if (error) { |
| 76 | ++ return reject(error); |
| 77 | ++ } |
| 78 | ++ const matches = (stderr || '').match(/\> (.+): error: (.+)?/g); |
| 79 | ++ fancyLog(`Bundled extension: ${ansiColors.yellow(path.join('copilot', esbuildConfigFileName))} with ${matches ? matches.length : 0} errors.`); |
| 80 | ++ for (const match of matches || []) { |
| 81 | ++ fancyLog.error(match); |
| 82 | ++ } |
| 83 | ++ return resolve(); |
| 84 | ++ }); |
| 85 | ++ proc.stdout!.on('data', (data) => { |
| 86 | ++ fancyLog(`${ansiColors.green('esbuilding copilot')}: ${data.toString('utf8')}`); |
| 87 | ++ }); |
| 88 | ++ }).then(() => { |
| 89 | ++ // Step 2: Use `vsce.listFiles` with Npm package manager so `.vscodeignore` |
| 90 | ++ // is applied to both source files AND `node_modules` dependencies. |
| 91 | ++ // This is the key difference from `packageCopilotExtensionStream` which |
| 92 | ++ // uses `PackageManager.None` and then blindly merges all production deps. |
| 93 | ++ return vsce.listFiles({ cwd: extensionPath, packageManager: vsce.PackageManager.Npm }); |
| 94 | ++ }).then(fileNames => { |
| 95 | ++ const files = fileNames |
| 96 | ++ .map(fileName => path.join(extensionPath, fileName)) |
| 97 | ++ .map(filePath => new File({ |
| 98 | ++ path: filePath, |
| 99 | ++ stat: fs.statSync(filePath), |
| 100 | ++ base: extensionPath, |
| 101 | ++ contents: fs.createReadStream(filePath) |
| 102 | ++ })); |
| 103 | ++ |
| 104 | ++ es.readArray(files).pipe(result); |
| 105 | ++ }).catch(err => { |
| 106 | ++ console.error('Failed to package copilot extension:', err); |
| 107 | ++ result.emit('error', err); |
| 108 | ++ }); |
| 109 | ++ |
| 110 | ++ // Apply the same package.json cleanup as bundled extensions get |
| 111 | ++ const cleaned = updateExtensionPackageJSON( |
| 112 | ++ result.pipe(rename(p => p.dirname = `extensions/copilot/${p.dirname}`)), |
| 113 | ++ (data: any) => { |
| 114 | ++ delete data.scripts; |
| 115 | ++ delete data.dependencies; |
| 116 | ++ delete data.devDependencies; |
| 117 | ++ if (data.main) { |
| 118 | ++ data.main = data.main.replace('/out/', '/dist/'); |
| 119 | ++ } |
| 120 | ++ return data; |
| 121 | ++ } |
| 122 | ++ ); |
| 123 | ++ |
| 124 | ++ return minifyExtensionResources(cleaned) |
| 125 | ++ .pipe(util2.setExecutableBit(['**/*.sh'])); |
| 126 | ++} |
| 127 | ++ |
| 128 | ++/** |
| 129 | ++ * Materializes native dependency shims (`node-pty`, `ripgrep`) into the copilot |
| 130 | ++ * extension output at {@link outputDir}. Uses the root `node_modules` as the |
| 131 | ++ * source for native binaries, targeting the current platform/arch. |
| 132 | ++ * |
| 133 | ++ * This is the equivalent of what {@link copyCopilotNativeDepsTask} in |
| 134 | ++ * `gulpfile.vscode.ts` does during a full product build, but scoped to |
| 135 | ++ * just the standalone copilot extension output. |
| 136 | ++ * |
| 137 | ++ * Failures are logged as warnings rather than throwing, since the copilot |
| 138 | ++ * extension can still create shims at runtime if they are missing. |
| 139 | ++ */ |
| 140 | ++export function prepareCopilotExtensionNativeShims(outputDir: string): void { |
| 141 | ++ const platform = process.platform; |
| 142 | ++ const arch = process.arch; |
| 143 | ++ const appNodeModulesDir = path.join(root, 'node_modules'); |
| 144 | ++ |
| 145 | ++ if (!fs.existsSync(outputDir)) { |
| 146 | ++ fancyLog.warn('[prepareCopilotExtensionNativeShims] Copilot extension not found at', outputDir, '- skipping shims'); |
| 147 | ++ return; |
| 148 | ++ } |
| 149 | ++ |
| 150 | ++ try { |
| 151 | ++ prepareBuiltInCopilotExtensionShims(platform, arch, outputDir, appNodeModulesDir); |
| 152 | ++ fancyLog(`[prepareCopilotExtensionNativeShims] Materialized native shims for ${platform}-${arch}`); |
| 153 | ++ } catch (err) { |
| 154 | ++ // Downgrade to a warning for local builds since the extension |
| 155 | ++ // can still function without shims (it creates them at runtime). |
| 156 | ++ fancyLog.warn(`[prepareCopilotExtensionNativeShims] Failed to materialize shims: ${err}`); |
| 157 | ++ fancyLog.warn('[prepareCopilotExtensionNativeShims] The extension will still work but will create shims at runtime.'); |
| 158 | ++ } |
| 159 | ++} |
| 160 | ++ |
| 161 | + export function packageMarketplaceExtensionsStream(forWeb: boolean): Stream { |
| 162 | + const marketplaceExtensionsDescriptions = [ |
| 163 | + ...builtInExtensions.filter(({ name }) => (forWeb ? !marketplaceWebExtensionsExclude.has(name) : true)), |
0 commit comments