Skip to main content

gglib_core/ports/
system_probe.rs

1//! System probe port for dependency and GPU detection.
2//!
3//! This port abstracts active system probing (command execution, hardware detection)
4//! from the core domain. Implementations live in adapters (e.g., gglib-runtime).
5//!
6//! # Design Notes
7//!
8//! - Core owns the trait and types (pure)
9//! - Runtime owns the implementation (active probing via `Command::new`)
10//! - CLI injects the probe via main.rs
11
12use crate::utils::system::{Dependency, GpuInfo, SystemMemoryInfo};
13
14/// Port for probing system dependencies and hardware.
15///
16/// Implementations of this trait perform active system probing by executing
17/// commands, querying hardware, etc. The core domain uses this trait to
18/// remain pure and testable.
19///
20/// # Example
21///
22/// ```ignore
23/// use gglib_core::ports::SystemProbePort;
24///
25/// fn check_system(probe: &dyn SystemProbePort) {
26///     let deps = probe.check_all_dependencies();
27///     let gpu = probe.detect_gpu_info();
28///     // ...
29/// }
30/// ```
31pub trait SystemProbePort: Send + Sync {
32    /// Check all system dependencies and return their status.
33    ///
34    /// Returns a list of dependencies with their installation status,
35    /// version information, and hints for installation.
36    fn check_all_dependencies(&self) -> Vec<Dependency>;
37
38    /// Detect GPU hardware and acceleration software.
39    ///
40    /// Returns information about available GPUs including NVIDIA/CUDA,
41    /// AMD/ROCm, and Apple Metal support.
42    fn detect_gpu_info(&self) -> GpuInfo;
43
44    /// Get system memory information for model fit calculations.
45    ///
46    /// Returns total RAM, GPU memory (if available), and platform info
47    /// useful for determining which models can run on this system.
48    fn get_system_memory_info(&self) -> SystemMemoryInfo;
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54    use crate::utils::system::DependencyStatus;
55
56    /// Mock implementation for testing.
57    struct MockSystemProbe {
58        deps: Vec<Dependency>,
59        gpu: GpuInfo,
60        memory: SystemMemoryInfo,
61    }
62
63    impl SystemProbePort for MockSystemProbe {
64        fn check_all_dependencies(&self) -> Vec<Dependency> {
65            self.deps.clone()
66        }
67
68        fn detect_gpu_info(&self) -> GpuInfo {
69            self.gpu.clone()
70        }
71
72        fn get_system_memory_info(&self) -> SystemMemoryInfo {
73            self.memory.clone()
74        }
75    }
76
77    #[test]
78    fn test_mock_probe() {
79        let probe = MockSystemProbe {
80            deps: vec![
81                Dependency::required("cargo", "Rust build tool").with_status(
82                    DependencyStatus::Present {
83                        version: "1.75.0".to_string(),
84                    },
85                ),
86            ],
87            gpu: GpuInfo {
88                has_nvidia_gpu: false,
89                cuda_version: None,
90                has_metal: true,
91                has_vulkan: false,
92                vulkan_headers: false,
93                vulkan_glslc: false,
94                vulkan_spirv_headers: false,
95            },
96            memory: SystemMemoryInfo {
97                total_ram_bytes: 16 * 1024 * 1024 * 1024,
98                gpu_memory_bytes: Some(12 * 1024 * 1024 * 1024),
99                is_unified_memory: true,
100                has_nvidia_gpu: false,
101            },
102        };
103
104        let deps = probe.check_all_dependencies();
105        assert_eq!(deps.len(), 1);
106        assert_eq!(deps[0].name, "cargo");
107
108        let gpu = probe.detect_gpu_info();
109        assert!(gpu.has_metal);
110        assert!(!gpu.has_nvidia_gpu);
111
112        let mem = probe.get_system_memory_info();
113        assert!(mem.is_unified_memory);
114    }
115}