Try to clean up inProgress handling for chat sessions

This api is very strange. Reducing where it's exposed because it really should not exist
This commit is contained in:
Matt Bierner
2026-03-20 15:02:15 -07:00
parent 8f46cf34c3
commit cafda08d8f
4 changed files with 38 additions and 54 deletions
@@ -47,7 +47,7 @@ import { ChatViewPane } from '../widgetHosts/viewPane/chatViewPane.js';
import { AgentSessionProviders, getAgentSessionProviderName } from '../agentSessions/agentSessions.js';
import { BugIndicatingError, isCancellationError } from '../../../../../base/common/errors.js';
import { IEditorGroupsService } from '../../../../services/editor/common/editorGroupsService.js';
import { getChatSessionType, isUntitledChatSession, LocalChatSessionUri } from '../../common/model/chatUri.js';
import { isUntitledChatSession, LocalChatSessionUri } from '../../common/model/chatUri.js';
import { assertNever } from '../../../../../base/common/assert.js';
import { ICommandService } from '../../../../../platform/commands/common/commands.js';
import { Target } from '../../common/promptSyntax/promptTypes.js';
@@ -295,7 +295,7 @@ export class ChatSessionsService extends Disposable implements IChatSessionsServ
private readonly _onDidChangeOptionGroups = this._register(new Emitter<string>());
public get onDidChangeOptionGroups() { return this._onDidChangeOptionGroups.event; }
private readonly inProgressMap: Map<string, number> = new Map();
private readonly inProgressMap = new Map</* chatSessionType */ string, number>();
private readonly _sessionTypeOptions = new Map<string, IChatSessionProviderOptionGroup[]>();
private readonly _sessionTypeNewSessionOptions = new Map</* sessionType */string, ChatSessionOptionsMap>();
@@ -351,23 +351,6 @@ export class ChatSessionsService extends Disposable implements IChatSessionsServ
}
}));
this._register(this.onDidChangeSessionItems((delta) => {
const changedChatSessionTypes = new Set<string>();
for (const session of delta.addedOrUpdated ?? []) {
changedChatSessionTypes.add(getChatSessionType(session.resource));
}
for (const resource of delta.removed ?? []) {
changedChatSessionTypes.add(getChatSessionType(resource));
}
for (const chatSessionType of changedChatSessionTypes) {
this.updateInProgressStatus(chatSessionType).catch(error => {
this._logService.warn(`Failed to update progress status for '${chatSessionType}':`, error);
});
}
}));
this._register(this._labelService.registerFormatter({
scheme: Schemas.copilotPr,
formatting: {
@@ -378,27 +361,17 @@ export class ChatSessionsService extends Disposable implements IChatSessionsServ
}));
}
public reportInProgress(chatSessionType: string, count: number): void {
let displayName: string | undefined;
if (chatSessionType === AgentSessionProviders.Local) {
displayName = localize('chat.session.inProgress.local', "Local Agent");
} else if (chatSessionType === AgentSessionProviders.Background) {
displayName = localize('chat.session.inProgress.background', "Background Agent");
} else if (chatSessionType === AgentSessionProviders.Cloud) {
displayName = localize('chat.session.inProgress.cloud', "Cloud Agent");
} else {
displayName = this._contributions.get(chatSessionType)?.contribution.displayName;
private reportInProgress(chatSessionType: string, count: number): void {
if (!this._itemControllers.has(chatSessionType)) {
this._logService.warn(`Attempted to report in-progress status for unknown chat session type '${chatSessionType}'`);
}
if (displayName) {
this.inProgressMap.set(displayName, count);
}
this.inProgressMap.set(chatSessionType, count);
this._onDidChangeInProgress.fire();
}
public getInProgress(): { displayName: string; count: number }[] {
return Array.from(this.inProgressMap.entries()).map(([displayName, count]) => ({ displayName, count }));
public getInProgress(): { chatSessionType: string; count: number }[] {
return Array.from(this.inProgressMap.entries()).map(([chatSessionType, count]) => ({ chatSessionType, count }));
}
private async updateInProgressStatus(chatSessionType: string): Promise<void> {
@@ -919,12 +892,9 @@ export class ChatSessionsService extends Disposable implements IChatSessionsServ
disposables.add(controller.onDidChangeChatSessionItems(e => {
this._onDidChangeSessionItems.fire(e);
this.updateInProgressStatus(chatSessionType);
}));
this.updateInProgressStatus(chatSessionType).catch(error => {
this._logService.warn(`Failed to update initial progress status for '${chatSessionType}':`, error);
});
return {
dispose: () => {
initialRefreshCts.cancel();
@@ -935,6 +905,9 @@ export class ChatSessionsService extends Disposable implements IChatSessionsServ
this._itemControllers.delete(chatSessionType);
this._onDidChangeItemsProviders.fire({ chatSessionType });
}
// Remove any in-progress tracking for this provider since it's no longer available
this.updateInProgressStatus(chatSessionType);
}
};
}
@@ -48,6 +48,7 @@ import { Color } from '../../../../../base/common/color.js';
import { IViewsService } from '../../../../services/views/common/viewsService.js';
import { ChatViewId } from '../chat.js';
import { isCompletionsEnabled } from '../../../../../editor/common/services/completionsEnablement.js';
import { AgentSessionProviders } from '../agentSessions/agentSessions.js';
const defaultChat = product.defaultChatAgent;
@@ -235,12 +236,15 @@ export class ChatStatusDashboard extends DomWidget {
}
}));
for (const { displayName, count } of inProgress) {
for (const { chatSessionType, count } of inProgress) {
if (count > 0) {
const text = localize('inProgressChatSession', "$(loading~spin) {0} in progress", displayName);
const chatSessionsElement = this.element.appendChild($('div.description'));
const parts = renderLabelWithIcons(text);
chatSessionsElement.append(...parts);
const displayName = this.getDisplayNameForChatSessionType(chatSessionType);
if (displayName) {
const text = localize('inProgressChatSession', "$(loading~spin) {0} in progress", displayName);
const chatSessionsElement = this.element.appendChild($('div.description'));
const parts = renderLabelWithIcons(text);
chatSessionsElement.append(...parts);
}
}
}
}
@@ -402,6 +406,18 @@ export class ChatStatusDashboard extends DomWidget {
}
}
private getDisplayNameForChatSessionType(chatSessionType: string): string | undefined {
if (chatSessionType === AgentSessionProviders.Local) {
return localize('chat.session.inProgress.local', "Local Agent");
} else if (chatSessionType === AgentSessionProviders.Background) {
return localize('chat.session.inProgress.background', "Background Agent");
} else if (chatSessionType === AgentSessionProviders.Cloud) {
return localize('chat.session.inProgress.cloud', "Cloud Agent");
} else {
return this.chatSessionsService.getChatSessionContribution(chatSessionType)?.displayName;
}
}
private canUseChat(): boolean {
if (!this.chatEntitlementService.sentiment.installed || this.chatEntitlementService.sentiment.disabled || this.chatEntitlementService.sentiment.untrusted) {
return false; // chat not installed or not enabled
@@ -315,8 +315,8 @@ export interface IChatSessionsService {
*/
refreshChatSessionItems(providerTypeFilter: readonly string[] | undefined, token: CancellationToken): Promise<void>;
reportInProgress(chatSessionType: string, count: number): void;
getInProgress(): { displayName: string; count: number }[];
/** @deprecated Use `getChatSessionItems` */
getInProgress(): { chatSessionType: string; count: number }[];
// #endregion
@@ -44,7 +44,7 @@ export class MockChatSessionsService implements IChatSessionsService {
private contributions: IChatSessionsExtensionPoint[] = [];
private optionGroups = new Map<string, IChatSessionProviderOptionGroup[]>();
private sessionOptions = new ResourceMap<ChatSessionOptionsMap>();
private inProgress = new Map<string, number>();
private inProgress = new Map</* chatSessionType*/ string, number>();
// For testing: allow triggering events
fireDidChangeItemsProviders(event: { chatSessionType: string }): void {
@@ -125,13 +125,8 @@ export class MockChatSessionsService implements IChatSessionsService {
}));
}
reportInProgress(chatSessionType: string, count: number): void {
this.inProgress.set(chatSessionType, count);
this._onDidChangeInProgress.fire();
}
getInProgress(): { displayName: string; count: number }[] {
return Array.from(this.inProgress.entries()).map(([displayName, count]) => ({ displayName, count }));
getInProgress(): { chatSessionType: string; count: number }[] {
return Array.from(this.inProgress.entries()).map(([chatSessionType, count]) => ({ chatSessionType, count }));
}
registerChatSessionContentProvider(chatSessionType: string, provider: IChatSessionContentProvider): IDisposable {