Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 24 additions & 12 deletions src/vs/workbench/contrib/chat/browser/chatWindowNotifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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();

Expand Down Expand Up @@ -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
Comment thread
bpasero marked this conversation as resolved.
}

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);
Expand Down
Loading