diff --git a/src/vs/workbench/contrib/chat/browser/chatWindowNotifier.ts b/src/vs/workbench/contrib/chat/browser/chatWindowNotifier.ts index d9fe036dac8801..3dce99f35720d6 100644 --- a/src/vs/workbench/contrib/chat/browser/chatWindowNotifier.ts +++ b/src/vs/workbench/contrib/chat/browser/chatWindowNotifier.ts @@ -11,17 +11,14 @@ import { autorunDelta, autorunIterableDelta } from '../../../../base/common/obse import { URI } from '../../../../base/common/uri.js'; import { localize } from '../../../../nls.js'; import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js'; -import { ICommandService } from '../../../../platform/commands/common/commands.js'; import { FocusMode } from '../../../../platform/native/common/native.js'; import { IWorkbenchContribution } from '../../../common/contributions.js'; import { IHostService } from '../../../services/host/browser/host.js'; import { IChatModel, IChatRequestNeedsInputInfo } from '../common/model/chatModel.js'; -import { IChatService } from '../common/chatService/chatService.js'; +import { IChatService, IChatToolInvocation, ToolConfirmKind } from '../common/chatService/chatService.js'; import { migrateLegacyTerminalToolSpecificData } from '../common/chat.js'; import { ChatConfiguration, ChatNotificationMode } from '../common/constants.js'; import { IChatWidgetService } from './chat.js'; -import { AcceptToolConfirmationActionId, IToolConfirmationActionContext } from './actions/chatToolActions.js'; -import { isMacintosh } from '../../../../base/common/platform.js'; /** * Observes all live chat models and triggers OS notifications when any model @@ -38,7 +35,6 @@ export class ChatWindowNotifier extends Disposable implements IWorkbenchContribu @IChatWidgetService private readonly _chatWidgetService: IChatWidgetService, @IHostService private readonly _hostService: IHostService, @IConfigurationService private readonly _configurationService: IConfigurationService, - @ICommandService private readonly _commandService: ICommandService, ) { super(); @@ -116,28 +112,44 @@ export class ChatWindowNotifier extends Disposable implements IWorkbenchContribu actions: [actionLabel], }, cts.token); + if (result.actionIndex === 0 && !isQuestionCarousel && this._confirmAllow(sessionResource)) { + return; // skip focusing/opening chat if we successfully confirmed the tool invocation from the toast action + } + if (result.clicked || typeof result.actionIndex === 'number') { await this._hostService.focus(targetWindow, { mode: FocusMode.Force }); const widget = await this._chatWidgetService.openSession(sessionResource); widget?.focusInput(); - - if (result.actionIndex === 0 && !isQuestionCarousel) { - await this._commandService.executeCommand(AcceptToolConfirmationActionId, { sessionResource } satisfies IToolConfirmationActionContext); - } } } finally { this._clearNotification(sessionResource); } } + private _confirmAllow(sessionResource: URI): boolean { + const model = this._chatService.getSession(sessionResource); + const lastResponse = model?.lastRequest?.response; + if (!lastResponse) { + return false; + } + for (const part of lastResponse.response.value) { + const state = part.kind === 'toolInvocation' ? part.state.get() : undefined; + if (state?.type === IChatToolInvocation.StateKind.WaitingForConfirmation || state?.type === IChatToolInvocation.StateKind.WaitingForPostApproval) { + state.confirm({ type: ToolConfirmKind.UserAction }); + return true; + } + } + return false; + } + private _getNotificationBody(sessionResource: URI, info: IChatRequestNeedsInputInfo, isQuestionCarousel: boolean): string { - const terminalCommand = this._getPendingTerminalCommand(sessionResource); if (isQuestionCarousel) { return localize('questionCarouselDetail', "Questions need your input."); } - if (isMacintosh && terminalCommand) { - return this._sanitizeOSToastText(terminalCommand); // prefer full command on macOS where you can approve from the toast + const terminalCommand = this._getPendingTerminalCommand(sessionResource); + if (terminalCommand) { + return this._sanitizeOSToastText(terminalCommand); } if (info.detail) { return this._sanitizeOSToastText(info.detail);