omni_director/providers/
loader.rs

1//! # Provider Loader
2//!
3//! Handles dynamic loading of providers from shared libraries.
4
5use super::{Provider, ProviderError, ProviderResult, ProviderMetadata, FeatureMetadata, ProviderContext, FeatureInterface, FeatureOperation, ParameterDefinition, EventRegistry};
6use std::collections::HashMap;
7use std::path::Path;
8use std::sync::Arc;
9use libloading::{Library, Symbol};
10use tokio::sync::RwLock;
11
12/// Provider loader manages dynamic loading of provider libraries
13pub struct ProviderLoader {
14    /// Loaded libraries (kept alive)
15    libraries: RwLock<Vec<Library>>,
16}
17
18/// Provider factory function signature
19type ProviderFactoryFn = unsafe extern "C" fn() -> *mut std::ffi::c_void;
20
21/// Provider metadata function signature  
22type ProviderMetadataFn = unsafe extern "C" fn() -> *const std::os::raw::c_char;
23
24impl ProviderLoader {
25    /// Create a new provider loader
26    pub fn new() -> Self {
27        Self {
28            libraries: RwLock::new(Vec::new()),
29        }
30    }
31    
32    /// Load providers from a directory
33    pub async fn load_from_directory<P: AsRef<Path>>(
34        &self,
35        directory: P,
36        context: Arc<dyn ProviderContext>,
37    ) -> ProviderResult<Vec<(Arc<dyn Provider>, ProviderMetadata)>> {
38        self.load_from_directory_with_registry(directory, context, None).await
39    }
40    
41    /// Load providers from a directory with optional event registry
42    pub async fn load_from_directory_with_registry<P: AsRef<Path>>(
43        &self,
44        directory: P,
45        context: Arc<dyn ProviderContext>,
46        event_registry: Option<Arc<EventRegistry>>,
47    ) -> ProviderResult<Vec<(Arc<dyn Provider>, ProviderMetadata)>> {
48        let directory = directory.as_ref();
49        
50        if !directory.exists() {
51            tokio::fs::create_dir_all(directory).await?;
52            return Ok(Vec::new());
53        }
54        
55        let mut providers = Vec::new();
56        let mut read_dir = tokio::fs::read_dir(directory).await?;
57        
58        while let Some(entry) = read_dir.next_entry().await? {
59            let path = entry.path();
60            
61            // Check for provider libraries
62            if self.is_provider_library(&path) {
63                match self.load_provider_from_file_with_registry(&path, Arc::clone(&context), event_registry.clone()).await {
64                    Ok((provider, metadata)) => {
65                        providers.push((provider, metadata));
66                    }
67                    Err(e) => {
68                        eprintln!("Failed to load provider from {:?}: {}", path, e);
69                    }
70                }
71            }
72        }
73        
74        Ok(providers)
75    }
76    
77    /// Load feature interfaces from a directory (does not register as callable providers)
78    pub async fn load_features_from_directory<P: AsRef<Path>>(
79        &self,
80        directory: P,
81    ) -> ProviderResult<Vec<FeatureInterface>> {
82        let directory = directory.as_ref();
83        
84        if !directory.exists() {
85            tokio::fs::create_dir_all(directory).await?;
86            return Ok(Vec::new());
87        }
88        
89        let mut features = Vec::new();
90        let mut read_dir = tokio::fs::read_dir(directory).await?;
91        
92        while let Some(entry) = read_dir.next_entry().await? {
93            let path = entry.path();
94            
95            // Check for feature libraries
96            if self.is_provider_library(&path) {
97                match self.load_feature_interface_from_file(&path).await {
98                    Ok(feature) => {
99                        features.push(feature);
100                    }
101                    Err(e) => {
102                        eprintln!("Failed to load feature interface from {:?}: {}", path, e);
103                    }
104                }
105            }
106        }
107        
108        Ok(features)
109    }
110    
111    /// Check if a file is a provider library
112    fn is_provider_library(&self, path: &Path) -> bool {
113        if let Some(extension) = path.extension().and_then(|s| s.to_str()) {
114            match extension {
115                #[cfg(target_os = "windows")]
116                "dll" => true,
117                #[cfg(target_os = "linux")]
118                "so" => true,
119                #[cfg(target_os = "macos")]
120                "dylib" => true,
121                _ => false,
122            }
123        } else {
124            false
125        }
126    }
127    
128    /// Load a provider from a specific file
129    pub async fn load_provider_from_file<P: AsRef<Path>>(
130        &self,
131        library_path: P,
132        context: Arc<dyn ProviderContext>,
133    ) -> ProviderResult<(Arc<dyn Provider>, ProviderMetadata)> {
134        self.load_provider_from_file_with_registry(library_path, context, None).await
135    }
136    
137    /// Load a provider from a specific file with optional event registry
138    pub async fn load_provider_from_file_with_registry<P: AsRef<Path>>(
139        &self,
140        library_path: P,
141        context: Arc<dyn ProviderContext>,
142        event_registry: Option<Arc<EventRegistry>>,
143    ) -> ProviderResult<(Arc<dyn Provider>, ProviderMetadata)> {
144        let library_path = library_path.as_ref();
145        
146        println!("Loading provider from file: {:?}", library_path);
147        
148        // Load the library
149        let lib = unsafe {
150            Library::new(library_path).map_err(|e| {
151                ProviderError::LoadingFailed(format!(
152                    "Failed to load library {:?}: {}",
153                    library_path, e
154                ))
155            })?
156        };
157        
158        println!("Successfully loaded library: {:?}", library_path);
159        
160        // Determine if this is a legacy CPI or new-style provider
161        let provider_type = self.detect_provider_type(&lib)?;
162        
163        match provider_type {
164            ProviderType::LegacyCpi => {
165                self.load_legacy_cpi(&lib, library_path, context, event_registry).await
166            }
167            ProviderType::ModernProvider => {
168                self.load_modern_provider(&lib, library_path, context, event_registry).await
169            }
170            ProviderType::Feature => {
171                // Features are interface definitions, not callable providers
172                Err(ProviderError::LoadingFailed(
173                    "Feature interfaces should be loaded separately, not as providers".to_string()
174                ))
175            }
176        }
177    }
178    
179    /// Detect what type of provider this library contains
180    fn detect_provider_type(&self, lib: &Library) -> ProviderResult<ProviderType> {
181        // Check for modern provider interface
182        if unsafe { lib.get::<Symbol<ProviderFactoryFn>>(b"create_provider").is_ok() } {
183            return Ok(ProviderType::ModernProvider);
184        }
185        
186        // Check for legacy CPI interface  
187        if unsafe { lib.get::<Symbol<ProviderFactoryFn>>(b"create_plugin").is_ok() } {
188            return Ok(ProviderType::LegacyCpi);
189        }
190        
191        // Check for feature interface
192        if unsafe { lib.get::<Symbol<ProviderMetadataFn>>(b"get_feature_name").is_ok() } {
193            return Ok(ProviderType::Feature);
194        }
195        
196        Err(ProviderError::LoadingFailed(
197            "Library does not contain recognized provider interface".to_string()
198        ))
199    }
200    
201    /// Load a feature interface from a specific file
202    pub async fn load_feature_interface_from_file<P: AsRef<Path>>(
203        &self,
204        library_path: P,
205    ) -> ProviderResult<FeatureInterface> {
206        let library_path = library_path.as_ref();
207        
208        println!("Loading feature interface from file: {:?}", library_path);
209        
210        // Load the library
211        let lib = unsafe {
212            Library::new(library_path).map_err(|e| {
213                ProviderError::LoadingFailed(format!(
214                    "Failed to load library {:?}: {}",
215                    library_path, e
216                ))
217            })?
218        };
219        
220        // Verify it's a feature interface
221        let provider_type = self.detect_provider_type(&lib)?;
222        if !matches!(provider_type, ProviderType::Feature) {
223            return Err(ProviderError::LoadingFailed(
224                "Library is not a feature interface".to_string()
225            ));
226        }
227        
228        // Get feature name
229        let get_feature_name: Symbol<unsafe extern "C" fn() -> *const std::os::raw::c_char> = unsafe {
230            lib.get(b"get_feature_name").map_err(|e| {
231                ProviderError::LoadingFailed(format!(
232                    "Failed to find get_feature_name function: {}",
233                    e
234                ))
235            })?
236        };
237        
238        let name_ptr = unsafe { get_feature_name() };
239        let feature_name = if !name_ptr.is_null() {
240            unsafe { 
241                std::ffi::CStr::from_ptr(name_ptr)
242                    .to_str()
243                    .unwrap_or("unknown")
244                    .to_string()
245            }
246        } else {
247            "unknown".to_string()
248        };
249        
250        // FULL PRODUCTION IMPLEMENTATION - Extract operations from the feature library
251        
252        // Get feature metadata to extract operations
253        let get_feature_metadata: Symbol<unsafe extern "C" fn() -> *const std::os::raw::c_char> = unsafe {
254            lib.get(b"get_feature_metadata").map_err(|e| {
255                ProviderError::LoadingFailed(format!(
256                    "Failed to find get_feature_metadata function: {}",
257                    e
258                ))
259            })?
260        };
261        
262        let metadata_ptr = unsafe { get_feature_metadata() };
263        let metadata_str = if !metadata_ptr.is_null() {
264            unsafe { std::ffi::CStr::from_ptr(metadata_ptr).to_str().unwrap_or("{}") }
265        } else {
266            "{}"
267        };
268        
269        let metadata_json: serde_json::Value = serde_json::from_str(metadata_str)
270            .map_err(|e| ProviderError::LoadingFailed(format!("Invalid feature metadata JSON: {}", e)))?;
271        
272        // Extract operations from metadata with FULL specifications
273        let operations: Vec<FeatureOperation> = metadata_json.get("operations")
274            .and_then(|v| v.as_array())
275            .map(|arr| {
276                arr.iter()
277                    .filter_map(|v| v.as_str())
278                    .map(|op_name| {
279                        // Try to load operation specification from the feature library
280                        let spec_function_name = format!("{}_operation_spec", op_name);
281                        let spec_function_bytes = spec_function_name.as_bytes();
282                        
283                        // Attempt to get the operation spec function
284                        let operation_spec: Option<serde_json::Value> = unsafe {
285                            lib.get::<unsafe extern "C" fn() -> *const std::os::raw::c_char>(spec_function_bytes)
286                                .ok()
287                                .and_then(|get_spec| {
288                                    let spec_ptr = get_spec();
289                                    if !spec_ptr.is_null() {
290                                        std::ffi::CStr::from_ptr(spec_ptr)
291                                            .to_str()
292                                            .ok()
293                                            .and_then(|spec_str| serde_json::from_str::<serde_json::Value>(spec_str).ok())
294                                    } else {
295                                        None
296                                    }
297                                })
298                        };
299                        
300                        // Extract operation details from spec or use defaults
301                        let (description, parameters, returns) = if let Some(spec) = operation_spec {
302                            let desc = spec.get("description")
303                                .and_then(|v| v.as_str())
304                                .map(|s| s.to_string())
305                                .unwrap_or_else(|| format!("{} operation", op_name));
306                            
307                            let params = spec.get("parameters")
308                                .and_then(|v| v.as_object())
309                                .map(|obj| {
310                                    obj.iter().map(|(name, param_spec)| {
311                                        let param_def = ParameterDefinition {
312                                            name: name.clone(),
313                                            param_type: param_spec.get("type")
314                                                .and_then(|v| v.as_str())
315                                                .unwrap_or("string")
316                                                .to_string(),
317                                            required: param_spec.get("required")
318                                                .and_then(|v| v.as_bool())
319                                                .unwrap_or(false),
320                                            description: param_spec.get("description")
321                                                .and_then(|v| v.as_str())
322                                                .map(|s| s.to_string()),
323                                        };
324                                        (name.clone(), param_def)
325                                    }).collect()
326                                })
327                                .unwrap_or_default();
328                            
329                            let ret_type = spec.get("returns")
330                                .and_then(|v| v.get("type"))
331                                .and_then(|v| v.as_str())
332                                .map(|s| s.to_string());
333                            
334                            (desc, params, ret_type)
335                        } else {
336                            // Fallback to basic operation definition
337                            (
338                                format!("{} operation", op_name),
339                                HashMap::new(),
340                                Some("Value".to_string())
341                            )
342                        };
343                        
344                        FeatureOperation {
345                            name: op_name.to_string(),
346                            description,
347                            parameters,
348                            returns,
349                        }
350                    })
351                    .collect()
352            })
353            .unwrap_or_default();
354        
355        if operations.is_empty() {
356            return Err(ProviderError::LoadingFailed(
357                format!("Feature '{}' has no operations defined", feature_name)
358            ));
359        }
360        
361        let feature_interface = FeatureInterface {
362            name: feature_name.clone(),
363            description: metadata_json.get("description")
364                .and_then(|v| v.as_str())
365                .map(|s| s.to_string())
366                .unwrap_or_else(|| format!("{} feature interface", feature_name)),
367            operations,
368        };
369        
370        println!("Successfully loaded feature interface: {}", feature_interface.name);
371        
372        Ok(feature_interface)
373    }
374    
375    /// Load a legacy CPI and wrap it as a provider
376    async fn load_legacy_cpi(
377        &self,
378        lib: &Library,
379        library_path: &Path,
380        context: Arc<dyn ProviderContext>,
381        event_registry: Option<Arc<EventRegistry>>,
382    ) -> ProviderResult<(Arc<dyn Provider>, ProviderMetadata)> {
383        println!("Detected legacy CPI plugin");
384        
385        // For now, create a wrapper that adapts the CPI to our provider interface
386        let provider = Arc::new(LegacyCpiAdapter::new(
387            library_path.to_string_lossy().to_string()
388        ));
389        
390        let metadata = ProviderMetadata {
391            name: "legacy-cpi".to_string(),
392            version: "1.0.0".to_string(),
393            description: "Legacy CPI adapter".to_string(),
394            author: None,
395            license: None,
396            features: vec![], // Features are loaded separately
397            settings_schema: None,
398            file_path: Some(library_path.to_string_lossy().to_string()),
399            metadata: None, // Legacy CPIs don't have raw metadata
400        };
401        
402        // Store the library to keep it alive
403        {
404            let mut libraries = self.libraries.write().await;
405            // We can't move lib here because we borrowed it, so we need to reload it
406            let owned_lib = unsafe { Library::new(library_path)? };
407            libraries.push(owned_lib);
408        }
409        
410        Ok((provider, metadata))
411    }
412    
413    /// Load a modern provider
414    async fn load_modern_provider(
415        &self,
416        lib: &Library,
417        library_path: &Path,
418        context: Arc<dyn ProviderContext>,
419        event_registry: Option<Arc<EventRegistry>>,
420    ) -> ProviderResult<(Arc<dyn Provider>, ProviderMetadata)> {
421        println!("Detected modern provider");
422        
423        // Get the create_provider function
424        let create_provider: Symbol<unsafe extern "C" fn() -> *mut std::ffi::c_void> = unsafe {
425            lib.get(b"create_provider").map_err(|e| {
426                ProviderError::LoadingFailed(format!(
427                    "Failed to find create_provider function: {}",
428                    e
429                ))
430            })?
431        };
432        
433        // Get the metadata function
434        let get_metadata: Symbol<unsafe extern "C" fn() -> *const std::os::raw::c_char> = unsafe {
435            lib.get(b"get_provider_metadata").map_err(|e| {
436                ProviderError::LoadingFailed(format!(
437                    "Failed to find get_provider_metadata function: {}",
438                    e
439                ))
440            })?
441        };
442        
443        // Get the initialize function
444        let initialize_provider: Symbol<unsafe extern "C" fn(*mut std::ffi::c_void, *mut std::ffi::c_void) -> bool> = unsafe {
445            lib.get(b"initialize_provider").map_err(|e| {
446                ProviderError::LoadingFailed(format!(
447                    "Failed to find initialize_provider function: {}",
448                    e
449                ))
450            })?
451        };
452        
453        // Create the provider instance
454        let provider_ptr = unsafe { create_provider() };
455        if provider_ptr.is_null() {
456            return Err(ProviderError::LoadingFailed(
457                "create_provider returned null".to_string()
458            ));
459        }
460        
461        // Get metadata
462        let metadata_ptr = unsafe { get_metadata() };
463        let metadata_str = if !metadata_ptr.is_null() {
464            unsafe { std::ffi::CStr::from_ptr(metadata_ptr).to_str().unwrap_or("{}") }
465        } else {
466            "{}"
467        };
468        
469        let metadata_json: serde_json::Value = serde_json::from_str(metadata_str)
470            .map_err(|e| ProviderError::LoadingFailed(format!("Invalid metadata JSON: {}", e)))?;
471        
472        // Initialize the provider with event registry if available
473        if let Some(registry) = event_registry {
474            // Create a registry adapter that bridges the FFI interface to our event registry
475            let mut registry_adapter = Box::new(RegistryAdapter::new());
476            registry_adapter.set_registry(Arc::clone(&registry));
477            let registry_ptr = Box::into_raw(registry_adapter) as *mut std::ffi::c_void;
478            
479            // Set the FFI interface on the provider (required)
480            let set_registry_interface: Symbol<unsafe extern "C" fn(*mut std::ffi::c_void, *const FFIRegistryInterface) -> bool> = unsafe {
481                lib.get(b"set_registry_interface").map_err(|e| {
482                    ProviderError::LoadingFailed(format!(
483                        "Provider must implement set_registry_interface function: {}",
484                        e
485                    ))
486                })?
487            };
488            
489            // Create FFI interface with the registration callback
490            let ffi_interface = FFIRegistryInterface {
491                register_fn: ffi_register_event,
492            };
493            
494            let interface_success = unsafe { set_registry_interface(provider_ptr, &ffi_interface) };
495            if !interface_success {
496                return Err(ProviderError::InitializationFailed(
497                    "Failed to set registry interface on provider".to_string()
498                ));
499            }
500            
501            let init_success = unsafe { initialize_provider(provider_ptr, registry_ptr) };
502            if !init_success {
503                return Err(ProviderError::InitializationFailed(
504                    "Provider initialization failed".to_string()
505                ));
506            }
507        } else {
508            // No event registry provided, skip initialization
509            println!("Warning: No event registry provided for modern provider initialization");
510        }
511        
512        // Create the provider wrapper
513        let provider = Arc::new(ModernProviderWrapper::new(
514            provider_ptr,
515            metadata_json.clone(),
516            library_path.to_path_buf(),
517        ));
518        
519        // Create metadata - modern providers don't expose features
520        let metadata = ProviderMetadata {
521            name: metadata_json.get("name")
522                .and_then(|v| v.as_str())
523                .unwrap_or("unknown")
524                .to_string(),
525            version: metadata_json.get("version")
526                .and_then(|v| v.as_str())
527                .unwrap_or("0.0.0")
528                .to_string(),
529            description: metadata_json.get("description")
530                .and_then(|v| v.as_str())
531                .unwrap_or("")
532                .to_string(),
533            author: None,
534            license: None,
535            features: vec![], // Features are loaded separately
536            settings_schema: None,
537            file_path: Some(library_path.to_string_lossy().to_string()),
538            metadata: Some(metadata_json), // Store raw metadata for validation
539        };
540        
541        // Store the library to keep it alive
542        {
543            let mut libraries = self.libraries.write().await;
544            let owned_lib = unsafe { Library::new(library_path)? };
545            libraries.push(owned_lib);
546        }
547        
548        Ok((provider, metadata))
549    }
550    
551    /// Load a feature and wrap it as a provider
552    async fn load_feature_as_provider(
553        &self,
554        lib: &Library,
555        library_path: &Path,
556        context: Arc<dyn ProviderContext>,
557    ) -> ProviderResult<(Arc<dyn Provider>, ProviderMetadata)> {
558        println!("Detected feature plugin");
559        
560        // Get feature name
561        let get_feature_name: Symbol<unsafe extern "C" fn() -> *const std::os::raw::c_char> = unsafe {
562            lib.get(b"get_feature_name").map_err(|e| {
563                ProviderError::LoadingFailed(format!(
564                    "Failed to find get_feature_name function: {}",
565                    e
566                ))
567            })?
568        };
569        
570        let name_ptr = unsafe { get_feature_name() };
571        let feature_name = if !name_ptr.is_null() {
572            unsafe { 
573                std::ffi::CStr::from_ptr(name_ptr)
574                    .to_str()
575                    .unwrap_or("unknown")
576                    .to_string()
577            }
578        } else {
579            "unknown".to_string()
580        };
581        
582        // Get operations
583        let register_operations: Symbol<unsafe extern "C" fn() -> *const std::os::raw::c_char> = unsafe {
584            lib.get(b"register_operations").map_err(|e| {
585                ProviderError::LoadingFailed(format!(
586                    "Failed to find register_operations function: {}",
587                    e
588                ))
589            })?
590        };
591        
592        let operations_ptr = unsafe { register_operations() };
593        let operations_json = if !operations_ptr.is_null() {
594            unsafe { 
595                std::ffi::CStr::from_ptr(operations_ptr)
596                    .to_str()
597                    .unwrap_or("[]")
598                    .to_string()
599            }
600        } else {
601            "[]".to_string()
602        };
603        
604        let operations: Vec<String> = serde_json::from_str(&operations_json)
605            .unwrap_or_else(|_| vec![]);
606        
607        println!("Feature loaded: {} with operations: {:?}", feature_name, operations);
608        
609        // Create feature adapter
610        let provider = Arc::new(FeatureAdapter::new(
611            feature_name.clone(),
612            operations.clone(),
613            library_path.to_string_lossy().to_string(),
614        ));
615        
616        // Build metadata
617        let feature_metadata = FeatureMetadata::new(
618            feature_name.clone(),
619            format!("{} feature", feature_name),
620            "1.0.0".to_string(),
621        );
622        
623        let metadata = ProviderMetadata {
624            name: format!("feature-{}", feature_name),
625            version: "1.0.0".to_string(),
626            description: format!("Feature provider for {}", feature_name),
627            author: None,
628            license: None,
629            features: vec![feature_metadata],
630            settings_schema: None,
631            file_path: Some(library_path.to_string_lossy().to_string()),
632            metadata: None, // Feature adapters don't have raw metadata
633        };
634        
635        // Store the library to keep it alive
636        {
637            let mut libraries = self.libraries.write().await;
638            let owned_lib = unsafe { Library::new(library_path)? };
639            libraries.push(owned_lib);
640        }
641        
642        Ok((provider, metadata))
643    }
644}
645
646/// Types of providers that can be loaded
647#[derive(Debug, Clone, Copy)]
648enum ProviderType {
649    LegacyCpi,
650    ModernProvider,
651    Feature,
652}
653
654/// Registry adapter for FFI providers that need to register with event registry
655struct RegistryAdapter {
656    // This will be filled with the actual event registry when needed
657    registry: Option<Arc<EventRegistry>>,
658}
659
660/// FFI callback function for event registration
661unsafe extern "C" fn ffi_register_event(
662    registry: *mut std::ffi::c_void,
663    event_name: *const std::os::raw::c_char,
664    handler: unsafe extern "C" fn(data: *const std::os::raw::c_char) -> *const std::os::raw::c_char,
665) {
666    if registry.is_null() || event_name.is_null() {
667        eprintln!("FFI: Invalid parameters for event registration");
668        return;
669    }
670    
671    let adapter = registry as *mut RegistryAdapter;
672    let adapter_ref = &*adapter;
673    
674    if let Some(event_registry) = &adapter_ref.registry {
675        let event_name_str = match std::ffi::CStr::from_ptr(event_name).to_str() {
676            Ok(s) => s,
677            Err(_) => {
678                eprintln!("FFI: Invalid event name string");
679                return;
680            }
681        };
682        
683        println!("🔍 DEBUG: FFI registering event: {}", event_name_str);
684        
685        // Create a wrapper that converts the FFI handler to our EventHandler type
686        let event_handler = Box::new(move |data: serde_json::Value| -> Result<serde_json::Value, String> {
687            let data_str = data.to_string();
688            let data_cstr = std::ffi::CString::new(data_str).map_err(|_| "Failed to create C string")?;
689            
690            unsafe {
691                let result_ptr = handler(data_cstr.as_ptr());
692                if result_ptr.is_null() {
693                    return Err("Handler returned null".to_string());
694                }
695                
696                let result_str = std::ffi::CStr::from_ptr(result_ptr).to_str()
697                    .map_err(|_| "Invalid result string")?;
698                
699                serde_json::from_str(result_str)
700                    .map_err(|e| format!("Invalid JSON result: {}", e))
701            }
702        });
703        
704        // Register using spawn to avoid nested runtime issue
705        if let Ok(handle) = tokio::runtime::Handle::try_current() {
706            let registry_clone = Arc::clone(event_registry);
707            let event_name_owned = event_name_str.to_string();
708            
709            handle.spawn(async move {
710                registry_clone.register(&event_name_owned, event_handler).await;
711            });
712        } else {
713            eprintln!("FFI: No tokio runtime available for event registration");
714        }
715    } else {
716        eprintln!("FFI: No event registry available");
717    }
718}
719
720impl RegistryAdapter {
721    fn new() -> Self {
722        Self { registry: None }
723    }
724    
725    fn set_registry(&mut self, registry: Arc<EventRegistry>) {
726        self.registry = Some(registry);
727    }
728}
729
730// FFI-compatible registry interface for providers
731#[repr(C)]
732pub struct FFIRegistryInterface {
733    pub register_fn: unsafe extern "C" fn(
734        registry: *mut std::ffi::c_void,
735        event_name: *const std::os::raw::c_char,
736        handler: unsafe extern "C" fn(data: *const std::os::raw::c_char) -> *const std::os::raw::c_char,
737    ),
738}
739
740/// Adapter for legacy CPI plugins
741struct LegacyCpiAdapter {
742    name: String,
743    file_path: String,
744}
745
746impl LegacyCpiAdapter {
747    fn new(file_path: String) -> Self {
748        // Extract name from file path
749        let name = Path::new(&file_path)
750            .file_stem()
751            .and_then(|s| s.to_str())
752            .unwrap_or("unknown")
753            .to_string();
754            
755        Self { name, file_path }
756    }
757}
758
759impl Provider for LegacyCpiAdapter {
760    fn name(&self) -> &str {
761        &self.name
762    }
763    
764    fn version(&self) -> &str {
765        "1.0.0"
766    }
767    
768    fn features(&self) -> Vec<String> {
769        // Legacy CPIs don't expose features through the provider interface
770        // Features are separate interface definitions loaded independently
771        vec![]
772    }
773    
774    fn feature_operations(&self, feature: &str) -> ProviderResult<Vec<String>> {
775        // TODO: Extract from actual CPI
776        match feature {
777            "vm-management" => Ok(vec!["start".to_string(), "stop".to_string(), "create".to_string()]),
778            "vm-control" => Ok(vec!["reset".to_string(), "pause".to_string()]),
779            _ => Err(ProviderError::FeatureNotSupported {
780                provider: self.name.clone(),
781                feature: feature.to_string(),
782            }),
783        }
784    }
785    
786    fn execute_operation(
787        &self,
788        feature: &str,
789        operation: &str,
790        args: HashMap<String, serde_json::Value>,
791        context: &dyn ProviderContext,
792    ) -> ProviderResult<serde_json::Value> {
793        // TODO: Route to actual CPI execution
794        Ok(serde_json::json!({
795            "success": true,
796            "provider": self.name,
797            "feature": feature,
798            "operation": operation,
799            "message": "Legacy CPI operation executed"
800        }))
801    }
802    
803    fn initialize(&mut self, context: &dyn ProviderContext) -> ProviderResult<()> {
804        Ok(())
805    }
806    
807    fn shutdown(&mut self, context: &dyn ProviderContext) -> ProviderResult<()> {
808        Ok(())
809    }
810}
811
812/// Wrapper for modern providers loaded via FFI
813struct ModernProviderWrapper {
814    provider_ptr: *mut std::ffi::c_void,
815    metadata: serde_json::Value,
816    file_path: std::path::PathBuf,
817}
818
819impl ModernProviderWrapper {
820    fn new(provider_ptr: *mut std::ffi::c_void, metadata: serde_json::Value, file_path: std::path::PathBuf) -> Self {
821        Self {
822            provider_ptr,
823            metadata,
824            file_path,
825        }
826    }
827}
828
829unsafe impl Send for ModernProviderWrapper {}
830unsafe impl Sync for ModernProviderWrapper {}
831
832impl Provider for ModernProviderWrapper {
833    fn name(&self) -> &str {
834        self.metadata.get("name")
835            .and_then(|v| v.as_str())
836            .unwrap_or("unknown")
837    }
838    
839    fn version(&self) -> &str {
840        self.metadata.get("version")
841            .and_then(|v| v.as_str())
842            .unwrap_or("0.0.0")
843    }
844    
845    fn features(&self) -> Vec<String> {
846        // Modern providers don't expose features through the provider interface
847        // Features are separate interface definitions loaded independently
848        vec![]
849    }
850    
851    fn feature_operations(&self, feature: &str) -> ProviderResult<Vec<String>> {
852        // For modern providers, operations are registered dynamically with the event registry
853        // We don't need to enumerate them here as they're handled by the registry
854        Ok(vec![])
855    }
856    
857    fn execute_operation(
858        &self,
859        feature: &str,
860        operation: &str,
861        args: HashMap<String, serde_json::Value>,
862        context: &dyn ProviderContext,
863    ) -> ProviderResult<serde_json::Value> {
864        // Modern providers use event registry for execution, not direct calls
865        Err(ProviderError::ExecutionFailed(
866            "Modern providers should be executed through event registry".to_string()
867        ))
868    }
869    
870    fn initialize(&mut self, context: &dyn ProviderContext) -> ProviderResult<()> {
871        // Modern providers are initialized when loaded and registered with event registry
872        Ok(())
873    }
874    
875    fn shutdown(&mut self, context: &dyn ProviderContext) -> ProviderResult<()> {
876        // TODO: Call provider's shutdown function via FFI if available
877        Ok(())
878    }
879}
880
881/// Adapter for feature plugins
882struct FeatureAdapter {
883    name: String,
884    operations: Vec<String>,
885    file_path: String,
886}
887
888impl FeatureAdapter {
889    fn new(name: String, operations: Vec<String>, file_path: String) -> Self {
890        Self { name, operations, file_path }
891    }
892}
893
894impl Provider for FeatureAdapter {
895    fn name(&self) -> &str {
896        &self.name
897    }
898    
899    fn version(&self) -> &str {
900        "1.0.0"
901    }
902    
903    fn features(&self) -> Vec<String> {
904        vec![self.name.clone()]
905    }
906    
907    fn feature_operations(&self, feature: &str) -> ProviderResult<Vec<String>> {
908        if feature == self.name {
909            Ok(self.operations.clone())
910        } else {
911            Err(ProviderError::FeatureNotSupported {
912                provider: self.name.clone(),
913                feature: feature.to_string(),
914            })
915        }
916    }
917    
918    fn execute_operation(
919        &self,
920        feature: &str,
921        operation: &str,
922        args: HashMap<String, serde_json::Value>,
923        context: &dyn ProviderContext,
924    ) -> ProviderResult<serde_json::Value> {
925        if feature != self.name {
926            return Err(ProviderError::FeatureNotSupported {
927                provider: self.name.clone(),
928                feature: feature.to_string(),
929            });
930        }
931        
932        if !self.operations.contains(&operation.to_string()) {
933            return Err(ProviderError::OperationNotSupported {
934                provider: self.name.clone(),
935                feature: feature.to_string(),
936                operation: operation.to_string(),
937            });
938        }
939        
940        // TODO: Route to actual feature execution via FFI
941        Ok(serde_json::json!({
942            "success": true,
943            "provider": self.name,
944            "feature": feature,
945            "operation": operation,
946            "args": args,
947            "message": "Feature operation executed"
948        }))
949    }
950    
951    fn initialize(&mut self, context: &dyn ProviderContext) -> ProviderResult<()> {
952        Ok(())
953    }
954    
955    fn shutdown(&mut self, context: &dyn ProviderContext) -> ProviderResult<()> {
956        Ok(())
957    }
958}