Skip to main content

casial_core/
coordination.rs

1//! # Coordination Module
2//!
3//! Handles the coordination of different AI perspectives and context injection strategies.
4//! Implements the consciousness-computation substrate for managing multiple viewpoints.
5
6use crate::{CasialError, PerceptionId};
7use ahash::AHashMap;
8use anyhow::Result;
9use serde::{Deserialize, Serialize};
10
11/// Coordination metrics for performance monitoring
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct CoordinationMetrics {
14    pub perception_lock_latency_ms: f64,
15    pub paradox_resolution_time_ms: f64,
16    pub context_composition_time_ms: f64,
17    pub total_coordination_time_ms: f64,
18    pub memory_usage_bytes: usize,
19}
20
21/// Coordination strategy for different scenarios
22#[derive(Debug, Clone, Serialize, Deserialize)]
23pub enum CoordinationStrategy {
24    /// Fast coordination with minimal paradox handling
25    Rapid,
26    /// Balanced approach with moderate paradox resolution
27    Balanced,
28    /// Comprehensive coordination with full paradox synthesis
29    Comprehensive,
30    /// Custom strategy with specific parameters
31    Custom {
32        paradox_timeout_ms: u64,
33        perception_lock_attempts: u32,
34        synthesis_depth: u8,
35    },
36}
37
38impl Default for CoordinationStrategy {
39    fn default() -> Self {
40        Self::Balanced
41    }
42}
43
44/// Configuration for coordination behavior
45#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct CoordinationConfig {
47    pub strategy: CoordinationStrategy,
48    pub enable_perception_locking: bool,
49    pub enable_paradox_detection: bool,
50    pub enable_synthesis: bool,
51    pub max_coordination_time_ms: u64,
52    pub memory_limit_bytes: Option<usize>,
53}
54
55impl Default for CoordinationConfig {
56    fn default() -> Self {
57        Self {
58            strategy: CoordinationStrategy::default(),
59            enable_perception_locking: true,
60            enable_paradox_detection: true,
61            enable_synthesis: true,
62            max_coordination_time_ms: 5000, // 5 second timeout
63            memory_limit_bytes: Some(100 * 1024 * 1024), // 100MB limit
64        }
65    }
66}
67
68/// State of a coordination session
69#[derive(Debug, Clone)]
70pub struct CoordinationSession {
71    pub id: uuid::Uuid,
72    pub active_perceptions: Vec<PerceptionId>,
73    pub locked_perceptions: Vec<PerceptionId>,
74    pub detected_paradoxes: Vec<uuid::Uuid>,
75    pub start_time: std::time::Instant,
76    pub config: CoordinationConfig,
77    pub metrics: CoordinationMetrics,
78}
79
80impl CoordinationSession {
81    /// Create a new coordination session
82    pub fn new(config: CoordinationConfig) -> Self {
83        Self {
84            id: uuid::Uuid::new_v4(),
85            active_perceptions: Vec::new(),
86            locked_perceptions: Vec::new(),
87            detected_paradoxes: Vec::new(),
88            start_time: std::time::Instant::now(),
89            config,
90            metrics: CoordinationMetrics {
91                perception_lock_latency_ms: 0.0,
92                paradox_resolution_time_ms: 0.0,
93                context_composition_time_ms: 0.0,
94                total_coordination_time_ms: 0.0,
95                memory_usage_bytes: 0,
96            },
97        }
98    }
99
100    /// Add a perception to this coordination session
101    pub fn add_perception(&mut self, perception_id: PerceptionId) -> Result<()> {
102        if !self.active_perceptions.contains(&perception_id) {
103            self.active_perceptions.push(perception_id);
104        }
105        Ok(())
106    }
107
108    /// Attempt to lock a perception for exclusive coordination
109    pub fn lock_perception(&mut self, perception_id: PerceptionId) -> Result<bool> {
110        if !self.config.enable_perception_locking {
111            return Ok(false);
112        }
113
114        let lock_start = std::time::Instant::now();
115
116        // Simulate perception lock attempt
117        // In a real implementation, this would coordinate with other sessions
118        let lock_acquired = !self.locked_perceptions.contains(&perception_id);
119
120        if lock_acquired {
121            self.locked_perceptions.push(perception_id);
122        }
123
124        self.metrics.perception_lock_latency_ms = lock_start.elapsed().as_secs_f64() * 1000.0;
125
126        Ok(lock_acquired)
127    }
128
129    /// Release a perception lock
130    pub fn unlock_perception(&mut self, perception_id: PerceptionId) -> Result<()> {
131        self.locked_perceptions.retain(|&id| id != perception_id);
132        Ok(())
133    }
134
135    /// Check if session has timed out
136    pub fn is_timed_out(&self) -> bool {
137        self.start_time.elapsed().as_millis() > self.config.max_coordination_time_ms as u128
138    }
139
140    /// Finalize the session and calculate final metrics
141    pub fn finalize(&mut self) {
142        self.metrics.total_coordination_time_ms = self.start_time.elapsed().as_secs_f64() * 1000.0;
143
144        // Estimate memory usage (simplified)
145        self.metrics.memory_usage_bytes = self.active_perceptions.len()
146            * std::mem::size_of::<PerceptionId>()
147            + self.locked_perceptions.len() * std::mem::size_of::<PerceptionId>()
148            + self.detected_paradoxes.len() * std::mem::size_of::<uuid::Uuid>();
149    }
150}
151
152/// Coordination pool for managing multiple concurrent sessions
153pub struct CoordinationPool {
154    active_sessions: AHashMap<uuid::Uuid, CoordinationSession>,
155    global_perception_locks: AHashMap<PerceptionId, uuid::Uuid>,
156    max_concurrent_sessions: usize,
157}
158
159impl CoordinationPool {
160    /// Create a new coordination pool
161    pub fn new(max_concurrent_sessions: usize) -> Self {
162        Self {
163            active_sessions: AHashMap::new(),
164            global_perception_locks: AHashMap::new(),
165            max_concurrent_sessions,
166        }
167    }
168
169    /// Start a new coordination session
170    pub fn start_session(&mut self, config: CoordinationConfig) -> Result<uuid::Uuid> {
171        if self.active_sessions.len() >= self.max_concurrent_sessions {
172            return Err(CasialError::CoordinationFailure(
173                "Maximum concurrent sessions reached".to_string(),
174            )
175            .into());
176        }
177
178        let session = CoordinationSession::new(config);
179        let session_id = session.id;
180
181        self.active_sessions.insert(session_id, session);
182
183        Ok(session_id)
184    }
185
186    /// End a coordination session
187    pub fn end_session(&mut self, session_id: uuid::Uuid) -> Result<CoordinationMetrics> {
188        if let Some(mut session) = self.active_sessions.remove(&session_id) {
189            // Release all perception locks held by this session
190            for perception_id in &session.locked_perceptions {
191                self.global_perception_locks.remove(perception_id);
192            }
193
194            session.finalize();
195            Ok(session.metrics)
196        } else {
197            Err(
198                CasialError::CoordinationFailure(format!("Session {} not found", session_id))
199                    .into(),
200            )
201        }
202    }
203
204    /// Get session statistics
205    pub fn get_statistics(&self) -> CoordinationPoolStats {
206        let active_session_count = self.active_sessions.len();
207        let total_locked_perceptions = self.global_perception_locks.len();
208
209        let avg_session_time = if active_session_count > 0 {
210            self.active_sessions
211                .values()
212                .map(|s| s.start_time.elapsed().as_secs_f64() * 1000.0)
213                .sum::<f64>()
214                / active_session_count as f64
215        } else {
216            0.0
217        };
218
219        CoordinationPoolStats {
220            active_sessions: active_session_count,
221            max_sessions: self.max_concurrent_sessions,
222            locked_perceptions: total_locked_perceptions,
223            average_session_duration_ms: avg_session_time,
224        }
225    }
226
227    /// Cleanup timed-out sessions
228    pub fn cleanup_timed_out_sessions(&mut self) -> usize {
229        let timed_out_sessions: Vec<uuid::Uuid> = self
230            .active_sessions
231            .iter()
232            .filter(|(_, session)| session.is_timed_out())
233            .map(|(id, _)| *id)
234            .collect();
235
236        let count = timed_out_sessions.len();
237
238        for session_id in timed_out_sessions {
239            let _ = self.end_session(session_id);
240        }
241
242        count
243    }
244}
245
246/// Statistics for coordination pool monitoring
247#[derive(Debug, Clone, Serialize, Deserialize)]
248pub struct CoordinationPoolStats {
249    pub active_sessions: usize,
250    pub max_sessions: usize,
251    pub locked_perceptions: usize,
252    pub average_session_duration_ms: f64,
253}
254
255#[cfg(test)]
256mod tests {
257    use super::*;
258
259    #[test]
260    fn test_coordination_session_creation() {
261        let config = CoordinationConfig::default();
262        let session = CoordinationSession::new(config);
263        assert_eq!(session.active_perceptions.len(), 0);
264        assert_eq!(session.locked_perceptions.len(), 0);
265    }
266
267    #[test]
268    fn test_coordination_pool() {
269        let mut pool = CoordinationPool::new(10);
270        let config = CoordinationConfig::default();
271
272        let session_id = pool.start_session(config).unwrap();
273        assert_eq!(pool.active_sessions.len(), 1);
274
275        let metrics = pool.end_session(session_id).unwrap();
276        assert_eq!(pool.active_sessions.len(), 0);
277        assert!(metrics.total_coordination_time_ms >= 0.0);
278    }
279}