agent sessions - tweaks to sessions picker actions (rename, delete) (#284036)

This commit is contained in:
Benjamin Pasero
2025-12-17 12:53:18 +01:00
committed by GitHub
parent bd2c6f03bd
commit bade067e41
4 changed files with 108 additions and 15 deletions
@@ -13,7 +13,7 @@ import { IAgentSessionsService, AgentSessionsService } from './agentSessionsServ
import { LocalAgentsSessionsProvider } from './localAgentSessionsProvider.js';
import { registerWorkbenchContribution2, WorkbenchPhase } from '../../../../common/contributions.js';
import { ISubmenuItem, MenuId, MenuRegistry, registerAction2 } from '../../../../../platform/actions/common/actions.js';
import { ArchiveAgentSessionAction, ArchiveAgentSessionSectionAction, UnarchiveAgentSessionAction, OpenAgentSessionInEditorGroupAction, OpenAgentSessionInNewEditorGroupAction, OpenAgentSessionInNewWindowAction, ShowAgentSessionsSidebar, HideAgentSessionsSidebar, ToggleAgentSessionsSidebar, RefreshAgentSessionsViewerAction, FindAgentSessionInViewerAction, MarkAgentSessionUnreadAction, MarkAgentSessionReadAction, FocusAgentSessionsAction, SetAgentSessionsOrientationAutoAction, SetAgentSessionsOrientationStackedAction, SetAgentSessionsOrientationSideBySideAction, ToggleChatViewSessionsAction, PickAgentSessionAction, ArchiveAllAgentSessionsAction, RenameAgentSessionAction } from './agentSessionsActions.js';
import { ArchiveAgentSessionAction, ArchiveAgentSessionSectionAction, UnarchiveAgentSessionAction, OpenAgentSessionInEditorGroupAction, OpenAgentSessionInNewEditorGroupAction, OpenAgentSessionInNewWindowAction, ShowAgentSessionsSidebar, HideAgentSessionsSidebar, ToggleAgentSessionsSidebar, RefreshAgentSessionsViewerAction, FindAgentSessionInViewerAction, MarkAgentSessionUnreadAction, MarkAgentSessionReadAction, FocusAgentSessionsAction, SetAgentSessionsOrientationAutoAction, SetAgentSessionsOrientationStackedAction, SetAgentSessionsOrientationSideBySideAction, ToggleChatViewSessionsAction, PickAgentSessionAction, ArchiveAllAgentSessionsAction, RenameAgentSessionAction, DeleteAgentSessionAction, DeleteAllLocalSessionsAction } from './agentSessionsActions.js';
//#region Actions and Menus
@@ -24,6 +24,8 @@ registerAction2(ArchiveAgentSessionSectionAction);
registerAction2(ArchiveAgentSessionAction);
registerAction2(UnarchiveAgentSessionAction);
registerAction2(RenameAgentSessionAction);
registerAction2(DeleteAgentSessionAction);
registerAction2(DeleteAllLocalSessionsAction);
registerAction2(MarkAgentSessionUnreadAction);
registerAction2(MarkAgentSessionReadAction);
registerAction2(OpenAgentSessionInNewWindowAction);
@@ -71,3 +71,6 @@ export const agentSessionSelectedUnfocusedBadgeBorder = registerColor(
{ dark: transparent(foreground, 0.3), light: transparent(foreground, 0.3), hcDark: foreground, hcLight: foreground },
localize('agentSessionSelectedUnfocusedBadgeBorder', "Border color for the badges in selected agent session items when the view is unfocused.")
);
export const AGENT_SESSION_RENAME_ACTION_ID = 'agentSession.rename';
export const AGENT_SESSION_DELETE_ACTION_ID = 'agentSession.delete';
@@ -8,7 +8,7 @@ import { AgentSessionSection, IAgentSession, IAgentSessionSection, IMarshalledAg
import { Action2, MenuId, MenuRegistry } from '../../../../../platform/actions/common/actions.js';
import { Codicon } from '../../../../../base/common/codicons.js';
import { ServicesAccessor } from '../../../../../editor/browser/editorExtensions.js';
import { AgentSessionProviders, AgentSessionsViewerOrientation, IAgentSessionsControl } from './agentSessions.js';
import { AGENT_SESSION_DELETE_ACTION_ID, AGENT_SESSION_RENAME_ACTION_ID, AgentSessionProviders, AgentSessionsViewerOrientation, IAgentSessionsControl } from './agentSessions.js';
import { IChatService } from '../../common/chatService.js';
import { ChatContextKeys } from '../../common/chatContextKeys.js';
import { IChatEditorOptions } from '../chatEditor.js';
@@ -37,6 +37,7 @@ import { KeyCode, KeyMod } from '../../../../../base/common/keyCodes.js';
//#region Chat View
export class ToggleChatViewSessionsAction extends Action2 {
constructor() {
super({
id: 'workbench.action.chat.toggleChatViewSessions',
@@ -135,6 +136,7 @@ export class SetAgentSessionsOrientationSideBySideAction extends Action2 {
}
export class PickAgentSessionAction extends Action2 {
constructor() {
super({
id: `workbench.action.chat.history`,
@@ -182,8 +184,8 @@ export class ArchiveAllAgentSessionsAction extends Action2 {
constructor() {
super({
id: 'workbench.action.chat.clearHistory',
title: localize2('chat.clear.label', "Archive All Workspace Agent Sessions"),
id: 'workbench.action.chat.archiveAllAgentSessions',
title: localize2('archiveAll.label', "Archive All Workspace Agent Sessions"),
precondition: ChatContextKeys.enabled,
category: CHAT_CATEGORY,
f1: true,
@@ -263,7 +265,7 @@ export class ArchiveAgentSessionSectionAction extends Action2 {
abstract class BaseAgentSessionAction extends Action2 {
run(accessor: ServicesAccessor, context?: IAgentSession | IMarshalledAgentSessionContext): void {
async run(accessor: ServicesAccessor, context?: IAgentSession | IMarshalledAgentSessionContext): Promise<void> {
const agentSessionsService = accessor.get(IAgentSessionsService);
const viewsService = accessor.get(IViewsService);
@@ -280,7 +282,7 @@ abstract class BaseAgentSessionAction extends Action2 {
}
if (session) {
this.runWithSession(session, accessor);
await this.runWithSession(session, accessor);
}
}
@@ -421,9 +423,8 @@ export class RenameAgentSessionAction extends BaseAgentSessionAction {
constructor() {
super({
id: 'agentSession.rename',
id: AGENT_SESSION_RENAME_ACTION_ID,
title: localize2('rename', "Rename..."),
icon: Codicon.edit,
keybinding: {
primary: KeyCode.F2,
mac: {
@@ -455,6 +456,79 @@ export class RenameAgentSessionAction extends BaseAgentSessionAction {
}
}
export class DeleteAgentSessionAction extends BaseAgentSessionAction {
constructor() {
super({
id: AGENT_SESSION_DELETE_ACTION_ID,
title: localize2('delete', "Delete..."),
menu: {
id: MenuId.AgentSessionsContext,
group: 'edit',
order: 4,
when: ChatContextKeys.agentSessionType.isEqualTo(AgentSessionProviders.Local)
}
});
}
async runWithSession(session: IAgentSession, accessor: ServicesAccessor): Promise<void> {
const chatService = accessor.get(IChatService);
const dialogService = accessor.get(IDialogService);
const widgetService = accessor.get(IChatWidgetService);
const confirmed = await dialogService.confirm({
message: localize('deleteSession.confirm', "Are you sure you want to delete this chat session?"),
detail: localize('deleteSession.detail', "This action cannot be undone."),
primaryButton: localize('deleteSession.delete', "Delete")
});
if (!confirmed.confirmed) {
return;
}
// Clear chat widget
await widgetService.getWidgetBySessionResource(session.resource)?.clear();
// Remove from storage
await chatService.removeHistoryEntry(session.resource);
}
}
export class DeleteAllLocalSessionsAction extends Action2 {
constructor() {
super({
id: 'workbench.action.chat.clearHistory',
title: localize2('agentSessions.deleteAll', "Delete All Local Workspace Chat Sessions"),
precondition: ChatContextKeys.enabled,
category: CHAT_CATEGORY,
f1: true,
});
}
async run(accessor: ServicesAccessor, ...args: unknown[]) {
const chatService = accessor.get(IChatService);
const widgetService = accessor.get(IChatWidgetService);
const dialogService = accessor.get(IDialogService);
const confirmed = await dialogService.confirm({
message: localize('deleteAllChats.confirm', "Are you sure you want to delete all local workspace chat sessions?"),
detail: localize('deleteAllChats.detail', "This action cannot be undone."),
primaryButton: localize('deleteAllChats.button', "Delete All")
});
if (!confirmed.confirmed) {
return;
}
// Clear all chat widgets
await Promise.all(widgetService.getAllWidgets().map(widget => widget.clear()));
// Remove from storage
await chatService.clearAllHistoryEntries();
}
}
abstract class BaseOpenAgentSessionAction extends BaseAgentSessionAction {
async runWithSession(session: IAgentSession, accessor: ServicesAccessor): Promise<void> {
@@ -9,13 +9,14 @@ import { fromNow } from '../../../../../base/common/date.js';
import { DisposableStore } from '../../../../../base/common/lifecycle.js';
import { ThemeIcon } from '../../../../../base/common/themables.js';
import { localize } from '../../../../../nls.js';
import { ICommandService } from '../../../../../platform/commands/common/commands.js';
import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
import { IQuickInputButton, IQuickInputService, IQuickPickItem, IQuickPickSeparator } from '../../../../../platform/quickinput/common/quickInput.js';
import { IChatService } from '../../common/chatService.js';
import { openSession } from './agentSessionsOpener.js';
import { IAgentSession, isLocalAgentSessionItem } from './agentSessionsModel.js';
import { IAgentSessionsService } from './agentSessionsService.js';
import { AgentSessionsSorter, groupAgentSessions } from './agentSessionsViewer.js';
import { AGENT_SESSION_DELETE_ACTION_ID, AGENT_SESSION_RENAME_ACTION_ID } from './agentSessions.js';
interface ISessionPickItem extends IQuickPickItem {
readonly session: IAgentSession;
@@ -36,6 +37,11 @@ const renameButton: IQuickInputButton = {
tooltip: localize('renameSession', "Rename")
};
const deleteButton: IQuickInputButton = {
iconClass: ThemeIcon.asClassName(Codicon.trash),
tooltip: localize('deleteSession', "Delete")
};
export class AgentSessionsPicker {
private readonly sorter = new AgentSessionsSorter();
@@ -44,7 +50,7 @@ export class AgentSessionsPicker {
@IAgentSessionsService private readonly agentSessionsService: IAgentSessionsService,
@IQuickInputService private readonly quickInputService: IQuickInputService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IChatService private readonly chatService: IChatService,
@ICommandService private readonly commandService: ICommandService,
) { }
async pickAgentSession(): Promise<void> {
@@ -75,17 +81,24 @@ export class AgentSessionsPicker {
disposables.add(picker.onDidTriggerItemButton(async e => {
const session = e.item.session;
let reopenResolved: boolean = false;
if (e.button === renameButton) {
const title = await this.quickInputService.input({ prompt: localize('newChatTitle', "New agent session title"), value: session.label });
if (title) {
this.chatService.setChatSessionTitle(session.resource, title);
}
reopenResolved = true;
await this.commandService.executeCommand(AGENT_SESSION_RENAME_ACTION_ID, session);
} else if (e.button === deleteButton) {
reopenResolved = true;
await this.commandService.executeCommand(AGENT_SESSION_DELETE_ACTION_ID, session);
} else {
const newArchivedState = !session.isArchived();
session.setArchived(newArchivedState);
}
picker.items = this.createPickerItems();
if (reopenResolved) {
await this.agentSessionsService.model.resolve(session.providerType);
this.pickAgentSession();
} else {
picker.items = this.createPickerItems();
}
}));
disposables.add(picker.onDidHide(() => disposables.dispose()));
@@ -117,6 +130,7 @@ export class AgentSessionsPicker {
const buttons: IQuickInputButton[] = [];
if (isLocalAgentSessionItem(session)) {
buttons.push(renameButton);
buttons.push(deleteButton);
}
buttons.push(session.isArchived() ? unarchiveButton : archiveButton);