mojentic/
event.rs

1//! Event system for agent communication.
2//!
3//! This module provides the core event types that agents use to communicate.
4//! Events are the fundamental unit of information exchange in the agent system.
5//!
6//! # Examples
7//!
8//! ```
9//! use mojentic::event::Event;
10//! use serde::{Deserialize, Serialize};
11//! use std::any::Any;
12//!
13//! #[derive(Debug, Clone, Serialize, Deserialize)]
14//! struct MyCustomEvent {
15//!     source: String,
16//!     correlation_id: Option<String>,
17//!     data: String,
18//! }
19//!
20//! impl Event for MyCustomEvent {
21//!     fn source(&self) -> &str {
22//!         &self.source
23//!     }
24//!
25//!     fn correlation_id(&self) -> Option<&str> {
26//!         self.correlation_id.as_deref()
27//!     }
28//!
29//!     fn set_correlation_id(&mut self, id: String) {
30//!         self.correlation_id = Some(id);
31//!     }
32//!
33//!     fn as_any(&self) -> &dyn Any {
34//!         self
35//!     }
36//!
37//!     fn clone_box(&self) -> Box<dyn Event> {
38//!         Box::new(self.clone())
39//!     }
40//! }
41//! ```
42
43use serde::{Deserialize, Serialize};
44use std::any::Any;
45
46/// Base trait for all events in the agent system.
47///
48/// Events are used to communicate between agents in an asynchronous manner.
49/// Each event has a source (the agent that created it) and optionally a
50/// correlation_id to track related events through a workflow.
51pub trait Event: Send + Sync + std::fmt::Debug {
52    /// Returns the source agent identifier
53    fn source(&self) -> &str;
54
55    /// Returns the correlation ID if set
56    fn correlation_id(&self) -> Option<&str>;
57
58    /// Sets the correlation ID
59    fn set_correlation_id(&mut self, id: String);
60
61    /// Cast to Any for downcasting
62    fn as_any(&self) -> &dyn Any;
63
64    /// Clone the event into a Box
65    fn clone_box(&self) -> Box<dyn Event>;
66}
67
68/// A special event type that signals the dispatcher to terminate
69#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct TerminateEvent {
71    pub source: String,
72    pub correlation_id: Option<String>,
73}
74
75impl Event for TerminateEvent {
76    fn source(&self) -> &str {
77        &self.source
78    }
79
80    fn correlation_id(&self) -> Option<&str> {
81        self.correlation_id.as_deref()
82    }
83
84    fn set_correlation_id(&mut self, id: String) {
85        self.correlation_id = Some(id);
86    }
87
88    fn as_any(&self) -> &dyn Any {
89        self
90    }
91
92    fn clone_box(&self) -> Box<dyn Event> {
93        Box::new(self.clone())
94    }
95}
96
97impl TerminateEvent {
98    /// Create a new TerminateEvent
99    pub fn new(source: impl Into<String>) -> Self {
100        Self {
101            source: source.into(),
102            correlation_id: None,
103        }
104    }
105}
106
107#[cfg(test)]
108mod tests {
109    use super::*;
110
111    #[derive(Debug, Clone, Serialize, Deserialize)]
112    struct TestEvent {
113        source: String,
114        correlation_id: Option<String>,
115        data: String,
116    }
117
118    impl Event for TestEvent {
119        fn source(&self) -> &str {
120            &self.source
121        }
122
123        fn correlation_id(&self) -> Option<&str> {
124            self.correlation_id.as_deref()
125        }
126
127        fn set_correlation_id(&mut self, id: String) {
128            self.correlation_id = Some(id);
129        }
130
131        fn as_any(&self) -> &dyn Any {
132            self
133        }
134
135        fn clone_box(&self) -> Box<dyn Event> {
136            Box::new(self.clone())
137        }
138    }
139
140    #[test]
141    fn test_event_source() {
142        let event = TestEvent {
143            source: "TestAgent".to_string(),
144            correlation_id: None,
145            data: "test".to_string(),
146        };
147
148        assert_eq!(event.source(), "TestAgent");
149    }
150
151    #[test]
152    fn test_event_correlation_id() {
153        let mut event = TestEvent {
154            source: "TestAgent".to_string(),
155            correlation_id: None,
156            data: "test".to_string(),
157        };
158
159        assert_eq!(event.correlation_id(), None);
160
161        event.set_correlation_id("test-123".to_string());
162        assert_eq!(event.correlation_id(), Some("test-123"));
163    }
164
165    #[test]
166    fn test_terminate_event() {
167        let mut event = TerminateEvent::new("System");
168        assert_eq!(event.source(), "System");
169        assert_eq!(event.correlation_id(), None);
170
171        event.set_correlation_id("stop-123".to_string());
172        assert_eq!(event.correlation_id(), Some("stop-123"));
173    }
174
175    #[test]
176    fn test_event_clone_box() {
177        let event = TestEvent {
178            source: "TestAgent".to_string(),
179            correlation_id: Some("test-456".to_string()),
180            data: "test data".to_string(),
181        };
182
183        let cloned = event.clone_box();
184        assert_eq!(cloned.source(), "TestAgent");
185        assert_eq!(cloned.correlation_id(), Some("test-456"));
186    }
187
188    #[test]
189    fn test_event_as_any() {
190        let event = TestEvent {
191            source: "TestAgent".to_string(),
192            correlation_id: None,
193            data: "test".to_string(),
194        };
195
196        let any = event.as_any();
197        assert!(any.is::<TestEvent>());
198        assert!(any.downcast_ref::<TestEvent>().is_some());
199    }
200}