"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ScriptCompletionProvider = void 0;
const child_process_1 = require("child_process");
const tiny_invariant_1 = __importDefault(require("tiny-invariant"));
const logger_1 = __importDefault(require("../logger"));
const cache_1 = require("../cache");
const util_1 = require("../util");
const ANSI_ESCAPE = /\x1b(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g;
function stripText(text) {
    return text.replace(ANSI_ESCAPE, '');
}
class ScriptCompletionProvider {
    constructor(scriptPath, options) {
        this.scriptPath = scriptPath;
        this.options = options;
    }
    id() {
        return `exec:${this.scriptPath}`;
    }
    async callApi(prompt, context) {
        const cacheKey = `exec:${this.scriptPath}:${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 result for script ${this.scriptPath}: ${cachedResult}`);
            return JSON.parse(cachedResult);
        }
        else {
            return new Promise((resolve, reject) => {
                const scriptPartsRegex = /[^\s"']+|"([^"]*)"|'([^']*)'/g;
                let match;
                const scriptParts = [];
                while ((match = scriptPartsRegex.exec(this.scriptPath)) !== null) {
                    // If it's a quoted match, push the first group (ignoring the quotes)
                    if (match[1]) {
                        scriptParts.push(match[1]);
                    }
                    else if (match[2]) {
                        // If it's a single-quoted match, push the second group (ignoring the quotes)
                        scriptParts.push(match[2]);
                    }
                    else {
                        // Otherwise, push the whole match
                        scriptParts.push(match[0]);
                    }
                }
                const command = scriptParts.shift();
                (0, tiny_invariant_1.default)(command, 'No command found in script path');
                // These are not useful in the shell
                delete context?.fetchWithCache;
                delete context?.getCache;
                delete context?.logger;
                const scriptArgs = scriptParts.concat([
                    prompt,
                    (0, util_1.safeJsonStringify)(this.options || {}),
                    (0, util_1.safeJsonStringify)(context || {}),
                ]);
                const options = this.options?.config.basePath ? { cwd: this.options.config.basePath } : {};
                (0, child_process_1.execFile)(command, scriptArgs, options, async (error, stdout, stderr) => {
                    if (error) {
                        logger_1.default.debug(`Error running script ${this.scriptPath}: ${error.message}`);
                        reject(error);
                        return;
                    }
                    const standardOutput = stripText(String(stdout).trim());
                    const errorOutput = stripText(String(stderr).trim());
                    if (errorOutput) {
                        logger_1.default.debug(`Error output from script ${this.scriptPath}: ${errorOutput}`);
                        if (!standardOutput) {
                            reject(new Error(errorOutput));
                            return;
                        }
                    }
                    logger_1.default.debug(`Output from script ${this.scriptPath}: ${standardOutput}`);
                    const result = { output: standardOutput };
                    if ((0, cache_1.isCacheEnabled)()) {
                        await cache.set(cacheKey, JSON.stringify(result));
                    }
                    resolve(result);
                });
            });
        }
    }
}
exports.ScriptCompletionProvider = ScriptCompletionProvider;
//# sourceMappingURL=scriptCompletion.js.map