Skip to main content

hyper_risk/
alerts.rs

1use serde::{Deserialize, Serialize};
2use std::fs;
3use std::path::PathBuf;
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
6#[serde(rename_all = "camelCase")]
7pub struct AlertRule {
8    pub id: String,
9    pub name: String,
10    pub condition: String,
11    pub severity: String,
12    pub enabled: bool,
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
16#[serde(rename_all = "camelCase")]
17pub struct TelegramConfig {
18    pub enabled: bool,
19    pub bot_token: String,
20    pub chat_id: String,
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
24#[serde(rename_all = "camelCase")]
25pub struct AlertConfig {
26    pub system_notifications: bool,
27    pub telegram: TelegramConfig,
28    pub rules: Vec<AlertRule>,
29}
30
31#[derive(Debug, Clone, Serialize, Deserialize)]
32#[serde(rename_all = "camelCase")]
33pub struct AlertHistoryEntry {
34    pub id: String,
35    pub timestamp: String,
36    pub severity: String,
37    pub message: String,
38    pub channel: String,
39    pub status: String,
40}
41
42impl Default for AlertConfig {
43    fn default() -> Self {
44        Self {
45            system_notifications: true,
46            telegram: TelegramConfig {
47                enabled: false,
48                bot_token: String::new(),
49                chat_id: String::new(),
50            },
51            rules: vec![
52                AlertRule {
53                    id: "large-loss".to_string(),
54                    name: "Large Loss Alert".to_string(),
55                    condition: "loss > 1000 USD".to_string(),
56                    severity: "critical".to_string(),
57                    enabled: true,
58                },
59                AlertRule {
60                    id: "position-size".to_string(),
61                    name: "Position Size Alert".to_string(),
62                    condition: "position > 50000 USD".to_string(),
63                    severity: "warning".to_string(),
64                    enabled: true,
65                },
66                AlertRule {
67                    id: "circuit-breaker".to_string(),
68                    name: "Circuit Breaker Triggered".to_string(),
69                    condition: "circuit_breaker == fired".to_string(),
70                    severity: "critical".to_string(),
71                    enabled: true,
72                },
73                AlertRule {
74                    id: "agent-disconnected".to_string(),
75                    name: "Agent Disconnected".to_string(),
76                    condition: "agent_status == offline".to_string(),
77                    severity: "warning".to_string(),
78                    enabled: true,
79                },
80            ],
81        }
82    }
83}
84
85pub fn alert_config_path() -> PathBuf {
86    let mut path = dirs::config_dir().unwrap_or_else(|| PathBuf::from("."));
87    path.push("hyper-agent");
88    let _ = fs::create_dir_all(&path);
89    path.push("alert-config.json");
90    path
91}
92
93pub fn alert_history_path() -> PathBuf {
94    let mut path = dirs::config_dir().unwrap_or_else(|| PathBuf::from("."));
95    path.push("hyper-agent");
96    let _ = fs::create_dir_all(&path);
97    path.push("alert-history.json");
98    path
99}