1use crate::config::OmegaConfig;
4use crate::error::{RuntimeError, RuntimeResult};
5use crate::events::{EventBus, EventHandler, OmegaEvent};
6use omega_agentdb::{AgentDB, AgentDBConfig};
7use omega_loops::LoopEngine;
8use omega_memory::CosmicMemory;
9use omega_meta_sona::MetaSONA;
10use parking_lot::RwLock;
11use std::sync::Arc;
12use tracing::{debug, info};
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum RuntimeState {
17 Uninitialized,
19 Initializing,
21 Running,
23 Paused,
25 ShuttingDown,
27 Stopped,
29}
30
31impl RuntimeState {
32 pub fn can_transition_to(&self, target: RuntimeState) -> bool {
34 use RuntimeState::*;
35 matches!(
36 (self, target),
37 (Uninitialized, Initializing)
38 | (Initializing, Running)
39 | (Initializing, Stopped)
40 | (Running, Paused)
41 | (Running, ShuttingDown)
42 | (Paused, Running)
43 | (Paused, ShuttingDown)
44 | (ShuttingDown, Stopped)
45 )
46 }
47
48 pub fn description(&self) -> &'static str {
50 match self {
51 RuntimeState::Uninitialized => "uninitialized",
52 RuntimeState::Initializing => "initializing",
53 RuntimeState::Running => "running",
54 RuntimeState::Paused => "paused",
55 RuntimeState::ShuttingDown => "shutting down",
56 RuntimeState::Stopped => "stopped",
57 }
58 }
59}
60
61pub struct OmegaRuntime {
63 config: OmegaConfig,
64 agentdb: Arc<AgentDB>,
65 memory: Arc<CosmicMemory>,
66 loops: Arc<LoopEngine>,
67 meta_sona: Arc<MetaSONA>,
68 event_bus: Arc<RwLock<EventBus>>,
69 state: Arc<RwLock<RuntimeState>>,
70}
71
72impl OmegaRuntime {
73 pub async fn new(config: OmegaConfig) -> RuntimeResult<Self> {
75 info!("Creating OmegaRuntime with configuration");
76
77 config.validate().map_err(|e| {
79 RuntimeError::Config(format!("Invalid configuration: {}", e))
80 })?;
81
82 let agentdb = Arc::new(
84 AgentDB::new(AgentDBConfig::default())
85 .await
86 .map_err(|e| RuntimeError::AgentDB(e.to_string()))?
87 );
88
89 let memory = Arc::new(
90 CosmicMemory::new()
91 .await
92 .map_err(|e| RuntimeError::Memory(e.to_string()))?
93 );
94
95 let loops = Arc::new(LoopEngine::new());
96 let meta_sona = Arc::new(MetaSONA::new());
97
98 let event_bus = if config.enable_event_logging {
99 Arc::new(RwLock::new(EventBus::new()))
100 } else {
101 Arc::new(RwLock::new(EventBus::with_buffer_size(0)))
102 };
103
104 Ok(Self {
105 config,
106 agentdb,
107 memory,
108 loops,
109 meta_sona,
110 event_bus,
111 state: Arc::new(RwLock::new(RuntimeState::Uninitialized)),
112 })
113 }
114
115 pub async fn start(&self) -> RuntimeResult<()> {
117 self.transition_state(RuntimeState::Initializing)?;
118
119 info!("Starting OmegaRuntime");
120
121 debug!("AgentDB ready");
124 debug!("Memory system ready");
125 debug!("Loop engine ready");
126 debug!("Meta-SONA ready");
127
128 self.transition_state(RuntimeState::Running)?;
129
130 self.emit_event(OmegaEvent::SystemStarted {
131 timestamp: chrono::Utc::now(),
132 });
133
134 info!("OmegaRuntime started successfully");
135 Ok(())
136 }
137
138 pub async fn stop(&self) -> RuntimeResult<()> {
140 self.transition_state(RuntimeState::ShuttingDown)?;
141
142 info!("Stopping OmegaRuntime");
143
144 debug!("Meta-SONA stopping");
147 debug!("Loop engine stopping");
148 debug!("Memory system stopping");
149 debug!("AgentDB stopping");
150
151 self.transition_state(RuntimeState::Stopped)?;
152
153 self.emit_event(OmegaEvent::SystemShutdown {
154 timestamp: chrono::Utc::now(),
155 });
156
157 info!("OmegaRuntime stopped");
158 Ok(())
159 }
160
161 pub async fn pause(&self) -> RuntimeResult<()> {
163 self.transition_state(RuntimeState::Paused)?;
164
165 info!("Pausing OmegaRuntime");
166
167 self.emit_event(OmegaEvent::SystemPaused {
168 timestamp: chrono::Utc::now(),
169 });
170
171 Ok(())
172 }
173
174 pub async fn resume(&self) -> RuntimeResult<()> {
176 self.transition_state(RuntimeState::Running)?;
177
178 info!("Resuming OmegaRuntime");
179
180 self.emit_event(OmegaEvent::SystemResumed {
181 timestamp: chrono::Utc::now(),
182 });
183
184 Ok(())
185 }
186
187 pub fn agentdb(&self) -> &AgentDB {
189 &self.agentdb
190 }
191
192 pub fn memory(&self) -> &CosmicMemory {
194 &self.memory
195 }
196
197 pub fn loops(&self) -> &LoopEngine {
199 &self.loops
200 }
201
202 pub fn meta_sona(&self) -> &MetaSONA {
204 &self.meta_sona
205 }
206
207 pub fn config(&self) -> &OmegaConfig {
209 &self.config
210 }
211
212 pub fn state(&self) -> RuntimeState {
214 *self.state.read()
215 }
216
217 pub fn is_running(&self) -> bool {
219 *self.state.read() == RuntimeState::Running
220 }
221
222 pub fn is_paused(&self) -> bool {
224 *self.state.read() == RuntimeState::Paused
225 }
226
227 pub fn on_event(&self, handler: EventHandler) {
229 self.event_bus.write().on(handler);
230 }
231
232 pub fn event_history(&self) -> Vec<OmegaEvent> {
234 self.event_bus.read().history().to_vec()
235 }
236
237 pub fn clear_event_history(&self) {
239 self.event_bus.write().clear_history();
240 }
241
242 fn transition_state(&self, new_state: RuntimeState) -> RuntimeResult<()> {
244 let mut state = self.state.write();
245
246 if !state.can_transition_to(new_state) {
247 return Err(RuntimeError::InvalidStateTransition {
248 current: state.description().to_string(),
249 attempted: new_state.description().to_string(),
250 });
251 }
252
253 debug!("State transition: {} -> {}", state.description(), new_state.description());
254 *state = new_state;
255 Ok(())
256 }
257
258 fn emit_event(&self, event: OmegaEvent) {
260 if self.config.enable_event_logging {
261 self.event_bus.write().emit(event);
262 }
263 }
264
265 pub async fn health(&self) -> RuntimeHealth {
267 RuntimeHealth {
268 state: self.state(),
269 agentdb_healthy: true, memory_healthy: true,
271 loops_healthy: true,
272 meta_sona_healthy: true,
273 }
274 }
275}
276
277#[derive(Debug, Clone)]
279pub struct RuntimeHealth {
280 pub state: RuntimeState,
281 pub agentdb_healthy: bool,
282 pub memory_healthy: bool,
283 pub loops_healthy: bool,
284 pub meta_sona_healthy: bool,
285}
286
287impl RuntimeHealth {
288 pub fn is_healthy(&self) -> bool {
290 self.agentdb_healthy
291 && self.memory_healthy
292 && self.loops_healthy
293 && self.meta_sona_healthy
294 && self.state == RuntimeState::Running
295 }
296}
297
298#[cfg(test)]
299mod tests {
300 use super::*;
301
302 #[test]
303 fn test_state_transitions() {
304 use RuntimeState::*;
305
306 assert!(Uninitialized.can_transition_to(Initializing));
307 assert!(Initializing.can_transition_to(Running));
308 assert!(Running.can_transition_to(Paused));
309 assert!(Paused.can_transition_to(Running));
310 assert!(Running.can_transition_to(ShuttingDown));
311 assert!(ShuttingDown.can_transition_to(Stopped));
312
313 assert!(!Uninitialized.can_transition_to(Running));
314 assert!(!Running.can_transition_to(Stopped));
315 assert!(!Stopped.can_transition_to(Running));
316 }
317
318 #[tokio::test]
319 async fn test_runtime_creation() {
320 let config = OmegaConfig::minimal();
321 let runtime = OmegaRuntime::new(config).await;
322 assert!(runtime.is_ok());
323 }
324
325 #[tokio::test]
326 async fn test_runtime_lifecycle() {
327 let config = OmegaConfig::minimal();
328 let runtime = OmegaRuntime::new(config).await.unwrap();
329
330 assert_eq!(runtime.state(), RuntimeState::Uninitialized);
331
332 runtime.start().await.unwrap();
333 assert_eq!(runtime.state(), RuntimeState::Running);
334 assert!(runtime.is_running());
335
336 runtime.pause().await.unwrap();
337 assert_eq!(runtime.state(), RuntimeState::Paused);
338 assert!(runtime.is_paused());
339
340 runtime.resume().await.unwrap();
341 assert_eq!(runtime.state(), RuntimeState::Running);
342
343 runtime.stop().await.unwrap();
344 assert_eq!(runtime.state(), RuntimeState::Stopped);
345 }
346
347 #[tokio::test]
348 async fn test_invalid_state_transition() {
349 let config = OmegaConfig::minimal();
350 let runtime = OmegaRuntime::new(config).await.unwrap();
351
352 let result = runtime.pause().await;
354 assert!(result.is_err());
355 }
356
357 #[tokio::test]
358 async fn test_event_emission() {
359 let mut config = OmegaConfig::minimal();
360 config.enable_event_logging = true; let runtime = OmegaRuntime::new(config).await.unwrap();
362
363 runtime.start().await.unwrap();
364
365 let history = runtime.event_history();
366 assert!(history.iter().any(|e| matches!(e, OmegaEvent::SystemStarted { .. })));
367 }
368}