"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PalmChatProvider = void 0;
const cache_1 = require("../cache");
const logger_1 = __importDefault(require("../logger"));
const shared_1 = require("./shared");
const DEFAULT_API_HOST = 'generativelanguage.googleapis.com';
class PalmGenericProvider {
    constructor(modelName, options = {}) {
        const { config, id, env } = options;
        this.env = env;
        this.modelName = modelName;
        this.config = config || {};
        this.id = id ? () => id : this.id;
    }
    id() {
        return `palm:${this.modelName}`;
    }
    toString() {
        return `[Google AI Studio Provider ${this.modelName}]`;
    }
    getApiHost() {
        return (this.config.apiHost ||
            this.env?.GOOGLE_API_HOST ||
            this.env?.PALM_API_HOST ||
            process.env.GOOGLE_API_HOST ||
            process.env.PALM_API_HOST ||
            DEFAULT_API_HOST);
    }
    getApiKey() {
        return (this.config.apiKey ||
            this.env?.GOOGLE_API_KEY ||
            this.env?.PALM_API_KEY ||
            process.env.GOOGLE_API_KEY ||
            process.env.PALM_API_KEY);
    }
    // @ts-ignore: Prompt is not used in this implementation
    async callApi(prompt) {
        throw new Error('Not implemented');
    }
}
class PalmChatProvider extends PalmGenericProvider {
    constructor(modelName, options = {}) {
        if (!PalmChatProvider.CHAT_MODELS.includes(modelName)) {
            logger_1.default.warn(`Using unknown Google chat model: ${modelName}`);
        }
        super(modelName, options);
    }
    async callApi(prompt) {
        if (!this.getApiKey()) {
            throw new Error('Google API key is not set. Set the GOOGLE_API_KEY environment variable or add `apiKey` to the provider config.');
        }
        const isGemini = this.modelName.startsWith('gemini');
        if (isGemini) {
            return this.callGemini(prompt);
        }
        // https://developers.generativeai.google/tutorials/curl_quickstart
        // https://ai.google.dev/api/rest/v1beta/models/generateMessage
        const messages = (0, shared_1.parseChatPrompt)(prompt, [{ content: prompt }]);
        const body = {
            prompt: { messages },
            temperature: this.config.temperature,
            topP: this.config.topP,
            topK: this.config.topK,
            safetySettings: this.config.safetySettings,
            stopSequences: this.config.stopSequences,
            maxOutputTokens: this.config.maxOutputTokens,
        };
        logger_1.default.debug(`Calling Google API: ${JSON.stringify(body)}`);
        let data;
        try {
            ({ data } = (await (0, cache_1.fetchWithCache)(`https://${this.getApiHost()}/v1beta3/models/${this.modelName}:generateMessage?key=${this.getApiKey()}`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(body),
            }, shared_1.REQUEST_TIMEOUT_MS)));
        }
        catch (err) {
            return {
                error: `API call error: ${String(err)}`,
            };
        }
        logger_1.default.debug(`\tGoogle API response: ${JSON.stringify(data)}`);
        if (!data?.candidates || data.candidates.length === 0) {
            return {
                error: `API did not return any candidate responses: ${JSON.stringify(data)}`,
            };
        }
        try {
            const output = data.candidates[0].content;
            return {
                output,
            };
        }
        catch (err) {
            return {
                error: `API response error: ${String(err)}: ${JSON.stringify(data)}`,
            };
        }
    }
    async callGemini(prompt) {
        const contents = (0, shared_1.parseChatPrompt)(prompt, [{ parts: [{ text: prompt }] }]);
        const body = {
            contents,
            generationConfig: {
                temperature: this.config.temperature,
                topP: this.config.topP,
                topK: this.config.topK,
                stopSequences: this.config.stopSequences,
                maxOutputTokens: this.config.maxOutputTokens,
                ...this.config.generationConfig,
            },
            safetySettings: this.config.safetySettings,
        };
        logger_1.default.debug(`Calling Google API: ${JSON.stringify(body)}`);
        let data;
        try {
            // https://ai.google.dev/docs/gemini_api_overview#curl
            // https://ai.google.dev/tutorials/rest_quickstart
            ({ data } = (await (0, cache_1.fetchWithCache)(`https://${this.getApiHost()}/v1beta/models/${this.modelName}:generateContent?key=${this.getApiKey()}`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(body),
            }, shared_1.REQUEST_TIMEOUT_MS)));
        }
        catch (err) {
            return {
                error: `API call error: ${String(err)}`,
            };
        }
        logger_1.default.debug(`\tGoogle API response: ${JSON.stringify(data)}`);
        if (!data?.candidates || data.candidates.length === 0) {
            return {
                error: `API did not return any candidate responses: ${JSON.stringify(data)}`,
            };
        }
        const candidate = data.candidates[0];
        const parts = candidate.content.parts.map((part) => part.text).join('');
        try {
            return {
                output: parts,
            };
        }
        catch (err) {
            return {
                error: `API response error: ${String(err)}: ${JSON.stringify(data)}`,
            };
        }
    }
}
exports.PalmChatProvider = PalmChatProvider;
PalmChatProvider.CHAT_MODELS = ['chat-bison-001', 'gemini-pro', 'gemini-pro-vision'];
//# sourceMappingURL=palm.js.map