Add secondary chat execute button (#208495)

* Set up secondary chat execute button

* Add "send to new chat"

* Fix build
This commit is contained in:
Rob Lourens 2024-03-25 00:25:16 -03:00 committed by GitHub
parent 3c1fdd40ea
commit b0d975fc63
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 167 additions and 86 deletions

View file

@ -134,7 +134,9 @@ export class DropdownWithPrimaryActionViewItem extends BaseActionViewItem {
this._dropdown = new DropdownMenuActionViewItem(dropdownAction, dropdownMenuActions, this._contextMenuProvider, {
menuAsChild: true,
classNames: ['codicon', dropdownIcon || 'codicon-chevron-down'],
hoverDelegate: this._options?.hoverDelegate
actionRunner: this._options?.actionRunner,
hoverDelegate: this._options?.hoverDelegate,
keybindingProvider: this._options?.getKeyBinding
});
if (this._dropdownContainer) {
this._dropdown.render(this._dropdownContainer);

View file

@ -218,6 +218,7 @@ export class MenuId {
static readonly ChatCodeBlock = new MenuId('ChatCodeblock');
static readonly ChatMessageTitle = new MenuId('ChatMessageTitle');
static readonly ChatExecute = new MenuId('ChatExecute');
static readonly ChatExecuteSecondary = new MenuId('ChatExecuteSecondary');
static readonly ChatInputSide = new MenuId('ChatInputSide');
static readonly AccessibleView = new MenuId('AccessibleView');
static readonly MultiDiffEditorFileToolbar = new MenuId('MultiDiffEditorFileToolbar');

View file

@ -10,16 +10,15 @@ import { ThemeIcon } from 'vs/base/common/themables';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { EditorAction2, ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { localize, localize2 } from 'vs/nls';
import { Action2, IAction2Options, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { IsLinuxContext, IsWindowsContext } from 'vs/platform/contextkey/common/contextkeys';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
import { Registry } from 'vs/platform/registry/common/platform';
import { ViewAction } from 'vs/workbench/browser/parts/views/viewPane';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { IViewsService } from 'vs/workbench/services/views/common/viewsService';
import { AccessibilityHelpAction } from 'vs/workbench/contrib/accessibility/browser/accessibleViewActions';
import { runAccessibilityHelpAction } from 'vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp';
import { IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat';
@ -27,14 +26,14 @@ 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 { IChatAgentService } from 'vs/workbench/contrib/chat/common/chatAgents';
import { CONTEXT_CHAT_INPUT_CURSOR_AT_TOP, CONTEXT_IN_CHAT_INPUT, CONTEXT_IN_CHAT_SESSION, CONTEXT_PROVIDER_EXISTS, CONTEXT_REQUEST, CONTEXT_RESPONSE } from 'vs/workbench/contrib/chat/common/chatContextKeys';
import { CONTEXT_CHAT_INPUT_CURSOR_AT_TOP, CONTEXT_CHAT_INPUT_HAS_AGENT, CONTEXT_CHAT_INPUT_HAS_TEXT, 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 { 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';
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
import { IsLinuxContext, IsWindowsContext } from 'vs/platform/contextkey/common/contextkeys';
import { IViewsService } from 'vs/workbench/services/views/common/viewsService';
export const CHAT_CATEGORY = localize2('chat.category', 'Chat');
export const CHAT_OPEN_ACTION_ID = 'workbench.action.chat.open';
@ -101,11 +100,16 @@ export class ChatSubmitSecondaryAgentEditorAction extends EditorAction2 {
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: CONTEXT_IN_CHAT_INPUT,
precondition: ContextKeyExpr.and(CONTEXT_CHAT_INPUT_HAS_TEXT, CONTEXT_CHAT_INPUT_HAS_AGENT.negate(), CONTEXT_CHAT_REQUEST_IN_PROGRESS.negate()),
keybinding: {
when: EditorContextKeys.textInputFocus,
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(),
}
});
}
@ -141,12 +145,17 @@ export class ChatSubmitEditorAction extends EditorAction2 {
super({
id: ChatSubmitEditorAction.ID,
title: localize2({ key: 'actions.chat.submit', comment: ['Apply input from the chat input box'] }, "Submit"),
precondition: CONTEXT_IN_CHAT_INPUT,
precondition: CONTEXT_CHAT_INPUT_HAS_TEXT,
keybinding: {
when: EditorContextKeys.textInputFocus,
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',
},
});
}

View file

@ -4,12 +4,15 @@
*--------------------------------------------------------------------------------------------*/
import { Codicon } from 'vs/base/common/codicons';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { localize2 } from 'vs/nls';
import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
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 } from 'vs/workbench/contrib/chat/common/chatContextKeys';
import { CONTEXT_CHAT_INPUT_HAS_TEXT, CONTEXT_CHAT_REQUEST_IN_PROGRESS, CONTEXT_IN_CHAT_INPUT } from 'vs/workbench/contrib/chat/common/chatContextKeys';
import { IChatService } from 'vs/workbench/contrib/chat/common/chatService';
export interface IVoiceChatExecuteActionContext {
@ -32,7 +35,7 @@ export class SubmitAction extends Action2 {
f1: false,
category: CHAT_CATEGORY,
icon: Codicon.send,
precondition: CONTEXT_CHAT_INPUT_HAS_TEXT,
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(),
@ -50,34 +53,72 @@ export class SubmitAction extends Action2 {
}
}
class SendToNewChatAction extends Action2 {
constructor() {
super({
id: 'workbench.action.chat.sendToNewChat',
title: localize2('chat.newChat.label', "Send to New Chat"),
precondition: ContextKeyExpr.and(CONTEXT_CHAT_REQUEST_IN_PROGRESS.negate(), CONTEXT_CHAT_INPUT_HAS_TEXT),
category: CHAT_CATEGORY,
f1: false,
menu: {
id: MenuId.ChatExecuteSecondary,
group: 'group_2'
},
keybinding: {
weight: KeybindingWeight.WorkbenchContrib,
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Enter,
when: CONTEXT_IN_CHAT_INPUT,
}
});
}
async run(accessor: ServicesAccessor, ...args: any[]) {
const context: IChatExecuteActionContext | undefined = args[0];
const widgetService = accessor.get(IChatWidgetService);
const widget = context?.widget ?? widgetService.lastFocusedWidget;
if (!widget) {
return;
}
widget.clear();
widget.acceptInput(context?.inputValue);
}
}
export class CancelAction extends Action2 {
static readonly ID = 'workbench.action.chat.cancel';
constructor() {
super({
id: CancelAction.ID,
title: localize2('interactive.cancel.label', "Cancel"),
f1: false,
category: CHAT_CATEGORY,
icon: Codicon.debugStop,
menu: {
id: MenuId.ChatExecute,
when: CONTEXT_CHAT_REQUEST_IN_PROGRESS,
group: 'navigation',
}
});
}
run(accessor: ServicesAccessor, ...args: any[]) {
const context: IChatExecuteActionContext = args[0];
if (!context.widget) {
return;
}
const chatService = accessor.get(IChatService);
if (context.widget.viewModel) {
chatService.cancelCurrentRequestForSession(context.widget.viewModel.sessionId);
}
}
}
export function registerChatExecuteActions() {
registerAction2(SubmitAction);
registerAction2(class CancelAction extends Action2 {
constructor() {
super({
id: 'workbench.action.chat.cancel',
title: localize2('interactive.cancel.label', "Cancel"),
f1: false,
category: CHAT_CATEGORY,
icon: Codicon.debugStop,
menu: {
id: MenuId.ChatExecute,
when: CONTEXT_CHAT_REQUEST_IN_PROGRESS,
group: 'navigation',
}
});
}
run(accessor: ServicesAccessor, ...args: any[]) {
const context: IChatExecuteActionContext = args[0];
if (!context.widget) {
return;
}
const chatService = accessor.get(IChatService);
if (context.widget.viewModel) {
chatService.cancelCurrentRequestForSession(context.widget.viewModel.sessionId);
}
}
});
registerAction2(CancelAction);
registerAction2(SendToNewChatAction);
}

View file

@ -4,16 +4,18 @@
*--------------------------------------------------------------------------------------------*/
import * as dom from 'vs/base/browser/dom';
import { DEFAULT_FONT_FAMILY } from 'vs/base/browser/fonts';
import { IHistoryNavigationWidget } from 'vs/base/browser/history';
import { ActionViewItem, IActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionViewItems';
import * as aria from 'vs/base/browser/ui/aria/aria';
import { Checkbox } from 'vs/base/browser/ui/toggle/toggle';
import { IAction } from 'vs/base/common/actions';
import { Codicon } from 'vs/base/common/codicons';
import { Emitter } from 'vs/base/common/event';
import { HistoryNavigator } from 'vs/base/common/history';
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { isMacintosh } from 'vs/base/common/platform';
import { URI } from 'vs/base/common/uri';
import { IEditorConstructionOptions } from 'vs/editor/browser/config/editorConfiguration';
import { EditorExtensionsRegistry } from 'vs/editor/browser/editorExtensions';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditor/codeEditorWidget';
import { IDimension } from 'vs/editor/common/core/dimension';
@ -23,31 +25,33 @@ import { IModelService } from 'vs/editor/common/services/model';
import { HoverController } from 'vs/editor/contrib/hover/browser/hover';
import { localize } from 'vs/nls';
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
import { DropdownWithPrimaryActionViewItem } from 'vs/platform/actions/browser/dropdownWithPrimaryActionViewItem';
import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { HiddenItemStrategy, MenuWorkbenchToolBar } from 'vs/platform/actions/browser/toolbar';
import { MenuId } from 'vs/platform/actions/common/actions';
import { IMenuService, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { registerAndCreateHistoryNavigationContext } from 'vs/platform/history/browser/contextScopedHistoryWidget';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { defaultCheckboxStyles } from 'vs/platform/theme/browser/defaultStyles';
import { asCssVariableWithDefault, checkboxBorder, inputBackground } from 'vs/platform/theme/common/colorRegistry';
import { DEFAULT_FONT_FAMILY } from 'vs/base/browser/fonts';
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 { ChatSubmitEditorAction, ChatSubmitSecondaryAgentEditorAction } from 'vs/workbench/contrib/chat/browser/actions/chatActions';
import { IChatExecuteActionContext, SubmitAction } from 'vs/workbench/contrib/chat/browser/actions/chatExecuteActions';
import { ChatSubmitSecondaryAgentEditorAction } from 'vs/workbench/contrib/chat/browser/actions/chatActions';
import { CancelAction, 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';
import { CONTEXT_CHAT_INPUT_CURSOR_AT_TOP, CONTEXT_CHAT_INPUT_HAS_FOCUS, CONTEXT_CHAT_INPUT_HAS_TEXT, CONTEXT_IN_CHAT_INPUT } from 'vs/workbench/contrib/chat/common/chatContextKeys';
import { chatAgentLeader } from 'vs/workbench/contrib/chat/common/chatParserTypes';
import { IChatFollowup } from 'vs/workbench/contrib/chat/common/chatService';
import { IChatResponseViewModel } from 'vs/workbench/contrib/chat/common/chatViewModel';
import { IChatHistoryEntry, IChatWidgetHistoryService } from 'vs/workbench/contrib/chat/common/chatWidgetHistoryService';
import { getSimpleCodeEditorWidgetOptions, getSimpleEditorOptions } from 'vs/workbench/contrib/codeEditor/browser/simpleEditorOptions';
import { IEditorConstructionOptions } from 'vs/editor/browser/config/editorConfiguration';
const $ = dom.$;
@ -139,7 +143,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IKeybindingService private readonly keybindingService: IKeybindingService,
@IAccessibilityService private readonly accessibilityService: IAccessibilityService
@IAccessibilityService private readonly accessibilityService: IAccessibilityService,
) {
super();
@ -368,8 +372,9 @@ 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 (action.id === SubmitAction.ID) {
return this.instantiationService.createInstance(SubmitButtonActionViewItem, { widget } satisfies IChatExecuteActionContext, action, options);
if ((action.id === SubmitAction.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);
return this.instantiationService.createInstance(ChatSubmitDropdownActionItem, action, dropdownAction);
}
return undefined;
@ -482,40 +487,57 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
}
}
class SubmitButtonActionViewItem extends ActionViewItem {
private readonly _tooltip: string;
constructor(
context: unknown,
action: IAction,
options: IActionViewItemOptions,
@IKeybindingService keybindingService: IKeybindingService,
@IChatAgentService chatAgentService: IChatAgentService,
) {
super(context, action, options);
const primaryKeybinding = keybindingService.lookupKeybinding(ChatSubmitEditorAction.ID)?.getLabel();
let tooltip = action.label;
if (primaryKeybinding) {
tooltip += ` (${primaryKeybinding})`;
}
const secondaryAgent = chatAgentService.getSecondaryAgent();
if (secondaryAgent) {
const secondaryKeybinding = keybindingService.lookupKeybinding(ChatSubmitSecondaryAgentEditorAction.ID)?.getLabel();
if (secondaryKeybinding) {
tooltip += `\n${chatAgentLeader}${secondaryAgent.name} (${secondaryKeybinding})`;
}
}
this._tooltip = tooltip;
}
protected override getTooltip(): string | undefined {
return this._tooltip;
}
}
function getLastPosition(model: ITextModel): IPosition {
return { lineNumber: model.getLineCount(), column: model.getLineLength(model.getLineCount()) + 1 };
}
// This does seems like a lot just to customize an item with dropdown. This whole class exists just because we need an
// onDidChange listener on the submenu, which is apparently not needed in other cases.
class ChatSubmitDropdownActionItem extends DropdownWithPrimaryActionViewItem {
constructor(
action: MenuItemAction,
dropdownAction: IAction,
@IMenuService menuService: IMenuService,
@IContextMenuService contextMenuService: IContextMenuService,
@IChatAgentService chatAgentService: IChatAgentService,
@IContextKeyService contextKeyService: IContextKeyService,
@IKeybindingService keybindingService: IKeybindingService,
@INotificationService notificationService: INotificationService,
@IThemeService themeService: IThemeService,
@IAccessibilityService accessibilityService: IAccessibilityService
) {
super(
action,
dropdownAction,
[],
'',
contextMenuService,
{
getKeyBinding: (action: IAction) => keybindingService.lookupKeybinding(action.id, contextKeyService)
},
keybindingService,
notificationService,
contextKeyService,
themeService,
accessibilityService);
const menu = menuService.createMenu(MenuId.ChatExecuteSecondary, contextKeyService);
const setActions = () => {
const secondary: IAction[] = [];
createAndFillInActionBarActions(menu, { shouldForwardArgs: true }, secondary);
const secondaryAgent = chatAgentService.getSecondaryAgent();
if (secondaryAgent) {
secondary.forEach(a => {
if (a.id === ChatSubmitSecondaryAgentEditorAction.ID) {
a.label = localize('chat.submitToSecondaryAgent', "Send to @{0}", secondaryAgent.name);
}
return a;
});
}
this.update(dropdownAction, secondary);
};
setActions();
this._register(menu.onDidChange(() => setActions()));
}
}

View file

@ -32,10 +32,10 @@ import { ChatListDelegate, ChatListItemRenderer, IChatListItemRendererOptions, I
import { ChatEditorOptions } from 'vs/workbench/contrib/chat/browser/chatOptions';
import { ChatViewPane } from 'vs/workbench/contrib/chat/browser/chatViewPane';
import { ChatAgentLocation, IChatAgentCommand, IChatAgentData, IChatAgentService } from 'vs/workbench/contrib/chat/common/chatAgents';
import { CONTEXT_CHAT_REQUEST_IN_PROGRESS, CONTEXT_IN_CHAT_SESSION, CONTEXT_RESPONSE_FILTERED } from 'vs/workbench/contrib/chat/common/chatContextKeys';
import { CONTEXT_CHAT_INPUT_HAS_AGENT, CONTEXT_CHAT_REQUEST_IN_PROGRESS, CONTEXT_IN_CHAT_SESSION, CONTEXT_RESPONSE_FILTERED } from 'vs/workbench/contrib/chat/common/chatContextKeys';
import { IChatContributionService } from 'vs/workbench/contrib/chat/common/chatContributionService';
import { ChatModelInitState, IChatModel } from 'vs/workbench/contrib/chat/common/chatModel';
import { IParsedChatRequest, chatAgentLeader, chatSubcommandLeader, extractAgentAndCommand } from 'vs/workbench/contrib/chat/common/chatParserTypes';
import { ChatRequestAgentPart, IParsedChatRequest, chatAgentLeader, chatSubcommandLeader, extractAgentAndCommand } from 'vs/workbench/contrib/chat/common/chatParserTypes';
import { ChatRequestParser } from 'vs/workbench/contrib/chat/common/chatRequestParser';
import { IChatFollowup, IChatService } from 'vs/workbench/contrib/chat/common/chatService';
import { IChatSlashCommandService } from 'vs/workbench/contrib/chat/common/chatSlashCommands';
@ -115,6 +115,8 @@ export class ChatWidget extends Disposable implements IChatWidget {
private bodyDimension: dom.Dimension | undefined;
private visibleChangeCount = 0;
private requestInProgress: IContextKey<boolean>;
private agentInInput: IContextKey<boolean>;
private _visible = false;
public get visible() {
return this._visible;
@ -147,6 +149,8 @@ export class ChatWidget extends Disposable implements IChatWidget {
get parsedInput() {
if (this.parsedChatRequest === undefined) {
this.parsedChatRequest = this.instantiationService.createInstance(ChatRequestParser).parseChatRequest(this.viewModel!.sessionId, this.getInput(), this.location, { selectedAgent: this._lastSelectedAgent });
this.agentInInput.set((!!this.parsedChatRequest.parts.find(part => part instanceof ChatRequestAgentPart)));
}
return this.parsedChatRequest;
@ -171,6 +175,7 @@ export class ChatWidget extends Disposable implements IChatWidget {
) {
super();
CONTEXT_IN_CHAT_SESSION.bindTo(contextKeyService).set(true);
this.agentInInput = CONTEXT_CHAT_INPUT_HAS_AGENT.bindTo(contextKeyService);
this.requestInProgress = CONTEXT_CHAT_REQUEST_IN_PROGRESS.bindTo(contextKeyService);
this._register((chatWidgetService as ChatWidgetService).register(this));

View file

@ -22,3 +22,4 @@ export const CONTEXT_IN_CHAT_SESSION = new RawContextKey<boolean>('inChat', fals
export const CONTEXT_PROVIDER_EXISTS = new RawContextKey<boolean>('hasChatProvider', false, { type: 'boolean', description: localize('hasChatProvider', "True when some chat provider has been registered.") });
export const CONTEXT_CHAT_INPUT_CURSOR_AT_TOP = new RawContextKey<boolean>('chatCursorAtTop', false);
export const CONTEXT_CHAT_INPUT_HAS_AGENT = new RawContextKey<boolean>('chatInputHasAgent', false);