Skip to content

Commit ffa6b68

Browse files
sandy081Copilot
andauthored
sessions: move session grouping from management service to providers (#307198)
* Move session grouping from management service to providers Sessions providers now own chat-to-session grouping and return ISession[] directly. The management service becomes a thin pass-through that tracks the active session and active chat. Key changes: - ISessionsProvider returns ISession[] from getSessions() with capabilities - CopilotChatSessionsProvider owns SessionsGroupModel and chat grouping - IChat slimmed to resource, title, status, and reactive properties - ISession gains mainChat; IActiveSession adds activeChat (management layer) - Unified sendAndCreateChat replaces separate sendRequest/sendAndCreateChat - Provider capabilities (multipleChatsPerSession) gate multi-chat UI - ISessionWorkspace.repositories renamed to folders - ISessionRepository renamed to ISessionFolder Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix compilation --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 24ff97e commit ffa6b68

26 files changed

Lines changed: 730 additions & 989 deletions

src/vs/sessions/browser/parts/sessionCompositeBar.ts

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,9 @@ export class SessionCompositeBar extends Disposable {
7373
}
7474

7575
const chats = activeSession.chats.read(reader);
76-
const activeChatId = activeSession.activeChat.map(c => c.chatId).read(reader);
77-
const mainChatId = activeSession.mainChat.chatId;
78-
this._rebuildTabs(chats, activeChatId, mainChatId);
76+
const activeChatUri = activeSession.activeChat.read(reader)?.resource.toString() ?? '';
77+
const mainChatUri = activeSession.mainChat.resource.toString();
78+
this._rebuildTabs(chats, activeChatUri, mainChatUri);
7979
}));
8080

8181

@@ -89,7 +89,7 @@ export class SessionCompositeBar extends Disposable {
8989
reset(this._tabsContainer);
9090

9191
for (const chat of chats) {
92-
this._createTab(chat, chat.chatId === mainChatId);
92+
this._createTab(chat, chat.resource.toString() === mainChatId);
9393
}
9494

9595
this._updateActiveTab(activeChatId);
@@ -130,11 +130,19 @@ export class SessionCompositeBar extends Disposable {
130130
prompt: localize('renameChat.prompt', "Rename Chat"),
131131
});
132132
if (newTitle) {
133-
await this._sessionsManagementService.renameChat(chat, newTitle);
133+
const session = this._sessionsManagementService.activeSession.get();
134+
if (session) {
135+
await this._sessionsManagementService.renameChat(session, chat.resource, newTitle);
136+
}
134137
}
135138
}));
136139

137-
const deleteAction = this._tabDisposables.add(new Action('sessionCompositeBar.deleteChat', localize('deleteChat', "Delete"), undefined, !isMainChat, () => this._sessionsManagementService.deleteChat(chat)));
140+
const deleteAction = this._tabDisposables.add(new Action('sessionCompositeBar.deleteChat', localize('deleteChat', "Delete"), undefined, !isMainChat, async () => {
141+
const session = this._sessionsManagementService.activeSession.get();
142+
if (session) {
143+
await this._sessionsManagementService.deleteChat(session, chat.resource);
144+
}
145+
}));
138146

