openalerts 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +253 -0
- package/dist/channels/console.d.ts +6 -0
- package/dist/channels/console.d.ts.map +1 -0
- package/dist/channels/console.js +10 -0
- package/dist/channels/console.js.map +1 -0
- package/dist/channels/telegram.d.ts +12 -0
- package/dist/channels/telegram.d.ts.map +1 -0
- package/dist/channels/telegram.js +28 -0
- package/dist/channels/telegram.js.map +1 -0
- package/dist/channels/webhook.d.ts +8 -0
- package/dist/channels/webhook.d.ts.map +1 -0
- package/dist/channels/webhook.js +15 -0
- package/dist/channels/webhook.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +234 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +51 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +86 -0
- package/dist/config.js.map +1 -0
- package/dist/core/alert-channel.d.ts +16 -0
- package/dist/core/alert-channel.d.ts.map +1 -0
- package/dist/core/alert-channel.js +23 -0
- package/dist/core/alert-channel.js.map +1 -0
- package/dist/core/bounded-map.d.ts +52 -0
- package/dist/core/bounded-map.d.ts.map +1 -0
- package/dist/core/bounded-map.js +129 -0
- package/dist/core/bounded-map.js.map +1 -0
- package/dist/core/engine.d.ts +36 -0
- package/dist/core/engine.d.ts.map +1 -0
- package/dist/core/engine.js +162 -0
- package/dist/core/engine.js.map +1 -0
- package/dist/core/evaluator.d.ts +19 -0
- package/dist/core/evaluator.d.ts.map +1 -0
- package/dist/core/evaluator.js +168 -0
- package/dist/core/evaluator.js.map +1 -0
- package/dist/core/event-bus.d.ts +18 -0
- package/dist/core/event-bus.d.ts.map +1 -0
- package/dist/core/event-bus.js +32 -0
- package/dist/core/event-bus.js.map +1 -0
- package/dist/core/formatter.d.ts +15 -0
- package/dist/core/formatter.d.ts.map +1 -0
- package/dist/core/formatter.js +125 -0
- package/dist/core/formatter.js.map +1 -0
- package/dist/core/rules.d.ts +3 -0
- package/dist/core/rules.d.ts.map +1 -0
- package/dist/core/rules.js +410 -0
- package/dist/core/rules.js.map +1 -0
- package/dist/core/store.d.ts +9 -0
- package/dist/core/store.d.ts.map +1 -0
- package/dist/core/store.js +72 -0
- package/dist/core/store.js.map +1 -0
- package/dist/core/types.d.ts +158 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +18 -0
- package/dist/core/types.js.map +1 -0
- package/dist/db/index.d.ts +6 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +31 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/queries.d.ts +157 -0
- package/dist/db/queries.d.ts.map +1 -0
- package/dist/db/queries.js +221 -0
- package/dist/db/queries.js.map +1 -0
- package/dist/db/schema.d.ts +5 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +177 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/readers/openclaw.d.ts +11 -0
- package/dist/readers/openclaw.d.ts.map +1 -0
- package/dist/readers/openclaw.js +267 -0
- package/dist/readers/openclaw.js.map +1 -0
- package/dist/server/dashboard.d.ts +2 -0
- package/dist/server/dashboard.d.ts.map +1 -0
- package/dist/server/dashboard.js +765 -0
- package/dist/server/dashboard.js.map +1 -0
- package/dist/server/index.d.ts +10 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +28 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/routes.d.ts +6 -0
- package/dist/server/routes.d.ts.map +1 -0
- package/dist/server/routes.js +146 -0
- package/dist/server/routes.js.map +1 -0
- package/dist/server/sse.d.ts +21 -0
- package/dist/server/sse.d.ts.map +1 -0
- package/dist/server/sse.js +53 -0
- package/dist/server/sse.js.map +1 -0
- package/dist/watchers/files.d.ts +19 -0
- package/dist/watchers/files.d.ts.map +1 -0
- package/dist/watchers/files.js +105 -0
- package/dist/watchers/files.js.map +1 -0
- package/dist/watchers/gateway-adapter.d.ts +18 -0
- package/dist/watchers/gateway-adapter.d.ts.map +1 -0
- package/dist/watchers/gateway-adapter.js +273 -0
- package/dist/watchers/gateway-adapter.js.map +1 -0
- package/dist/watchers/gateway.d.ts +27 -0
- package/dist/watchers/gateway.d.ts.map +1 -0
- package/dist/watchers/gateway.js +131 -0
- package/dist/watchers/gateway.js.map +1 -0
- package/package.json +48 -0
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export interface ChannelConfig {
|
|
2
|
+
type: "telegram" | "discord" | "slack" | "webhook" | "console";
|
|
3
|
+
token?: string;
|
|
4
|
+
chatId?: string;
|
|
5
|
+
webhookUrl?: string;
|
|
6
|
+
url?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface RuleOverride {
|
|
9
|
+
enabled?: boolean;
|
|
10
|
+
threshold?: number;
|
|
11
|
+
cooldownMinutes?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface WatchConfig {
|
|
14
|
+
/** Path to ~/.openclaw or custom openclaw data dir */
|
|
15
|
+
openclawDir: string;
|
|
16
|
+
/** Workspaces to watch (relative to openclawDir or absolute) */
|
|
17
|
+
workspaces: string[];
|
|
18
|
+
}
|
|
19
|
+
export interface ServerConfig {
|
|
20
|
+
port: number;
|
|
21
|
+
host: string;
|
|
22
|
+
}
|
|
23
|
+
export interface AppConfig {
|
|
24
|
+
/** OpenClaw gateway WebSocket URL */
|
|
25
|
+
gatewayUrl: string;
|
|
26
|
+
/** Gateway operator token (gateway.auth.token from openclaw.json) */
|
|
27
|
+
gatewayToken: string;
|
|
28
|
+
/** Where openalerts stores its own data */
|
|
29
|
+
stateDir: string;
|
|
30
|
+
/** File watching config */
|
|
31
|
+
watch: WatchConfig;
|
|
32
|
+
/** HTTP server config */
|
|
33
|
+
server: ServerConfig;
|
|
34
|
+
/** Alert channels */
|
|
35
|
+
channels: ChannelConfig[];
|
|
36
|
+
/** Per-rule overrides */
|
|
37
|
+
rules?: Record<string, RuleOverride>;
|
|
38
|
+
/** Suppress outbound alerts (log only) */
|
|
39
|
+
quiet?: boolean;
|
|
40
|
+
/** Hourly alert cap (default 10) */
|
|
41
|
+
maxAlertsPerHour?: number;
|
|
42
|
+
}
|
|
43
|
+
export declare function loadConfig(configPath?: string): AppConfig;
|
|
44
|
+
export declare function writeDefaultConfig(targetPath: string): void;
|
|
45
|
+
/**
|
|
46
|
+
* Auto-detect the OpenClaw gateway operator token.
|
|
47
|
+
* Primary source: gateway.auth.token in openclaw.json (the master operator token).
|
|
48
|
+
* This is the correct token for WS connect with client.id = "cli".
|
|
49
|
+
*/
|
|
50
|
+
export declare function detectGatewayToken(openclawDir: string): string;
|
|
51
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;IAE/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,sDAAsD;IACtD,WAAW,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,SAAS;IACxB,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,YAAY,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,2BAA2B;IAC3B,KAAK,EAAE,WAAW,CAAC;IACnB,yBAAyB;IACzB,MAAM,EAAE,YAAY,CAAC;IACrB,qBAAqB;IACrB,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,yBAAyB;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACrC,0CAA0C;IAC1C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,oCAAoC;IACpC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAkBD,wBAAgB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAsBzD;AAYD,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAgB3D;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAa9D"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
const DEFAULTS = {
|
|
5
|
+
gatewayUrl: "ws://127.0.0.1:18789",
|
|
6
|
+
gatewayToken: "",
|
|
7
|
+
stateDir: path.join(os.homedir(), ".openalerts"),
|
|
8
|
+
watch: {
|
|
9
|
+
openclawDir: path.join(os.homedir(), ".openclaw"),
|
|
10
|
+
workspaces: ["workspace", "workspace-study"],
|
|
11
|
+
},
|
|
12
|
+
server: {
|
|
13
|
+
port: 4242,
|
|
14
|
+
host: "127.0.0.1",
|
|
15
|
+
},
|
|
16
|
+
channels: [],
|
|
17
|
+
quiet: false,
|
|
18
|
+
};
|
|
19
|
+
export function loadConfig(configPath) {
|
|
20
|
+
const candidates = [
|
|
21
|
+
configPath,
|
|
22
|
+
path.join(process.cwd(), "openalerts.config.json"),
|
|
23
|
+
path.join(os.homedir(), ".openalerts", "config.json"),
|
|
24
|
+
// legacy path migration
|
|
25
|
+
path.join(os.homedir(), ".openalerts-watch", "config.json"),
|
|
26
|
+
path.join(os.homedir(), ".config", "openalerts", "config.json"),
|
|
27
|
+
].filter(Boolean);
|
|
28
|
+
for (const p of candidates) {
|
|
29
|
+
if (fs.existsSync(p)) {
|
|
30
|
+
try {
|
|
31
|
+
const raw = JSON.parse(fs.readFileSync(p, "utf8"));
|
|
32
|
+
return mergeConfig(DEFAULTS, raw);
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
console.error(`[openalerts] Failed to parse config at ${p}: ${err}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return { ...DEFAULTS };
|
|
40
|
+
}
|
|
41
|
+
function mergeConfig(base, override) {
|
|
42
|
+
return {
|
|
43
|
+
...base,
|
|
44
|
+
...override,
|
|
45
|
+
watch: { ...base.watch, ...(override.watch ?? {}) },
|
|
46
|
+
server: { ...base.server, ...(override.server ?? {}) },
|
|
47
|
+
channels: override.channels ?? base.channels,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export function writeDefaultConfig(targetPath) {
|
|
51
|
+
const openclawDir = path.join(os.homedir(), ".openclaw");
|
|
52
|
+
const autoToken = detectGatewayToken(openclawDir);
|
|
53
|
+
const sample = {
|
|
54
|
+
...DEFAULTS,
|
|
55
|
+
gatewayToken: autoToken || "PASTE_YOUR_OPERATOR_TOKEN_HERE",
|
|
56
|
+
channels: [
|
|
57
|
+
{
|
|
58
|
+
type: "telegram",
|
|
59
|
+
token: "YOUR_BOT_TOKEN",
|
|
60
|
+
chatId: "YOUR_CHAT_ID",
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
};
|
|
64
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
65
|
+
fs.writeFileSync(targetPath, JSON.stringify(sample, null, 2) + "\n");
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Auto-detect the OpenClaw gateway operator token.
|
|
69
|
+
* Primary source: gateway.auth.token in openclaw.json (the master operator token).
|
|
70
|
+
* This is the correct token for WS connect with client.id = "cli".
|
|
71
|
+
*/
|
|
72
|
+
export function detectGatewayToken(openclawDir) {
|
|
73
|
+
// Primary: master token from openclaw.json gateway.auth.token
|
|
74
|
+
const configPath = path.join(openclawDir, "openclaw.json");
|
|
75
|
+
try {
|
|
76
|
+
const data = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
77
|
+
const gw = data.gateway;
|
|
78
|
+
const auth = gw?.auth;
|
|
79
|
+
if (typeof auth?.token === "string" && auth.token) {
|
|
80
|
+
return auth.token;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch { /* ignore */ }
|
|
84
|
+
return "";
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AlertChannel, AlertEvent, OpenAlertsLogger } from "./types.js";
|
|
2
|
+
export declare class AlertDispatcher {
|
|
3
|
+
private channels;
|
|
4
|
+
private logger;
|
|
5
|
+
private diagnosisHint;
|
|
6
|
+
constructor(opts: {
|
|
7
|
+
channels?: AlertChannel[];
|
|
8
|
+
logger?: OpenAlertsLogger;
|
|
9
|
+
diagnosisHint?: string;
|
|
10
|
+
});
|
|
11
|
+
addChannel(channel: AlertChannel): void;
|
|
12
|
+
get hasChannels(): boolean;
|
|
13
|
+
get channelCount(): number;
|
|
14
|
+
dispatch(alert: AlertEvent): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=alert-channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alert-channel.d.ts","sourceRoot":"","sources":["../../src/core/alert-channel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAG7E,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,aAAa,CAAS;gBAElB,IAAI,EAAE;QAAE,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,gBAAgB,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE;IAMlG,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAIvC,IAAI,WAAW,IAAI,OAAO,CAAqC;IAC/D,IAAI,YAAY,IAAI,MAAM,CAAiC;IAErD,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;CAWjD"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { formatAlertMessage as formatAlert } from "./formatter.js";
|
|
2
|
+
export class AlertDispatcher {
|
|
3
|
+
channels;
|
|
4
|
+
logger;
|
|
5
|
+
diagnosisHint;
|
|
6
|
+
constructor(opts) {
|
|
7
|
+
this.channels = opts.channels ? [...opts.channels] : [];
|
|
8
|
+
this.logger = opts.logger ?? console;
|
|
9
|
+
this.diagnosisHint = opts.diagnosisHint ?? "";
|
|
10
|
+
}
|
|
11
|
+
addChannel(channel) {
|
|
12
|
+
this.channels.push(channel);
|
|
13
|
+
}
|
|
14
|
+
get hasChannels() { return this.channels.length > 0; }
|
|
15
|
+
get channelCount() { return this.channels.length; }
|
|
16
|
+
async dispatch(alert) {
|
|
17
|
+
if (this.channels.length === 0)
|
|
18
|
+
return;
|
|
19
|
+
const formatted = formatAlert(alert, { diagnosisHint: this.diagnosisHint });
|
|
20
|
+
await Promise.allSettled(this.channels.map(ch => Promise.resolve(ch.send(alert, formatted)).catch(err => this.logger.warn(`[channel:${ch.name}] send failed: ${String(err)}`))));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=alert-channel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alert-channel.js","sourceRoot":"","sources":["../../src/core/alert-channel.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,IAAI,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAEnE,MAAM,OAAO,eAAe;IAClB,QAAQ,CAAiB;IACzB,MAAM,CAAmB;IACzB,aAAa,CAAS;IAE9B,YAAY,IAAsF;QAChG,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC;QACrC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,IAAI,EAAE,CAAC;IAChD,CAAC;IAED,UAAU,CAAC,OAAqB;QAC9B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI,WAAW,KAAc,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IAC/D,IAAI,YAAY,KAAa,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IAE3D,KAAK,CAAC,QAAQ,CAAC,KAAiB;QAC9B,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QACvC,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,EAAE,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;QAC5E,MAAM,OAAO,CAAC,UAAU,CACtB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CACrB,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CACrD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,IAAI,kBAAkB,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CACrE,CACF,CACF,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded Map with LRU Eviction
|
|
3
|
+
*
|
|
4
|
+
* Prevents memory leaks by automatically pruning oldest entries when size limit is reached.
|
|
5
|
+
* Uses LRU (Least Recently Used) eviction strategy.
|
|
6
|
+
*/
|
|
7
|
+
export type BoundedMapOptions = {
|
|
8
|
+
/** Maximum number of entries */
|
|
9
|
+
maxSize: number;
|
|
10
|
+
/** Optional callback when entries are evicted */
|
|
11
|
+
onEvict?: (key: string, value: unknown) => void;
|
|
12
|
+
/** Optional TTL in ms for entries */
|
|
13
|
+
ttlMs?: number;
|
|
14
|
+
};
|
|
15
|
+
export type BoundedMapStats = {
|
|
16
|
+
size: number;
|
|
17
|
+
maxSize: number;
|
|
18
|
+
evictionCount: number;
|
|
19
|
+
hitCount: number;
|
|
20
|
+
missCount: number;
|
|
21
|
+
};
|
|
22
|
+
export declare class BoundedMap<K extends string, V> {
|
|
23
|
+
private readonly options;
|
|
24
|
+
private map;
|
|
25
|
+
private evictionCount;
|
|
26
|
+
private hitCount;
|
|
27
|
+
private missCount;
|
|
28
|
+
constructor(options: BoundedMapOptions);
|
|
29
|
+
/** Set a value */
|
|
30
|
+
set(key: K, value: V): this;
|
|
31
|
+
/** Get a value */
|
|
32
|
+
get(key: K): V | undefined;
|
|
33
|
+
/** Check if key exists */
|
|
34
|
+
has(key: K): boolean;
|
|
35
|
+
/** Delete a key */
|
|
36
|
+
delete(key: K): boolean;
|
|
37
|
+
/** Clear all entries */
|
|
38
|
+
clear(): void;
|
|
39
|
+
/** Get current size */
|
|
40
|
+
get size(): number;
|
|
41
|
+
/** Get all keys */
|
|
42
|
+
keys(): IterableIterator<K>;
|
|
43
|
+
/** Get all values */
|
|
44
|
+
values(): IterableIterator<V>;
|
|
45
|
+
/** Get all entries */
|
|
46
|
+
entries(): IterableIterator<[K, V]>;
|
|
47
|
+
/** Get stats */
|
|
48
|
+
getStats(): BoundedMapStats;
|
|
49
|
+
/** Evict oldest (least recently used) entry */
|
|
50
|
+
private evictOldest;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=bounded-map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bounded-map.d.ts","sourceRoot":"","sources":["../../src/core/bounded-map.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAQF,qBAAa,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC;IAM7B,OAAO,CAAC,QAAQ,CAAC,OAAO;IALpC,OAAO,CAAC,GAAG,CAA0B;IACrC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,SAAS,CAAK;gBAEO,OAAO,EAAE,iBAAiB;IAMvD,kBAAkB;IAClB,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAkB3B,kBAAkB;IAClB,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,SAAS;IAwB1B,0BAA0B;IAC1B,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO;IAgBpB,mBAAmB;IACnB,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO;IAQvB,wBAAwB;IACxB,KAAK,IAAI,IAAI;IASb,uBAAuB;IACvB,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,mBAAmB;IACnB,IAAI,IAAI,gBAAgB,CAAC,CAAC,CAAC;IAI3B,qBAAqB;IACrB,MAAM,IAAI,gBAAgB,CAAC,CAAC,CAAC;IAI7B,sBAAsB;IACtB,OAAO,IAAI,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAInC,gBAAgB;IAChB,QAAQ,IAAI,eAAe;IAU3B,+CAA+C;IAC/C,OAAO,CAAC,WAAW;CAgBpB"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded Map with LRU Eviction
|
|
3
|
+
*
|
|
4
|
+
* Prevents memory leaks by automatically pruning oldest entries when size limit is reached.
|
|
5
|
+
* Uses LRU (Least Recently Used) eviction strategy.
|
|
6
|
+
*/
|
|
7
|
+
export class BoundedMap {
|
|
8
|
+
options;
|
|
9
|
+
map = new Map();
|
|
10
|
+
evictionCount = 0;
|
|
11
|
+
hitCount = 0;
|
|
12
|
+
missCount = 0;
|
|
13
|
+
constructor(options) {
|
|
14
|
+
this.options = options;
|
|
15
|
+
if (options.maxSize <= 0) {
|
|
16
|
+
throw new Error("maxSize must be positive");
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/** Set a value */
|
|
20
|
+
set(key, value) {
|
|
21
|
+
const now = Date.now();
|
|
22
|
+
// If key exists, update it
|
|
23
|
+
if (this.map.has(key)) {
|
|
24
|
+
this.map.set(key, { value, accessTs: now, createTs: this.map.get(key).createTs });
|
|
25
|
+
return this;
|
|
26
|
+
}
|
|
27
|
+
// If at capacity, evict oldest entry
|
|
28
|
+
if (this.map.size >= this.options.maxSize) {
|
|
29
|
+
this.evictOldest();
|
|
30
|
+
}
|
|
31
|
+
this.map.set(key, { value, accessTs: now, createTs: now });
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
/** Get a value */
|
|
35
|
+
get(key) {
|
|
36
|
+
const entry = this.map.get(key);
|
|
37
|
+
if (!entry) {
|
|
38
|
+
this.missCount++;
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
// Check TTL if configured
|
|
42
|
+
if (this.options.ttlMs) {
|
|
43
|
+
const age = Date.now() - entry.createTs;
|
|
44
|
+
if (age > this.options.ttlMs) {
|
|
45
|
+
this.delete(key);
|
|
46
|
+
this.missCount++;
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Update access time (LRU)
|
|
51
|
+
entry.accessTs = Date.now();
|
|
52
|
+
this.hitCount++;
|
|
53
|
+
return entry.value;
|
|
54
|
+
}
|
|
55
|
+
/** Check if key exists */
|
|
56
|
+
has(key) {
|
|
57
|
+
if (!this.map.has(key))
|
|
58
|
+
return false;
|
|
59
|
+
// Check TTL if configured
|
|
60
|
+
if (this.options.ttlMs) {
|
|
61
|
+
const entry = this.map.get(key);
|
|
62
|
+
const age = Date.now() - entry.createTs;
|
|
63
|
+
if (age > this.options.ttlMs) {
|
|
64
|
+
this.delete(key);
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
/** Delete a key */
|
|
71
|
+
delete(key) {
|
|
72
|
+
const entry = this.map.get(key);
|
|
73
|
+
if (entry) {
|
|
74
|
+
this.options.onEvict?.(key, entry.value);
|
|
75
|
+
}
|
|
76
|
+
return this.map.delete(key);
|
|
77
|
+
}
|
|
78
|
+
/** Clear all entries */
|
|
79
|
+
clear() {
|
|
80
|
+
if (this.options.onEvict) {
|
|
81
|
+
for (const [key, entry] of this.map) {
|
|
82
|
+
this.options.onEvict(key, entry.value);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
this.map.clear();
|
|
86
|
+
}
|
|
87
|
+
/** Get current size */
|
|
88
|
+
get size() {
|
|
89
|
+
return this.map.size;
|
|
90
|
+
}
|
|
91
|
+
/** Get all keys */
|
|
92
|
+
keys() {
|
|
93
|
+
return this.map.keys();
|
|
94
|
+
}
|
|
95
|
+
/** Get all values */
|
|
96
|
+
values() {
|
|
97
|
+
return Array.from(this.map.values()).map(e => e.value).values();
|
|
98
|
+
}
|
|
99
|
+
/** Get all entries */
|
|
100
|
+
entries() {
|
|
101
|
+
return Array.from(this.map.entries()).map(([k, e]) => [k, e.value]).values();
|
|
102
|
+
}
|
|
103
|
+
/** Get stats */
|
|
104
|
+
getStats() {
|
|
105
|
+
return {
|
|
106
|
+
size: this.map.size,
|
|
107
|
+
maxSize: this.options.maxSize,
|
|
108
|
+
evictionCount: this.evictionCount,
|
|
109
|
+
hitCount: this.hitCount,
|
|
110
|
+
missCount: this.missCount,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/** Evict oldest (least recently used) entry */
|
|
114
|
+
evictOldest() {
|
|
115
|
+
let oldestKey;
|
|
116
|
+
let oldestTs = Infinity;
|
|
117
|
+
for (const [key, entry] of this.map) {
|
|
118
|
+
if (entry.accessTs < oldestTs) {
|
|
119
|
+
oldestTs = entry.accessTs;
|
|
120
|
+
oldestKey = key;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (oldestKey) {
|
|
124
|
+
this.delete(oldestKey);
|
|
125
|
+
this.evictionCount++;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=bounded-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bounded-map.js","sourceRoot":"","sources":["../../src/core/bounded-map.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { OpenAlertsEventBus } from "./event-bus.js";
|
|
2
|
+
import { type AlertEvent, type EvaluatorState, type OpenAlertsEvent, type OpenAlertsInitOptions, type StoredEvent } from "./types.js";
|
|
3
|
+
import type { DatabaseSync } from "node:sqlite";
|
|
4
|
+
export declare class OpenAlertsEngine {
|
|
5
|
+
readonly bus: OpenAlertsEventBus;
|
|
6
|
+
readonly state: EvaluatorState;
|
|
7
|
+
private config;
|
|
8
|
+
private stateDir;
|
|
9
|
+
private dispatcher;
|
|
10
|
+
private enricher;
|
|
11
|
+
private logger;
|
|
12
|
+
private logPrefix;
|
|
13
|
+
private db;
|
|
14
|
+
private watchdogTimer;
|
|
15
|
+
private pruneTimer;
|
|
16
|
+
private running;
|
|
17
|
+
private eventRing;
|
|
18
|
+
private static readonly RING_MAX;
|
|
19
|
+
constructor(options: OpenAlertsInitOptions & {
|
|
20
|
+
db?: DatabaseSync | null;
|
|
21
|
+
});
|
|
22
|
+
start(): void;
|
|
23
|
+
ingest(event: OpenAlertsEvent): void;
|
|
24
|
+
stop(): void;
|
|
25
|
+
addChannel(channel: {
|
|
26
|
+
readonly name: string;
|
|
27
|
+
send(alert: AlertEvent, formatted: string): Promise<void> | void;
|
|
28
|
+
}): void;
|
|
29
|
+
sendTestAlert(): void;
|
|
30
|
+
get isRunning(): boolean;
|
|
31
|
+
getRecentEvents(limit?: number): StoredEvent[];
|
|
32
|
+
getRecentLiveEvents(limit?: number): OpenAlertsEvent[];
|
|
33
|
+
private handleEvent;
|
|
34
|
+
private fireAlert;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/core/engine.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAIpD,OAAO,EAEL,KAAK,UAAU,EAEf,KAAK,cAAc,EAEnB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAE1B,KAAK,WAAW,EACjB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,qBAAa,gBAAgB;IAC3B,QAAQ,CAAC,GAAG,EAAE,kBAAkB,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAE/B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,EAAE,CAAsB;IAEhC,OAAO,CAAC,aAAa,CAA+C;IACpE,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAyB;IAC1C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAO;gBAE3B,OAAO,EAAE,qBAAqB,GAAG;QAAE,EAAE,CAAC,EAAE,YAAY,GAAG,IAAI,CAAA;KAAE;IAmBzE,KAAK,IAAI,IAAI;IAoCb,MAAM,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;IAEpC,IAAI,IAAI,IAAI;IASZ,UAAU,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI;IAItH,aAAa,IAAI,IAAI;IAUrB,IAAI,SAAS,IAAI,OAAO,CAAyB;IAEjD,eAAe,CAAC,KAAK,SAAM,GAAG,WAAW,EAAE;IAC3C,mBAAmB,CAAC,KAAK,SAAM,GAAG,eAAe,EAAE;IAEnD,OAAO,CAAC,WAAW;YAgCL,SAAS;CA8BxB"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { AlertDispatcher } from "./alert-channel.js";
|
|
2
|
+
import { OpenAlertsEventBus } from "./event-bus.js";
|
|
3
|
+
import { createEvaluatorState, processEvent, processWatchdogTick, warmFromHistory } from "./evaluator.js";
|
|
4
|
+
import { ALL_RULES } from "./rules.js";
|
|
5
|
+
import { appendEvent, pruneLog, readAllEvents, readRecentEvents } from "./store.js";
|
|
6
|
+
import { DEFAULTS, } from "./types.js";
|
|
7
|
+
import { upsertAlert, insertDiagnostic } from "../db/queries.js";
|
|
8
|
+
export class OpenAlertsEngine {
|
|
9
|
+
bus;
|
|
10
|
+
state;
|
|
11
|
+
config;
|
|
12
|
+
stateDir;
|
|
13
|
+
dispatcher;
|
|
14
|
+
enricher;
|
|
15
|
+
logger;
|
|
16
|
+
logPrefix;
|
|
17
|
+
db;
|
|
18
|
+
watchdogTimer = null;
|
|
19
|
+
pruneTimer = null;
|
|
20
|
+
running = false;
|
|
21
|
+
eventRing = [];
|
|
22
|
+
static RING_MAX = 500;
|
|
23
|
+
constructor(options) {
|
|
24
|
+
this.config = options.config;
|
|
25
|
+
this.stateDir = options.stateDir;
|
|
26
|
+
this.enricher = options.enricher ?? null;
|
|
27
|
+
this.logger = options.logger ?? console;
|
|
28
|
+
this.logPrefix = options.logPrefix ?? "openalerts";
|
|
29
|
+
this.db = options.db ?? null;
|
|
30
|
+
this.bus = new OpenAlertsEventBus();
|
|
31
|
+
this.state = createEvaluatorState();
|
|
32
|
+
this.dispatcher = new AlertDispatcher({
|
|
33
|
+
channels: options.channels,
|
|
34
|
+
logger: this.logger,
|
|
35
|
+
diagnosisHint: options.diagnosisHint,
|
|
36
|
+
});
|
|
37
|
+
this.bus.on(event => this.handleEvent(event));
|
|
38
|
+
}
|
|
39
|
+
start() {
|
|
40
|
+
if (this.running)
|
|
41
|
+
return;
|
|
42
|
+
this.running = true;
|
|
43
|
+
try {
|
|
44
|
+
const history = readAllEvents(this.stateDir);
|
|
45
|
+
warmFromHistory(this.state, history);
|
|
46
|
+
this.logger.info(`${this.logPrefix}: warmed from ${history.length} events`);
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
this.logger.warn(`${this.logPrefix}: warm-start failed: ${err}`);
|
|
50
|
+
}
|
|
51
|
+
this.watchdogTimer = setInterval(() => {
|
|
52
|
+
const alerts = processWatchdogTick(this.state, this.config);
|
|
53
|
+
for (const alert of alerts) {
|
|
54
|
+
void this.fireAlert(alert).catch(err => this.logger.error(`${this.logPrefix}: watchdog alert failed: ${err}`));
|
|
55
|
+
}
|
|
56
|
+
}, DEFAULTS.watchdogIntervalMs);
|
|
57
|
+
this.pruneTimer = setInterval(() => {
|
|
58
|
+
try {
|
|
59
|
+
pruneLog(this.stateDir, {
|
|
60
|
+
maxAgeMs: (this.config.maxLogAgeDays ?? DEFAULTS.maxLogAgeDays) * 24 * 60 * 60 * 1000,
|
|
61
|
+
maxSizeKb: this.config.maxLogSizeKb ?? DEFAULTS.maxLogSizeKb,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
this.logger.warn(`${this.logPrefix}: prune failed: ${err}`);
|
|
66
|
+
}
|
|
67
|
+
}, DEFAULTS.pruneIntervalMs);
|
|
68
|
+
const ch = this.dispatcher.hasChannels ? `${this.dispatcher.channelCount} channel(s)` : "log-only";
|
|
69
|
+
this.logger.info(`${this.logPrefix}: started — ${ch}, ${ALL_RULES.length} rules active`);
|
|
70
|
+
}
|
|
71
|
+
ingest(event) { this.bus.emit(event); }
|
|
72
|
+
stop() {
|
|
73
|
+
if (!this.running)
|
|
74
|
+
return;
|
|
75
|
+
this.running = false;
|
|
76
|
+
if (this.watchdogTimer) {
|
|
77
|
+
clearInterval(this.watchdogTimer);
|
|
78
|
+
this.watchdogTimer = null;
|
|
79
|
+
}
|
|
80
|
+
if (this.pruneTimer) {
|
|
81
|
+
clearInterval(this.pruneTimer);
|
|
82
|
+
this.pruneTimer = null;
|
|
83
|
+
}
|
|
84
|
+
this.bus.clear();
|
|
85
|
+
this.logger.info(`${this.logPrefix}: stopped`);
|
|
86
|
+
}
|
|
87
|
+
addChannel(channel) {
|
|
88
|
+
this.dispatcher.addChannel(channel);
|
|
89
|
+
}
|
|
90
|
+
sendTestAlert() {
|
|
91
|
+
void this.fireAlert({
|
|
92
|
+
type: "alert", id: `test:manual:${Date.now()}`,
|
|
93
|
+
ruleId: "test", severity: "info",
|
|
94
|
+
title: "Test alert — delivery verified",
|
|
95
|
+
detail: "If you see this, alert delivery is working.",
|
|
96
|
+
ts: Date.now(), fingerprint: "test:manual",
|
|
97
|
+
}).catch(err => this.logger.error(`${this.logPrefix}: test alert failed: ${err}`));
|
|
98
|
+
}
|
|
99
|
+
get isRunning() { return this.running; }
|
|
100
|
+
getRecentEvents(limit = 100) { return readRecentEvents(this.stateDir, limit); }
|
|
101
|
+
getRecentLiveEvents(limit = 200) { return this.eventRing.slice(-limit); }
|
|
102
|
+
handleEvent(event) {
|
|
103
|
+
this.eventRing.push(event);
|
|
104
|
+
if (this.eventRing.length > OpenAlertsEngine.RING_MAX)
|
|
105
|
+
this.eventRing = this.eventRing.slice(-OpenAlertsEngine.RING_MAX);
|
|
106
|
+
const snapshot = {
|
|
107
|
+
type: "diagnostic", eventType: event.type, ts: event.ts,
|
|
108
|
+
summary: `${event.type}${event.outcome ? `:${event.outcome}` : ""}`,
|
|
109
|
+
channel: event.channel, sessionKey: event.sessionKey,
|
|
110
|
+
};
|
|
111
|
+
try {
|
|
112
|
+
appendEvent(this.stateDir, snapshot);
|
|
113
|
+
}
|
|
114
|
+
catch { /* ignore */ }
|
|
115
|
+
// Write to SQLite
|
|
116
|
+
if (this.db) {
|
|
117
|
+
try {
|
|
118
|
+
insertDiagnostic(this.db, {
|
|
119
|
+
event_type: event.type, ts: event.ts,
|
|
120
|
+
summary: snapshot.summary, channel: event.channel,
|
|
121
|
+
session_key: event.sessionKey, agent_id: event.agentId,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
catch { /* ignore */ }
|
|
125
|
+
}
|
|
126
|
+
const alerts = processEvent(this.state, this.config, event);
|
|
127
|
+
for (const alert of alerts) {
|
|
128
|
+
void this.fireAlert(alert).catch(err => this.logger.error(`${this.logPrefix}: alert fire failed: ${err}`));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
async fireAlert(alert) {
|
|
132
|
+
try {
|
|
133
|
+
appendEvent(this.stateDir, alert);
|
|
134
|
+
}
|
|
135
|
+
catch { /* ignore */ }
|
|
136
|
+
// Write to SQLite
|
|
137
|
+
if (this.db) {
|
|
138
|
+
try {
|
|
139
|
+
upsertAlert(this.db, {
|
|
140
|
+
id: alert.id, rule_id: alert.ruleId,
|
|
141
|
+
severity: alert.severity, title: alert.title,
|
|
142
|
+
detail: alert.detail, ts: alert.ts, fingerprint: alert.fingerprint,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
catch { /* ignore */ }
|
|
146
|
+
}
|
|
147
|
+
let enriched = alert;
|
|
148
|
+
if (this.enricher) {
|
|
149
|
+
try {
|
|
150
|
+
const result = await this.enricher(alert);
|
|
151
|
+
if (result)
|
|
152
|
+
enriched = result;
|
|
153
|
+
}
|
|
154
|
+
catch { /* ignore */ }
|
|
155
|
+
}
|
|
156
|
+
if (!this.config.quiet) {
|
|
157
|
+
void this.dispatcher.dispatch(enriched).catch(err => this.logger.error(`${this.logPrefix}: dispatch failed: ${err}`));
|
|
158
|
+
}
|
|
159
|
+
this.logger.info(`${this.logPrefix}: [${alert.severity}] ${alert.title}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/core/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type AlertEvent, type EvaluatorState, type MonitorConfig, type OpenAlertsEvent, type StoredEvent } from "./types.js";
|
|
2
|
+
/** Create a fresh evaluator state. */
|
|
3
|
+
export declare function createEvaluatorState(): EvaluatorState;
|
|
4
|
+
/**
|
|
5
|
+
* Warm the evaluator state from persisted events.
|
|
6
|
+
* Replays recent events to rebuild windows/counters without re-firing alerts.
|
|
7
|
+
*/
|
|
8
|
+
export declare function warmFromHistory(state: EvaluatorState, events: StoredEvent[]): void;
|
|
9
|
+
/**
|
|
10
|
+
* Process a single event through all rules.
|
|
11
|
+
* Returns alerts that should be fired (already filtered by cooldown + hourly cap).
|
|
12
|
+
*/
|
|
13
|
+
export declare function processEvent(state: EvaluatorState, config: MonitorConfig, event: OpenAlertsEvent): AlertEvent[];
|
|
14
|
+
/**
|
|
15
|
+
* Run the watchdog tick — checks for gateway-down condition.
|
|
16
|
+
* Called every 30 seconds by the engine timer.
|
|
17
|
+
*/
|
|
18
|
+
export declare function processWatchdogTick(state: EvaluatorState, config: MonitorConfig): AlertEvent[];
|
|
19
|
+
//# sourceMappingURL=evaluator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../../src/core/evaluator.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,WAAW,EACjB,MAAM,YAAY,CAAC;AAEpB,sCAAsC;AACtC,wBAAgB,oBAAoB,IAAI,cAAc,CA0BrD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,WAAW,EAAE,GACpB,IAAI,CASN;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,eAAe,GACrB,UAAU,EAAE,CAsGd;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,aAAa,GACpB,UAAU,EAAE,CAEd"}
|