omni_director/providers/
context.rs

1//! # Provider Context
2//!
3//! Execution context for providers, providing access to system services.
4
5use std::collections::HashMap;
6use serde_json::Value;
7use async_trait::async_trait;
8
9/// Log levels for provider logging
10#[derive(Debug, Clone)]
11pub enum LogLevel {
12    Error,
13    Warn,
14    Info,
15    Debug,
16    Trace,
17}
18
19/// Provider execution context
20#[async_trait]
21pub trait ProviderContext: Send + Sync {
22    /// Log a message
23    async fn log(&self, level: LogLevel, message: &str);
24    
25    /// Get a configuration value
26    async fn get_config(&self, key: &str) -> Option<Value>;
27    
28    /// Set a configuration value
29    async fn set_config(&self, key: &str, value: Value) -> Result<(), Box<dyn std::error::Error + Send + Sync>>;
30    
31    /// Get system information
32    async fn get_system_info(&self) -> HashMap<String, Value>;
33    
34    /// Get provider-specific settings
35    async fn get_provider_settings(&self, provider: &str) -> HashMap<String, Value>;
36    
37    /// Store data in the context
38    async fn store_data(&self, key: &str, value: Value) -> Result<(), Box<dyn std::error::Error + Send + Sync>>;
39    
40    /// Retrieve data from the context
41    async fn get_data(&self, key: &str) -> Option<Value>;
42    
43    /// Call another provider/feature/operation
44    async fn call_operation(
45        &self,
46        provider: &str,
47        feature: &str,
48        operation: &str,
49        args: HashMap<String, Value>,
50    ) -> Result<Value, Box<dyn std::error::Error + Send + Sync>>;
51}
52
53/// Default implementation of provider context
54#[derive(Debug)]
55pub struct DefaultProviderContext {
56    config: tokio::sync::RwLock<HashMap<String, Value>>,
57    data: tokio::sync::RwLock<HashMap<String, Value>>,
58    provider_settings: HashMap<String, HashMap<String, Value>>,
59}
60
61impl DefaultProviderContext {
62    /// Create a new default provider context
63    pub fn new() -> Self {
64        Self {
65            config: tokio::sync::RwLock::new(HashMap::new()),
66            data: tokio::sync::RwLock::new(HashMap::new()),
67            provider_settings: HashMap::new(),
68        }
69    }
70    
71    /// Create with provider settings
72    pub fn with_provider_settings(provider_settings: HashMap<String, HashMap<String, Value>>) -> Self {
73        Self {
74            config: tokio::sync::RwLock::new(HashMap::new()),
75            data: tokio::sync::RwLock::new(HashMap::new()),
76            provider_settings,
77        }
78    }
79}
80
81#[async_trait]
82impl ProviderContext for DefaultProviderContext {
83    async fn log(&self, level: LogLevel, message: &str) {
84        let level_str = match level {
85            LogLevel::Error => "ERROR",
86            LogLevel::Warn => "WARN",
87            LogLevel::Info => "INFO",
88            LogLevel::Debug => "DEBUG",
89            LogLevel::Trace => "TRACE",
90        };
91        
92        println!("[{}] {}", level_str, message);
93    }
94    
95    async fn get_config(&self, key: &str) -> Option<Value> {
96        let config = self.config.read().await;
97        config.get(key).cloned()
98    }
99    
100    async fn set_config(&self, key: &str, value: Value) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
101        let mut config = self.config.write().await;
102        config.insert(key.to_string(), value);
103        Ok(())
104    }
105    
106    async fn get_system_info(&self) -> HashMap<String, Value> {
107        let mut info = HashMap::new();
108        info.insert("hostname".to_string(), Value::String(whoami::hostname()));
109        info.insert("username".to_string(), Value::String(whoami::username()));
110        info.insert("platform".to_string(), Value::String(std::env::consts::OS.to_string()));
111        info.insert("arch".to_string(), Value::String(std::env::consts::ARCH.to_string()));
112        info
113    }
114    
115    async fn get_provider_settings(&self, provider: &str) -> HashMap<String, Value> {
116        self.provider_settings.get(provider).cloned().unwrap_or_default()
117    }
118    
119    async fn store_data(&self, key: &str, value: Value) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
120        let mut data = self.data.write().await;
121        data.insert(key.to_string(), value);
122        Ok(())
123    }
124    
125    async fn get_data(&self, key: &str) -> Option<Value> {
126        let data = self.data.read().await;
127        data.get(key).cloned()
128    }
129    
130    async fn call_operation(
131        &self,
132        provider: &str,
133        feature: &str,
134        operation: &str,
135        args: HashMap<String, Value>,
136    ) -> Result<Value, Box<dyn std::error::Error + Send + Sync>> {
137        // This would be implemented to route to the actual provider system
138        // For now, return a placeholder
139        Err(format!(
140            "Cross-provider calls not yet implemented: {}/{}/{}",
141            provider, feature, operation
142        ).into())
143    }
144}