From 464aacc8870280509220121cacedfe5553dda96e Mon Sep 17 00:00:00 2001 From: Johannes Date: Fri, 7 Nov 2025 11:14:03 +0100 Subject: [PATCH 01/28] Revert "lock inline chat to its own agent so that must intellisense is disabled" This reverts commit f04c75b832383fdeeb7399d9a5aad5470ef8c544. --- .../inlineChat/browser/inlineChatController.ts | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index 2db18e0e9fb3..0b860c317048 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -14,7 +14,7 @@ import { Lazy } from '../../../../base/common/lazy.js'; import { DisposableStore, MutableDisposable, toDisposable } from '../../../../base/common/lifecycle.js'; import { Schemas } from '../../../../base/common/network.js'; import { MovingAverage } from '../../../../base/common/numbers.js'; -import { autorun, derived, IObservable, observableFromEvent, observableSignalFromEvent, observableValue, waitForState } from '../../../../base/common/observable.js'; +import { autorun, derived, IObservable, observableSignalFromEvent, observableValue, waitForState } from '../../../../base/common/observable.js'; import { isEqual } from '../../../../base/common/resources.js'; import { StopWatch } from '../../../../base/common/stopwatch.js'; import { assertType } from '../../../../base/common/types.js'; @@ -49,7 +49,6 @@ import { ISharedWebContentExtractorService } from '../../../../platform/webConte import { IEditorService, SIDE_GROUP } from '../../../services/editor/common/editorService.js'; import { IChatAttachmentResolveService } from '../../chat/browser/chatAttachmentResolveService.js'; import { IChatWidgetLocationOptions } from '../../chat/browser/chatWidget.js'; -import { IChatAgentService } from '../../chat/common/chatAgents.js'; import { ChatContextKeys } from '../../chat/common/chatContextKeys.js'; import { IChatEditingSession, ModifiedFileEntryState } from '../../chat/common/chatEditingService.js'; import { ChatRequestRemovalReason, IChatRequestModel, IChatTextEditGroup, IChatTextEditGroupState, IResponse } from '../../chat/common/chatModel.js'; @@ -1270,7 +1269,7 @@ export class InlineChatController2 implements IEditorContribution { @IChatAttachmentResolveService private readonly _chatAttachmentResolveService: IChatAttachmentResolveService, @IEditorService private readonly _editorService: IEditorService, @IMarkerDecorationsService private readonly _markerDecorationsService: IMarkerDecorationsService, - @IChatAgentService chatAgentService: IChatAgentService, + @IInlineChatSessionService inlineChatService: IInlineChatSessionService, @IChatService chatService: IChatService, ) { @@ -1336,21 +1335,8 @@ export class InlineChatController2 implements IEditorContribution { { editor: this._editor, notebookEditor }, ); - this._store.add(result); - result.domNode.classList.add('inline-chat-2'); - // agent lock - const agentObs = observableFromEvent(this, chatAgentService.onDidChangeAgents, () => chatAgentService.getDefaultAgent(ChatAgentLocation.EditorInline)); - this._store.add(autorun(r => { - const agent = agentObs.read(r); - if (agent) { - result.widget.chatWidget.lockToCodingAgent(agent.name, agent.fullName || agent.name, agent.id); - } else { - result.widget.chatWidget.unlockFromCodingAgent(); - } - })); - return result; }); From a2ee7fa2175cacbfc593efc3d1f5a91d7f77b443 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 7 Nov 2025 14:44:38 +0100 Subject: [PATCH 02/28] add debug logging #276060 (#276063) --- .../services/accounts/common/defaultAccount.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/services/accounts/common/defaultAccount.ts b/src/vs/workbench/services/accounts/common/defaultAccount.ts index 92cb9d5feb33..0e01f666b360 100644 --- a/src/vs/workbench/services/accounts/common/defaultAccount.ts +++ b/src/vs/workbench/services/accounts/common/defaultAccount.ts @@ -161,7 +161,7 @@ export class DefaultAccountManagementContribution extends Disposable implements await this.extensionService.whenInstalledExtensionsRegistered(); const declaredProvider = this.authenticationService.declaredProviders.find(provider => provider.id === defaultAccountProviderId); if (!declaredProvider) { - this.logService.info(`Default account authentication provider ${defaultAccountProviderId} is not declared.`); + this.logService.info(`[DefaultAccount] Authentication provider is not declared.`, defaultAccountProviderId); return; } @@ -200,7 +200,7 @@ export class DefaultAccountManagementContribution extends Disposable implements const [key, value] = field.split('='); result.set(key, value); } - this.logService.trace(`DefaultAccount#extractFromToken: ${JSON.stringify(Object.fromEntries(result))}`); + this.logService.debug(`[DefaultAccount] extractFromToken: ${JSON.stringify(Object.fromEntries(result))}`); return result; } @@ -209,6 +209,7 @@ export class DefaultAccountManagementContribution extends Disposable implements const session = sessions.find(s => this.scopesMatch(s.scopes, scopes)); if (!session) { + this.logService.debug('[DefaultAccount] No matching session found', authProviderId); return null; } @@ -236,6 +237,7 @@ export class DefaultAccountManagementContribution extends Disposable implements private async getTokenEntitlements(accessToken: string): Promise> { const tokenEntitlementsUrl = this.getTokenEntitlementUrl(); if (!tokenEntitlementsUrl) { + this.logService.debug('[DefaultAccount] No token entitlements URL found'); return {}; } @@ -271,6 +273,7 @@ export class DefaultAccountManagementContribution extends Disposable implements private async getChatEntitlements(accessToken: string): Promise> { const chatEntitlementsUrl = this.getChatEntitlementUrl(); if (!chatEntitlementsUrl) { + this.logService.debug('[DefaultAccount] No chat entitlements URL found'); return {}; } @@ -298,6 +301,7 @@ export class DefaultAccountManagementContribution extends Disposable implements private async getMcpRegistryProvider(accessToken: string): Promise { const mcpRegistryDataUrl = this.getMcpRegistryDataUrl(); if (!mcpRegistryDataUrl) { + this.logService.debug('[DefaultAccount] No MCP registry data URL found'); return undefined; } @@ -316,7 +320,7 @@ export class DefaultAccountManagementContribution extends Disposable implements this.logService.debug('Fetched MCP registry providers', data.mcp_registries); return data.mcp_registries[0]; } - this.logService.error('Failed to fetch MCP registry providers', 'No data returned'); + this.logService.debug('Failed to fetch MCP registry providers', 'No data returned'); } catch (error) { this.logService.error('Failed to fetch MCP registry providers', getErrorMessage(error)); } From b052f402df32e3c41b862c2e8433c6e371ab740c Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Fri, 7 Nov 2025 14:45:06 +0100 Subject: [PATCH 03/28] Changes defaul of triggerCommandOnProviderChange to false. (#276070) Changes defaul of triggerCommandOnProviderChange to false. Fixes https://github.com/microsoft/vscode/issues/276065 --- src/vs/editor/common/config/editorOptions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index d47b46e4f17f..45a1772562ff 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -4495,7 +4495,7 @@ class InlineEditorSuggest extends BaseEditorOption Date: Fri, 7 Nov 2025 14:06:35 +0000 Subject: [PATCH 04/28] SCM - fix rendering issue with incoming changes node (#276055) (#276073) SCM - fix rendering issue with incoming/outgoing changes nodes --- .../contrib/scm/browser/scmHistoryViewPane.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/scm/browser/scmHistoryViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmHistoryViewPane.ts index 4c03f38c193d..7d6719bfcd42 100644 --- a/src/vs/workbench/contrib/scm/browser/scmHistoryViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmHistoryViewPane.ts @@ -1250,14 +1250,22 @@ class SCMHistoryViewModel extends Disposable { // Create the color map const colorMap = this._getGraphColorMap(historyItemRefs); + // Only show incoming changes node if the remote history item reference is part of the graph + const addIncomingChangesNode = this._scmViewService.graphShowIncomingChangesConfig.get() + && historyItemRefs.some(ref => ref.id === historyItemRemoteRef?.id); + + // Only show outgoing changes node if the history item reference is part of the graph + const addOutgoingChangesNode = this._scmViewService.graphShowOutgoingChangesConfig.get() + && historyItemRefs.some(ref => ref.id === historyItemRef?.id); + const viewModels = toISCMHistoryItemViewModelArray( historyItems, colorMap, historyProvider.historyItemRef.get(), historyProvider.historyItemRemoteRef.get(), historyProvider.historyItemBaseRef.get(), - this._scmViewService.graphShowIncomingChangesConfig.get(), - this._scmViewService.graphShowOutgoingChangesConfig.get(), + addIncomingChangesNode, + addOutgoingChangesNode, mergeBase) .map(historyItemViewModel => ({ repository, From b2803883955bc4699ff3b2b78eb7be53fa5e282e Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 7 Nov 2025 16:38:19 +0100 Subject: [PATCH 05/28] add more logs (#276093) --- .../accounts/common/defaultAccount.ts | 59 ++++++++++++------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/src/vs/workbench/services/accounts/common/defaultAccount.ts b/src/vs/workbench/services/accounts/common/defaultAccount.ts index 0e01f666b360..feb482006f60 100644 --- a/src/vs/workbench/services/accounts/common/defaultAccount.ts +++ b/src/vs/workbench/services/accounts/common/defaultAccount.ts @@ -149,16 +149,22 @@ export class DefaultAccountManagementContribution extends Disposable implements } private async initialize(): Promise { + this.logService.debug('[DefaultAccount] Starting initialization'); + if (!this.productService.defaultAccount) { + this.logService.debug('[DefaultAccount] No default account configuration in product service, skipping initialization'); return; } const defaultAccountProviderId = this.getDefaultAccountProviderId(); + this.logService.debug('[DefaultAccount] Default account provider ID:', defaultAccountProviderId); if (!defaultAccountProviderId) { return; } await this.extensionService.whenInstalledExtensionsRegistered(); + this.logService.debug('[DefaultAccount] Installed extensions registered.'); + const declaredProvider = this.authenticationService.declaredProviders.find(provider => provider.id === defaultAccountProviderId); if (!declaredProvider) { this.logService.info(`[DefaultAccount] Authentication provider is not declared.`, defaultAccountProviderId); @@ -180,6 +186,7 @@ export class DefaultAccountManagementContribution extends Disposable implements this.setDefaultAccount(await this.getDefaultAccountFromAuthenticatedSessions(defaultAccountProviderId, this.productService.defaultAccount!.authenticationProvider.scopes)); })); + this.logService.debug('[DefaultAccount] Initialization complete'); } private setDefaultAccount(account: IDefaultAccount | null): void { @@ -187,8 +194,10 @@ export class DefaultAccountManagementContribution extends Disposable implements this.defaultAccountService.setDefaultAccount(this.defaultAccount); if (this.defaultAccount) { this.accountStatusContext.set(DefaultAccountStatus.Available); + this.logService.debug('[DefaultAccount] Account status set to Available'); } else { this.accountStatusContext.set(DefaultAccountStatus.Unavailable); + this.logService.debug('[DefaultAccount] Account status set to Unavailable'); } } @@ -205,29 +214,37 @@ export class DefaultAccountManagementContribution extends Disposable implements } private async getDefaultAccountFromAuthenticatedSessions(authProviderId: string, scopes: string[]): Promise { - const sessions = await this.authenticationService.getSessions(authProviderId, undefined, undefined, true); - const session = sessions.find(s => this.scopesMatch(s.scopes, scopes)); + try { + this.logService.debug('[DefaultAccount] Getting Default Account from authenticated sessions for provider:', authProviderId); + const sessions = await this.authenticationService.getSessions(authProviderId, undefined, undefined, true); + const session = sessions.find(s => this.scopesMatch(s.scopes, scopes)); - if (!session) { - this.logService.debug('[DefaultAccount] No matching session found', authProviderId); + if (!session) { + this.logService.debug('[DefaultAccount] No matching session found for provider:', authProviderId); + return null; + } + + const [chatEntitlements, tokenEntitlements] = await Promise.all([ + this.getChatEntitlements(session.accessToken), + this.getTokenEntitlements(session.accessToken), + ]); + + const mcpRegistryProvider = tokenEntitlements.mcp ? await this.getMcpRegistryProvider(session.accessToken) : undefined; + + const account = { + sessionId: session.id, + enterprise: this.isEnterpriseAuthenticationProvider(authProviderId) || session.account.label.includes('_'), + ...chatEntitlements, + ...tokenEntitlements, + mcpRegistryUrl: mcpRegistryProvider?.url, + mcpAccess: mcpRegistryProvider?.registry_access, + }; + this.logService.debug('[DefaultAccount] Successfully created default account for provider:', authProviderId); + return account; + } catch (error) { + this.logService.error('[DefaultAccount] Failed to create default account for provider:', authProviderId, getErrorMessage(error)); return null; } - - const [chatEntitlements, tokenEntitlements] = await Promise.all([ - this.getChatEntitlements(session.accessToken), - this.getTokenEntitlements(session.accessToken), - ]); - - const mcpRegistryProvider = tokenEntitlements.mcp ? await this.getMcpRegistryProvider(session.accessToken) : undefined; - - return { - sessionId: session.id, - enterprise: this.isEnterpriseAuthenticationProvider(authProviderId) || session.account.label.includes('_'), - ...chatEntitlements, - ...tokenEntitlements, - mcpRegistryUrl: mcpRegistryProvider?.url, - mcpAccess: mcpRegistryProvider?.registry_access, - }; } private scopesMatch(scopes: ReadonlyArray, expectedScopes: string[]): boolean { @@ -241,6 +258,7 @@ export class DefaultAccountManagementContribution extends Disposable implements return {}; } + this.logService.debug('[DefaultAccount] Fetching token entitlements from:', tokenEntitlementsUrl); try { const chatContext = await this.requestService.request({ type: 'GET', @@ -277,6 +295,7 @@ export class DefaultAccountManagementContribution extends Disposable implements return {}; } + this.logService.debug('[DefaultAccount] Fetching chat entitlements from:', chatEntitlementsUrl); try { const context = await this.requestService.request({ type: 'GET', From 6334e872891a3ed53200dace2b4ece1b443d746a Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Fri, 7 Nov 2025 10:02:28 -0800 Subject: [PATCH 06/28] Merge pull request #276138 from microsoft/connor4312/fix-wrong-schema-url-cp tools: fix wrong data passed to tool schema uri --- .../toolInvocationParts/chatToolConfirmationSubPart.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/chat/browser/chatContentParts/toolInvocationParts/chatToolConfirmationSubPart.ts b/src/vs/workbench/contrib/chat/browser/chatContentParts/toolInvocationParts/chatToolConfirmationSubPart.ts index 1370e86e3f7c..a01b0e3451a4 100644 --- a/src/vs/workbench/contrib/chat/browser/chatContentParts/toolInvocationParts/chatToolConfirmationSubPart.ts +++ b/src/vs/workbench/contrib/chat/browser/chatContentParts/toolInvocationParts/chatToolConfirmationSubPart.ts @@ -185,7 +185,7 @@ export class ToolConfirmationSubPart extends AbstractToolConfirmationSubPart { )); const markerOwner = generateUuid(); - const schemaUri = createToolSchemaUri(toolInvocation.toolCallId); + const schemaUri = createToolSchemaUri(toolInvocation.toolId); const validator = new RunOnceScheduler(async () => { const newMarker: IMarkerData[] = []; From f7154468b54568f02020407cbbe94b779b384de7 Mon Sep 17 00:00:00 2001 From: Matt Bierner <12821956+mjbvz@users.noreply.github.com> Date: Fri, 7 Nov 2025 11:20:33 -0800 Subject: [PATCH 07/28] Use legacy lookup for chat session Fixes #276167 Workaround until we get proper fix as part of #274403 --- .../contrib/chat/browser/languageModelToolsService.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/languageModelToolsService.ts b/src/vs/workbench/contrib/chat/browser/languageModelToolsService.ts index 950a09461064..4cfe60b1ec82 100644 --- a/src/vs/workbench/contrib/chat/browser/languageModelToolsService.ts +++ b/src/vs/workbench/contrib/chat/browser/languageModelToolsService.ts @@ -37,7 +37,6 @@ import { ChatModel } from '../common/chatModel.js'; import { IVariableReference } from '../common/chatModes.js'; import { ChatToolInvocation } from '../common/chatProgressTypes/chatToolInvocation.js'; import { ConfirmedReason, IChatService, IChatToolInvocation, ToolConfirmKind } from '../common/chatService.js'; -import { LocalChatSessionUri } from '../common/chatUri.js'; import { ChatRequestToolReferenceEntry, toToolSetVariableEntry, toToolVariableEntry } from '../common/chatVariableEntries.js'; import { ChatConfiguration } from '../common/constants.js'; import { ILanguageModelToolsConfirmationService } from '../common/languageModelToolsConfirmationService.js'; @@ -267,7 +266,7 @@ export class LanguageModelToolsService extends Disposable implements ILanguageMo try { if (dto.context) { store = new DisposableStore(); - const model = this._chatService.getSession(LocalChatSessionUri.forSession(dto.context.sessionId)) as ChatModel | undefined; + const model = this._chatService.getSessionByLegacyId(dto.context.sessionId) as ChatModel | undefined; if (!model) { throw new Error(`Tool called for unknown chat session`); } From 116e2c59034cd6ef1b6ec0524edeac1b56a89f99 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Fri, 7 Nov 2025 16:20:46 -0500 Subject: [PATCH 08/28] get hidden chat terminal count to update (#276179) get hidden chat terminal count to update (#276163) --- .../contrib/terminal/browser/terminal.ts | 2 +- .../terminal/browser/terminalService.ts | 1 + .../terminal/browser/terminalTabbedView.ts | 7 +++++-- .../terminal/browser/terminalTabsChatEntry.ts | 20 +++++++++---------- .../chat/browser/terminalChatActions.ts | 2 +- .../chat/browser/terminalChatService.ts | 12 +++++++---- 6 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index 5372e518f440..99d4879266b7 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -132,7 +132,7 @@ export interface ITerminalChatService { * Returns the list of terminal instances that have been registered with a tool session id. * This is used for surfacing tool-driven/background terminals in UI (eg. quick picks). */ - getToolSessionTerminalInstances(): readonly ITerminalInstance[]; + getToolSessionTerminalInstances(hiddenOnly?: boolean): readonly ITerminalInstance[]; /** * Returns the tool session ID for a given terminal instance, if it has been registered. diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index 2a89cf343a79..f3c393fc2b49 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -1036,6 +1036,7 @@ export class TerminalService extends Disposable implements ITerminalService { this._onDidDisposeInstance.fire(instance); }) ]); + this._onDidChangeInstances.fire(); return instance; } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts b/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts index 068a4c19933a..95b836afefb4 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts @@ -173,16 +173,19 @@ export class TerminalTabbedView extends Disposable { private _shouldShowTabs(): boolean { const enabled = this._terminalConfigurationService.config.tabs.enabled; const hide = this._terminalConfigurationService.config.tabs.hideCondition; - const hasChatTerminals = this._terminalChatService.getToolSessionTerminalInstances().length > 0; + const hiddenChatTerminals = this._terminalChatService.getToolSessionTerminalInstances(true); if (!enabled) { return false; } + if (hiddenChatTerminals.length > 0) { + return true; + } if (hide === 'never') { return true; } - if (this._terminalGroupService.instances.length && hasChatTerminals) { + if (this._terminalGroupService.instances.length) { return true; } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalTabsChatEntry.ts b/src/vs/workbench/contrib/terminal/browser/terminalTabsChatEntry.ts index beb7bb97a7a2..a536c00ea8de 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalTabsChatEntry.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalTabsChatEntry.ts @@ -11,7 +11,6 @@ import { localize } from '../../../../nls.js'; import { ICommandService } from '../../../../platform/commands/common/commands.js'; import { ITerminalChatService } from './terminal.js'; import * as dom from '../../../../base/browser/dom.js'; -import { IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js'; export class TerminalTabsChatEntry extends Disposable { @@ -29,7 +28,6 @@ export class TerminalTabsChatEntry extends Disposable { private readonly _tabContainer: HTMLElement, @ICommandService private readonly _commandService: ICommandService, @ITerminalChatService private readonly _terminalChatService: ITerminalChatService, - @IContextKeyService private readonly _contextKeyService: IContextKeyService, ) { super(); @@ -55,6 +53,7 @@ export class TerminalTabsChatEntry extends Disposable { runChatTerminalsCommand(); } })); + this.update(); } get element(): HTMLElement { @@ -62,9 +61,8 @@ export class TerminalTabsChatEntry extends Disposable { } update(): void { - const chatTerminalCount = this._terminalChatService.getToolSessionTerminalInstances().length; - - if (!this._contextKeyService.getContextKeyValue('hasHiddenChatTerminals')) { + const hiddenChatTerminalCount = this._terminalChatService.getToolSessionTerminalInstances(true).length; + if (hiddenChatTerminalCount <= 0) { this._entry.style.display = 'none'; this._label.textContent = ''; this._entry.removeAttribute('aria-label'); @@ -75,16 +73,16 @@ export class TerminalTabsChatEntry extends Disposable { this._entry.style.display = ''; const hasText = this._tabContainer.classList.contains('has-text'); if (hasText) { - this._label.textContent = chatTerminalCount === 1 - ? localize('terminal.tabs.chatEntryLabelSingle', "{0} Hidden Terminal", chatTerminalCount) - : localize('terminal.tabs.chatEntryLabelPlural', "{0} Hidden Terminals", chatTerminalCount); + this._label.textContent = hiddenChatTerminalCount === 1 + ? localize('terminal.tabs.chatEntryLabelSingle', "{0} Hidden Terminal", hiddenChatTerminalCount) + : localize('terminal.tabs.chatEntryLabelPlural', "{0} Hidden Terminals", hiddenChatTerminalCount); } else { - this._label.textContent = `${chatTerminalCount}`; + this._label.textContent = `${hiddenChatTerminalCount}`; } - const ariaLabel = chatTerminalCount === 1 + const ariaLabel = hiddenChatTerminalCount === 1 ? localize('terminal.tabs.chatEntryAriaLabelSingle', "Show 1 hidden chat terminal") - : localize('terminal.tabs.chatEntryAriaLabelPlural', "Show {0} hidden chat terminals", chatTerminalCount); + : localize('terminal.tabs.chatEntryAriaLabelPlural', "Show {0} hidden chat terminals", hiddenChatTerminalCount); this._entry.setAttribute('aria-label', ariaLabel); } } diff --git a/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatActions.ts b/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatActions.ts index 345b0114c7a5..93ff50574a22 100644 --- a/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatActions.ts +++ b/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatActions.ts @@ -313,7 +313,7 @@ registerAction2(class ShowChatTerminalsAction extends Action2 { precondition: ContextKeyExpr.and(TerminalChatContextKeys.hasHiddenChatTerminals, ChatContextKeys.enabled), menu: [{ id: MenuId.ViewTitle, - when: ContextKeyExpr.and(TerminalChatContextKeys.hasChatTerminals, ContextKeyExpr.equals('view', ChatViewId)), + when: ContextKeyExpr.and(TerminalChatContextKeys.hasHiddenChatTerminals, ContextKeyExpr.equals('view', ChatViewId)), group: 'terminal', order: 0, isHiddenByDefault: true diff --git a/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatService.ts b/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatService.ts index b629add0cf1c..33672e6ffbe9 100644 --- a/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatService.ts +++ b/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatService.ts @@ -109,7 +109,12 @@ export class TerminalChatService extends Disposable implements ITerminalChatServ return this._terminalInstancesByToolSessionId.get(terminalToolSessionId); } - getToolSessionTerminalInstances(): readonly ITerminalInstance[] { + getToolSessionTerminalInstances(hiddenOnly?: boolean): readonly ITerminalInstance[] { + if (hiddenOnly) { + const foregroundInstances = new Set(this._terminalService.foregroundInstances.map(i => i.instanceId)); + const uniqueInstances = new Set(this._terminalInstancesByToolSessionId.values()); + return Array.from(uniqueInstances).filter(i => !foregroundInstances.has(i.instanceId)); + } // Ensure unique instances in case multiple tool sessions map to the same terminal return Array.from(new Set(this._terminalInstancesByToolSessionId.values())); } @@ -213,8 +218,7 @@ export class TerminalChatService extends Disposable implements ITerminalChatServ private _updateHasToolTerminalContextKeys(): void { const toolCount = this._terminalInstancesByToolSessionId.size; this._hasToolTerminalContext.set(toolCount > 0); - const foregroundInstances = new Set(this._terminalService.foregroundInstances.map(i => i.instanceId)); - const hiddenToolCount = Array.from(this._terminalInstancesByToolSessionId.values()).filter(instance => !foregroundInstances.has(instance.instanceId)).length; - this._hasHiddenToolTerminalContext.set(hiddenToolCount > 0); + const hiddenTerminalCount = this.getToolSessionTerminalInstances(true).length; + this._hasHiddenToolTerminalContext.set(hiddenTerminalCount > 0); } } From 48cdf17f0e856e1daca2ad2747814085a2453df0 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Fri, 7 Nov 2025 16:30:40 -0500 Subject: [PATCH 09/28] undo terminal completion provider API finalization (#276200) --- extensions/terminal-suggest/package.json | 1 + .../common/extensionsApiProposals.ts | 3 + .../workbench/api/common/extHost.api.impl.ts | 1 + .../common/terminalExtensionPoints.ts | 4 + src/vscode-dts/vscode.d.ts | 276 ----------------- ...e.proposed.terminalCompletionProvider.d.ts | 286 ++++++++++++++++++ 6 files changed, 295 insertions(+), 276 deletions(-) create mode 100644 src/vscode-dts/vscode.proposed.terminalCompletionProvider.d.ts diff --git a/extensions/terminal-suggest/package.json b/extensions/terminal-suggest/package.json index 4b6aef3f9367..66e99b20e11c 100644 --- a/extensions/terminal-suggest/package.json +++ b/extensions/terminal-suggest/package.json @@ -14,6 +14,7 @@ "Other" ], "enabledApiProposals": [ + "terminalCompletionProvider", "terminalShellEnv" ], "contributes": { diff --git a/src/vs/platform/extensions/common/extensionsApiProposals.ts b/src/vs/platform/extensions/common/extensionsApiProposals.ts index a8778a5980d6..959b3477de4a 100644 --- a/src/vs/platform/extensions/common/extensionsApiProposals.ts +++ b/src/vs/platform/extensions/common/extensionsApiProposals.ts @@ -403,6 +403,9 @@ const _allApiProposals = { telemetry: { proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.telemetry.d.ts', }, + terminalCompletionProvider: { + proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.terminalCompletionProvider.d.ts', + }, terminalDataWriteEvent: { proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.terminalDataWriteEvent.d.ts', }, diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index f6757129db39..da16fe2d2e41 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -880,6 +880,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I return extHostTerminalService.registerProfileProvider(extension, id, provider); }, registerTerminalCompletionProvider(provider: vscode.TerminalCompletionProvider, ...triggerCharacters: string[]): vscode.Disposable { + checkProposedApiEnabled(extension, 'terminalCompletionProvider'); return extHostTerminalService.registerTerminalCompletionProvider(extension, provider, ...triggerCharacters); }, registerTerminalQuickFixProvider(id: string, provider: vscode.TerminalQuickFixProvider): vscode.Disposable { diff --git a/src/vs/workbench/contrib/terminal/common/terminalExtensionPoints.ts b/src/vs/workbench/contrib/terminal/common/terminalExtensionPoints.ts index 3e956f4660e3..36dc472bcf24 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalExtensionPoints.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalExtensionPoints.ts @@ -9,6 +9,7 @@ import { createDecorator } from '../../../../platform/instantiation/common/insta import { IExtensionTerminalProfile, ITerminalCompletionProviderContribution, ITerminalContributions, ITerminalProfileContribution } from '../../../../platform/terminal/common/terminal.js'; import { URI } from '../../../../base/common/uri.js'; import { Emitter, Event } from '../../../../base/common/event.js'; +import { isProposedApiEnabled } from '../../../services/extensions/common/extensions.js'; // terminal extension point const terminalsExtPoint = extensionsRegistry.ExtensionsRegistry.registerExtensionPoint(terminalContributionsDescriptor); @@ -48,6 +49,9 @@ export class TerminalContributionService implements ITerminalContributionService }).flat(); this._terminalCompletionProviders = contributions.map(c => { + if (!isProposedApiEnabled(c.description, 'terminalCompletionProvider')) { + return []; + } return c.value?.completionProviders?.map(p => { return { ...p, extensionIdentifier: c.description.identifier.value }; }) || []; diff --git a/src/vscode-dts/vscode.d.ts b/src/vscode-dts/vscode.d.ts index 8f20c5ea0112..a548e0050496 100644 --- a/src/vscode-dts/vscode.d.ts +++ b/src/vscode-dts/vscode.d.ts @@ -8194,255 +8194,6 @@ declare module 'vscode' { constructor(options: TerminalOptions | ExtensionTerminalOptions); } - /** - * A provider that supplies terminal completion items. - * - * Implementations of this interface should return an array of {@link TerminalCompletionItem} or a - * {@link TerminalCompletionList} describing completions for the current command line. - * - * @example Simple provider returning a single completion - * window.registerTerminalCompletionProvider({ - * provideTerminalCompletions(terminal, context) { - * return [{ label: '--help', replacementRange: [Math.max(0, context.cursorPosition - 2), context.cursorPosition] }]; - * } - * }); - */ - export interface TerminalCompletionProvider { - /** - * Provide completions for the given terminal and context. - * @param terminal The terminal for which completions are being provided. - * @param context Information about the terminal's current state. - * @param token A cancellation token. - * @return A list of completions. - */ - provideTerminalCompletions(terminal: Terminal, context: TerminalCompletionContext, token: CancellationToken): ProviderResult>; - } - - - /** - * Represents a completion suggestion for a terminal command line. - * - * @example Completion item for `ls -|` - * const item = { - * label: '-A', - * replacementRange: [3, 4], // replace the single character at index 3 - * detail: 'List all entries except for . and .. (always set for the super-user)', - * kind: TerminalCompletionItemKind.Flag - * }; - * - * The fields on a completion item describe what text should be shown to the user - * and which portion of the command line should be replaced when the item is accepted. - */ - export class TerminalCompletionItem { - /** - * The label of the completion. - */ - label: string | CompletionItemLabel; - - /** - * The range in the command line to replace when the completion is accepted. Defined - * as a tuple where the first entry is the inclusive start index and the second entry is the - * exclusive end index. - * - */ - replacementRange: readonly [number, number]; - - /** - * The completion's detail which appears on the right of the list. - */ - detail?: string; - - /** - * A human-readable string that represents a doc-comment. - */ - documentation?: string | MarkdownString; - - /** - * The completion's kind. Note that this will map to an icon. If no kind is provided, a generic icon representing plaintext will be provided. - */ - kind?: TerminalCompletionItemKind; - - /** - * Creates a new terminal completion item. - * - * @param label The label of the completion. - * @param replacementRange The inclusive start and exclusive end index of the text to replace. - * @param kind The completion's kind. - */ - constructor( - label: string | CompletionItemLabel, - replacementRange: readonly [number, number], - kind?: TerminalCompletionItemKind - ); - } - - /** - * The kind of an individual terminal completion item. - * - * The kind is used to render an appropriate icon in the suggest list and to convey the semantic - * meaning of the suggestion (file, folder, flag, commit, branch, etc.). - */ - export enum TerminalCompletionItemKind { - /** - * A file completion item. - * Example: `README.md` - */ - File = 0, - /** - * A folder completion item. - * Example: `src/` - */ - Folder = 1, - /** - * A method completion item. - * Example: `git commit` - */ - Method = 2, - /** - * An alias completion item. - * Example: `ll` as an alias for `ls -l` - */ - Alias = 3, - /** - * An argument completion item. - * Example: `origin` in `git push origin master` - */ - Argument = 4, - /** - * An option completion item. An option value is expected to follow. - * Example: `--locale` in `code --locale en` - */ - Option = 5, - /** - * The value of an option completion item. - * Example: `en-US` in `code --locale en-US` - */ - OptionValue = 6, - /** - * A flag completion item. - * Example: `--amend` in `git commit --amend` - */ - Flag = 7, - /** - * A symbolic link file completion item. - * Example: `link.txt` (symlink to a file) - */ - SymbolicLinkFile = 8, - /** - * A symbolic link folder completion item. - * Example: `node_modules/` (symlink to a folder) - */ - SymbolicLinkFolder = 9, - /** - * A source control commit completion item. - * Example: `abc1234` (commit hash) - */ - ScmCommit = 10, - /** - * A source control branch completion item. - * Example: `main` - */ - ScmBranch = 11, - /** - * A source control tag completion item. - * Example: `v1.0.0` - */ - ScmTag = 12, - /** - * A source control stash completion item. - * Example: `stash@{0}` - */ - ScmStash = 13, - /** - * A source control remote completion item. - * Example: `origin` - */ - ScmRemote = 14, - /** - * A pull request completion item. - * Example: `#42 Add new feature` - */ - PullRequest = 15, - /** - * A closed pull request completion item. - * Example: `#41 Fix bug (closed)` - */ - PullRequestDone = 16, - } - - /** - * Context information passed to {@link TerminalCompletionProvider.provideTerminalCompletions}. - * - * It contains the full command line and the current cursor position - */ - export interface TerminalCompletionContext { - /** - * The complete terminal command line. - */ - readonly commandLine: string; - /** - * The index of the cursor in the command line. - */ - readonly cursorIndex: number; - } - - /** - * Represents a collection of {@link TerminalCompletionItem completion items} to be presented - * in the terminal plus {@link TerminalCompletionList.resourceOptions} which indicate - * which file and folder resources should be requested for the terminal's cwd. - * - * @example Create a completion list that requests files for the terminal cwd - * const list = new TerminalCompletionList([ - * { label: 'ls', replacementRange: [0, 0], kind: TerminalCompletionItemKind.Method } - * ], { showFiles: true, cwd: Uri.file('/home/user') }); - */ - export class TerminalCompletionList { - - /** - * Resources that should be shown in the completions list for the cwd of the terminal. - */ - resourceOptions?: TerminalCompletionResourceOptions; - - /** - * The completion items. - */ - items: T[]; - - /** - * Creates a new completion list. - * - * @param items The completion items. - * @param resourceOptions Indicates which resources should be shown as completions for the cwd of the terminal. - */ - constructor(items: T[], resourceOptions?: TerminalCompletionResourceOptions); - } - - - /** - * Configuration for requesting file and folder resources to be shown as completions. - * - * When a provider indicates that it wants file/folder resources, the terminal will surface completions for files and - * folders that match {@link globPattern} from the provided {@link cwd}. - */ - export interface TerminalCompletionResourceOptions { - /** - * Show files as completion items. - */ - showFiles: boolean; - /** - * Show folders as completion items. - */ - showDirectories: boolean; - /** - * A glob pattern string that controls which files suggest should surface. Note that this will only apply if {@param showFiles} or {@param showDirectories} is set to true. - */ - globPattern?: string; - /** - * The cwd from which to request resources. - */ - cwd: Uri; - } - /** * A file decoration represents metadata that can be rendered with a file. */ @@ -12019,33 +11770,6 @@ declare module 'vscode' { * @returns A {@link Disposable disposable} that unregisters the provider. */ export function registerTerminalProfileProvider(id: string, provider: TerminalProfileProvider): Disposable; - /** - * Register a completion provider for terminals. - * @param provider The completion provider. - * @param triggerCharacters Optional characters that trigger completion. When any of these characters is typed, - * the completion provider will be invoked. For example, passing `'-'` would cause the provider to be invoked - * whenever the user types a dash character. - * @returns A {@link Disposable} that unregisters this provider when being disposed. - * - * @example Register a provider for an extension - * window.registerTerminalCompletionProvider({ - * provideTerminalCompletions(terminal, context) { - * return new TerminalCompletionList([ - * { label: '--version', replacementRange: [Math.max(0, context.cursorPosition - 2), context.cursorPosition] } - * ]); - * } - * }); - * - * @example Register a provider with trigger characters - * window.registerTerminalCompletionProvider({ - * provideTerminalCompletions(terminal, context) { - * return new TerminalCompletionList([ - * { label: '--help', replacementRange: [Math.max(0, context.cursorPosition - 2), context.cursorPosition] } - * ]); - * } - * }, '-'); - */ - export function registerTerminalCompletionProvider(provider: TerminalCompletionProvider, ...triggerCharacters: string[]): Disposable; /** * Register a file decoration provider. * diff --git a/src/vscode-dts/vscode.proposed.terminalCompletionProvider.d.ts b/src/vscode-dts/vscode.proposed.terminalCompletionProvider.d.ts new file mode 100644 index 000000000000..5aa612e3d8b6 --- /dev/null +++ b/src/vscode-dts/vscode.proposed.terminalCompletionProvider.d.ts @@ -0,0 +1,286 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module 'vscode' { + + // https://github.com/microsoft/vscode/issues/226562 + + /** + * A provider that supplies terminal completion items. + * + * Implementations of this interface should return an array of {@link TerminalCompletionItem} or a + * {@link TerminalCompletionList} describing completions for the current command line. + * + * @example Simple provider returning a single completion + * window.registerTerminalCompletionProvider({ + * provideTerminalCompletions(terminal, context) { + * return [{ label: '--help', replacementRange: [Math.max(0, context.cursorPosition - 2), context.cursorPosition] }]; + * } + * }); + */ + export interface TerminalCompletionProvider { + /** + * Provide completions for the given terminal and context. + * @param terminal The terminal for which completions are being provided. + * @param context Information about the terminal's current state. + * @param token A cancellation token. + * @return A list of completions. + */ + provideTerminalCompletions(terminal: Terminal, context: TerminalCompletionContext, token: CancellationToken): ProviderResult>; + } + + /** + * Represents a completion suggestion for a terminal command line. + * + * @example Completion item for `ls -|` + * const item = { + * label: '-A', + * replacementRange: [3, 4], // replace the single character at index 3 + * detail: 'List all entries except for . and .. (always set for the super-user)', + * kind: TerminalCompletionItemKind.Flag + * }; + * + * The fields on a completion item describe what text should be shown to the user + * and which portion of the command line should be replaced when the item is accepted. + */ + export class TerminalCompletionItem { + /** + * The label of the completion. + */ + label: string | CompletionItemLabel; + + /** + * The range in the command line to replace when the completion is accepted. Defined + * as a tuple where the first entry is the inclusive start index and the second entry is the + * exclusive end index. + */ + replacementRange: readonly [number, number]; + + /** + * The completion's detail which appears on the right of the list. + */ + detail?: string; + + /** + * A human-readable string that represents a doc-comment. + */ + documentation?: string | MarkdownString; + + /** + * The completion's kind. Note that this will map to an icon. If no kind is provided, a generic icon representing plaintext will be provided. + */ + kind?: TerminalCompletionItemKind; + + /** + * Creates a new terminal completion item. + * + * @param label The label of the completion. + * @param replacementRange The inclusive start and exclusive end index of the text to replace. + * @param kind The completion's kind. + */ + constructor( + label: string | CompletionItemLabel, + replacementRange: readonly [number, number], + kind?: TerminalCompletionItemKind + ); + } + + /** + * The kind of an individual terminal completion item. + * + * The kind is used to render an appropriate icon in the suggest list and to convey the semantic + * meaning of the suggestion (file, folder, flag, commit, branch, etc.). + */ + export enum TerminalCompletionItemKind { + /** + * A file completion item. + * Example: `README.md` + */ + File = 0, + /** + * A folder completion item. + * Example: `src/` + */ + Folder = 1, + /** + * A method completion item. + * Example: `git commit` + */ + Method = 2, + /** + * An alias completion item. + * Example: `ll` as an alias for `ls -l` + */ + Alias = 3, + /** + * An argument completion item. + * Example: `origin` in `git push origin main` + */ + Argument = 4, + /** + * An option completion item. An option value is expected to follow. + * Example: `--locale` in `code --locale en` + */ + Option = 5, + /** + * The value of an option completion item. + * Example: `en-US` in `code --locale en-US` + */ + OptionValue = 6, + /** + * A flag completion item. + * Example: `--amend` in `git commit --amend` + */ + Flag = 7, + /** + * A symbolic link file completion item. + * Example: `link.txt` (symlink to a file) + */ + SymbolicLinkFile = 8, + /** + * A symbolic link folder completion item. + * Example: `node_modules/` (symlink to a folder) + */ + SymbolicLinkFolder = 9, + /** + * A source control commit completion item. + * Example: `abc1234` (commit hash) + */ + ScmCommit = 10, + /** + * A source control branch completion item. + * Example: `main` + */ + ScmBranch = 11, + /** + * A source control tag completion item. + * Example: `v1.0.0` + */ + ScmTag = 12, + /** + * A source control stash completion item. + * Example: `stash@{0}` + */ + ScmStash = 13, + /** + * A source control remote completion item. + * Example: `origin` + */ + ScmRemote = 14, + /** + * A pull request completion item. + * Example: `#42 Add new feature` + */ + PullRequest = 15, + /** + * A closed pull request completion item. + * Example: `#41 Fix bug (closed)` + */ + PullRequestDone = 16, + } + + /** + * Context information passed to {@link TerminalCompletionProvider.provideTerminalCompletions}. + * + * It contains the full command line and the current cursor position. + */ + export interface TerminalCompletionContext { + /** + * The complete terminal command line. + */ + readonly commandLine: string; + /** + * The index of the cursor in the command line. + */ + readonly cursorIndex: number; + } + + /** + * Represents a collection of {@link TerminalCompletionItem completion items} to be presented + * in the terminal plus {@link TerminalCompletionList.resourceOptions} which indicate + * which file and folder resources should be requested for the terminal's cwd. + * + * @example Create a completion list that requests files for the terminal cwd + * const list = new TerminalCompletionList([ + * { label: 'ls', replacementRange: [0, 0], kind: TerminalCompletionItemKind.Method } + * ], { showFiles: true, cwd: Uri.file('/home/user') }); + */ + export class TerminalCompletionList { + + /** + * Resources that should be shown in the completions list for the cwd of the terminal. + */ + resourceOptions?: TerminalCompletionResourceOptions; + + /** + * The completion items. + */ + items: T[]; + + /** + * Creates a new completion list. + * + * @param items The completion items. + * @param resourceOptions Indicates which resources should be shown as completions for the cwd of the terminal. + */ + constructor(items: T[], resourceOptions?: TerminalCompletionResourceOptions); + } + + /** + * Configuration for requesting file and folder resources to be shown as completions. + * + * When a provider indicates that it wants file/folder resources, the terminal will surface completions for files and + * folders that match {@link globPattern} from the provided {@link cwd}. + */ + export interface TerminalCompletionResourceOptions { + /** + * Show files as completion items. + */ + showFiles: boolean; + /** + * Show folders as completion items. + */ + showDirectories: boolean; + /** + * A glob pattern string that controls which files suggest should surface. Note that this will only apply if {@param showFiles} or {@param showDirectories} is set to true. + */ + globPattern?: string; + /** + * The cwd from which to request resources. + */ + cwd: Uri; + } + + export namespace window { + /** + * Register a completion provider for terminals. + * @param provider The completion provider. + * @param triggerCharacters Optional characters that trigger completion. When any of these characters is typed, + * the completion provider will be invoked. For example, passing `'-'` would cause the provider to be invoked + * whenever the user types a dash character. + * @returns A {@link Disposable} that unregisters this provider when being disposed. + * + * @example Register a provider for an extension + * window.registerTerminalCompletionProvider({ + * provideTerminalCompletions(terminal, context) { + * return new TerminalCompletionList([ + * { label: '--version', replacementRange: [Math.max(0, context.cursorPosition - 2), context.cursorPosition] } + * ]); + * } + * }); + * + * @example Register a provider with trigger characters + * window.registerTerminalCompletionProvider({ + * provideTerminalCompletions(terminal, context) { + * return new TerminalCompletionList([ + * { label: '--help', replacementRange: [Math.max(0, context.cursorPosition - 2), context.cursorPosition] } + * ]); + * } + * }, '-'); + */ + export function registerTerminalCompletionProvider(provider: TerminalCompletionProvider, ...triggerCharacters: string[]): Disposable; + } +} + From 74bc8f43904c442c58926700d1297a1642b1a127 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 10 Nov 2025 15:48:42 +0100 Subject: [PATCH 10/28] Chat: send entitlements when anonymous usage changes (#276183) (#276185) --- .../chat/common/chatEntitlementService.ts | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/services/chat/common/chatEntitlementService.ts b/src/vs/workbench/services/chat/common/chatEntitlementService.ts index 38aeb52e2ca0..390e4dc21e93 100644 --- a/src/vs/workbench/services/chat/common/chatEntitlementService.ts +++ b/src/vs/workbench/services/chat/common/chatEntitlementService.ts @@ -216,6 +216,16 @@ function isAnonymous(configurationService: IConfigurationService, entitlement: C return true; } +function logChatEntitlements(state: IChatEntitlementContextState, configurationService: IConfigurationService, telemetryService: ITelemetryService): void { + telemetryService.publicLog2('chatEntitlements', { + chatHidden: Boolean(state.hidden), + chatDisabled: Boolean(state.disabled), + chatEntitlement: state.entitlement, + chatRegistered: Boolean(state.registered), + chatAnonymous: isAnonymous(configurationService, state.entitlement, state) + }); +} + export class ChatEntitlementService extends Disposable implements IChatEntitlementService { declare _serviceBrand: undefined; @@ -228,7 +238,8 @@ export class ChatEntitlementService extends Disposable implements IChatEntitleme @IProductService productService: IProductService, @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService, @IContextKeyService private readonly contextKeyService: IContextKeyService, - @IConfigurationService private readonly configurationService: IConfigurationService + @IConfigurationService private readonly configurationService: IConfigurationService, + @ITelemetryService private readonly telemetryService: ITelemetryService ) { super(); @@ -236,6 +247,7 @@ export class ChatEntitlementService extends Disposable implements IChatEntitleme this.completionsQuotaExceededContextKey = ChatEntitlementContextKeys.completionsQuotaExceeded.bindTo(this.contextKeyService); this.anonymousContextKey = ChatEntitlementContextKeys.chatAnonymous.bindTo(this.contextKeyService); + this.anonymousContextKey.set(this.anonymous); this.onDidChangeEntitlement = Event.map( Event.filter( @@ -372,6 +384,10 @@ export class ChatEntitlementService extends Disposable implements IChatEntitleme anonymousUsage = newAnonymousUsage; this.anonymousContextKey.set(newAnonymousUsage); + if (this.context?.hasValue) { + logChatEntitlements(this.context.value.state, this.configurationService, this.telemetryService); + } + this._onDidChangeAnonymous.fire(); } }; @@ -1278,13 +1294,7 @@ export class ChatEntitlementContext extends Disposable { this.registeredContext.set(!!state.registered); this.logService.trace(`[chat entitlement context] updateContext(): ${JSON.stringify(state)}`); - this.telemetryService.publicLog2('chatEntitlements', { - chatHidden: Boolean(state.hidden), - chatDisabled: Boolean(state.disabled), - chatEntitlement: state.entitlement, - chatRegistered: Boolean(state.registered), - chatAnonymous: isAnonymous(this.configurationService, state.entitlement, state) - }); + logChatEntitlements(state, this.configurationService, this.telemetryService); this._onDidChange.fire(); } From ef5e0b68ce9d9da83ef925e0107ae33ad91969bd Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 10 Nov 2025 15:49:04 +0100 Subject: [PATCH 11/28] chat - track and apply `defaultVisibilityMarker` (#276461) --- src/vs/workbench/browser/layout.ts | 13 ++++++++++++- src/vs/workbench/browser/workbench.contribution.ts | 9 +++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index c517d4fbd29d..7d0fcca60ea0 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -3050,7 +3050,18 @@ class LayoutStateModel extends Disposable { } private loadKeyFromStorage(key: WorkbenchLayoutStateKey): T | undefined { - const value = this.storageService.get(`${LayoutStateModel.STORAGE_PREFIX}${key.name}`, key.scope); + let value = this.storageService.get(`${LayoutStateModel.STORAGE_PREFIX}${key.name}`, key.scope); + + // TODO@bpasero remove this code in 1y when "pre-AI" workspaces have migrated + // Refs: https://github.com/microsoft/vscode-internalbacklog/issues/6168 + if ( + key.scope === StorageScope.WORKSPACE && + key.name === LayoutStateKeys.AUXILIARYBAR_HIDDEN.name && + this.configurationService.getValue('workbench.secondarySideBar.enableDefaultVisibilityInOldWorkspace') === true && + this.storageService.get('workbench.panel.chat.numberOfVisibleViews', StorageScope.WORKSPACE) === undefined + ) { + value = undefined; + } if (value !== undefined) { this.isNew[key.scope] = false; // remember that we had previous state for this scope diff --git a/src/vs/workbench/browser/workbench.contribution.ts b/src/vs/workbench/browser/workbench.contribution.ts index a971e7e18c79..d87011805bb1 100644 --- a/src/vs/workbench/browser/workbench.contribution.ts +++ b/src/vs/workbench/browser/workbench.contribution.ts @@ -568,6 +568,15 @@ const registry = Registry.as(ConfigurationExtensions.Con localize('workbench.secondarySideBar.defaultVisibility.maximized', "The secondary side bar is visible and maximized by default.") ] }, + 'workbench.secondarySideBar.enableDefaultVisibilityInOldWorkspace': { + 'type': 'boolean', + 'default': false, + 'description': localize('enableDefaultVisibilityInOldWorkspace', "Enables the default secondary sidebar visibility in older workspaces before we had default visibility support."), + 'tags': ['advanced'], + 'experiment': { + 'mode': 'auto' + } + }, 'workbench.secondarySideBar.showLabels': { 'type': 'boolean', 'default': true, From c5a35b4aa508a6dfe4687bee2c2e7f704506799a Mon Sep 17 00:00:00 2001 From: Alex Ross <38270282+alexr00@users.noreply.github.com> Date: Mon, 10 Nov 2025 16:04:11 +0100 Subject: [PATCH 12/28] Comments fail to re-expand after collapse in outdated/specific-commit-version files (#276464) Fixes #276458 --- src/vs/workbench/contrib/comments/browser/commentsController.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/comments/browser/commentsController.ts b/src/vs/workbench/contrib/comments/browser/commentsController.ts index d3c673e4eb70..9de143e39b6d 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsController.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsController.ts @@ -1084,7 +1084,7 @@ export class CommentController implements IEditorContribution { } private onEditorMouseDown(e: IEditorMouseEvent): void { - this.mouseDownInfo = this._activeEditorHasCommentingRange.get() ? parseMouseDownInfoFromEvent(e) : null; + this.mouseDownInfo = (e.target.element?.className.indexOf('comment-range-glyph') ?? -1) >= 0 ? parseMouseDownInfoFromEvent(e) : null; } private onEditorMouseUp(e: IEditorMouseEvent): void { From a94578cda4b71bb522248b1cdcc348230bcab145 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 10 Nov 2025 09:21:05 -0800 Subject: [PATCH 13/28] Filter subagent and todo tools from subagent requests Fix #276548 --- .../workbench/contrib/chat/common/tools/runSubagentTool.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/vs/workbench/contrib/chat/common/tools/runSubagentTool.ts b/src/vs/workbench/contrib/chat/common/tools/runSubagentTool.ts index 1870a9582f0e..93b6aa3d858b 100644 --- a/src/vs/workbench/contrib/chat/common/tools/runSubagentTool.ts +++ b/src/vs/workbench/contrib/chat/common/tools/runSubagentTool.ts @@ -32,6 +32,7 @@ import { ToolSet, VSCodeToolReference } from '../languageModelToolsService.js'; +import { ManageTodoListToolToolId } from './manageTodoListTool.js'; import { createToolSimpleTextResult } from './toolHelpers.js'; export const RunSubagentToolId = 'runSubagent'; @@ -206,6 +207,11 @@ export class RunSubagentTool extends Disposable implements IToolImpl { } }; + if (modeTools) { + modeTools[RunSubagentToolId] = false; + modeTools[ManageTodoListToolToolId] = false; + } + // Build the agent request const agentRequest: IChatAgentRequest = { sessionId: invocation.context.sessionId, From 507f50c4289e1f7c154a8129c5b0122a671cf038 Mon Sep 17 00:00:00 2001 From: Justin Chen <54879025+justschen@users.noreply.github.com> Date: Mon, 10 Nov 2025 14:22:13 -0800 Subject: [PATCH 14/28] fix selections not included in implicit (#276604) --- src/vs/workbench/contrib/chat/browser/chatInputPart.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/chat/browser/chatInputPart.ts b/src/vs/workbench/contrib/chat/browser/chatInputPart.ts index d7d71a24ddaf..d0f7768d3526 100644 --- a/src/vs/workbench/contrib/chat/browser/chatInputPart.ts +++ b/src/vs/workbench/contrib/chat/browser/chatInputPart.ts @@ -189,7 +189,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge const contextArr = this.getAttachedContext(sessionResource); - if (this.implicitContext?.enabled && this.implicitContext?.value && this.configurationService.getValue('chat.implicitContext.suggestedContext')) { + if ((this.implicitContext?.enabled && this.implicitContext?.value) || (this.implicitContext && !URI.isUri(this.implicitContext.value) && this.configurationService.getValue('chat.implicitContext.suggestedContext'))) { const implicitChatVariables = this.implicitContext.toBaseEntries(); contextArr.add(...implicitChatVariables); } From 1725d512166b815ceef8511d389d99baeb312506 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 11 Nov 2025 15:16:27 +0100 Subject: [PATCH 15/28] fix #276579 (#276591) --- src/vs/platform/mcp/common/mcpGalleryService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/platform/mcp/common/mcpGalleryService.ts b/src/vs/platform/mcp/common/mcpGalleryService.ts index a626b1fbd38e..62d7b2c30a7d 100644 --- a/src/vs/platform/mcp/common/mcpGalleryService.ts +++ b/src/vs/platform/mcp/common/mcpGalleryService.ts @@ -1035,7 +1035,7 @@ export class McpGalleryService extends Disposable implements IMcpGalleryService if (!latestVersionResourceUriTemplate) { return undefined; } - return format2(latestVersionResourceUriTemplate, { name }); + return format2(latestVersionResourceUriTemplate, { name: encodeURIComponent(name) }); } private getWebUrl(name: string, mcpGalleryManifest: IMcpGalleryManifest): string | undefined { From ac4cbdf48759c7d8c3eb91ffe6bb04316e263c57 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 10 Nov 2025 14:46:26 -0800 Subject: [PATCH 16/28] Ignore obsolete chat content part type Fix #276094 --- src/vs/workbench/contrib/chat/common/chatModel.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/contrib/chat/common/chatModel.ts b/src/vs/workbench/contrib/chat/common/chatModel.ts index 2571eabf7cb0..7567b60dc288 100644 --- a/src/vs/workbench/contrib/chat/common/chatModel.ts +++ b/src/vs/workbench/contrib/chat/common/chatModel.ts @@ -408,6 +408,7 @@ class AbstractResponse implements IResponse { case 'thinking': case 'multiDiffData': case 'mcpServersStarting': + case 'mcpServersInteractionRequired' as string: // obsolete part, ignore // Ignore continue; case 'toolInvocation': From c9c9bbf74647c23803798916a34252facd34bc7f Mon Sep 17 00:00:00 2001 From: Simon Siefke Date: Tue, 9 Dec 2025 17:21:46 +0100 Subject: [PATCH 17/28] fix: memory leak in status bar --- src/vs/workbench/api/browser/mainThreadStatusBar.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadStatusBar.ts b/src/vs/workbench/api/browser/mainThreadStatusBar.ts index 96059861a79a..1a84d34a28ef 100644 --- a/src/vs/workbench/api/browser/mainThreadStatusBar.ts +++ b/src/vs/workbench/api/browser/mainThreadStatusBar.ts @@ -6,7 +6,7 @@ import { MainThreadStatusBarShape, MainContext, ExtHostContext, StatusBarItemDto, ExtHostStatusBarShape } from '../common/extHost.protocol.js'; import { ThemeColor } from '../../../base/common/themables.js'; import { extHostNamedCustomer, IExtHostContext } from '../../services/extensions/common/extHostCustomers.js'; -import { DisposableStore, toDisposable } from '../../../base/common/lifecycle.js'; +import { DisposableStore, DisposableMap, toDisposable } from '../../../base/common/lifecycle.js'; import { Command } from '../../../editor/common/languages.js'; import { IAccessibilityInformation } from '../../../platform/accessibility/common/accessibility.js'; import { IMarkdownString } from '../../../base/common/htmlContent.js'; @@ -20,6 +20,7 @@ export class MainThreadStatusBar implements MainThreadStatusBarShape { private readonly _proxy: ExtHostStatusBarShape; private readonly _store = new DisposableStore(); + private readonly _entryDisposables = new DisposableMap(); constructor( extHostContext: IExtHostContext, @@ -71,11 +72,13 @@ export class MainThreadStatusBar implements MainThreadStatusBarShape { const kind = this.statusbarService.setOrUpdateEntry(entryId, id, extensionId, name, text, tooltipOrTooltipProvider, command, color, backgroundColor, alignLeft, priority, accessibilityInformation); if (kind === StatusBarUpdateKind.DidDefine) { - this._store.add(toDisposable(() => this.statusbarService.unsetEntry(entryId))); + const disposable = toDisposable(() => this.statusbarService.unsetEntry(entryId)); + this._entryDisposables.set(entryId, disposable); } } $disposeEntry(entryId: string) { + this._entryDisposables.deleteAndDispose(entryId); this.statusbarService.unsetEntry(entryId); } } From 7064b1fa9866930d8a2d5af8aeed56a4a34e677b Mon Sep 17 00:00:00 2001 From: Simon Siefke Date: Tue, 9 Dec 2025 19:24:18 +0300 Subject: [PATCH 18/28] Discard changes to src/vs/workbench/browser/layout.ts --- src/vs/workbench/browser/layout.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index ccaaf3b16265..a6dffa420a8f 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -3052,7 +3052,6 @@ class LayoutStateModel extends Disposable { private loadKeyFromStorage(key: WorkbenchLayoutStateKey): T | undefined { const value = this.storageService.get(`${LayoutStateModel.STORAGE_PREFIX}${key.name}`, key.scope); - if (value !== undefined) { this.isNew[key.scope] = false; // remember that we had previous state for this scope From 502760b2d985dfc9078cbb3c5b2215bb089e0f6d Mon Sep 17 00:00:00 2001 From: Simon Siefke Date: Tue, 9 Dec 2025 19:24:24 +0300 Subject: [PATCH 19/28] Discard changes to src/vs/workbench/browser/workbench.contribution.ts --- src/vs/workbench/browser/workbench.contribution.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/vs/workbench/browser/workbench.contribution.ts b/src/vs/workbench/browser/workbench.contribution.ts index 4850bf415869..8715c5e9d412 100644 --- a/src/vs/workbench/browser/workbench.contribution.ts +++ b/src/vs/workbench/browser/workbench.contribution.ts @@ -574,15 +574,6 @@ const registry = Registry.as(ConfigurationExtensions.Con localize('workbench.secondarySideBar.defaultVisibility.maximized', "The secondary side bar is visible and maximized by default.") ] }, - 'workbench.secondarySideBar.enableDefaultVisibilityInOldWorkspace': { - 'type': 'boolean', - 'default': false, - 'description': localize('enableDefaultVisibilityInOldWorkspace', "Enables the default secondary sidebar visibility in older workspaces before we had default visibility support."), - 'tags': ['advanced'], - 'experiment': { - 'mode': 'auto' - } - }, 'workbench.secondarySideBar.showLabels': { 'type': 'boolean', 'default': true, From 423d660e593b04b78bb39c98dde425a646e114ae Mon Sep 17 00:00:00 2001 From: Simon Siefke Date: Tue, 9 Dec 2025 19:24:31 +0300 Subject: [PATCH 20/28] Discard changes to src/vs/workbench/contrib/chat/browser/languageModelToolsService.ts --- .../contrib/chat/browser/languageModelToolsService.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/languageModelToolsService.ts b/src/vs/workbench/contrib/chat/browser/languageModelToolsService.ts index fa860c243fe1..8823457d37c8 100644 --- a/src/vs/workbench/contrib/chat/browser/languageModelToolsService.ts +++ b/src/vs/workbench/contrib/chat/browser/languageModelToolsService.ts @@ -302,11 +302,7 @@ export class LanguageModelToolsService extends Disposable implements ILanguageMo try { if (dto.context) { store = new DisposableStore(); -<<<<<<< HEAD - const model = this._chatService.getSessionByLegacyId(dto.context.sessionId) as ChatModel | undefined; -======= const model = this._chatService.getSession(dto.context.sessionResource); ->>>>>>> origin/main if (!model) { throw new Error(`Tool called for unknown chat session`); } From 111c9ddb0b67b55982ebec562ff882756e23b40d Mon Sep 17 00:00:00 2001 From: Simon Siefke Date: Tue, 9 Dec 2025 19:24:38 +0300 Subject: [PATCH 21/28] Discard changes to src/vs/workbench/contrib/chat/common/chatModel.ts --- src/vs/workbench/contrib/chat/common/chatModel.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/contrib/chat/common/chatModel.ts b/src/vs/workbench/contrib/chat/common/chatModel.ts index 0d3f5038a26f..eb1b93279b40 100644 --- a/src/vs/workbench/contrib/chat/common/chatModel.ts +++ b/src/vs/workbench/contrib/chat/common/chatModel.ts @@ -419,7 +419,6 @@ class AbstractResponse implements IResponse { case 'thinking': case 'multiDiffData': case 'mcpServersStarting': - case 'mcpServersInteractionRequired' as string: // obsolete part, ignore // Ignore continue; case 'toolInvocation': From f2bc92ae856bf46a4cb2624a9da4cdaee02c3015 Mon Sep 17 00:00:00 2001 From: Simon Siefke Date: Tue, 9 Dec 2025 19:24:44 +0300 Subject: [PATCH 22/28] Discard changes to src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts --- .../contrib/inlineChat/browser/inlineChatController.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index 4cc0d7899a9f..757b17aaa117 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -15,7 +15,7 @@ import { Lazy } from '../../../../base/common/lazy.js'; import { DisposableStore, MutableDisposable, toDisposable } from '../../../../base/common/lifecycle.js'; import { Schemas } from '../../../../base/common/network.js'; import { MovingAverage } from '../../../../base/common/numbers.js'; -import { autorun, derived, IObservable, observableSignalFromEvent, observableValue, waitForState } from '../../../../base/common/observable.js'; +import { autorun, derived, IObservable, observableFromEvent, observableSignalFromEvent, observableValue, waitForState } from '../../../../base/common/observable.js'; import { isEqual } from '../../../../base/common/resources.js'; import { StopWatch } from '../../../../base/common/stopwatch.js'; import { assertType } from '../../../../base/common/types.js'; @@ -1288,11 +1288,7 @@ export class InlineChatController2 implements IEditorContribution { @IChatAttachmentResolveService private readonly _chatAttachmentResolveService: IChatAttachmentResolveService, @IEditorService private readonly _editorService: IEditorService, @IMarkerDecorationsService private readonly _markerDecorationsService: IMarkerDecorationsService, -<<<<<<< HEAD - @IInlineChatSessionService inlineChatService: IInlineChatSessionService, -======= @ILanguageModelsService private readonly _languageModelService: ILanguageModelsService, ->>>>>>> origin/main @IChatService chatService: IChatService, ) { From 6ac85b68a792603e04f9b0da42ef1e9e0311ab8d Mon Sep 17 00:00:00 2001 From: Simon Siefke Date: Tue, 9 Dec 2025 19:24:50 +0300 Subject: [PATCH 23/28] Discard changes to src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts --- .../contrib/terminal/browser/terminalTabbedView.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts b/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts index ba3c1f3a3a08..56a03cc03fb9 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts @@ -172,17 +172,6 @@ export class TerminalTabbedView extends Disposable { return false; } if (hiddenChatTerminals.length > 0) { -<<<<<<< HEAD - return true; - } - - if (hide === 'never') { - return true; - } - - if (this._terminalGroupService.instances.length) { - return true; -======= return true; } @@ -199,7 +188,6 @@ export class TerminalTabbedView extends Disposable { return true; } break; ->>>>>>> origin/main } return false; } From e1e3f758d94365c1ee92c278c559360ef2489b44 Mon Sep 17 00:00:00 2001 From: Simon Siefke Date: Tue, 9 Dec 2025 19:24:57 +0300 Subject: [PATCH 24/28] Discard changes to src/vs/workbench/contrib/terminal/common/terminalExtensionPoints.ts --- .../contrib/terminal/common/terminalExtensionPoints.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/common/terminalExtensionPoints.ts b/src/vs/workbench/contrib/terminal/common/terminalExtensionPoints.ts index 7a126ff33bd2..d0bbed0384bb 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalExtensionPoints.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalExtensionPoints.ts @@ -10,10 +10,7 @@ import { IExtensionTerminalProfile, ITerminalCompletionProviderContribution, ITe import { URI } from '../../../../base/common/uri.js'; import { Emitter, Event } from '../../../../base/common/event.js'; import { isProposedApiEnabled } from '../../../services/extensions/common/extensions.js'; -<<<<<<< HEAD -======= import { isObject, isString } from '../../../../base/common/types.js'; ->>>>>>> origin/main // terminal extension point const terminalsExtPoint = extensionsRegistry.ExtensionsRegistry.registerExtensionPoint(terminalContributionsDescriptor); From 5ecae36ae43c295d5ad4226b2a1e095bb0fc569d Mon Sep 17 00:00:00 2001 From: Simon Siefke Date: Tue, 9 Dec 2025 19:25:10 +0300 Subject: [PATCH 25/28] Discard changes to src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatService.ts --- .../terminalContrib/chat/browser/terminalChatService.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatService.ts b/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatService.ts index 6bf95f268457..18c41bb70c19 100644 --- a/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatService.ts +++ b/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChatService.ts @@ -298,8 +298,6 @@ export class TerminalChatService extends Disposable implements ITerminalChatServ this._hasToolTerminalContext.set(toolCount > 0); const hiddenTerminalCount = this.getToolSessionTerminalInstances(true).length; this._hasHiddenToolTerminalContext.set(hiddenTerminalCount > 0); -<<<<<<< HEAD -======= } setChatSessionAutoApproval(chatSessionId: string, enabled: boolean): void { @@ -312,6 +310,5 @@ export class TerminalChatService extends Disposable implements ITerminalChatServ hasChatSessionAutoApproval(chatSessionId: string): boolean { return this._sessionAutoApprovalEnabled.has(chatSessionId); ->>>>>>> origin/main } } From 0945f8ca921d68a880ba90d0928a294c8297e2dd Mon Sep 17 00:00:00 2001 From: Simon Siefke Date: Tue, 9 Dec 2025 19:25:15 +0300 Subject: [PATCH 26/28] Discard changes to src/vs/workbench/services/accounts/common/defaultAccount.ts --- .../accounts/common/defaultAccount.ts | 40 ------------------- 1 file changed, 40 deletions(-) diff --git a/src/vs/workbench/services/accounts/common/defaultAccount.ts b/src/vs/workbench/services/accounts/common/defaultAccount.ts index 88ac4eb7823d..42ff1bdca1aa 100644 --- a/src/vs/workbench/services/accounts/common/defaultAccount.ts +++ b/src/vs/workbench/services/accounts/common/defaultAccount.ts @@ -153,12 +153,6 @@ export class DefaultAccountManagementContribution extends Disposable implements private async initialize(): Promise { this.logService.debug('[DefaultAccount] Starting initialization'); -<<<<<<< HEAD - - if (!this.productService.defaultAccount) { - this.logService.debug('[DefaultAccount] No default account configuration in product service, skipping initialization'); - return; -======= let defaultAccount: IDefaultAccount | null = null; try { defaultAccount = await this.fetchDefaultAccount(); @@ -178,7 +172,6 @@ export class DefaultAccountManagementContribution extends Disposable implements if (isWeb && !this.environmentService.remoteAuthority) { this.logService.debug('[DefaultAccount] Running in web without remote, skipping initialization'); return null; ->>>>>>> origin/main } const defaultAccountProviderId = this.getDefaultAccountProviderId(); @@ -193,33 +186,11 @@ export class DefaultAccountManagementContribution extends Disposable implements const declaredProvider = this.authenticationService.declaredProviders.find(provider => provider.id === defaultAccountProviderId); if (!declaredProvider) { this.logService.info(`[DefaultAccount] Authentication provider is not declared.`, defaultAccountProviderId); -<<<<<<< HEAD - return; - } - - this.registerSignInAction(defaultAccountProviderId, this.productService.defaultAccount.authenticationProvider.scopes); - this.setDefaultAccount(await this.getDefaultAccountFromAuthenticatedSessions(defaultAccountProviderId, this.productService.defaultAccount.authenticationProvider.scopes)); - - this._register(this.authenticationService.onDidChangeSessions(async e => { - if (e.providerId !== this.getDefaultAccountProviderId()) { - return; - } - - if (this.defaultAccount && e.event.removed?.some(session => session.id === this.defaultAccount?.sessionId)) { - this.setDefaultAccount(null); - return; - } - this.setDefaultAccount(await this.getDefaultAccountFromAuthenticatedSessions(defaultAccountProviderId, this.productService.defaultAccount!.authenticationProvider.scopes)); - })); - - this.logService.debug('[DefaultAccount] Initialization complete'); -======= return null; } this.registerSignInAction(defaultAccountProviderId, this.productService.defaultAccount.authenticationProvider.scopes[0]); return await this.getDefaultAccountFromAuthenticatedSessions(defaultAccountProviderId, this.productService.defaultAccount.authenticationProvider.scopes); ->>>>>>> origin/main } private setDefaultAccount(account: IDefaultAccount | null): void { @@ -246,18 +217,10 @@ export class DefaultAccountManagementContribution extends Disposable implements return result; } -<<<<<<< HEAD - private async getDefaultAccountFromAuthenticatedSessions(authProviderId: string, scopes: string[]): Promise { - try { - this.logService.debug('[DefaultAccount] Getting Default Account from authenticated sessions for provider:', authProviderId); - const sessions = await this.authenticationService.getSessions(authProviderId, undefined, undefined, true); - const session = sessions.find(s => this.scopesMatch(s.scopes, scopes)); -======= private async getDefaultAccountFromAuthenticatedSessions(authProviderId: string, scopes: string[][]): Promise { try { this.logService.debug('[DefaultAccount] Getting Default Account from authenticated sessions for provider:', authProviderId); const session = await this.findMatchingProviderSession(authProviderId, scopes); ->>>>>>> origin/main if (!session) { this.logService.debug('[DefaultAccount] No matching session found for provider:', authProviderId); @@ -285,8 +248,6 @@ export class DefaultAccountManagementContribution extends Disposable implements this.logService.error('[DefaultAccount] Failed to create default account for provider:', authProviderId, getErrorMessage(error)); return null; } -<<<<<<< HEAD -======= } private async findMatchingProviderSession(authProviderId: string, allScopes: string[][]): Promise { @@ -315,7 +276,6 @@ export class DefaultAccountManagementContribution extends Disposable implements } } throw new Error('Unable to get sessions after multiple attempts'); ->>>>>>> origin/main } private scopesMatch(scopes: ReadonlyArray, expectedScopes: string[]): boolean { From 6a17b56dd56e0d51749e0f94a4210d3e5c6c16b3 Mon Sep 17 00:00:00 2001 From: Simon Siefke Date: Tue, 9 Dec 2025 19:25:23 +0300 Subject: [PATCH 27/28] Discard changes to src/vs/workbench/services/chat/common/chatEntitlementService.ts --- .../workbench/services/chat/common/chatEntitlementService.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/vs/workbench/services/chat/common/chatEntitlementService.ts b/src/vs/workbench/services/chat/common/chatEntitlementService.ts index 71a4061a3f04..d191a668294a 100644 --- a/src/vs/workbench/services/chat/common/chatEntitlementService.ts +++ b/src/vs/workbench/services/chat/common/chatEntitlementService.ts @@ -239,12 +239,8 @@ export class ChatEntitlementService extends Disposable implements IChatEntitleme @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService, @IContextKeyService private readonly contextKeyService: IContextKeyService, @IConfigurationService private readonly configurationService: IConfigurationService, -<<<<<<< HEAD - @ITelemetryService private readonly telemetryService: ITelemetryService -======= @ITelemetryService private readonly telemetryService: ITelemetryService, @ILifecycleService private readonly lifecycleService: ILifecycleService, ->>>>>>> origin/main ) { super(); From 6e57ed160a3de07d49573f96403dc8e069871d42 Mon Sep 17 00:00:00 2001 From: Simon Siefke Date: Mon, 15 Dec 2025 17:16:06 +0100 Subject: [PATCH 28/28] simplify code --- .../workbench/api/browser/mainThreadStatusBar.ts | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadStatusBar.ts b/src/vs/workbench/api/browser/mainThreadStatusBar.ts index 1a84d34a28ef..2350040756f5 100644 --- a/src/vs/workbench/api/browser/mainThreadStatusBar.ts +++ b/src/vs/workbench/api/browser/mainThreadStatusBar.ts @@ -6,7 +6,7 @@ import { MainThreadStatusBarShape, MainContext, ExtHostContext, StatusBarItemDto, ExtHostStatusBarShape } from '../common/extHost.protocol.js'; import { ThemeColor } from '../../../base/common/themables.js'; import { extHostNamedCustomer, IExtHostContext } from '../../services/extensions/common/extHostCustomers.js'; -import { DisposableStore, DisposableMap, toDisposable } from '../../../base/common/lifecycle.js'; +import { DisposableMap, toDisposable, Disposable } from '../../../base/common/lifecycle.js'; import { Command } from '../../../editor/common/languages.js'; import { IAccessibilityInformation } from '../../../platform/accessibility/common/accessibility.js'; import { IMarkdownString } from '../../../base/common/htmlContent.js'; @@ -16,16 +16,16 @@ import { IManagedHoverTooltipMarkdownString } from '../../../base/browser/ui/hov import { CancellationToken } from '../../../base/common/cancellation.js'; @extHostNamedCustomer(MainContext.MainThreadStatusBar) -export class MainThreadStatusBar implements MainThreadStatusBarShape { +export class MainThreadStatusBar extends Disposable implements MainThreadStatusBarShape { private readonly _proxy: ExtHostStatusBarShape; - private readonly _store = new DisposableStore(); - private readonly _entryDisposables = new DisposableMap(); + private readonly _entryDisposables = this._register(new DisposableMap()); constructor( extHostContext: IExtHostContext, @IExtensionStatusBarItemService private readonly statusbarService: IExtensionStatusBarItemService ) { + super(); this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostStatusBar); // once, at startup read existing items and send them over @@ -36,7 +36,7 @@ export class MainThreadStatusBar implements MainThreadStatusBarShape { this._proxy.$acceptStaticEntries(entries); - this._store.add(statusbarService.onDidChange(e => { + this._register(statusbarService.onDidChange(e => { if (e.added) { this._proxy.$acceptStaticEntries([asDto(e.added[0], e.added[1])]); } @@ -56,10 +56,6 @@ export class MainThreadStatusBar implements MainThreadStatusBarShape { } } - dispose(): void { - this._store.dispose(); - } - $setEntry(entryId: string, id: string, extensionId: string | undefined, name: string, text: string, tooltip: IMarkdownString | string | undefined, hasTooltipProvider: boolean, command: Command | undefined, color: string | ThemeColor | undefined, backgroundColor: ThemeColor | undefined, alignLeft: boolean, priority: number | undefined, accessibilityInformation: IAccessibilityInformation | undefined): void { const tooltipOrTooltipProvider = hasTooltipProvider ? { @@ -79,6 +75,5 @@ export class MainThreadStatusBar implements MainThreadStatusBarShape { $disposeEntry(entryId: string) { this._entryDisposables.deleteAndDispose(entryId); - this.statusbarService.unsetEntry(entryId); } }