mirror of
https://github.com/microsoft/vscode.git
synced 2026-09-27 10:37:38 +01:00
add workbench.action.chat.newLocalChat command
This commit is contained in:
@@ -24,12 +24,12 @@ import { localChatSessionType } from '../../common/chatSessionsService.js';
|
||||
import { ChatAgentLocation, ChatModeKind } from '../../common/constants.js';
|
||||
import { getChatSessionType, LocalChatSessionUri } from '../../common/model/chatUri.js';
|
||||
import { ChatViewId, IChatWidgetService, isIChatViewViewContext } from '../chat.js';
|
||||
import { EditingSessionAction, getEditingSessionContext } from '../chatEditing/chatEditingActions.js';
|
||||
import { EditingSessionAction, EditingSessionActionContext, getEditingSessionContext } from '../chatEditing/chatEditingActions.js';
|
||||
import { ChatEditorInput } from '../widgetHosts/editor/chatEditorInput.js';
|
||||
import { ChatViewPane } from '../widgetHosts/viewPane/chatViewPane.js';
|
||||
import { ACTION_ID_NEW_CHAT, ACTION_ID_NEW_EDIT_SESSION, CHAT_CATEGORY, handleCurrentEditingSession } from './chatActions.js';
|
||||
import { clearChatEditor } from './chatClear.js';
|
||||
import { AgentSessionsViewerOrientation } from '../agentSessions/agentSessions.js';
|
||||
import { AgentSessionProviders, AgentSessionsViewerOrientation } from '../agentSessions/agentSessions.js';
|
||||
|
||||
export interface INewEditSessionActionContext {
|
||||
|
||||
@@ -51,6 +51,23 @@ export interface INewEditSessionActionContext {
|
||||
isPartialQuery?: boolean;
|
||||
}
|
||||
|
||||
function isNewEditSessionActionContext(arg: unknown): arg is INewEditSessionActionContext {
|
||||
if (arg && typeof arg === 'object') {
|
||||
const obj = arg as Record<string, unknown>;
|
||||
if (obj.inputValue !== undefined && typeof obj.inputValue !== 'string') {
|
||||
return false;
|
||||
}
|
||||
if (obj.agentMode !== undefined && typeof obj.agentMode !== 'boolean') {
|
||||
return false;
|
||||
}
|
||||
if (obj.isPartialQuery !== undefined && typeof obj.isPartialQuery !== 'boolean') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function registerNewChatActions() {
|
||||
|
||||
// Add "New Chat" submenu to Chat view menu
|
||||
@@ -119,64 +136,36 @@ export function registerNewChatActions() {
|
||||
}
|
||||
|
||||
async run(accessor: ServicesAccessor, ...args: unknown[]) {
|
||||
const accessibilityService = accessor.get(IAccessibilityService);
|
||||
const viewsService = accessor.get(IViewsService);
|
||||
|
||||
const executeCommandContext = args[0] as INewEditSessionActionContext | undefined;
|
||||
const executeCommandContext = isNewEditSessionActionContext(args[0]) ? args[0] : undefined;
|
||||
|
||||
// Context from toolbar or lastFocusedWidget
|
||||
const context = getEditingSessionContext(accessor, args);
|
||||
const { editingSession, chatWidget: widget } = context ?? {};
|
||||
if (!widget) {
|
||||
return;
|
||||
}
|
||||
await runNewChatAction(accessor, context, executeCommandContext);
|
||||
}
|
||||
}
|
||||
);
|
||||
CommandsRegistry.registerCommandAlias(ACTION_ID_NEW_EDIT_SESSION, ACTION_ID_NEW_CHAT);
|
||||
|
||||
const dialogService = accessor.get(IDialogService);
|
||||
registerAction2(class NewLocalChatAction extends Action2 {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'workbench.action.chat.newLocalChat',
|
||||
title: localize2('chat.newLocalChat.label', "New Local Chat"),
|
||||
category: CHAT_CATEGORY,
|
||||
icon: Codicon.plus,
|
||||
precondition: ContextKeyExpr.and(ChatContextKeys.enabled, ChatContextKeys.location.isEqualTo(ChatAgentLocation.Chat)),
|
||||
f1: false,
|
||||
});
|
||||
}
|
||||
|
||||
const model = widget.viewModel?.model;
|
||||
if (model && !(await handleCurrentEditingSession(model, undefined, dialogService))) {
|
||||
return;
|
||||
}
|
||||
async run(accessor: ServicesAccessor, ...args: unknown[]) {
|
||||
const executeCommandContext = isNewEditSessionActionContext(args[0]) ? args[0] : undefined;
|
||||
|
||||
await editingSession?.stop();
|
||||
|
||||
// Create a new session with the same type as the current session
|
||||
const currentResource = widget.viewModel?.model.sessionResource;
|
||||
const sessionType = currentResource ? getChatSessionType(currentResource) : localChatSessionType;
|
||||
if (isIChatViewViewContext(widget.viewContext) && sessionType !== localChatSessionType) {
|
||||
// For the sidebar, we need to explicitly load a session with the same type
|
||||
const newResource = getResourceForNewChatSession(sessionType);
|
||||
const view = await viewsService.openView(ChatViewId) as ChatViewPane;
|
||||
await view.loadSession(newResource);
|
||||
} else {
|
||||
// For the editor, widget.clear() already preserves the session type via clearChatEditor
|
||||
await widget.clear();
|
||||
}
|
||||
|
||||
widget.attachmentModel.clear(true);
|
||||
widget.input.relatedFiles?.clear();
|
||||
widget.focusInput();
|
||||
|
||||
accessibilityService.alert(localize('newChat', "New chat"));
|
||||
|
||||
if (!executeCommandContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof executeCommandContext.agentMode === 'boolean') {
|
||||
widget.input.setChatMode(executeCommandContext.agentMode ? ChatModeKind.Agent : ChatModeKind.Edit);
|
||||
}
|
||||
|
||||
if (executeCommandContext.inputValue) {
|
||||
if (executeCommandContext.isPartialQuery) {
|
||||
widget.setInput(executeCommandContext.inputValue);
|
||||
} else {
|
||||
widget.acceptInput(executeCommandContext.inputValue);
|
||||
}
|
||||
}
|
||||
// Context from toolbar or lastFocusedWidget
|
||||
const context = getEditingSessionContext(accessor, args);
|
||||
await runNewChatAction(accessor, context, executeCommandContext, AgentSessionProviders.Local);
|
||||
}
|
||||
});
|
||||
CommandsRegistry.registerCommandAlias(ACTION_ID_NEW_EDIT_SESSION, ACTION_ID_NEW_CHAT);
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.ChatViewSessionTitleNavigationToolbar, {
|
||||
command: {
|
||||
@@ -296,3 +285,62 @@ function getResourceForNewChatSession(sessionType: string): URI {
|
||||
|
||||
return LocalChatSessionUri.forSession(generateUuid());
|
||||
}
|
||||
|
||||
async function runNewChatAction(
|
||||
accessor: ServicesAccessor,
|
||||
context: EditingSessionActionContext | undefined,
|
||||
executeCommandContext?: INewEditSessionActionContext,
|
||||
sessionType?: AgentSessionProviders
|
||||
) {
|
||||
const accessibilityService = accessor.get(IAccessibilityService);
|
||||
const viewsService = accessor.get(IViewsService);
|
||||
|
||||
const { editingSession, chatWidget: widget } = context ?? {};
|
||||
if (!widget) {
|
||||
return;
|
||||
}
|
||||
|
||||
const dialogService = accessor.get(IDialogService);
|
||||
|
||||
const model = widget.viewModel?.model;
|
||||
if (model && !(await handleCurrentEditingSession(model, undefined, dialogService))) {
|
||||
return;
|
||||
}
|
||||
|
||||
await editingSession?.stop();
|
||||
|
||||
// Create a new session with the same type as the current session
|
||||
const currentResource = widget.viewModel?.model.sessionResource;
|
||||
const newSessionType = sessionType ?? (currentResource ? getChatSessionType(currentResource) : localChatSessionType);
|
||||
if (isIChatViewViewContext(widget.viewContext) && newSessionType !== localChatSessionType) {
|
||||
// For the sidebar, we need to explicitly load a session with the same type
|
||||
const newResource = getResourceForNewChatSession(newSessionType);
|
||||
const view = await viewsService.openView(ChatViewId) as ChatViewPane;
|
||||
await view.loadSession(newResource);
|
||||
} else {
|
||||
// For the editor, widget.clear() already preserves the session type via clearChatEditor
|
||||
await widget.clear();
|
||||
}
|
||||
|
||||
widget.attachmentModel.clear(true);
|
||||
widget.input.relatedFiles?.clear();
|
||||
widget.focusInput();
|
||||
|
||||
accessibilityService.alert(localize('newChat', "New chat"));
|
||||
|
||||
if (!executeCommandContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof executeCommandContext.agentMode === 'boolean') {
|
||||
widget.input.setChatMode(executeCommandContext.agentMode ? ChatModeKind.Agent : ChatModeKind.Edit);
|
||||
}
|
||||
|
||||
if (executeCommandContext.inputValue) {
|
||||
if (executeCommandContext.isPartialQuery) {
|
||||
widget.setInput(executeCommandContext.inputValue);
|
||||
} else {
|
||||
widget.acceptInput(executeCommandContext.inputValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,11 +58,13 @@ export abstract class EditingSessionAction extends Action2 {
|
||||
abstract runEditingSessionAction(accessor: ServicesAccessor, editingSession: IChatEditingSession, chatWidget: IChatWidget, ...args: unknown[]): any;
|
||||
}
|
||||
|
||||
export type EditingSessionActionContext = { editingSession?: IChatEditingSession; chatWidget: IChatWidget };
|
||||
|
||||
/**
|
||||
* Resolve view title toolbar context. If none, return context from the lastFocusedWidget.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function getEditingSessionContext(accessor: ServicesAccessor, args: any[]): { editingSession?: IChatEditingSession; chatWidget: IChatWidget } | undefined {
|
||||
export function getEditingSessionContext(accessor: ServicesAccessor, args: any[]): EditingSessionActionContext | undefined {
|
||||
const arg0 = args.at(0);
|
||||
const context = isChatViewTitleActionContext(arg0) ? arg0 : undefined;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user