diff --git a/src/vs/workbench/api/browser/mainThreadChatSessions.ts b/src/vs/workbench/api/browser/mainThreadChatSessions.ts index efbb3782c3724..df7a26168b023 100644 --- a/src/vs/workbench/api/browser/mainThreadChatSessions.ts +++ b/src/vs/workbench/api/browser/mainThreadChatSessions.ts @@ -120,17 +120,27 @@ export class ObservableChatSession extends Disposable implements ChatSession { if (sessionContent.hasActiveResponseCallback && !this.interruptActiveResponseCallback) { this.interruptActiveResponseCallback = async () => { + const confirmInterrupt = () => { + if (this._disposalPending) { + this._proxy.$disposeChatSessionContent(this._providerHandle, this.sessionId); + this._disposalPending = false; + } + this._proxy.$interruptChatSessionActiveResponse(this._providerHandle, this.sessionId, 'ongoing'); + return true; + }; + + if (sessionContent.supportsInterruption) { + // If the session supports hot reload, interrupt without confirmation + return confirmInterrupt(); + } + + // Prompt the user to confirm interruption return this._dialogService.confirm({ message: localize('interruptActiveResponse', 'Are you sure you want to interrupt the active session?') }).then(confirmed => { if (confirmed.confirmed) { // User confirmed interruption - dispose the session content on extension host - if (this._disposalPending) { - this._proxy.$disposeChatSessionContent(this._providerHandle, this.sessionId); - this._disposalPending = false; - } - this._proxy.$interruptChatSessionActiveResponse(this._providerHandle, this.sessionId, 'ongoing'); - return true; + return confirmInterrupt(); } else { // When user cancels the interruption, fire an empty progress message to keep the session alive // This matches the behavior of the old implementation diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 1361b81143e6d..de74a2f28a3e4 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -1518,9 +1518,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I checkProposedApiEnabled(extension, 'chatSessionsProvider'); return extHostChatSessions.registerChatSessionItemProvider(extension, chatSessionType, provider); }, - registerChatSessionContentProvider(chatSessionType: string, provider: vscode.ChatSessionContentProvider) { + registerChatSessionContentProvider(chatSessionType: string, provider: vscode.ChatSessionContentProvider, capabilities?: vscode.ChatSessionCapabilities) { checkProposedApiEnabled(extension, 'chatSessionsProvider'); - return extHostChatSessions.registerChatSessionContentProvider(extension, chatSessionType, provider); + return extHostChatSessions.registerChatSessionContentProvider(extension, chatSessionType, provider, capabilities); }, registerChatOutputRenderer: (viewType: string, renderer: vscode.ChatOutputRenderer) => { checkProposedApiEnabled(extension, 'chatOutputRenderer'); diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 090aaaa1c05e6..b5c295f625b8a 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -3145,6 +3145,7 @@ export interface ChatSessionDto { history: Array; hasActiveResponseCallback: boolean; hasRequestHandler: boolean; + supportsInterruption: boolean; } diff --git a/src/vs/workbench/api/common/extHostChatSessions.ts b/src/vs/workbench/api/common/extHostChatSessions.ts index 765fef204604e..7779ae391f8c3 100644 --- a/src/vs/workbench/api/common/extHostChatSessions.ts +++ b/src/vs/workbench/api/common/extHostChatSessions.ts @@ -57,6 +57,7 @@ export class ExtHostChatSessions extends Disposable implements ExtHostChatSessio private readonly _chatSessionContentProviders = new Map(); private _nextChatSessionItemProviderHandle = 0; @@ -110,11 +111,11 @@ export class ExtHostChatSessions extends Disposable implements ExtHostChatSessio }; } - registerChatSessionContentProvider(extension: IExtensionDescription, chatSessionType: string, provider: vscode.ChatSessionContentProvider): vscode.Disposable { + registerChatSessionContentProvider(extension: IExtensionDescription, chatSessionType: string, provider: vscode.ChatSessionContentProvider, capabilities?: vscode.ChatSessionCapabilities): vscode.Disposable { const handle = this._nextChatSessionContentProviderHandle++; const disposables = new DisposableStore(); - this._chatSessionContentProviders.set(handle, { provider, extension, disposable: disposables }); + this._chatSessionContentProviders.set(handle, { provider, extension, capabilities, disposable: disposables }); this._proxy.$registerChatSessionContentProvider(handle, chatSessionType); return new extHostTypes.Disposable(() => { @@ -243,11 +244,12 @@ export class ExtHostChatSessions extends Disposable implements ExtHostChatSessio this._proxy.$handleProgressComplete(handle, id, 'ongoing'); }); } - + const { capabilities } = provider; return { id: sessionId + '', hasActiveResponseCallback: !!session.activeResponseCallback, hasRequestHandler: !!session.requestHandler, + supportsInterruption: !!capabilities?.supportsInterruptions, history: session.history.map(turn => { if (turn instanceof extHostTypes.ChatRequestTurn) { return { type: 'request' as const, prompt: turn.prompt, participant: turn.participant }; diff --git a/src/vscode-dts/vscode.proposed.chatSessionsProvider.d.ts b/src/vscode-dts/vscode.proposed.chatSessionsProvider.d.ts index 92ba38d36e421..acebca716e662 100644 --- a/src/vscode-dts/vscode.proposed.chatSessionsProvider.d.ts +++ b/src/vscode-dts/vscode.proposed.chatSessionsProvider.d.ts @@ -111,7 +111,6 @@ declare module 'vscode' { } export interface ChatSession { - /** * The full history of the session * @@ -171,7 +170,14 @@ declare module 'vscode' { * * @returns A disposable that unregisters the provider when disposed. */ - export function registerChatSessionContentProvider(chatSessionType: string, provider: ChatSessionContentProvider): Disposable; + export function registerChatSessionContentProvider(chatSessionType: string, provider: ChatSessionContentProvider, capabilities?: ChatSessionCapabilities): Disposable; + } + + export interface ChatSessionCapabilities { + /** + * Whether sessions can be interrupted and resumed without side-effects. + */ + supportsInterruptions?: boolean; } export interface ChatSessionShowOptions {