Path: blob/main/src/vs/workbench/contrib/chat/browser/actions/manageModelsActions.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { coalesce } from '../../../../../base/common/arrays.js';6import { Codicon } from '../../../../../base/common/codicons.js';7import { DisposableStore } from '../../../../../base/common/lifecycle.js';8import { ThemeIcon } from '../../../../../base/common/themables.js';9import { localize2 } from '../../../../../nls.js';10import { Action2 } from '../../../../../platform/actions/common/actions.js';11import { ICommandService } from '../../../../../platform/commands/common/commands.js';12import { ContextKeyExpr } from '../../../../../platform/contextkey/common/contextkey.js';13import { ServicesAccessor } from '../../../../../platform/instantiation/common/instantiation.js';14import { IQuickInputService, IQuickPickItem } from '../../../../../platform/quickinput/common/quickInput.js';15import { ChatContextKeys } from '../../common/chatContextKeys.js';16import { ILanguageModelChatMetadataAndIdentifier, ILanguageModelsService } from '../../common/languageModels.js';17import { CHAT_CATEGORY } from './chatActions.js';1819interface IVendorQuickPickItem extends IQuickPickItem {20managementCommand?: string;21vendor: string;22}2324interface IModelQuickPickItem extends IQuickPickItem {25modelId: string;26vendor: string;27}2829export class ManageModelsAction extends Action2 {30static readonly ID = 'workbench.action.chat.manageLanguageModels';3132constructor() {33super({34id: ManageModelsAction.ID,35title: localize2('manageLanguageModels', 'Manage Language Models...'),36category: CHAT_CATEGORY,37precondition: ContextKeyExpr.and(ChatContextKeys.enabled, ContextKeyExpr.or(38ChatContextKeys.Entitlement.planFree,39ChatContextKeys.Entitlement.planPro,40ChatContextKeys.Entitlement.planProPlus,41ChatContextKeys.Entitlement.internal42)),43f1: true44});45}46override async run(accessor: ServicesAccessor, ...args: any[]): Promise<void> {47const languageModelsService = accessor.get(ILanguageModelsService);48const quickInputService = accessor.get(IQuickInputService);49const commandService = accessor.get(ICommandService);5051const vendors = languageModelsService.getVendors();52const store = new DisposableStore();5354const quickPickItems: IVendorQuickPickItem[] = vendors.map(vendor => ({55label: vendor.displayName,56vendor: vendor.vendor,57managementCommand: vendor.managementCommand,58buttons: vendor.managementCommand ? [{59iconClass: ThemeIcon.asClassName(Codicon.settingsGear),60tooltip: `Manage ${vendor.displayName}`61}] : undefined62}));6364const quickPick = store.add(quickInputService.createQuickPick<IQuickPickItem>());65quickPick.title = 'Manage Language Models';66quickPick.placeholder = 'Select a provider...';67quickPick.items = quickPickItems;68quickPick.show();6970store.add(quickPick.onDidAccept(async () => {71quickPick.hide();72const selectedItem: IVendorQuickPickItem = quickPick.selectedItems[0] as IVendorQuickPickItem;73if (selectedItem) {74const models: ILanguageModelChatMetadataAndIdentifier[] = coalesce((await languageModelsService.selectLanguageModels({ vendor: selectedItem.vendor }, true)).map(modelIdentifier => {75const modelMetadata = languageModelsService.lookupLanguageModel(modelIdentifier);76if (!modelMetadata) {77return undefined;78}79return {80metadata: modelMetadata,81identifier: modelIdentifier,82};83}));84await this.showModelSelectorQuickpick(models, quickInputService, languageModelsService);85}86}));8788store.add(quickPick.onDidTriggerItemButton(async (event) => {89const selectedItem = event.item as IVendorQuickPickItem;90const managementCommand = selectedItem.managementCommand;91if (managementCommand) {92commandService.executeCommand(managementCommand, selectedItem.vendor);93}94}));9596store.add(quickPick.onDidHide(() => {97store.dispose();98}));99}100101private async showModelSelectorQuickpick(102modelsAndIdentifiers: ILanguageModelChatMetadataAndIdentifier[],103quickInputService: IQuickInputService,104languageModelsService: ILanguageModelsService105): Promise<void> {106const store = new DisposableStore();107const modelItems: IModelQuickPickItem[] = modelsAndIdentifiers.map(model => ({108label: model.metadata.name,109detail: model.metadata.id,110modelId: model.identifier,111vendor: model.metadata.vendor,112picked: model.metadata.isUserSelectable113}));114115if (modelItems.length === 0) {116store.dispose();117return;118}119120const quickPick = quickInputService.createQuickPick<IModelQuickPickItem>();121quickPick.items = modelItems;122quickPick.title = 'Manage Language Models';123quickPick.placeholder = 'Select language models...';124quickPick.selectedItems = modelItems.filter(item => item.picked);125quickPick.canSelectMany = true;126quickPick.show();127128// Handle selection129store.add(quickPick.onDidAccept(async () => {130quickPick.hide();131const items: IModelQuickPickItem[] = quickPick.items as IModelQuickPickItem[];132items.forEach(item => {133languageModelsService.updateModelPickerPreference(item.modelId, quickPick.selectedItems.includes(item));134});135}));136137store.add(quickPick.onDidHide(() => {138store.dispose();139}));140}141}142143144