// engine/cost-guardrails.ts — Cost Guardrails computation logic (SPEC-393)
import { getBudget } from '../storage/budget-store.js';
/**
 * Compute the current budget status for a spec.
 * Recommends a model tier based on usage percentage to control costs.
 */
export function computeBudgetStatus(budget) {
    const remaining = budget.maxUsdCents - budget.usedUsdCents;
    const usagePercent = budget.maxUsdCents > 0 ? Math.round((budget.usedUsdCents / budget.maxUsdCents) * 100) : 0;
    const warningTriggered = usagePercent >= budget.warningThreshold;
    const exhausted = budget.usedUsdCents >= budget.maxUsdCents;
    // Auto-downgrade model based on remaining budget
    const recommendedModel = exhausted || usagePercent >= 80 ? 'haiku' : usagePercent >= 60 ? 'sonnet' : 'opus';
    return {
        specId: budget.specId,
        maxUsdCents: budget.maxUsdCents,
        usedUsdCents: budget.usedUsdCents,
        remainingUsdCents: Math.max(0, remaining),
        usagePercent,
        warningTriggered,
        recommendedModel,
        exhausted,
    };
}
/**
 * Format a budget status into a human-readable summary message.
 */
export function formatBudgetMessage(status) {
    const dollars = (status.usedUsdCents / 100).toFixed(2);
    const max = (status.maxUsdCents / 100).toFixed(2);
    let msg = `Budget: $${dollars} / $${max} (${status.usagePercent}%)`;
    if (status.exhausted) {
        msg += ' EXHAUSTED — using haiku';
    }
    else if (status.warningTriggered) {
        msg += ` Warning — downgraded to ${status.recommendedModel}`;
    }
    return msg;
}
/**
 * Enforces budget limits before executing a licensed tool.
 * - If no budget is configured for the spec → no-op (pass through).
 * - If budget is exhausted → throws an Error to block tool execution.
 * - If warning threshold is reached → logs a warning but allows execution.
 *
 * @param specId - The spec identifier to check budget for.
 * @param projectPath - The project root path used to locate budget data.
 * @throws {Error} When the spec budget is exhausted.
 */
export async function checkBudgetEnforcement(specId, projectPath) {
    const budget = await getBudget(projectPath, specId);
    if (budget === null) {
        return;
    }
    const status = computeBudgetStatus(budget);
    if (status.exhausted) {
        const used = (status.usedUsdCents / 100).toFixed(2);
        const max = (status.maxUsdCents / 100).toFixed(2);
        throw new Error(`Budget exhausted for ${specId}: $${used} of $${max} used. ` +
            `Use set_spec_budget to increase or switch to haiku model.`);
    }
    if (status.warningTriggered) {
        console.warn(`[Planu] Budget warning for ${specId}: ${status.usagePercent}% used ` +
            `($${(status.usedUsdCents / 100).toFixed(2)} of $${(status.maxUsdCents / 100).toFixed(2)}). ` +
            `Recommended model: ${status.recommendedModel}.`);
    }
}
//# sourceMappingURL=cost-guardrails.js.map