diff --git a/src/vs/workbench/contrib/chat/browser/chat.shared.contribution.ts b/src/vs/workbench/contrib/chat/browser/chat.shared.contribution.ts index 3f9c08bb6f1c79..831144a40417b7 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.shared.contribution.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.shared.contribution.ts @@ -195,6 +195,7 @@ import { ChatTipService, IChatTipService } from './chatTipService.js'; import { ChatQueuePickerRendering } from './widget/input/chatQueuePickerActionItem.js'; import { ExploreAgentDefaultModel } from './exploreAgentDefaultModel.js'; import { PlanAgentDefaultModel } from './planAgentDefaultModel.js'; +import { RiskAssessmentModelContribution } from './riskAssessmentModelContribution.js'; import { UtilityModelContribution, UtilitySmallModelContribution } from './utilityModelContribution.js'; import { ChatImageCarouselService, IChatImageCarouselService } from './chatImageCarouselService.js'; import { browserChatToolReferenceNames } from '../../browserView/common/browserChatToolReferenceNames.js'; @@ -1148,12 +1149,15 @@ configurationRegistry.registerConfiguration({ }, [ChatConfiguration.ToolRiskAssessmentModel]: { type: 'string', - description: nls.localize('chat.tools.riskAssessment.model', "The language model id used to generate tool risk assessments. Should be a small, fast model."), - default: 'copilot-utility-small', + description: nls.localize('chat.tools.riskAssessment.model', "Override the language model used for tool risk assessments. Leave empty to use the default model. A fast and inexpensive model is recommended."), + default: '', tags: ['experimental', 'advanced'], experiment: { mode: 'auto' }, + enum: RiskAssessmentModelContribution.modelIds, + enumItemLabels: RiskAssessmentModelContribution.modelLabels, + markdownEnumDescriptions: RiskAssessmentModelContribution.modelDescriptions }, [ChatConfiguration.PlanAgentDefaultModel]: { type: 'string', diff --git a/src/vs/workbench/contrib/chat/browser/riskAssessmentModelContribution.ts b/src/vs/workbench/contrib/chat/browser/riskAssessmentModelContribution.ts new file mode 100644 index 00000000000000..d588b33103e2a4 --- /dev/null +++ b/src/vs/workbench/contrib/chat/browser/riskAssessmentModelContribution.ts @@ -0,0 +1,45 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ILogService } from '../../../../platform/log/common/log.js'; +import { localize } from '../../../../nls.js'; +import { registerWorkbenchContribution2, WorkbenchPhase } from '../../../common/contributions.js'; +import { ChatConfiguration } from '../common/constants.js'; +import { COPILOT_VENDOR_ID, ILanguageModelsService } from '../common/languageModels.js'; +import { createDefaultModelArrays, DefaultModelContribution } from './defaultModelContribution.js'; + +const defaultEntryLabel = localize('chat.riskAssessmentModel.defaultEntry.label', 'Default'); +const defaultEntryDescription = localize('chat.riskAssessmentModel.defaultEntry.description', "Use the built-in default risk assessment model"); + +const modelArrays = createDefaultModelArrays(defaultEntryLabel, defaultEntryDescription); + +/** + * Populates the dynamic enum of language models for the `chat.tools.riskAssessment.model` + * setting. + */ +export class RiskAssessmentModelContribution extends DefaultModelContribution { + static readonly ID = 'workbench.contrib.riskAssessmentModel'; + + static readonly modelIds = modelArrays.modelIds; + static readonly modelLabels = modelArrays.modelLabels; + static readonly modelDescriptions = modelArrays.modelDescriptions; + + constructor( + @ILanguageModelsService languageModelsService: ILanguageModelsService, + @ILogService logService: ILogService, + ) { + super(modelArrays, { + configKey: ChatConfiguration.ToolRiskAssessmentModel, + configSectionId: 'chatSidebar', + logPrefix: '[RiskAssessmentModel]', + filter: metadata => metadata.vendor !== COPILOT_VENDOR_ID, + storageFormat: 'vendorAndId', + defaultEntryLabel, + defaultEntryDescription, + }, languageModelsService, logService); + } +} + +registerWorkbenchContribution2(RiskAssessmentModelContribution.ID, RiskAssessmentModelContribution, WorkbenchPhase.BlockRestore); diff --git a/src/vs/workbench/contrib/chat/browser/tools/chatToolRiskAssessmentService.ts b/src/vs/workbench/contrib/chat/browser/tools/chatToolRiskAssessmentService.ts index a8183c09e88d40..e4f94ff0bf9432 100644 --- a/src/vs/workbench/contrib/chat/browser/tools/chatToolRiskAssessmentService.ts +++ b/src/vs/workbench/contrib/chat/browser/tools/chatToolRiskAssessmentService.ts @@ -109,9 +109,19 @@ export class ChatToolRiskAssessmentService implements IChatToolRiskAssessmentSer } private async _invokeModel(tool: IToolData, parameters: unknown, token: CancellationToken): Promise { - const modelId = this._configurationService.getValue(ChatConfiguration.ToolRiskAssessmentModel) || 'copilot-utility-small'; + const rawModel = this._configurationService.getValue(ChatConfiguration.ToolRiskAssessmentModel); + + // Parse the configured model value which is in `vendor/id` format. + // An empty string means "use the default". + let selector: { vendor?: string; id?: string } | undefined; + if (rawModel && rawModel.includes('/')) { + const [vendor, id] = rawModel.split('/', 2); + if (vendor && id) { + selector = { vendor, id }; + } + } - const models = await this._languageModelsService.selectLanguageModels({ vendor: 'copilot', id: modelId }); + const models = await this._languageModelsService.selectLanguageModels(selector ?? { id: 'copilot-utility-small' }); if (!models.length || token.isCancellationRequested) { return undefined; }