Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/chat/browser/agentSessions/agentSessionsPicker.ts
5281 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { renderAsPlaintext } from '../../../../../base/browser/markdownRenderer.js';
7
import { Codicon } from '../../../../../base/common/codicons.js';
8
import { DisposableStore } from '../../../../../base/common/lifecycle.js';
9
import { ThemeIcon } from '../../../../../base/common/themables.js';
10
import { localize } from '../../../../../nls.js';
11
import { ICommandService } from '../../../../../platform/commands/common/commands.js';
12
import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
13
import { IQuickInputButton, IQuickInputService, IQuickPickItem, IQuickPickSeparator } from '../../../../../platform/quickinput/common/quickInput.js';
14
import { openSession } from './agentSessionsOpener.js';
15
import { IAgentSession, isLocalAgentSessionItem } from './agentSessionsModel.js';
16
import { IAgentSessionsService } from './agentSessionsService.js';
17
import { AgentSessionsSorter, groupAgentSessionsByDate, sessionDateFromNow } from './agentSessionsViewer.js';
18
import { AGENT_SESSION_DELETE_ACTION_ID, AGENT_SESSION_RENAME_ACTION_ID, getAgentSessionTime } from './agentSessions.js';
19
import { AgentSessionsFilter } from './agentSessionsFilter.js';
20
21
interface ISessionPickItem extends IQuickPickItem {
22
readonly session: IAgentSession;
23
}
24
25
export const archiveButton: IQuickInputButton = {
26
iconClass: ThemeIcon.asClassName(Codicon.archive),
27
tooltip: localize('archiveSession', "Archive")
28
};
29
30
export const unarchiveButton: IQuickInputButton = {
31
iconClass: ThemeIcon.asClassName(Codicon.inbox),
32
tooltip: localize('unarchiveSession', "Unarchive")
33
};
34
35
export const renameButton: IQuickInputButton = {
36
iconClass: ThemeIcon.asClassName(Codicon.edit),
37
tooltip: localize('renameSession', "Rename")
38
};
39
40
export const deleteButton: IQuickInputButton = {
41
iconClass: ThemeIcon.asClassName(Codicon.trash),
42
tooltip: localize('deleteSession', "Delete")
43
};
44
45
export function getSessionDescription(session: IAgentSession): string {
46
const descriptionText = typeof session.description === 'string' ? session.description : session.description ? renderAsPlaintext(session.description) : undefined;
47
const timeAgo = sessionDateFromNow(getAgentSessionTime(session.timing));
48
const descriptionParts = [descriptionText, session.providerLabel, timeAgo].filter(part => !!part);
49
50
return descriptionParts.join(' • ');
51
}
52
53
export function getSessionButtons(session: IAgentSession): IQuickInputButton[] {
54
const buttons: IQuickInputButton[] = [];
55
56
if (isLocalAgentSessionItem(session)) {
57
buttons.push(renameButton);
58
buttons.push(deleteButton);
59
}
60
buttons.push(session.isArchived() ? unarchiveButton : archiveButton);
61
62
return buttons;
63
}
64
65
export class AgentSessionsPicker {
66
67
private readonly sorter = new AgentSessionsSorter();
68
69
constructor(
70
private readonly anchor: HTMLElement | undefined,
71
@IAgentSessionsService private readonly agentSessionsService: IAgentSessionsService,
72
@IQuickInputService private readonly quickInputService: IQuickInputService,
73
@IInstantiationService private readonly instantiationService: IInstantiationService,
74
@ICommandService private readonly commandService: ICommandService,
75
) { }
76
77
async pickAgentSession(): Promise<void> {
78
const disposables = new DisposableStore();
79
const picker = disposables.add(this.quickInputService.createQuickPick<ISessionPickItem>({ useSeparators: true }));
80
const filter = disposables.add(this.instantiationService.createInstance(AgentSessionsFilter, {}));
81
82
picker.anchor = this.anchor;
83
picker.items = this.createPickerItems(filter);
84
picker.canAcceptInBackground = true;
85
picker.placeholder = localize('chatAgentPickerPlaceholder', "Search agent sessions by name");
86
87
disposables.add(picker.onDidAccept(e => {
88
const pick = picker.selectedItems[0];
89
if (pick) {
90
this.instantiationService.invokeFunction(openSession, pick.session, {
91
sideBySide: e.inBackground,
92
editorOptions: {
93
preserveFocus: e.inBackground,
94
pinned: e.inBackground
95
}
96
});
97
}
98
99
if (!e.inBackground) {
100
picker.hide();
101
}
102
}));
103
104
disposables.add(picker.onDidTriggerItemButton(async e => {
105
const session = e.item.session;
106
107
let reopenResolved: boolean = false;
108
if (e.button === renameButton) {
109
reopenResolved = true;
110
await this.commandService.executeCommand(AGENT_SESSION_RENAME_ACTION_ID, session);
111
} else if (e.button === deleteButton) {
112
reopenResolved = true;
113
await this.commandService.executeCommand(AGENT_SESSION_DELETE_ACTION_ID, session);
114
} else {
115
const newArchivedState = !session.isArchived();
116
session.setArchived(newArchivedState);
117
}
118
119
if (reopenResolved) {
120
await this.agentSessionsService.model.resolve(session.providerType);
121
this.pickAgentSession();
122
} else {
123
picker.items = this.createPickerItems(filter);
124
}
125
}));
126
127
disposables.add(picker.onDidHide(() => disposables.dispose()));
128
picker.show();
129
}
130
131
private createPickerItems(filter: AgentSessionsFilter): (ISessionPickItem | IQuickPickSeparator)[] {
132
const sessions = this.agentSessionsService.model.sessions
133
.filter(session => !filter.exclude(session))
134
.sort(this.sorter.compare.bind(this.sorter));
135
const items: (ISessionPickItem | IQuickPickSeparator)[] = [];
136
137
const groupedSessions = groupAgentSessionsByDate(sessions);
138
for (const group of groupedSessions.values()) {
139
if (group.sessions.length > 0) {
140
items.push({ type: 'separator', label: group.label });
141
items.push(...group.sessions.map(session => this.toPickItem(session)));
142
}
143
}
144
145
return items;
146
}
147
148
private toPickItem(session: IAgentSession): ISessionPickItem {
149
const description = getSessionDescription(session);
150
const buttons = getSessionButtons(session);
151
152
return {
153
id: session.resource.toString(),
154
label: session.label,
155
tooltip: session.tooltip,
156
description,
157
iconClass: ThemeIcon.asClassName(session.icon),
158
buttons,
159
session
160
};
161
}
162
}
163
164