diff --git a/src/vs/workbench/api/common/extHostLanguageModels.ts b/src/vs/workbench/api/common/extHostLanguageModels.ts index dc5cc3d8bca..b82b1bd992a 100644 --- a/src/vs/workbench/api/common/extHostLanguageModels.ts +++ b/src/vs/workbench/api/common/extHostLanguageModels.ts @@ -27,6 +27,7 @@ import { IExtHostAuthentication } from './extHostAuthentication.js'; import { IExtHostRpcService } from './extHostRpcService.js'; import * as typeConvert from './extHostTypeConverters.js'; import * as extHostTypes from './extHostTypes.js'; +import { ChatAgentLocation } from '../../contrib/chat/common/constants.js'; export interface IExtHostLanguageModels extends ExtHostLanguageModels { } @@ -189,6 +190,22 @@ export class ExtHostLanguageModels implements ExtHostLanguageModelsShape { checkProposedApiEnabled(data.extension, 'chatProvider'); } + const isDefaultForLocation: { [K in ChatAgentLocation]?: boolean } = {}; + if (isProposedApiEnabled(data.extension, 'chatProvider')) { + if (m.isDefault === true) { + for (const key of Object.values(ChatAgentLocation)) { + if (typeof key === 'string') { + isDefaultForLocation[key as ChatAgentLocation] = true; + } + } + } else if (typeof m.isDefault === 'object') { + for (const key of Object.keys(m.isDefault)) { + const enumKey = parseInt(key) as extHostTypes.ChatLocation; + isDefaultForLocation[typeConvert.ChatLocation.from(enumKey)] = m.isDefault[enumKey]; + } + } + } + return { metadata: { extension: data.extension.identifier, @@ -202,7 +219,7 @@ export class ExtHostLanguageModels implements ExtHostLanguageModelsShape { maxInputTokens: m.maxInputTokens, maxOutputTokens: m.maxOutputTokens, auth, - isDefault: m.isDefault, + isDefaultForLocation, isUserSelectable: m.isUserSelectable, statusIcon: m.statusIcon, modelPickerCategory: m.category ?? DEFAULT_MODEL_PICKER_CATEGORY, @@ -333,7 +350,7 @@ export class ExtHostLanguageModels implements ExtHostLanguageModelsShape { } for (const [modelIdentifier, modelData] of this._localModels) { - if (modelData.metadata.isDefault) { + if (modelData.metadata.isDefaultForLocation[ChatAgentLocation.Chat]) { defaultModelId = modelIdentifier; break; } diff --git a/src/vs/workbench/contrib/chat/browser/chatSetup/chatSetupProviders.ts b/src/vs/workbench/contrib/chat/browser/chatSetup/chatSetupProviders.ts index 0c3e8b3a134..37dbdf9e408 100644 --- a/src/vs/workbench/contrib/chat/browser/chatSetup/chatSetupProviders.ts +++ b/src/vs/workbench/contrib/chat/browser/chatSetup/chatSetupProviders.ts @@ -400,7 +400,7 @@ export class SetupAgent extends Disposable implements IChatAgentImplementation { for (const id of languageModelsService.getLanguageModelIds()) { const model = languageModelsService.lookupLanguageModel(id); - if (model?.isDefault) { + if (model?.isDefaultForLocation[ChatAgentLocation.Chat]) { return true; } } diff --git a/src/vs/workbench/contrib/chat/browser/widget/input/chatInputPart.ts b/src/vs/workbench/contrib/chat/browser/widget/input/chatInputPart.ts index b5b4ce7d945..9669d88db00 100644 --- a/src/vs/workbench/contrib/chat/browser/widget/input/chatInputPart.ts +++ b/src/vs/workbench/contrib/chat/browser/widget/input/chatInputPart.ts @@ -115,10 +115,12 @@ import { resizeImage } from '../../chatImageUtils.js'; import { IModelPickerDelegate, ModelPickerActionItem } from './modelPickerActionItem.js'; import { IModePickerDelegate, ModePickerActionItem } from './modePickerActionItem.js'; import { SearchableOptionPickerActionItem } from '../../chatSessions/searchableOptionPickerActionItemtest.js'; +import { mixin } from '../../../../../../base/common/objects.js'; const $ = dom.$; const INPUT_EDITOR_MAX_HEIGHT = 250; +const CachedLanguageModelsKey = 'chat.cachedLanguageModels.v2'; export interface IChatInputStyles { overlayBackground: string; @@ -152,7 +154,18 @@ const emptyInputState = observableMemento({ defaultValue: undefined, key: 'chat.untitledInputState', toStorage: JSON.stringify, - fromStorage: JSON.parse, + fromStorage(value) { + const obj = JSON.parse(value) as IChatModelInputState; + if (obj.selectedModel && !obj.selectedModel.metadata.isDefaultForLocation) { + // Migrate old `isDefault` to `isDefaultForLocation` + type OldILanguageModelChatMetadata = ILanguageModelChatMetadata & { isDefault?: boolean }; + const oldIsDefault = (obj.selectedModel.metadata as OldILanguageModelChatMetadata).isDefault; + const isDefaultForLocation = { [ChatAgentLocation.Chat]: Boolean(oldIsDefault) }; + mixin(obj.selectedModel.metadata, { isDefaultForLocation: isDefaultForLocation } satisfies Partial); + delete (obj.selectedModel.metadata as OldILanguageModelChatMetadata).isDefault; + } + return obj; + }, }); export class ChatInputPart extends Disposable implements IHistoryNavigationWidget { @@ -553,8 +566,8 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge // Remove vendor from cache since the models changed and what is stored is no longer valid // TODO @lramos15 - The cache should be less confusing since we have the LM Service cache + the view cache interacting weirdly this.storageService.store( - 'chat.cachedLanguageModels', - this.storageService.getObject('chat.cachedLanguageModels', StorageScope.APPLICATION, []).filter(m => !m.identifier.startsWith(vendor)), + CachedLanguageModelsKey, + this.storageService.getObject(CachedLanguageModelsKey, StorageScope.APPLICATION, []).filter(m => !m.identifier.startsWith(vendor)), StorageScope.APPLICATION, StorageTarget.MACHINE ); @@ -621,7 +634,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge const model = this.getModels().find(m => m.identifier === persistedSelection); if (model) { // Only restore the model if it wasn't the default at the time of storing or it is now the default - if (!persistedAsDefault || model.metadata.isDefault) { + if (!persistedAsDefault || model.metadata.isDefaultForLocation[this.location]) { this.setCurrentLanguageModel(model); this.checkModelSupported(); } @@ -632,7 +645,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge this._waitForPersistedLanguageModel.clear(); // Only restore the model if it wasn't the default at the time of storing or it is now the default - if (!persistedAsDefault || persistedModel.isDefault) { + if (!persistedAsDefault || persistedModel.isDefaultForLocation[this.location]) { if (persistedModel.isUserSelectable) { this.setCurrentLanguageModel({ metadata: persistedModel, identifier: persistedSelection }); this.checkModelSupported(); @@ -929,7 +942,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge // Store as global user preference (session-specific state is in the model's inputModel) this.storageService.store(this.getSelectedModelStorageKey(), model.identifier, StorageScope.APPLICATION, StorageTarget.USER); - this.storageService.store(this.getSelectedModelIsDefaultStorageKey(), !!model.metadata.isDefault, StorageScope.APPLICATION, StorageTarget.USER); + this.storageService.store(this.getSelectedModelIsDefaultStorageKey(), !!model.metadata.isDefaultForLocation[this.location], StorageScope.APPLICATION, StorageTarget.USER); this._onDidChangeCurrentLanguageModel.fire(model); @@ -986,13 +999,13 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge } private getModels(): ILanguageModelChatMetadataAndIdentifier[] { - const cachedModels = this.storageService.getObject('chat.cachedLanguageModels', StorageScope.APPLICATION, []); + const cachedModels = this.storageService.getObject(CachedLanguageModelsKey, StorageScope.APPLICATION, []); let models = this.languageModelsService.getLanguageModelIds() .map(modelId => ({ identifier: modelId, metadata: this.languageModelsService.lookupLanguageModel(modelId)! })); - if (models.length === 0 || models.some(m => m.metadata.isDefault) === false) { + if (models.length === 0 || models.some(m => m.metadata.isDefaultForLocation[this.location]) === false) { models = cachedModels; } else { - this.storageService.store('chat.cachedLanguageModels', models, StorageScope.APPLICATION, StorageTarget.MACHINE); + this.storageService.store(CachedLanguageModelsKey, models, StorageScope.APPLICATION, StorageTarget.MACHINE); } models.sort((a, b) => a.metadata.name.localeCompare(b.metadata.name)); return models.filter(entry => entry.metadata?.isUserSelectable && this.modelSupportedForDefaultAgent(entry) && this.modelSupportedForInlineChat(entry)); @@ -1000,7 +1013,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge private setCurrentLanguageModelToDefault() { const allModels = this.getModels(); - const defaultModel = allModels.find(m => m.metadata.isDefault) || allModels.find(m => m.metadata.isUserSelectable); + const defaultModel = allModels.find(m => m.metadata.isDefaultForLocation[this.location]) || allModels.find(m => m.metadata.isUserSelectable); if (defaultModel) { this.setCurrentLanguageModel(defaultModel); } diff --git a/src/vs/workbench/contrib/chat/common/languageModels.ts b/src/vs/workbench/contrib/chat/common/languageModels.ts index 0c698ae95bd..3c92e9646f1 100644 --- a/src/vs/workbench/contrib/chat/common/languageModels.ts +++ b/src/vs/workbench/contrib/chat/common/languageModels.ts @@ -31,6 +31,7 @@ import { IStorageService, StorageScope, StorageTarget } from '../../../../platfo import { IExtensionService } from '../../../services/extensions/common/extensions.js'; import { ExtensionsRegistry } from '../../../services/extensions/common/extensionsRegistry.js'; import { ChatContextKeys } from './actions/chatContextKeys.js'; +import { ChatAgentLocation } from './constants.js'; import { ILanguageModelsProviderGroup, ILanguageModelsConfigurationService } from './languageModelsConfiguration.js'; export const enum ChatMessageRole { @@ -178,7 +179,7 @@ export interface ILanguageModelChatMetadata { readonly maxInputTokens: number; readonly maxOutputTokens: number; - readonly isDefault?: boolean; + readonly isDefaultForLocation: { [K in ChatAgentLocation]?: boolean }; readonly isUserSelectable?: boolean; readonly statusIcon?: ThemeIcon; readonly modelPickerCategory: { label: string; order: number } | undefined; diff --git a/src/vs/workbench/contrib/chat/test/browser/chatManagement/chatModelsViewModel.test.ts b/src/vs/workbench/contrib/chat/test/browser/chatManagement/chatModelsViewModel.test.ts index 6b0adcdd5a5..87a4fc80080 100644 --- a/src/vs/workbench/contrib/chat/test/browser/chatManagement/chatModelsViewModel.test.ts +++ b/src/vs/workbench/contrib/chat/test/browser/chatManagement/chatModelsViewModel.test.ts @@ -15,6 +15,7 @@ import { ExtensionIdentifier } from '../../../../../../platform/extensions/commo import { IStringDictionary } from '../../../../../../base/common/collections.js'; import { ILanguageModelsConfigurationService } from '../../../common/languageModelsConfiguration.js'; import { mock } from '../../../../../../base/test/common/mock.js'; +import { ChatAgentLocation } from '../../../common/constants.js'; class MockLanguageModelsService implements ILanguageModelsService { _serviceBrand: undefined; @@ -214,6 +215,9 @@ suite('ChatModelsViewModel', () => { toolCalling: true, vision: true, agentMode: false + }, + isDefaultForLocation: { + [ChatAgentLocation.Chat]: true } }); @@ -232,6 +236,9 @@ suite('ChatModelsViewModel', () => { toolCalling: true, vision: true, agentMode: true + }, + isDefaultForLocation: { + [ChatAgentLocation.Chat]: true } }); @@ -250,6 +257,9 @@ suite('ChatModelsViewModel', () => { toolCalling: true, vision: false, agentMode: false + }, + isDefaultForLocation: { + [ChatAgentLocation.Chat]: true } }); @@ -268,6 +278,9 @@ suite('ChatModelsViewModel', () => { toolCalling: false, vision: true, agentMode: false + }, + isDefaultForLocation: { + [ChatAgentLocation.Chat]: true } }); @@ -604,6 +617,9 @@ suite('ChatModelsViewModel', () => { toolCalling: true, vision: true, agentMode: false + }, + isDefaultForLocation: { + [ChatAgentLocation.Chat]: true } }); @@ -623,6 +639,9 @@ suite('ChatModelsViewModel', () => { toolCalling: true, vision: true, agentMode: true + }, + isDefaultForLocation: { + [ChatAgentLocation.Chat]: true } }); } @@ -708,6 +727,9 @@ suite('ChatModelsViewModel', () => { toolCalling: true, vision: false, agentMode: false + }, + isDefaultForLocation: { + [ChatAgentLocation.Chat]: true } }); @@ -734,6 +756,9 @@ suite('ChatModelsViewModel', () => { toolCalling: true, vision: false, agentMode: false + }, + isDefaultForLocation: { + [ChatAgentLocation.Chat]: true } }); @@ -843,6 +868,9 @@ suite('ChatModelsViewModel', () => { toolCalling: true, vision: false, agentMode: false + }, + isDefaultForLocation: { + [ChatAgentLocation.Chat]: true } }); diff --git a/src/vs/workbench/contrib/chat/test/browser/promptSyntax/languageProviders/promptHovers.test.ts b/src/vs/workbench/contrib/chat/test/browser/promptSyntax/languageProviders/promptHovers.test.ts index fc209823326..c4a7e74209f 100644 --- a/src/vs/workbench/contrib/chat/test/browser/promptSyntax/languageProviders/promptHovers.test.ts +++ b/src/vs/workbench/contrib/chat/test/browser/promptSyntax/languageProviders/promptHovers.test.ts @@ -14,7 +14,7 @@ import { TestInstantiationService } from '../../../../../../../platform/instanti import { workbenchInstantiationService } from '../../../../../../test/browser/workbenchTestServices.js'; import { LanguageModelToolsService } from '../../../../browser/tools/languageModelToolsService.js'; import { ChatMode, CustomChatMode, IChatModeService } from '../../../../common/chatModes.js'; -import { ChatConfiguration } from '../../../../common/constants.js'; +import { ChatAgentLocation, ChatConfiguration } from '../../../../common/constants.js'; import { ILanguageModelToolsService, IToolData, ToolDataSource } from '../../../../common/tools/languageModelToolsService.js'; import { ILanguageModelChatMetadata, ILanguageModelsService } from '../../../../common/languageModels.js'; import { PromptHoverProvider } from '../../../../common/promptSyntax/languageProviders/promptHovers.js'; @@ -53,8 +53,8 @@ suite('PromptHoverProvider', () => { instaService.set(ILanguageModelToolsService, toolService); const testModels: ILanguageModelChatMetadata[] = [ - { id: 'mae-4', name: 'MAE 4', vendor: 'olama', version: '1.0', family: 'mae', modelPickerCategory: undefined, extension: new ExtensionIdentifier('a.b'), isUserSelectable: true, maxInputTokens: 8192, maxOutputTokens: 1024, capabilities: { agentMode: true, toolCalling: true } } satisfies ILanguageModelChatMetadata, - { id: 'mae-4.1', name: 'MAE 4.1', vendor: 'copilot', version: '1.0', family: 'mae', modelPickerCategory: undefined, extension: new ExtensionIdentifier('a.b'), isUserSelectable: true, maxInputTokens: 8192, maxOutputTokens: 1024, capabilities: { agentMode: true, toolCalling: true } } satisfies ILanguageModelChatMetadata, + { id: 'mae-4', name: 'MAE 4', vendor: 'olama', version: '1.0', family: 'mae', modelPickerCategory: undefined, extension: new ExtensionIdentifier('a.b'), isUserSelectable: true, maxInputTokens: 8192, maxOutputTokens: 1024, capabilities: { agentMode: true, toolCalling: true }, isDefaultForLocation: { [ChatAgentLocation.Chat]: true } } satisfies ILanguageModelChatMetadata, + { id: 'mae-4.1', name: 'MAE 4.1', vendor: 'copilot', version: '1.0', family: 'mae', modelPickerCategory: undefined, extension: new ExtensionIdentifier('a.b'), isUserSelectable: true, maxInputTokens: 8192, maxOutputTokens: 1024, capabilities: { agentMode: true, toolCalling: true }, isDefaultForLocation: { [ChatAgentLocation.Chat]: true } } satisfies ILanguageModelChatMetadata, ]; instaService.stub(ILanguageModelsService, { diff --git a/src/vs/workbench/contrib/chat/test/browser/promptSyntax/languageProviders/promptValidator.test.ts b/src/vs/workbench/contrib/chat/test/browser/promptSyntax/languageProviders/promptValidator.test.ts index a59e2adf9ac..fc3f3f90363 100644 --- a/src/vs/workbench/contrib/chat/test/browser/promptSyntax/languageProviders/promptValidator.test.ts +++ b/src/vs/workbench/contrib/chat/test/browser/promptSyntax/languageProviders/promptValidator.test.ts @@ -18,7 +18,7 @@ import { IMarkerData, MarkerSeverity } from '../../../../../../../platform/marke import { workbenchInstantiationService } from '../../../../../../test/browser/workbenchTestServices.js'; import { LanguageModelToolsService } from '../../../../browser/tools/languageModelToolsService.js'; import { ChatMode, CustomChatMode, IChatModeService } from '../../../../common/chatModes.js'; -import { ChatConfiguration } from '../../../../common/constants.js'; +import { ChatAgentLocation, ChatConfiguration } from '../../../../common/constants.js'; import { ILanguageModelToolsService, IToolData, ToolDataSource } from '../../../../common/tools/languageModelToolsService.js'; import { ILanguageModelChatMetadata, ILanguageModelsService } from '../../../../common/languageModels.js'; import { getPromptFileExtension } from '../../../../common/promptSyntax/config/promptFileLocations.js'; @@ -112,9 +112,9 @@ suite('PromptValidator', () => { instaService.set(ILanguageModelToolsService, toolService); const testModels: ILanguageModelChatMetadata[] = [ - { id: 'mae-4', name: 'MAE 4', vendor: 'olama', version: '1.0', family: 'mae', modelPickerCategory: undefined, extension: new ExtensionIdentifier('a.b'), isUserSelectable: true, maxInputTokens: 8192, maxOutputTokens: 1024, capabilities: { agentMode: true, toolCalling: true } } satisfies ILanguageModelChatMetadata, - { id: 'mae-4.1', name: 'MAE 4.1', vendor: 'copilot', version: '1.0', family: 'mae', modelPickerCategory: undefined, extension: new ExtensionIdentifier('a.b'), isUserSelectable: true, maxInputTokens: 8192, maxOutputTokens: 1024, capabilities: { agentMode: true, toolCalling: true } } satisfies ILanguageModelChatMetadata, - { id: 'mae-3.5-turbo', name: 'MAE 3.5 Turbo', vendor: 'copilot', version: '1.0', family: 'mae', modelPickerCategory: undefined, extension: new ExtensionIdentifier('a.b'), isUserSelectable: true, maxInputTokens: 8192, maxOutputTokens: 1024 } satisfies ILanguageModelChatMetadata + { id: 'mae-4', name: 'MAE 4', vendor: 'olama', version: '1.0', family: 'mae', modelPickerCategory: undefined, extension: new ExtensionIdentifier('a.b'), isUserSelectable: true, maxInputTokens: 8192, maxOutputTokens: 1024, capabilities: { agentMode: true, toolCalling: true }, isDefaultForLocation: { [ChatAgentLocation.Chat]: true } } satisfies ILanguageModelChatMetadata, + { id: 'mae-4.1', name: 'MAE 4.1', vendor: 'copilot', version: '1.0', family: 'mae', modelPickerCategory: undefined, extension: new ExtensionIdentifier('a.b'), isUserSelectable: true, maxInputTokens: 8192, maxOutputTokens: 1024, capabilities: { agentMode: true, toolCalling: true }, isDefaultForLocation: { [ChatAgentLocation.Chat]: true } } satisfies ILanguageModelChatMetadata, + { id: 'mae-3.5-turbo', name: 'MAE 3.5 Turbo', vendor: 'copilot', version: '1.0', family: 'mae', modelPickerCategory: undefined, extension: new ExtensionIdentifier('a.b'), isUserSelectable: true, maxInputTokens: 8192, maxOutputTokens: 1024, isDefaultForLocation: { [ChatAgentLocation.Chat]: true } } satisfies ILanguageModelChatMetadata ]; instaService.stub(ILanguageModelsService, { diff --git a/src/vs/workbench/contrib/chat/test/common/languageModels.test.ts b/src/vs/workbench/contrib/chat/test/common/languageModels.test.ts index 7f71c221cbe..3bc0df9fce8 100644 --- a/src/vs/workbench/contrib/chat/test/common/languageModels.test.ts +++ b/src/vs/workbench/contrib/chat/test/common/languageModels.test.ts @@ -10,7 +10,7 @@ import { DisposableStore } from '../../../../../base/common/lifecycle.js'; import { mock } from '../../../../../base/test/common/mock.js'; import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js'; import { NullLogService } from '../../../../../platform/log/common/log.js'; -import { ChatMessageRole, languageModelChatProviderExtensionPoint, LanguageModelsService, IChatMessage, IChatResponsePart } from '../../common/languageModels.js'; +import { ChatMessageRole, languageModelChatProviderExtensionPoint, LanguageModelsService, IChatMessage, IChatResponsePart, ILanguageModelChatMetadata } from '../../common/languageModels.js'; import { IExtensionService, nullExtensionDescription } from '../../../../services/extensions/common/extensions.js'; import { ExtensionsRegistry } from '../../../../services/extensions/common/extensionsRegistry.js'; import { DEFAULT_MODEL_PICKER_CATEGORY } from '../../common/widget/input/modelPickerWidget.js'; @@ -79,7 +79,8 @@ suite('LanguageModels', function () { id: 'test-id-1', maxInputTokens: 100, maxOutputTokens: 100, - }, + isDefaultForLocation: {} + } satisfies ILanguageModelChatMetadata, { extension: nullExtensionDescription.identifier, name: 'Pretty Name', @@ -90,7 +91,8 @@ suite('LanguageModels', function () { id: 'test-id-12', maxInputTokens: 100, maxOutputTokens: 100, - } + isDefaultForLocation: {} + } satisfies ILanguageModelChatMetadata ]; const modelMetadataAndIdentifier = modelMetadata.map(m => ({ metadata: m, @@ -153,7 +155,8 @@ suite('LanguageModels', function () { maxInputTokens: 100, maxOutputTokens: 100, modelPickerCategory: DEFAULT_MODEL_PICKER_CATEGORY, - } + isDefaultForLocation: {} + } satisfies ILanguageModelChatMetadata ]; const modelMetadataAndIdentifier = modelMetadata.map(m => ({ metadata: m, diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts index 3b27190d3ca..05f5ee69e13 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts @@ -205,7 +205,7 @@ export class InlineChatController implements IEditorContribution { this._store.add(result); this._store.add(result.widget.chatWidget.input.onDidChangeCurrentLanguageModel(newModel => { - InlineChatController._selectVendorDefaultLanguageModel = Boolean(newModel.metadata.isDefault); + InlineChatController._selectVendorDefaultLanguageModel = Boolean(newModel.metadata.isDefaultForLocation[location.location]); })); result.domNode.classList.add('inline-chat-2'); @@ -440,11 +440,11 @@ export class InlineChatController implements IEditorContribution { // or unless the user has chosen to persist their model choice const persistModelChoice = this._configurationService.getValue(InlineChatConfigKeys.PersistModelChoice); const model = this._zone.value.widget.chatWidget.input.selectedLanguageModel; - if (!persistModelChoice && InlineChatController._selectVendorDefaultLanguageModel && model && !model.metadata.isDefault) { + if (!persistModelChoice && InlineChatController._selectVendorDefaultLanguageModel && model && !model.metadata.isDefaultForLocation[session.chatModel.initialLocation]) { const ids = await this._languageModelService.selectLanguageModels({ vendor: model.metadata.vendor }, false); for (const identifier of ids) { const candidate = this._languageModelService.lookupLanguageModel(identifier); - if (candidate?.isDefault) { + if (candidate?.isDefaultForLocation[session.chatModel.initialLocation]) { this._zone.value.widget.chatWidget.input.setCurrentLanguageModel({ metadata: candidate, identifier }); break; } diff --git a/src/vs/workbench/contrib/mcp/browser/mcpCommands.ts b/src/vs/workbench/contrib/mcp/browser/mcpCommands.ts index 936baf66103..7678a38062e 100644 --- a/src/vs/workbench/contrib/mcp/browser/mcpCommands.ts +++ b/src/vs/workbench/contrib/mcp/browser/mcpCommands.ts @@ -52,7 +52,7 @@ import { CHAT_CONFIG_MENU_ID } from '../../chat/browser/actions/chatActions.js'; import { ChatViewId, IChatWidgetService } from '../../chat/browser/chat.js'; import { ChatContextKeys } from '../../chat/common/actions/chatContextKeys.js'; import { IChatElicitationRequest, IChatToolInvocation } from '../../chat/common/chatService/chatService.js'; -import { ChatModeKind } from '../../chat/common/constants.js'; +import { ChatAgentLocation, ChatModeKind } from '../../chat/common/constants.js'; import { ILanguageModelsService } from '../../chat/common/languageModels.js'; import { ILanguageModelToolsService } from '../../chat/common/tools/languageModelToolsService.js'; import { VIEW_CONTAINER } from '../../extensions/browser/extensions.contribution.js'; @@ -1067,7 +1067,7 @@ export class McpConfigureSamplingModels extends Action2 { label: model.name, description: model.tooltip, id, - picked: existingIds.size ? existingIds.has(id) : model.isDefault, + picked: existingIds.size ? existingIds.has(id) : model.isDefaultForLocation[ChatAgentLocation.Chat], }; }).filter(isDefined); diff --git a/src/vs/workbench/contrib/mcp/common/mcpSamplingService.ts b/src/vs/workbench/contrib/mcp/common/mcpSamplingService.ts index 1438caa3827..d19658136fb 100644 --- a/src/vs/workbench/contrib/mcp/common/mcpSamplingService.ts +++ b/src/vs/workbench/contrib/mcp/common/mcpSamplingService.ts @@ -18,6 +18,7 @@ import { IDialogService } from '../../../../platform/dialogs/common/dialogs.js'; import { ExtensionIdentifier } from '../../../../platform/extensions/common/extensions.js'; import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js'; import { INotificationService, Severity } from '../../../../platform/notification/common/notification.js'; +import { ChatAgentLocation } from '../../chat/common/constants.js'; import { ChatImageMimeType, ChatMessageRole, IChatMessage, IChatMessagePart, ILanguageModelsService } from '../../chat/common/languageModels.js'; import { McpCommandIds } from './mcpCommandIds.js'; import { IMcpServerSamplingConfiguration, mcpServerSamplingSection } from './mcpConfiguration.js'; @@ -232,7 +233,7 @@ export class McpSamplingService extends Disposable implements IMcpSamplingServic } // 2. Get the configured models, or the default model(s) - const foundModelIdsDeep = config.allowedModels?.filter(m => !!this._languageModelsService.lookupLanguageModel(m)) || this._languageModelsService.getLanguageModelIds().filter(m => this._languageModelsService.lookupLanguageModel(m)?.isDefault); + const foundModelIdsDeep = config.allowedModels?.filter(m => !!this._languageModelsService.lookupLanguageModel(m)) || this._languageModelsService.getLanguageModelIds().filter(m => this._languageModelsService.lookupLanguageModel(m)?.isDefaultForLocation[ChatAgentLocation.Chat]); const foundModelIds = foundModelIdsDeep.flat().sort((a, b) => b.length - a.length); // Sort by length to prefer most specific diff --git a/src/vscode-dts/vscode.proposed.chatProvider.d.ts b/src/vscode-dts/vscode.proposed.chatProvider.d.ts index 755325b964c..4879dbb93d9 100644 --- a/src/vscode-dts/vscode.proposed.chatProvider.d.ts +++ b/src/vscode-dts/vscode.proposed.chatProvider.d.ts @@ -36,7 +36,7 @@ declare module 'vscode' { * Whether or not this will be selected by default in the model picker * NOT BEING FINALIZED */ - readonly isDefault?: boolean; + readonly isDefault?: boolean | { [K in ChatLocation]?: boolean }; /** * Whether or not the model will show up in the model picker immediately upon being made known via {@linkcode LanguageModelChatProvider.provideLanguageModelChatInformation}.