Skip to content

Commit

Permalink
Clean up chat submit actions (#209578)
Browse files Browse the repository at this point in the history
* Align submit/send actions in chat

* Clean up chat submit actions
  • Loading branch information
roblourens authored Apr 4, 2024
1 parent 0da22a2 commit 8098a78
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 90 deletions.
83 changes: 2 additions & 81 deletions src/vs/workbench/contrib/chat/browser/actions/chatActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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<void> {
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'] }, "Submit"),
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<void> {
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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -31,16 +33,27 @@ 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,
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',
},
]
});
}

Expand All @@ -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({
Expand Down Expand Up @@ -121,4 +178,5 @@ export function registerChatExecuteActions() {
registerAction2(SubmitAction);
registerAction2(CancelAction);
registerAction2(SendToNewChatAction);
registerAction2(ChatSubmitSecondaryAgentAction);
}
5 changes: 2 additions & 3 deletions src/vs/workbench/contrib/chat/browser/chatInputPart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -540,7 +539,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);
}

Expand Down

0 comments on commit 8098a78

Please sign in to comment.