"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;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.RuntimePolicy = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const ExecutorHealth_1 = require("./ExecutorHealth");
const RuntimeHealthMonitor_1 = require("./RuntimeHealthMonitor");
class RuntimePolicy {
    executorHealth;
    runtimeHealth;
    constructor() {
        this.executorHealth = new ExecutorHealth_1.ExecutorHealth();
        this.runtimeHealth = new RuntimeHealthMonitor_1.RuntimeHealthMonitor();
    }
    decide(intent, explicitExecutors = []) {
        const strictModelExecutors = this.getStrictModelExecutors();
        const base = explicitExecutors.length
            ? explicitExecutors
            : strictModelExecutors.length
                ? strictModelExecutors
                : intent === 'RESEARCH_ANALYSIS'
                    ? ['gemini', 'claude', 'codex']
                    : ['codex', 'claude', 'gemini'];
        const allowedRaw = (process.env.OPENLIFE_ALLOWED_LLM_EXECUTORS || '').trim().toLowerCase();
        const allowed = new Set();
        if (allowedRaw) {
            for (const entry of allowedRaw.split(',').map(s => s.trim()).filter(Boolean)) {
                if (entry === 'codex' || entry === 'gemini' || entry === 'claude' || entry === 'openclaude') {
                    allowed.add(entry);
                }
            }
        }
        const allowFiltered = allowed.size > 0 ? base.filter(e => allowed.has(e)) : base;
        const preferred = allowFiltered.filter((executor) => {
            const health = this.executorHealth.get(executor);
            const geminiApiAvailable = executor === 'gemini' && !!(process.env.GEMINI_API_KEY || '').trim();
            if (this.runtimeHealth.isCoolingDown(executor) && !geminiApiAvailable)
                return false;
            if (!health)
                return true;
            if (geminiApiAvailable)
                return true;
            return health.available !== false;
        });
        return {
            preferred,
            rationale: preferred.length
                ? `Executores ordenados por policy + health atual${allowed.size > 0 ? ' + allowlist' : ''}.`
                : 'Todos os executores da cadeia configurada estão indisponíveis no momento.'
        };
    }
    getStrictModelExecutors() {
        try {
            const modelsPath = path.join(process.cwd(), 'models.json');
            if (!fs.existsSync(modelsPath))
                return [];
            const cfg = JSON.parse(fs.readFileSync(modelsPath, 'utf-8'));
            const chain = [cfg.primary, ...(cfg.fallbacks || [])].filter(Boolean);
            if (chain.length !== 1)
                return [];
            const provider = chain[0].provider || '';
            if (provider === 'openai-cli')
                return ['codex'];
            if (provider === 'gemini-cli' || provider === 'gemini-api')
                return ['gemini'];
            if (provider === 'anthropic-api')
                return ['claude'];
            return [];
        }
        catch {
            return [];
        }
    }
    recordResult(executor, ok, reason) {
        this.executorHealth.set(executor, ok, reason);
        if (ok) {
            this.runtimeHealth.markHealthy(executor);
            return;
        }
        const normalized = (reason || '').toLowerCase();
        const shouldCooldown = /quota|429|capacity|rate limit|temporarily unavailable|overloaded|auth/i.test(normalized);
        if (shouldCooldown) {
            const cooldown = /auth/i.test(normalized) ? 30 : 10;
            this.runtimeHealth.markFailure(executor, reason || 'runtime failure', cooldown);
        }
    }
    status() {
        return {
            executors: this.executorHealth.getAll(),
            cooldowns: this.runtimeHealth.all()
        };
    }
    saveSnapshot() {
        const snapshotPath = path.join(process.cwd(), '.openlife', 'runtime-policy-status.json');
        fs.mkdirSync(path.dirname(snapshotPath), { recursive: true });
        fs.writeFileSync(snapshotPath, JSON.stringify(this.status(), null, 2), 'utf-8');
        return snapshotPath;
    }
}
exports.RuntimePolicy = RuntimePolicy;