139147
this._tabDisposables.add(addDisposableListener(tab, EventType.CONTEXT_MENU, (e: MouseEvent) => {
140148
e.preventDefault();
@@ -153,12 +161,15 @@ export class SessionCompositeBar extends Disposable {
153161
}
154162

155163
private _onTabClicked(chat: IChat): void {
156-
this._sessionsManagementService.openChat(chat.resource);
164+
const session = this._sessionsManagementService.activeSession.get();
165+
if (session) {
166+
this._sessionsManagementService.openChat(session, chat.resource);
167+
}
157168
}
158169

159170
private _updateActiveTab(activeChatId: string): void {
160171
for (const tab of this._tabs) {
161-
const isActive = tab.chat.chatId === activeChatId;
172+
const isActive = tab.chat.resource.toString() === activeChatId;
162173
tab.element.classList.toggle('active', isActive);
163174
tab.element.setAttribute('aria-selected', String(isActive));
164175
}

src/vs/sessions/contrib/chat/browser/extensionToolbarPickers.ts

Lines changed: 0 additions & 178 deletions
This file was deleted.

src/vs/sessions/contrib/chat/browser/newChatPermissionPicker.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ import { IConfigurationService } from '../../../../platform/configuration/common
1414
import { IDialogService } from '../../../../platform/dialogs/common/dialogs.js';
1515
import { ISessionsManagementService } from '../../sessions/browser/sessionsManagementService.js';
1616
import { ISessionsProvidersService } from '../../sessions/browser/sessionsProvidersService.js';
17-
import { CopilotCLISession } from '../../copilotChatSessions/browser/copilotChatSessionsProvider.js';
1817
import { renderIcon } from '../../../../base/browser/ui/iconLabel/iconLabels.js';
1918
import { ThemeIcon } from '../../../../base/common/themables.js';
2019
import { ChatConfiguration, ChatPermissionLevel } from '../../../../workbench/contrib/chat/common/constants.js';
2120
import Severity from '../../../../base/common/severity.js';
2221
import { MarkdownString } from '../../../../base/common/htmlContent.js';
2322
import { IOpenerService } from '../../../../platform/opener/common/opener.js';
2423
import { URI } from '../../../../base/common/uri.js';
24+
import { CopilotChatSessionsProvider } from '../../copilotChatSessions/browser/copilotChatSessionsProvider.js';
2525

2626
// Track whether warnings have been shown this VS Code session
2727
const shownWarnings = new Set<ChatPermissionLevel>();
@@ -68,11 +68,10 @@ export class NewChatPermissionPicker extends Disposable {
6868
// Write permission level to the active session data when it changes
6969
this._register(this.onDidChangeLevel(level => {
7070
const session = this.sessionsManagementService.activeSession.get();
71-
const providerSession = session ? this.sessionsProvidersService.getUntitledSession(session.providerId) : undefined;
72-
if (!(providerSession instanceof CopilotCLISession)) {
73-
throw new Error('NewChatPermissionPicker requires a CopilotCLISession');
71+
if (!session) {
72+
return;
7473
}
75-
providerSession.setPermissionLevel(level);
74+
this.sessionsProvidersService.getProvider<CopilotChatSessionsProvider>(session.providerId)?.getSession(session.sessionId)?.setPermissionLevel(level);
7675
}));
7776
}
7877

src/vs/sessions/contrib/chat/browser/newChatViewPane.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ class NewChatWidget extends Disposable implements IHistoryNavigationWidget {
514514
return;
515515
}
516516
const hasText = !!this._editor?.getModel()?.getValue().trim();
517-
const session = this.sessionsManagementService.activeSession.get()?.activeChat.get();
517+
const session = this.sessionsManagementService.activeSession.get();
518518
const hasActiveSession = !!session;
519519
const isLoading = session?.loading.get() ?? false;
520520
this._sendButton.enabled = !this._sending && hasText && hasActiveSession && !isLoading;
@@ -559,11 +559,11 @@ class NewChatWidget extends Disposable implements IHistoryNavigationWidget {
559559
this._updateInputLoadingState();
560560

561561
try {
562-
const chat = this.sessionsManagementService.activeSession.get()?.activeChat.get();
563-
if (!chat) {
562+
const session = this.sessionsManagementService.activeSession.get();
563+
if (!session) {
564564
return;
565565
}
566-
await this.sessionsManagementService.sendRequest(chat, { query, attachedContext });
566+
await this.sessionsManagementService.sendAndCreateChat(session, { query, attachedContext });
567567
this._contextAttachments.clear();
568568
this._editor.getModel()?.setValue('');
569569
} catch (e) {

src/vs/sessions/contrib/chat/browser/runScriptAction.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ export class RunScriptContribution extends Disposable implements IWorkbenchContr
261261
}
262262

263263
async run(): Promise<void> {
264-
await that._sessionManagementService.sendAndCreateChat({ query: '/generate-run-commands' }, session);
264+
await that._sessionManagementService.sendAndCreateChat(session, { query: '/generate-run-commands' });
265265
}
266266
}));
267267
}));
@@ -698,7 +698,7 @@ class RunScriptActionViewItem extends BaseActionViewItem {
698698
class: undefined,
699699
category: addCategory,
700700
run: async () => {
701-
await this._sessionsManagementService.sendAndCreateChat({ query: '/generate-run-commands' }, session);
701+
await this._sessionsManagementService.sendAndCreateChat(session, { query: '/generate-run-commands' });
702702
},
703703
});
704704

src/vs/sessions/contrib/chat/browser/sessionTypePicker.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ export class SessionTypePicker extends Disposable {
7777
return;
7878
}
7979

80-
const chat = this.sessionsManagementService.activeSession.get()?.activeChat.get();
81-
if (!chat) {
80+
const session = this.sessionsManagementService.activeSession.get();
81+
if (!session) {
8282
return;
8383
}
8484

@@ -93,7 +93,7 @@ export class SessionTypePicker extends Disposable {
9393
const delegate: IActionListDelegate<ISessionType> = {
9494
onSelect: (type) => {
9595
this.actionWidgetService.hide();
96-
this.sessionsManagementService.setSessionType(chat, type);
96+
this.sessionsManagementService.setSessionType(session, type);
9797
},
9898
onHide: () => { triggerElement.focus(); },
9999
};

src/vs/sessions/contrib/chat/test/browser/sessionWorkspacePicker.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,17 @@ function createMockProvider(id: string, opts?: {
5151
onDidChangeSessions: Event.None,
5252
getSessions: () => [],
5353
createNewSession: () => { throw new Error('Not implemented'); },
54-
createNewSessionFrom: () => { throw new Error('Not implemented'); },
5554
setSessionType: () => { throw new Error('Not implemented'); },
5655
getSessionTypes: () => [],
57-
renameSession: async () => { },
56+
renameChat: async () => { },
5857
setModel: () => { },
5958
archiveSession: async () => { },
6059
unarchiveSession: async () => { },
6160
deleteSession: async () => { },
61+
deleteChat: async () => { },
6262
setRead: () => { },
63-
getUntitledSession: () => undefined,
64-
sendRequest: async () => { throw new Error('Not implemented'); },
63+
sendAndCreateChat: async () => { throw new Error('Not implemented'); },
64+
capabilities: { multipleChatsPerSession: false },
6565
};
6666
}
6767

0 commit comments

Comments
 (0)