mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-25 15:35:43 +01:00
Try storing all chat session options in a map
This commit is contained in:
@@ -401,12 +401,9 @@ export class SessionsManagementService extends Disposable implements ISessionsMa
|
||||
if (selectedOptions && selectedOptions.size > 0) {
|
||||
const contributedSession = model.contributedChatSession;
|
||||
if (contributedSession) {
|
||||
const initialSessionOptions = [...selectedOptions.entries()].map(
|
||||
([optionId, value]) => ({ optionId, value })
|
||||
);
|
||||
model.setContributedChatSession({
|
||||
...contributedSession,
|
||||
initialSessionOptions,
|
||||
initialSessionOptions: selectedOptions,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ import { ChatRequestAgentPart } from '../../contrib/chat/common/requestParser/ch
|
||||
import { ChatRequestParser } from '../../contrib/chat/common/requestParser/chatRequestParser.js';
|
||||
import { getDynamicVariablesForWidget, getSelectedToolAndToolSetsForWidget } from '../../contrib/chat/browser/attachments/chatVariables.js';
|
||||
import { IChatContentInlineReference, IChatContentReference, IChatFollowup, IChatNotebookEdit, IChatProgress, IChatService, IChatTask, IChatTaskSerialized, IChatWarningMessage } from '../../contrib/chat/common/chatService/chatService.js';
|
||||
import { IChatSessionsService } from '../../contrib/chat/common/chatSessionsService.js';
|
||||
import { ChatSessionOptionsMap, IChatSessionsService } from '../../contrib/chat/common/chatSessionsService.js';
|
||||
import { ChatAgentLocation, ChatModeKind } from '../../contrib/chat/common/constants.js';
|
||||
import { ILanguageModelToolsService } from '../../contrib/chat/common/tools/languageModelToolsService.js';
|
||||
import { IExtHostContext, extHostNamedCustomer } from '../../services/extensions/common/extHostCustomers.js';
|
||||
@@ -253,10 +253,7 @@ export class MainThreadChatAgents2 extends Disposable implements MainThreadChatA
|
||||
chatSessionContext = {
|
||||
chatSessionResource,
|
||||
isUntitled,
|
||||
initialSessionOptions: contributedSession.initialSessionOptions?.map(o => ({
|
||||
optionId: o.optionId,
|
||||
value: typeof o.value === 'string' ? o.value : o.value.id,
|
||||
})),
|
||||
initialSessionOptions: ChatSessionOptionsMap.toStrValueArray(contributedSession.initialSessionOptions),
|
||||
};
|
||||
}
|
||||
return await this._proxy.$invokeAgent(handle, request, {
|
||||
|
||||
@@ -25,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, IChatSessionItemsDelta, IChatSessionProviderOptionItem, IChatSessionRequestHistoryItem, IChatSessionsService } from '../../contrib/chat/common/chatSessionsService.js';
|
||||
import { ChatSessionOptionsMap, ChatSessionStatus, IChatNewSessionRequest, IChatSession, IChatSessionContentProvider, IChatSessionHistoryItem, IChatSessionItem, IChatSessionItemController, IChatSessionItemsDelta, IChatSessionProviderOptionItem, IChatSessionRequestHistoryItem, IChatSessionsService, ReadonlyChatSessionOptionsMap } 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';
|
||||
@@ -44,9 +44,9 @@ export class ObservableChatSession extends Disposable implements IChatSession {
|
||||
readonly providerHandle: number;
|
||||
readonly history: Array<IChatSessionHistoryItem>;
|
||||
title?: string;
|
||||
private _options?: Record<string, string | IChatSessionProviderOptionItem>;
|
||||
public get options(): Record<string, string | IChatSessionProviderOptionItem> | undefined {
|
||||
return this._options;
|
||||
private _options?: ChatSessionOptionsMap;
|
||||
public get options(): ReadonlyChatSessionOptionsMap | undefined {
|
||||
return this._options ? new Map(this._options) : undefined;
|
||||
}
|
||||
private readonly _progressObservable = observableValue<IChatProgress[]>(this, []);
|
||||
private readonly _isCompleteObservable = observableValue<boolean>(this, false);
|
||||
@@ -115,7 +115,7 @@ export class ObservableChatSession extends Disposable implements IChatSession {
|
||||
token
|
||||
);
|
||||
|
||||
this._options = sessionContent.options;
|
||||
this._options = sessionContent.options ? ChatSessionOptionsMap.fromRecord(sessionContent.options) : undefined;
|
||||
this.title = sessionContent.title;
|
||||
this.history.length = 0;
|
||||
this.history.push(...sessionContent.history.map((turn: IChatSessionHistoryItemDto) => {
|
||||
@@ -383,7 +383,11 @@ class MainThreadChatSessionItemController extends Disposable implements IChatSes
|
||||
}
|
||||
|
||||
async newChatSessionItem(request: IChatNewSessionRequest, token: CancellationToken): Promise<IChatSessionItem | undefined> {
|
||||
const dto = await raceCancellationError(this._proxy.$newChatSessionItem(this._handle, request, token), token);
|
||||
const dto = await raceCancellationError(this._proxy.$newChatSessionItem(this._handle, {
|
||||
prompt: request.prompt,
|
||||
command: request.command,
|
||||
initialSessionOptions: request.initialSessionOptions ? ChatSessionOptionsMap.toStrValueArray(request.initialSessionOptions) : undefined,
|
||||
}, token), token);
|
||||
if (!dto) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -458,7 +462,7 @@ export class MainThreadChatSessions extends Disposable implements MainThreadChat
|
||||
this._register(this._chatSessionsService.onDidChangeSessionOptions(({ sessionResource, updates }) => {
|
||||
warnOnUntitledSessionResource(sessionResource, this._logService);
|
||||
const handle = this._getHandleForSessionType(sessionResource.scheme);
|
||||
this._logService.trace(`[MainThreadChatSessions] onRequestNotifyExtension received: scheme '${sessionResource.scheme}', handle ${handle}, ${updates.length} update(s)`);
|
||||
this._logService.trace(`[MainThreadChatSessions] onRequestNotifyExtension received: scheme '${sessionResource.scheme}', handle ${handle}, ${updates.size} update(s)`);
|
||||
if (handle !== undefined) {
|
||||
this.notifyOptionsChange(handle, sessionResource, updates);
|
||||
} else {
|
||||
@@ -546,10 +550,10 @@ export class MainThreadChatSessions extends Disposable implements MainThreadChat
|
||||
controller.addOrUpdateItem(resolvedItem);
|
||||
}
|
||||
|
||||
$onDidChangeChatSessionOptions(handle: number, sessionResourceComponents: UriComponents, updates: ReadonlyArray<{ optionId: string; value: string }>): void {
|
||||
$onDidChangeChatSessionOptions(handle: number, sessionResourceComponents: UriComponents, updates: Record<string, string | IChatSessionProviderOptionItem>): void {
|
||||
const sessionResource = URI.revive(sessionResourceComponents);
|
||||
warnOnUntitledSessionResource(sessionResource, this._logService);
|
||||
this._chatSessionsService.updateSessionOptions(sessionResource, updates);
|
||||
this._chatSessionsService.updateSessionOptions(sessionResource, ChatSessionOptionsMap.fromRecord(updates));
|
||||
}
|
||||
|
||||
async $onDidCommitChatSessionItem(handle: number, originalComponents: UriComponents, modifiedCompoennts: UriComponents): Promise<void> {
|
||||
@@ -696,12 +700,12 @@ export class MainThreadChatSessions extends Disposable implements MainThreadChat
|
||||
try {
|
||||
const initialSessionOptions = this._chatSessionsService.getSessionOptions(sessionResource);
|
||||
await session.initialize(token, {
|
||||
initialSessionOptions: initialSessionOptions ? [...initialSessionOptions].map(([optionId, value]) => ({ optionId, value })) : undefined,
|
||||
initialSessionOptions: initialSessionOptions ? [...initialSessionOptions].map(([optionId, value]) => ({ optionId, value: typeof value === 'string' ? value : value?.id })) : undefined,
|
||||
});
|
||||
if (session.options) {
|
||||
for (const [_, handle] of this._sessionTypeToHandle) {
|
||||
if (handle === providerHandle) {
|
||||
for (const [optionId, value] of Object.entries(session.options)) {
|
||||
for (const [optionId, value] of session.options) {
|
||||
this._chatSessionsService.setSessionOption(sessionResource, optionId, value);
|
||||
}
|
||||
break;
|
||||
@@ -810,7 +814,7 @@ export class MainThreadChatSessions extends Disposable implements MainThreadChat
|
||||
this._chatSessionsService.setOptionGroupsForSessionType(chatSessionScheme, handle, groupsWithCallbacks);
|
||||
}
|
||||
if (options?.newSessionOptions) {
|
||||
this._chatSessionsService.setNewSessionOptionsForSessionType(chatSessionScheme, options.newSessionOptions);
|
||||
this._chatSessionsService.setNewSessionOptionsForSessionType(chatSessionScheme, ChatSessionOptionsMap.fromRecord(options.newSessionOptions));
|
||||
}
|
||||
}).catch(err => this._logService.error('Error fetching chat session options', err));
|
||||
}
|
||||
@@ -850,10 +854,10 @@ export class MainThreadChatSessions extends Disposable implements MainThreadChat
|
||||
/**
|
||||
* Notify the extension about option changes for a session
|
||||
*/
|
||||
async notifyOptionsChange(handle: number, sessionResource: URI, updates: ReadonlyArray<{ optionId: string; value: string | IChatSessionProviderOptionItem | undefined }>): Promise<void> {
|
||||
async notifyOptionsChange(handle: number, sessionResource: URI, updates: ReadonlyMap<string, string | IChatSessionProviderOptionItem | undefined>): Promise<void> {
|
||||
this._logService.trace(`[MainThreadChatSessions] notifyOptionsChange: starting proxy call for handle ${handle}, sessionResource ${sessionResource}`);
|
||||
try {
|
||||
await this._proxy.$provideHandleOptionsChange(handle, sessionResource, updates, CancellationToken.None);
|
||||
await this._proxy.$provideHandleOptionsChange(handle, sessionResource, Object.fromEntries(updates), CancellationToken.None);
|
||||
this._logService.trace(`[MainThreadChatSessions] notifyOptionsChange: proxy call completed for handle ${handle}, sessionResource ${sessionResource}`);
|
||||
} catch (error) {
|
||||
this._logService.error(`[MainThreadChatSessions] notifyOptionsChange: error for handle ${handle}, sessionResource ${sessionResource}:`, error);
|
||||
|
||||
@@ -60,7 +60,7 @@ import { ICodeMapperRequest, ICodeMapperResult } from '../../contrib/chat/common
|
||||
import { IChatContextItem } from '../../contrib/chat/common/contextContrib/chatContext.js';
|
||||
import { IChatProgressHistoryResponseContent, IChatRequestVariableData } from '../../contrib/chat/common/model/chatModel.js';
|
||||
import { ChatResponseClearToPreviousToolInvocationReason, IChatContentInlineReference, IChatExternalEditsDto, IChatFollowup, IChatMultiDiffData, IChatMultiDiffDataSerialized, IChatNotebookEdit, IChatProgress, IChatTask, IChatTaskDto, IChatUserActionEvent, IChatVoteAction } from '../../contrib/chat/common/chatService/chatService.js';
|
||||
import { IChatNewSessionRequest, IChatSessionItem, IChatSessionProviderOptionGroup, IChatSessionProviderOptionItem } from '../../contrib/chat/common/chatSessionsService.js';
|
||||
import { IChatSessionItem, IChatSessionProviderOptionGroup, IChatSessionProviderOptionItem } from '../../contrib/chat/common/chatSessionsService.js';
|
||||
import { IChatRequestVariableValue } from '../../contrib/chat/common/attachments/chatVariables.js';
|
||||
import { ChatAgentLocation } from '../../contrib/chat/common/constants.js';
|
||||
import { IChatMessage, IChatResponsePart, ILanguageModelChatInfoOptions, ILanguageModelChatMetadataAndIdentifier, ILanguageModelChatRequestOptions, ILanguageModelChatSelector } from '../../contrib/chat/common/languageModels.js';
|
||||
@@ -3592,20 +3592,19 @@ export type IChatSessionHistoryItemDto = {
|
||||
|
||||
export type IChatSessionRequestHistoryItemDto = Extract<IChatSessionHistoryItemDto, { type: 'request' }>;
|
||||
|
||||
export interface ChatSessionOptionUpdateDto {
|
||||
readonly optionId: string;
|
||||
readonly value: string | IChatSessionProviderOptionItem | undefined;
|
||||
}
|
||||
|
||||
export interface ChatSessionOptionUpdateDto2 {
|
||||
readonly optionId: string;
|
||||
readonly value: string | IChatSessionProviderOptionItem;
|
||||
}
|
||||
|
||||
export interface ChatSessionContentContextDto {
|
||||
readonly initialSessionOptions?: ReadonlyArray<{ optionId: string; value: string }>;
|
||||
}
|
||||
|
||||
export interface IChatNewSessionRequestDto {
|
||||
readonly prompt: string;
|
||||
readonly command?: string;
|
||||
|
||||
readonly initialSessionOptions?: ReadonlyArray<{ optionId: string; value: string }>;
|
||||
}
|
||||
|
||||
export interface ChatSessionDto {
|
||||
id: string;
|
||||
resource: UriComponents;
|
||||
@@ -3636,7 +3635,7 @@ export interface MainThreadChatSessionsShape extends IDisposable {
|
||||
$onDidCommitChatSessionItem(controllerHandle: number, original: UriComponents, modified: UriComponents): void;
|
||||
$registerChatSessionContentProvider(handle: number, chatSessionScheme: string): void;
|
||||
$unregisterChatSessionContentProvider(handle: number): void;
|
||||
$onDidChangeChatSessionOptions(handle: number, sessionResource: UriComponents, updates: ReadonlyArray<ChatSessionOptionUpdateDto2>): void;
|
||||
$onDidChangeChatSessionOptions(handle: number, sessionResource: UriComponents, updates: Record<string, string | IChatSessionProviderOptionItem>): void;
|
||||
$onDidChangeChatSessionProviderOptions(handle: number): void;
|
||||
|
||||
$handleProgressChunk(handle: number, sessionResource: UriComponents, requestId: string, chunks: (IChatProgressDto | [IChatProgressDto, number])[]): Promise<void>;
|
||||
@@ -3647,7 +3646,7 @@ export interface MainThreadChatSessionsShape extends IDisposable {
|
||||
export interface ExtHostChatSessionsShape {
|
||||
$refreshChatSessionItems(providerHandle: number, token: CancellationToken): Promise<void>;
|
||||
$onDidChangeChatSessionItemState(providerHandle: number, sessionResource: UriComponents, archived: boolean): void;
|
||||
$newChatSessionItem(controllerHandle: number, request: IChatNewSessionRequest, token: CancellationToken): Promise<Dto<IChatSessionItem> | undefined>;
|
||||
$newChatSessionItem(controllerHandle: number, request: IChatNewSessionRequestDto, token: CancellationToken): Promise<Dto<IChatSessionItem> | undefined>;
|
||||
|
||||
$provideChatSessionContent(providerHandle: number, sessionResource: UriComponents, context: ChatSessionContentContextDto, token: CancellationToken): Promise<ChatSessionDto>;
|
||||
$interruptChatSessionActiveResponse(providerHandle: number, sessionResource: UriComponents, requestId: string): Promise<void>;
|
||||
@@ -3655,7 +3654,7 @@ export interface ExtHostChatSessionsShape {
|
||||
$invokeChatSessionRequestHandler(providerHandle: number, sessionResource: UriComponents, request: IChatAgentRequest, history: any[], token: CancellationToken): Promise<IChatAgentResult>;
|
||||
$provideChatSessionProviderOptions(providerHandle: number, token: CancellationToken): Promise<IChatSessionProviderOptions | undefined>;
|
||||
$invokeOptionGroupSearch(providerHandle: number, optionGroupId: string, query: string, token: CancellationToken): Promise<IChatSessionProviderOptionItem[]>;
|
||||
$provideHandleOptionsChange(providerHandle: number, sessionResource: UriComponents, updates: ReadonlyArray<ChatSessionOptionUpdateDto>, token: CancellationToken): Promise<void>;
|
||||
$provideHandleOptionsChange(providerHandle: number, sessionResource: UriComponents, updates: Record<string, string | IChatSessionProviderOptionItem | undefined>, token: CancellationToken): Promise<void>;
|
||||
$forkChatSession(providerHandle: number, sessionResource: UriComponents, request: IChatSessionRequestHistoryItemDto | undefined, token: CancellationToken): Promise<Dto<IChatSessionItem>>;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,11 +18,11 @@ import { SymbolKind, SymbolKinds } from '../../../editor/common/languages.js';
|
||||
import { IExtensionDescription } from '../../../platform/extensions/common/extensions.js';
|
||||
import { ILogService } from '../../../platform/log/common/log.js';
|
||||
import { IChatRequestVariableEntry, IDiagnosticVariableEntryFilterData, ISymbolVariableEntry, PromptFileVariableKind, toPromptFileVariableEntry } from '../../contrib/chat/common/attachments/chatVariableEntries.js';
|
||||
import { IChatNewSessionRequest, IChatSessionProviderOptionItem } from '../../contrib/chat/common/chatSessionsService.js';
|
||||
import { IChatSessionProviderOptionItem } from '../../contrib/chat/common/chatSessionsService.js';
|
||||
import { ChatAgentLocation } from '../../contrib/chat/common/constants.js';
|
||||
import { IChatAgentRequest, IChatAgentResult } from '../../contrib/chat/common/participants/chatAgents.js';
|
||||
import { Proxied } from '../../services/extensions/common/proxyIdentifier.js';
|
||||
import { ChatSessionContentContextDto, ChatSessionDto, ExtHostChatSessionsShape, IChatAgentProgressShape, IChatSessionRequestHistoryItemDto, IChatSessionProviderOptions, MainContext, MainThreadChatSessionsShape } from './extHost.protocol.js';
|
||||
import { ChatSessionContentContextDto, ChatSessionDto, ExtHostChatSessionsShape, IChatAgentProgressShape, IChatSessionRequestHistoryItemDto, IChatSessionProviderOptions, MainContext, MainThreadChatSessionsShape, IChatNewSessionRequestDto } from './extHost.protocol.js';
|
||||
import { ChatAgentResponseStream } from './extHostChatAgents2.js';
|
||||
import { CommandsConverter, ExtHostCommands } from './extHostCommands.js';
|
||||
import { ExtHostLanguageModels } from './extHostLanguageModels.js';
|
||||
@@ -485,7 +485,11 @@ export class ExtHostChatSessions extends Disposable implements ExtHostChatSessio
|
||||
|
||||
if (provider.onDidChangeChatSessionOptions) {
|
||||
disposables.add(provider.onDidChangeChatSessionOptions(evt => {
|
||||
this._proxy.$onDidChangeChatSessionOptions(handle, evt.resource, evt.updates);
|
||||
const updates: Record<string, string | IChatSessionProviderOptionItem> = Object.create(null);
|
||||
for (const update of evt.updates) {
|
||||
updates[update.optionId] = update.value;
|
||||
}
|
||||
this._proxy.$onDidChangeChatSessionOptions(handle, evt.resource, updates);
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -568,7 +572,7 @@ export class ExtHostChatSessions extends Disposable implements ExtHostChatSessio
|
||||
};
|
||||
}
|
||||
|
||||
async $provideHandleOptionsChange(handle: number, sessionResourceComponents: UriComponents, updates: ReadonlyArray<{ optionId: string; value: string | IChatSessionProviderOptionItem | undefined }>, token: CancellationToken): Promise<void> {
|
||||
async $provideHandleOptionsChange(handle: number, sessionResourceComponents: UriComponents, updates: Record<string, string | IChatSessionProviderOptionItem | undefined>, token: CancellationToken): Promise<void> {
|
||||
const sessionResource = URI.revive(sessionResourceComponents);
|
||||
const provider = this._chatSessionContentProviders.get(handle);
|
||||
if (!provider) {
|
||||
@@ -582,11 +586,11 @@ export class ExtHostChatSessions extends Disposable implements ExtHostChatSessio
|
||||
}
|
||||
|
||||
try {
|
||||
const updatesToSend = updates.map(update => ({
|
||||
optionId: update.optionId,
|
||||
value: update.value === undefined ? undefined : (typeof update.value === 'string' ? update.value : update.value.id)
|
||||
const updatesToSend = Object.entries(updates).map(([optionId, value]) => ({
|
||||
optionId,
|
||||
value: value === undefined ? undefined : (typeof value === 'string' ? value : value.id)
|
||||
}));
|
||||
await provider.provider.provideHandleOptionsChange(sessionResource, updatesToSend, token);
|
||||
provider.provider.provideHandleOptionsChange(sessionResource, updatesToSend, token);
|
||||
} catch (error) {
|
||||
this._logService.error(`Error calling provideHandleOptionsChange for handle ${handle}, sessionResource ${sessionResource}:`, error);
|
||||
}
|
||||
@@ -831,7 +835,7 @@ export class ExtHostChatSessions extends Disposable implements ExtHostChatSessio
|
||||
await controllerData.controller.refreshHandler(token);
|
||||
}
|
||||
|
||||
async $newChatSessionItem(handle: number, request: IChatNewSessionRequest, token: CancellationToken): Promise<ReturnType<typeof typeConvert.ChatSessionItem.from> | undefined> {
|
||||
async $newChatSessionItem(handle: number, request: IChatNewSessionRequestDto, token: CancellationToken): Promise<ReturnType<typeof typeConvert.ChatSessionItem.from> | undefined> {
|
||||
const controllerData = this._chatSessionItemControllers.get(handle);
|
||||
if (!controllerData) {
|
||||
this._logService.warn(`No controller found for handle ${handle}`);
|
||||
|
||||
@@ -34,7 +34,7 @@ import { ExtHostChatSessions } from '../../common/extHostChatSessions.js';
|
||||
import { ExtHostCommands } from '../../common/extHostCommands.js';
|
||||
import { ExtHostLanguageModels } from '../../common/extHostLanguageModels.js';
|
||||
import * as extHostTypes from '../../common/extHostTypes.js';
|
||||
import { ExtHostChatSessionsShape, IChatProgressDto, IChatSessionProviderOptions } from '../../common/extHost.protocol.js';
|
||||
import { ChatSessionDto, ExtHostChatSessionsShape, IChatProgressDto, IChatSessionProviderOptions } from '../../common/extHost.protocol.js';
|
||||
import { IExtHostAuthentication } from '../../common/extHostAuthentication.js';
|
||||
import { IExtHostTelemetry } from '../../common/extHostTelemetry.js';
|
||||
import { ILabelService } from '../../../../platform/label/common/label.js';
|
||||
@@ -744,11 +744,14 @@ suite('MainThreadChatSessions', function () {
|
||||
|
||||
mainThread.$registerChatSessionContentProvider(handle, sessionScheme);
|
||||
|
||||
const sessionContent = {
|
||||
const sessionContent: ChatSessionDto = {
|
||||
id: 'test-session',
|
||||
resource: URI.parse(`${sessionScheme}:/test-session`),
|
||||
history: [],
|
||||
hasActiveResponseCallback: false,
|
||||
hasRequestHandler: false,
|
||||
hasForkHandler: false,
|
||||
supportsInterruption: false,
|
||||
options: {
|
||||
'models': 'gpt-4'
|
||||
}
|
||||
@@ -770,7 +773,7 @@ suite('MainThreadChatSessions', function () {
|
||||
const call = (proxy.$provideHandleOptionsChange as sinon.SinonStub).firstCall;
|
||||
assert.strictEqual(call.args[0], handle);
|
||||
assert.deepStrictEqual(call.args[1], resource);
|
||||
assert.deepStrictEqual(call.args[2], [{ optionId: 'models', value: 'gpt-4-turbo' }]);
|
||||
assert.deepStrictEqual(call.args[2], { models: 'gpt-4-turbo' });
|
||||
|
||||
mainThread.$unregisterChatSessionContentProvider(handle);
|
||||
});
|
||||
@@ -787,9 +790,9 @@ suite('MainThreadChatSessions', function () {
|
||||
|
||||
// Attempt to notify option change for an unregistered scheme
|
||||
// This should not throw, but also should not call the proxy
|
||||
chatSessionsService.updateSessionOptions(resource, [
|
||||
{ optionId: 'models', value: 'gpt-4-turbo' }
|
||||
]);
|
||||
chatSessionsService.updateSessionOptions(resource, new Map([
|
||||
['models', 'gpt-4-turbo']
|
||||
]));
|
||||
|
||||
// Verify the extension was NOT notified (no provider registered)
|
||||
assert.strictEqual((proxy.$provideHandleOptionsChange as sinon.SinonStub).callCount, 0);
|
||||
|
||||
@@ -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, IChatSessionItemsDelta, IChatSessionOptionsChangeEvent, IChatSessionProviderOptionGroup, IChatSessionProviderOptionItem, IChatSessionRequestHistoryItem, IChatSessionsExtensionPoint, IChatSessionsService, isSessionInProgressStatus, ResolvedChatSessionsExtensionPoint } from '../../common/chatSessionsService.js';
|
||||
import { ChatSessionOptionsMap, IChatNewSessionRequest, IChatSession, IChatSessionContentProvider, IChatSessionItem, IChatSessionItemController, IChatSessionItemsDelta, IChatSessionOptionsChangeEvent, IChatSessionProviderOptionGroup, IChatSessionProviderOptionItem, IChatSessionRequestHistoryItem, IChatSessionsExtensionPoint, IChatSessionsService, isSessionInProgressStatus, ReadonlyChatSessionOptionsMap, 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';
|
||||
@@ -235,7 +235,7 @@ const extensionPoint = ExtensionsRegistry.registerExtensionPoint<IChatSessionsEx
|
||||
|
||||
class ContributedChatSessionData extends Disposable {
|
||||
|
||||
private readonly _optionsCache: Map<string /* 'models' */, string | IChatSessionProviderOptionItem>;
|
||||
private readonly _optionsCache: ChatSessionOptionsMap;
|
||||
public getOption(optionId: string): string | IChatSessionProviderOptionItem | undefined {
|
||||
return this._optionsCache.get(optionId);
|
||||
}
|
||||
@@ -250,17 +250,12 @@ class ContributedChatSessionData extends Disposable {
|
||||
readonly session: IChatSession,
|
||||
readonly chatSessionType: string,
|
||||
readonly resource: URI,
|
||||
readonly options: Record<string, string | IChatSessionProviderOptionItem> | undefined,
|
||||
readonly options: ReadonlyChatSessionOptionsMap | undefined,
|
||||
private readonly onWillDispose: (resource: URI) => void
|
||||
) {
|
||||
super();
|
||||
|
||||
this._optionsCache = new Map<string, string | IChatSessionProviderOptionItem>();
|
||||
if (options) {
|
||||
for (const [key, value] of Object.entries(options)) {
|
||||
this._optionsCache.set(key, value);
|
||||
}
|
||||
}
|
||||
this._optionsCache = new Map(options);
|
||||
|
||||
this._register(this.session.onWillDispose(() => {
|
||||
this.onWillDispose(this.resource);
|
||||
@@ -301,8 +296,8 @@ export class ChatSessionsService extends Disposable implements IChatSessionsServ
|
||||
public get onDidChangeOptionGroups() { return this._onDidChangeOptionGroups.event; }
|
||||
|
||||
private readonly inProgressMap: Map<string, number> = new Map();
|
||||
private readonly _sessionTypeOptions: Map<string, IChatSessionProviderOptionGroup[]> = new Map();
|
||||
private readonly _sessionTypeNewSessionOptions: Map<string, Record<string, string | IChatSessionProviderOptionItem>> = new Map();
|
||||
private readonly _sessionTypeOptions = new Map<string, IChatSessionProviderOptionGroup[]>();
|
||||
private readonly _sessionTypeNewSessionOptions = new Map</* sessionType */string, ChatSessionOptionsMap>();
|
||||
|
||||
private readonly _sessions = new ResourceMap<ContributedChatSessionData>();
|
||||
private readonly _resourceAliases = new ResourceMap<URI>(); // real resource -> untitled resource
|
||||
@@ -1073,8 +1068,10 @@ export class ChatSessionsService extends Disposable implements IChatSessionsServ
|
||||
session = await raceCancellationError(provider.provideChatSessionContent(sessionResource, token), token);
|
||||
}
|
||||
|
||||
for (const [optionId, value] of Object.entries(session.options ?? {})) {
|
||||
this.setSessionOption(sessionResource, optionId, value);
|
||||
if (session.options) {
|
||||
for (const [optionId, value] of session.options) {
|
||||
this.setSessionOption(sessionResource, optionId, value);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure another session wasn't created while we were awaiting the provider
|
||||
@@ -1095,8 +1092,7 @@ export class ChatSessionsService extends Disposable implements IChatSessionsServ
|
||||
|
||||
// Make sure any listeners are aware of the new session and its options
|
||||
if (session.options) {
|
||||
const updates = Object.entries(session.options).map(([optionId, value]) => ({ optionId, value }));
|
||||
this._onDidChangeSessionOptions.fire({ sessionResource, updates });
|
||||
this._onDidChangeSessionOptions.fire({ sessionResource, updates: session.options });
|
||||
}
|
||||
|
||||
return session;
|
||||
@@ -1104,7 +1100,7 @@ export class ChatSessionsService extends Disposable implements IChatSessionsServ
|
||||
|
||||
public hasAnySessionOptions(sessionResource: URI): boolean {
|
||||
const session = this._sessions.get(this._resolveResource(sessionResource));
|
||||
return !!session && !!session.options && Object.keys(session.options).length > 0;
|
||||
return !!session && !!session.options && session.options.size > 0;
|
||||
}
|
||||
|
||||
public getSessionOptions(sessionResource: URI): Map<string, string> | undefined {
|
||||
@@ -1125,17 +1121,17 @@ export class ChatSessionsService extends Disposable implements IChatSessionsServ
|
||||
}
|
||||
|
||||
public setSessionOption(sessionResource: URI, optionId: string, value: string | IChatSessionProviderOptionItem): boolean {
|
||||
return this.updateSessionOptions(sessionResource, [{ optionId, value }]);
|
||||
return this.updateSessionOptions(sessionResource, new Map([[optionId, value]]));
|
||||
}
|
||||
|
||||
public updateSessionOptions(sessionResource: URI, updates: ReadonlyArray<{ optionId: string; value: string | IChatSessionProviderOptionItem }>): boolean {
|
||||
public updateSessionOptions(sessionResource: URI, updates: ReadonlyChatSessionOptionsMap): boolean {
|
||||
const session = this._sessions.get(this._resolveResource(sessionResource));
|
||||
if (!session) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let didChange = false;
|
||||
for (const { optionId, value } of updates) {
|
||||
for (const [optionId, value] of updates) {
|
||||
const existingValue = session.getOption(optionId);
|
||||
if (existingValue !== value) {
|
||||
session.setOption(optionId, value);
|
||||
@@ -1181,12 +1177,12 @@ export class ChatSessionsService extends Disposable implements IChatSessionsServ
|
||||
return this._sessionTypeOptions.get(chatSessionType);
|
||||
}
|
||||
|
||||
public getNewSessionOptionsForSessionType(chatSessionType: string): Record<string, string | IChatSessionProviderOptionItem> | undefined {
|
||||
return this._sessionTypeNewSessionOptions.get(chatSessionType);
|
||||
public getNewSessionOptionsForSessionType(chatSessionType: string): ReadonlyChatSessionOptionsMap | undefined {
|
||||
return new Map(this._sessionTypeNewSessionOptions.get(chatSessionType));
|
||||
}
|
||||
|
||||
public setNewSessionOptionsForSessionType(chatSessionType: string, options: Record<string, string | IChatSessionProviderOptionItem>): void {
|
||||
this._sessionTypeNewSessionOptions.set(chatSessionType, options);
|
||||
public setNewSessionOptionsForSessionType(chatSessionType: string, options: ReadonlyChatSessionOptionsMap): void {
|
||||
this._sessionTypeNewSessionOptions.set(chatSessionType, new Map(options));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1293,7 +1289,7 @@ export enum ChatSessionPosition {
|
||||
type NewChatSessionSendOptions = {
|
||||
readonly prompt: string;
|
||||
readonly attachedContext?: IChatRequestVariableEntry[];
|
||||
readonly initialSessionOptions?: ReadonlyArray<{ optionId: string; value: string | { id: string; name: string } }>;
|
||||
readonly initialSessionOptions?: ReadonlyChatSessionOptionsMap;
|
||||
};
|
||||
|
||||
export type NewChatSessionOpenOptions = {
|
||||
|
||||
@@ -706,7 +706,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
|
||||
if (needsUpdate) {
|
||||
this.chatSessionsService.updateSessionOptions(
|
||||
ctx.chatSessionResource,
|
||||
[{ optionId: agentOptionId, value: mode.isBuiltin ? '' : modeName }]
|
||||
new Map([[agentOptionId, mode.isBuiltin ? '' : modeName]])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import { IChatRequestVariableEntry } from '../attachments/chatVariableEntries.js
|
||||
import { IChatRequestVariableValue } from '../attachments/chatVariables.js';
|
||||
import { ChatAgentLocation } from '../constants.js';
|
||||
import { IPreparedToolInvocation, IToolConfirmationMessages, IToolResult, IToolResultInputOutputDetails, ToolDataSource } from '../tools/languageModelToolsService.js';
|
||||
import { ReadonlyChatSessionOptionsMap } from '../chatSessionsService.js';
|
||||
|
||||
export interface IChatRequest {
|
||||
message: string;
|
||||
@@ -1541,7 +1542,7 @@ export interface IChatService {
|
||||
|
||||
export interface IChatSessionContext {
|
||||
readonly chatSessionResource: URI;
|
||||
readonly initialSessionOptions?: ReadonlyArray<{ optionId: string; value: string | { id: string; name: string } }>;
|
||||
readonly initialSessionOptions?: ReadonlyChatSessionOptionsMap;
|
||||
}
|
||||
|
||||
export const KEYWORD_ACTIVIATION_SETTING_ID = 'accessibility.voice.keywordActivation';
|
||||
|
||||
@@ -830,8 +830,7 @@ export class ChatService extends Disposable implements IChatService {
|
||||
|
||||
// Capture session options before loading the remote session,
|
||||
// since the alias registration below may change the lookup.
|
||||
const sessionOptions = this.chatSessionService.getSessionOptions(sessionResource);
|
||||
const initialSessionOptions = sessionOptions ? [...sessionOptions].map(([optionId, value]) => ({ optionId, value })) : undefined;
|
||||
const initialSessionOptions = this.chatSessionService.getSessionOptions(sessionResource);
|
||||
|
||||
const newItem = await this.chatSessionService.createNewChatSessionItem(getChatSessionType(sessionResource), { prompt: requestText, command: commandPart?.text, initialSessionOptions }, CancellationToken.None);
|
||||
if (newItem) {
|
||||
@@ -847,7 +846,7 @@ export class ChatService extends Disposable implements IChatService {
|
||||
// so that the agent receives them when invoked.
|
||||
model.setContributedChatSession({
|
||||
chatSessionResource: newItem.resource,
|
||||
initialSessionOptions: sessionOptions ? [...sessionOptions].map(([optionId, value]) => ({ optionId, value })) : undefined,
|
||||
initialSessionOptions: initialSessionOptions,
|
||||
});
|
||||
|
||||
sessionResource = newItem.resource;
|
||||
|
||||
@@ -174,11 +174,8 @@ export interface IChatSession extends IDisposable {
|
||||
|
||||
readonly history: readonly IChatSessionHistoryItem[];
|
||||
|
||||
/**
|
||||
* Session options as key-value pairs. Keys correspond to option group IDs (e.g., 'models', 'subagents')
|
||||
* and values are either the selected option item IDs (string) or full option items (for locked state).
|
||||
*/
|
||||
readonly options?: Record<string, string | IChatSessionProviderOptionItem>;
|
||||
|
||||
readonly options?: ReadonlyChatSessionOptionsMap;
|
||||
|
||||
readonly progressObs?: IObservable<IChatProgress[]>;
|
||||
readonly isCompleteObs?: IObservable<boolean>;
|
||||
@@ -217,7 +214,7 @@ export interface IChatNewSessionRequest {
|
||||
readonly prompt: string;
|
||||
readonly command?: string;
|
||||
|
||||
readonly initialSessionOptions?: ReadonlyArray<{ optionId: string; value: string | IChatSessionProviderOptionItem }>;
|
||||
readonly initialSessionOptions?: ReadonlyChatSessionOptionsMap;
|
||||
}
|
||||
|
||||
export interface IChatSessionItemsDelta {
|
||||
@@ -238,13 +235,47 @@ export interface IChatSessionItemController {
|
||||
|
||||
export interface IChatSessionOptionsChangeEvent {
|
||||
readonly sessionResource: URI;
|
||||
readonly updates: ReadonlyArray<{ optionId: string; value: string | IChatSessionProviderOptionItem }>;
|
||||
readonly updates: ReadonlyMap<string, string | IChatSessionProviderOptionItem | undefined>;
|
||||
}
|
||||
|
||||
export type ResolvedChatSessionsExtensionPoint = Omit<IChatSessionsExtensionPoint, 'icon'> & {
|
||||
readonly icon: ThemeIcon | URI | undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Session options as key-value pairs.
|
||||
*
|
||||
* Keys correspond to option group IDs (e.g., 'models', 'subagents') and values are either the selected option item IDs (string) or full option items (for locked state).
|
||||
*/
|
||||
export type ChatSessionOptionsMap = Map<string, string | IChatSessionProviderOptionItem>;
|
||||
|
||||
export namespace ChatSessionOptionsMap {
|
||||
export function fromRecord(obj: { [key: string]: string | IChatSessionProviderOptionItem }): ChatSessionOptionsMap {
|
||||
return new Map(Object.entries(obj));
|
||||
}
|
||||
|
||||
export function toRecord(map: ReadonlyChatSessionOptionsMap): Record<string, string | IChatSessionProviderOptionItem> {
|
||||
const record: Record<string, string | IChatSessionProviderOptionItem> = Object.create(null);
|
||||
for (const [key, value] of map) {
|
||||
record[key] = value;
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
export function toStrValueArray(map: ReadonlyChatSessionOptionsMap | undefined): Array<{ optionId: string; value: string }> | undefined {
|
||||
if (!map) {
|
||||
return undefined;
|
||||
}
|
||||
return Array.from(map, ([optionId, value]) => ({ optionId, value: typeof value === 'string' ? value : value.id }));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Readonly version of {@link ChatSessionOptionsMap}
|
||||
*/
|
||||
export type ReadonlyChatSessionOptionsMap = ReadonlyMap<string, string | IChatSessionProviderOptionItem>;
|
||||
|
||||
|
||||
export const IChatSessionsService = createDecorator<IChatSessionsService>('chatSessionsService');
|
||||
|
||||
export interface IChatSessionsService {
|
||||
@@ -299,10 +330,10 @@ export interface IChatSessionsService {
|
||||
getOrCreateChatSession(sessionResource: URI, token: CancellationToken): Promise<IChatSession>;
|
||||
|
||||
hasAnySessionOptions(sessionResource: URI): boolean;
|
||||
getSessionOptions(sessionResource: URI): Map<string, string> | undefined;
|
||||
getSessionOptions(sessionResource: URI): ReadonlyChatSessionOptionsMap | undefined;
|
||||
getSessionOption(sessionResource: URI, optionId: string): string | IChatSessionProviderOptionItem | undefined;
|
||||
setSessionOption(sessionResource: URI, optionId: string, value: string | IChatSessionProviderOptionItem): boolean;
|
||||
updateSessionOptions(sessionResource: URI, updates: ReadonlyArray<{ optionId: string; value: string | IChatSessionProviderOptionItem }>): boolean;
|
||||
updateSessionOptions(sessionResource: URI, updates: ReadonlyChatSessionOptionsMap): boolean;
|
||||
|
||||
/**
|
||||
* Fired when options for a chat session change.
|
||||
@@ -350,8 +381,8 @@ export interface IChatSessionsService {
|
||||
getOptionGroupsForSessionType(chatSessionType: string): IChatSessionProviderOptionGroup[] | undefined;
|
||||
setOptionGroupsForSessionType(chatSessionType: string, handle: number, optionGroups?: IChatSessionProviderOptionGroup[]): void;
|
||||
|
||||
getNewSessionOptionsForSessionType(chatSessionType: string): Record<string, string | IChatSessionProviderOptionItem> | undefined;
|
||||
setNewSessionOptionsForSessionType(chatSessionType: string, options: Record<string, string | IChatSessionProviderOptionItem>): void;
|
||||
getNewSessionOptionsForSessionType(chatSessionType: string): ReadonlyChatSessionOptionsMap | undefined;
|
||||
setNewSessionOptionsForSessionType(chatSessionType: string, options: ReadonlyChatSessionOptionsMap): void;
|
||||
|
||||
getInProgressSessionDescription(chatModel: IChatModel): string | undefined;
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ import { MockChatVariablesService } from '../mockChatVariables.js';
|
||||
import { MockPromptsService } from '../promptSyntax/service/mockPromptsService.js';
|
||||
import { MockLanguageModelToolsService } from '../tools/mockLanguageModelToolsService.js';
|
||||
import { MockChatService } from './mockChatService.js';
|
||||
import { IChatSessionsService } from '../../../common/chatSessionsService.js';
|
||||
import { ChatSessionOptionsMap, IChatSessionsService } from '../../../common/chatSessionsService.js';
|
||||
import { MockChatSessionsService } from '../mockChatSessionsService.js';
|
||||
|
||||
const chatAgentWithUsedContextId = 'ChatProviderWithUsedContext';
|
||||
@@ -937,7 +937,7 @@ suite('ChatService', () => {
|
||||
assert.ok(newModel, 'New model should exist at the real resource');
|
||||
assert.ok(newModel.contributedChatSession, 'New model should have contributedChatSession');
|
||||
assert.deepStrictEqual(
|
||||
newModel.contributedChatSession?.initialSessionOptions?.map(o => ({ optionId: o.optionId, value: o.value })),
|
||||
ChatSessionOptionsMap.toStrValueArray(newModel.contributedChatSession?.initialSessionOptions),
|
||||
[
|
||||
{ optionId: 'model', value: 'claude-3.5-sonnet' },
|
||||
{ optionId: 'repo', value: 'my-repo' },
|
||||
|
||||
@@ -9,7 +9,7 @@ import { IDisposable } from '../../../../../base/common/lifecycle.js';
|
||||
import { ResourceMap } from '../../../../../base/common/map.js';
|
||||
import { ThemeIcon } from '../../../../../base/common/themables.js';
|
||||
import { URI } from '../../../../../base/common/uri.js';
|
||||
import { IChatNewSessionRequest, IChatSession, IChatSessionContentProvider, IChatSessionItem, IChatSessionItemController, IChatSessionItemsDelta, IChatSessionOptionsChangeEvent, IChatSessionProviderOptionGroup, IChatSessionProviderOptionItem, IChatSessionRequestHistoryItem, IChatSessionsExtensionPoint, IChatSessionsService, ResolvedChatSessionsExtensionPoint } from '../../common/chatSessionsService.js';
|
||||
import { ReadonlyChatSessionOptionsMap, IChatNewSessionRequest, IChatSession, IChatSessionContentProvider, IChatSessionItem, IChatSessionItemController, IChatSessionItemsDelta, IChatSessionOptionsChangeEvent, IChatSessionProviderOptionGroup, IChatSessionRequestHistoryItem, IChatSessionsExtensionPoint, IChatSessionsService, ResolvedChatSessionsExtensionPoint, ChatSessionOptionsMap } from '../../common/chatSessionsService.js';
|
||||
import { IChatModel } from '../../common/model/chatModel.js';
|
||||
import { IChatAgentAttachmentCapabilities } from '../../common/participants/chatAgents.js';
|
||||
import { Target } from '../../common/promptSyntax/promptTypes.js';
|
||||
@@ -43,7 +43,7 @@ export class MockChatSessionsService implements IChatSessionsService {
|
||||
private contentProviders = new Map<string, IChatSessionContentProvider>();
|
||||
private contributions: IChatSessionsExtensionPoint[] = [];
|
||||
private optionGroups = new Map<string, IChatSessionProviderOptionGroup[]>();
|
||||
private sessionOptions = new ResourceMap<Map<string, string>>();
|
||||
private sessionOptions = new ResourceMap<ChatSessionOptionsMap>();
|
||||
private inProgress = new Map<string, number>();
|
||||
|
||||
// For testing: allow triggering events
|
||||
@@ -172,33 +172,34 @@ export class MockChatSessionsService implements IChatSessionsService {
|
||||
}
|
||||
}
|
||||
|
||||
getNewSessionOptionsForSessionType(_chatSessionType: string): Record<string, string | IChatSessionProviderOptionItem> | undefined {
|
||||
getNewSessionOptionsForSessionType(_chatSessionType: string): ReadonlyChatSessionOptionsMap | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
setNewSessionOptionsForSessionType(_chatSessionType: string, _options: Record<string, string | IChatSessionProviderOptionItem>): void {
|
||||
setNewSessionOptionsForSessionType(_chatSessionType: string, _options: ReadonlyChatSessionOptionsMap): void {
|
||||
// noop
|
||||
}
|
||||
|
||||
getSessionOptions(sessionResource: URI): Map<string, string> | undefined {
|
||||
getSessionOptions(sessionResource: URI): ReadonlyChatSessionOptionsMap | undefined {
|
||||
const options = this.sessionOptions.get(sessionResource);
|
||||
return options && options.size > 0 ? options : undefined;
|
||||
}
|
||||
|
||||
getSessionOption(sessionResource: URI, optionId: string): string | undefined {
|
||||
return this.sessionOptions.get(sessionResource)?.get(optionId);
|
||||
const value = this.sessionOptions.get(sessionResource)?.get(optionId);
|
||||
return typeof value === 'string' ? value : value?.id;
|
||||
}
|
||||
|
||||
setSessionOption(sessionResource: URI, optionId: string, value: string): boolean {
|
||||
return this.updateSessionOptions(sessionResource, [{ optionId, value }]);
|
||||
return this.updateSessionOptions(sessionResource, new Map([[optionId, value]]));
|
||||
}
|
||||
|
||||
updateSessionOptions(sessionResource: URI, updates: ReadonlyArray<{ optionId: string; value: string }>): boolean {
|
||||
updateSessionOptions(sessionResource: URI, updates: ReadonlyChatSessionOptionsMap): boolean {
|
||||
if (!this.sessionOptions.has(sessionResource)) {
|
||||
this.sessionOptions.set(sessionResource, new Map());
|
||||
}
|
||||
for (const update of updates) {
|
||||
this.sessionOptions.get(sessionResource)!.set(update.optionId, update.value);
|
||||
for (const [optionId, value] of updates) {
|
||||
this.sessionOptions.get(sessionResource)!.set(optionId, value);
|
||||
}
|
||||
|
||||
this._onDidChangeSessionOptions.fire({ sessionResource, updates });
|
||||
|
||||
Reference in New Issue
Block a user