Path: blob/main/src/vs/workbench/contrib/chat/browser/agentSessions/agentSessionsPicker.ts
5281 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { renderAsPlaintext } from '../../../../../base/browser/markdownRenderer.js';6import { Codicon } from '../../../../../base/common/codicons.js';7import { DisposableStore } from '../../../../../base/common/lifecycle.js';8import { ThemeIcon } from '../../../../../base/common/themables.js';9import { localize } from '../../../../../nls.js';10import { ICommandService } from '../../../../../platform/commands/common/commands.js';11import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';12import { IQuickInputButton, IQuickInputService, IQuickPickItem, IQuickPickSeparator } from '../../../../../platform/quickinput/common/quickInput.js';13import { openSession } from './agentSessionsOpener.js';14import { IAgentSession, isLocalAgentSessionItem } from './agentSessionsModel.js';15import { IAgentSessionsService } from './agentSessionsService.js';16import { AgentSessionsSorter, groupAgentSessionsByDate, sessionDateFromNow } from './agentSessionsViewer.js';17import { AGENT_SESSION_DELETE_ACTION_ID, AGENT_SESSION_RENAME_ACTION_ID, getAgentSessionTime } from './agentSessions.js';18import { AgentSessionsFilter } from './agentSessionsFilter.js';1920interface ISessionPickItem extends IQuickPickItem {21readonly session: IAgentSession;22}2324export const archiveButton: IQuickInputButton = {25iconClass: ThemeIcon.asClassName(Codicon.archive),26tooltip: localize('archiveSession', "Archive")27};2829export const unarchiveButton: IQuickInputButton = {30iconClass: ThemeIcon.asClassName(Codicon.inbox),31tooltip: localize('unarchiveSession', "Unarchive")32};3334export const renameButton: IQuickInputButton = {35iconClass: ThemeIcon.asClassName(Codicon.edit),36tooltip: localize('renameSession', "Rename")37};3839export const deleteButton: IQuickInputButton = {40iconClass: ThemeIcon.asClassName(Codicon.trash),41tooltip: localize('deleteSession', "Delete")42};4344export function getSessionDescription(session: IAgentSession): string {45const descriptionText = typeof session.description === 'string' ? session.description : session.description ? renderAsPlaintext(session.description) : undefined;46const timeAgo = sessionDateFromNow(getAgentSessionTime(session.timing));47const descriptionParts = [descriptionText, session.providerLabel, timeAgo].filter(part => !!part);4849return descriptionParts.join(' • ');50}5152export function getSessionButtons(session: IAgentSession): IQuickInputButton[] {53const buttons: IQuickInputButton[] = [];5455if (isLocalAgentSessionItem(session)) {56buttons.push(renameButton);57buttons.push(deleteButton);58}59buttons.push(session.isArchived() ? unarchiveButton : archiveButton);6061return buttons;62}6364export class AgentSessionsPicker {6566private readonly sorter = new AgentSessionsSorter();6768constructor(69private readonly anchor: HTMLElement | undefined,70@IAgentSessionsService private readonly agentSessionsService: IAgentSessionsService,71@IQuickInputService private readonly quickInputService: IQuickInputService,72@IInstantiationService private readonly instantiationService: IInstantiationService,73@ICommandService private readonly commandService: ICommandService,74) { }7576async pickAgentSession(): Promise<void> {77const disposables = new DisposableStore();78const picker = disposables.add(this.quickInputService.createQuickPick<ISessionPickItem>({ useSeparators: true }));79const filter = disposables.add(this.instantiationService.createInstance(AgentSessionsFilter, {}));8081picker.anchor = this.anchor;82picker.items = this.createPickerItems(filter);83picker.canAcceptInBackground = true;84picker.placeholder = localize('chatAgentPickerPlaceholder', "Search agent sessions by name");8586disposables.add(picker.onDidAccept(e => {87const pick = picker.selectedItems[0];88if (pick) {89this.instantiationService.invokeFunction(openSession, pick.session, {90sideBySide: e.inBackground,91editorOptions: {92preserveFocus: e.inBackground,93pinned: e.inBackground94}95});96}9798if (!e.inBackground) {99picker.hide();100}101}));102103disposables.add(picker.onDidTriggerItemButton(async e => {104const session = e.item.session;105106let reopenResolved: boolean = false;107if (e.button === renameButton) {108reopenResolved = true;109await this.commandService.executeCommand(AGENT_SESSION_RENAME_ACTION_ID, session);110} else if (e.button === deleteButton) {111reopenResolved = true;112await this.commandService.executeCommand(AGENT_SESSION_DELETE_ACTION_ID, session);113} else {114const newArchivedState = !session.isArchived();115session.setArchived(newArchivedState);116}117118if (reopenResolved) {119await this.agentSessionsService.model.resolve(session.providerType);120this.pickAgentSession();121} else {122picker.items = this.createPickerItems(filter);123}124}));125126disposables.add(picker.onDidHide(() => disposables.dispose()));127picker.show();128}129130private createPickerItems(filter: AgentSessionsFilter): (ISessionPickItem | IQuickPickSeparator)[] {131const sessions = this.agentSessionsService.model.sessions132.filter(session => !filter.exclude(session))133.sort(this.sorter.compare.bind(this.sorter));134const items: (ISessionPickItem | IQuickPickSeparator)[] = [];135136const groupedSessions = groupAgentSessionsByDate(sessions);137for (const group of groupedSessions.values()) {138if (group.sessions.length > 0) {139items.push({ type: 'separator', label: group.label });140items.push(...group.sessions.map(session => this.toPickItem(session)));141}142}143144return items;145}146147private toPickItem(session: IAgentSession): ISessionPickItem {148const description = getSessionDescription(session);149const buttons = getSessionButtons(session);150151return {152id: session.resource.toString(),153label: session.label,154tooltip: session.tooltip,155description,156iconClass: ThemeIcon.asClassName(session.icon),157buttons,158session159};160}161}162163164