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}