mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-08 07:44:33 +01:00
@@ -22,7 +22,7 @@ import { URI } from '../../base/common/uri.js';
|
||||
import { Disposable } from '../../base/common/lifecycle.js';
|
||||
import { IWorkbenchContribution, registerWorkbenchContribution2, WorkbenchPhase } from '../../workbench/common/contributions.js';
|
||||
import { IChatProgress } from '../../workbench/contrib/chat/common/chatService/chatService.js';
|
||||
import { IChatSessionsService, IChatSessionItem, IChatSessionFileChange, ChatSessionStatus, IChatSessionHistoryItem } from '../../workbench/contrib/chat/common/chatSessionsService.js';
|
||||
import { IChatSessionsService, IChatSessionItem, IChatSessionFileChange, ChatSessionStatus, IChatSessionHistoryItem, IChatSessionItemsDelta } from '../../workbench/contrib/chat/common/chatSessionsService.js';
|
||||
import { IGitService, IGitExtensionDelegate, IGitRepository } from '../../workbench/contrib/git/common/gitService.js';
|
||||
import { IFileService } from '../../platform/files/common/files.js';
|
||||
import { InMemoryFileSystemProvider } from '../../platform/files/common/inMemoryFilesystemProvider.js';
|
||||
@@ -228,7 +228,7 @@ class MockChatAgentContribution extends Disposable implements IWorkbenchContribu
|
||||
static readonly ID = 'sessions.test.mockChatAgent';
|
||||
|
||||
private readonly _sessionItems: IChatSessionItem[] = [];
|
||||
private readonly _itemsChangedEmitter = new Emitter<void>();
|
||||
private readonly _itemsChangedEmitter = new Emitter<IChatSessionItemsDelta>();
|
||||
private readonly _sessionHistory = new Map<string, IChatSessionHistoryItem[]>();
|
||||
|
||||
constructor(
|
||||
@@ -273,6 +273,7 @@ class MockChatAgentContribution extends Disposable implements IWorkbenchContribu
|
||||
|
||||
// Add or update session in list
|
||||
const existing = this._sessionItems.find(s => s.resource.toString() === key);
|
||||
let addedOrUpdated: IChatSessionItem | undefined = existing;
|
||||
if (existing) {
|
||||
existing.timing.lastRequestStarted = now;
|
||||
existing.timing.lastRequestEnded = now;
|
||||
@@ -280,15 +281,19 @@ class MockChatAgentContribution extends Disposable implements IWorkbenchContribu
|
||||
existing.changes = changes;
|
||||
}
|
||||
} else {
|
||||
this._sessionItems.push({
|
||||
addedOrUpdated = {
|
||||
resource,
|
||||
label: message.slice(0, 50) || 'Mock Session',
|
||||
status: ChatSessionStatus.Completed,
|
||||
timing: { created: now, lastRequestStarted: now, lastRequestEnded: now },
|
||||
...(changes ? { changes } : {}),
|
||||
});
|
||||
};
|
||||
this._sessionItems.push(addedOrUpdated);
|
||||
}
|
||||
|
||||
if (addedOrUpdated) {
|
||||
this._itemsChangedEmitter.fire({ addedOrUpdated: [addedOrUpdated] });
|
||||
}
|
||||
this._itemsChangedEmitter.fire();
|
||||
}
|
||||
|
||||
private registerMockAgents(): void {
|
||||
|
||||
@@ -15,6 +15,7 @@ import { isEqual } from '../../../base/common/resources.js';
|
||||
import { URI, UriComponents } from '../../../base/common/uri.js';
|
||||
import { localize } from '../../../nls.js';
|
||||
import { IDialogService } from '../../../platform/dialogs/common/dialogs.js';
|
||||
import { IInstantiationService } from '../../../platform/instantiation/common/instantiation.js';
|
||||
import { ILogService } from '../../../platform/log/common/log.js';
|
||||
import { hasValidDiff, IAgentSession } from '../../contrib/chat/browser/agentSessions/agentSessionsModel.js';
|
||||
import { IAgentSessionsService } from '../../contrib/chat/browser/agentSessions/agentSessionsService.js';
|
||||
@@ -24,7 +25,7 @@ import { ChatEditorInput } from '../../contrib/chat/browser/widgetHosts/editor/c
|
||||
import { IChatRequestVariableEntry } from '../../contrib/chat/common/attachments/chatVariableEntries.js';
|
||||
import { awaitStatsForSession } from '../../contrib/chat/common/chat.js';
|
||||
import { IChatContentInlineReference, IChatProgress, IChatService, ResponseModelState } from '../../contrib/chat/common/chatService/chatService.js';
|
||||
import { ChatSessionStatus, IChatNewSessionRequest, IChatSession, IChatSessionContentProvider, IChatSessionHistoryItem, IChatSessionItem, IChatSessionItemController, IChatSessionProviderOptionItem, IChatSessionsService } from '../../contrib/chat/common/chatSessionsService.js';
|
||||
import { ChatSessionStatus, IChatNewSessionRequest, IChatSession, IChatSessionContentProvider, IChatSessionHistoryItem, IChatSessionItem, IChatSessionItemController, IChatSessionItemsDelta, IChatSessionProviderOptionItem, IChatSessionsService } from '../../contrib/chat/common/chatSessionsService.js';
|
||||
import { ChatAgentLocation } from '../../contrib/chat/common/constants.js';
|
||||
import { IChatModel } from '../../contrib/chat/common/model/chatModel.js';
|
||||
import { isUntitledChatSession } from '../../contrib/chat/common/model/chatUri.js';
|
||||
@@ -329,16 +330,25 @@ class MainThreadChatSessionItemController extends Disposable implements IChatSes
|
||||
private readonly _proxy: ExtHostChatSessionsShape;
|
||||
private readonly _handle: number;
|
||||
|
||||
private readonly _onDidChangeChatSessionItems = this._register(new Emitter<void>());
|
||||
private readonly _onDidChangeChatSessionItems = this._register(new Emitter<IChatSessionItemsDelta>());
|
||||
public readonly onDidChangeChatSessionItems = this._onDidChangeChatSessionItems.event;
|
||||
|
||||
constructor(
|
||||
proxy: ExtHostChatSessionsShape,
|
||||
handle: number
|
||||
chatSessionType: string,
|
||||
handle: number,
|
||||
@IChatService chatService: IChatService,
|
||||
) {
|
||||
super();
|
||||
this._proxy = proxy;
|
||||
this._handle = handle;
|
||||
|
||||
this._register(chatService.registerChatModelChangeListeners(chatSessionType, (sessionResource) => {
|
||||
const item = this._items.get(sessionResource);
|
||||
if (item) {
|
||||
this._onDidChangeChatSessionItems.fire({ addedOrUpdated: [item] });
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private readonly _items = new ResourceMap<IChatSessionItem>();
|
||||
@@ -361,7 +371,9 @@ class MainThreadChatSessionItemController extends Disposable implements IChatSes
|
||||
changes: revive(dto.changes),
|
||||
};
|
||||
this._items.set(item.resource, item);
|
||||
this._onDidChangeChatSessionItems.fire();
|
||||
this._onDidChangeChatSessionItems.fire({
|
||||
addedOrUpdated: [item],
|
||||
});
|
||||
return item;
|
||||
}
|
||||
|
||||
@@ -373,17 +385,18 @@ class MainThreadChatSessionItemController extends Disposable implements IChatSes
|
||||
for (const uri of change.removed) {
|
||||
this._items.delete(uri);
|
||||
}
|
||||
this._onDidChangeChatSessionItems.fire();
|
||||
this._onDidChangeChatSessionItems.fire({
|
||||
addedOrUpdated: change.addedOrUpdated,
|
||||
removed: change.removed,
|
||||
});
|
||||
}
|
||||
|
||||
addOrUpdateItem(item: IChatSessionItem): void {
|
||||
warnOnUntitledSessionResource(item.resource);
|
||||
this._items.set(item.resource, item);
|
||||
this._onDidChangeChatSessionItems.fire();
|
||||
}
|
||||
|
||||
fireOnDidChangeChatSessionItems(): void {
|
||||
this._onDidChangeChatSessionItems.fire();
|
||||
this._onDidChangeChatSessionItems.fire({
|
||||
addedOrUpdated: [item],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -413,6 +426,7 @@ export class MainThreadChatSessions extends Disposable implements MainThreadChat
|
||||
@IEditorService private readonly _editorService: IEditorService,
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -446,7 +460,7 @@ export class MainThreadChatSessions extends Disposable implements MainThreadChat
|
||||
$registerChatSessionItemController(handle: number, chatSessionType: string): void {
|
||||
const disposables = new DisposableStore();
|
||||
|
||||
const controller = disposables.add(new MainThreadChatSessionItemController(this._proxy, handle));
|
||||
const controller = disposables.add(this._instantiationService.createInstance(MainThreadChatSessionItemController, this._proxy, chatSessionType, handle));
|
||||
disposables.add(this._chatSessionsService.registerChatSessionItemController(chatSessionType, controller));
|
||||
|
||||
this._itemControllerRegistrations.set(handle, {
|
||||
@@ -454,11 +468,6 @@ export class MainThreadChatSessions extends Disposable implements MainThreadChat
|
||||
controller,
|
||||
dispose: () => disposables.dispose(),
|
||||
});
|
||||
|
||||
disposables.add(this._chatService.registerChatModelChangeListeners(
|
||||
chatSessionType,
|
||||
() => controller.fireOnDidChangeChatSessionItems()
|
||||
));
|
||||
}
|
||||
|
||||
private getController(handle: number): MainThreadChatSessionItemController {
|
||||
@@ -469,11 +478,6 @@ export class MainThreadChatSessions extends Disposable implements MainThreadChat
|
||||
return registration.controller;
|
||||
}
|
||||
|
||||
$onDidChangeChatSessionItems(handle: number): void {
|
||||
const controller = this.getController(handle);
|
||||
controller.fireOnDidChangeChatSessionItems();
|
||||
}
|
||||
|
||||
private async _resolveSessionItem(item: Dto<IChatSessionItem>): Promise<IChatSessionItem> {
|
||||
const uri = URI.revive(item.resource);
|
||||
const model = this._chatService.getSession(uri);
|
||||
|
||||
@@ -3587,7 +3587,6 @@ export interface MainThreadChatSessionsShape extends IDisposable {
|
||||
$unregisterChatSessionItemController(controllerHandle: number): void;
|
||||
$updateChatSessionItems(controllerHandle: number, change: IChatSessionItemsChange): Promise<void>;
|
||||
$addOrUpdateChatSessionItem(controllerHandle: number, item: Dto<IChatSessionItem>): Promise<void>;
|
||||
$onDidChangeChatSessionItems(controllerHandle: number): void;
|
||||
$onDidCommitChatSessionItem(controllerHandle: number, original: UriComponents, modified: UriComponents): void;
|
||||
$registerChatSessionContentProvider(handle: number, chatSessionScheme: string): void;
|
||||
$unregisterChatSessionContentProvider(handle: number): void;
|
||||
|
||||
@@ -27,6 +27,7 @@ import { IChatEntitlementService } from '../../../../services/chat/common/chatEn
|
||||
import { ILifecycleService } from '../../../../services/lifecycle/common/lifecycle.js';
|
||||
import { Extensions, IOutputChannelRegistry, IOutputService } from '../../../../services/output/common/output.js';
|
||||
import { ChatSessionStatus as AgentSessionStatus, IChatSessionFileChange, IChatSessionFileChange2, IChatSessionItem, IChatSessionsService, ResolvedChatSessionsExtensionPoint } from '../../common/chatSessionsService.js';
|
||||
import { getChatSessionType } from '../../common/model/chatUri.js';
|
||||
import { IChatWidgetService } from '../chat.js';
|
||||
import { AgentSessionProviders, getAgentSessionProvider, getAgentSessionProviderIcon, getAgentSessionProviderName, isBuiltInAgentSessionProvider } from './agentSessions.js';
|
||||
|
||||
@@ -434,7 +435,19 @@ export class AgentSessionsModel extends Disposable implements IAgentSessionsMode
|
||||
// Sessions updates
|
||||
this._register(this.chatSessionsService.onDidChangeItemsProviders(({ chatSessionType }) => this.resolve(chatSessionType)));
|
||||
this._register(this.chatSessionsService.onDidChangeAvailability(() => this.resolve(undefined)));
|
||||
this._register(this.chatSessionsService.onDidChangeSessionItems(({ chatSessionType }) => this.updateItems([chatSessionType], CancellationToken.None)));
|
||||
this._register(this.chatSessionsService.onDidChangeSessionItems((delta) => {
|
||||
const changedChatSessionTypes = new Set<string>();
|
||||
|
||||
for (const resource of delta.addedOrUpdated ?? []) {
|
||||
changedChatSessionTypes.add(getChatSessionType(resource.resource));
|
||||
}
|
||||
|
||||
for (const resource of delta.removed ?? []) {
|
||||
changedChatSessionTypes.add(getChatSessionType(resource));
|
||||
}
|
||||
|
||||
this.updateItems(Array.from(changedChatSessionTypes), CancellationToken.None);
|
||||
}));
|
||||
this._register(this.workspaceContextService.onDidChangeWorkspaceFolders(() => this.resolve(undefined)));
|
||||
this._register(this.workspaceTrustManagementService.onDidChangeTrust(() => this.resolve(undefined)));
|
||||
|
||||
|
||||
+30
-16
@@ -10,12 +10,14 @@ import { Emitter } from '../../../../../base/common/event.js';
|
||||
import { Disposable } from '../../../../../base/common/lifecycle.js';
|
||||
import { ResourceSet } from '../../../../../base/common/map.js';
|
||||
import { Schemas } from '../../../../../base/common/network.js';
|
||||
import { IWorkbenchContribution } from '../../../../common/contributions.js';
|
||||
import { IChatModel } from '../../common/model/chatModel.js';
|
||||
import { convertLegacyChatSessionTiming, IChatDetail, IChatService, ResponseModelState } from '../../common/chatService/chatService.js';
|
||||
import { ChatSessionStatus, IChatSessionItem, IChatSessionItemController, IChatSessionsService, localChatSessionType } from '../../common/chatSessionsService.js';
|
||||
import { getChatSessionType } from '../../common/model/chatUri.js';
|
||||
import { isEqual } from '../../../../../base/common/resources.js';
|
||||
import { URI } from '../../../../../base/common/uri.js';
|
||||
import { ILogService } from '../../../../../platform/log/common/log.js';
|
||||
import { IWorkbenchContribution } from '../../../../common/contributions.js';
|
||||
import { convertLegacyChatSessionTiming, IChatDetail, IChatService, ResponseModelState } from '../../common/chatService/chatService.js';
|
||||
import { ChatSessionStatus, IChatSessionItem, IChatSessionItemController, IChatSessionItemsDelta, IChatSessionsService, localChatSessionType } from '../../common/chatSessionsService.js';
|
||||
import { IChatModel } from '../../common/model/chatModel.js';
|
||||
import { getChatSessionType } from '../../common/model/chatUri.js';
|
||||
|
||||
export class LocalAgentsSessionsController extends Disposable implements IChatSessionItemController, IWorkbenchContribution {
|
||||
|
||||
@@ -26,7 +28,7 @@ export class LocalAgentsSessionsController extends Disposable implements IChatSe
|
||||
private readonly _onDidChange = this._register(new Emitter<void>());
|
||||
readonly onDidChange = this._onDidChange.event;
|
||||
|
||||
readonly _onDidChangeChatSessionItems = this._register(new Emitter<void>());
|
||||
readonly _onDidChangeChatSessionItems = this._register(new Emitter<IChatSessionItemsDelta>());
|
||||
readonly onDidChangeChatSessionItems = this._onDidChangeChatSessionItems.event;
|
||||
|
||||
constructor(
|
||||
@@ -51,20 +53,32 @@ export class LocalAgentsSessionsController extends Disposable implements IChatSe
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
const refreshItems = async () => {
|
||||
this._onDidChangeChatSessionItems.fire();
|
||||
await this.refresh(CancellationToken.None);
|
||||
this._onDidChangeChatSessionItems.fire();
|
||||
};
|
||||
this._register(this.chatService.registerChatModelChangeListeners(Schemas.vscodeLocalChatSession, async sessionResource => {
|
||||
if (getChatSessionType(sessionResource) !== this.chatSessionType) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._register(this.chatService.registerChatModelChangeListeners(Schemas.vscodeLocalChatSession, refreshItems));
|
||||
let item = this.getItem(sessionResource);
|
||||
if (!item) {
|
||||
await this.refresh(CancellationToken.None);
|
||||
item = this.getItem(sessionResource);
|
||||
}
|
||||
|
||||
this._register(this.chatService.onDidDisposeSession(e => {
|
||||
const session = e.sessionResource.filter(resource => getChatSessionType(resource) === this.chatSessionType);
|
||||
if (session.length > 0) {
|
||||
refreshItems();
|
||||
if (item) {
|
||||
this._onDidChangeChatSessionItems.fire({ addedOrUpdated: [item] });
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(this.chatService.onDidDisposeSession(e => {
|
||||
const removedSessionResources = e.sessionResource.filter(resource => getChatSessionType(resource) === this.chatSessionType);
|
||||
if (removedSessionResources.length) {
|
||||
this._onDidChangeChatSessionItems.fire({ removed: removedSessionResources });
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private getItem(sessionResource: URI): IChatSessionItem | undefined {
|
||||
return this._items.find(item => isEqual(item.resource, sessionResource));
|
||||
}
|
||||
|
||||
private async provideChatSessionItems(token: CancellationToken): Promise<IChatSessionItem[]> {
|
||||
|
||||
@@ -9,7 +9,7 @@ import { CancellationToken, CancellationTokenSource } from '../../../../../base/
|
||||
import { Codicon } from '../../../../../base/common/codicons.js';
|
||||
import { AsyncEmitter, Emitter, Event } from '../../../../../base/common/event.js';
|
||||
import { combinedDisposable, Disposable, DisposableMap, DisposableStore, IDisposable } from '../../../../../base/common/lifecycle.js';
|
||||
import { ResourceMap } from '../../../../../base/common/map.js';
|
||||
import { ResourceMap, ResourceSet } from '../../../../../base/common/map.js';
|
||||
import { Schemas } from '../../../../../base/common/network.js';
|
||||
import * as resources from '../../../../../base/common/resources.js';
|
||||
import { ThemeIcon } from '../../../../../base/common/themables.js';
|
||||
@@ -31,7 +31,7 @@ import { ExtensionsRegistry } from '../../../../services/extensions/common/exten
|
||||
import { ChatEditorInput } from '../widgetHosts/editor/chatEditorInput.js';
|
||||
import { IChatAgentAttachmentCapabilities, IChatAgentData, IChatAgentService } from '../../common/participants/chatAgents.js';
|
||||
import { ChatContextKeys } from '../../common/actions/chatContextKeys.js';
|
||||
import { IChatNewSessionRequest, IChatSession, IChatSessionContentProvider, IChatSessionItem, IChatSessionItemController, IChatSessionOptionsWillNotifyExtensionEvent, IChatSessionProviderOptionGroup, IChatSessionProviderOptionItem, IChatSessionsExtensionPoint, IChatSessionsService, isSessionInProgressStatus, ResolvedChatSessionsExtensionPoint } from '../../common/chatSessionsService.js';
|
||||
import { IChatNewSessionRequest, IChatSession, IChatSessionContentProvider, IChatSessionItem, IChatSessionItemController, IChatSessionItemsDelta, IChatSessionOptionsWillNotifyExtensionEvent, IChatSessionProviderOptionGroup, IChatSessionProviderOptionItem, IChatSessionsExtensionPoint, IChatSessionsService, isSessionInProgressStatus, ResolvedChatSessionsExtensionPoint } from '../../common/chatSessionsService.js';
|
||||
import { ChatAgentLocation, ChatModeKind } from '../../common/constants.js';
|
||||
import { CHAT_CATEGORY } from '../actions/chatActions.js';
|
||||
import { IChatEditorOptions } from '../widgetHosts/editor/chatEditor.js';
|
||||
@@ -47,7 +47,10 @@ 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 { isUntitledChatSession, LocalChatSessionUri } from '../../common/model/chatUri.js';
|
||||
import {
|
||||
getChatSessionType,
|
||||
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';
|
||||
@@ -276,7 +279,7 @@ export class ChatSessionsService extends Disposable implements IChatSessionsServ
|
||||
private readonly _onDidChangeItemsProviders = this._register(new Emitter<{ readonly chatSessionType: string }>());
|
||||
readonly onDidChangeItemsProviders = this._onDidChangeItemsProviders.event;
|
||||
|
||||
private readonly _onDidChangeSessionItems = this._register(new Emitter<{ readonly chatSessionType: string }>());
|
||||
private readonly _onDidChangeSessionItems = this._register(new Emitter<IChatSessionItemsDelta>());
|
||||
readonly onDidChangeSessionItems = this._onDidChangeSessionItems.event;
|
||||
|
||||
private readonly _onDidChangeAvailability = this._register(new Emitter<void>());
|
||||
@@ -350,10 +353,17 @@ export class ChatSessionsService extends Disposable implements IChatSessionsServ
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(this.onDidChangeSessionItems(({ chatSessionType }) => {
|
||||
this.updateInProgressStatus(chatSessionType).catch(error => {
|
||||
this._logService.warn(`Failed to update progress status for '${chatSessionType}':`, error);
|
||||
});
|
||||
this._register(this.onDidChangeSessionItems((delta) => {
|
||||
const changedChatSessionTypes = new Set<string>();
|
||||
for (const resource of delta.addedOrUpdated ?? []) {
|
||||
changedChatSessionTypes.add(getChatSessionType(resource.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({
|
||||
@@ -597,7 +607,11 @@ export class ChatSessionsService extends Disposable implements IChatSessionsServ
|
||||
}
|
||||
|
||||
private _evaluateAvailability(): void {
|
||||
let hasChanges = false;
|
||||
const newlyEnabledChatSessionTypes = new Set<string>();
|
||||
const newlyDisabledChatSessionTypes = new Set<string>();
|
||||
|
||||
const disposedChatSessions = new ResourceSet();
|
||||
|
||||
for (const { contribution, extension } of this._contributions.values()) {
|
||||
const isCurrentlyRegistered = this._contributionDisposables.has(contribution.type);
|
||||
const shouldBeRegistered = this._isContributionAvailable(contribution);
|
||||
@@ -607,21 +621,25 @@ export class ChatSessionsService extends Disposable implements IChatSessionsServ
|
||||
this._contributionDisposables.deleteAndDispose(contribution.type);
|
||||
|
||||
// Also dispose any cached sessions for this contribution
|
||||
this._disposeSessionsForContribution(contribution.type);
|
||||
hasChanges = true;
|
||||
for (const sessionResource of this._disposeSessionsForContribution(contribution.type)) {
|
||||
disposedChatSessions.add(sessionResource);
|
||||
}
|
||||
|
||||
newlyDisabledChatSessionTypes.add(contribution.type);
|
||||
} else if (!isCurrentlyRegistered && shouldBeRegistered) {
|
||||
// Enable the contribution by registering it
|
||||
this._enableContribution(contribution, extension);
|
||||
hasChanges = true;
|
||||
newlyEnabledChatSessionTypes.add(contribution.type);
|
||||
}
|
||||
}
|
||||
if (hasChanges) {
|
||||
if (newlyEnabledChatSessionTypes.size > 0 || newlyDisabledChatSessionTypes.size > 0) {
|
||||
this._onDidChangeAvailability.fire();
|
||||
for (const chatSessionType of this._itemControllers.keys()) {
|
||||
for (const chatSessionType of [...newlyEnabledChatSessionTypes, ...newlyDisabledChatSessionTypes]) {
|
||||
this._onDidChangeItemsProviders.fire({ chatSessionType });
|
||||
}
|
||||
for (const { contribution } of this._contributions.values()) {
|
||||
this._onDidChangeSessionItems.fire({ chatSessionType: contribution.type });
|
||||
|
||||
if (disposedChatSessions.size > 0) {
|
||||
this._onDidChangeSessionItems.fire({ removed: Array.from(disposedChatSessions) });
|
||||
}
|
||||
}
|
||||
this._updateHasCanDelegateProvidersContextKey();
|
||||
@@ -638,7 +656,12 @@ export class ChatSessionsService extends Disposable implements IChatSessionsServ
|
||||
disposableStore.add(this._registerMenuItems(contribution, ext));
|
||||
}
|
||||
|
||||
private _disposeSessionsForContribution(contributionId: string): void {
|
||||
/**
|
||||
* Disposes of all sessions that belong to a contribution
|
||||
*
|
||||
* @returns List of session resources that were disposed.
|
||||
*/
|
||||
private _disposeSessionsForContribution(contributionId: string): URI[] {
|
||||
// Find and dispose all sessions that belong to this contribution
|
||||
const sessionsToDispose: URI[] = [];
|
||||
for (const [sessionResource, sessionData] of this._sessions) {
|
||||
@@ -657,6 +680,7 @@ export class ChatSessionsService extends Disposable implements IChatSessionsServ
|
||||
sessionData.dispose(); // This will call _onWillDisposeSession and clean up
|
||||
}
|
||||
}
|
||||
return sessionsToDispose;
|
||||
}
|
||||
|
||||
private _registerAgent(contribution: IChatSessionsExtensionPoint, ext: IRelaxedExtensionDescription): IDisposable {
|
||||
@@ -866,8 +890,8 @@ export class ChatSessionsService extends Disposable implements IChatSessionsServ
|
||||
this._itemControllers.set(chatSessionType, { controller, initialRefresh: controller.refresh(initialRefreshCts.token) });
|
||||
this._onDidChangeItemsProviders.fire({ chatSessionType });
|
||||
|
||||
disposables.add(controller.onDidChangeChatSessionItems(() => {
|
||||
this._onDidChangeSessionItems.fire({ chatSessionType });
|
||||
disposables.add(controller.onDidChangeChatSessionItems(e => {
|
||||
this._onDidChangeSessionItems.fire(e);
|
||||
}));
|
||||
|
||||
this.updateInProgressStatus(chatSessionType).catch(error => {
|
||||
|
||||
@@ -14,7 +14,7 @@ import { ICommandService } from '../../../../../platform/commands/common/command
|
||||
import { ILogService } from '../../../../../platform/log/common/log.js';
|
||||
import { IStorageService, StorageScope, StorageTarget } from '../../../../../platform/storage/common/storage.js';
|
||||
import { ILifecycleService, LifecyclePhase } from '../../../../services/lifecycle/common/lifecycle.js';
|
||||
import { ChatSessionStatus, IChatSessionItem, IChatSessionItemController, IChatSessionsService } from '../../common/chatSessionsService.js';
|
||||
import { ChatSessionStatus, IChatSessionItem, IChatSessionItemController, IChatSessionItemsDelta, IChatSessionsService } from '../../common/chatSessionsService.js';
|
||||
import { AgentSessionProviders } from '../agentSessions/agentSessions.js';
|
||||
import { IAgentSession } from '../agentSessions/agentSessionsModel.js';
|
||||
import { ISessionOpenerParticipant, ISessionOpenOptions, sessionOpenerRegistry } from '../agentSessions/agentSessionsOpener.js';
|
||||
@@ -36,8 +36,8 @@ export class GrowthSessionController extends Disposable implements IChatSessionI
|
||||
|
||||
private static readonly SESSION_URI = URI.from({ scheme: AgentSessionProviders.Growth, path: '/growth-welcome' });
|
||||
|
||||
private readonly _onDidChangeChatSessionItems = this._register(new Emitter<void>());
|
||||
readonly onDidChangeChatSessionItems: Event<void> = this._onDidChangeChatSessionItems.event;
|
||||
private readonly _onDidChangeChatSessionItems = this._register(new Emitter<IChatSessionItemsDelta>());
|
||||
readonly onDidChangeChatSessionItems = this._onDidChangeChatSessionItems.event;
|
||||
|
||||
private readonly _onDidDismiss = this._register(new Emitter<void>());
|
||||
readonly onDidDismiss: Event<void> = this._onDidDismiss.event;
|
||||
@@ -103,7 +103,9 @@ export class GrowthSessionController extends Disposable implements IChatSessionI
|
||||
this.storageService.store(GrowthSessionController.STORAGE_KEY, true, StorageScope.APPLICATION, StorageTarget.USER);
|
||||
|
||||
// Fire change event first so that listeners (like the model) see empty items
|
||||
this._onDidChangeChatSessionItems.fire();
|
||||
this._onDidChangeChatSessionItems.fire({
|
||||
removed: [GrowthSessionController.SESSION_URI],
|
||||
});
|
||||
// Then fire dismiss event which triggers unregistration of the controller.
|
||||
this._onDidDismiss.fire();
|
||||
}
|
||||
|
||||
@@ -1499,7 +1499,7 @@ export interface IChatService {
|
||||
readonly onDidReceiveQuestionCarouselAnswer: Event<{ requestId: string; resolveId: string; answers: IChatQuestionAnswers | undefined }>;
|
||||
notifyQuestionCarouselAnswer(requestId: string, resolveId: string, answers: IChatQuestionAnswers | undefined): void;
|
||||
|
||||
readonly onDidDisposeSession: Event<{ readonly sessionResource: URI[]; readonly reason: 'cleared' }>;
|
||||
readonly onDidDisposeSession: Event<{ readonly sessionResource: readonly URI[]; readonly reason: 'cleared' }>;
|
||||
|
||||
transferChatSession(transferredSessionResource: URI, toWorkspace: URI): Promise<void>;
|
||||
|
||||
@@ -1510,7 +1510,7 @@ export interface IChatService {
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
registerChatModelChangeListeners(chatSessionType: string, onChange: () => void): IDisposable;
|
||||
registerChatModelChangeListeners(chatSessionType: string, onChange: (chatSessionResource: URI) => void): IDisposable;
|
||||
|
||||
/**
|
||||
* For tests only!
|
||||
|
||||
@@ -1615,7 +1615,7 @@ export class ChatService extends Disposable implements IChatService {
|
||||
return localSessionId;
|
||||
}
|
||||
|
||||
public registerChatModelChangeListeners(chatSessionType: string, onChange: () => void): IDisposable {
|
||||
public registerChatModelChangeListeners(chatSessionType: string, onChange: (chatSessionResource: URI) => void): IDisposable {
|
||||
const disposableStore = new DisposableStore();
|
||||
const chatModelsICareAbout = this.chatModels.map(models =>
|
||||
Array.from(models).filter((model: IChatModel) => model.sessionResource.scheme === chatSessionType)
|
||||
@@ -1638,7 +1638,7 @@ export class ChatService extends Disposable implements IChatService {
|
||||
listeners.set(added.sessionResource, autorun(reader => {
|
||||
requestChangeListener.read(reader)?.read(reader);
|
||||
modelChangeListener.read(reader);
|
||||
onChange();
|
||||
onChange(added.sessionResource);
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -198,9 +198,14 @@ export interface IChatNewSessionRequest {
|
||||
readonly command?: string;
|
||||
}
|
||||
|
||||
export interface IChatSessionItemsDelta {
|
||||
readonly addedOrUpdated?: readonly IChatSessionItem[];
|
||||
readonly removed?: readonly URI[];
|
||||
}
|
||||
|
||||
export interface IChatSessionItemController {
|
||||
|
||||
readonly onDidChangeChatSessionItems: Event<void>;
|
||||
readonly onDidChangeChatSessionItems: Event<IChatSessionItemsDelta>;
|
||||
|
||||
get items(): readonly IChatSessionItem[];
|
||||
|
||||
@@ -229,7 +234,7 @@ export interface IChatSessionsService {
|
||||
|
||||
// #region Chat session item provider support
|
||||
readonly onDidChangeItemsProviders: Event<{ readonly chatSessionType: string }>;
|
||||
readonly onDidChangeSessionItems: Event<{ readonly chatSessionType: string }>;
|
||||
readonly onDidChangeSessionItems: Event<IChatSessionItemsDelta>;
|
||||
|
||||
readonly onDidChangeAvailability: Event<void>;
|
||||
readonly onDidChangeInProgress: Event<void>;
|
||||
|
||||
+45
-42
@@ -77,7 +77,7 @@ suite('AgentSessions', () => {
|
||||
|
||||
test('should resolve sessions from controllers', async () => {
|
||||
return runWithFakedTimers({}, async () => {
|
||||
const chatSessionType = 'test-type';
|
||||
const chatSessionType = chatSessionTestType;
|
||||
const controller = new StaticChatSessionItemController([
|
||||
makeSimpleSessionItem('session-1', {
|
||||
label: 'Test Session 1'
|
||||
@@ -93,9 +93,9 @@ suite('AgentSessions', () => {
|
||||
await viewModel.resolve(undefined);
|
||||
|
||||
assert.strictEqual(viewModel.sessions.length, 2);
|
||||
assert.strictEqual(viewModel.sessions[0].resource.toString(), 'test://session-1');
|
||||
assert.strictEqual(viewModel.sessions[0].resource.toString(), `${chatSessionTestType}://session-1`);
|
||||
assert.strictEqual(viewModel.sessions[0].label, 'Test Session 1');
|
||||
assert.strictEqual(viewModel.sessions[1].resource.toString(), 'test://session-2');
|
||||
assert.strictEqual(viewModel.sessions[1].resource.toString(), `${chatSessionTestType}://session-2`);
|
||||
assert.strictEqual(viewModel.sessions[1].label, 'Test Session 2');
|
||||
});
|
||||
});
|
||||
@@ -114,8 +114,8 @@ suite('AgentSessions', () => {
|
||||
await viewModel.resolve(undefined);
|
||||
|
||||
assert.strictEqual(viewModel.sessions.length, 2);
|
||||
assert.strictEqual(viewModel.sessions[0].resource.toString(), 'test://session-1');
|
||||
assert.strictEqual(viewModel.sessions[1].resource.toString(), 'test://session-2');
|
||||
assert.strictEqual(viewModel.sessions[0].resource.toString(), `${chatSessionTestType}://session-1`);
|
||||
assert.strictEqual(viewModel.sessions[1].resource.toString(), `${chatSessionTestType}://session-2`);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -123,7 +123,7 @@ suite('AgentSessions', () => {
|
||||
return runWithFakedTimers({}, async () => {
|
||||
const controller = new StaticChatSessionItemController([]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = createViewModel();
|
||||
|
||||
let willResolveFired = false;
|
||||
@@ -150,7 +150,7 @@ suite('AgentSessions', () => {
|
||||
return runWithFakedTimers({}, async () => {
|
||||
const controller = new StaticChatSessionItemController([makeSimpleSessionItem('session-1')]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = createViewModel();
|
||||
|
||||
let sessionsChangedFired = false;
|
||||
@@ -180,7 +180,7 @@ suite('AgentSessions', () => {
|
||||
changes: { files: 1, insertions: 10, deletions: 5 }
|
||||
}]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = createViewModel();
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
@@ -241,7 +241,7 @@ suite('AgentSessions', () => {
|
||||
|
||||
test('should respond to onDidChangeItemsProviders event', async () => {
|
||||
return runWithFakedTimers({}, async () => {
|
||||
const chatSessionType = 'test-type';
|
||||
const chatSessionType = chatSessionTestType;
|
||||
const controller = new StaticChatSessionItemController([makeSimpleSessionItem('session-1')]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionType, controller);
|
||||
@@ -263,7 +263,7 @@ suite('AgentSessions', () => {
|
||||
return runWithFakedTimers({}, async () => {
|
||||
const controller = new StaticChatSessionItemController([makeSimpleSessionItem('session-1')]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = createViewModel();
|
||||
|
||||
const sessionsChangedPromise = Event.toPromise(viewModel.onDidChangeSessions);
|
||||
@@ -280,15 +280,16 @@ suite('AgentSessions', () => {
|
||||
|
||||
test('should respond to onDidChangeSessionItems event', async () => {
|
||||
return runWithFakedTimers({}, async () => {
|
||||
const controller = new StaticChatSessionItemController([makeSimpleSessionItem('session-1')]);
|
||||
const testSession = makeSimpleSessionItem('session-1');
|
||||
const controller = new StaticChatSessionItemController([testSession]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = createViewModel();
|
||||
|
||||
const sessionsChangedPromise = Event.toPromise(viewModel.onDidChangeSessions);
|
||||
|
||||
// Trigger event - this should automatically call resolve
|
||||
mockChatSessionsService.fireDidChangeSessionItems('test-type');
|
||||
mockChatSessionsService.fireDidChangeSessionItems({ addedOrUpdated: [testSession] });
|
||||
|
||||
// Wait for the sessions to be resolved
|
||||
await sessionsChangedPromise;
|
||||
@@ -301,13 +302,13 @@ suite('AgentSessions', () => {
|
||||
return runWithFakedTimers({}, async () => {
|
||||
const controller = new StaticChatSessionItemController([makeSimpleSessionItem('session-1')]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = createViewModel();
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
|
||||
assert.strictEqual(viewModel.sessions.length, 1);
|
||||
assert.strictEqual(viewModel.sessions[0].providerType, 'test-type');
|
||||
assert.strictEqual(viewModel.sessions[0].providerType, chatSessionTestType);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -315,7 +316,7 @@ suite('AgentSessions', () => {
|
||||
return runWithFakedTimers({}, async () => {
|
||||
const controller = new StaticChatSessionItemController([]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = createViewModel();
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
@@ -347,7 +348,7 @@ suite('AgentSessions', () => {
|
||||
}
|
||||
]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = createViewModel();
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
@@ -375,7 +376,7 @@ suite('AgentSessions', () => {
|
||||
get items() { return _items; }
|
||||
};
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = createViewModel();
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
@@ -415,7 +416,7 @@ suite('AgentSessions', () => {
|
||||
timing: makeNewSessionTiming()
|
||||
}]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = createViewModel();
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
@@ -437,7 +438,7 @@ suite('AgentSessions', () => {
|
||||
}
|
||||
};
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
// Registering calls a refresh initially
|
||||
assert.strictEqual(controllerCallCount, 1);
|
||||
|
||||
@@ -669,7 +670,7 @@ suite('AgentSessions', () => {
|
||||
|
||||
function createSession(overrides: Partial<IAgentSession> = {}): IAgentSession {
|
||||
return {
|
||||
providerType: 'test-type',
|
||||
providerType: chatSessionTestType,
|
||||
providerLabel: 'Test Provider',
|
||||
icon: Codicon.chatSparkle,
|
||||
resource: URI.parse('test://session'),
|
||||
@@ -1214,7 +1215,7 @@ suite('AgentSessions', () => {
|
||||
return runWithFakedTimers({}, async () => {
|
||||
const controller = new StaticChatSessionItemController([makeSimpleSessionItem('session-1')]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = disposables.add(instantiationService.createInstance(AgentSessionsModel));
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
@@ -1236,7 +1237,7 @@ suite('AgentSessions', () => {
|
||||
return runWithFakedTimers({}, async () => {
|
||||
const controller = new StaticChatSessionItemController([makeSimpleSessionItem('session-1')]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = disposables.add(instantiationService.createInstance(AgentSessionsModel));
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
@@ -1256,7 +1257,7 @@ suite('AgentSessions', () => {
|
||||
return runWithFakedTimers({}, async () => {
|
||||
const controller = new StaticChatSessionItemController([makeSimpleSessionItem('session-1')]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = disposables.add(instantiationService.createInstance(AgentSessionsModel));
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
@@ -1284,7 +1285,7 @@ suite('AgentSessions', () => {
|
||||
timing: makeNewSessionTiming()
|
||||
}]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = disposables.add(instantiationService.createInstance(AgentSessionsModel));
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
@@ -1303,7 +1304,7 @@ suite('AgentSessions', () => {
|
||||
timing: makeNewSessionTiming()
|
||||
}]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = disposables.add(instantiationService.createInstance(AgentSessionsModel));
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
@@ -1358,7 +1359,7 @@ suite('AgentSessions', () => {
|
||||
timing: futureSessionTiming,
|
||||
}]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = disposables.add(instantiationService.createInstance(AgentSessionsModel));
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
@@ -1379,7 +1380,7 @@ suite('AgentSessions', () => {
|
||||
return runWithFakedTimers({}, async () => {
|
||||
const controller = new StaticChatSessionItemController([makeSimpleSessionItem('session-1')]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = disposables.add(instantiationService.createInstance(AgentSessionsModel));
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
@@ -1401,7 +1402,7 @@ suite('AgentSessions', () => {
|
||||
return runWithFakedTimers({}, async () => {
|
||||
const controller = new StaticChatSessionItemController([makeSimpleSessionItem('session-1')]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = disposables.add(instantiationService.createInstance(AgentSessionsModel));
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
@@ -1424,7 +1425,7 @@ suite('AgentSessions', () => {
|
||||
return runWithFakedTimers({}, async () => {
|
||||
const controller = new StaticChatSessionItemController([makeSimpleSessionItem('session-1')]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = disposables.add(instantiationService.createInstance(AgentSessionsModel));
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
@@ -1455,7 +1456,7 @@ suite('AgentSessions', () => {
|
||||
timing: oldSessionTiming,
|
||||
}]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = disposables.add(instantiationService.createInstance(AgentSessionsModel));
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
@@ -1480,7 +1481,7 @@ suite('AgentSessions', () => {
|
||||
timing: newSessionTiming,
|
||||
}]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = disposables.add(instantiationService.createInstance(AgentSessionsModel));
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
@@ -1506,7 +1507,7 @@ suite('AgentSessions', () => {
|
||||
timing: sessionTiming,
|
||||
}]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = disposables.add(instantiationService.createInstance(AgentSessionsModel));
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
@@ -1532,7 +1533,7 @@ suite('AgentSessions', () => {
|
||||
timing: sessionTiming,
|
||||
}]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = disposables.add(instantiationService.createInstance(AgentSessionsModel));
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
@@ -1557,7 +1558,7 @@ suite('AgentSessions', () => {
|
||||
timing: newSessionTiming,
|
||||
}]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = disposables.add(instantiationService.createInstance(AgentSessionsModel));
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
@@ -1590,7 +1591,7 @@ suite('AgentSessions', () => {
|
||||
timing: newSessionTiming,
|
||||
}]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = disposables.add(instantiationService.createInstance(AgentSessionsModel));
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
@@ -1629,7 +1630,7 @@ suite('AgentSessions', () => {
|
||||
timing: newSessionTiming,
|
||||
}]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = disposables.add(instantiationService.createInstance(AgentSessionsModel));
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
@@ -1659,7 +1660,7 @@ suite('AgentSessions', () => {
|
||||
lastRequestEnded: Date.UTC(2025, 10 /* November */, 2),
|
||||
};
|
||||
|
||||
const chatSessionType = 'test-type';
|
||||
const chatSessionType = chatSessionTestType;
|
||||
const controller = new StaticChatSessionItemController([{
|
||||
resource: URI.parse('test://old-session'),
|
||||
label: 'Old Session',
|
||||
@@ -1727,7 +1728,7 @@ suite('AgentSessions', () => {
|
||||
get items() { return _items; }
|
||||
};
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = disposables.add(instantiationService.createInstance(AgentSessionsModel));
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
@@ -1757,7 +1758,7 @@ suite('AgentSessions', () => {
|
||||
get items() { return _items; }
|
||||
};
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = disposables.add(instantiationService.createInstance(AgentSessionsModel));
|
||||
|
||||
await viewModel.resolve(undefined);
|
||||
@@ -1967,7 +1968,7 @@ suite('AgentSessions', () => {
|
||||
return runWithFakedTimers({}, async () => {
|
||||
const controller = new StaticChatSessionItemController([makeSimpleSessionItem('session-1')]);
|
||||
|
||||
mockChatSessionsService.registerChatSessionItemController('test-type', controller);
|
||||
mockChatSessionsService.registerChatSessionItemController(chatSessionTestType, controller);
|
||||
viewModel = disposables.add(instantiationService.createInstance(AgentSessionsModel));
|
||||
|
||||
// Set willShutdown to true
|
||||
@@ -2018,9 +2019,11 @@ suite('AgentSessions', () => {
|
||||
|
||||
}); // End of Agent Sessions suite
|
||||
|
||||
const chatSessionTestType = 'test-type';
|
||||
|
||||
function makeSimpleSessionItem(id: string, overrides?: Partial<IChatSessionItem>): IChatSessionItem {
|
||||
return {
|
||||
resource: URI.parse(`test://${id}`),
|
||||
resource: URI.parse(`${chatSessionTestType}://${id}`),
|
||||
label: `Session ${id}`,
|
||||
timing: makeNewSessionTiming(),
|
||||
...overrides
|
||||
|
||||
+26
-4
@@ -6,7 +6,7 @@
|
||||
import assert from 'assert';
|
||||
import { CancellationToken } from '../../../../../../base/common/cancellation.js';
|
||||
import { Codicon } from '../../../../../../base/common/codicons.js';
|
||||
import { Emitter } from '../../../../../../base/common/event.js';
|
||||
import { Emitter, Event } from '../../../../../../base/common/event.js';
|
||||
import { DisposableStore } from '../../../../../../base/common/lifecycle.js';
|
||||
import { observableValue } from '../../../../../../base/common/observable.js';
|
||||
import { URI } from '../../../../../../base/common/uri.js';
|
||||
@@ -585,14 +585,25 @@ suite('LocalAgentsSessionsController', () => {
|
||||
|
||||
// Add the session first
|
||||
mockChatService.addSession(mockModel);
|
||||
mockChatService.setLiveSessionItems([{
|
||||
sessionResource,
|
||||
title: 'Test Session',
|
||||
lastMessageDate: Date.now(),
|
||||
isActive: true,
|
||||
timing: createTestTiming(),
|
||||
lastResponseState: ResponseModelState.Complete
|
||||
}]);
|
||||
|
||||
let changeEventCount = 0;
|
||||
disposables.add(controller.onDidChangeChatSessionItems(() => {
|
||||
changeEventCount++;
|
||||
}));
|
||||
|
||||
const onDidChangeChatSessionItems = Event.toPromise(controller.onDidChangeChatSessionItems);
|
||||
|
||||
// Simulate progress change by triggering the progress listener
|
||||
mockChatService.triggerProgressEvent();
|
||||
mockChatService.triggerProgressEvent(sessionResource);
|
||||
await onDidChangeChatSessionItems;
|
||||
|
||||
assert.strictEqual(changeEventCount, 1);
|
||||
});
|
||||
@@ -611,15 +622,26 @@ suite('LocalAgentsSessionsController', () => {
|
||||
|
||||
// Add the session first
|
||||
mockChatService.addSession(mockModel);
|
||||
mockChatService.setLiveSessionItems([{
|
||||
sessionResource,
|
||||
title: 'Test Session',
|
||||
lastMessageDate: Date.now(),
|
||||
isActive: true,
|
||||
timing: createTestTiming(),
|
||||
lastResponseState: ResponseModelState.Complete
|
||||
}]);
|
||||
|
||||
let changeEventCount = 0;
|
||||
disposables.add(controller.onDidChangeChatSessionItems(() => {
|
||||
changeEventCount++;
|
||||
}));
|
||||
|
||||
// Simulate progress change by triggering the progress listener
|
||||
mockChatService.triggerProgressEvent();
|
||||
const onDidChangeChatSessionItems = Event.toPromise(controller.onDidChangeChatSessionItems);
|
||||
|
||||
// Simulate progress change by triggering the progress listener
|
||||
mockChatService.triggerProgressEvent(sessionResource);
|
||||
|
||||
await onDidChangeChatSessionItems;
|
||||
assert.strictEqual(changeEventCount, 1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import { CancellationToken } from '../../../../../../base/common/cancellation.js';
|
||||
import { Emitter, Event } from '../../../../../../base/common/event.js';
|
||||
import { IDisposable } from '../../../../../../base/common/lifecycle.js';
|
||||
import { ResourceMap } from '../../../../../../base/common/map.js';
|
||||
import { ISettableObservable, observableValue } from '../../../../../../base/common/observable.js';
|
||||
import { URI } from '../../../../../../base/common/uri.js';
|
||||
import { ChatRequestQueueKind, ChatSendResult, IChatDetail, IChatModelReference, IChatProgress, IChatSendRequestOptions, IChatService, IChatSessionContext, IChatSessionStartOptions, IChatUserActionEvent } from '../../../common/chatService/chatService.js';
|
||||
@@ -22,7 +23,7 @@ export class MockChatService implements IChatService {
|
||||
readonly onDidSubmitRequest = Event.None;
|
||||
readonly onDidCreateModel = Event.None;
|
||||
|
||||
private sessions = new Map<string, IChatModel>();
|
||||
private readonly sessions = new ResourceMap<IChatModel>();
|
||||
private liveSessionItems: IChatDetail[] = [];
|
||||
private historySessionItems: IChatDetail[] = [];
|
||||
|
||||
@@ -50,13 +51,13 @@ export class MockChatService implements IChatService {
|
||||
}
|
||||
|
||||
addSession(session: IChatModel): void {
|
||||
this.sessions.set(session.sessionResource.toString(), session);
|
||||
this.sessions.set(session.sessionResource, session);
|
||||
// Update the chatModels observable
|
||||
this._chatModels.set([...this.sessions.values()], undefined);
|
||||
}
|
||||
|
||||
removeSession(sessionResource: URI): void {
|
||||
this.sessions.delete(sessionResource.toString());
|
||||
this.sessions.delete(sessionResource);
|
||||
// Update the chatModels observable
|
||||
this._chatModels.set([...this.sessions.values()], undefined);
|
||||
}
|
||||
@@ -78,7 +79,7 @@ export class MockChatService implements IChatService {
|
||||
}
|
||||
|
||||
getSession(sessionResource: URI): IChatModel | undefined {
|
||||
return this.sessions.get(sessionResource.toString());
|
||||
return this.sessions.get(sessionResource);
|
||||
}
|
||||
|
||||
getLatestRequest(): IChatRequestModel | undefined {
|
||||
@@ -190,9 +191,9 @@ export class MockChatService implements IChatService {
|
||||
}
|
||||
|
||||
|
||||
private onChange?: () => void;
|
||||
private onChange?: (sessionResource: URI) => void;
|
||||
|
||||
registerChatModelChangeListeners(chatSessionType: string, onChange: () => void): IDisposable {
|
||||
registerChatModelChangeListeners(chatSessionType: string, onChange: (sessionResource: URI) => void): IDisposable {
|
||||
// Store the emitter so tests can trigger it
|
||||
this.onChange = onChange;
|
||||
return {
|
||||
@@ -203,9 +204,7 @@ export class MockChatService implements IChatService {
|
||||
}
|
||||
|
||||
// Helper method for tests to trigger progress events
|
||||
triggerProgressEvent(): void {
|
||||
if (this.onChange) {
|
||||
this.onChange();
|
||||
}
|
||||
triggerProgressEvent(sessionResource: URI): void {
|
||||
this.onChange?.(sessionResource);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import { ThemeIcon } from '../../../../../base/common/themables.js';
|
||||
import { URI } from '../../../../../base/common/uri.js';
|
||||
import { IChatAgentAttachmentCapabilities } from '../../common/participants/chatAgents.js';
|
||||
import { IChatModel } from '../../common/model/chatModel.js';
|
||||
import { IChatNewSessionRequest, IChatSession, IChatSessionContentProvider, IChatSessionItemController, IChatSessionItem, IChatSessionOptionsWillNotifyExtensionEvent, IChatSessionProviderOptionGroup, IChatSessionProviderOptionItem, IChatSessionsExtensionPoint, IChatSessionsService, ResolvedChatSessionsExtensionPoint } from '../../common/chatSessionsService.js';
|
||||
import { IChatNewSessionRequest, IChatSession, IChatSessionContentProvider, IChatSessionItemController, IChatSessionItem, IChatSessionOptionsWillNotifyExtensionEvent, IChatSessionProviderOptionGroup, IChatSessionProviderOptionItem, IChatSessionsExtensionPoint, IChatSessionsService, ResolvedChatSessionsExtensionPoint, IChatSessionItemsDelta } from '../../common/chatSessionsService.js';
|
||||
import { Target } from '../../common/promptSyntax/promptTypes.js';
|
||||
|
||||
export class MockChatSessionsService implements IChatSessionsService {
|
||||
@@ -22,7 +22,7 @@ export class MockChatSessionsService implements IChatSessionsService {
|
||||
private readonly _onDidChangeItemsProviders = new Emitter<{ readonly chatSessionType: string }>();
|
||||
readonly onDidChangeItemsProviders = this._onDidChangeItemsProviders.event;
|
||||
|
||||
private readonly _onDidChangeSessionItems = new Emitter<{ readonly chatSessionType: string }>();
|
||||
private readonly _onDidChangeSessionItems = new Emitter<IChatSessionItemsDelta>();
|
||||
readonly onDidChangeSessionItems = this._onDidChangeSessionItems.event;
|
||||
|
||||
private readonly _onDidChangeAvailability = new Emitter<void>();
|
||||
@@ -52,8 +52,8 @@ export class MockChatSessionsService implements IChatSessionsService {
|
||||
this._onDidChangeItemsProviders.fire(event);
|
||||
}
|
||||
|
||||
fireDidChangeSessionItems(chatSessionType: string): void {
|
||||
this._onDidChangeSessionItems.fire({ chatSessionType });
|
||||
fireDidChangeSessionItems(event: IChatSessionItemsDelta): void {
|
||||
this._onDidChangeSessionItems.fire(event);
|
||||
}
|
||||
|
||||
fireDidChangeAvailability(): void {
|
||||
|
||||
Reference in New Issue
Block a user