"use strict";
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
var AvailableModelsManager_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AvailableModelsManager = exports.ICompletionsModelManagerService = void 0;
const authentication_1 = require("../../../../../../platform/authentication/common/authentication");
const endpointProvider_1 = require("../../../../../../platform/endpoint/common/endpointProvider");
const services_1 = require("../../../../../../util/common/services");
const lifecycle_1 = require("../../../../../../util/vs/base/common/lifecycle");
const instantiation_1 = require("../../../../../../util/vs/platform/instantiation/common/instantiation");
const modelPickerUserSelection_1 = require("../../../extension/src/modelPickerUserSelection");
const tokenization_1 = require("../../../prompt/src/tokenization");
const event_1 = require("../util/event");
const copilotTokenNotifier_1 = require("../auth/copilotTokenNotifier");
const config_1 = require("../config");
const featuresService_1 = require("../experiments/featuresService");
const logger_1 = require("../logger");
exports.ICompletionsModelManagerService = (0, services_1.createServiceIdentifier)('ICompletionsModelManagerService');
const FallbackModelId = 'gpt-41-copilot';
let AvailableModelsManager = AvailableModelsManager_1 = class AvailableModelsManager extends lifecycle_1.Disposable {
    constructor(shouldFetch = true, _instantiationService, _featuresService, _endpointProvider, authenticationService, _logService) {
        super();
        this._instantiationService = _instantiationService;
        this._featuresService = _featuresService;
        this._endpointProvider = _endpointProvider;
        this._logService = _logService;
        this.fetchedModelData = [];
        this.customModels = [];
        this.editorPreviewFeaturesDisabled = false;
        this._onDidChangeModels = this._register(new event_1.Emitter());
        this.onDidChangeModels = this._onDidChangeModels.event;
        if (shouldFetch) {
            this._register((0, copilotTokenNotifier_1.onCopilotToken)(authenticationService, () => this.refreshAvailableModels()));
        }
    }
    // This will get its initial call after the initial token got fetched
    async refreshAvailableModels() {
        await this.refreshModels();
    }
    /**
     * Returns the default model, determined by the order returned from the API
     * Note: this does NOT fetch models to avoid side effects
     */
    getDefaultModelId() {
        if (this.fetchedModelData) {
            const fetchedDefaultModel = AvailableModelsManager_1.filterCompletionModels(this.fetchedModelData, this.editorPreviewFeaturesDisabled)[0];
            if (fetchedDefaultModel) {
                return fetchedDefaultModel.id;
            }
        }
        return FallbackModelId;
    }
    async refreshModels() {
        const fetchedData = await this._endpointProvider.getAllCompletionModels(true);
        if (fetchedData) {
            this.fetchedModelData = fetchedData;
            this._onDidChangeModels.fire();
        }
    }
    /**
     * Returns a list of models that are available for generic completions.
     * Calls to CAPI to retrieve the list.
     */
    getGenericCompletionModels() {
        const filteredResult = AvailableModelsManager_1.filterCompletionModels(this.fetchedModelData, this.editorPreviewFeaturesDisabled);
        return AvailableModelsManager_1.mapCompletionModels(filteredResult);
    }
    getTokenizerForModel(modelId) {
        const modelItems = this.getGenericCompletionModels();
        const modelItem = modelItems.find(item => item.modelId === modelId);
        if (modelItem) {
            return modelItem.tokenizer;
        }
        // The tokenizer the default model uses
        return tokenization_1.TokenizerName.o200k;
    }
    static filterCompletionModels(data, editorPreviewFeaturesDisabled) {
        return data
            .filter(item => item.capabilities.type === 'completion')
            .filter(item => !editorPreviewFeaturesDisabled || item.preview === false || item.preview === undefined);
    }
    static filterModelsWithEditorPreviewFeatures(data, editorPreviewFeaturesDisabled) {
        return data.filter(item => !editorPreviewFeaturesDisabled || item.preview === false || item.preview === undefined);
    }
    static mapCompletionModels(data) {
        return data.map(item => ({
            modelId: item.id,
            label: item.name,
            preview: !!item.preview,
            tokenizer: item.capabilities.tokenizer,
        }));
    }
    getCurrentModelRequestInfo(featureSettings = undefined) {
        const defaultModelId = this.getDefaultModelId();
        let userSelectedCompletionModel = this._instantiationService.invokeFunction(modelPickerUserSelection_1.getUserSelectedModelConfiguration);
        if (userSelectedCompletionModel) {
            const genericModels = this.getGenericCompletionModels().map(model => model.modelId);
            if (!genericModels.includes(userSelectedCompletionModel)) {
                if (genericModels.length > 0) {
                    this._logService.logIt(logger_1.LogLevel.INFO, `User selected model ${userSelectedCompletionModel} is not in the list of generic models: ${genericModels.join(', ')}, falling back to default model.`);
                }
                userSelectedCompletionModel = null;
            }
            if (defaultModelId === userSelectedCompletionModel) {
                userSelectedCompletionModel = null;
            }
        }
        const debugOverride = this._instantiationService.invokeFunction((config_1.getConfig), config_1.ConfigKey.DebugOverrideEngine) ||
            this._instantiationService.invokeFunction((config_1.getConfig), config_1.ConfigKey.DebugOverrideEngineLegacy);
        if (debugOverride) {
            return new ModelRequestInfo(debugOverride, 'override');
        }
        const customEngine = featureSettings ? this._featuresService.customEngine(featureSettings) : undefined;
        const targetEngine = featureSettings ? this._featuresService.customEngineTargetEngine(featureSettings) : undefined;
        if (userSelectedCompletionModel) {
            // If the user selected completion model matches the targetEngine, use the custom engine
            if (customEngine && targetEngine && userSelectedCompletionModel === targetEngine) {
                return new ModelRequestInfo(customEngine, 'exp');
            }
            return new ModelRequestInfo(userSelectedCompletionModel, 'modelpicker');
        }
        if (customEngine) {
            return new ModelRequestInfo(customEngine, 'exp');
        }
        if (this.customModels.length > 0) {
            return new ModelRequestInfo(this.customModels[0], 'custommodel');
        }
        return new ModelRequestInfo(defaultModelId, 'default');
    }
};
exports.AvailableModelsManager = AvailableModelsManager;
exports.AvailableModelsManager = AvailableModelsManager = AvailableModelsManager_1 = __decorate([
    __param(1, instantiation_1.IInstantiationService),
    __param(2, featuresService_1.ICompletionsFeaturesService),
    __param(3, endpointProvider_1.IEndpointProvider),
    __param(4, authentication_1.IAuthenticationService),
    __param(5, logger_1.ICompletionsLogTargetService)
], AvailableModelsManager);
class ModelRequestInfo {
    constructor(modelId, modelChoiceSource) {
        this.modelId = modelId;
        this.modelChoiceSource = modelChoiceSource;
    }
    get headers() {
        return {};
    }
}
//# sourceMappingURL=model.js.map