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