"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.runPythonCode = exports.runPython = void 0;
const os_1 = __importDefault(require("os"));
const path_1 = __importDefault(require("path"));
const fs_1 = require("fs");
const python_shell_1 = require("python-shell");
const logger_1 = __importDefault(require("../logger"));
const util_1 = require("../util");
/**
 * Runs a Python script using the provided list of arguments.
 * @param {string} scriptPath - The path to the Python script to run.
 * @param {string} method - The method name to call in the Python script.
 * @param {(string | object)[]} args - The list of arguments to pass to the Python method.
 * @returns {Promise<any>} - The result from the Python script.
 */
async function runPython(scriptPath, method, args, options = {}) {
    const absPath = path_1.default.resolve(scriptPath);
    const tempJsonPath = path_1.default.join(os_1.default.tmpdir(), `promptfoo-python-input-json-${Date.now()}-${Math.random().toString(16).slice(2)}.json`);
    const pythonOptions = {
        mode: 'text',
        pythonPath: options.pythonExecutable || process.env.PROMPTFOO_PYTHON || 'python',
        scriptPath: __dirname,
        args: [absPath, method, tempJsonPath],
    };
    try {
        await fs_1.promises.writeFile(tempJsonPath, (0, util_1.safeJsonStringify)(args));
        const results = await python_shell_1.PythonShell.run('wrapper.py', pythonOptions);
        logger_1.default.debug(`Python script ${absPath} returned: ${results.join('\n')}`);
        let result;
        try {
            result = JSON.parse(results[results.length - 1]);
        }
        catch (error) {
            throw new Error(`Invalid JSON: ${error.message} when parsing result: ${results[results.length - 1]}\nStack Trace: ${error.stack}`);
        }
        if (result?.type !== 'final_result') {
            throw new Error('The Python script `call_api` function must return a dict with an `output`');
        }
        return result.data;
    }
    catch (error) {
        logger_1.default.error(`Error running Python script: ${error.message}\nStack Trace: ${error.stack?.replace('--- Python Traceback ---', 'Python Traceback: ') ||
            'No Python traceback available'}`);
        throw new Error(`Error running Python script: ${error.message}\nStack Trace: ${error.stack?.replace('--- Python Traceback ---', 'Python Traceback: ') ||
            'No Python traceback available'}`);
    }
    finally {
        await fs_1.promises
            .unlink(tempJsonPath)
            .catch((error) => logger_1.default.error(`Error removing temporary file: ${error}`));
    }
}
exports.runPython = runPython;
/**
 * Executes Python code by writing it to a temporary file
 * @param {string} code - The Python code to execute.
 * @param {string} method - The method name to call in the Python script.
 * @param {(string | object | undefined)[]} args - The list of arguments to pass to the Python method.
 * @returns {Promise<any>} - The result from executing the Python code.
 */
async function runPythonCode(code, method, args) {
    const tempFilePath = path_1.default.join(os_1.default.tmpdir(), `temp-python-code-${Date.now()}-${Math.random().toString(16).slice(2)}.py`);
    try {
        await fs_1.promises.writeFile(tempFilePath, code);
        // Necessary to await so temp file doesn't get deleted.
        const result = await runPython(tempFilePath, method, args);
        return result;
    }
    catch (error) {
        logger_1.default.error(`Error executing Python code: ${error}`);
        throw error;
    }
    finally {
        await fs_1.promises
            .unlink(tempFilePath)
            .catch((error) => logger_1.default.error(`Error removing temporary file: ${error}`));
    }
}
exports.runPythonCode = runPythonCode;
//# sourceMappingURL=wrapper.js.map