omega_runtime/
api.rs

1//! High-level API for interacting with the Omega Runtime
2
3use crate::error::{APIError, APIResult};
4use crate::events::{LoopType, MemoryTier};
5use crate::runtime::OmegaRuntime;
6use serde::{Deserialize, Serialize};
7use std::sync::Arc;
8use uuid::Uuid;
9
10/// High-level API for the Omega Runtime
11pub struct OmegaAPI {
12    runtime: Arc<OmegaRuntime>,
13}
14
15impl OmegaAPI {
16    /// Create a new API instance
17    pub fn new(runtime: Arc<OmegaRuntime>) -> Self {
18        Self { runtime }
19    }
20
21    /// Store a memory in the specified tier
22    pub async fn store_memory(
23        &self,
24        content: &str,
25        tier: MemoryTier,
26    ) -> APIResult<Uuid> {
27        if !self.runtime.is_running() {
28            return Err(APIError::Runtime(crate::error::RuntimeError::NotRunning));
29        }
30
31        let id = Uuid::new_v4();
32
33        // TODO: Implement actual memory storage when memory system API is available
34        tracing::debug!(
35            "Storing memory {} in tier {:?}: {}",
36            id,
37            tier,
38            content
39        );
40
41        Ok(id)
42    }
43
44    /// Query memories from the specified tier
45    pub async fn query_memory(
46        &self,
47        query: &str,
48        tier: Option<MemoryTier>,
49    ) -> APIResult<Vec<Memory>> {
50        if !self.runtime.is_running() {
51            return Err(APIError::Runtime(crate::error::RuntimeError::NotRunning));
52        }
53
54        // TODO: Implement actual memory query when memory system API is available
55        tracing::debug!(
56            "Querying memory with query '{}' in tier {:?}",
57            query,
58            tier
59        );
60
61        Ok(Vec::new())
62    }
63
64    /// Create a new intelligence from a specification
65    pub async fn create_intelligence(
66        &self,
67        spec: IntelligenceSpec,
68    ) -> APIResult<Intelligence> {
69        if !self.runtime.is_running() {
70            return Err(APIError::Runtime(crate::error::RuntimeError::NotRunning));
71        }
72
73        let intelligence = Intelligence {
74            id: Uuid::new_v4(),
75            architecture_id: Uuid::new_v4(),
76            name: spec.name,
77            description: spec.description,
78            fitness: 0.0,
79            generation: 0,
80            created_at: chrono::Utc::now(),
81        };
82
83        tracing::info!(
84            "Created intelligence {} with architecture {}",
85            intelligence.id,
86            intelligence.architecture_id
87        );
88
89        Ok(intelligence)
90    }
91
92    /// Evolve an architecture
93    pub async fn evolve_architecture(
94        &self,
95        id: Uuid,
96    ) -> APIResult<Architecture> {
97        if !self.runtime.is_running() {
98            return Err(APIError::Runtime(crate::error::RuntimeError::NotRunning));
99        }
100
101        // TODO: Implement actual architecture evolution when Meta-SONA API is available
102        let architecture = Architecture {
103            id,
104            fitness: 0.5,
105            generation: 1,
106            parameters: serde_json::json!({}),
107            created_at: chrono::Utc::now(),
108        };
109
110        tracing::info!("Evolved architecture {}", id);
111
112        Ok(architecture)
113    }
114
115    /// Trigger a cognitive loop cycle
116    pub async fn trigger_loop(
117        &self,
118        loop_type: LoopType,
119        input: CycleInput,
120    ) -> APIResult<CycleOutput> {
121        if !self.runtime.is_running() {
122            return Err(APIError::Runtime(crate::error::RuntimeError::NotRunning));
123        }
124
125        // TODO: Implement actual loop triggering when loop engine API is available
126        let output = CycleOutput {
127            cycle_id: Uuid::new_v4(),
128            loop_type,
129            result: serde_json::json!({}),
130            duration: std::time::Duration::from_millis(100),
131        };
132
133        tracing::debug!("Triggered {:?} loop cycle {}", loop_type, output.cycle_id);
134
135        Ok(output)
136    }
137
138    /// Get the status of all cognitive loops
139    pub async fn get_loop_status(&self) -> APIResult<LoopStatus> {
140        if !self.runtime.is_running() {
141            return Err(APIError::Runtime(crate::error::RuntimeError::NotRunning));
142        }
143
144        // TODO: Implement actual loop status retrieval
145        Ok(LoopStatus {
146            conscious: LoopInfo {
147                enabled: true,
148                cycles_completed: 0,
149                average_duration_ms: 0,
150            },
151            subconscious: LoopInfo {
152                enabled: true,
153                cycles_completed: 0,
154                average_duration_ms: 0,
155            },
156            meta: LoopInfo {
157                enabled: true,
158                cycles_completed: 0,
159                average_duration_ms: 0,
160            },
161            unconscious: LoopInfo {
162                enabled: true,
163                cycles_completed: 0,
164                average_duration_ms: 0,
165            },
166        })
167    }
168
169    /// Get runtime metrics
170    pub async fn get_metrics(&self) -> APIResult<RuntimeMetrics> {
171        let health = self.runtime.health().await;
172
173        Ok(RuntimeMetrics {
174            state: format!("{:?}", health.state),
175            is_healthy: health.is_healthy(),
176            event_count: self.runtime.event_history().len(),
177            // TODO: Add more metrics when subsystems expose them
178            agent_count: 0,
179            memory_usage_bytes: 0,
180            loop_cycles_total: 0,
181        })
182    }
183
184    /// Get the runtime configuration
185    pub fn get_config(&self) -> &crate::config::OmegaConfig {
186        self.runtime.config()
187    }
188}
189
190/// Memory representation
191#[derive(Debug, Clone, Serialize, Deserialize)]
192pub struct Memory {
193    pub id: Uuid,
194    pub content: String,
195    pub tier: MemoryTier,
196    pub created_at: chrono::DateTime<chrono::Utc>,
197    pub accessed_at: chrono::DateTime<chrono::Utc>,
198    pub access_count: usize,
199}
200
201/// Specification for creating an intelligence
202#[derive(Debug, Clone, Serialize, Deserialize)]
203pub struct IntelligenceSpec {
204    pub name: String,
205    pub description: String,
206    pub initial_parameters: Option<serde_json::Value>,
207}
208
209/// Intelligence representation
210#[derive(Debug, Clone, Serialize, Deserialize)]
211pub struct Intelligence {
212    pub id: Uuid,
213    pub architecture_id: Uuid,
214    pub name: String,
215    pub description: String,
216    pub fitness: f64,
217    pub generation: usize,
218    pub created_at: chrono::DateTime<chrono::Utc>,
219}
220
221/// Architecture representation
222#[derive(Debug, Clone, Serialize, Deserialize)]
223pub struct Architecture {
224    pub id: Uuid,
225    pub fitness: f64,
226    pub generation: usize,
227    pub parameters: serde_json::Value,
228    pub created_at: chrono::DateTime<chrono::Utc>,
229}
230
231/// Input for a cognitive loop cycle
232#[derive(Debug, Clone, Serialize, Deserialize)]
233pub struct CycleInput {
234    pub data: serde_json::Value,
235}
236
237/// Output from a cognitive loop cycle
238#[derive(Debug, Clone, Serialize, Deserialize)]
239pub struct CycleOutput {
240    pub cycle_id: Uuid,
241    pub loop_type: LoopType,
242    pub result: serde_json::Value,
243    pub duration: std::time::Duration,
244}
245
246/// Status of a single loop
247#[derive(Debug, Clone, Serialize, Deserialize)]
248pub struct LoopInfo {
249    pub enabled: bool,
250    pub cycles_completed: u64,
251    pub average_duration_ms: u64,
252}
253
254/// Status of all cognitive loops
255#[derive(Debug, Clone, Serialize, Deserialize)]
256pub struct LoopStatus {
257    pub conscious: LoopInfo,
258    pub subconscious: LoopInfo,
259    pub meta: LoopInfo,
260    pub unconscious: LoopInfo,
261}
262
263/// Runtime metrics
264#[derive(Debug, Clone, Serialize, Deserialize)]
265pub struct RuntimeMetrics {
266    pub state: String,
267    pub is_healthy: bool,
268    pub event_count: usize,
269    pub agent_count: usize,
270    pub memory_usage_bytes: usize,
271    pub loop_cycles_total: u64,
272}
273
274#[cfg(test)]
275mod tests {
276    use super::*;
277    use crate::config::OmegaConfig;
278
279    #[tokio::test]
280    async fn test_api_creation() {
281        let config = OmegaConfig::minimal();
282        let runtime = Arc::new(OmegaRuntime::new(config).await.unwrap());
283        let api = OmegaAPI::new(runtime);
284
285        // API should be created successfully
286        assert!(api.get_config().validate().is_ok());
287    }
288
289    #[tokio::test]
290    async fn test_api_requires_running_runtime() {
291        let config = OmegaConfig::minimal();
292        let runtime = Arc::new(OmegaRuntime::new(config).await.unwrap());
293        let api = OmegaAPI::new(runtime);
294
295        // Operations should fail when runtime is not running
296        let result = api.store_memory("test", MemoryTier::Working).await;
297        assert!(result.is_err());
298    }
299
300    #[tokio::test]
301    async fn test_create_intelligence() {
302        let config = OmegaConfig::minimal();
303        let runtime = Arc::new(OmegaRuntime::new(config).await.unwrap());
304        runtime.start().await.unwrap();
305
306        let api = OmegaAPI::new(runtime.clone());
307
308        let spec = IntelligenceSpec {
309            name: "TestIntelligence".to_string(),
310            description: "A test intelligence".to_string(),
311            initial_parameters: None,
312        };
313
314        let intelligence = api.create_intelligence(spec).await.unwrap();
315        assert_eq!(intelligence.name, "TestIntelligence");
316        assert_eq!(intelligence.generation, 0);
317    }
318
319    #[tokio::test]
320    async fn test_get_metrics() {
321        let config = OmegaConfig::minimal();
322        let runtime = Arc::new(OmegaRuntime::new(config).await.unwrap());
323        runtime.start().await.unwrap();
324
325        let api = OmegaAPI::new(runtime.clone());
326
327        let metrics = api.get_metrics().await.unwrap();
328        assert_eq!(metrics.state, "Running");
329    }
330}