"use strict";
// Tool failure alerts.
//
// Sliding-window counter per tool name. Records each tool call result;
// when failure rate exceeds the configured threshold over a recent
// sample window (and the call count is large enough to be meaningful),
// fires a single `tool.failure_alert` notification.
//
// Single-fire with cooldown: an alert only fires once per `cooldownMs`
// to avoid spamming the operator. Reset on success-streak.
//
// Pure logic + an optional listener so the server can wire alerts onto
// the event store without coupling this module to it.
Object.defineProperty(exports, "__esModule", { value: true });
exports.createToolFailureAlerts = createToolFailureAlerts;
/**
 * Build a failure-alert tracker. Returned object exposes `record(tool,
 * success)` for each tool call and `subscribe(listener)` for callers
 * that want to receive alerts.
 */
function createToolFailureAlerts(config = {}) {
    const windowSize = Math.max(1, config.windowSize ?? 50);
    const minSamples = Math.max(1, config.minSamples ?? 10);
    const failureThreshold = Math.min(1, Math.max(0, config.failureThreshold ?? 0.30));
    const cooldownMs = Math.max(0, config.cooldownMs ?? 5 * 60 * 1000);
    const now = config.now ?? (() => Date.now());
    const states = new Map();
    const listeners = new Set();
    function record(tool, success) {
        if (!tool)
            return null;
        let state = states.get(tool);
        if (!state) {
            state = { results: [], lastAlertAt: 0 };
            states.set(tool, state);
        }
        state.results.push(success);
        if (state.results.length > windowSize)
            state.results = state.results.slice(-windowSize);
        if (state.results.length < minSamples)
            return null;
        const failureCount = state.results.filter((value) => !value).length;
        const failureRate = failureCount / state.results.length;
        if (failureRate < failureThreshold) {
            return null;
        }
        const t = now();
        if (state.lastAlertAt && t - state.lastAlertAt < cooldownMs)
            return null;
        state.lastAlertAt = t;
        const alert = {
            tool,
            failureRate,
            failureCount,
            totalCount: state.results.length,
            windowSize,
            threshold: failureThreshold,
            firedAt: new Date(t).toISOString(),
        };
        for (const listener of listeners) {
            try {
                listener(alert);
            }
            catch { /* listener errors are non-fatal */ }
        }
        return alert;
    }
    function subscribe(listener) {
        listeners.add(listener);
        return () => { listeners.delete(listener); };
    }
    function status() {
        const out = {};
        for (const [tool, state] of states) {
            const failureCount = state.results.filter((value) => !value).length;
            out[tool] = {
                samples: state.results.length,
                failureCount,
                failureRate: state.results.length === 0 ? 0 : failureCount / state.results.length,
                lastAlertAt: state.lastAlertAt ? new Date(state.lastAlertAt).toISOString() : null,
            };
        }
        return out;
    }
    function reset() {
        states.clear();
    }
    return { record, subscribe, status, reset };
}
//# sourceMappingURL=toolFailureAlerts.js.map