Skip to main content

agent_engine/events/
types.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use serde_json::Value;
4use uuid::Uuid;
5
6#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
7pub enum Severity {
8    Low,
9    Medium,
10    High,
11    Critical,
12}
13
14impl Severity {
15    pub fn as_str(&self) -> &str {
16        match self {
17            Severity::Low => "low",
18            Severity::Medium => "medium",
19            Severity::High => "high",
20            Severity::Critical => "critical",
21        }
22    }
23
24    #[allow(clippy::should_implement_trait)]
25    pub fn from_str(s: &str) -> Self {
26        match s.to_lowercase().as_str() {
27            "low" => Severity::Low,
28            "high" => Severity::High,
29            "critical" => Severity::Critical,
30            _ => Severity::Medium,
31        }
32    }
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct EventSource {
37    pub source_type: String,
38    pub name: String,
39    pub callback: Option<String>,
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct EventChannel {
44    pub id: String,
45    pub name: String,
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct EventSender {
50    pub id: String,
51    pub name: String,
52    pub sender_type: String,
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct EventContent {
57    pub text: String,
58    pub content_type: String,
59    pub severity: Option<Severity>,
60    pub data: Option<Value>,
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct Event {
65    pub id: String,
66    pub timestamp: DateTime<Utc>,
67    pub source: EventSource,
68    pub channel: Option<EventChannel>,
69    pub sender: Option<EventSender>,
70    pub content: EventContent,
71    pub expects_response: bool,
72    pub reply_to: Option<String>,
73}
74
75impl Event {
76    /// Create a simple event from minimal params (for CLI / quick use).
77    pub fn simple(source_type: &str, text: &str, severity: Option<Severity>) -> Self {
78        Event {
79            id: Uuid::new_v4().to_string(),
80            timestamp: Utc::now(),
81            source: EventSource {
82                source_type: source_type.to_string(),
83                name: source_type.to_string(),
84                callback: None,
85            },
86            channel: None,
87            sender: None,
88            content: EventContent {
89                text: text.to_string(),
90                content_type: "message".to_string(),
91                severity,
92                data: None,
93            },
94            expects_response: false,
95            reply_to: None,
96        }
97    }
98}
99
100#[cfg(test)]
101mod tests {
102    use super::*;
103
104    #[test]
105    fn severity_ordering() {
106        assert!(Severity::Low < Severity::Medium);
107        assert!(Severity::Medium < Severity::High);
108        assert!(Severity::High < Severity::Critical);
109    }
110
111    #[test]
112    fn severity_str_roundtrip() {
113        for s in [Severity::Low, Severity::Medium, Severity::High, Severity::Critical] {
114            assert_eq!(Severity::from_str(s.as_str()), s);
115        }
116        assert_eq!(Severity::from_str("garbage"), Severity::Medium);
117    }
118
119    #[test]
120    fn event_simple_defaults() {
121        let e = Event::simple("cli", "hello", Some(Severity::High));
122        assert_eq!(e.source.source_type, "cli");
123        assert_eq!(e.content.text, "hello");
124        assert_eq!(e.content.severity, Some(Severity::High));
125        assert!(!e.expects_response);
126        assert!(e.channel.is_none());
127    }
128
129    #[test]
130    fn event_serde_roundtrip() {
131        let e = Event::simple("discord", "yo", Some(Severity::Critical));
132        let json = serde_json::to_string(&e).unwrap();
133        let back: Event = serde_json::from_str(&json).unwrap();
134        assert_eq!(back.id, e.id);
135        assert_eq!(back.content.text, "yo");
136        assert_eq!(back.content.severity, Some(Severity::Critical));
137    }
138}