"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.policyManager = exports.PolicyManager = exports.CostPolicy = exports.LoopDetectionPolicy = exports.TokenCapPolicy = exports.IdlePolicy = exports.TimeoutPolicy = void 0;
class TimeoutPolicy {
    constructor() {
        this.name = 'timeout';
    }
    evaluate(runId, runState, config) {
        if (!runState.startedAt || runState.status !== 'running') {
            return null;
        }
        const duration = Date.now() - runState.startedAt;
        if (duration > config.runMaxDurationMs) {
            return {
                policy: this.name,
                reason: `Run exceeded maximum duration of ${config.runMaxDurationMs}ms`,
                threshold: config.runMaxDurationMs,
                actual: duration,
                runId,
                timestamp: Date.now()
            };
        }
        return null;
    }
}
exports.TimeoutPolicy = TimeoutPolicy;
class IdlePolicy {
    constructor() {
        this.name = 'idle';
    }
    evaluate(runId, runState, config) {
        if (!runState.startedAt || runState.status !== 'running') {
            return null;
        }
        if (!runState.lastTokenAt) {
            const timeSinceStart = Date.now() - runState.startedAt;
            if (timeSinceStart > config.runIdleMs) {
                return {
                    policy: this.name,
                    reason: `Run has been idle (no tokens) for ${timeSinceStart}ms`,
                    threshold: config.runIdleMs,
                    actual: timeSinceStart,
                    runId,
                    timestamp: Date.now()
                };
            }
            return null;
        }
        const timeSinceLastToken = Date.now() - runState.lastTokenAt;
        if (timeSinceLastToken > config.runIdleMs) {
            return {
                policy: this.name,
                reason: `Run has been idle (no new tokens) for ${timeSinceLastToken}ms`,
                threshold: config.runIdleMs,
                actual: timeSinceLastToken,
                runId,
                timestamp: Date.now()
            };
        }
        return null;
    }
}
exports.IdlePolicy = IdlePolicy;
class TokenCapPolicy {
    constructor() {
        this.name = 'token_cap';
    }
    evaluate(runId, runState, config) {
        if (runState.status !== 'running') {
            return null;
        }
        if (runState.tokenCount > config.runMaxTokens) {
            return {
                policy: this.name,
                reason: `Run exceeded maximum token count of ${config.runMaxTokens}`,
                threshold: config.runMaxTokens,
                actual: runState.tokenCount,
                runId,
                timestamp: Date.now()
            };
        }
        return null;
    }
}
exports.TokenCapPolicy = TokenCapPolicy;
class LoopDetectionPolicy {
    constructor() {
        this.name = 'loop_detection';
    }
    evaluate(runId, runState, config) {
        if (runState.status !== 'running' || runState.events.length < 10) {
            return null;
        }
        const now = Date.now();
        const cutoff = now - (config.loopWindow * 1000);
        const recentTokenEvents = runState.events
            .filter(event => event.type === 'token' && event.at >= cutoff)
            .slice(-config.loopMax);
        if (recentTokenEvents.length >= config.loopMax) {
            const tokenCounts = recentTokenEvents.map(event => event.type === 'token' ? event.tokens : 0);
            const tokenCountMap = new Map();
            for (const count of tokenCounts) {
                tokenCountMap.set(count, (tokenCountMap.get(count) || 0) + 1);
            }
            const maxRepetition = Math.max(...tokenCountMap.values());
            if (maxRepetition >= Math.ceil(config.loopMax * 0.7)) {
                return {
                    policy: this.name,
                    reason: `Run detected in loop pattern with ${maxRepetition} repeated token counts`,
                    threshold: Math.ceil(config.loopMax * 0.7),
                    actual: maxRepetition,
                    runId,
                    timestamp: Date.now()
                };
            }
        }
        return null;
    }
}
exports.LoopDetectionPolicy = LoopDetectionPolicy;
class CostPolicy {
    constructor() {
        this.name = 'cost';
    }
    evaluate(runId, runState, config) {
        if (runState.status !== 'running') {
            return null;
        }
        const maxCost = config.runMaxCost || 1.0;
        const currentCost = runState.cost || 0;
        if (currentCost > maxCost) {
            return {
                policy: this.name,
                reason: `Run exceeded maximum cost of $${maxCost.toFixed(2)}`,
                threshold: maxCost,
                actual: currentCost,
                runId,
                timestamp: Date.now()
            };
        }
        return null;
    }
}
exports.CostPolicy = CostPolicy;
class PolicyManager {
    constructor() {
        this.policies = [
            new TimeoutPolicy(),
            new IdlePolicy(),
            new TokenCapPolicy(),
            new LoopDetectionPolicy(),
            new CostPolicy()
        ];
    }
    evaluatePolicies(runId, runState, config) {
        const violations = [];
        for (const policy of this.policies) {
            try {
                const violation = policy.evaluate(runId, runState, config);
                if (violation) {
                    violations.push(violation);
                }
            }
            catch (error) {
                console.error(`Policy ${policy.name} evaluation failed for run ${runId}:`, error);
            }
        }
        return violations;
    }
    getPolicy(name) {
        return this.policies.find(p => p.name === name);
    }
    getPolicyNames() {
        return this.policies.map(p => p.name);
    }
}
exports.PolicyManager = PolicyManager;
exports.policyManager = new PolicyManager();
//# sourceMappingURL=policies.js.map