function assertNever(value) {
    throw new Error(`Unhandled trigger condition type: ${value.type}`);
}
export class TriggerEvaluator {
    triggers;
    budget;
    lastFiredMap = new Map();
    callCount = 0;
    constructor(triggers, budget) {
        this.triggers = triggers
            .filter((t) => t.enabled !== false)
            .sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
        this.budget = budget;
    }
    evaluate(state) {
        if (this.isBudgetExhausted()) {
            return [];
        }
        const fired = [];
        for (const trigger of this.triggers) {
            if (!this.isCooldownSatisfied(trigger, state.iteration)) {
                continue;
            }
            if (this.matchesCondition(trigger.condition, state)) {
                fired.push(trigger);
            }
        }
        return fired;
    }
    recordFiring(triggerId, iteration) {
        this.lastFiredMap.set(triggerId, iteration);
        this.callCount++;
    }
    isBudgetExhausted() {
        if (this.budget?.maxCallsPerRun === undefined) {
            return false;
        }
        return this.callCount >= this.budget.maxCallsPerRun;
    }
    isCooldownSatisfied(trigger, currentIteration) {
        if (trigger.cooldownIterations === undefined) {
            return true;
        }
        const lastFired = this.lastFiredMap.get(trigger.id);
        if (lastFired === undefined) {
            return true;
        }
        return currentIteration - lastFired >= trigger.cooldownIterations;
    }
    matchesCondition(condition, state) {
        switch (condition.type) {
            case 'on_error': {
                if (state.lastError === undefined)
                    return false;
                if (condition.categories && condition.categories.length > 0) {
                    return condition.categories.some((cat) => state.lastError?.includes(cat));
                }
                return true;
            }
            case 'on_iteration': {
                return state.iteration % condition.everyN === 0;
            }
            case 'on_context_percent': {
                return state.contextWindowPercent >= condition.threshold;
            }
            case 'on_tool_category': {
                if (state.lastToolCategory === undefined)
                    return false;
                return condition.categories.includes(state.lastToolCategory);
            }
            case 'on_cost_percent': {
                if (state.costBudgetPercent === undefined)
                    return false;
                return state.costBudgetPercent >= condition.threshold;
            }
            case 'on_complexity': {
                return state.totalToolCalls >= condition.toolCallThreshold;
            }
            case 'custom': {
                return condition.predicate(state);
            }
            default:
                return assertNever(condition);
        }
    }
}
//# sourceMappingURL=evaluator.js.map