"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DependencySentinel = void 0;
const BrainClient_1 = require("../brain/BrainClient");
const AICore_1 = require("../ai/AICore");
const child_process_1 = require("child_process");
const chalk_1 = __importDefault(require("chalk"));
const util = __importStar(require("util"));
const execAsync = util.promisify(child_process_1.exec);
class DependencySentinel {
    constructor(workDir, maxRetries = 3) {
        this.workDir = workDir;
        this.maxRetries = maxRetries;
        this.brains = BrainClient_1.BrainClient.getInstance();
        this.ai = AICore_1.AICore.getInstance();
    }
    /**
     * Execute a command with self-healing capabilities.
     * If the command fails, the Sentinel will analyze the output and attempt to fix it.
     */
    async guard(command) {
        let attempts = 0;
        while (attempts <= this.maxRetries) {
            if (attempts > 0) {
                console.log(chalk_1.default.yellow(`🛡️  Sentinel Retry [${attempts}/${this.maxRetries}] for: ${command}`));
                await this.brains.addUpdate('Sentinel', 'orchestrator', 'thought', `Retry ${attempts}/${this.maxRetries} for command: ${command}`);
            }
            try {
                console.log(chalk_1.default.blue(`🛡️  Sentinel running: ${command}`));
                // We use execSync for now to simplify streaming output, 
                // but for a robust implementation we might want proper streaming.
                // Using stdio: 'inherit' lets the user see progress.
                (0, child_process_1.execSync)(command, { cwd: this.workDir, stdio: 'inherit' });
                console.log(chalk_1.default.green(`✅ Command passed: ${command}`));
                return true;
            }
            catch (error) {
                console.log(chalk_1.default.red(`❌ Command failed: ${command}`));
                // In execSync with inherit, we don't capture stdout/stderr easily in the error object 
                // (unless we assume it printed to screen and we can't see it programmatically).
                // To fix this, we need to re-run it capturing output OR use execAsync initially.
                // Let's use a "dry run" with capture to get the error details for the AI.
                const errorOutput = await this.captureErrorOutput(command);
                attempts++;
                if (attempts > this.maxRetries) {
                    console.log(chalk_1.default.red(`💀 Sentinel gave up after ${this.maxRetries} attempts.`));
                    return false;
                }
                await this.diagnoseAndFix(command, errorOutput);
            }
        }
        return false;
    }
    async captureErrorOutput(command) {
        try {
            await execAsync(command, { cwd: this.workDir });
            return ""; // It unexpectedly passed?
        }
        catch (e) {
            return `${e.stdout}\n${e.stderr}`;
        }
    }
    async diagnoseAndFix(command, errorLog) {
        await this.brains.addUpdate('Sentinel', 'orchestrator', 'thought', `Diagnosing failure for: ${command}`);
        const prompt = `
      You are the Dependency Sentinel, a self-healing build agent.
      
      COMMAND: ${command}
      WORKING_DIR: ${this.workDir}
      
      ERROR OUTPUT:
      \`\`\`
      ${errorLog.slice(0, 4000)}
      \`\`\`
      
      TASK:
      Analyze the error and provide a shell command to fix it.
      Common fixes:
      - "pnpm add <package>" (if module not found)
      - "pnpm add -D @types/<package>" (if type error)
      - "mkdir -p <dir>" (if directory missing)
      
      RETURN FORMAT:
      Return ONLY the shell command to execute. No markdown, no explanations.
      If you cannot determine a fix, return "SKIP".
    `;
        const fixCommand = await this.ai.generateText(prompt);
        const cleanCommand = fixCommand.replace(/`/g, '').trim();
        if (cleanCommand === 'SKIP' || !cleanCommand) {
            console.log(chalk_1.default.red("🛡️  Sentinel could not determine a fix."));
            return;
        }
        console.log(chalk_1.default.magenta(`🛡️  Sentinel attempting fix: ${cleanCommand}`));
        await this.brains.addUpdate('Sentinel', 'orchestrator', 'action', `Executing fix: ${cleanCommand}`);
        try {
            (0, child_process_1.execSync)(cleanCommand, { cwd: this.workDir, stdio: 'inherit' });
            console.log(chalk_1.default.green(`✅ Fix executed successfully.`));
        }
        catch (e) {
            console.log(chalk_1.default.red(`❌ Fix execution failed.`));
        }
    }
}
exports.DependencySentinel = DependencySentinel;
//# sourceMappingURL=DependencySentinel.js.map