"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PythonProvider = void 0;
const path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
const logger_1 = __importDefault(require("../logger"));
const cache_1 = require("../cache");
const wrapper_1 = require("../python/wrapper");
const util_1 = require("../util");
class PythonProvider {
    constructor(scriptPath, options) {
        this.scriptPath = scriptPath;
        this.options = options;
        this.id = () => options?.id ?? `python:${this.scriptPath}`;
        this.config = options?.config ?? {};
    }
    id() {
        return `python:${this.scriptPath}`;
    }
    async executePythonScript(prompt, context, apiType) {
        const absPath = path_1.default.resolve(path_1.default.join(this.options?.config.basePath || '', this.scriptPath));
        logger_1.default.debug(`Computing file hash for script ${absPath}`);
        const fileHash = (0, util_1.sha256)(fs_1.default.readFileSync(absPath, 'utf-8'));
        const cacheKey = `python:${this.scriptPath}:${apiType}:${fileHash}:${prompt}:${JSON.stringify(this.options)}`;
        const cache = await (0, cache_1.getCache)();
        let cachedResult;
        if ((0, cache_1.isCacheEnabled)()) {
            cachedResult = (await cache.get(cacheKey));
        }
        if (cachedResult) {
            logger_1.default.debug(`Returning cached ${apiType} result for script ${absPath}`);
            return JSON.parse(cachedResult);
        }
        else {
            if (context) {
                // These are not useful in Python
                delete context.fetchWithCache;
                delete context.getCache;
                delete context.logger;
            }
            const args = apiType === 'call_api' ? [prompt, this.options, context] : [prompt, this.options];
            logger_1.default.debug(`Running python script ${absPath} with scriptPath ${this.scriptPath} and args: ${(0, util_1.safeJsonStringify)(args)}`);
            let result;
            switch (apiType) {
                case 'call_api':
                    result = (await (0, wrapper_1.runPython)(absPath, apiType, args, {
                        pythonExecutable: this.config.pythonExecutable,
                    }));
                    if (!result || (!('output' in result) && !('error' in result))) {
                        throw new Error(`The Python script \`${apiType}\` function must return a dict with an \`output\` string/object or \`error\` string, instead got: ${JSON.stringify(result)}`);
                    }
                    break;
                case 'call_embedding_api':
                    result = (await (0, wrapper_1.runPython)(absPath, apiType, args, {
                        pythonExecutable: this.config.pythonExecutable,
                    }));
                    if (!result || (!('embedding' in result) && !('error' in result))) {
                        throw new Error(`The Python script \`${apiType}\` function must return a dict with an \`embedding\` array or \`error\` string, instead got ${JSON.stringify(result)}`);
                    }
                    break;
                case 'call_classification_api':
                    result = (await (0, wrapper_1.runPython)(absPath, apiType, args, {
                        pythonExecutable: this.config.pythonExecutable,
                    }));
                    if (!result || (!('classification' in result) && !('error' in result))) {
                        throw new Error(`The Python script \`${apiType}\` function must return a dict with a \`classification\` object or \`error\` string, instead of ${JSON.stringify(result)}`);
                    }
                    break;
                default:
                    throw new Error(`Unsupported apiType: ${apiType}`);
            }
            if ((0, cache_1.isCacheEnabled)() && !('error' in result)) {
                await cache.set(cacheKey, JSON.stringify(result));
            }
            return result;
        }
    }
    async callApi(prompt, context) {
        return this.executePythonScript(prompt, context, 'call_api');
    }
    async callEmbeddingApi(prompt) {
        return this.executePythonScript(prompt, undefined, 'call_embedding_api');
    }
    async callClassificationApi(prompt) {
        return this.executePythonScript(prompt, undefined, 'call_classification_api');
    }
}
exports.PythonProvider = PythonProvider;
//# sourceMappingURL=pythonCompletion.js.map