From f46b8a488626b01af39ef617bb7a3d7abebe632c Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Sun, 23 Nov 2025 22:20:40 -0800 Subject: [PATCH] Add disableBackgroundKeepAlive option for chat sessions (#278979) * Add disableBackgroundKeepAlive for quick chat ChatModels * Named interface --------- Co-authored-by: Benjamin Pasero --- src/vs/workbench/contrib/chat/browser/chatQuick.ts | 2 +- src/vs/workbench/contrib/chat/common/chatModel.ts | 4 ++-- src/vs/workbench/contrib/chat/common/chatModelStore.ts | 1 + src/vs/workbench/contrib/chat/common/chatService.ts | 7 ++++++- src/vs/workbench/contrib/chat/common/chatServiceImpl.ts | 9 +++++---- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/chatQuick.ts b/src/vs/workbench/contrib/chat/browser/chatQuick.ts index 59523459629..c12c4889d58 100644 --- a/src/vs/workbench/contrib/chat/browser/chatQuick.ts +++ b/src/vs/workbench/contrib/chat/browser/chatQuick.ts @@ -395,7 +395,7 @@ class QuickChat extends Disposable { } private updateModel(): void { - this.modelRef ??= this.chatService.startSession(ChatAgentLocation.Chat, CancellationToken.None); + this.modelRef ??= this.chatService.startSession(ChatAgentLocation.Chat, CancellationToken.None, { disableBackgroundKeepAlive: true }); const model = this.modelRef?.object; if (!model) { throw new Error('Could not start chat session'); diff --git a/src/vs/workbench/contrib/chat/common/chatModel.ts b/src/vs/workbench/contrib/chat/common/chatModel.ts index a7a7afc1f42..7c3ba5b0c3a 100644 --- a/src/vs/workbench/contrib/chat/common/chatModel.ts +++ b/src/vs/workbench/contrib/chat/common/chatModel.ts @@ -1645,7 +1645,7 @@ export class ChatModel extends Disposable implements IChatModel { constructor( initialData: ISerializableChatData | IExportableChatData | undefined, - initialModelProps: { initialLocation: ChatAgentLocation; canUseTools: boolean; resource?: URI; sessionId?: string }, + initialModelProps: { initialLocation: ChatAgentLocation; canUseTools: boolean; resource?: URI; sessionId?: string; disableBackgroundKeepAlive?: boolean }, @ILogService private readonly logService: ILogService, @IChatAgentService private readonly chatAgentService: IChatAgentService, @IChatEditingService private readonly chatEditingService: IChatEditingService, @@ -1713,7 +1713,7 @@ export class ChatModel extends Disposable implements IChatModel { // Retain a reference to itself when a request is in progress, so the ChatModel stays alive in the background // only while running a request. TODO also keep it alive for 5min or so so we don't have to dispose/restore too often? - if (this.initialLocation === ChatAgentLocation.Chat && configurationService.getValue('chat.localBackgroundSessions')) { + if (this.initialLocation === ChatAgentLocation.Chat && configurationService.getValue('chat.localBackgroundSessions') && !initialModelProps.disableBackgroundKeepAlive) { const selfRef = this._register(new MutableDisposable()); this._register(autorun(r => { const inProgress = this.requestInProgress.read(r); diff --git a/src/vs/workbench/contrib/chat/common/chatModelStore.ts b/src/vs/workbench/contrib/chat/common/chatModelStore.ts index fe6a9b169f3..2dbe1da20c2 100644 --- a/src/vs/workbench/contrib/chat/common/chatModelStore.ts +++ b/src/vs/workbench/contrib/chat/common/chatModelStore.ts @@ -21,6 +21,7 @@ export interface IStartSessionProps { readonly sessionId?: string; readonly canUseTools: boolean; readonly transferEditingSession?: IChatEditingSession; + readonly disableBackgroundKeepAlive?: boolean; } export interface ChatModelStoreDelegate { diff --git a/src/vs/workbench/contrib/chat/common/chatService.ts b/src/vs/workbench/contrib/chat/common/chatService.ts index 790dc303214..6a59191dbb6 100644 --- a/src/vs/workbench/contrib/chat/common/chatService.ts +++ b/src/vs/workbench/contrib/chat/common/chatService.ts @@ -945,7 +945,7 @@ export interface IChatService { isEnabled(location: ChatAgentLocation): boolean; hasSessions(): boolean; - startSession(location: ChatAgentLocation, token: CancellationToken, options?: { canUseTools?: boolean }): IChatModelReference; + startSession(location: ChatAgentLocation, token: CancellationToken, options?: IChatSessionStartOptions): IChatModelReference; /** * Get an active session without holding a reference to it. @@ -1014,3 +1014,8 @@ export interface IChatSessionContext { } export const KEYWORD_ACTIVIATION_SETTING_ID = 'accessibility.voice.keywordActivation'; + +export interface IChatSessionStartOptions { + canUseTools?: boolean; + disableBackgroundKeepAlive?: boolean; +} diff --git a/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts b/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts index f30dad6467f..24493c565ea 100644 --- a/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts +++ b/src/vs/workbench/contrib/chat/common/chatServiceImpl.ts @@ -33,7 +33,7 @@ import { ChatModel, ChatRequestModel, ChatRequestRemovalReason, IChatModel, ICha import { ChatModelStore, IStartSessionProps } from './chatModelStore.js'; import { chatAgentLeader, ChatRequestAgentPart, ChatRequestAgentSubcommandPart, ChatRequestSlashCommandPart, ChatRequestTextPart, chatSubcommandLeader, getPromptText, IParsedChatRequest } from './chatParserTypes.js'; import { ChatRequestParser } from './chatRequestParser.js'; -import { ChatMcpServersStarting, IChatCompleteResponse, IChatDetail, IChatFollowup, IChatModelReference, IChatProgress, IChatSendRequestData, IChatSendRequestOptions, IChatSendRequestResponseState, IChatService, IChatSessionContext, IChatTransferredSessionData, IChatUserActionEvent } from './chatService.js'; +import { ChatMcpServersStarting, IChatCompleteResponse, IChatDetail, IChatFollowup, IChatModelReference, IChatProgress, IChatSendRequestData, IChatSendRequestOptions, IChatSendRequestResponseState, IChatService, IChatSessionContext, IChatSessionStartOptions, IChatTransferredSessionData, IChatUserActionEvent } from './chatService.js'; import { ChatRequestTelemetry, ChatServiceTelemetry } from './chatServiceTelemetry.js'; import { IChatSessionsService } from './chatSessionsService.js'; import { ChatSessionStore, IChatTransfer2 } from './chatSessionStore.js'; @@ -413,7 +413,7 @@ export class ChatService extends Disposable implements IChatService { await this._chatSessionStore.clearAllSessions(); } - startSession(location: ChatAgentLocation, token: CancellationToken, options?: { canUseTools?: boolean }): IChatModelReference { + startSession(location: ChatAgentLocation, token: CancellationToken, options?: IChatSessionStartOptions): IChatModelReference { this.trace('startSession'); const sessionId = generateUuid(); const sessionResource = LocalChatSessionUri.forSession(sessionId); @@ -424,12 +424,13 @@ export class ChatService extends Disposable implements IChatService { sessionResource, sessionId, canUseTools: options?.canUseTools ?? true, + disableBackgroundKeepAlive: options?.disableBackgroundKeepAlive }); } private _startSession(props: IStartSessionProps): ChatModel { - const { initialData, location, token, sessionResource, sessionId, canUseTools, transferEditingSession } = props; - const model = this.instantiationService.createInstance(ChatModel, initialData, { initialLocation: location, canUseTools, resource: sessionResource, sessionId }); + const { initialData, location, token, sessionResource, sessionId, canUseTools, transferEditingSession, disableBackgroundKeepAlive } = props; + const model = this.instantiationService.createInstance(ChatModel, initialData, { initialLocation: location, canUseTools, resource: sessionResource, sessionId, disableBackgroundKeepAlive }); if (location === ChatAgentLocation.Chat) { model.startEditingSession(true, transferEditingSession); }