mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-08 07:44:33 +01:00
Go back to original edits mode in unified view with all models (#244354)
By default, adding setting chat.edits2.enabled to control it. Disallow switching from edits mode to others, unless using edits2.
This commit is contained in:
@@ -805,19 +805,19 @@ export async function handleCurrentEditingSession(currentEditingSession: IChatEd
|
||||
phrase = phrase ?? defaultPhrase;
|
||||
const { result } = await dialogService.prompt({
|
||||
title: localize('chat.startEditing.confirmation.title', "Start new chat?"),
|
||||
message: phrase + ' ' + localize('chat.startEditing.confirmation.pending.message.2', "Do you want to accept pending edits to {0} files?", undecidedEdits.length),
|
||||
message: phrase + ' ' + localize('chat.startEditing.confirmation.pending.message.2', "Do you want to keep pending edits to {0} files?", undecidedEdits.length),
|
||||
type: 'info',
|
||||
cancelButton: true,
|
||||
buttons: [
|
||||
{
|
||||
label: localize('chat.startEditing.confirmation.acceptEdits', "Accept & Continue"),
|
||||
label: localize('chat.startEditing.confirmation.acceptEdits', "Keep & Continue"),
|
||||
run: async () => {
|
||||
await currentEditingSession.accept();
|
||||
return true;
|
||||
}
|
||||
},
|
||||
{
|
||||
label: localize('chat.startEditing.confirmation.discardEdits', "Discard & Continue"),
|
||||
label: localize('chat.startEditing.confirmation.discardEdits', "Undo & Continue"),
|
||||
run: async () => {
|
||||
await currentEditingSession.reject();
|
||||
return true;
|
||||
|
||||
@@ -10,6 +10,7 @@ import { ServicesAccessor } from '../../../../../editor/browser/editorExtensions
|
||||
import { localize, localize2 } from '../../../../../nls.js';
|
||||
import { Action2, MenuId, registerAction2 } from '../../../../../platform/actions/common/actions.js';
|
||||
import { ICommandService } from '../../../../../platform/commands/common/commands.js';
|
||||
import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.js';
|
||||
import { ContextKeyExpr } from '../../../../../platform/contextkey/common/contextkey.js';
|
||||
import { IDialogService } from '../../../../../platform/dialogs/common/dialogs.js';
|
||||
import { KeybindingWeight } from '../../../../../platform/keybinding/common/keybindingsRegistry.js';
|
||||
@@ -19,12 +20,12 @@ import { ChatContextKeyExprs, ChatContextKeys } from '../../common/chatContextKe
|
||||
import { IChatEditingService, IChatEditingSession, WorkingSetEntryState } from '../../common/chatEditingService.js';
|
||||
import { chatVariableLeader } from '../../common/chatParserTypes.js';
|
||||
import { IChatService } from '../../common/chatService.js';
|
||||
import { ChatAgentLocation, ChatMode } from '../../common/constants.js';
|
||||
import { ChatAgentLocation, ChatConfiguration, ChatMode } from '../../common/constants.js';
|
||||
import { ILanguageModelToolsService } from '../../common/languageModelToolsService.js';
|
||||
import { EditsViewId, IChatWidget, IChatWidgetService } from '../chat.js';
|
||||
import { discardAllEditsWithConfirmation, getEditingSessionContext } from '../chatEditing/chatEditingActions.js';
|
||||
import { getEditingSessionContext } from '../chatEditing/chatEditingActions.js';
|
||||
import { ChatViewPane } from '../chatViewPane.js';
|
||||
import { CHAT_CATEGORY } from './chatActions.js';
|
||||
import { CHAT_CATEGORY, handleCurrentEditingSession } from './chatActions.js';
|
||||
import { ACTION_ID_NEW_CHAT, ChatDoneActionId } from './chatClearActions.js';
|
||||
|
||||
export interface IVoiceChatExecuteActionContext {
|
||||
@@ -146,6 +147,7 @@ class ToggleChatModeAction extends Action2 {
|
||||
async run(accessor: ServicesAccessor, ...args: any[]) {
|
||||
const chatService = accessor.get(IChatService);
|
||||
const commandService = accessor.get(ICommandService);
|
||||
const configurationService = accessor.get(IConfigurationService);
|
||||
const dialogService = accessor.get(IDialogService);
|
||||
|
||||
const context = getEditingSessionContext(accessor, args);
|
||||
@@ -154,52 +156,62 @@ class ToggleChatModeAction extends Action2 {
|
||||
}
|
||||
|
||||
const arg = args.at(0) as IToggleChatModeArgs | undefined;
|
||||
if (arg?.mode === context.chatWidget.input.currentMode) {
|
||||
const chatSession = context.chatWidget.viewModel?.model;
|
||||
const requestCount = chatSession?.getRequests().length ?? 0;
|
||||
const switchToMode = arg?.mode ?? this.getNextMode(context.chatWidget, requestCount, configurationService);
|
||||
const needToClearEdits = (!chatService.unifiedViewEnabled || (!configurationService.getValue(ChatConfiguration.Edits2Enabled) && (context.chatWidget.input.currentMode === ChatMode.Edit || switchToMode === ChatMode.Edit))) && requestCount > 0;
|
||||
|
||||
if (switchToMode === context.chatWidget.input.currentMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!chatService.unifiedViewEnabled) {
|
||||
// TODO will not require discarding the session when we are able to switch modes mid-session
|
||||
const entries = context.editingSession?.entries.get();
|
||||
if (context.editingSession && entries && entries.length > 0 && entries.some(entry => entry.state.get() === WorkingSetEntryState.Modified)) {
|
||||
if (!await discardAllEditsWithConfirmation(accessor, context.editingSession)) {
|
||||
// User cancelled
|
||||
if (needToClearEdits) {
|
||||
// If not in unified view, or not using edits2 and switching into or out of edit mode, ask to discard the session
|
||||
const phrase = localize('switchMode.confirmPhrase', "Switching chat modes will end your current edit session.");
|
||||
if (!context.editingSession) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentEdits = context.editingSession.entries.get();
|
||||
const undecidedEdits = currentEdits.filter((edit) => edit.state.get() === WorkingSetEntryState.Modified);
|
||||
if (undecidedEdits.length > 0) {
|
||||
if (!await handleCurrentEditingSession(context.editingSession, phrase, dialogService)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
const chatSession = context.chatWidget.viewModel?.model;
|
||||
if (chatSession?.getRequests().length) {
|
||||
const confirmation = await dialogService.confirm({
|
||||
title: localize('agent.newSession', "Start new session?"),
|
||||
message: localize('agent.newSessionMessage', "Changing the chat mode will start a new session. Would you like to continue?"),
|
||||
primaryButton: localize('agent.newSession.confirm', "Yes"),
|
||||
type: 'info'
|
||||
});
|
||||
if (!confirmation.confirmed) {
|
||||
return;
|
||||
}
|
||||
const confirmation = await dialogService.confirm({
|
||||
title: localize('agent.newSession', "Start new session?"),
|
||||
message: localize('agent.newSessionMessage', "Changing the chat mode will end your current edit session. Would you like to continue?"),
|
||||
primaryButton: localize('agent.newSession.confirm', "Yes"),
|
||||
type: 'info'
|
||||
});
|
||||
if (!confirmation.confirmed) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (arg?.mode) {
|
||||
context.chatWidget.input.setChatMode(arg.mode);
|
||||
} else {
|
||||
const modes = [ChatMode.Agent, ChatMode.Edit];
|
||||
if (context.chatWidget.location === ChatAgentLocation.Panel) {
|
||||
modes.push(ChatMode.Ask);
|
||||
}
|
||||
context.chatWidget.input.setChatMode(switchToMode);
|
||||
|
||||
const modeIndex = modes.indexOf(context.chatWidget.input.currentMode);
|
||||
const newMode = modes[(modeIndex + 1) % modes.length];
|
||||
context.chatWidget.input.setChatMode(newMode);
|
||||
}
|
||||
|
||||
if (!chatService.unifiedViewEnabled && context.chatWidget.viewModel?.model.getRequests().length) {
|
||||
if (needToClearEdits) {
|
||||
const clearAction = chatService.unifiedViewEnabled ? ACTION_ID_NEW_CHAT : ChatDoneActionId;
|
||||
await commandService.executeCommand(clearAction);
|
||||
}
|
||||
}
|
||||
|
||||
private getNextMode(chatWidget: IChatWidget, requestCount: number, configurationService: IConfigurationService): ChatMode {
|
||||
const modes = [ChatMode.Agent];
|
||||
if (configurationService.getValue(ChatConfiguration.Edits2Enabled) || requestCount === 0) {
|
||||
modes.push(ChatMode.Edit);
|
||||
}
|
||||
if (chatWidget.location === ChatAgentLocation.Panel) {
|
||||
modes.push(ChatMode.Ask);
|
||||
}
|
||||
|
||||
const modeIndex = modes.indexOf(chatWidget.input.currentMode);
|
||||
const newMode = modes[(modeIndex + 1) % modes.length];
|
||||
return newMode;
|
||||
}
|
||||
}
|
||||
|
||||
export const ToggleRequestPausedActionId = 'workbench.action.chat.toggleRequestPaused';
|
||||
|
||||
@@ -76,7 +76,7 @@ import { IChatFollowup, IChatService } from '../common/chatService.js';
|
||||
import { IChatVariablesService } from '../common/chatVariables.js';
|
||||
import { IChatResponseViewModel } from '../common/chatViewModel.js';
|
||||
import { ChatInputHistoryMaxEntries, IChatHistoryEntry, IChatInputState, IChatWidgetHistoryService } from '../common/chatWidgetHistoryService.js';
|
||||
import { ChatAgentLocation, ChatMode } from '../common/constants.js';
|
||||
import { ChatAgentLocation, ChatConfiguration, ChatMode } from '../common/constants.js';
|
||||
import { ILanguageModelChatMetadataAndIdentifier, ILanguageModelsService } from '../common/languageModels.js';
|
||||
import { CancelAction, ChatEditingSessionSubmitAction, ChatSubmitAction, ChatSwitchToNextModelActionId, IChatExecuteActionContext, IToggleChatModeArgs, ToggleAgentModeActionId } from './actions/chatExecuteActions.js';
|
||||
import { AttachToolsAction } from './actions/chatToolActions.js';
|
||||
@@ -437,6 +437,11 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
|
||||
this._register(this._onDidChangeCurrentChatMode.event(() => {
|
||||
this.checkModelSupported();
|
||||
}));
|
||||
this._register(this.configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration(ChatConfiguration.Edits2Enabled)) {
|
||||
this.checkModelSupported();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public switchToNextModel(): void {
|
||||
@@ -470,7 +475,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
|
||||
|
||||
private modelSupportedForDefaultAgent(model: ILanguageModelChatMetadataAndIdentifier): boolean {
|
||||
// Probably this logic could live in configuration on the agent, or somewhere else, if it gets more complex
|
||||
if (this.currentMode === ChatMode.Agent || (this.currentMode === ChatMode.Edit && this.chatService.unifiedViewEnabled)) {
|
||||
if (this.currentMode === ChatMode.Agent || (this.currentMode === ChatMode.Edit && this.configurationService.getValue(ChatConfiguration.Edits2Enabled))) {
|
||||
if (this.configurationService.getValue('chat.agent.allModels')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ export enum ChatConfiguration {
|
||||
UnifiedChatView = 'chat.unifiedChatView',
|
||||
UseFileStorage = 'chat.useFileStorage',
|
||||
AgentEnabled = 'chat.agent.enabled',
|
||||
Edits2Enabled = 'chat.edits2.enabled',
|
||||
}
|
||||
|
||||
export enum ChatMode {
|
||||
|
||||
Reference in New Issue
Block a user