"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.OllamaEmbeddingProvider = exports.OllamaChatProvider = exports.OllamaCompletionProvider = void 0;
const logger_1 = __importDefault(require("../logger"));
const cache_1 = require("../cache");
const shared_1 = require("./shared");
const OllamaCompletionOptionKeys = new Set([
    'num_predict',
    'top_k',
    'top_p',
    'tfs_z',
    'seed',
    'useNUMA',
    'num_ctx',
    'num_keep',
    'num_batch',
    'num_gqa',
    'num_gpu',
    'main_gpu',
    'low_vram',
    'f16_kv',
    'logits_all',
    'vocab_only',
    'use_mmap',
    'use_mlock',
    'embedding_only',
    'rope_frequency_base',
    'rope_frequency_scale',
    'typical_p',
    'repeat_last_n',
    'temperature',
    'repeat_penalty',
    'presence_penalty',
    'frequency_penalty',
    'mirostat',
    'mirostat_tau',
    'mirostat_eta',
    'penalize_newline',
    'stop',
    'num_thread',
]);
class OllamaCompletionProvider {
    constructor(modelName, options = {}) {
        const { id, config } = options;
        this.modelName = modelName;
        this.id = id ? () => id : this.id;
        this.config = config || {};
    }
    id() {
        return `ollama:completion:${this.modelName}`;
    }
    toString() {
        return `[Ollama Completion Provider ${this.modelName}]`;
    }
    async callApi(prompt) {
        const params = {
            model: this.modelName,
            prompt,
            options: Object.keys(this.config).reduce((options, key) => {
                const optionName = key;
                if (OllamaCompletionOptionKeys.has(optionName)) {
                    options[optionName] = this.config[optionName];
                }
                return options;
            }, {}),
        };
        logger_1.default.debug(`Calling Ollama API: ${JSON.stringify(params)}`);
        let response;
        try {
            response = await (0, cache_1.fetchWithCache)(`${process.env.OLLAMA_BASE_URL || 'http://localhost:11434'}/api/generate`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    ...(process.env.OLLAMA_API_KEY
                        ? { Authorization: `Bearer ${process.env.OLLAMA_API_KEY}` }
                        : {}),
                },
                body: JSON.stringify(params),
            }, shared_1.REQUEST_TIMEOUT_MS, 'text');
        }
        catch (err) {
            return {
                error: `API call error: ${String(err)}. Output:\n${response?.data}`,
            };
        }
        logger_1.default.debug(`\tOllama generate API response: ${response.data}`);
        if (response.data.error) {
            return {
                error: `Ollama error: ${response.data.error}`,
            };
        }
        try {
            const output = response.data
                .split('\n')
                .filter((line) => line.trim() !== '')
                .map((line) => {
                const parsed = JSON.parse(line);
                if (parsed.response) {
                    return parsed.response;
                }
                return null;
            })
                .filter((s) => s !== null)
                .join('');
            return {
                output,
            };
        }
        catch (err) {
            return {
                error: `Ollama API response error: ${String(err)}: ${JSON.stringify(response.data)}`,
            };
        }
    }
}
exports.OllamaCompletionProvider = OllamaCompletionProvider;
class OllamaChatProvider {
    constructor(modelName, options = {}) {
        const { id, config } = options;
        this.modelName = modelName;
        this.id = id ? () => id : this.id;
        this.config = config || {};
    }
    id() {
        return `ollama:chat:${this.modelName}`;
    }
    toString() {
        return `[Ollama Chat Provider ${this.modelName}]`;
    }
    async callApi(prompt) {
        const messages = (0, shared_1.parseChatPrompt)(prompt, [{ role: 'user', content: prompt }]);
        const params = {
            model: this.modelName,
            messages,
            options: Object.keys(this.config).reduce((options, key) => {
                const optionName = key;
                if (OllamaCompletionOptionKeys.has(optionName)) {
                    options[optionName] = this.config[optionName];
                }
                return options;
            }, {}),
        };
        logger_1.default.debug(`Calling Ollama API: ${JSON.stringify(params)}`);
        let response;
        try {
            response = await (0, cache_1.fetchWithCache)(`${process.env.OLLAMA_BASE_URL || 'http://localhost:11434'}/api/chat`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    ...(process.env.OLLAMA_API_KEY
                        ? { Authorization: `Bearer ${process.env.OLLAMA_API_KEY}` }
                        : {}),
                },
                body: JSON.stringify(params),
            }, shared_1.REQUEST_TIMEOUT_MS, 'text');
        }
        catch (err) {
            return {
                error: `API call error: ${String(err)}. Output:\n${response?.data}`,
            };
        }
        logger_1.default.debug(`\tOllama generate API response: ${response.data}`);
        if (response.data.error) {
            return {
                error: `Ollama error: ${response.data.error}`,
            };
        }
        try {
            const output = response.data
                .split('\n')
                .filter((line) => line.trim() !== '')
                .map((line) => {
                const parsed = JSON.parse(line);
                if (parsed.message?.content) {
                    return parsed.message.content;
                }
                return null;
            })
                .filter((s) => s !== null)
                .join('');
            return {
                output,
            };
        }
        catch (err) {
            return {
                error: `Ollama API response error: ${String(err)}: ${JSON.stringify(response.data)}`,
            };
        }
    }
}
exports.OllamaChatProvider = OllamaChatProvider;
class OllamaEmbeddingProvider extends OllamaCompletionProvider {
    async callEmbeddingApi(text) {
        const params = {
            model: this.modelName,
            prompt: text,
        };
        logger_1.default.debug(`Calling Ollama API: ${JSON.stringify(params)}`);
        let response;
        try {
            response = await (0, cache_1.fetchWithCache)(`${process.env.OLLAMA_BASE_URL || 'http://localhost:11434'}/api/embeddings`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    ...(process.env.OLLAMA_API_KEY
                        ? { Authorization: `Bearer ${process.env.OLLAMA_API_KEY}` }
                        : {}),
                },
                body: JSON.stringify(params),
            }, shared_1.REQUEST_TIMEOUT_MS, 'json');
        }
        catch (err) {
            return {
                error: `API call error: ${String(err)}`,
            };
        }
        logger_1.default.debug(`\tOllama embeddings API response: ${JSON.stringify(response.data)}`);
        try {
            const embedding = response.data.embeddings;
            if (!embedding) {
                throw new Error('No embedding found in Ollama embeddings API response');
            }
            return {
                embedding,
            };
        }
        catch (err) {
            return {
                error: `API response error: ${String(err)}: ${JSON.stringify(response.data)}`,
            };
        }
    }
}
exports.OllamaEmbeddingProvider = OllamaEmbeddingProvider;
//# sourceMappingURL=ollama.js.map