mirror of
https://github.com/microsoft/vscode.git
synced 2026-08-23 15:34:20 +01:00
* pet: add achievements and accessory rewards Add persistent cross-window pet achievements with six enabled rewards, a standalone collection modal, account badges, and semantic unlock triggers. Add the body-owned accessory rig and atlases, unlock star and New state, accessibility help, fixtures, and tests while retaining disabled rewards for later re-enablement. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5c8a4f1e-3bb0-4d6f-a3ed-249fbcd4ce15 * pet: address achievement review feedback Defer customization observation until the pet is enabled, detect newly installed MCP servers independently of enablement, and fully clear legacy fork state on reset. Rename the Crown persistence ID and use contrast-paired badge colors for the New affordance. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5c8a4f1e-3bb0-4d6f-a3ed-249fbcd4ce15 * pet: update model and skill rewards Reward changing the model picker selection with the Construction Hard Hat, and reward adding a custom skill with the Crown. Keep the instructions achievement and Sailor Hat disabled for future use. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5c8a4f1e-3bb0-4d6f-a3ed-249fbcd4ce15 * pet: fix component fixture asset loading Serve pet fixture media from the source tree used by both Vite and the CI rspack server, remove the intentionally empty screenshot variant, and approve the new blocking fixture snapshots. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5c8a4f1e-3bb0-4d6f-a3ed-249fbcd4ce15 * pet: accept component fixture screenshots Record the authoritative Linux CI hashes for the new blocking pet achievement and accessory fixtures. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5c8a4f1e-3bb0-4d6f-a3ed-249fbcd4ce15 * pet: restore fake timers within unlock test Avoid leaving the renderer test clock installed after the unlock-state interaction test so later notebook and notification suites can advance timers normally. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5c8a4f1e-3bb0-4d6f-a3ed-249fbcd4ce15 * remove unused achievements for now * pet: remove unrelated branch changes Restore server command, session artifact, and chat pill files to current main after they were accidentally included with the dormant achievement cleanup. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5c8a4f1e-3bb0-4d6f-a3ed-249fbcd4ce15 --------- Copilot-Session: 5c8a4f1e-3bb0-4d6f-a3ed-249fbcd4ce15
256 lines
9.4 KiB
TypeScript
256 lines
9.4 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
import { gulp, rename, filter, jsonEditor } from './lib/gulp/facade.ts';
|
|
import * as path from 'path';
|
|
import * as cp from 'child_process';
|
|
import es from 'event-stream';
|
|
import * as util from './lib/util.ts';
|
|
import { getVersion } from './lib/getVersion.ts';
|
|
import * as task from './lib/gulp/task.ts';
|
|
import * as optimize from './lib/optimize.ts';
|
|
import { readISODate } from './lib/date.ts';
|
|
import product from '../product.json' with { type: 'json' };
|
|
import { getProductionDependencies } from './lib/dependencies.ts';
|
|
import vfs from 'vinyl-fs';
|
|
import packageJson from '../package.json' with { type: 'json' };
|
|
import { compileBuildWithManglingTask } from './gulpfile.compile.ts';
|
|
import { copyCodiconsTask } from './lib/compilation.ts';
|
|
import * as extensions from './lib/extensions.ts';
|
|
import buildfile from './buildfile.ts';
|
|
|
|
const REPO_ROOT = path.dirname(import.meta.dirname);
|
|
const BUILD_ROOT = path.dirname(REPO_ROOT);
|
|
const WEB_FOLDER = path.join(REPO_ROOT, 'remote', 'web');
|
|
|
|
const commit = getVersion(REPO_ROOT);
|
|
const quality = (product as { quality?: string }).quality;
|
|
const version = (quality && quality !== 'stable') ? `${packageJson.version}-${quality}` : packageJson.version;
|
|
|
|
// esbuild-based bundle for standalone web
|
|
function runEsbuildBundle(outDir: string, minify: boolean, nls: boolean, sourceMapBaseUrl?: string): Promise<void> {
|
|
return new Promise((resolve, reject) => {
|
|
const scriptPath = path.join(REPO_ROOT, 'build/next/index.ts');
|
|
const args = [scriptPath, 'bundle', '--out', outDir, '--target', 'web'];
|
|
if (minify) {
|
|
args.push('--minify');
|
|
args.push('--mangle-privates');
|
|
}
|
|
if (nls) {
|
|
args.push('--nls');
|
|
}
|
|
if (sourceMapBaseUrl) {
|
|
args.push('--source-map-base-url', sourceMapBaseUrl);
|
|
}
|
|
|
|
const proc = cp.spawn(process.execPath, args, {
|
|
cwd: REPO_ROOT,
|
|
stdio: 'inherit'
|
|
});
|
|
|
|
proc.on('error', reject);
|
|
proc.on('close', code => {
|
|
if (code === 0) {
|
|
resolve();
|
|
} else {
|
|
reject(new Error(`esbuild web bundle failed with exit code ${code} (outDir: ${outDir}, minify: ${minify}, nls: ${nls})`));
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
export const vscodeWebResourceIncludes = [
|
|
|
|
// NLS
|
|
'out-build/nls.messages.js',
|
|
|
|
// Accessibility Signals
|
|
'out-build/vs/platform/accessibilitySignal/browser/media/*.mp3',
|
|
'out-build/vs/workbench/contrib/agentsVoice/browser/media/*.mp3',
|
|
|
|
// Welcome
|
|
'out-build/vs/workbench/contrib/welcomeGettingStarted/common/media/**/*.{svg,png}',
|
|
'out-build/vs/workbench/contrib/welcomeOnboarding/browser/media/*.svg',
|
|
|
|
// Chat Pet
|
|
'out-build/vs/workbench/contrib/chat/browser/widget/media/chatPet/**/*.{gif,png}',
|
|
|
|
// Extensions
|
|
'out-build/vs/workbench/contrib/extensions/browser/media/{theme-icon.png,language-icon.svg}',
|
|
'out-build/vs/workbench/services/extensionManagement/common/media/*.{svg,png}',
|
|
|
|
// Webview
|
|
'out-build/vs/workbench/contrib/webview/browser/pre/*.{js,html}',
|
|
|
|
// Tree Sitter highlights
|
|
'out-build/vs/editor/common/languages/highlights/*.scm',
|
|
|
|
// Tree Sitter injections
|
|
'out-build/vs/editor/common/languages/injections/*.scm',
|
|
|
|
// Extension Host Worker
|
|
'out-build/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html'
|
|
];
|
|
|
|
const vscodeWebResources = [
|
|
|
|
// Includes
|
|
...vscodeWebResourceIncludes,
|
|
|
|
// Excludes
|
|
'!out-build/vs/**/{node,electron-browser,electron-main,electron-utility}/**',
|
|
'!out-build/vs/editor/standalone/**',
|
|
'!out-build/vs/workbench/**/*-tb.png',
|
|
'!out-build/vs/code/**/*-dev.html',
|
|
'!**/test/**'
|
|
];
|
|
|
|
const vscodeWebEntryPoints = [
|
|
buildfile.workerEditor,
|
|
buildfile.workerExtensionHost,
|
|
buildfile.workerNotebook,
|
|
buildfile.workerLanguageDetection,
|
|
buildfile.workerLocalFileSearch,
|
|
buildfile.workerOutputLinks,
|
|
buildfile.workerBackgroundTokenization,
|
|
buildfile.keyboardMaps,
|
|
buildfile.workbenchWeb,
|
|
buildfile.sessionsWeb,
|
|
].flat();
|
|
|
|
/**
|
|
* @param extensionsRoot The location where extension will be read from
|
|
* @param product The parsed product.json file contents
|
|
*/
|
|
export const createVSCodeWebFileContentMapper = (extensionsRoot: string, product: typeof import('../product.json')) => {
|
|
return (path: string): ((content: string) => string) | undefined => {
|
|
if (path.endsWith('vs/platform/product/common/product.js')) {
|
|
return content => {
|
|
const productConfiguration = JSON.stringify({
|
|
...product,
|
|
version,
|
|
commit,
|
|
date: readISODate('out-build')
|
|
});
|
|
return content.replace('/*BUILD->INSERT_PRODUCT_CONFIGURATION*/', () => productConfiguration.substr(1, productConfiguration.length - 2) /* without { and }*/);
|
|
};
|
|
} else if (path.endsWith('vs/workbench/services/extensionManagement/browser/builtinExtensionsScannerService.js')) {
|
|
return content => {
|
|
const builtinExtensions = JSON.stringify(extensions.scanBuiltinExtensions(extensionsRoot));
|
|
return content.replace('/*BUILD->INSERT_BUILTIN_EXTENSIONS*/', () => builtinExtensions.substr(1, builtinExtensions.length - 2) /* without [ and ]*/);
|
|
};
|
|
}
|
|
|
|
return undefined;
|
|
};
|
|
};
|
|
|
|
const bundleVSCodeWebTask = task.define('bundle-vscode-web-OLD', task.series(
|
|
util.rimraf('out-vscode-web'),
|
|
optimize.bundleTask(
|
|
{
|
|
out: 'out-vscode-web',
|
|
esm: {
|
|
src: 'out-build',
|
|
entryPoints: vscodeWebEntryPoints,
|
|
resources: vscodeWebResources,
|
|
fileContentMapper: createVSCodeWebFileContentMapper('.build/web/extensions', product)
|
|
}
|
|
}
|
|
)
|
|
));
|
|
|
|
const minifyVSCodeWebTask = task.define('minify-vscode-web-OLD', task.series(
|
|
bundleVSCodeWebTask,
|
|
util.rimraf('out-vscode-web-min'),
|
|
optimize.minifyTask('out-vscode-web', `https://main.vscode-cdn.net/sourcemaps/${commit}/core`)
|
|
));
|
|
task.task(minifyVSCodeWebTask);
|
|
|
|
// esbuild-based tasks (new)
|
|
const sourceMappingURLBase = `https://main.vscode-cdn.net/sourcemaps/${commit}`;
|
|
const esbuildBundleVSCodeWebTask = task.define('esbuild-vscode-web', () => runEsbuildBundle('out-vscode-web', false, true));
|
|
const esbuildBundleVSCodeWebMinTask = task.define('esbuild-vscode-web-min', () => runEsbuildBundle('out-vscode-web-min', true, true, `${sourceMappingURLBase}/core`));
|
|
|
|
function packageTask(sourceFolderName: string, destinationFolderName: string) {
|
|
const destination = path.join(BUILD_ROOT, destinationFolderName);
|
|
|
|
return () => {
|
|
const src = gulp.src(sourceFolderName + '/**', { base: '.' })
|
|
.pipe(rename(function (path) { path.dirname = path.dirname!.replace(new RegExp('^' + sourceFolderName), 'out'); }));
|
|
|
|
const extensions = gulp.src('.build/web/extensions/**', { base: '.build/web', dot: true });
|
|
|
|
const sources = es.merge(src, extensions)
|
|
.pipe(filter(['**', '!**/*.{js,css}.map'], { dot: true }));
|
|
|
|
const name = product.nameShort;
|
|
const packageJsonStream = gulp.src(['remote/web/package.json'], { base: 'remote/web' })
|
|
.pipe(jsonEditor({ name, version, type: 'module' }));
|
|
|
|
const license = gulp.src(['remote/LICENSE'], { base: 'remote', allowEmpty: true });
|
|
|
|
const productionDependencies = getProductionDependencies(WEB_FOLDER);
|
|
const dependenciesSrc = productionDependencies.map(d => path.relative(REPO_ROOT, d)).map(d => [`${d}/**`, `!${d}/**/{test,tests}/**`, `!${d}/.bin/**`]).flat();
|
|
|
|
const deps = gulp.src(dependenciesSrc, { base: 'remote/web', dot: true })
|
|
.pipe(filter(['**', '!**/package-lock.json']))
|
|
.pipe(util.cleanNodeModules(path.join(import.meta.dirname, '.webignore')));
|
|
|
|
const favicon = gulp.src('resources/server/favicon.ico', { base: 'resources/server' });
|
|
const manifest = gulp.src('resources/server/manifest.json', { base: 'resources/server' });
|
|
const pwaicons = es.merge(
|
|
gulp.src('resources/server/code-192.png', { base: 'resources/server' }),
|
|
gulp.src('resources/server/code-512.png', { base: 'resources/server' })
|
|
);
|
|
|
|
const all = es.merge(
|
|
packageJsonStream,
|
|
license,
|
|
sources,
|
|
deps,
|
|
favicon,
|
|
manifest,
|
|
pwaicons
|
|
);
|
|
|
|
const result = all
|
|
.pipe(util.skipDirectories())
|
|
.pipe(util.fixWin32DirectoryPermissions());
|
|
|
|
return result.pipe(vfs.dest(destination));
|
|
};
|
|
}
|
|
|
|
const compileWebExtensionsBuildTask = task.define('compile-web-extensions-build', task.series(
|
|
task.define('clean-web-extensions-build', util.rimraf('.build/web/extensions')),
|
|
task.define('bundle-web-extensions-build', () => extensions.packageAllLocalExtensionsStream(true, false).pipe(gulp.dest('.build/web'))),
|
|
task.define('bundle-marketplace-web-extensions-build', () => extensions.packageMarketplaceExtensionsStream(true).pipe(gulp.dest('.build/web'))),
|
|
task.define('bundle-web-extension-media-build', () => extensions.buildExtensionMedia(false, '.build/web/extensions')),
|
|
));
|
|
task.task(compileWebExtensionsBuildTask);
|
|
|
|
const dashed = (str: string) => (str ? `-${str}` : ``);
|
|
|
|
['', 'min'].forEach(minified => {
|
|
const sourceFolderName = `out-vscode-web${dashed(minified)}`;
|
|
const destinationFolderName = `vscode-web`;
|
|
|
|
const vscodeWebTaskCI = task.define(`vscode-web${dashed(minified)}-ci`, task.series(
|
|
copyCodiconsTask,
|
|
compileWebExtensionsBuildTask,
|
|
minified ? esbuildBundleVSCodeWebMinTask : esbuildBundleVSCodeWebTask,
|
|
util.rimraf(path.join(BUILD_ROOT, destinationFolderName)),
|
|
packageTask(sourceFolderName, destinationFolderName)
|
|
));
|
|
task.task(vscodeWebTaskCI);
|
|
|
|
const vscodeWebTask = task.define(`vscode-web${dashed(minified)}`, task.series(
|
|
compileBuildWithManglingTask,
|
|
vscodeWebTaskCI
|
|
));
|
|
task.task(vscodeWebTask);
|
|
});
|