Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
bf3b738
Try to align `scanBuiltinExtensions` with new esbuild changes
mjbvz Feb 17, 2026
5d1ee87
fixed to changes view
benibenj Feb 17, 2026
ab105ed
Allow workspace folder selection option when creating external termin…
anthonykim1 Feb 17, 2026
d692656
Fix tsgo ext build problem matching (#295603)
alexr00 Feb 17, 2026
2761b1c
Remove dead code
roblourens Feb 17, 2026
3a4a8ce
chat: allow stopping agent when message is queued (#295879)
connor4312 Feb 17, 2026
67da8fb
Merge pull request #295884 from microsoft/roblou/proposed-dormouse
roblourens Feb 17, 2026
fe7aa51
new model picker in sessions window (#295871)
sandy081 Feb 17, 2026
da135e4
queuing: interrupt when messages are sent during confirmation (#295866)
connor4312 Feb 17, 2026
48b2dca
improved yaml parser (#295833)
aeschli Feb 17, 2026
08534fd
Merge pull request #295812 from microsoft/dev/mjbvz/fix-295527
mjbvz Feb 17, 2026
0a1e0c9
debug: cancel debug launch when ESC is pressed on input variable dial…
na3shkw Feb 17, 2026
ec51417
Fix todo list widget border radius to match chat input (#295888)
daviddossett Feb 17, 2026
4d39872
Fix global /hooks stealing claude /hooks
roblourens Feb 18, 2026
8c4b950
Merge pull request #295896 from microsoft/roblou/attractive-ape
roblourens Feb 18, 2026
a77d179
Disallow tools running on canceled/complete chat requests
roblourens Feb 18, 2026
25f2063
Polish chat confirmation widget styling (#295890)
daviddossett Feb 18, 2026
039d493
Revert toolbar icons and labels to use regular foreground color (#295…
daviddossett Feb 18, 2026
5b40015
Merge pull request #295903 from microsoft/roblou/frozen-kangaroo
roblourens Feb 18, 2026
6b7de47
Merge pull request #295876 from microsoft/benibenj/minor-kingfisher
benibenj Feb 18, 2026
321e4e1
add console to chat from integrated browser (#295839)
justschen Feb 18, 2026
f7cc822
Fix /agents to open agent picker instead of agent configuration
roblourens Feb 18, 2026
a697c81
Action id constants
roblourens Feb 18, 2026
e67a6f8
Merge pull request #295916 from microsoft/roblou/boring-squid
roblourens Feb 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,11 @@
"owner": "typescript",
"applyTo": "closedDocuments",
"fileLocation": [
"absolute"
"relative",
"${workspaceFolder}"
],
"pattern": {
"regexp": "Error: ([^(]+)\\((\\d+|\\d+,\\d+|\\d+,\\d+,\\d+,\\d+)\\): (.*)$",
"regexp": "\\] ([^(]+)\\((\\d+,\\d+)\\): (.*)$",
"file": 1,
"location": 2,
"message": 3
Expand Down
40 changes: 39 additions & 1 deletion build/gulpfile.extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { EventEmitter } from 'events';
EventEmitter.defaultMaxListeners = 100;

import es from 'event-stream';
import fancyLog from 'fancy-log';
import glob from 'glob';
import gulp from 'gulp';
import filter from 'gulp-filter';
Expand All @@ -27,6 +28,25 @@ import watcher from './lib/watch/index.ts';
const root = path.dirname(import.meta.dirname);
const commit = getVersion(root);

// Tracks active extension compilations to emit aggregate
// "Starting compilation" / "Finished compilation" messages
// that the problem matcher in tasks.json relies on.
let activeExtensionCompilations = 0;

function onExtensionCompilationStart(): void {
if (activeExtensionCompilations === 0) {
fancyLog('Starting compilation');
}
activeExtensionCompilations++;
}

function onExtensionCompilationEnd(): void {
activeExtensionCompilations--;
if (activeExtensionCompilations === 0) {
fancyLog('Finished compilation');
}
}

// To save 250ms for each gulp startup, we are caching the result here
// const compilations = glob.sync('**/tsconfig.json', {
// cwd: extensionsPath,
Expand Down Expand Up @@ -175,7 +195,25 @@ const tasks = compilations.map(function (tsconfigFile) {
const nonts = gulp.src(src, srcOpts).pipe(filter(['**', '!**/*.ts'], { dot: true }));
const watchInput = watcher(src, { ...srcOpts, ...{ readDelay: 200 } });
const watchNonTs = watchInput.pipe(filter(['**', '!**/*.ts'], { dot: true })).pipe(gulp.dest(out));
const tsgoStream = watchInput.pipe(util.debounce(() => createTsgoStream(absolutePath, { taskName: 'extensions' }, () => rewriteTsgoSourceMappingUrlsIfNeeded(false, out, baseUrl)), 200));
const tsgoStream = watchInput.pipe(util.debounce(() => {
onExtensionCompilationStart();
const stream = createTsgoStream(absolutePath, { taskName: 'extensions' }, () => rewriteTsgoSourceMappingUrlsIfNeeded(false, out, baseUrl));
// Wrap in a result stream that always emits 'end' (even on
// error) so the debounce resets to idle and can process future
// file changes. Errors from tsgo (e.g. type errors causing a
// non-zero exit code) are already reported by spawnTsgo's
// runReporter, so swallowing the stream error is safe.
const result = es.through();
stream.on('end', () => {
onExtensionCompilationEnd();
result.emit('end');
});
stream.on('error', () => {
onExtensionCompilationEnd();
result.emit('end');
});
return result;
}, 200));
const watchStream = es.merge(nonts.pipe(gulp.dest(out)), watchNonTs, tsgoStream);

return watchStream;
Expand Down
12 changes: 6 additions & 6 deletions build/lib/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ interface IExtensionManifest {
/**
* Loosely based on `getExtensionKind` from `src/vs/workbench/services/extensions/common/extensionManifestPropertiesService.ts`
*/
function isWebExtension(manifest: IExtensionManifest): boolean {
export function isWebExtension(manifest: IExtensionManifest): boolean {
if (Boolean(manifest.browser)) {
return true;
}
Expand Down Expand Up @@ -578,11 +578,11 @@ export function packageMarketplaceExtensionsStream(forWeb: boolean): Stream {
}

export interface IScannedBuiltinExtension {
extensionPath: string;
packageJSON: any;
packageNLS?: any;
readmePath?: string;
changelogPath?: string;
readonly extensionPath: string;
readonly packageJSON: unknown;
readonly packageNLS: unknown | undefined;
readonly readmePath: string | undefined;
readonly changelogPath: string | undefined;
}

export function scanBuiltinExtensions(extensionsRoot: string, exclude: string[] = []): IScannedBuiltinExtension[] {
Expand Down
43 changes: 27 additions & 16 deletions build/lib/tsgo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@ import * as path from 'path';
const root = path.dirname(path.dirname(import.meta.dirname));
const npx = process.platform === 'win32' ? 'npx.cmd' : 'npx';
const ansiRegex = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
const timestampRegex = /^\[\d{2}:\d{2}:\d{2}\]\s*/;

export function spawnTsgo(projectPath: string, config: { taskName: string; noEmit?: boolean }, onComplete?: () => Promise<void> | void): Promise<void> {
function runReporter(stdError: string) {
const matches = (stdError || '').match(/error \w+: (.+)?/g);
fancyLog(`Finished ${ansiColors.green(config.taskName)} ${projectPath} with ${matches ? matches.length : 0} errors.`);
for (const match of matches || []) {
fancyLog.error(match);
function runReporter(output: string) {
const lines = (output || '').split('\n');
const errorLines = lines.filter(line => /error \w+:/.test(line));
if (errorLines.length > 0) {
fancyLog(`Finished ${ansiColors.green(config.taskName)} ${projectPath} with ${errorLines.length} errors.`);
for (const line of errorLines) {
fancyLog(line);
}
}
}

Expand All @@ -34,21 +38,28 @@ export function spawnTsgo(projectPath: string, config: { taskName: string; noEmi
shell: true
});

const handleData = (data: Buffer) => {
const lines = data.toString()
.split(/\r?\n/)
.map(line => line.replace(ansiRegex, '').trim())
.filter(line => line.length > 0)
.filter(line => !/Starting compilation|File change detected|Compilation complete/i.test(line));

runReporter(lines.join('\n'));
};
let stdoutData = '';
let stderrData = '';

child.stdout?.on('data', handleData);
child.stderr?.on('data', handleData);
child.stdout?.on('data', (data: Buffer) => {
stdoutData += data.toString();
});
child.stderr?.on('data', (data: Buffer) => {
stderrData += data.toString();
});

return new Promise<void>((resolve, reject) => {
child.on('exit', code => {
const allOutput = stdoutData + '\n' + stderrData;
const lines = allOutput
.split(/\r?\n/)
.map(line => line.replace(ansiRegex, '').trim())
.map(line => line.replace(timestampRegex, ''))
.filter(line => line.length > 0)
.filter(line => !/Starting compilation|File change detected|Compilation complete/i.test(line));

runReporter(lines.join('\n'));

if (code === 0) {
Promise.resolve(onComplete?.()).then(() => resolve(), reject);
} else {
Expand Down
43 changes: 27 additions & 16 deletions build/next/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { getVersion } from '../lib/getVersion.ts';
import product from '../../product.json' with { type: 'json' };
import packageJson from '../../package.json' with { type: 'json' };
import { useEsbuildTranspile } from '../buildConfig.ts';
import { isWebExtension, type IScannedBuiltinExtension } from '../lib/extensions.ts';

const globAsync = promisify(glob);

Expand Down Expand Up @@ -378,33 +379,43 @@ async function cleanDir(dir: string): Promise<void> {
* Scan for built-in extensions in the given directory.
* Returns an array of extension entries for the builtinExtensionsScannerService.
*/
function scanBuiltinExtensions(extensionsRoot: string): Array<{ extensionPath: string; packageJSON: unknown }> {
const result: Array<{ extensionPath: string; packageJSON: unknown }> = [];
function scanBuiltinExtensions(extensionsRoot: string): Array<IScannedBuiltinExtension> {
const scannedExtensions: Array<IScannedBuiltinExtension> = [];
const extensionsPath = path.join(REPO_ROOT, extensionsRoot);

if (!fs.existsSync(extensionsPath)) {
return result;
return scannedExtensions;
}

for (const entry of fs.readdirSync(extensionsPath, { withFileTypes: true })) {
if (!entry.isDirectory()) {
for (const extensionFolder of fs.readdirSync(extensionsPath)) {
const packageJSONPath = path.join(extensionsPath, extensionFolder, 'package.json');
if (!fs.existsSync(packageJSONPath)) {
continue;
}
const packageJsonPath = path.join(extensionsPath, entry.name, 'package.json');
if (fs.existsSync(packageJsonPath)) {
try {
const packageJSON = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
result.push({
extensionPath: entry.name,
packageJSON
});
} catch (e) {
// Skip invalid extensions
try {
const packageJSON = JSON.parse(fs.readFileSync(packageJSONPath, 'utf8'));
if (!isWebExtension(packageJSON)) {
continue;
}
const children = fs.readdirSync(path.join(extensionsPath, extensionFolder));
const packageNLSPath = children.filter(child => child === 'package.nls.json')[0];
const packageNLS = packageNLSPath ? JSON.parse(fs.readFileSync(path.join(extensionsPath, extensionFolder, packageNLSPath), 'utf8')) : undefined;
const readme = children.filter(child => /^readme(\.txt|\.md|)$/i.test(child))[0];
const changelog = children.filter(child => /^changelog(\.txt|\.md|)$/i.test(child))[0];

scannedExtensions.push({
extensionPath: extensionFolder,
packageJSON,
packageNLS,
readmePath: readme ? path.join(extensionFolder, readme) : undefined,
changelogPath: changelog ? path.join(extensionFolder, changelog) : undefined,
});
} catch (e) {
// Skip invalid extensions
}
}

return result;
return scannedExtensions;
}

/**
Expand Down
Loading
Loading