diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts b/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts index 670f8a79cc1..3279a6a0b97 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts @@ -32,17 +32,27 @@ export interface IChatExecuteActionContext { voice?: IVoiceChatExecuteActionContext; } -export class SubmitAction extends Action2 { +abstract class SubmitAction extends Action2 { + run(accessor: ServicesAccessor, ...args: any[]) { + const context: IChatExecuteActionContext | undefined = args[0]; + + const widgetService = accessor.get(IChatWidgetService); + const widget = context?.widget ?? widgetService.lastFocusedWidget; + widget?.acceptInput(context?.inputValue); + } +} + +export class ChatSubmitAction extends SubmitAction { static readonly ID = 'workbench.action.chat.submit'; constructor() { super({ - id: SubmitAction.ID, + id: ChatSubmitAction.ID, title: localize2('interactive.submit.label', "Send and Dispatch"), f1: false, category: CHAT_CATEGORY, icon: Codicon.send, - precondition: ContextKeyExpr.and(ChatContextKeys.inputHasText, ChatContextKeys.requestInProgress.negate(), ContextKeyExpr.or(ChatContextKeys.location.notEqualsTo(ChatAgentLocation.EditingSession), ContextKeyExpr.and(ChatContextKeys.location.isEqualTo(ChatAgentLocation.EditingSession), applyingChatEditsContextKey.toNegated()))), + precondition: ContextKeyExpr.and(ChatContextKeys.inputHasText, ChatContextKeys.requestInProgress.negate(), ChatContextKeys.location.notEqualsTo(ChatAgentLocation.EditingSession)), keybinding: { when: ChatContextKeys.inChatInput, primary: KeyCode.Enter, @@ -57,19 +67,45 @@ export class SubmitAction extends Action2 { { id: MenuId.ChatExecute, order: 4, - when: ContextKeyExpr.and(ChatContextKeys.requestInProgress.negate(), ContextKeyExpr.or(ChatContextKeys.location.notEqualsTo(ChatAgentLocation.EditingSession), ContextKeyExpr.and(ChatContextKeys.location.isEqualTo(ChatAgentLocation.EditingSession), applyingChatEditsContextKey.toNegated()))), + when: ContextKeyExpr.and(ChatContextKeys.requestInProgress.negate(), ChatContextKeys.location.notEqualsTo(ChatAgentLocation.EditingSession)), group: 'navigation', }, ] }); } +} - run(accessor: ServicesAccessor, ...args: any[]) { - const context: IChatExecuteActionContext | undefined = args[0]; +export class ChatEditingSessionSubmitAction extends SubmitAction { + static readonly ID = 'workbench.action.edits.submit'; - const widgetService = accessor.get(IChatWidgetService); - const widget = context?.widget ?? widgetService.lastFocusedWidget; - widget?.acceptInput(context?.inputValue); + constructor() { + super({ + id: ChatEditingSessionSubmitAction.ID, + title: localize2('edits.submit.label', "Send"), + f1: false, + category: CHAT_CATEGORY, + icon: Codicon.send, + precondition: ContextKeyExpr.and(ChatContextKeys.inputHasText, ChatContextKeys.requestInProgress.negate(), ChatContextKeys.location.isEqualTo(ChatAgentLocation.EditingSession), applyingChatEditsContextKey.toNegated()), + keybinding: { + when: ChatContextKeys.inChatInput, + primary: KeyCode.Enter, + weight: KeybindingWeight.EditorContrib + }, + menu: [ + { + id: MenuId.ChatExecuteSecondary, + group: 'group_1', + when: ContextKeyExpr.and(ChatContextKeys.requestInProgress.negate(), ChatContextKeys.location.isEqualTo(ChatAgentLocation.EditingSession), applyingChatEditsContextKey.toNegated()), + order: 1 + }, + { + id: MenuId.ChatExecute, + order: 4, + when: ContextKeyExpr.and(ChatContextKeys.requestInProgress.negate(), ChatContextKeys.location.isEqualTo(ChatAgentLocation.EditingSession), applyingChatEditsContextKey.toNegated()), + group: 'navigation', + }, + ] + }); } } @@ -345,7 +381,8 @@ export class CancelAction extends Action2 { } export function registerChatExecuteActions() { - registerAction2(SubmitAction); + registerAction2(ChatSubmitAction); + registerAction2(ChatEditingSessionSubmitAction); registerAction2(SubmitWithoutDispatchingAction); registerAction2(CancelAction); registerAction2(SendToNewChatAction); diff --git a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts index df7bd7800ab..4ef5da659d2 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts @@ -44,7 +44,7 @@ import { registerChatCodeBlockActions, registerChatCodeCompareBlockActions } fro import { registerChatContextActions } from './actions/chatContextActions.js'; import { registerChatCopyActions } from './actions/chatCopyActions.js'; import { registerChatDeveloperActions } from './actions/chatDeveloperActions.js'; -import { SubmitAction, registerChatExecuteActions } from './actions/chatExecuteActions.js'; +import { ChatSubmitAction, registerChatExecuteActions } from './actions/chatExecuteActions.js'; import { registerChatFileTreeActions } from './actions/chatFileTreeActions.js'; import { registerChatExportActions } from './actions/chatImportExport.js'; import { registerMoveActions } from './actions/chatMoveActions.js'; @@ -259,7 +259,7 @@ class ChatSlashStaticSlashCommandsContribution extends Disposable { return (agentLine + '\n' + commandText).trim(); }))).join('\n'); - progress.report({ content: new MarkdownString(agentText, { isTrusted: { enabledCommands: [SubmitAction.ID] } }), kind: 'markdownContent' }); + progress.report({ content: new MarkdownString(agentText, { isTrusted: { enabledCommands: [ChatSubmitAction.ID] } }), kind: 'markdownContent' }); // Report variables if (defaultAgent?.metadata.helpTextVariablesPrefix) { diff --git a/src/vs/workbench/contrib/chat/browser/chatInputPart.ts b/src/vs/workbench/contrib/chat/browser/chatInputPart.ts index 267e93c75ad..47e1ec40be6 100644 --- a/src/vs/workbench/contrib/chat/browser/chatInputPart.ts +++ b/src/vs/workbench/contrib/chat/browser/chatInputPart.ts @@ -77,7 +77,7 @@ import { IChatFollowup } from '../common/chatService.js'; import { IChatResponseViewModel } from '../common/chatViewModel.js'; import { IChatHistoryEntry, IChatInputState, IChatWidgetHistoryService } from '../common/chatWidgetHistoryService.js'; import { ILanguageModelChatMetadata, ILanguageModelsService } from '../common/languageModels.js'; -import { CancelAction, ChatModelPickerActionId, ChatSubmitSecondaryAgentAction, IChatExecuteActionContext, SubmitAction } from './actions/chatExecuteActions.js'; +import { CancelAction, ChatModelPickerActionId, ChatSubmitSecondaryAgentAction, IChatExecuteActionContext, ChatSubmitAction } from './actions/chatExecuteActions.js'; import { ImplicitContextAttachmentWidget } from './attachments/implicitContextAttachment.js'; import { IChatWidget } from './chat.js'; import { ChatAttachmentModel } from './chatAttachmentModel.js'; @@ -630,7 +630,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge hiddenItemStrategy: HiddenItemStrategy.Ignore, // keep it lean when hiding items and avoid a "..." overflow menu actionViewItemProvider: (action, options) => { if (this.location === ChatAgentLocation.Panel || this.location === ChatAgentLocation.Editor) { - if ((action.id === SubmitAction.ID || action.id === CancelAction.ID) && action instanceof MenuItemAction) { + if ((action.id === ChatSubmitAction.ID || action.id === CancelAction.ID) && action instanceof MenuItemAction) { const dropdownAction = this.instantiationService.createInstance(MenuItemAction, { id: 'chat.moreExecuteActions', title: localize('notebook.moreExecuteActionsLabel', "More..."), icon: Codicon.chevronDown }, undefined, undefined, undefined, undefined); return this.instantiationService.createInstance(ChatSubmitDropdownActionItem, action, dropdownAction, options); } diff --git a/src/vs/workbench/contrib/chat/browser/contrib/chatInputCompletions.ts b/src/vs/workbench/contrib/chat/browser/contrib/chatInputCompletions.ts index a5fe14671f4..58cd6c5cc22 100644 --- a/src/vs/workbench/contrib/chat/browser/contrib/chatInputCompletions.ts +++ b/src/vs/workbench/contrib/chat/browser/contrib/chatInputCompletions.ts @@ -33,7 +33,7 @@ import { ChatRequestAgentPart, ChatRequestAgentSubcommandPart, ChatRequestTextPa import { IChatSlashCommandService } from '../../common/chatSlashCommands.js'; import { IChatVariablesService, IDynamicVariable } from '../../common/chatVariables.js'; import { ILanguageModelToolsService } from '../../common/languageModelToolsService.js'; -import { SubmitAction } from '../actions/chatExecuteActions.js'; +import { ChatEditingSessionSubmitAction, ChatSubmitAction } from '../actions/chatExecuteActions.js'; import { IChatWidget, IChatWidgetService } from '../chat.js'; import { ChatInputPart } from '../chatInputPart.js'; import { ChatDynamicVariableModel, SelectAndInsertFileAction } from './chatDynamicVariables.js'; @@ -87,7 +87,7 @@ class SlashCommandCompletions extends Disposable { range, sortText: c.sortText ?? 'a'.repeat(i + 1), kind: CompletionItemKind.Text, // The icons are disabled here anyway, - command: c.executeImmediately ? { id: SubmitAction.ID, title: withSlash, arguments: [{ widget, inputValue: `${withSlash} ` }] } : undefined, + command: c.executeImmediately ? { id: widget.location === ChatAgentLocation.EditingSession ? ChatEditingSessionSubmitAction.ID : ChatSubmitAction.ID, title: withSlash, arguments: [{ widget, inputValue: `${withSlash} ` }] } : undefined, }; }) }; @@ -128,7 +128,7 @@ class SlashCommandCompletions extends Disposable { filterText: `${chatAgentLeader}${c.command}`, sortText: c.sortText ?? 'z'.repeat(i + 1), kind: CompletionItemKind.Text, // The icons are disabled here anyway, - command: c.executeImmediately ? { id: SubmitAction.ID, title: withSlash, arguments: [{ widget, inputValue: `${withSlash} ` }] } : undefined, + command: c.executeImmediately ? { id: widget.location === ChatAgentLocation.EditingSession ? ChatEditingSessionSubmitAction.ID : ChatSubmitAction.ID, title: withSlash, arguments: [{ widget, inputValue: `${withSlash} ` }] } : undefined, }; }) }; diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChat.contribution.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChat.contribution.ts index 35c4e7b1f81..2cc76db29aa 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChat.contribution.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChat.contribution.ts @@ -19,7 +19,7 @@ import { IInlineChatSavingService } from './inlineChatSavingService.js'; import { IInlineChatSessionService } from './inlineChatSessionService.js'; import { InlineChatEnabler, InlineChatSessionServiceImpl } from './inlineChatSessionServiceImpl.js'; import { AccessibleViewRegistry } from '../../../../platform/accessibility/browser/accessibleViewRegistry.js'; -import { CancelAction, SubmitAction } from '../../chat/browser/actions/chatExecuteActions.js'; +import { CancelAction, ChatSubmitAction } from '../../chat/browser/actions/chatExecuteActions.js'; import { localize } from '../../../../nls.js'; import { ChatContextKeys } from '../../chat/common/chatContextKeys.js'; import { ContextKeyExpr } from '../../../../platform/contextkey/common/contextkey.js'; @@ -43,7 +43,7 @@ const editActionMenuItem: IMenuItem = { group: '0_main', order: 0, command: { - id: SubmitAction.ID, + id: ChatSubmitAction.ID, title: localize('send.edit', "Edit Code"), }, when: ContextKeyExpr.and( @@ -57,7 +57,7 @@ const generateActionMenuItem: IMenuItem = { group: '0_main', order: 0, command: { - id: SubmitAction.ID, + id: ChatSubmitAction.ID, title: localize('send.generate', "Generate"), }, when: ContextKeyExpr.and(