Merge pull request #202454 from microsoft/roblou/occasional-weasel

Some chat session improvements
This commit is contained in:
Rob Lourens 2024-01-14 14:17:19 -03:00 committed by GitHub
commit 04d168ab43
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 59 additions and 42 deletions

View file

@ -155,14 +155,11 @@ export function registerChatActions() {
registerAction2(ChatSubmitSecondaryAgentEditorAction);
registerAction2(class ClearChatHistoryAction extends Action2 {
registerAction2(class ClearChatInputHistoryAction extends Action2 {
constructor() {
super({
id: 'workbench.action.chatEditor.clearHistory',
title: {
value: localize('interactiveSession.clearHistory.label', "Clear Input History"),
original: 'Clear Input History'
},
id: 'workbench.action.chat.clearInputHistory',
title: localize2('interactiveSession.clearHistory.label', "Clear Input History"),
precondition: CONTEXT_PROVIDER_EXISTS,
category: CHAT_CATEGORY,
f1: true,
@ -174,6 +171,22 @@ export function registerChatActions() {
}
});
registerAction2(class ClearChatHistoryAction extends Action2 {
constructor() {
super({
id: 'workbench.action.chat.clearHistory',
title: localize2('chat.clear.label', "Clear All Workspace Chats"),
precondition: CONTEXT_PROVIDER_EXISTS,
category: CHAT_CATEGORY,
f1: true,
});
}
async run(accessor: ServicesAccessor, ...args: any[]) {
const chatService = accessor.get(IChatService);
chatService.clearAllHistoryEntries();
}
});
registerAction2(class FocusChatAction extends EditorAction2 {
constructor() {
super({
@ -257,10 +270,7 @@ export function getOpenChatEditorAction(id: string, label: string, when?: string
const getHistoryChatActionDescriptorForViewTitle = (viewId: string, providerId: string): Readonly<IAction2Options> & { viewId: string } => ({
viewId,
id: `workbench.action.chat.${providerId}.history`,
title: {
value: localize('interactiveSession.history.label', "Show History"),
original: 'Show History'
},
title: localize2('chat.history.label', "Show Chats"),
menu: {
id: MenuId.ViewTitle,
when: ContextKeyExpr.equals('view', viewId),
@ -295,7 +305,7 @@ export function getHistoryAction(viewId: string, providerId: string) {
}));
const selection = await quickInputService.pick(picks,
{
placeHolder: localize('interactiveSession.history.pick', "Switch to chat session"),
placeHolder: localize('interactiveSession.history.pick', "Switch to chat"),
onDidTriggerItemButton: context => {
chatService.removeHistoryEntry(context.item.chat.sessionId);
context.removeItem();

View file

@ -20,15 +20,15 @@ import { ChatEditorInput } from 'vs/workbench/contrib/chat/browser/chatEditorInp
import { ChatViewPane } from 'vs/workbench/contrib/chat/browser/chatViewPane';
import { CONTEXT_IN_CHAT_SESSION, CONTEXT_PROVIDER_EXISTS } from 'vs/workbench/contrib/chat/common/chatContextKeys';
export const ACTION_ID_CLEAR_CHAT = `workbench.action.chat.clear`;
export const ACTION_ID_NEW_CHAT = `workbench.action.chat.newChat`;
export function registerClearActions() {
export function registerNewChatActions() {
registerAction2(class ClearEditorAction extends Action2 {
registerAction2(class NewChatEditorAction extends Action2 {
constructor() {
super({
id: 'workbench.action.chatEditor.clear',
title: localize2('chat.newSession.label', "New Session"),
id: 'workbench.action.chatEditor.newChat',
title: localize2('chat.newChat.label', "New Chat"),
icon: Codicon.plus,
f1: false,
precondition: CONTEXT_PROVIDER_EXISTS,
@ -50,10 +50,10 @@ export function registerClearActions() {
registerAction2(class GlobalClearChatAction extends Action2 {
constructor() {
super({
id: ACTION_ID_CLEAR_CHAT,
title: localize2('chat.newSession.label', "New Session"),
id: ACTION_ID_NEW_CHAT,
title: localize2('chat.newChat.label', "New Chat"),
category: CHAT_CATEGORY,
icon: Codicon.clearAll,
icon: Codicon.plus,
precondition: CONTEXT_PROVIDER_EXISTS,
f1: true,
keybinding: {
@ -86,10 +86,10 @@ export function registerClearActions() {
});
}
const getClearChatActionDescriptorForViewTitle = (viewId: string, providerId: string): Readonly<IAction2Options> & { viewId: string } => ({
const getNewChatActionDescriptorForViewTitle = (viewId: string, providerId: string): Readonly<IAction2Options> & { viewId: string } => ({
viewId,
id: `workbench.action.chat.${providerId}.clear`,
title: localize2('chat.newSession.label', "New Session"),
id: `workbench.action.chat.${providerId}.newChat`,
title: localize2('chat.newChat.label', "New Chat"),
menu: {
id: MenuId.ViewTitle,
when: ContextKeyExpr.equals('view', viewId),
@ -102,10 +102,10 @@ const getClearChatActionDescriptorForViewTitle = (viewId: string, providerId: st
f1: false
});
export function getClearAction(viewId: string, providerId: string) {
return class ClearAction extends ViewAction<ChatViewPane> {
export function getNewChatAction(viewId: string, providerId: string) {
return class NewChatAction extends ViewAction<ChatViewPane> {
constructor() {
super(getClearChatActionDescriptorForViewTitle(viewId, providerId));
super(getNewChatActionDescriptorForViewTitle(viewId, providerId));
}
async runInView(accessor: ServicesAccessor, view: ChatViewPane) {

View file

@ -29,8 +29,8 @@ enum MoveToNewLocation {
const getMoveToChatActionDescriptorForViewTitle = (viewId: string, providerId: string, moveTo: MoveToNewLocation): Readonly<IAction2Options> & { viewId: string } => ({
id: `workbench.action.chat.${providerId}.openIn${moveTo}`,
title: {
value: moveTo === MoveToNewLocation.Editor ? localize('chat.openInEditor.label', "Open Session in Editor") : localize('chat.openInNewWindow.label', "Open Session in New Window"),
original: moveTo === MoveToNewLocation.Editor ? 'Open Session in Editor' : 'Open Session in New Window',
value: moveTo === MoveToNewLocation.Editor ? localize('chat.openInEditor.label', "Open Chat in Editor") : localize('chat.openInNewWindow.label', "Open Chat in New Window"),
original: moveTo === MoveToNewLocation.Editor ? 'Open Chat in Editor' : 'Open Chat in New Window',
},
category: CHAT_CATEGORY,
precondition: CONTEXT_PROVIDER_EXISTS,
@ -78,8 +78,8 @@ export function registerMoveActions() {
super({
id: `workbench.action.chat.openInEditor`,
title: {
value: localize('interactiveSession.openInEditor.label', "Open Session in Editor"),
original: 'Open Session in Editor'
value: localize('interactiveSession.openInEditor.label', "Open Chat in Editor"),
original: 'Open Chat in Editor'
},
category: CHAT_CATEGORY,
precondition: CONTEXT_PROVIDER_EXISTS,
@ -98,8 +98,8 @@ export function registerMoveActions() {
super({
id: `workbench.action.chat.openInNewWindow`,
title: {
value: localize('interactiveSession.openInNewWindow.label', "Open Session in New Window"),
original: 'Open Session In New Window'
value: localize('interactiveSession.openInNewWindow.label', "Open Chat in New Window"),
original: 'Open Chat In New Window'
},
category: CHAT_CATEGORY,
precondition: CONTEXT_PROVIDER_EXISTS,
@ -117,8 +117,8 @@ export function registerMoveActions() {
super({
id: `workbench.action.chat.openInSidebar`,
title: {
value: localize('interactiveSession.openInSidebar.label', "Open Session in Side Bar"),
original: 'Open Session in Side Bar'
value: localize('interactiveSession.openInSidebar.label', "Open Chat in Side Bar"),
original: 'Open Chat in Side Bar'
},
category: CHAT_CATEGORY,
precondition: CONTEXT_PROVIDER_EXISTS,

View file

@ -37,7 +37,7 @@ import { IEditorResolverService, RegisteredEditorPriority } from 'vs/workbench/s
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
import '../common/chatColors';
import { registerMoveActions } from 'vs/workbench/contrib/chat/browser/actions/chatMoveActions';
import { ACTION_ID_CLEAR_CHAT, registerClearActions } from 'vs/workbench/contrib/chat/browser/actions/chatClearActions';
import { ACTION_ID_NEW_CHAT, registerNewChatActions } from 'vs/workbench/contrib/chat/browser/actions/chatClearActions';
import { AccessibleViewType, IAccessibleViewService } from 'vs/workbench/contrib/accessibility/browser/accessibleView';
import { isResponseVM } from 'vs/workbench/contrib/chat/common/chatViewModel';
import { CONTEXT_IN_CHAT_SESSION } from 'vs/workbench/contrib/chat/common/chatContextKeys';
@ -227,12 +227,12 @@ class ChatSlashStaticSlashCommandsContribution extends Disposable {
) {
super();
this._store.add(slashCommandService.registerSlashCommand({
command: 'clear',
detail: nls.localize('clear', "Clear the session"),
sortText: 'z2_clear',
command: 'newChat',
detail: nls.localize('newChat', "Start a new chat"),
sortText: 'z2_newChat',
executeImmediately: true
}, async () => {
commandService.executeCommand(ACTION_ID_CLEAR_CHAT);
commandService.executeCommand(ACTION_ID_NEW_CHAT);
}));
this._store.add(slashCommandService.registerSlashCommand({
command: 'help',
@ -295,7 +295,7 @@ registerChatExecuteActions();
registerQuickChatActions();
registerChatExportActions();
registerMoveActions();
registerClearActions();
registerNewChatActions();
registerSingleton(IChatService, ChatService, InstantiationType.Delayed);
registerSingleton(IChatContributionService, ChatContributionService, InstantiationType.Delayed);

View file

@ -14,7 +14,7 @@ import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneCont
import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { IViewContainersRegistry, IViewDescriptor, IViewsRegistry, ViewContainer, ViewContainerLocation, Extensions as ViewExtensions } from 'vs/workbench/common/views';
import { getHistoryAction, getOpenChatEditorAction } from 'vs/workbench/contrib/chat/browser/actions/chatActions';
import { getClearAction } from 'vs/workbench/contrib/chat/browser/actions/chatClearActions';
import { getNewChatAction } from 'vs/workbench/contrib/chat/browser/actions/chatClearActions';
import { getMoveToEditorAction, getMoveToNewWindowAction } from 'vs/workbench/contrib/chat/browser/actions/chatMoveActions';
import { getQuickChatActionForProvider } from 'vs/workbench/contrib/chat/browser/actions/chatQuickInputActions';
import { CHAT_SIDEBAR_PANEL_ID, ChatViewPane, IChatViewOptions } from 'vs/workbench/contrib/chat/browser/chatViewPane';
@ -135,7 +135,7 @@ export class ChatExtensionPointHandler implements IWorkbenchContribution {
// Actions in view title
const disposables = new DisposableStore();
disposables.add(registerAction2(getHistoryAction(viewId, providerDescriptor.id)));
disposables.add(registerAction2(getClearAction(viewId, providerDescriptor.id)));
disposables.add(registerAction2(getNewChatAction(viewId, providerDescriptor.id)));
disposables.add(registerAction2(getMoveToEditorAction(viewId, providerDescriptor.id)));
disposables.add(registerAction2(getMoveToNewWindowAction(viewId, providerDescriptor.id)));

View file

@ -314,6 +314,7 @@ export interface IChatService {
addCompleteRequest(sessionId: string, message: IParsedChatRequest | string, response: IChatCompleteResponse): void;
sendRequestToProvider(sessionId: string, message: IChatDynamicRequest): void;
getHistory(): IChatDetail[];
clearAllHistoryEntries(): void;
removeHistoryEntry(sessionId: string): void;
onDidPerformUserAction: Event<IChatUserActionEvent>;

View file

@ -135,7 +135,7 @@ export class ChatService extends Disposable implements IChatService {
private readonly _sessionModels = this._register(new DisposableMap<string, ChatModel>());
private readonly _pendingRequests = this._register(new DisposableMap<string, CancellationTokenSource>());
private readonly _persistedSessions: ISerializableChatsData;
private _persistedSessions: ISerializableChatsData;
private readonly _hasProvider: IContextKey<boolean>;
private _transferredSessionData: IChatTransferredSessionData | undefined;
@ -331,6 +331,12 @@ export class ChatService extends Disposable implements IChatService {
removeHistoryEntry(sessionId: string): void {
delete this._persistedSessions[sessionId];
this.saveState();
}
clearAllHistoryEntries(): void {
this._persistedSessions = {};
this.saveState();
}
startSession(providerId: string, token: CancellationToken): ChatModel {