/** * HQ alerting engine — evaluates the current snapshot against a set of * operator-configurable rules and emits `hq.alert` messages when a threshold * is crossed. Mirrors the BrainMonitor's self-activation logic (tool-failure * streaks, error storms) but at the fleet-wide command-center scope. * * Rules are evaluated on a periodic tick (default 15s, unref'd) against the * latest in-memory snapshot. Deduplication prevents alert storms: a rule that * is still firing is not re-emitted until it clears (state machine per rule). * * @module hq/alerts */ import type { HqAlertMessage, HqSnapshot } from './protocol.js'; /** Severity levels for alerts, mirroring {@link HqAlertMessage}. */ export type HqAlertSeverity = HqAlertMessage['severity']; export interface HqAlert { id: string; ruleId: string; severity: HqAlertSeverity; message: string; /** Epoch ms when the alert first fired in its current episode. */ firstFiredAt: number; /** Epoch ms of the most recent evaluation that confirmed the alert. */ lastFiredAt: number; } export interface HqAlertRuleConfig { /** Maximum cost (USD) across the whole fleet before alerting. Default 50. */ costThresholdUsd?: number; /** Seconds of silence from ALL machines before a stale alert fires. Default 120. */ staleMachineSeconds?: number; /** Minimum number of active agents before concurrency alert fires. Default: disabled (0). */ maxAgents?: number; /** * Hours before expiry at which the `token-expiry-imminent` warning fires. * Default 24. Set to 0 to disable the warning entirely (expired-only alert remains). */ tokenExpiryWarningHours?: number; } /** * In-memory alert state. Tracks which rules are currently firing so the same * alert is not re-emitted every tick — only state transitions (cleared → * firing) emit. Optionally persists to disk via a callback. */ export declare class HqAlertEngine { private readonly active; private readonly history; private readonly maxHistory; private timer; private readonly onAlert; private readonly onPersist?; constructor(opts: { onAlert: (alert: HqAlert) => void; maxHistory?: number; /** Optional durable sink — fires when an alert transitions to firing. */ onPersist?: ((alert: HqAlert) => void) | undefined; }); /** * Evaluate all rules against the snapshot. Emits (via the `onAlert` * callback) only for rules that newly transition to firing. Clears rules * that are no longer firing. Returns the list of newly-fired alerts. */ evaluate(snapshot: HqSnapshot | null, config?: HqAlertRuleConfig, now?: number): HqAlert[]; /** Currently-active (firing) alerts. */ activeAlerts(): HqAlert[]; /** Historical alerts (newest-last), capped at maxHistory. */ recentAlerts(limit?: number): HqAlert[]; /** Seed the history from a durable store on boot (no alert callbacks fired). */ seed(alerts: readonly HqAlert[]): void; /** * Start periodic evaluation against a snapshot getter. The timer is * unref'd so it never keeps the process alive. Returns a disposer. */ startPeriodic(getSnapshot: () => HqSnapshot | null, config?: HqAlertRuleConfig | (() => HqAlertRuleConfig | undefined), intervalMs?: number): () => void; } /** Map an internal {@link HqAlert} to the wire {@link HqAlertMessage}. */ export declare function toAlertMessage(alert: HqAlert): HqAlertMessage; //# sourceMappingURL=alerts.d.ts.map