"use strict";
// Cost tracking — Gap #5 in the harness reliability audit.
//
// Tracks token usage per turn, estimates cost using configurable rates,
// and enforces budget caps. Integrates with LoopConfig.costTracking.
Object.defineProperty(exports, "__esModule", { value: true });
exports.CostTracker = void 0;
const DEFAULT_RATES = {
    // Local models (free)
    'qwen2.5-coder:14b': { input: 0, output: 0 },
    'qwen2.5-coder:7b': { input: 0, output: 0 },
    'gemma3:12b': { input: 0, output: 0 },
    'gemma3:27b': { input: 0, output: 0 },
    'llama3.3:70b': { input: 0, output: 0 },
    'deepseek-coder-v2:16b': { input: 0, output: 0 },
    'codestral:22b': { input: 0, output: 0 },
    // Cloud APIs
    'gpt-4o': { input: 0.0025, output: 0.01 },
    'gpt-4o-mini': { input: 0.00015, output: 0.0006 },
    'gpt-4.1': { input: 0.002, output: 0.008 },
    'claude-sonnet-4-20250514': { input: 0.003, output: 0.015 },
    'claude-haiku-3.5': { input: 0.0008, output: 0.004 },
    'gemini-2.5-pro': { input: 0.00125, output: 0.01 },
    'gemini-2.5-flash': { input: 0.00015, output: 0.0006 },
};
class CostTracker {
    turns = [];
    rate;
    budgetUsd;
    model;
    constructor(model, options) {
        this.model = model;
        this.budgetUsd = options?.budgetUsd;
        const customRates = options?.rates ?? {};
        this.rate = customRates[model] ?? DEFAULT_RATES[model] ?? { input: 0, output: 0 };
    }
    /** Record a turn's token usage. Returns true if budget is exceeded. */
    recordTurn(turn, inputTokens, outputTokens) {
        const cost = (inputTokens / 1000) * this.rate.input + (outputTokens / 1000) * this.rate.output;
        this.turns.push({ turn, inputTokens, outputTokens, estimatedCostUsd: Math.round(cost * 1_000_000) / 1_000_000 });
        if (this.budgetUsd !== undefined && this.totalCost() > this.budgetUsd) {
            return true; // budget exceeded
        }
        return false;
    }
    totalCost() {
        return this.turns.reduce((s, t) => s + t.estimatedCostUsd, 0);
    }
    totalInputTokens() {
        return this.turns.reduce((s, t) => s + t.inputTokens, 0);
    }
    totalOutputTokens() {
        return this.turns.reduce((s, t) => s + t.outputTokens, 0);
    }
    summarize(passedTasks) {
        const totalCost = this.totalCost();
        return {
            model: this.model,
            totalInputTokens: this.totalInputTokens(),
            totalOutputTokens: this.totalOutputTokens(),
            totalEstimatedCostUsd: Math.round(totalCost * 1_000_000) / 1_000_000,
            turns: [...this.turns],
            budgetUsd: this.budgetUsd,
            budgetExceeded: this.budgetUsd !== undefined && totalCost > this.budgetUsd,
            costPerSuccess: passedTasks !== undefined && passedTasks > 0
                ? Math.round((totalCost / passedTasks) * 1_000_000) / 1_000_000
                : undefined,
        };
    }
    /** Get rate for display. */
    getRate() {
        return { ...this.rate };
    }
    /** Register or override a model rate at runtime. */
    static registerRate(model, rate) {
        DEFAULT_RATES[model] = rate;
    }
    /** Get all known rates. */
    static getAllRates() {
        return { ...DEFAULT_RATES };
    }
}
exports.CostTracker = CostTracker;
//# sourceMappingURL=costTracker.js.map