Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
7db9c13
Initial plan
Copilot Feb 6, 2026
fa5eb11
Add allowTrustedDomains property to terminal sandbox network config
Copilot Feb 6, 2026
e36b368
Optimize domain deduplication using Set
Copilot Feb 6, 2026
0aecd1a
Extract ITrustedDomainService interface into contrib/url/common
Copilot Feb 6, 2026
208068c
Extract allowedDomains to variable for readability
Copilot Feb 6, 2026
40df840
Fix build error when using tsgo
mjbvz Feb 9, 2026
39009f2
Cleanup tsgo compile
mjbvz Feb 9, 2026
b7592cd
Force local window for debug renderer actions
Copilot Feb 9, 2026
f54d28f
Merge pull request #293923 from mjbvz/dev/mjbvz/live-vicuna
mjbvz Feb 9, 2026
692b629
Make chatHooks proposal self contained
mjbvz Feb 9, 2026
d779b1f
rerender sticky scroll only on line number change not on column chang…
aiday-mar Feb 9, 2026
8461f46
Merge pull request #293928 from mjbvz/dev/mjbvz/sure-rook
mjbvz Feb 9, 2026
0d90baf
Merge pull request #293931 from mjbvz/dev/mjbvz/great-anaconda
mjbvz Feb 9, 2026
783fa9d
Fix chat accessibility progress sound for queued and non-queued reque…
meganrogge Feb 9, 2026
9899b0a
use proper role (#293938)
meganrogge Feb 9, 2026
690522d
Use regular foreground for agent session list titles (#293927)
daviddossett Feb 9, 2026
384a718
Merge pull request #293330 from microsoft/copilot/update-trusted-doma…
jrieken Feb 9, 2026
e083e83
support claude rules (#293829)
aeschli Feb 9, 2026
91ce49b
Ask Question does not show that the session requires input from the u…
bpasero Feb 9, 2026
259c60a
Start moving core to use a push based chat sessions model
mjbvz Feb 9, 2026
0911b97
fix action list not scrolling (#294026)
meganrogge Feb 9, 2026
cd71c4b
do not fetch policy data if already fetched (#293995)
sandy081 Feb 9, 2026
66a6caf
Merge pull request #294030 from mjbvz/dev/mjbvz/amateur-leopon
mjbvz Feb 9, 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
4 changes: 2 additions & 2 deletions build/gulpfile.extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ const tasks = compilations.map(function (tsconfigFile) {
const compileTask = task.define(`compile-extension:${name}`, task.series(cleanTask, async () => {
const nonts = gulp.src(src, srcOpts).pipe(filter(['**', '!**/*.ts'], { dot: true }));
const copyNonTs = util.streamToPromise(nonts.pipe(gulp.dest(out)));
const tsgo = spawnTsgo(absolutePath, () => rewriteTsgoSourceMappingUrlsIfNeeded(false, out, baseUrl));
const tsgo = spawnTsgo(absolutePath, { reporterId: 'extensions' }, () => rewriteTsgoSourceMappingUrlsIfNeeded(false, out, baseUrl));

await Promise.all([copyNonTs, tsgo]);
}));
Expand All @@ -175,7 +175,7 @@ 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, () => rewriteTsgoSourceMappingUrlsIfNeeded(false, out, baseUrl)), 200));
const tsgoStream = watchInput.pipe(util.debounce(() => createTsgoStream(absolutePath, { reporterId: 'extensions' }, () => rewriteTsgoSourceMappingUrlsIfNeeded(false, out, baseUrl)), 200));
const watchStream = es.merge(nonts.pipe(gulp.dest(out)), watchNonTs, tsgoStream);

return watchStream;
Expand Down
20 changes: 9 additions & 11 deletions build/lib/tsgo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ 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;

export function spawnTsgo(projectPath: string, onComplete?: () => Promise<void> | void): Promise<void> {
const reporter = createReporter('extensions');
export function spawnTsgo(projectPath: string, config: { reporterId: string }, onComplete?: () => Promise<void> | void): Promise<void> {
const reporter = createReporter(config.reporterId);
let report: NodeJS.ReadWriteStream | undefined;

const beginReport = (emitError: boolean) => {
Expand All @@ -31,10 +31,9 @@ export function spawnTsgo(projectPath: string, onComplete?: () => Promise<void>
report = undefined;
};

const args = ['tsgo', '--project', projectPath, '--pretty', 'false', '--sourceMap', '--inlineSources'];

beginReport(false);

const args = ['tsgo', '--project', projectPath, '--pretty', 'false', '--sourceMap', '--inlineSources'];
const child = cp.spawn(npx, args, {
cwd: root,
stdio: ['ignore', 'pipe', 'pipe'],
Expand Down Expand Up @@ -79,7 +78,7 @@ export function spawnTsgo(projectPath: string, onComplete?: () => Promise<void>
child.stdout?.on('data', handleData);
child.stderr?.on('data', handleData);

const done = new Promise<void>((resolve, reject) => {
return new Promise<void>((resolve, reject) => {
child.on('exit', code => {
if (buffer.trim()) {
handleLine(buffer);
Expand All @@ -88,23 +87,22 @@ export function spawnTsgo(projectPath: string, onComplete?: () => Promise<void>
endReport();
if (code === 0) {
Promise.resolve(onComplete?.()).then(() => resolve(), reject);
return;
} else {
reject(new Error(`tsgo exited with code ${code ?? 'unknown'}`));
}
reject(new Error(`tsgo exited with code ${code ?? 'unknown'}`));
});

child.on('error', err => {
endReport();
reject(err);
});
});

return done;
}

export function createTsgoStream(projectPath: string, onComplete?: () => Promise<void> | void): NodeJS.ReadWriteStream {
export function createTsgoStream(projectPath: string, config: { reporterId: string }, onComplete?: () => Promise<void> | void): NodeJS.ReadWriteStream {
const stream = es.through();

spawnTsgo(projectPath, onComplete).then(() => {
spawnTsgo(projectPath, config, onComplete).then(() => {
stream.emit('end');
}).catch(() => {
// Errors are already reported by spawnTsgo via the reporter.
Expand Down
3 changes: 3 additions & 0 deletions extensions/prompt-basics/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
".instructions.md",
"copilot-instructions.md"
],
"filenamePatterns": [
"**/.claude/rules/**/*.md"
],
"configuration": "./language-configuration.json"
},
{
Expand Down
6 changes: 3 additions & 3 deletions src/vs/base/browser/ui/actionbar/actionViewItems.ts
Original file line number Diff line number Diff line change
Expand Up @@ -436,12 +436,12 @@ export class ActionViewItem extends BaseActionViewItem {
if (this.options.isTabList) {
this.label.setAttribute('aria-selected', this.action.checked ? 'true' : 'false');
} else {
this.label.setAttribute('aria-checked', this.action.checked ? 'true' : 'false');
this.label.setAttribute('role', 'checkbox');
this.label.setAttribute('aria-pressed', this.action.checked ? 'true' : 'false');
this.label.setAttribute('role', 'button');
}
} else {
this.label.classList.remove('checked');
this.label.removeAttribute(this.options.isTabList ? 'aria-selected' : 'aria-checked');
this.label.removeAttribute(this.options.isTabList ? 'aria-selected' : 'aria-pressed');
this.label.setAttribute('role', this.getDefaultAriaRole());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export class StickyScrollController extends Disposable implements IEditorContrib
private _minRebuildFromLine: number | undefined;
private _mouseTarget: EventTarget | null = null;
private _cursorPositionListener: IDisposable | undefined;
private _positionLineNumber: number | undefined;

private readonly _onDidChangeStickyScrollHeight = this._register(new Emitter<{ height: number }>());
public readonly onDidChangeStickyScrollHeight = this._onDidChangeStickyScrollHeight.event;
Expand Down Expand Up @@ -478,7 +479,11 @@ export class StickyScrollController extends Disposable implements IEditorContrib
const lineNumberOption = this._editor.getOption(EditorOption.lineNumbers);
if (lineNumberOption.renderType === RenderLineNumbersType.Relative) {
if (!this._cursorPositionListener) {
this._cursorPositionListener = this._editor.onDidChangeCursorPosition(() => {
this._cursorPositionListener = this._editor.onDidChangeCursorPosition((e) => {
if (this._positionLineNumber === e.position.lineNumber) {
return;
}
this._positionLineNumber = e.position.lineNumber;
this._showEndForLine = undefined;
this._renderStickyScroll(0);
});
Expand Down
11 changes: 11 additions & 0 deletions src/vs/platform/actionWidget/browser/actionList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -411,10 +411,20 @@ export class ActionList<T> extends Disposable {

focusPrevious() {
this._list.focusPrevious(1, true, undefined, this.focusCondition);
const focused = this._list.getFocus();
if (focused.length > 0) {
this._list.reveal(focused[0]);
}
this._list.domFocus();
}

focusNext() {
this._list.focusNext(1, true, undefined, this.focusCondition);
const focused = this._list.getFocus();
if (focused.length > 0) {
this._list.reveal(focused[0]);
}
this._list.domFocus();
}

acceptSelected(preview?: boolean) {
Expand Down Expand Up @@ -447,6 +457,7 @@ export class ActionList<T> extends Disposable {
}

private onFocus() {
this._list.domFocus();
const focused = this._list.getFocus();
if (focused.length === 0) {
return;
Expand Down
53 changes: 37 additions & 16 deletions src/vs/workbench/api/browser/mainThreadChatSessions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

import { raceCancellationError } from '../../../base/common/async.js';
import { CancellationToken } from '../../../base/common/cancellation.js';
import { Emitter, Event } from '../../../base/common/event.js';
import { isCancellationError } from '../../../base/common/errors.js';
import { Emitter } from '../../../base/common/event.js';
import { IMarkdownString, MarkdownString } from '../../../base/common/htmlContent.js';
import { Disposable, DisposableMap, DisposableStore, IDisposable } from '../../../base/common/lifecycle.js';
import { ResourceMap } from '../../../base/common/map.js';
Expand All @@ -24,7 +25,7 @@ import { ChatEditorInput } from '../../contrib/chat/browser/widgetHosts/editor/c
import { IChatRequestVariableEntry } from '../../contrib/chat/common/attachments/chatVariableEntries.js';
import { awaitStatsForSession } from '../../contrib/chat/common/chat.js';
import { IChatContentInlineReference, IChatProgress, IChatService, ResponseModelState } from '../../contrib/chat/common/chatService/chatService.js';
import { ChatSessionStatus, IChatSession, IChatSessionContentProvider, IChatSessionHistoryItem, IChatSessionItem, IChatSessionItemProvider, IChatSessionProviderOptionItem, IChatSessionsService } from '../../contrib/chat/common/chatSessionsService.js';
import { ChatSessionStatus, IChatSession, IChatSessionContentProvider, IChatSessionHistoryItem, IChatSessionItem, IChatSessionItemController, IChatSessionProviderOptionItem, IChatSessionsService } from '../../contrib/chat/common/chatSessionsService.js';
import { ChatAgentLocation } from '../../contrib/chat/common/constants.js';
import { IChatModel } from '../../contrib/chat/common/model/chatModel.js';
import { IChatAgentRequest } from '../../contrib/chat/common/participants/chatAgents.js';
Expand Down Expand Up @@ -322,8 +323,9 @@ export class ObservableChatSession extends Disposable implements IChatSession {

@extHostNamedCustomer(MainContext.MainThreadChatSessions)
export class MainThreadChatSessions extends Disposable implements MainThreadChatSessionsShape {
private readonly _itemProvidersRegistrations = this._register(new DisposableMap<number, IDisposable & {
readonly provider: IChatSessionItemProvider;
private readonly _itemControllerRegistrations = this._register(new DisposableMap<number, IDisposable & {
readonly chatSessionType: string;
readonly controller: IChatSessionItemController;
readonly onDidChangeItems: Emitter<void>;
}>());
private readonly _contentProvidersRegistrations = this._register(new DisposableMap<number>());
Expand Down Expand Up @@ -361,8 +363,8 @@ export class MainThreadChatSessions extends Disposable implements MainThreadChat
}));

this._register(this._agentSessionsService.model.onDidChangeSessionArchivedState(session => {
for (const [handle, { provider }] of this._itemProvidersRegistrations) {
if (provider.chatSessionType === session.providerType) {
for (const [handle, { chatSessionType }] of this._itemControllerRegistrations) {
if (chatSessionType === session.providerType) {
this._proxy.$onDidChangeChatSessionItemState(handle, session.resource, session.isArchived());
}
}
Expand All @@ -377,16 +379,35 @@ export class MainThreadChatSessions extends Disposable implements MainThreadChat
// Register the provider handle - this tracks that a provider exists
const disposables = new DisposableStore();
const changeEmitter = disposables.add(new Emitter<void>());
const provider: IChatSessionItemProvider = {
chatSessionType,
onDidChangeChatSessionItems: Event.debounce(changeEmitter.event, (_, e) => e, 200),
provideChatSessionItems: (token) => this._provideChatSessionItems(handle, token),


const self = this;

const controller = new class implements IChatSessionItemController {

items: IChatSessionItem[] = [];

get onDidChangeChatSessionItems() {
return changeEmitter.event;
}

async refresh(token: CancellationToken): Promise<void> {
try {
this.items = await self._provideChatSessionItems(handle, token);
} catch (err) {
if (isCancellationError(err)) {
return;
}
throw err;
}
}
};
disposables.add(this._chatSessionsService.registerChatSessionItemProvider(provider));
disposables.add(this._chatSessionsService.registerChatSessionItemController(chatSessionType, controller));

this._itemProvidersRegistrations.set(handle, {
this._itemControllerRegistrations.set(handle, {
dispose: () => disposables.dispose(),
provider,
chatSessionType,
controller,
onDidChangeItems: changeEmitter,
});

Expand All @@ -398,7 +419,7 @@ export class MainThreadChatSessions extends Disposable implements MainThreadChat
}

$onDidChangeChatSessionItems(handle: number): void {
this._itemProvidersRegistrations.get(handle)?.onDidChangeItems.fire();
this._itemControllerRegistrations.get(handle)?.onDidChangeItems.fire();
}

$onDidChangeChatSessionOptions(handle: number, sessionResourceComponents: UriComponents, updates: ReadonlyArray<{ optionId: string; value: string }>): void {
Expand All @@ -412,7 +433,7 @@ export class MainThreadChatSessions extends Disposable implements MainThreadChat
const modifiedResource = URI.revive(modifiedCompoennts);

this._logService.trace(`$onDidCommitChatSessionItem: handle(${handle}), original(${originalResource}), modified(${modifiedResource})`);
const chatSessionType = this._itemProvidersRegistrations.get(handle)?.provider.chatSessionType;
const chatSessionType = this._itemControllerRegistrations.get(handle)?.chatSessionType;
if (!chatSessionType) {
this._logService.error(`No chat session type found for provider handle ${handle}`);
return;
Expand Down Expand Up @@ -591,7 +612,7 @@ export class MainThreadChatSessions extends Disposable implements MainThreadChat
}

$unregisterChatSessionItemProvider(handle: number): void {
this._itemProvidersRegistrations.deleteAndDispose(handle);
this._itemControllerRegistrations.deleteAndDispose(handle);
}

$registerChatSessionContentProvider(handle: number, chatSessionScheme: string): void {
Expand Down
8 changes: 1 addition & 7 deletions src/vs/workbench/contrib/chat/browser/actions/chatActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -971,13 +971,7 @@ export function registerChatActions() {
category: CHAT_CATEGORY,
icon: Codicon.sparkle,
f1: true,
precondition: ChatContextKeys.enabled,
menu: {
id: CHAT_CONFIG_MENU_ID,
when: ContextKeyExpr.and(ChatContextKeys.enabled, ContextKeyExpr.equals('view', ChatViewId)),
order: 11,
group: '1_level'
}
precondition: ChatContextKeys.enabled
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { Extensions as QuickAccessExtensions, IQuickAccessRegistry } from '../..
import { ChatContextKeys } from '../../common/actions/chatContextKeys.js';
import { AgentSessionsViewerOrientation, AgentSessionsViewerPosition } from './agentSessions.js';
import { IAgentSessionsService, AgentSessionsService } from './agentSessionsService.js';
import { LocalAgentsSessionsProvider } from './localAgentSessionsProvider.js';
import { LocalAgentsSessionsController } from './localAgentSessionsProvider.js';
import { registerWorkbenchContribution2, WorkbenchPhase } from '../../../../common/contributions.js';
import { ISubmenuItem, MenuId, MenuRegistry, registerAction2 } from '../../../../../platform/actions/common/actions.js';
import { ArchiveAgentSessionAction, ArchiveAgentSessionSectionAction, UnarchiveAgentSessionAction, OpenAgentSessionInEditorGroupAction, OpenAgentSessionInNewEditorGroupAction, OpenAgentSessionInNewWindowAction, ShowAgentSessionsSidebar, HideAgentSessionsSidebar, ToggleAgentSessionsSidebar, RefreshAgentSessionsViewerAction, FindAgentSessionInViewerAction, MarkAgentSessionUnreadAction, MarkAgentSessionReadAction, FocusAgentSessionsAction, SetAgentSessionsOrientationStackedAction, SetAgentSessionsOrientationSideBySideAction, PickAgentSessionAction, ArchiveAllAgentSessionsAction, MarkAllAgentSessionsReadAction, RenameAgentSessionAction, DeleteAgentSessionAction, DeleteAllLocalSessionsAction, MarkAgentSessionSectionReadAction, ToggleShowAgentSessionsAction, UnarchiveAgentSessionSectionAction } from './agentSessionsActions.js';
Expand Down Expand Up @@ -169,7 +169,7 @@ Registry.as<IQuickAccessRegistry>(QuickAccessExtensions.Quickaccess).registerQui

//#region Workbench Contributions

registerWorkbenchContribution2(LocalAgentsSessionsProvider.ID, LocalAgentsSessionsProvider, WorkbenchPhase.AfterRestored);
registerWorkbenchContribution2(LocalAgentsSessionsController.ID, LocalAgentsSessionsController, WorkbenchPhase.AfterRestored);

registerSingleton(IAgentSessionsService, AgentSessionsService, InstantiationType.Delayed);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,11 @@ import { Schemas } from '../../../../../base/common/network.js';
import { IWorkbenchContribution } from '../../../../common/contributions.js';
import { IChatModel } from '../../common/model/chatModel.js';
import { convertLegacyChatSessionTiming, IChatDetail, IChatService, ResponseModelState } from '../../common/chatService/chatService.js';
import { ChatSessionStatus, IChatSessionItem, IChatSessionItemProvider, IChatSessionsService, localChatSessionType } from '../../common/chatSessionsService.js';
import { ChatSessionStatus, IChatSessionItem, IChatSessionItemController, IChatSessionsService, localChatSessionType } from '../../common/chatSessionsService.js';
import { getChatSessionType } from '../../common/model/chatUri.js';
import { ILogService } from '../../../../../platform/log/common/log.js';

interface IChatSessionItemWithProvider extends IChatSessionItem {
readonly provider: IChatSessionItemProvider;
}

export class LocalAgentsSessionsProvider extends Disposable implements IChatSessionItemProvider, IWorkbenchContribution {
export class LocalAgentsSessionsController extends Disposable implements IChatSessionItemController, IWorkbenchContribution {

static readonly ID = 'workbench.contrib.localAgentsSessionsProvider';

Expand All @@ -40,11 +36,20 @@ export class LocalAgentsSessionsProvider extends Disposable implements IChatSess
) {
super();

this._register(this.chatSessionsService.registerChatSessionItemProvider(this));
this._register(this.chatSessionsService.registerChatSessionItemController(this.chatSessionType, this));

this.registerListeners();
}

private _items: IChatSessionItem[] = [];
get items(): readonly IChatSessionItem[] {
return this._items;
}

async refresh(token: CancellationToken): Promise<void> {
this._items = await this.provideChatSessionItems(token);
}

private registerListeners(): void {
this._register(this.chatSessionsService.registerChatModelChangeListeners(
this.chatService,
Expand All @@ -66,8 +71,8 @@ export class LocalAgentsSessionsProvider extends Disposable implements IChatSess
}));
}

async provideChatSessionItems(token: CancellationToken): Promise<IChatSessionItem[]> {
const sessions: IChatSessionItemWithProvider[] = [];
private async provideChatSessionItems(token: CancellationToken): Promise<IChatSessionItem[]> {
const sessions: IChatSessionItem[] = [];
const sessionsByResource = new ResourceSet();

for (const sessionDetail of await this.chatService.getLiveSessionItems()) {
Expand All @@ -88,7 +93,7 @@ export class LocalAgentsSessionsProvider extends Disposable implements IChatSess
return sessions;
}

private async getHistoryItems(): Promise<IChatSessionItemWithProvider[]> {
private async getHistoryItems(): Promise<IChatSessionItem[]> {
try {
const historyItems = await this.chatService.getHistorySessionItems();

Expand All @@ -98,7 +103,7 @@ export class LocalAgentsSessionsProvider extends Disposable implements IChatSess
}
}

private toChatSessionItem(chat: IChatDetail): IChatSessionItemWithProvider | undefined {
private toChatSessionItem(chat: IChatDetail): IChatSessionItem | undefined {
const model = this.chatService.getSession(chat.sessionResource);

let description: string | undefined;
Expand All @@ -112,7 +117,6 @@ export class LocalAgentsSessionsProvider extends Disposable implements IChatSess

return {
resource: chat.sessionResource,
provider: this,
label: chat.title,
description,
status: model ? this.modelToStatus(model) : this.chatResponseStateToStatus(chat.lastResponseState),
Expand Down
Loading
Loading