omni_director/providers/
context.rs1use std::collections::HashMap;
6use serde_json::Value;
7use async_trait::async_trait;
8
9#[derive(Debug, Clone)]
11pub enum LogLevel {
12 Error,
13 Warn,
14 Info,
15 Debug,
16 Trace,
17}
18
19#[async_trait]
21pub trait ProviderContext: Send + Sync {
22 async fn log(&self, level: LogLevel, message: &str);
24
25 async fn get_config(&self, key: &str) -> Option<Value>;
27
28 async fn set_config(&self, key: &str, value: Value) -> Result<(), Box<dyn std::error::Error + Send + Sync>>;
30
31 async fn get_system_info(&self) -> HashMap<String, Value>;
33
34 async fn get_provider_settings(&self, provider: &str) -> HashMap<String, Value>;
36
37 async fn store_data(&self, key: &str, value: Value) -> Result<(), Box<dyn std::error::Error + Send + Sync>>;
39
40 async fn get_data(&self, key: &str) -> Option<Value>;
42
43 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#[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 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 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 Err(format!(
140 "Cross-provider calls not yet implemented: {}/{}/{}",
141 provider, feature, operation
142 ).into())
143 }
144}