From 4e048a8bcf5d202a6805e763131fe7ac8b4f5acd Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 1 Apr 2024 14:28:03 -0500 Subject: [PATCH 1/2] Align submit/send actions in chat --- src/vs/workbench/contrib/chat/browser/actions/chatActions.ts | 2 +- .../contrib/chat/browser/actions/chatExecuteActions.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatActions.ts b/src/vs/workbench/contrib/chat/browser/actions/chatActions.ts index ec4b2ee2b21dc..264e2b6b4bfac 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatActions.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatActions.ts @@ -144,7 +144,7 @@ export class ChatSubmitEditorAction extends EditorAction2 { constructor() { super({ id: ChatSubmitEditorAction.ID, - title: localize2({ key: 'actions.chat.submit', comment: ['Apply input from the chat input box'] }, "Submit"), + title: localize2({ key: 'actions.chat.submit', comment: ['Apply input from the chat input box'] }, "Send"), precondition: CONTEXT_CHAT_INPUT_HAS_TEXT, keybinding: { when: CONTEXT_IN_CHAT_INPUT, diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts b/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts index 4888f64fa5a27..aebb3a88f1888 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts @@ -31,7 +31,7 @@ export class SubmitAction extends Action2 { constructor() { super({ id: SubmitAction.ID, - title: localize2('interactive.submit.label', "Submit"), + title: localize2('interactive.submit.label', "Send"), f1: false, category: CHAT_CATEGORY, icon: Codicon.send, From 16d322050af294313e97abfe4c41f7d52bc8f5ed Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Thu, 4 Apr 2024 14:37:45 -0700 Subject: [PATCH 2/2] Clean up chat submit actions --- .../chat/browser/actions/chatActions.ts | 83 +------------------ .../browser/actions/chatExecuteActions.ts | 68 +++++++++++++-- .../contrib/chat/browser/chatInputPart.ts | 5 +- 3 files changed, 67 insertions(+), 89 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatActions.ts b/src/vs/workbench/contrib/chat/browser/actions/chatActions.ts index 264e2b6b4bfac..3c5fb0a252f83 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatActions.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatActions.ts @@ -25,10 +25,9 @@ import { IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat'; import { IChatEditorOptions } from 'vs/workbench/contrib/chat/browser/chatEditor'; import { ChatEditorInput } from 'vs/workbench/contrib/chat/browser/chatEditorInput'; import { ChatViewPane } from 'vs/workbench/contrib/chat/browser/chatViewPane'; -import { ChatAgentLocation, IChatAgentService } from 'vs/workbench/contrib/chat/common/chatAgents'; -import { CONTEXT_CHAT_INPUT_CURSOR_AT_TOP, CONTEXT_CHAT_INPUT_HAS_AGENT, CONTEXT_CHAT_INPUT_HAS_TEXT, CONTEXT_CHAT_LOCATION, CONTEXT_CHAT_REQUEST_IN_PROGRESS, CONTEXT_IN_CHAT_INPUT, CONTEXT_IN_CHAT_SESSION, CONTEXT_PROVIDER_EXISTS, CONTEXT_REQUEST, CONTEXT_RESPONSE } from 'vs/workbench/contrib/chat/common/chatContextKeys'; +import { ChatAgentLocation } from 'vs/workbench/contrib/chat/common/chatAgents'; +import { CONTEXT_CHAT_INPUT_CURSOR_AT_TOP, CONTEXT_CHAT_LOCATION, CONTEXT_IN_CHAT_INPUT, CONTEXT_IN_CHAT_SESSION, CONTEXT_PROVIDER_EXISTS, CONTEXT_REQUEST, CONTEXT_RESPONSE } from 'vs/workbench/contrib/chat/common/chatContextKeys'; import { IChatContributionService } from 'vs/workbench/contrib/chat/common/chatContributionService'; -import { chatAgentLeader } from 'vs/workbench/contrib/chat/common/chatParserTypes'; import { IChatDetail, IChatService } from 'vs/workbench/contrib/chat/common/chatService'; import { IChatWidgetHistoryService } from 'vs/workbench/contrib/chat/common/chatWidgetHistoryService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -93,86 +92,8 @@ class OpenChatGlobalAction extends Action2 { } } -export class ChatSubmitSecondaryAgentEditorAction extends EditorAction2 { - static readonly ID = 'workbench.action.chat.submitSecondaryAgent'; - - constructor() { - super({ - id: ChatSubmitSecondaryAgentEditorAction.ID, - title: localize2({ key: 'actions.chat.submitSecondaryAgent', comment: ['Send input from the chat input box to the secondary agent'] }, "Submit to Secondary Agent"), - precondition: ContextKeyExpr.and(CONTEXT_CHAT_INPUT_HAS_TEXT, CONTEXT_CHAT_INPUT_HAS_AGENT.negate(), CONTEXT_CHAT_REQUEST_IN_PROGRESS.negate()), - keybinding: { - when: CONTEXT_IN_CHAT_INPUT, - primary: KeyMod.CtrlCmd | KeyCode.Enter, - weight: KeybindingWeight.EditorContrib - }, - menu: { - id: MenuId.ChatExecuteSecondary, - group: 'group_1', - when: CONTEXT_CHAT_INPUT_HAS_AGENT.negate(), - } - }); - } - - runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor): void | Promise { - const editorUri = editor.getModel()?.uri; - if (editorUri) { - const agentService = accessor.get(IChatAgentService); - const secondaryAgent = agentService.getSecondaryAgent(); - if (!secondaryAgent) { - return; - } - - const widgetService = accessor.get(IChatWidgetService); - const widget = widgetService.getWidgetByInputUri(editorUri); - if (!widget) { - return; - } - - if (widget.getInput().match(/^\s*@/)) { - widget.acceptInput(); - } else { - widget.acceptInputWithPrefix(`${chatAgentLeader}${secondaryAgent.name}`); - } - } - } -} - -export class ChatSubmitEditorAction extends EditorAction2 { - static readonly ID = 'workbench.action.chat.acceptInput'; - - constructor() { - super({ - id: ChatSubmitEditorAction.ID, - title: localize2({ key: 'actions.chat.submit', comment: ['Apply input from the chat input box'] }, "Send"), - precondition: CONTEXT_CHAT_INPUT_HAS_TEXT, - keybinding: { - when: CONTEXT_IN_CHAT_INPUT, - primary: KeyCode.Enter, - weight: KeybindingWeight.EditorContrib - }, - menu: { - id: MenuId.ChatExecuteSecondary, - when: CONTEXT_CHAT_REQUEST_IN_PROGRESS.negate(), - group: 'group_1', - }, - }); - } - - runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor): void | Promise { - const editorUri = editor.getModel()?.uri; - if (editorUri) { - const widgetService = accessor.get(IChatWidgetService); - widgetService.getWidgetByInputUri(editorUri)?.acceptInput(); - } - } -} - export function registerChatActions() { registerAction2(OpenChatGlobalAction); - registerAction2(ChatSubmitEditorAction); - - registerAction2(ChatSubmitSecondaryAgentEditorAction); registerAction2(class ClearChatInputHistoryAction extends Action2 { constructor() { diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts b/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts index aebb3a88f1888..65f81218005b6 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts @@ -12,7 +12,9 @@ import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { CHAT_CATEGORY } from 'vs/workbench/contrib/chat/browser/actions/chatActions'; import { IChatWidget, IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat'; -import { CONTEXT_CHAT_INPUT_HAS_TEXT, CONTEXT_CHAT_REQUEST_IN_PROGRESS, CONTEXT_IN_CHAT_INPUT } from 'vs/workbench/contrib/chat/common/chatContextKeys'; +import { IChatAgentService } from 'vs/workbench/contrib/chat/common/chatAgents'; +import { CONTEXT_CHAT_INPUT_HAS_AGENT, CONTEXT_CHAT_INPUT_HAS_TEXT, CONTEXT_CHAT_REQUEST_IN_PROGRESS, CONTEXT_IN_CHAT_INPUT } from 'vs/workbench/contrib/chat/common/chatContextKeys'; +import { chatAgentLeader, extractAgentAndCommand } from 'vs/workbench/contrib/chat/common/chatParserTypes'; import { IChatService } from 'vs/workbench/contrib/chat/common/chatService'; export interface IVoiceChatExecuteActionContext { @@ -36,11 +38,22 @@ export class SubmitAction extends Action2 { category: CHAT_CATEGORY, icon: Codicon.send, precondition: ContextKeyExpr.and(CONTEXT_CHAT_INPUT_HAS_TEXT, CONTEXT_CHAT_REQUEST_IN_PROGRESS.negate()), - menu: { - id: MenuId.ChatExecute, - when: CONTEXT_CHAT_REQUEST_IN_PROGRESS.negate(), - group: 'navigation', + keybinding: { + when: CONTEXT_IN_CHAT_INPUT, + primary: KeyCode.Enter, + weight: KeybindingWeight.EditorContrib }, + menu: [ + { + id: MenuId.ChatExecuteSecondary, + group: 'group_1', + }, + { + id: MenuId.ChatExecute, + when: CONTEXT_CHAT_REQUEST_IN_PROGRESS.negate(), + group: 'navigation', + }, + ] }); } @@ -53,6 +66,50 @@ export class SubmitAction extends Action2 { } } + +export class ChatSubmitSecondaryAgentAction extends Action2 { + static readonly ID = 'workbench.action.chat.submitSecondaryAgent'; + + constructor() { + super({ + id: ChatSubmitSecondaryAgentAction.ID, + title: localize2({ key: 'actions.chat.submitSecondaryAgent', comment: ['Send input from the chat input box to the secondary agent'] }, "Submit to Secondary Agent"), + precondition: ContextKeyExpr.and(CONTEXT_CHAT_INPUT_HAS_TEXT, CONTEXT_CHAT_INPUT_HAS_AGENT.negate(), CONTEXT_CHAT_REQUEST_IN_PROGRESS.negate()), + keybinding: { + when: CONTEXT_IN_CHAT_INPUT, + primary: KeyMod.CtrlCmd | KeyCode.Enter, + weight: KeybindingWeight.EditorContrib + }, + menu: { + id: MenuId.ChatExecuteSecondary, + group: 'group_1' + } + }); + } + + run(accessor: ServicesAccessor, ...args: any[]) { + const context: IChatExecuteActionContext | undefined = args[0]; + const agentService = accessor.get(IChatAgentService); + const secondaryAgent = agentService.getSecondaryAgent(); + if (!secondaryAgent) { + return; + } + + const widgetService = accessor.get(IChatWidgetService); + const widget = context?.widget ?? widgetService.lastFocusedWidget; + if (!widget) { + return; + } + + if (extractAgentAndCommand(widget.parsedInput).agentPart) { + widget.acceptInput(); + } else { + widget.lastSelectedAgent = secondaryAgent; + widget.acceptInputWithPrefix(`${chatAgentLeader}${secondaryAgent.name}`); + } + } +} + class SendToNewChatAction extends Action2 { constructor() { super({ @@ -121,4 +178,5 @@ export function registerChatExecuteActions() { registerAction2(SubmitAction); registerAction2(CancelAction); registerAction2(SendToNewChatAction); + registerAction2(ChatSubmitSecondaryAgentAction); } diff --git a/src/vs/workbench/contrib/chat/browser/chatInputPart.ts b/src/vs/workbench/contrib/chat/browser/chatInputPart.ts index f11c2850463f7..0e1e334115d99 100644 --- a/src/vs/workbench/contrib/chat/browser/chatInputPart.ts +++ b/src/vs/workbench/contrib/chat/browser/chatInputPart.ts @@ -42,8 +42,7 @@ import { asCssVariableWithDefault, checkboxBorder, inputBackground } from 'vs/pl import { IThemeService } from 'vs/platform/theme/common/themeService'; import { AccessibilityVerbositySettingId } from 'vs/workbench/contrib/accessibility/browser/accessibilityConfiguration'; import { AccessibilityCommandId } from 'vs/workbench/contrib/accessibility/common/accessibilityCommands'; -import { ChatSubmitSecondaryAgentEditorAction } from 'vs/workbench/contrib/chat/browser/actions/chatActions'; -import { CancelAction, IChatExecuteActionContext, SubmitAction } from 'vs/workbench/contrib/chat/browser/actions/chatExecuteActions'; +import { CancelAction, ChatSubmitSecondaryAgentAction, IChatExecuteActionContext, SubmitAction } from 'vs/workbench/contrib/chat/browser/actions/chatExecuteActions'; import { IChatWidget } from 'vs/workbench/contrib/chat/browser/chat'; import { ChatFollowups } from 'vs/workbench/contrib/chat/browser/chatFollowups'; import { ChatAgentLocation, IChatAgentService } from 'vs/workbench/contrib/chat/common/chatAgents'; @@ -529,7 +528,7 @@ class ChatSubmitDropdownActionItem extends DropdownWithPrimaryActionViewItem { const secondaryAgent = chatAgentService.getSecondaryAgent(); if (secondaryAgent) { secondary.forEach(a => { - if (a.id === ChatSubmitSecondaryAgentEditorAction.ID) { + if (a.id === ChatSubmitSecondaryAgentAction.ID) { a.label = localize('chat.submitToSecondaryAgent', "Send to @{0}", secondaryAgent.name); }