"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NodeRunner = void 0;
exports.resolveShell = resolveShell;
const child_process_1 = require("child_process");
const fs_1 = require("fs");
const path_1 = require("path");
const util_1 = require("util");
const variable_resolver_js_1 = require("./variable-resolver.js");
const command_loader_js_1 = require("../commands/command-loader.js");
const prompt_builder_js_1 = require("../commands/prompt-builder.js");
const exec = (0, util_1.promisify)(child_process_1.exec);
// On Windows, prefer Git Bash for POSIX shell compatibility.
// Most Windows developers have Git for Windows installed.
const IS_WIN = process.platform === 'win32';
const GIT_BASH_CANDIDATES = [
    'C:\\Program Files\\Git\\bin\\bash.exe',
    'C:\\Program Files (x86)\\Git\\bin\\bash.exe',
    // Scoop
    (0, path_1.join)(process.env.USERPROFILE ?? '', 'scoop', 'apps', 'git', 'current', 'bin', 'bash.exe'),
    // Chocolatey
    'C:\\ProgramData\\chocolatey\\tools\\git\\bin\\bash.exe',
];
let _cachedShell = null; // null = not resolved yet
function resolveShell() {
    if (_cachedShell !== null)
        return _cachedShell;
    if (!IS_WIN) {
        _cachedShell = undefined;
        return undefined;
    }
    // Check known paths
    for (const p of GIT_BASH_CANDIDATES) {
        if ((0, fs_1.existsSync)(p)) {
            _cachedShell = p;
            return p;
        }
    }
    // Try `where bash` — finds bash on PATH (e.g. custom Git install, WSL)
    try {
        const out = (0, child_process_1.execSync)('where bash', { stdio: 'pipe', encoding: 'utf-8' });
        const firstLine = out.trim().split('\n')[0]?.trim();
        if (firstLine && (0, fs_1.existsSync)(firstLine)) {
            _cachedShell = firstLine;
            return firstLine;
        }
    }
    catch { /* not on PATH */ }
    // No bash found — fall back to cmd.exe (Node.js default on Windows).
    // Simple commands (npm test, git commit, etc.) work fine in cmd.exe.
    // Only complex POSIX syntax ($(…), set -e, here-docs) would need bash.
    _cachedShell = undefined;
    return undefined;
}
class NodeRunner {
    workspaceCwd;
    projectCwd;
    constructor(workspaceCwd, projectCwd) {
        this.workspaceCwd = workspaceCwd;
        this.projectCwd = projectCwd;
    }
    getCwd(node) {
        if (!node.workspace && this.projectCwd)
            return this.projectCwd;
        return this.workspaceCwd;
    }
    async runBash(node, ctx) {
        const startedAt = new Date().toISOString();
        const startTime = Date.now();
        const resolvedScript = (0, variable_resolver_js_1.resolveVariables)(node.content, ctx, 'bash');
        const timeoutMs = node.timeout ?? 300_000; // 5 min default
        const { stdout } = await exec(resolvedScript, {
            cwd: this.getCwd(node),
            env: { ...process.env, ARTIFACTS_DIR: ctx.ARTIFACTS_DIR },
            maxBuffer: 10 * 1024 * 1024,
            timeout: timeoutMs,
            ...(resolveShell() ? { shell: resolveShell() } : {}),
        });
        let structuredOutput;
        try {
            const parsed = JSON.parse(stdout);
            if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
                structuredOutput = parsed;
            }
        }
        catch { /* not JSON — leave undefined */ }
        return {
            status: 'completed',
            output: stdout,
            structuredOutput,
            durationMs: Date.now() - startTime,
            startedAt,
            completedAt: new Date().toISOString(),
        };
    }
    resolveAIPrompt(node, ctx) {
        if (node.type === 'command') {
            if (!this.projectCwd)
                throw new Error(`Command node "${node.id}" requires projectPath`);
            const cmd = (0, command_loader_js_1.loadCommand)(node.content, this.projectCwd);
            return {
                prompt: (0, prompt_builder_js_1.buildPrompt)(cmd.body, ctx),
                skill: cmd.skill,
                description: node.description || cmd.description || undefined,
            };
        }
        // type === 'prompt'
        return { prompt: (0, variable_resolver_js_1.resolveVariables)(node.content, ctx), description: node.description };
    }
}
exports.NodeRunner = NodeRunner;
//# sourceMappingURL=node-runner.js.map