
import { __decorate, __param } from '../../../../../../../external/tslib/tslib.es6.js';
import { SequencerByKey, timeout } from '../../../../base/common/async.js';
import { CancellationToken } from '../../../../base/common/cancellation.js';
import { getErrorMessage, isCancellationError, CancellationError } from '../../../../base/common/errors.js';
import { Emitter } from '../../../../base/common/event.js';
import { hash } from '../../../../base/common/hash.js';
import { Iterable } from '../../../../base/common/iterator.js';
import { DisposableStore, toDisposable } from '../../../../base/common/lifecycle.js';
import '../../../../base/common/observableInternal/index.js';
import { equals } from '../../../../base/common/objects.js';
import Severity$1 from '../../../../base/common/severity.js';
import { isFalsyOrWhitespace, format } from '../../../../base/common/strings.js';
import { SubmenuAction } from '../../../../base/common/actions.js';
import { isString, isObject } from '../../../../base/common/types.js';
import { generateUuid } from '../../../../base/common/uuid.js';
import { localize } from '../../../../nls.js';
import { ContextKeyExpr } from '../../../../platform/contextkey/common/contextkey.js';
import { IContextKeyService } from '../../../../platform/contextkey/common/contextkey.service.js';
import { ILogService } from '../../../../platform/log/common/log.service.js';
import { IProductService } from '../../../../platform/product/common/productService.service.js';
import { asJson } from '../../../../platform/request/common/request.js';
import { IRequestService } from '../../../../platform/request/common/request.service.js';
import { QuickInputHideReason } from '../../../../platform/quickinput/common/quickInput.js';
import { IQuickInputService } from '../../../../platform/quickinput/common/quickInput.service.js';
import { ISecretStorageService } from '../../../../platform/secrets/common/secrets.service.js';
import { StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js';
import { IStorageService } from '../../../../platform/storage/common/storage.service.js';
import { IExtensionService } from '../../../services/extensions/common/extensions.service.js';
import { ExtensionsRegistry } from '../../../services/extensions/common/extensionsRegistry.js';
import { ChatContextKeys } from './actions/chatContextKeys.js';
import { ILanguageModelsConfigurationService } from './languageModelsConfiguration.service.js';
import { observableValue } from '../../../../base/common/observableInternal/observables/observableValue.js';

var LanguageModelsService_1;
var ChatMessageRole;
(function(ChatMessageRole) {
    ChatMessageRole[ChatMessageRole["System"] = 0] = "System";
    ChatMessageRole[ChatMessageRole["User"] = 1] = "User";
    ChatMessageRole[ChatMessageRole["Assistant"] = 2] = "Assistant";
})(ChatMessageRole || (ChatMessageRole = {}));
var LanguageModelPartAudience;
(function(LanguageModelPartAudience) {
    LanguageModelPartAudience[LanguageModelPartAudience["Assistant"] = 0] = "Assistant";
    LanguageModelPartAudience[LanguageModelPartAudience["User"] = 1] = "User";
    LanguageModelPartAudience[LanguageModelPartAudience["Extension"] = 2] = "Extension";
})(LanguageModelPartAudience || (LanguageModelPartAudience = {}));
var ChatImageMimeType;
(function(ChatImageMimeType) {
    ChatImageMimeType["PNG"] = "image/png";
    ChatImageMimeType["JPEG"] = "image/jpeg";
    ChatImageMimeType["GIF"] = "image/gif";
    ChatImageMimeType["WEBP"] = "image/webp";
    ChatImageMimeType["BMP"] = "image/bmp";
})(ChatImageMimeType || (ChatImageMimeType = {}));
var ImageDetailLevel;
(function(ImageDetailLevel) {
    ImageDetailLevel["Low"] = "low";
    ImageDetailLevel["High"] = "high";
})(ImageDetailLevel || (ImageDetailLevel = {}));
var ILanguageModelChatMetadata;
(function(ILanguageModelChatMetadata) {
    function suitableForAgentMode(metadata) {
        const supportsToolsAgent = typeof metadata.capabilities?.agentMode === "undefined" || metadata.capabilities.agentMode;
        return supportsToolsAgent && !!metadata.capabilities?.toolCalling;
    }
    ILanguageModelChatMetadata.suitableForAgentMode = suitableForAgentMode;
    function asQualifiedName(metadata) {
        return `${metadata.name} (${metadata.vendor})`;
    }
    ILanguageModelChatMetadata.asQualifiedName = asQualifiedName;
    function matchesQualifiedName(name, metadata) {
        if (metadata.vendor === "copilot" && name === metadata.name) {
            return true;
        }
        return name === asQualifiedName(metadata);
    }
    ILanguageModelChatMetadata.matchesQualifiedName = matchesQualifiedName;
})(ILanguageModelChatMetadata || (ILanguageModelChatMetadata = {}));
async function getTextResponseFromStream(response) {
    let responseText = "";
    const streaming = (async () => {
        if (!response?.stream) {
            return;
        }
        for await (const part of response.stream) {
            if (Array.isArray(part)) {
                for (const item of part) {
                    if (item.type === "text") {
                        responseText += item.value;
                    }
                }
            } else if (part.type === "text") {
                responseText += part.value;
            }
        }
    })();
    try {
        await Promise.all([response.result, streaming]);
        return responseText;
    } catch (err) {
        if (responseText) {
            return responseText;
        }
        throw err;
    }
}
function isILanguageModelChatSelector(value) {
    if (typeof value !== "object" || value === null) {
        return false;
    }
    const obj = value;
    return ((obj.name === undefined || typeof obj.name === "string") && (obj.id === undefined || typeof obj.id === "string") && (obj.vendor === undefined || typeof obj.vendor === "string") && (obj.version === undefined || typeof obj.version === "string") && (obj.family === undefined || typeof obj.family === "string") && (obj.tokens === undefined || typeof obj.tokens === "number") && (obj.extension === undefined || typeof obj.extension === "object"));
}
const languageModelChatProviderType = {
    type: "object",
    required: ["vendor", "displayName"],
    properties: {
        vendor: {
            type: "string",
            description: ( localize(7214, "A globally unique vendor of language model chat provider."))
        },
        displayName: {
            type: "string",
            description: ( localize(7215, "The display name of the language model chat provider."))
        },
        configuration: {
            type: "object",
            description: ( localize(7216, "Configuration options for the language model chat provider.")),
            anyOf: [{
                $ref: "http://json-schema.org/draft-07/schema#"
            }, {
                properties: {
                    properties: {
                        type: "object",
                        additionalProperties: {
                            $ref: "http://json-schema.org/draft-07/schema#",
                            properties: {
                                secret: {
                                    type: "boolean",
                                    description: ( localize(7217, "Whether the property is a secret."))
                                }
                            }
                        }
                    },
                    additionalProperties: {
                        $ref: "http://json-schema.org/draft-07/schema#",
                        properties: {
                            secret: {
                                type: "boolean",
                                description: ( localize(7217, "Whether the property is a secret."))
                            }
                        }
                    }
                }
            }]
        },
        managementCommand: {
            type: "string",
            description: ( localize(
                7218,
                "A command to manage the language model chat provider, e.g. 'Manage Copilot models'. This is used in the chat model picker. If not provided, a gear icon is not rendered during vendor selection."
            )),
            deprecated: true,
            deprecationMessage: ( localize(
                7219,
                "The managementCommand property is deprecated and will be removed in a future release. Use the new configuration property instead."
            ))
        },
        when: {
            type: "string",
            description: ( localize(
                7220,
                "Condition which must be true to show this language model chat provider in the Manage Models list."
            ))
        }
    }
};
const languageModelChatProviderExtensionPoint = ExtensionsRegistry.registerExtensionPoint({
    extensionPoint: "languageModelChatProviders",
    jsonSchema: {
        description: ( localize(7221, "Contribute language model chat providers of a specific vendor.")),
        oneOf: [languageModelChatProviderType, {
            type: "array",
            items: languageModelChatProviderType
        }]
    },
    activationEventsGenerator: function*(contribs) {
        for (const contrib of contribs) {
            yield `onLanguageModelChatProvider:${contrib.vendor}`;
        }
    }
});
const CHAT_MODEL_PICKER_PREFERENCES_STORAGE_KEY = "chatModelPickerPreferences";
const CHAT_MODEL_RECENTLY_USED_STORAGE_KEY = "chatModelRecentlyUsed";
const CHAT_PARTICIPANT_NAME_REGISTRY_STORAGE_KEY = "chat.participantNameRegistry";
const CHAT_MODELS_CONTROL_STORAGE_KEY = "chat.modelsControl";
let LanguageModelsService = class LanguageModelsService {
    static {
        LanguageModelsService_1 = this;
    }
    static {
        this.SECRET_KEY_PREFIX = "chat.lm.secret.";
    }
    static {
        this.SECRET_INPUT = "${input:{0}}";
    }
    constructor(
        _extensionService,
        _logService,
        _storageService,
        _contextKeyService,
        _languageModelsConfigurationService,
        _quickInputService,
        _secretStorageService,
        _productService,
        _requestService
    ) {
        this._extensionService = _extensionService;
        this._logService = _logService;
        this._storageService = _storageService;
        this._contextKeyService = _contextKeyService;
        this._languageModelsConfigurationService = _languageModelsConfigurationService;
        this._quickInputService = _quickInputService;
        this._secretStorageService = _secretStorageService;
        this._productService = _productService;
        this._requestService = _requestService;
        this._store = ( new DisposableStore());
        this._providers = ( new Map());
        this._vendors = ( new Map());
        this._onDidChangeLanguageModelVendors = this._store.add(( new Emitter()));
        this.onDidChangeLanguageModelVendors = this._onDidChangeLanguageModelVendors.event;
        this._modelsGroups = ( new Map());
        this._modelCache = ( new Map());
        this._resolveLMSequencer = ( new SequencerByKey());
        this._modelPickerUserPreferences = {};
        this._modelConfigurations = ( new Map());
        this._onLanguageModelChange = this._store.add(( new Emitter()));
        this.onDidChangeLanguageModels = this._onLanguageModelChange.event;
        this._recentlyUsedModelIds = [];
        this._onDidChangeModelsControlManifest = this._store.add(( new Emitter()));
        this.onDidChangeModelsControlManifest = this._onDidChangeModelsControlManifest.event;
        this._modelsControlManifest = {
            free: {},
            paid: {}
        };
        this._chatControlDisposed = false;
        this._restrictedChatParticipants = observableValue(this, Object.create(null));
        this.restrictedChatParticipants = this._restrictedChatParticipants;
        this._hasUserSelectableModels = ChatContextKeys.languageModelsAreUserSelectable.bindTo(_contextKeyService);
        this._modelPickerUserPreferences = this._readModelPickerPreferences();
        this._recentlyUsedModelIds = this._readRecentlyUsedModels();
        this._initChatControlData();
        this._store.add(this._storageService.onDidChangeValue(
            StorageScope.PROFILE,
            CHAT_MODEL_PICKER_PREFERENCES_STORAGE_KEY,
            this._store
        )(() => this._onDidChangeModelPickerPreferences()));
        this._store.add(this.onDidChangeLanguageModels(() => {
            this._hasUserSelectableModels.set(this._modelCache.size > 0 && ( Array.from(( this._modelCache.values())).some(model => model.isUserSelectable)));
            this._refreshModelsControlManifest();
        }));
        this._store.add(
            this._languageModelsConfigurationService.onDidChangeLanguageModelGroups(changedGroups => this._onDidChangeLanguageModelGroups(changedGroups))
        );
        this._store.add(languageModelChatProviderExtensionPoint.setHandler((
            extensions,
            {
                added,
                removed
            }
        ) => {
            const addedVendors = [];
            const removedVendors = [];
            for (const extension of added) {
                for (const item of Iterable.wrap(extension.value)) {
                    if (( this._vendors.has(item.vendor))) {
                        extension.collector.error(( localize(
                            7222,
                            "The vendor '{0}' is already registered and cannot be registered twice",
                            item.vendor
                        )));
                        continue;
                    }
                    if (isFalsyOrWhitespace(item.vendor)) {
                        extension.collector.error(( localize(7223, "The vendor field cannot be empty.")));
                        continue;
                    }
                    if (item.vendor.trim() !== item.vendor) {
                        extension.collector.error(( localize(7224, "The vendor field cannot start or end with whitespace.")));
                        continue;
                    }
                    addedVendors.push(item);
                }
            }
            for (const extension of removed) {
                for (const item of Iterable.wrap(extension.value)) {
                    removedVendors.push(item);
                }
            }
            this.deltaLanguageModelChatProviderDescriptors(addedVendors, removedVendors);
        }));
    }
    deltaLanguageModelChatProviderDescriptors(added, removed) {
        const addedVendorIds = [];
        const removedVendorIds = [];
        for (const item of added) {
            if (( this._vendors.has(item.vendor))) {
                this._logService.error(
                    `The vendor '${item.vendor}' is already registered and cannot be registered twice`
                );
                continue;
            }
            if (isFalsyOrWhitespace(item.vendor)) {
                this._logService.error("The vendor field cannot be empty.");
                continue;
            }
            if (item.vendor.trim() !== item.vendor) {
                this._logService.error("The vendor field cannot start or end with whitespace.");
                continue;
            }
            const vendor = {
                vendor: item.vendor,
                displayName: item.displayName,
                configuration: item.configuration,
                managementCommand: item.managementCommand,
                when: item.when,
                isDefault: item.vendor === "copilot"
            };
            this._vendors.set(item.vendor, vendor);
            addedVendorIds.push(item.vendor);
            if (this._hasStoredModelForVendor(item.vendor)) {
                this._extensionService.activateByEvent(`onLanguageModelChatProvider:${item.vendor}`);
            }
        }
        for (const item of removed) {
            this._vendors.delete(item.vendor);
            this._providers.delete(item.vendor);
            this._clearModelCache(item.vendor);
            removedVendorIds.push(item.vendor);
        }
        for (const [vendor, _] of this._providers) {
            if (!( this._vendors.has(vendor))) {
                this._providers.delete(vendor);
            }
        }
        if (addedVendorIds.length > 0 || removedVendorIds.length > 0) {
            this._onDidChangeLanguageModelVendors.fire([...addedVendorIds, ...removedVendorIds]);
            if (removedVendorIds.length > 0) {
                for (const vendor of removedVendorIds) {
                    this._onLanguageModelChange.fire(vendor);
                }
            }
        }
    }
    async _onDidChangeLanguageModelGroups(changedGroups) {
        const changedVendors = ( new Set(( changedGroups.map(g => g.vendor))));
        await Promise.all(( Array.from(changedVendors).map(vendor => this._resolveAllLanguageModels(vendor, true))));
    }
    _readModelPickerPreferences() {
        return this._storageService.getObject(CHAT_MODEL_PICKER_PREFERENCES_STORAGE_KEY, StorageScope.PROFILE, {});
    }
    _onDidChangeModelPickerPreferences() {
        const newPreferences = this._readModelPickerPreferences();
        const oldPreferences = this._modelPickerUserPreferences;
        const affectedVendors = ( new Set());
        let hasChanges = false;
        for (const modelId in newPreferences) {
            if (oldPreferences[modelId] !== newPreferences[modelId]) {
                hasChanges = true;
                const model = this._modelCache.get(modelId);
                if (model) {
                    affectedVendors.add(model.vendor);
                }
            }
        }
        for (const modelId in oldPreferences) {
            if (!newPreferences.hasOwnProperty(modelId)) {
                hasChanges = true;
                const model = this._modelCache.get(modelId);
                if (model) {
                    affectedVendors.add(model.vendor);
                }
            }
        }
        if (hasChanges) {
            this._logService.trace("[LM] Updated model picker preferences from storage");
            this._modelPickerUserPreferences = newPreferences;
            for (const vendor of affectedVendors) {
                this._onLanguageModelChange.fire(vendor);
            }
        }
    }
    _hasStoredModelForVendor(vendor) {
        return ( ( Object.keys(this._modelPickerUserPreferences)).some(modelId => {
            return modelId.startsWith(vendor);
        }));
    }
    _saveModelPickerPreferences() {
        this._storageService.store(
            CHAT_MODEL_PICKER_PREFERENCES_STORAGE_KEY,
            this._modelPickerUserPreferences,
            StorageScope.PROFILE,
            StorageTarget.USER
        );
    }
    updateModelPickerPreference(modelIdentifier, showInModelPicker) {
        const model = this._modelCache.get(modelIdentifier);
        if (!model) {
            this._logService.warn(
                `[LM] Cannot update model picker preference for unknown model ${modelIdentifier}`
            );
            return;
        }
        this._modelPickerUserPreferences[modelIdentifier] = showInModelPicker;
        if (showInModelPicker === model.isUserSelectable) {
            delete this._modelPickerUserPreferences[modelIdentifier];
            this._saveModelPickerPreferences();
        } else if (model.isUserSelectable !== showInModelPicker) {
            this._saveModelPickerPreferences();
        }
        this._onLanguageModelChange.fire(model.vendor);
        this._logService.trace(
            `[LM] Updated model picker preference for ${modelIdentifier} to ${showInModelPicker}`
        );
    }
    getVendors() {
        return Array.from(( this._vendors.values())).filter(vendor => {
            if (!vendor.when) {
                return true;
            }
            const whenClause = ContextKeyExpr.deserialize(vendor.when);
            return whenClause ? this._contextKeyService.contextMatchesRules(whenClause) : false;
        });
    }
    getLanguageModelIds() {
        return Array.from(( this._modelCache.keys()));
    }
    lookupLanguageModel(modelIdentifier) {
        const model = this._modelCache.get(modelIdentifier);
        if (model && this._modelPickerUserPreferences[modelIdentifier] !== undefined) {
            return {
                ...model,
                isUserSelectable: this._modelPickerUserPreferences[modelIdentifier]
            };
        }
        return model;
    }
    lookupLanguageModelByQualifiedName(referenceName) {
        for (const [identifier, model] of this._modelCache.entries()) {
            if (ILanguageModelChatMetadata.matchesQualifiedName(referenceName, model)) {
                return {
                    metadata: model,
                    identifier
                };
            }
        }
        return undefined;
    }
    async _resolveAllLanguageModels(vendorId, silent) {
        const vendor = this._vendors.get(vendorId);
        if (!vendor) {
            return;
        }
        await this._extensionService.activateByEvent(`onLanguageModelChatProvider:${vendorId}`);
        const provider = this._providers.get(vendorId);
        if (!provider) {
            this._logService.warn(`[LM] No provider registered for vendor ${vendorId}`);
            return;
        }
        return this._resolveLMSequencer.queue(vendorId, async () => {
            const allModels = [];
            const languageModelsGroups = [];
            try {
                const models = await provider.provideLanguageModelChatInfo({
                    silent
                }, CancellationToken.None);
                if (models.length) {
                    allModels.push(...models);
                    const modelIdentifiers = [];
                    for (const m of models) {
                        if (vendor.isDefault) {
                            if (m.metadata.isUserSelectable || this._modelPickerUserPreferences[m.identifier] === true) {
                                modelIdentifiers.push(m.identifier);
                            } else {
                                this._logService.trace(
                                    `[LM] Skipping model ${m.identifier} from model picker as it is not user selectable.`
                                );
                            }
                        } else {
                            modelIdentifiers.push(m.identifier);
                        }
                    }
                    languageModelsGroups.push({
                        modelIdentifiers
                    });
                }
            } catch (error) {
                languageModelsGroups.push({
                    modelIdentifiers: [],
                    status: {
                        message: getErrorMessage(error),
                        severity: Severity$1.Error
                    }
                });
            }
            const groups = this._languageModelsConfigurationService.getLanguageModelsProviderGroups();
            const perModelConfigurations = ( new Map());
            for (const group of groups) {
                if (group.vendor !== vendorId) {
                    continue;
                }
                if (vendor.isDefault && !vendor.configuration) {
                    if (group.settings) {
                        for (const model of allModels) {
                            const modelConfig = group.settings[model.metadata.id];
                            if (modelConfig) {
                                perModelConfigurations.set(model.identifier, {
                                    ...modelConfig
                                });
                            }
                        }
                    }
                    languageModelsGroups.push({
                        group,
                        modelIdentifiers: []
                    });
                    continue;
                }
                const configuration = await this._resolveConfiguration(group, vendor.configuration);
                try {
                    const models = await provider.provideLanguageModelChatInfo({
                        group: group.name,
                        silent,
                        configuration
                    }, CancellationToken.None);
                    if (models.length) {
                        allModels.push(...models);
                        languageModelsGroups.push({
                            group,
                            modelIdentifiers: ( models.map(m => m.identifier))
                        });
                    }
                    if (group.settings) {
                        for (const model of models) {
                            const modelConfig = group.settings[model.metadata.id];
                            if (modelConfig) {
                                perModelConfigurations.set(model.identifier, {
                                    ...modelConfig
                                });
                            }
                        }
                    }
                } catch (error) {
                    languageModelsGroups.push({
                        group,
                        modelIdentifiers: [],
                        status: {
                            message: getErrorMessage(error),
                            severity: Severity$1.Error
                        }
                    });
                }
            }
            this._modelsGroups.set(vendorId, languageModelsGroups);
            const oldModels = this._clearModelCache(vendorId);
            let hasChanges = false;
            for (const model of allModels) {
                if (( this._modelCache.has(model.identifier))) {
                    this._logService.warn(`[LM] Model ${model.identifier} is already registered. Skipping.`);
                    continue;
                }
                this._modelCache.set(model.identifier, model.metadata);
                hasChanges = hasChanges || !equals(oldModels.get(model.identifier), model.metadata);
                oldModels.delete(model.identifier);
            }
            this._logService.trace(`[LM] Resolved language models for vendor ${vendorId}`, allModels);
            hasChanges = hasChanges || oldModels.size > 0;
            this._clearModelConfigurations(vendorId);
            for (const [identifier, config] of perModelConfigurations) {
                if (( this._modelCache.has(identifier))) {
                    this._modelConfigurations.set(identifier, config);
                }
            }
            if (hasChanges) {
                this._onLanguageModelChange.fire(vendorId);
            } else {
                this._logService.trace(`[LM] No changes in language models for vendor ${vendorId}`);
            }
        });
    }
    getLanguageModelGroups(vendor) {
        return this._modelsGroups.get(vendor) ?? [];
    }
    async selectLanguageModels(selector) {
        if (selector.vendor) {
            await this._resolveAllLanguageModels(selector.vendor, true);
        } else {
            const allVendors = Array.from(( this._vendors.keys()));
            await Promise.all(( allVendors.map(vendor => this._resolveAllLanguageModels(vendor, true))));
        }
        const result = [];
        for (const [internalModelIdentifier, model] of this._modelCache) {
            if ((selector.vendor === undefined || model.vendor === selector.vendor) && (selector.family === undefined || model.family === selector.family) && (selector.version === undefined || model.version === selector.version) && (selector.id === undefined || model.id === selector.id)) {
                result.push(internalModelIdentifier);
            }
        }
        this._logService.trace("[LM] selected language models", selector, result);
        return result;
    }
    registerLanguageModelProvider(vendor, provider) {
        this._logService.trace("[LM] registering language model provider", vendor, provider);
        if (!( this._vendors.has(vendor))) {
            throw ( new Error(`Chat model provider uses UNKNOWN vendor ${vendor}.`));
        }
        if (( this._providers.has(vendor))) {
            throw ( new Error(`Chat model provider for vendor ${vendor} is already registered.`));
        }
        this._providers.set(vendor, provider);
        if (this._hasStoredModelForVendor(vendor)) {
            this._resolveAllLanguageModels(vendor, true);
        }
        const modelChangeListener = provider.onDidChange(() => {
            this._resolveAllLanguageModels(vendor, true);
        });
        return toDisposable(() => {
            this._logService.trace("[LM] UNregistered language model provider", vendor);
            this._clearModelCache(vendor);
            this._providers.delete(vendor);
            modelChangeListener.dispose();
        });
    }
    async sendChatRequest(modelId, from, messages, options, token) {
        const metadata = this._modelCache.get(modelId);
        const provider = this._providers.get(metadata?.vendor || "");
        if (!provider) {
            throw ( new Error(`Chat provider for model ${modelId} is not registered.`));
        }
        const configuration = this.getModelConfiguration(modelId);
        const mergedOptions = configuration ? {
            ...options,
            configuration: {
                ...configuration,
                ...options.configuration
            }
        } : options;
        return provider.sendChatRequest(modelId, messages, from, mergedOptions, token);
    }
    _resolveModelConfigurationWithDefaults(modelId, metadata) {
        const userConfig = this._modelConfigurations.get(modelId);
        const schema = metadata?.configurationSchema;
        if (!schema?.properties && !userConfig) {
            return undefined;
        }
        const defaults = {};
        if (schema?.properties) {
            for (const [key, propSchema] of Object.entries(schema.properties)) {
                if (propSchema.default !== undefined) {
                    defaults[key] = propSchema.default;
                }
            }
        }
        if (!userConfig && ( Object.keys(defaults)).length === 0) {
            return undefined;
        }
        return {
            ...defaults,
            ...userConfig
        };
    }
    computeTokenLength(modelId, message, token) {
        const model = this._modelCache.get(modelId);
        if (!model) {
            throw ( new Error(`Chat model ${modelId} could not be found.`));
        }
        const provider = this._providers.get(model.vendor);
        if (!provider) {
            throw ( new Error(`Chat provider for model ${modelId} is not registered.`));
        }
        return provider.provideTokenCount(modelId, message, token);
    }
    getModelConfiguration(modelId) {
        const metadata = this._modelCache.get(modelId);
        return this._resolveModelConfigurationWithDefaults(modelId, metadata);
    }
    async setModelConfiguration(modelId, values) {
        const metadata = this._modelCache.get(modelId);
        if (!metadata) {
            return;
        }
        const allGroups = this._languageModelsConfigurationService.getLanguageModelsProviderGroups();
        let group;
        group = allGroups.find(
            g => g.vendor === metadata.vendor && g.settings?.[metadata.id] !== undefined
        );
        if (!group) {
            group = allGroups.find(g => g.vendor === metadata.vendor);
        }
        const existingConfig = this._modelConfigurations.get(modelId) ?? {};
        const updatedConfig = {
            ...existingConfig,
            ...values
        };
        const schema = metadata.configurationSchema;
        if (schema?.properties) {
            for (const [key, value] of Object.entries(updatedConfig)) {
                const propSchema = schema.properties[key];
                if (propSchema?.default !== undefined && propSchema.default === value) {
                    delete updatedConfig[key];
                }
            }
        }
        if (group) {
            const existingSettings = group.settings ?? {};
            let updatedSettings;
            if (( Object.keys(updatedConfig)).length === 0) {
                updatedSettings = {
                    ...existingSettings
                };
                delete updatedSettings[metadata.id];
            } else {
                updatedSettings = {
                    ...existingSettings,
                    [metadata.id]: updatedConfig
                };
            }
            const updatedGroup = {
                ...group,
                settings: ( Object.keys(updatedSettings)).length > 0 ? updatedSettings : undefined
            };
            if (!updatedGroup.settings && ( Object.keys(updatedGroup)).filter(k => k !== "name" && k !== "vendor" && k !== "range" && k !== "settings").length === 0) {
                await this._languageModelsConfigurationService.removeLanguageModelsProviderGroup(group);
            } else {
                await this._languageModelsConfigurationService.updateLanguageModelsProviderGroup(group, updatedGroup);
            }
        } else if (( Object.keys(updatedConfig)).length > 0) {
            const vendor = this.getVendors().find(v => v.vendor === metadata.vendor);
            if (!vendor) {
                return;
            }
            const newGroup = {
                name: vendor.displayName,
                vendor: metadata.vendor,
                settings: {
                    [metadata.id]: updatedConfig
                }
            };
            await this._languageModelsConfigurationService.addLanguageModelsProviderGroup(newGroup);
        }
        if (( Object.keys(updatedConfig)).length > 0) {
            this._modelConfigurations.set(modelId, updatedConfig);
        } else {
            this._modelConfigurations.delete(modelId);
        }
        this._onLanguageModelChange.fire(metadata.vendor);
    }
    getModelConfigurationActions(modelId) {
        const metadata = this._modelCache.get(modelId);
        const schema = metadata?.configurationSchema;
        if (!schema?.properties) {
            return [];
        }
        const actions = [];
        const currentConfig = this._modelConfigurations.get(modelId) ?? {};
        for (const [key, propSchema] of Object.entries(schema.properties)) {
            if (!propSchema.enum || !Array.isArray(propSchema.enum)) {
                continue;
            }
            const currentValue = currentConfig[key] ?? propSchema.default;
            const label = (typeof propSchema.title === "string" ? propSchema.title : undefined) ?? key.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/^./, s => s.toUpperCase());
            const defaultValue = propSchema.default;
            const enumItemLabels = propSchema.enumItemLabels;
            const enumDescriptions = propSchema.enumDescriptions;
            const enumActions = ( propSchema.enum.map((value, index) => {
                const itemLabel = enumItemLabels?.[index] ?? String(value);
                const displayLabel = value === defaultValue ? ( localize(7225, "{0} (default)", itemLabel)) : itemLabel;
                const tooltip = enumDescriptions?.[index] ?? "";
                return {
                    id: `configureModel.${key}.${value}`,
                    label: displayLabel,
                    class: undefined,
                    enabled: true,
                    tooltip,
                    checked: currentValue === value,
                    run: () => this.setModelConfiguration(modelId, {
                        [key]: value
                    })
                };
            }));
            actions.push(( new SubmenuAction(`configureModel.${key}`, label, enumActions)));
        }
        return actions;
    }
    async configureLanguageModelsProviderGroup(vendorId, providerGroupName) {
        const vendor = this.getVendors().find((
            {
                vendor
            }
        ) => vendor === vendorId);
        if (!vendor) {
            throw ( new Error(`Vendor ${vendorId} not found.`));
        }
        if (vendor.managementCommand) {
            await this._resolveAllLanguageModels(vendor.vendor, false);
            return;
        }
        const languageModelProviderGroups = this._languageModelsConfigurationService.getLanguageModelsProviderGroups();
        const existing = languageModelProviderGroups.find(g => g.vendor === vendorId && g.name === providerGroupName);
        const name = await this.promptForName(languageModelProviderGroups, vendor, existing);
        if (!name) {
            return;
        }
        const existingConfiguration = existing ? await this._resolveConfiguration(existing, vendor.configuration) : undefined;
        try {
            const configuration = vendor.configuration ? await this.promptForConfiguration(name, vendor.configuration, existingConfiguration) : undefined;
            if (vendor.configuration && !configuration) {
                return;
            }
            const languageModelProviderGroup = await this._resolveLanguageModelProviderGroup(name, vendorId, configuration, vendor.configuration);
            const saved = existing ? await this._languageModelsConfigurationService.updateLanguageModelsProviderGroup(existing, languageModelProviderGroup) : await this._languageModelsConfigurationService.addLanguageModelsProviderGroup(languageModelProviderGroup);
            if (vendor.configuration && this.requireConfiguring(vendor.configuration)) {
                const snippet = this.getSnippetForFirstUnconfiguredProperty(configuration ?? {}, vendor.configuration);
                await this._languageModelsConfigurationService.configureLanguageModels({
                    group: saved,
                    snippet
                });
            }
        } catch (error) {
            if (isCancellationError(error)) {
                return;
            }
            throw error;
        }
    }
    async configureModel(modelId) {
        const metadata = this._modelCache.get(modelId);
        if (!metadata || !metadata.configurationSchema) {
            return;
        }
        const vendorGroups = this._modelsGroups.get(metadata.vendor);
        let group;
        if (vendorGroups) {
            for (const vg of vendorGroups) {
                if (vg.modelIdentifiers.includes(modelId) && vg.group) {
                    group = vg.group;
                    break;
                }
            }
        }
        if (!group) {
            const vendor = this.getVendors().find(v => v.vendor === metadata.vendor);
            if (!vendor) {
                return;
            }
            const groupName = vendor.displayName;
            const newGroup = {
                name: groupName,
                vendor: metadata.vendor,
                settings: {
                    [metadata.id]: {}
                }
            };
            group = await this._languageModelsConfigurationService.addLanguageModelsProviderGroup(newGroup);
            await this._resolveAllLanguageModels(metadata.vendor, true);
        }
        const snippet = this._getModelConfigurationSnippet(metadata.id, metadata.configurationSchema);
        await this._languageModelsConfigurationService.configureLanguageModels({
            group,
            snippet
        });
    }
    _getModelConfigurationSnippet(modelId, schema) {
        const properties = [];
        if (schema.properties) {
            for (const [key, propSchema] of Object.entries(schema.properties)) {
                if (propSchema.defaultSnippets?.[0]) {
                    const snippet = propSchema.defaultSnippets[0];
                    let bodyText = snippet.bodyText ?? JSON.stringify(snippet.body, null, "\t\t\t");
                    bodyText = bodyText.replace(/"(\^[^"]*)"/g, (_, value) => value.substring(1));
                    properties.push(`\t\t\t"${key}": ${bodyText}`);
                } else if (propSchema.default !== undefined) {
                    properties.push(`\t\t\t"${key}": ${JSON.stringify(propSchema.default)}`);
                } else {
                    properties.push(`\t\t\t"${key}": $\{${key}\}`);
                }
            }
        }
        const modelContent = properties.length > 0 ? `{\n${properties.join(",\n")}\n\t\t}` : "{\n\t\t\t$0\n\t\t}";
        return `"settings": {\n\t\t"${modelId}": ${modelContent}\n\t}`;
    }
    async addLanguageModelsProviderGroup(name, vendorId, configuration) {
        const vendor = this.getVendors().find((
            {
                vendor
            }
        ) => vendor === vendorId);
        if (!vendor) {
            throw ( new Error(`Vendor ${vendorId} not found.`));
        }
        const languageModelProviderGroup = await this._resolveLanguageModelProviderGroup(name, vendorId, configuration, vendor.configuration);
        await this._languageModelsConfigurationService.addLanguageModelsProviderGroup(languageModelProviderGroup);
    }
    async removeLanguageModelsProviderGroup(vendorId, providerGroupName) {
        const vendor = this.getVendors().find((
            {
                vendor
            }
        ) => vendor === vendorId);
        if (!vendor) {
            throw ( new Error(`Vendor ${vendorId} not found.`));
        }
        const languageModelProviderGroups = this._languageModelsConfigurationService.getLanguageModelsProviderGroups();
        const existing = languageModelProviderGroups.find(g => g.vendor === vendorId && g.name === providerGroupName);
        if (!existing) {
            throw ( new Error(
                `Language model provider group ${providerGroupName} for vendor ${vendorId} not found.`
            ));
        }
        await this._deleteSecretsInConfiguration(existing, vendor.configuration);
        await this._languageModelsConfigurationService.removeLanguageModelsProviderGroup(existing);
    }
    requireConfiguring(schema) {
        if (schema.additionalProperties) {
            return true;
        }
        if (!schema.properties) {
            return false;
        }
        for (const property of ( Object.keys(schema.properties))) {
            if (!this.canPromptForProperty(schema.properties[property])) {
                return true;
            }
        }
        return false;
    }
    getSnippetForFirstUnconfiguredProperty(configuration, schema) {
        if (!schema.properties) {
            return undefined;
        }
        for (const property of ( Object.keys(schema.properties))) {
            if (configuration[property] === undefined) {
                const propertySchema = schema.properties[property];
                if (propertySchema && typeof propertySchema !== "boolean" && propertySchema.defaultSnippets?.[0]) {
                    const snippet = propertySchema.defaultSnippets[0];
                    let bodyText = snippet.bodyText ?? JSON.stringify(snippet.body, null, "\t");
                    bodyText = bodyText.replace(/"(\^[^"]*)"/g, (_, value) => value.substring(1));
                    return `"${property}": ${bodyText}`;
                }
            }
        }
        return undefined;
    }
    async promptForName(languageModelProviderGroups, vendor, existing) {
        let providerGroupName = existing?.name;
        if (!providerGroupName) {
            providerGroupName = vendor.displayName;
            let count = 1;
            while (( languageModelProviderGroups.some(g => g.vendor === vendor.vendor && g.name === providerGroupName))) {
                count++;
                providerGroupName = `${vendor.displayName} ${count}`;
            }
        }
        let result;
        const disposables = ( new DisposableStore());
        try {
            await ( new Promise(resolve => {
                const inputBox = disposables.add(this._quickInputService.createInputBox());
                inputBox.title = ( localize(7226, "Group Name"));
                inputBox.placeholder = ( localize(7227, "Enter a name for the group"));
                inputBox.value = providerGroupName;
                inputBox.ignoreFocusOut = true;
                disposables.add(inputBox.onDidChangeValue(value => {
                    if (!value) {
                        inputBox.validationMessage = ( localize(7228, "Please enter a name"));
                        inputBox.severity = Severity$1.Error;
                        return;
                    }
                    if (!existing && ( languageModelProviderGroups.some(g => g.name === value))) {
                        inputBox.validationMessage = ( localize(7229, "A language models group with this name already exists"));
                        inputBox.severity = Severity$1.Error;
                        return;
                    }
                    inputBox.validationMessage = undefined;
                    inputBox.severity = Severity$1.Ignore;
                }));
                disposables.add(inputBox.onDidAccept(async () => {
                    result = inputBox.value;
                    inputBox.hide();
                }));
                disposables.add(inputBox.onDidHide(() => resolve()));
                inputBox.show();
            }));
        } finally {
            disposables.dispose();
        }
        return result;
    }
    async promptForConfiguration(groupName, configuration, existing) {
        if (!configuration.properties) {
            return;
        }
        const result = existing ? {
            ...existing
        } : {};
        for (const property of ( Object.keys(configuration.properties))) {
            const propertySchema = configuration.properties[property];
            const required = !!configuration.required?.includes(property);
            const value = await this.promptForValue(groupName, property, propertySchema, required, existing);
            if (value !== undefined) {
                result[property] = value;
            }
        }
        return result;
    }
    async promptForValue(groupName, property, propertySchema, required, existing) {
        if (!propertySchema) {
            return undefined;
        }
        if (!this.canPromptForProperty(propertySchema)) {
            return undefined;
        }
        if (propertySchema.type === "array" && propertySchema.items && !Array.isArray(propertySchema.items) && propertySchema.items.enum) {
            const selectedItems = await this.promptForArray(groupName, property, propertySchema);
            if (selectedItems === undefined) {
                return undefined;
            }
            return selectedItems;
        }
        const value = await this.promptForInput(groupName, property, propertySchema, required, existing);
        if (value === undefined) {
            return undefined;
        }
        return value;
    }
    canPromptForProperty(propertySchema) {
        if (!propertySchema || typeof propertySchema === "boolean") {
            return false;
        }
        if (propertySchema.type === "array" && propertySchema.items && !Array.isArray(propertySchema.items) && propertySchema.items.enum) {
            return true;
        }
        if (propertySchema.type === "string" || propertySchema.type === "number" || propertySchema.type === "integer" || propertySchema.type === "boolean") {
            return true;
        }
        return false;
    }
    async promptForArray(groupName, property, propertySchema) {
        if (!propertySchema.items || Array.isArray(propertySchema.items) || !propertySchema.items.enum) {
            return undefined;
        }
        const items = propertySchema.items.enum;
        const disposables = ( new DisposableStore());
        try {
            return await ( new Promise(resolve => {
                const quickPick = disposables.add(this._quickInputService.createQuickPick());
                quickPick.title = `${groupName}: ${propertySchema.title ?? property}`;
                quickPick.items = ( items.map(item => ({
                    label: item
                })));
                quickPick.placeholder = propertySchema.description ?? ( localize(7230, "Select value for {0}", property));
                quickPick.canSelectMany = true;
                quickPick.ignoreFocusOut = true;
                disposables.add(quickPick.onDidAccept(() => {
                    resolve(( quickPick.selectedItems.map(item => item.label)));
                    quickPick.hide();
                }));
                disposables.add(quickPick.onDidHide(() => {
                    resolve(undefined);
                }));
                quickPick.show();
            }));
        } finally {
            disposables.dispose();
        }
    }
    async promptForInput(groupName, property, propertySchema, required, existing) {
        const disposables = ( new DisposableStore());
        try {
            const value = await ( new Promise((resolve, reject) => {
                const inputBox = disposables.add(this._quickInputService.createInputBox());
                inputBox.title = `${groupName}: ${propertySchema.title ?? property}`;
                inputBox.placeholder = ( localize(7231, "Enter value for {0}", property));
                inputBox.password = !!propertySchema.secret;
                inputBox.ignoreFocusOut = true;
                if (existing?.[property]) {
                    inputBox.value = String(existing?.[property]);
                } else if (propertySchema.default) {
                    inputBox.value = String(propertySchema.default);
                }
                if (propertySchema.description) {
                    inputBox.prompt = propertySchema.description;
                }
                disposables.add(inputBox.onDidChangeValue(value => {
                    if (!value && required) {
                        inputBox.validationMessage = ( localize(7232, "Value is required"));
                        inputBox.severity = Severity$1.Error;
                        return;
                    }
                    if (propertySchema.type === "number" || propertySchema.type === "integer") {
                        if (isNaN(Number(value))) {
                            inputBox.validationMessage = ( localize(7233, "Please enter a number"));
                            inputBox.severity = Severity$1.Error;
                            return;
                        }
                    }
                    if (propertySchema.type === "boolean") {
                        if (value !== "true" && value !== "false") {
                            inputBox.validationMessage = ( localize(7234, "Please enter true or false"));
                            inputBox.severity = Severity$1.Error;
                            return;
                        }
                    }
                    inputBox.validationMessage = undefined;
                    inputBox.severity = Severity$1.Ignore;
                }));
                disposables.add(inputBox.onDidAccept(() => {
                    if (!inputBox.value && required) {
                        inputBox.validationMessage = ( localize(7232, "Value is required"));
                        inputBox.severity = Severity$1.Error;
                        return;
                    }
                    resolve(inputBox.value);
                    inputBox.hide();
                }));
                disposables.add(inputBox.onDidHide(e => {
                    if (e.reason === QuickInputHideReason.Gesture) {
                        reject(( new CancellationError()));
                    } else {
                        resolve(undefined);
                    }
                }));
                inputBox.show();
            }));
            if (!value) {
                return undefined;
            }
            if (propertySchema.type === "number" || propertySchema.type === "integer") {
                return Number(value);
            } else if (propertySchema.type === "boolean") {
                return value === "true";
            } else {
                return value;
            }
        } finally {
            disposables.dispose();
        }
    }
    encodeSecretKey(property) {
        return format(LanguageModelsService_1.SECRET_INPUT, property);
    }
    decodeSecretKey(secretInput) {
        if (!isString(secretInput)) {
            return undefined;
        }
        return secretInput.substring(secretInput.indexOf(":") + 1, secretInput.length - 1);
    }
    _clearModelCache(vendor) {
        const removed = ( new Map());
        for (const [id, model] of this._modelCache.entries()) {
            if (model.vendor === vendor) {
                removed.set(id, model);
                this._modelCache.delete(id);
            }
        }
        return removed;
    }
    _clearModelConfigurations(vendor) {
        for (const [id] of this._modelConfigurations) {
            if (this._modelCache.get(id)?.vendor === vendor || id.startsWith(`${vendor}/`)) {
                this._modelConfigurations.delete(id);
            }
        }
    }
    async _resolveConfiguration(group, schema) {
        if (!schema) {
            return {};
        }
        const result = {};
        for (const key in group) {
            if (key === "vendor" || key === "name" || key === "range" || key === "settings") {
                continue;
            }
            let value = group[key];
            if (schema.properties?.[key]?.secret) {
                const secretKey = this.decodeSecretKey(value);
                value = secretKey ? await this._secretStorageService.get(secretKey) : undefined;
            }
            result[key] = value;
        }
        return result;
    }
    async _resolveLanguageModelProviderGroup(name, vendor, configuration, schema) {
        if (!schema) {
            return {
                name,
                vendor
            };
        }
        const result = {};
        for (const key in configuration) {
            let value = configuration[key];
            if (schema.properties?.[key]?.secret && isString(value)) {
                const secretKey = `${LanguageModelsService_1.SECRET_KEY_PREFIX}${( hash(generateUuid()).toString(16))}`;
                await this._secretStorageService.set(secretKey, value);
                value = this.encodeSecretKey(secretKey);
            }
            result[key] = value;
        }
        return {
            name,
            vendor,
            ...result
        };
    }
    async _deleteSecretsInConfiguration(group, schema) {
        if (!schema) {
            return;
        }
        const {
            vendor,
            name,
            range,
            ...configuration
        } = group;
        for (const key in configuration) {
            const value = group[key];
            if (schema.properties?.[key]?.secret) {
                const secretKey = this.decodeSecretKey(value);
                if (secretKey) {
                    await this._secretStorageService.delete(secretKey);
                }
            }
        }
    }
    async migrateLanguageModelsProviderGroup(languageModelsProviderGroup) {
        const {
            vendor,
            name,
            ...configuration
        } = languageModelsProviderGroup;
        if (!this._vendors.get(vendor)) {
            throw ( new Error(`Vendor ${vendor} not found.`));
        }
        await this._extensionService.activateByEvent(`onLanguageModelChatProvider:${vendor}`);
        const provider = this._providers.get(vendor);
        if (!provider) {
            throw ( new Error(`Chat model provider for vendor ${vendor} is not registered.`));
        }
        const models = await provider.provideLanguageModelChatInfo({
            group: name,
            silent: false,
            configuration
        }, CancellationToken.None);
        for (const model of models) {
            const oldIdentifier = `${vendor}/${model.metadata.id}`;
            if (this._modelPickerUserPreferences[oldIdentifier] === true) {
                this._modelPickerUserPreferences[model.identifier] = true;
            }
            delete this._modelPickerUserPreferences[oldIdentifier];
        }
        this._saveModelPickerPreferences();
        await this.addLanguageModelsProviderGroup(name, vendor, configuration);
    }
    _readRecentlyUsedModels() {
        return this._storageService.getObject(CHAT_MODEL_RECENTLY_USED_STORAGE_KEY, StorageScope.PROFILE, []);
    }
    _saveRecentlyUsedModels() {
        this._storageService.store(
            CHAT_MODEL_RECENTLY_USED_STORAGE_KEY,
            this._recentlyUsedModelIds,
            StorageScope.PROFILE,
            StorageTarget.USER
        );
    }
    getRecentlyUsedModelIds() {
        return this._recentlyUsedModelIds.filter(id => ( this._modelCache.has(id)) && id !== "copilot/auto").slice(0, 4);
    }
    addToRecentlyUsedList(modelIdentifier) {
        if (modelIdentifier === "copilot/auto") {
            return;
        }
        const index = this._recentlyUsedModelIds.indexOf(modelIdentifier);
        if (index !== -1) {
            this._recentlyUsedModelIds.splice(index, 1);
        }
        this._recentlyUsedModelIds.unshift(modelIdentifier);
        if (this._recentlyUsedModelIds.length > 20) {
            this._recentlyUsedModelIds.length = 20;
        }
        this._saveRecentlyUsedModels();
    }
    clearRecentlyUsedList() {
        this._recentlyUsedModelIds = [];
        this._saveRecentlyUsedModels();
    }
    getModelsControlManifest() {
        return this._modelsControlManifest;
    }
    _setModelsControlManifest(response) {
        this._modelsControlRawResponse = response;
        this._refreshModelsControlManifest();
    }
    _refreshModelsControlManifest() {
        const response = this._modelsControlRawResponse;
        const free = {};
        const paid = {};
        if (response?.free) {
            const freeEntries = Array.isArray(response.free) ? response.free : ( Object.values(response.free));
            for (const entry of freeEntries) {
                if (!entry || !isObject(entry)) {
                    continue;
                }
                free[entry.id] = {
                    label: entry.label,
                    featured: entry.featured,
                    exists: ( this._modelCache.has(`copilot/${entry.id}`))
                };
            }
        }
        if (response?.paid) {
            const paidEntries = Array.isArray(response.paid) ? response.paid : ( Object.values(response.paid));
            for (const entry of paidEntries) {
                if (!entry || !isObject(entry)) {
                    continue;
                }
                paid[entry.id] = {
                    label: entry.label,
                    featured: entry.featured,
                    minVSCodeVersion: entry.minVSCodeVersion,
                    exists: ( this._modelCache.has(`copilot/${entry.id}`))
                };
            }
        }
        this._modelsControlManifest = {
            free,
            paid
        };
        this._onDidChangeModelsControlManifest.fire(this._modelsControlManifest);
    }
    _initChatControlData() {
        this._chatControlUrl = this._productService.chatParticipantRegistry;
        if (!this._chatControlUrl) {
            return;
        }
        const raw = this._storageService.get(CHAT_PARTICIPANT_NAME_REGISTRY_STORAGE_KEY, StorageScope.APPLICATION);
        try {
            this._restrictedChatParticipants.set(JSON.parse(raw ?? "{}"), undefined);
        } catch (err) {
            this._storageService.remove(CHAT_PARTICIPANT_NAME_REGISTRY_STORAGE_KEY, StorageScope.APPLICATION);
        }
        const rawModels = this._storageService.get(CHAT_MODELS_CONTROL_STORAGE_KEY, StorageScope.APPLICATION);
        try {
            const models = JSON.parse(rawModels ?? "{}");
            if (isObject(models)) {
                this._setModelsControlManifest(models);
            }
        } catch (err) {
            this._storageService.remove(CHAT_MODELS_CONTROL_STORAGE_KEY, StorageScope.APPLICATION);
        }
        this._refreshChatControlData();
    }
    _refreshChatControlData() {
        if (this._chatControlDisposed) {
            return;
        }
        this._fetchChatControlData().catch(err => this._logService.warn("Failed to fetch chat control data", err)).then(() => timeout(5 * 60 * 1000)).then(() => this._refreshChatControlData());
    }
    async _fetchChatControlData() {
        this._logService.trace("[LM] Fetching chat control data from", this._chatControlUrl);
        let context;
        try {
            context = await this._requestService.request({
                type: "GET",
                url: this._chatControlUrl,
                callSite: "languageModels.fetchChatControlData"
            }, CancellationToken.None);
        } catch (err) {
            this._logService.warn("[LM] Failed to request chat control data", getErrorMessage(err));
            return;
        }
        if (context.res.statusCode !== 200) {
            this._logService.warn(
                `[LM] Chat control data request failed with status ${context.res.statusCode}`
            );
            return;
        }
        let result;
        try {
            result = await asJson(context);
        } catch (err) {
            this._logService.warn("[LM] Failed to parse chat control response", getErrorMessage(err));
            return;
        }
        this._logService.trace("[LM] Received chat control response", result ? ( Object.keys(result)) : "null");
        if (!result || result.version !== 1) {
            this._logService.warn("[LM] Unexpected chat control response version", result?.version);
            return;
        }
        const registry = result.restrictedChatParticipants;
        this._restrictedChatParticipants.set(registry, undefined);
        this._storageService.store(
            CHAT_PARTICIPANT_NAME_REGISTRY_STORAGE_KEY,
            JSON.stringify(registry),
            StorageScope.APPLICATION,
            StorageTarget.MACHINE
        );
        if (result.models) {
            this._logService.trace("[LM] Updating models control manifest", {
                freeCount: ( Object.keys(result.models.free ?? {})).length,
                paidCount: ( Object.keys(result.models.paid ?? {})).length
            });
            this._setModelsControlManifest(result.models);
            this._storageService.store(
                CHAT_MODELS_CONTROL_STORAGE_KEY,
                JSON.stringify(result.models),
                StorageScope.APPLICATION,
                StorageTarget.MACHINE
            );
        }
    }
    dispose() {
        this._chatControlDisposed = true;
        this._store.dispose();
        this._providers.clear();
    }
};
LanguageModelsService = LanguageModelsService_1 = ( __decorate([( __param(0, IExtensionService)), ( __param(1, ILogService)), ( __param(2, IStorageService)), ( __param(3, IContextKeyService)), ( __param(4, ILanguageModelsConfigurationService)), ( __param(5, IQuickInputService)), ( __param(6, ISecretStorageService)), ( __param(7, IProductService)), ( __param(8, IRequestService))], LanguageModelsService));

export { ChatImageMimeType, ChatMessageRole, ILanguageModelChatMetadata, ImageDetailLevel, LanguageModelPartAudience, LanguageModelsService, getTextResponseFromStream, isILanguageModelChatSelector, languageModelChatProviderExtensionPoint };
