rustchain/core/
mod.rs

1use crate::assert_invariant;
2#[cfg(feature = "rag")]
3use crate::rag::RagSystem;
4#[cfg(feature = "sandbox")]
5use crate::sandbox::EnhancedSandbox;
6use chrono::{DateTime, Utc};
7use serde::{Deserialize, Serialize};
8use sha2::{Digest, Sha256};
9use std::collections::HashMap;
10use std::sync::Arc;
11use std::time::Instant;
12use tokio::sync::RwLock;
13use uuid::Uuid;
14
15// Error handling
16pub mod error;
17pub mod error_formatting;
18pub use error::*;
19pub use error_formatting::*;
20
21// Mission system
22pub mod mission;
23pub use mission::*;
24
25// Executor system
26pub mod executor;
27pub use executor::*;
28
29// Enhanced audit system
30pub mod audit;
31pub use audit::*;
32
33// Memory system
34pub mod memory;
35pub use memory::*;
36
37// Agent system
38pub mod agent;
39pub use agent::*;
40
41// Chain system
42pub mod chain;
43pub use chain::*;
44
45// LLM system
46pub mod llm;
47pub use llm::*;
48
49// Tools system
50pub mod tools;
51pub use tools::*;
52
53// Web search tools
54#[cfg(feature = "tools")]
55pub mod web_search_tools;
56
57// Document loaders
58#[cfg(feature = "tools")]
59pub mod document_loaders;
60#[cfg(feature = "tools")]
61pub use document_loaders::*;
62
63// Vector stores
64#[cfg(feature = "rag")]
65pub mod pinecone_vector_store;
66
67#[cfg(feature = "rag")]
68pub mod chroma_vector_store;
69
70// Code interpreters
71#[cfg(feature = "tools")]
72pub mod python_interpreter;
73#[cfg(feature = "tools")]
74pub use python_interpreter::*;
75
76// Developer toolkits
77#[cfg(feature = "tools")]
78pub mod github_toolkit;
79
80// Plugin system for enterprise features
81pub mod plugin;
82pub use plugin::*;
83
84// Feature detection and boundary enforcement
85pub mod features;
86pub use features::*;
87
88/// Central runtime context that holds all system state
89#[derive(Clone)]
90pub struct RuntimeContext {
91    pub config: Arc<RwLock<Config>>,
92    pub audit: Arc<AuditSink>,
93    pub tool_registry: Arc<RwLock<ToolRegistry>>,
94    pub model_manager: Option<Arc<ModelManager>>,
95    pub sandbox: Arc<AgentSandbox>,
96    pub policy_engine: Arc<PolicyEngine>,
97    pub perf_collector: Arc<RwLock<PerfCollector>>,
98    pub plugin_manager: Arc<RwLock<PluginManager>>,
99    pub feature_detector: Arc<FeatureDetector>,
100    #[cfg(feature = "rag")]
101    pub rag_system: Option<Arc<RwLock<RagSystem>>>,
102    #[cfg(feature = "sandbox")]
103    pub enhanced_sandbox: Option<Arc<EnhancedSandbox>>,
104}
105
106impl RuntimeContext {
107    pub fn new() -> Self {
108        assert_invariant!(true, "RuntimeContext created", Some("core"));
109
110        Self {
111            config: Arc::new(RwLock::new(Config::default())),
112            audit: Arc::new(AuditSink::new()),
113            tool_registry: Arc::new(RwLock::new(ToolRegistry::new())),
114            model_manager: None,
115            sandbox: Arc::new(AgentSandbox::new()),
116            policy_engine: Arc::new(PolicyEngine::new()),
117            perf_collector: Arc::new(RwLock::new(PerfCollector::new())),
118            plugin_manager: Arc::new(RwLock::new(PluginManager::new())),
119            feature_detector: Arc::new(FeatureDetector::new()),
120            #[cfg(feature = "rag")]
121            rag_system: None,
122            #[cfg(feature = "sandbox")]
123            enhanced_sandbox: None,
124        }
125    }
126
127    pub async fn audit_action(&self, agent_id: &str, action: &str, outcome: &str) {
128        let entry = AuditEntry {
129            id: Uuid::new_v4(),
130            timestamp: Utc::now(),
131            actor: agent_id.to_string(),
132            action: action.to_string(),
133            outcome: outcome.to_string(),
134            reason: None,
135        };
136        self.audit.log(entry).await;
137    }
138
139    /// Check if an enterprise feature is available through plugins
140    pub async fn has_enterprise_feature(&self, feature: &str) -> bool {
141        if cfg!(feature = "enterprise") {
142            self.plugin_manager.read().await.has_feature(feature)
143        } else {
144            false
145        }
146    }
147
148    /// Get list of all available enterprise features
149    pub async fn get_enterprise_features(&self) -> Vec<String> {
150        if cfg!(feature = "enterprise") {
151            self.plugin_manager.read().await.enabled_features()
152        } else {
153            vec![]
154        }
155    }
156
157    /// Get list of all available core features
158    pub async fn get_available_features(&self) -> Vec<String> {
159        let mut features = Vec::new();
160        
161        // Core features that are always available
162        features.push("mission_execution".to_string());
163        features.push("safety_validation".to_string());
164        features.push("audit_logging".to_string());
165        features.push("policy_engine".to_string());
166        
167        // Feature-gated components
168        #[cfg(feature = "llm")]
169        features.push("llm_integration".to_string());
170        
171        #[cfg(feature = "tools")]
172        features.push("tool_system".to_string());
173        
174        #[cfg(feature = "rag")]
175        features.push("rag_system".to_string());
176        
177        #[cfg(feature = "sandbox")]
178        features.push("sandbox".to_string());
179        
180        #[cfg(feature = "server")]
181        features.push("api_server".to_string());
182        
183        #[cfg(feature = "compliance")]
184        features.push("compliance_checking".to_string());
185        
186        features
187    }
188
189    /// Load enterprise plugins (not available in community edition)
190    pub async fn load_enterprise_plugins(&self) -> crate::core::error::Result<()> {
191        // Community edition: No enterprise plugins available
192        Ok(())
193    }
194
195    /// Enhanced feature detection with detailed status
196    pub async fn check_feature_status(&self, feature: &str) -> FeatureStatus {
197        self.feature_detector.is_feature_available(self, feature).await
198    }
199
200    /// Require a feature or return detailed error
201    pub async fn require_feature(&self, feature: &str) -> crate::core::error::Result<()> {
202        self.feature_detector.require_feature(self, feature).await
203    }
204
205    /// Get comprehensive feature summary for this installation
206    pub async fn get_feature_summary(&self) -> FeatureSummary {
207        self.feature_detector.get_feature_summary(self).await
208    }
209
210    /// Get status for all features in a category
211    pub async fn get_category_status(&self, category: &str) -> Vec<FeatureStatus> {
212        self.feature_detector.get_category_status(self, category).await
213    }
214
215    /// Check if running enterprise edition with full features
216    pub async fn is_enterprise_complete(&self) -> bool {
217        self.get_feature_summary().await.is_enterprise_complete()
218    }
219}
220
221#[derive(Clone, Debug, Serialize, Deserialize)]
222pub struct Config {
223    pub mission_timeout_seconds: u64,
224    pub max_parallel_steps: usize,
225    pub audit_enabled: bool,
226    pub network_policy: NetworkPolicy,
227    pub agent_id: String,
228    pub max_tool_calls: usize,
229}
230
231impl Default for Config {
232    fn default() -> Self {
233        Self {
234            mission_timeout_seconds: 300,
235            max_parallel_steps: 4,
236            audit_enabled: true,
237            network_policy: NetworkPolicy::Offline,
238            agent_id: "rustchain-agent".to_string(),
239            max_tool_calls: 100,
240        }
241    }
242}
243
244#[derive(Clone, Debug, Serialize, Deserialize)]
245pub enum NetworkPolicy {
246    Offline,
247    AllowList(Vec<String>),
248}
249
250/// Enhanced audit sink with cryptographic chain integrity
251pub struct AuditSink {
252    entries: Arc<RwLock<Vec<AuditEntry>>>,
253}
254
255impl AuditSink {
256    pub fn new() -> Self {
257        Self {
258            entries: Arc::new(RwLock::new(Vec::new())),
259        }
260    }
261
262    pub async fn log(&self, entry: AuditEntry) {
263        self.entries.write().await.push(entry);
264    }
265
266    pub async fn get_chain_hash(&self) -> String {
267        let entries = self.entries.read().await;
268        if entries.is_empty() {
269            return "genesis".to_string();
270        }
271
272        let mut hasher = Sha256::new();
273        for entry in entries.iter() {
274            hasher.update(
275                format!(
276                    "{}{}{}{}",
277                    entry.timestamp.to_rfc3339(),
278                    entry.actor,
279                    entry.action,
280                    entry.outcome
281                )
282                .as_bytes(),
283            );
284        }
285        format!("{:x}", hasher.finalize())
286    }
287}
288
289#[derive(Clone, Debug, Serialize, Deserialize)]
290pub struct AuditEntry {
291    pub id: Uuid,
292    pub timestamp: DateTime<Utc>,
293    pub actor: String,
294    pub action: String,
295    pub outcome: String,
296    pub reason: Option<String>,
297}
298
299pub struct ToolRegistry {
300    tools: HashMap<String, Box<dyn Tool + Send + Sync>>,
301}
302
303impl ToolRegistry {
304    pub fn new() -> Self {
305        Self {
306            tools: HashMap::new(),
307        }
308    }
309
310    pub fn register(&mut self, name: String, tool: Box<dyn Tool + Send + Sync>) {
311        self.tools.insert(name, tool);
312    }
313
314    pub fn get(&self, name: &str) -> Option<&Box<dyn Tool + Send + Sync>> {
315        self.tools.get(name)
316    }
317}
318
319pub trait Tool {
320    fn name(&self) -> &str;
321    fn invoke(&self, args: serde_json::Value) -> anyhow::Result<serde_json::Value>;
322}
323
324/// Performance metrics collection
325#[derive(Debug, Clone)]
326pub struct PerfMetric {
327    pub name: String,
328    pub duration_ms: u128,
329}
330
331pub struct PerfCollector {
332    active: HashMap<String, Instant>,
333    pub completed: Vec<PerfMetric>,
334}
335
336impl PerfCollector {
337    pub fn new() -> Self {
338        Self {
339            active: HashMap::new(),
340            completed: vec![],
341        }
342    }
343
344    pub fn start(&mut self, name: &str) {
345        self.active.insert(name.to_string(), Instant::now());
346    }
347
348    pub fn end(&mut self, name: &str) {
349        if let Some(start) = self.active.remove(name) {
350            let duration = start.elapsed().as_millis();
351            self.completed.push(PerfMetric {
352                name: name.to_string(),
353                duration_ms: duration,
354            });
355        }
356    }
357
358    pub fn summary(&self) -> String {
359        self.completed
360            .iter()
361            .map(|m| format!("{}: {}ms", m.name, m.duration_ms))
362            .collect::<Vec<_>>()
363            .join("\n")
364    }
365}
366
367pub struct ModelManager {
368    // Will be implemented in Gate 6
369    #[cfg(feature = "llm")]
370    llm_manager: Option<crate::llm::LLMManager>,
371}
372
373impl ModelManager {
374    pub fn new() -> Self {
375        Self {
376            #[cfg(feature = "llm")]
377            llm_manager: None,
378        }
379    }
380
381    #[cfg(feature = "llm")]
382    pub fn with_llm_manager(mut self, manager: crate::llm::LLMManager) -> Self {
383        self.llm_manager = Some(manager);
384        self
385    }
386
387    #[cfg(feature = "llm")]
388    pub async fn complete(
389        &self,
390        request: crate::llm::LLMRequest,
391        provider: Option<&str>,
392    ) -> anyhow::Result<crate::llm::LLMResponse> {
393        if let Some(ref manager) = self.llm_manager {
394            manager.complete(request, provider).await
395        } else {
396            Err(anyhow::anyhow!("LLM manager not initialized"))
397        }
398    }
399}
400
401pub struct AgentSandbox {
402    #[allow(dead_code)]
403    allowed_paths: Vec<std::path::PathBuf>,
404    #[allow(dead_code)]
405    timeout_seconds: u64,
406}
407
408impl AgentSandbox {
409    pub fn new() -> Self {
410        // Safe default path handling - fallback to current directory or root
411        let current_dir = std::env::current_dir()
412            .unwrap_or_else(|_| std::path::PathBuf::from("."));
413            
414        Self {
415            allowed_paths: vec![current_dir],
416            timeout_seconds: 30,
417        }
418    }
419
420    pub fn execute(&self, code: &str) -> std::result::Result<String, String> {
421        // Placeholder sandbox execution
422        Ok(format!("Executed in sandbox: {}", code))
423    }
424}
425
426pub struct PolicyEngine {
427    policies: Vec<String>,
428}
429
430impl PolicyEngine {
431    pub fn new() -> Self {
432        Self {
433            policies: Vec::new(),
434        }
435    }
436
437    pub fn validate(&self, action: &str) -> bool {
438        // Basic policy validation - will be replaced by enhanced engine
439        !self.policies.iter().any(|p| action.contains(p))
440    }
441
442    pub fn add_policy(&mut self, policy: String) {
443        self.policies.push(policy);
444    }
445}