1use anyhow::Result;
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10use std::path::PathBuf;
11use std::sync::{Arc, RwLock};
12use tracing::{debug, info, warn};
13
14use crate::model_runtime::platform_detector::{HardwareCapabilities, Platform, HardwareArchitecture};
15
16#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
18pub enum AccelerationType {
19 CPU,
20 CUDA,
21 Metal,
22 Vulkan,
23 OpenCL,
24 DirectML,
25}
26
27impl std::fmt::Display for AccelerationType {
28 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29 match self {
30 AccelerationType::CPU => write!(f, "CPU"),
31 AccelerationType::CUDA => write!(f, "CUDA"),
32 AccelerationType::Metal => write!(f, "Metal"),
33 AccelerationType::Vulkan => write!(f, "Vulkan"),
34 AccelerationType::OpenCL => write!(f, "OpenCL"),
35 AccelerationType::DirectML => write!(f, "DirectML"),
36 }
37 }
38}
39
40#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
42pub enum EngineStatus {
43 NotInstalled,
44 Available,
45 Downloading,
46 Installed,
47 Active,
48 Corrupted,
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize)]
53pub struct EngineInfo {
54 pub id: String,
55 pub name: String,
56 pub version: String,
57 pub platform: Platform,
58 pub architecture: HardwareArchitecture,
59 pub acceleration: AccelerationType,
60 pub download_url: String,
61 pub file_size: u64,
62 pub checksum: String,
63 pub compatibility_score: f32,
64 pub status: EngineStatus,
65 pub install_path: Option<PathBuf>,
66 pub binary_name: String,
67 pub required_dependencies: Vec<String>,
68}
69
70impl EngineInfo {
71 pub fn calculate_compatibility(&self, hardware: &HardwareCapabilities) -> f32 {
73 let mut score: f32 = 0.0;
74
75 if self.platform == hardware.platform {
77 score += 50.0;
78 } else {
79 return 0.0; }
81
82 if self.architecture == hardware.architecture {
84 score += 20.0;
85 }
86
87 match (&self.acceleration, hardware) {
89 (AccelerationType::CPU, _) => score += 15.0,
90 (AccelerationType::CUDA, hw) if hw.has_cuda => score += 25.0,
91 (AccelerationType::Metal, hw) if hw.has_metal => score += 25.0,
92 (AccelerationType::Vulkan, hw) if hw.has_vulkan => score += 20.0,
93 _ => {
94 if self.acceleration != AccelerationType::CPU {
96 score -= 10.0;
97 }
98 }
99 }
100
101 if self.is_recent_version() {
103 score += 5.0;
104 }
105
106 score.clamp(0.0, 100.0)
107 }
108
109 fn is_recent_version(&self) -> bool {
111 self.version.contains("b") || self.version.contains("latest")
113 }
114}
115
116pub struct EngineRegistry {
118 pub installed_engines: HashMap<String, EngineInfo>,
119 pub available_engines: Vec<EngineInfo>,
120 pub default_engine: Option<String>,
121 pub storage_path: PathBuf,
122 download_in_progress: Arc<RwLock<bool>>,
124}
125
126impl EngineRegistry {
127 pub fn new() -> Result<Self> {
128 let storage_path = Self::get_engine_storage_path()?;
129 std::fs::create_dir_all(&storage_path)?;
130
131 Ok(Self {
132 installed_engines: HashMap::new(),
133 available_engines: Vec::new(),
134 default_engine: None,
135 download_in_progress: Arc::new(RwLock::new(false)),
136 storage_path,
137 })
138 }
139
140 fn get_engine_storage_path() -> Result<PathBuf> {
142 let base_dir = if cfg!(target_os = "windows") {
143 dirs::data_dir()
144 .ok_or_else(|| anyhow::anyhow!("Failed to get APPDATA directory"))?
145 .join("Aud.io")
146 .join("engines")
147 } else if cfg!(target_os = "macos") {
148 dirs::data_dir()
149 .ok_or_else(|| anyhow::anyhow!("Failed to get Library directory"))?
150 .join("Aud.io")
151 .join("engines")
152 } else {
153 dirs::data_dir()
154 .ok_or_else(|| anyhow::anyhow!("Failed to get .local/share directory"))?
155 .join("aud.io")
156 .join("engines")
157 };
158
159 Ok(base_dir)
160 }
161
162 pub async fn scan_installed_engines(&mut self, hardware_capabilities: &HardwareCapabilities) -> Result<()> {
164 self.installed_engines.clear();
165
166 if self.storage_path.exists() {
167 for entry in std::fs::read_dir(&self.storage_path)? {
168 let entry = entry?;
169 if entry.file_type()?.is_dir() {
170 let engine_dir = entry.path();
171 match self.load_engine_metadata(engine_dir.clone()).await {
172 Some(engine_info) => {
173 self.installed_engines.insert(engine_info.id.clone(), engine_info);
174 }
175 None => {
176 if self.has_binary(&engine_dir) {
178 warn!("Found orphaned engine at {} (missing or invalid metadata.json). Consider re-downloading this engine.", engine_dir.display());
179 }
180 }
181 }
182 }
183 }
184 }
185
186 self.refresh_available_engines(hardware_capabilities).await?;
188
189 debug!("Found {} installed engines", self.installed_engines.len());
190 Ok(())
191 }
192
193 fn has_binary(&self, engine_dir: &PathBuf) -> bool {
195 let binary_names = ["llama-server.exe", "llama-server", "llama-cli.exe", "llama-cli"];
196 let platform_dirs = ["Windows", "windows", "Linux", "MacOS", "macos"];
197
198 for platform_dir in platform_dirs.iter() {
199 let platform_path = engine_dir.join(platform_dir);
200 if platform_path.exists() {
201 for binary_name in binary_names.iter() {
202 if platform_path.join(binary_name).exists() {
203 return true;
204 }
205 }
206 }
207 }
208
209 false
210 }
211
212 async fn load_engine_metadata(&self, engine_dir: PathBuf) -> Option<EngineInfo> {
214 let metadata_path = engine_dir.join("metadata.json");
215 if !metadata_path.exists() {
216 return None;
217 }
218
219 match std::fs::read_to_string(&metadata_path) {
220 Ok(content) => {
221 match serde_json::from_str::<EngineInfo>(&content) {
222 Ok(mut engine_info) => {
223 let binary_path = engine_dir.join(&engine_info.binary_name);
225 if binary_path.exists() {
226 engine_info.status = EngineStatus::Installed;
227 engine_info.install_path = Some(engine_dir);
228 Some(engine_info)
229 } else {
230 warn!("Engine binary not found: {:?}", binary_path);
231 None
232 }
233 }
234 Err(e) => {
235 warn!("Failed to parse engine metadata: {}", e);
236 None
237 }
238 }
239 }
240 Err(e) => {
241 warn!("Failed to read engine metadata: {}", e);
242 None
243 }
244 }
245 }
246
247 pub fn get_compatible_engines(&self, hardware: &HardwareCapabilities) -> Vec<&EngineInfo> {
249 self.installed_engines
250 .values()
251 .filter(|engine| {
252 let compatibility = engine.calculate_compatibility(hardware);
253 compatibility > 30.0 && engine.status == EngineStatus::Installed
254 })
255 .collect()
256 }
257
258 pub fn select_best_compatible_engine(&self, hardware: &HardwareCapabilities) -> Option<EngineInfo> {
260 let mut compatible_engines: Vec<_> = self.get_compatible_engines(hardware)
261 .into_iter()
262 .map(|engine| {
263 let score = engine.calculate_compatibility(hardware);
264 (engine, score)
265 })
266 .collect();
267
268 compatible_engines.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal));
269
270 compatible_engines.first().map(|(engine, _)| (*engine).clone())
271 }
272
273 pub fn get_recommended_engine(&self, hardware: &HardwareCapabilities) -> Option<EngineInfo> {
275 if let Some(best_installed) = self.select_best_compatible_engine(hardware) {
277 if best_installed.calculate_compatibility(hardware) > 70.0 {
278 return Some(best_installed);
279 }
280 }
281
282 if !self.available_engines.is_empty() {
285 let mut compatible_engines: Vec<_> = self.available_engines
286 .iter()
287 .map(|engine| {
288 let score = engine.calculate_compatibility(hardware);
289 (engine, score)
290 })
291 .filter(|(_, score)| *score > 0.0) .collect();
293
294 compatible_engines.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal));
295
296 if let Some((engine, _)) = compatible_engines.first() {
297 let mut engine_clone = (*engine).clone();
298 engine_clone.status = EngineStatus::Available; return Some(engine_clone);
300 }
301 }
302
303 self.get_official_engine_recommendation(hardware)
305 }
306
307 fn get_latest_version(&self) -> String {
309 "b8037".to_string()
313 }
314
315 fn get_official_engine_recommendation(&self, hardware: &HardwareCapabilities) -> Option<EngineInfo> {
317 let latest_version = self.get_latest_version();
318
319 match (&hardware.platform, &hardware.architecture, hardware.has_cuda, hardware.has_metal) {
320 (Platform::Windows, HardwareArchitecture::X86_64, true, _) => {
321 Some(EngineInfo {
323 id: format!("llama-cuda-windows-x64-{}", latest_version),
324 name: format!("llama.cpp CUDA Windows x64 ({})", latest_version),
325 version: latest_version.to_string(),
326 platform: Platform::Windows,
327 architecture: HardwareArchitecture::X86_64,
328 acceleration: AccelerationType::CUDA,
329 download_url: format!("https://github.com/ggml-org/llama.cpp/releases/download/{}/llama-{}-bin-win-cuda-12.4-x64.zip", latest_version, latest_version),
330 file_size: 373 * 1024 * 1024, checksum: "".to_string(), compatibility_score: 95.0,
333 status: EngineStatus::Available,
334 install_path: None,
335 binary_name: "llama-server.exe".to_string(),
336 required_dependencies: vec!["CUDA 12.4+ Runtime".to_string()],
337 })
338 }
339 (Platform::Windows, HardwareArchitecture::X86_64, false, _) => {
340 Some(EngineInfo {
342 id: format!("llama-cpu-windows-x64-{}", latest_version),
343 name: format!("llama.cpp CPU Windows x64 ({})", latest_version),
344 version: latest_version.to_string(),
345 platform: Platform::Windows,
346 architecture: HardwareArchitecture::X86_64,
347 acceleration: AccelerationType::CPU,
348 download_url: format!("https://github.com/ggml-org/llama.cpp/releases/download/{}/llama-{}-bin-win-x64.zip", latest_version, latest_version),
349 file_size: 50 * 1024 * 1024,
350 checksum: "".to_string(),
351 compatibility_score: 85.0,
352 status: EngineStatus::Available,
353 install_path: None,
354 binary_name: "llama-server.exe".to_string(),
355 required_dependencies: vec![],
356 })
357 }
358 (Platform::MacOS, HardwareArchitecture::Aarch64, _, true) => {
359 Some(EngineInfo {
361 id: format!("llama-metal-macos-arm64-{}", latest_version),
362 name: format!("llama.cpp Metal macOS ARM64 ({})", latest_version),
363 version: latest_version.to_string(),
364 platform: Platform::MacOS,
365 architecture: HardwareArchitecture::Aarch64,
366 acceleration: AccelerationType::Metal,
367 download_url: format!("https://github.com/ggml-org/llama.cpp/releases/download/{}/llama-{}-bin-macos-arm64.tar.gz", latest_version, latest_version),
368 file_size: 29 * 1024 * 1024,
369 checksum: "".to_string(),
370 compatibility_score: 95.0,
371 status: EngineStatus::Available,
372 install_path: None,
373 binary_name: "llama-server".to_string(),
374 required_dependencies: vec![],
375 })
376 }
377 (Platform::MacOS, HardwareArchitecture::X86_64, _, _) => {
378 Some(EngineInfo {
380 id: format!("llama-cpu-macos-x64-{}", latest_version),
381 name: format!("llama.cpp CPU macOS x64 ({})", latest_version),
382 version: latest_version.to_string(),
383 platform: Platform::MacOS,
384 architecture: HardwareArchitecture::X86_64,
385 acceleration: AccelerationType::CPU,
386 download_url: format!("https://github.com/ggml-org/llama.cpp/releases/download/{}/llama-{}-bin-macos-x64.tar.gz", latest_version, latest_version),
387 file_size: 82 * 1024 * 1024,
388 checksum: "".to_string(),
389 compatibility_score: 85.0,
390 status: EngineStatus::Available,
391 install_path: None,
392 binary_name: "llama-server".to_string(),
393 required_dependencies: vec![],
394 })
395 }
396 (Platform::Linux, HardwareArchitecture::X86_64, true, _) => {
397 Some(EngineInfo {
399 id: format!("llama-cuda-linux-x64-{}", latest_version),
400 name: format!("llama.cpp CUDA Linux x64 ({})", latest_version),
401 version: latest_version.to_string(),
402 platform: Platform::Linux,
403 architecture: HardwareArchitecture::X86_64,
404 acceleration: AccelerationType::CUDA,
405 download_url: format!("https://github.com/ggml-org/llama.cpp/releases/download/{}/llama-{}-bin-ubuntu-x64-cuda-12.4.tar.gz", latest_version, latest_version), file_size: 180 * 1024 * 1024,
407 checksum: "".to_string(),
408 compatibility_score: 90.0,
409 status: EngineStatus::Available,
410 install_path: None,
411 binary_name: "llama-server".to_string(),
412 required_dependencies: vec!["CUDA 12.4+ Runtime".to_string()],
413 })
414 }
415 (Platform::Linux, HardwareArchitecture::X86_64, false, _) => {
416 Some(EngineInfo {
418 id: format!("llama-cpu-linux-x64-{}", latest_version),
419 name: format!("llama.cpp CPU Linux x64 ({})", latest_version),
420 version: latest_version.to_string(),
421 platform: Platform::Linux,
422 architecture: HardwareArchitecture::X86_64,
423 acceleration: AccelerationType::CPU,
424 download_url: format!("https://github.com/ggml-org/llama.cpp/releases/download/{}/llama-{}-bin-ubuntu-x64.tar.gz", latest_version, latest_version),
425 file_size: 45 * 1024 * 1024,
426 checksum: "".to_string(),
427 compatibility_score: 80.0,
428 status: EngineStatus::Available,
429 install_path: None,
430 binary_name: "llama-server".to_string(),
431 required_dependencies: vec![],
432 })
433 }
434 _ => None,
435 }
436 }
437
438 pub fn set_default_engine(&mut self, engine_id: &str) -> Result<()> {
440 if self.installed_engines.contains_key(engine_id) {
441 self.default_engine = Some(engine_id.to_string());
442 info!("Set default engine: {}", engine_id);
443 Ok(())
444 } else {
445 Err(anyhow::anyhow!("Engine not found: {}", engine_id))
446 }
447 }
448
449 pub fn has_installed_engine(&self) -> bool {
451 !self.installed_engines.is_empty()
452 }
453
454 pub fn get_default_engine(&self) -> Option<&EngineInfo> {
456 if let Some(ref engine_id) = self.default_engine {
457 self.installed_engines.get(engine_id)
458 } else {
459 self.installed_engines.values().next()
461 }
462 }
463
464 pub async fn add_installed_engine(&mut self, mut engine: EngineInfo) -> Result<()> {
466 engine.status = EngineStatus::Installed;
467 self.installed_engines.insert(engine.id.clone(), engine);
468 Ok(())
469 }
470
471 pub async fn refresh_available_engines(&mut self, hardware_capabilities: &HardwareCapabilities) -> Result<()> {
473 self.available_engines.clear();
475
476 let all_engines = self.get_all_compatible_engines(hardware_capabilities);
478
479 for engine in all_engines {
480 if !self.available_engines.iter().any(|e| e.id == engine.id) {
481 self.available_engines.push(engine);
482 }
483 }
484
485 let fallback_engines = self.get_additional_engine_recommendations(hardware_capabilities);
487 for engine in fallback_engines {
488 if !self.available_engines.iter().any(|e| e.id == engine.id) {
489 self.available_engines.push(engine);
490 }
491 }
492
493 info!("Refreshed available engines: {} found", self.available_engines.len());
494 Ok(())
495 }
496
497 fn get_all_compatible_engines(&self, hardware: &HardwareCapabilities) -> Vec<EngineInfo> {
499 let mut engines = Vec::new();
500 let latest_version = self.get_latest_version();
501
502 match (&hardware.platform, &hardware.architecture) {
503 (Platform::Windows, HardwareArchitecture::X86_64) => {
504 engines.push(EngineInfo {
508 id: format!("llama-cpu-windows-x64-{}", latest_version),
509 name: format!("llama.cpp CPU (Windows x64) ({})", latest_version),
510 version: latest_version.to_string(),
511 platform: Platform::Windows,
512 architecture: HardwareArchitecture::X86_64,
513 acceleration: AccelerationType::CPU,
514 download_url: format!("https://github.com/ggml-org/llama.cpp/releases/download/{}/llama-{}-bin-win-x64.zip", latest_version, latest_version),
515 file_size: 50 * 1024 * 1024,
516 checksum: "".to_string(),
517 compatibility_score: if !hardware.has_cuda { 95.0 } else { 80.0 },
518 status: EngineStatus::Available,
519 install_path: None,
520 binary_name: "llama-server.exe".to_string(),
521 required_dependencies: vec![],
522 });
523
524 if hardware.has_cuda {
526 engines.push(EngineInfo {
527 id: format!("llama-cuda-windows-x64-{}", latest_version),
528 name: format!("llama.cpp CUDA (Windows x64) ({})", latest_version),
529 version: latest_version.to_string(),
530 platform: Platform::Windows,
531 architecture: HardwareArchitecture::X86_64,
532 acceleration: AccelerationType::CUDA,
533 download_url: format!("https://github.com/ggml-org/llama.cpp/releases/download/{}/llama-{}-bin-win-cuda-12.4-x64.zip", latest_version, latest_version),
534 file_size: 373 * 1024 * 1024, checksum: "".to_string(),
536 compatibility_score: 100.0,
537 status: EngineStatus::Available,
538 install_path: None,
539 binary_name: "llama-server.exe".to_string(),
540 required_dependencies: vec!["NVIDIA GPU with CUDA support".to_string()],
541 });
542
543 engines.push(EngineInfo {
545 id: format!("llama-cuda13-windows-x64-{}", latest_version),
546 name: format!("llama.cpp CUDA 13 (Windows x64) ({})", latest_version),
547 version: latest_version.to_string(),
548 platform: Platform::Windows,
549 architecture: HardwareArchitecture::X86_64,
550 acceleration: AccelerationType::CUDA,
551 download_url: format!("https://github.com/ggml-org/llama.cpp/releases/download/{}/llama-{}-bin-win-cuda-13.1-x64.zip", latest_version, latest_version),
552 file_size: 384 * 1024 * 1024, checksum: "".to_string(),
554 compatibility_score: 95.0,
555 status: EngineStatus::Available,
556 install_path: None,
557 binary_name: "llama-server.exe".to_string(),
558 required_dependencies: vec!["CUDA 13.1+ Runtime".to_string()],
559 });
560 }
561
562 if hardware.has_vulkan || hardware.has_cuda {
564 engines.push(EngineInfo {
565 id: format!("llama-vulkan-windows-x64-{}", latest_version),
566 name: format!("llama.cpp Vulkan (Windows x64) ({})", latest_version),
567 version: latest_version.to_string(),
568 platform: Platform::Windows,
569 architecture: HardwareArchitecture::X86_64,
570 acceleration: AccelerationType::Vulkan,
571 download_url: format!("https://github.com/ggml-org/llama.cpp/releases/download/{}/llama-{}-bin-win-vulkan-x64.zip", latest_version, latest_version),
572 file_size: 80 * 1024 * 1024,
573 checksum: "".to_string(),
574 compatibility_score: 85.0,
575 status: EngineStatus::Available,
576 install_path: None,
577 binary_name: "llama-server.exe".to_string(),
578 required_dependencies: vec!["Vulkan-compatible GPU".to_string()],
579 });
580 }
581 }
582
583 (Platform::MacOS, HardwareArchitecture::Aarch64) => {
584 engines.push(EngineInfo {
586 id: format!("llama-metal-macos-arm64-{}", latest_version),
587 name: format!("llama.cpp Metal (macOS Apple Silicon) ({})", latest_version),
588 version: latest_version.to_string(),
589 platform: Platform::MacOS,
590 architecture: HardwareArchitecture::Aarch64,
591 acceleration: AccelerationType::Metal,
592 download_url: format!("https://github.com/ggml-org/llama.cpp/releases/download/{}/llama-{}-bin-macos-arm64.tar.gz", latest_version, latest_version),
593 file_size: 29 * 1024 * 1024,
594 checksum: "".to_string(),
595 compatibility_score: 100.0,
596 status: EngineStatus::Available,
597 install_path: None,
598 binary_name: "llama-server".to_string(),
599 required_dependencies: vec![],
600 });
601
602 engines.push(EngineInfo {
604 id: format!("llama-cpu-macos-arm64-{}", latest_version),
605 name: format!("llama.cpp CPU (macOS Apple Silicon) ({})", latest_version),
606 version: latest_version.to_string(),
607 platform: Platform::MacOS,
608 architecture: HardwareArchitecture::Aarch64,
609 acceleration: AccelerationType::CPU,
610 download_url: format!("https://github.com/ggml-org/llama.cpp/releases/download/{}/llama-{}-bin-macos-arm64.tar.gz", latest_version, latest_version),
611 file_size: 29 * 1024 * 1024,
612 checksum: "".to_string(),
613 compatibility_score: 90.0,
614 status: EngineStatus::Available,
615 install_path: None,
616 binary_name: "llama-server".to_string(),
617 required_dependencies: vec![],
618 });
619 }
620
621 (Platform::MacOS, HardwareArchitecture::X86_64) => {
622 engines.push(EngineInfo {
624 id: format!("llama-cpu-macos-x64-{}", latest_version),
625 name: format!("llama.cpp CPU (macOS Intel) ({})", latest_version),
626 version: latest_version.to_string(),
627 platform: Platform::MacOS,
628 architecture: HardwareArchitecture::X86_64,
629 acceleration: AccelerationType::CPU,
630 download_url: format!("https://github.com/ggml-org/llama.cpp/releases/download/{}/llama-{}-bin-macos-x64.tar.gz", latest_version, latest_version),
631 file_size: 82 * 1024 * 1024,
632 checksum: "".to_string(),
633 compatibility_score: 95.0,
634 status: EngineStatus::Available,
635 install_path: None,
636 binary_name: "llama-server".to_string(),
637 required_dependencies: vec![],
638 });
639 }
640
641 (Platform::Linux, HardwareArchitecture::X86_64) => {
642 engines.push(EngineInfo {
644 id: format!("llama-cpu-linux-x64-{}", latest_version),
645 name: format!("llama.cpp CPU (Linux x64) ({})", latest_version),
646 version: latest_version.to_string(),
647 platform: Platform::Linux,
648 architecture: HardwareArchitecture::X86_64,
649 acceleration: AccelerationType::CPU,
650 download_url: format!("https://github.com/ggml-org/llama.cpp/releases/download/{}/llama-{}-bin-ubuntu-x64.tar.gz", latest_version, latest_version),
651 file_size: 45 * 1024 * 1024,
652 checksum: "".to_string(),
653 compatibility_score: if !hardware.has_cuda { 95.0 } else { 80.0 },
654 status: EngineStatus::Available,
655 install_path: None,
656 binary_name: "llama-server".to_string(),
657 required_dependencies: vec![],
658 });
659
660 if hardware.has_cuda {
661 engines.push(EngineInfo {
662 id: format!("llama-cuda-linux-x64-{}", latest_version),
663 name: format!("llama.cpp CUDA (Linux x64) ({})", latest_version),
664 version: latest_version.to_string(),
665 platform: Platform::Linux,
666 architecture: HardwareArchitecture::X86_64,
667 acceleration: AccelerationType::CUDA,
668 download_url: format!("https://github.com/ggml-org/llama.cpp/releases/download/{}/llama-{}-bin-ubuntu-x64-cuda-12.4.tar.gz", latest_version, latest_version),
669 file_size: 180 * 1024 * 1024,
670 checksum: "".to_string(),
671 compatibility_score: 100.0,
672 status: EngineStatus::Available,
673 install_path: None,
674 binary_name: "llama-server".to_string(),
675 required_dependencies: vec!["NVIDIA GPU with CUDA support".to_string()],
676 });
677 }
678 }
679
680 _ => {
681 info!("Unknown platform/architecture: {:?}/{:?}", hardware.platform, hardware.architecture);
683 }
684 }
685
686 engines.sort_by(|a, b| b.compatibility_score.partial_cmp(&a.compatibility_score).unwrap());
688
689 engines
690 }
691
692 fn get_additional_engine_recommendations(&self, hardware: &HardwareCapabilities) -> Vec<EngineInfo> {
694 let mut engines = Vec::new();
695 let latest_version = self.get_latest_version();
696
697 match &hardware.platform {
699 Platform::Windows => {
700 engines.push(EngineInfo {
701 id: format!("llama-cpu-windows-x64-fallback-{}", latest_version),
702 name: format!("llama.cpp CPU Engine (Fallback {}) ", latest_version),
703 version: latest_version.to_string(),
704 platform: Platform::Windows,
705 architecture: HardwareArchitecture::X86_64,
706 acceleration: AccelerationType::CPU,
707 download_url: format!("https://github.com/ggml-org/llama.cpp/releases/download/{}/llama-{}-bin-win-x64.zip", latest_version, latest_version),
708 file_size: 50 * 1024 * 1024,
709 checksum: "".to_string(),
710 compatibility_score: 70.0,
711 status: EngineStatus::Available,
712 install_path: None,
713 binary_name: "llama-server.exe".to_string(),
714 required_dependencies: vec![],
715 });
716 }
717 Platform::Linux => {
718 engines.push(EngineInfo {
719 id: format!("llama-cpu-linux-x64-fallback-{}", latest_version),
720 name: format!("llama.cpp CPU Engine (Fallback {})", latest_version),
721 version: latest_version.to_string(),
722 platform: Platform::Linux,
723 architecture: HardwareArchitecture::X86_64,
724 acceleration: AccelerationType::CPU,
725 download_url: format!("https://github.com/ggml-org/llama.cpp/releases/download/{}/llama-{}-bin-ubuntu-x64.tar.gz", latest_version, latest_version),
726 file_size: 45 * 1024 * 1024,
727 checksum: "".to_string(),
728 compatibility_score: 70.0,
729 status: EngineStatus::Available,
730 install_path: None,
731 binary_name: "llama-server".to_string(),
732 required_dependencies: vec![],
733 });
734 }
735 Platform::MacOS => {
736 match &hardware.architecture {
742 HardwareArchitecture::Aarch64 => {
743 engines.push(EngineInfo {
744 id: format!("llama-metal-macos-arm64-fallback-{}", latest_version),
745 name: format!("llama.cpp Metal (Apple Silicon) fallback ({})", latest_version),
746 version: latest_version.to_string(),
747 platform: Platform::MacOS,
748 architecture: HardwareArchitecture::Aarch64,
749 acceleration: AccelerationType::Metal,
750 download_url: format!("https://github.com/ggml-org/llama.cpp/releases/download/{}/llama-{}-bin-macos-arm64.tar.gz", latest_version, latest_version),
751 file_size: 29 * 1024 * 1024,
752 checksum: "".to_string(),
753 compatibility_score: 85.0,
754 status: EngineStatus::Available,
755 install_path: None,
756 binary_name: "llama-server".to_string(),
757 required_dependencies: vec![],
758 });
759 engines.push(EngineInfo {
761 id: format!("llama-cpu-macos-arm64-fallback-{}", latest_version),
762 name: format!("llama.cpp CPU (Apple Silicon) fallback ({})", latest_version),
763 version: latest_version.to_string(),
764 platform: Platform::MacOS,
765 architecture: HardwareArchitecture::Aarch64,
766 acceleration: AccelerationType::CPU,
767 download_url: format!("https://github.com/ggml-org/llama.cpp/releases/download/{}/llama-{}-bin-macos-arm64.tar.gz", latest_version, latest_version),
768 file_size: 29 * 1024 * 1024,
769 checksum: "".to_string(),
770 compatibility_score: 70.0,
771 status: EngineStatus::Available,
772 install_path: None,
773 binary_name: "llama-server".to_string(),
774 required_dependencies: vec![],
775 });
776 }
777 _ => {
778 engines.push(EngineInfo {
780 id: format!("llama-cpu-macos-x64-fallback-{}", latest_version),
781 name: format!("llama.cpp CPU (macOS Intel) fallback ({})", latest_version),
782 version: latest_version.to_string(),
783 platform: Platform::MacOS,
784 architecture: HardwareArchitecture::X86_64,
785 acceleration: AccelerationType::CPU,
786 download_url: format!("https://github.com/ggml-org/llama.cpp/releases/download/{}/llama-{}-bin-macos-x64.tar.gz", latest_version, latest_version),
787 file_size: 82 * 1024 * 1024,
788 checksum: "".to_string(),
789 compatibility_score: 70.0,
790 status: EngineStatus::Available,
791 install_path: None,
792 binary_name: "llama-server".to_string(),
793 required_dependencies: vec![],
794 });
795 }
796 }
797 }
798 }
799
800 engines
801 }
802
803 pub fn get_default_engine_binary_path(&self) -> Option<PathBuf> {
805 if let Some(engine) = self.get_default_engine() {
806 engine.install_path.as_ref().map(|path| path.join(&engine.binary_name))
807 } else {
808 None
809 }
810 }
811
812 pub fn mark_download_started(&self) -> bool {
815 let mut flag = self.download_in_progress.write().unwrap();
816 if *flag {
817 false } else {
819 *flag = true;
820 true }
822 }
823
824 pub fn mark_download_finished(&self) {
826 *self.download_in_progress.write().unwrap() = false;
827 }
828
829 pub fn is_download_in_progress(&self) -> bool {
831 *self.download_in_progress.read().unwrap()
832 }
833}