Path: blob/main/src/vs/workbench/contrib/chat/browser/chatManagement/chatManagement.contribution.ts
5267 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 { KeyCode } from '../../../../../base/common/keyCodes.js';6import { isObject, isString } from '../../../../../base/common/types.js';7import { localize, localize2 } from '../../../../../nls.js';8import { Action2, MenuId, MenuRegistry, registerAction2 } from '../../../../../platform/actions/common/actions.js';9import { ContextKeyExpr } from '../../../../../platform/contextkey/common/contextkey.js';10import { SyncDescriptor } from '../../../../../platform/instantiation/common/descriptors.js';11import { IInstantiationService, ServicesAccessor } from '../../../../../platform/instantiation/common/instantiation.js';12import { KeybindingWeight } from '../../../../../platform/keybinding/common/keybindingsRegistry.js';13import { Registry } from '../../../../../platform/registry/common/platform.js';14import { IEditorPaneRegistry, EditorPaneDescriptor } from '../../../../browser/editor.js';15import { EditorExtensions, IEditorFactoryRegistry, IEditorSerializer } from '../../../../common/editor.js';16import { EditorInput } from '../../../../common/editor/editorInput.js';17import { IEditorService, MODAL_GROUP } from '../../../../services/editor/common/editorService.js';18import { ResourceContextKey } from '../../../../common/contextkeys.js';19import { ChatContextKeys } from '../../common/actions/chatContextKeys.js';20import { CONTEXT_MODELS_EDITOR, CONTEXT_MODELS_SEARCH_FOCUS, MANAGE_CHAT_COMMAND_ID } from '../../common/constants.js';21import { CHAT_CATEGORY } from '../actions/chatActions.js';22import { ChatManagementEditor, ModelsManagementEditor } from './chatManagementEditor.js';23import { ChatManagementEditorInput, ModelsManagementEditorInput } from './chatManagementEditorInput.js';24import { ILanguageModelsConfigurationService } from '../../common/languageModelsConfiguration.js';25import { Codicon } from '../../../../../base/common/codicons.js';26import { registerIcon } from '../../../../../platform/theme/common/iconRegistry.js';27import { Disposable } from '../../../../../base/common/lifecycle.js';28import { IWorkbenchContribution, registerWorkbenchContribution2, WorkbenchPhase } from '../../../../common/contributions.js';2930const languageModelsOpenSettingsIcon = registerIcon('language-models-open-settings', Codicon.goToFile, localize('languageModelsOpenSettings', 'Icon for open language models settings commands.'));3132const LANGUAGE_MODELS_ENTITLEMENT_PRECONDITION = ContextKeyExpr.and(ChatContextKeys.enabled, ContextKeyExpr.or(33ChatContextKeys.Entitlement.planFree,34ChatContextKeys.Entitlement.planPro,35ChatContextKeys.Entitlement.planProPlus,36ChatContextKeys.Entitlement.planBusiness,37ChatContextKeys.Entitlement.planEnterprise,38ChatContextKeys.Entitlement.internal39));4041Registry.as<IEditorPaneRegistry>(EditorExtensions.EditorPane).registerEditorPane(42EditorPaneDescriptor.create(43ChatManagementEditor,44ChatManagementEditor.ID,45localize('chatManagementEditor', "Chat Management Editor")46),47[48new SyncDescriptor(ChatManagementEditorInput)49]50);5152Registry.as<IEditorPaneRegistry>(EditorExtensions.EditorPane).registerEditorPane(53EditorPaneDescriptor.create(54ModelsManagementEditor,55ModelsManagementEditor.ID,56localize('modelsManagementEditor', "Models Management Editor")57),58[59new SyncDescriptor(ModelsManagementEditorInput)60]61);6263class ChatManagementEditorInputSerializer implements IEditorSerializer {6465canSerialize(editorInput: EditorInput): boolean {66return true;67}6869serialize(input: ChatManagementEditorInput): string {70return '';71}7273deserialize(instantiationService: IInstantiationService): ChatManagementEditorInput {74return instantiationService.createInstance(ChatManagementEditorInput);75}76}7778class ModelsManagementEditorInputSerializer implements IEditorSerializer {7980canSerialize(editorInput: EditorInput): boolean {81return true;82}8384serialize(input: ModelsManagementEditorInput): string {85return '';86}8788deserialize(instantiationService: IInstantiationService): ModelsManagementEditorInput {89return instantiationService.createInstance(ModelsManagementEditorInput);90}91}9293Registry.as<IEditorFactoryRegistry>(EditorExtensions.EditorFactory).registerEditorSerializer(ChatManagementEditorInput.ID, ChatManagementEditorInputSerializer);94Registry.as<IEditorFactoryRegistry>(EditorExtensions.EditorFactory).registerEditorSerializer(ModelsManagementEditorInput.ID, ModelsManagementEditorInputSerializer);9596interface IOpenManageCopilotEditorActionOptions {97query?: string;98section?: string;99}100101function sanitizeString(arg: unknown): string | undefined {102return isString(arg) ? arg : undefined;103}104105function sanitizeOpenManageCopilotEditorArgs(input: unknown): IOpenManageCopilotEditorActionOptions {106if (!isObject(input)) {107input = {};108}109110const args = <IOpenManageCopilotEditorActionOptions>input;111112return {113query: sanitizeString(args?.query),114section: sanitizeString(args?.section)115};116}117118class ChatManagementActionsContribution extends Disposable implements IWorkbenchContribution {119120static readonly ID = 'workbench.contrib.chatManagementActions';121122constructor(123@ILanguageModelsConfigurationService private readonly languageModelsConfigurationService: ILanguageModelsConfigurationService,124) {125super();126this.registerChatManagementActions();127this.registerLanguageModelsEditorTitleActions();128}129130private registerChatManagementActions() {131this._register(registerAction2(class extends Action2 {132constructor() {133super({134id: MANAGE_CHAT_COMMAND_ID,135title: localize2('openAiManagement', "Manage Language Models"),136category: CHAT_CATEGORY,137precondition: LANGUAGE_MODELS_ENTITLEMENT_PRECONDITION,138f1: true,139});140}141async run(accessor: ServicesAccessor, args: string | IOpenManageCopilotEditorActionOptions) {142const editorService = accessor.get(IEditorService);143args = sanitizeOpenManageCopilotEditorArgs(args);144return editorService.openEditor(new ModelsManagementEditorInput(), { pinned: true }, MODAL_GROUP);145}146}));147148this._register(registerAction2(class extends Action2 {149constructor() {150super({151id: 'chat.models.action.clearSearchResults',152precondition: CONTEXT_MODELS_EDITOR,153keybinding: {154primary: KeyCode.Escape,155weight: KeybindingWeight.EditorContrib,156when: CONTEXT_MODELS_SEARCH_FOCUS157},158title: localize2('models.clearResults', "Clear Models Search Results")159});160}161162run(accessor: ServicesAccessor) {163const activeEditorPane = accessor.get(IEditorService).activeEditorPane;164if (activeEditorPane instanceof ModelsManagementEditor) {165activeEditorPane.clearSearch();166}167return null;168}169}));170171this._register(registerAction2(class extends Action2 {172constructor() {173super({174id: 'workbench.action.openLanguageModelsJson',175title: localize2('openLanguageModelsJson', "Open Language Models (JSON)"),176category: CHAT_CATEGORY,177precondition: LANGUAGE_MODELS_ENTITLEMENT_PRECONDITION,178f1: true,179});180}181182async run(accessor: ServicesAccessor) {183const languageModelsConfigurationService = accessor.get(ILanguageModelsConfigurationService);184await languageModelsConfigurationService.configureLanguageModels();185}186}));187}188189private registerLanguageModelsEditorTitleActions() {190const modelsConfigurationFile = this.languageModelsConfigurationService.configurationFile;191const openModelsManagementEditorWhen = ContextKeyExpr.and(192CONTEXT_MODELS_EDITOR.toNegated(),193ResourceContextKey.Resource.isEqualTo(modelsConfigurationFile.toString()),194ContextKeyExpr.not('isInDiffEditor'),195LANGUAGE_MODELS_ENTITLEMENT_PRECONDITION196);197198MenuRegistry.appendMenuItem(MenuId.EditorTitle, {199command: {200id: MANAGE_CHAT_COMMAND_ID,201title: localize2('openAiManagement', "Manage Language Models"),202icon: languageModelsOpenSettingsIcon203},204when: openModelsManagementEditorWhen,205group: 'navigation',206order: 1207});208209const openLanguageModelsJsonWhen = ContextKeyExpr.and(210CONTEXT_MODELS_EDITOR,211LANGUAGE_MODELS_ENTITLEMENT_PRECONDITION212);213214MenuRegistry.appendMenuItem(MenuId.EditorTitle, {215command: {216id: 'workbench.action.openLanguageModelsJson',217title: localize2('openLanguageModelsJson', "Open Language Models (JSON)"),218icon: languageModelsOpenSettingsIcon219},220when: openLanguageModelsJsonWhen,221group: 'navigation',222order: 1223});224}225}226227registerWorkbenchContribution2(ChatManagementActionsContribution.ID, ChatManagementActionsContribution, WorkbenchPhase.AfterRestored);228229230