Skip to main content

rusty_stack/
state.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub enum Stage {
5    Welcome,
6    HardwareDetect,
7    Preflight,
8    ComponentDetect,
9    ComponentSelect,
10    Configuration,
11    Confirm,
12    Installing,
13    Complete,
14    Benchmarks,
15    Recovery,
16}
17
18/// What kind of run the selected components constitute. Drives flow verbiage
19/// so each screen shows only text/options relevant to the selected action:
20/// benchmarks and verification are "run", not "installed".
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum RunMode {
23    Install,
24    Benchmark,
25    Verify,
26}
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29pub enum Category {
30    Foundation,
31    Core,
32    UiUx,
33    Extension,
34    Environment,
35    Maintenance,
36    Performance,
37}
38
39#[derive(Debug, Clone)]
40pub struct Component {
41    pub id: String,
42    pub name: String,
43    pub description: String,
44    /// Script path relative to scripts_dir, or empty string for native Rust modules.
45    ///
46    /// For native Rust components, this field is empty and the installer
47    /// dispatches to the corresponding Rust module via
48    /// `installers::components::is_native_component()`.
49    ///
50    /// # Validation Assertions
51    ///
52    /// - **VAL-INSTALL-037**: Component.script no longer holds .sh filenames for ported components
53    /// - **VAL-INSTALL-038**: state.rs supports native module routing
54    /// - **VAL-INSTALL-040**: Verification/performance components use native routing
55    pub script: String,
56    pub category: Category,
57    pub required: bool,
58    pub selected: bool,
59    pub installed: bool,
60    pub progress: f32,
61    pub estimate: String,
62    /// Whether this component requires sudo to install
63    pub needs_sudo: bool,
64    /// Experimental / forward-only build (e.g. Flash Attention CK on RDNA3).
65    /// Rendered with an EXPERIMENTAL badge + `note`; still selectable +
66    /// installable — never greyed out or hidden.
67    pub experimental: bool,
68    /// Optional detail shown in the component panel (capability caveats,
69    /// what works vs. what falls back). Shown only when `experimental` is true.
70    pub note: Option<String>,
71}
72
73impl Component {
74    /// Returns `true` if this component uses a native Rust installer
75    /// (no shell script involved).
76    ///
77    /// # Validation Assertions
78    ///
79    /// - **VAL-INSTALL-038**: state.rs supports native module routing
80    pub fn is_native(&self) -> bool {
81        crate::installers::components::is_native_component(&self.id)
82    }
83}
84
85#[derive(Debug, Clone, Default, Serialize, Deserialize)]
86pub struct GPUInfo {
87    pub model: String,
88    pub driver: String,
89    pub architecture: String,
90    pub rocm_version: String,
91    pub gpu_count: usize,
92    pub memory_gb: f32,
93    pub temperature_c: Option<f32>,
94    pub power_watts: Option<f32>,
95}
96
97#[derive(Debug, Clone, Default, Serialize, Deserialize)]
98pub struct SystemInfo {
99    pub os: String,
100    pub distribution: String,
101    pub kernel: String,
102    pub cpu_model: String,
103    pub memory_gb: f32,
104    pub storage_gb: f32,
105    pub storage_available_gb: f32,
106}
107
108#[derive(Debug, Clone, Copy, PartialEq, Eq)]
109pub enum PreflightStatus {
110    Passed,
111    Warning,
112    Failed,
113}
114
115impl PreflightStatus {
116    pub fn label(self) -> &'static str {
117        match self {
118            PreflightStatus::Passed => "passed",
119            PreflightStatus::Warning => "warning",
120            PreflightStatus::Failed => "failed",
121        }
122    }
123}
124
125#[derive(Debug, Clone, Copy, PartialEq, Eq)]
126pub enum PreflightType {
127    Critical,
128    Warning,
129    Info,
130}
131
132#[derive(Debug, Clone)]
133pub struct PreflightCheck {
134    pub name: String,
135    pub status: PreflightStatus,
136    pub check_type: PreflightType,
137    pub message: String,
138    pub details: String,
139    pub score: i32,
140}
141
142#[derive(Debug, Clone, Default)]
143pub struct PreflightResult {
144    pub passed: bool,
145    pub summary: String,
146    pub checks: Vec<PreflightCheck>,
147    pub passed_count: usize,
148    pub failed_count: usize,
149    pub warning_count: usize,
150    pub total_score: i32,
151    pub can_continue: bool,
152}
153
154#[derive(Debug, Clone, Default)]
155pub struct HardwareState {
156    pub gpu: GPUInfo,
157    pub system: SystemInfo,
158    pub status: String,
159    pub progress: f32,
160}
161
162#[derive(Debug, Clone, Default)]
163pub struct InstallStatus {
164    pub progress: f32,
165    pub message: String,
166    pub completed: bool,
167}
168
169pub fn default_components() -> Vec<Component> {
170    use Category::*;
171
172    vec![
173        // ── Environment ──
174        Component {
175            id: "permanent-env".into(),
176            name: "Permanent ROCm Env".into(),
177            description: "Unified permanent ROCm environment (Python 3.12, \
178                          device-filtered — iGPUs excluded)"
179                .into(),
180            script: String::new(), // Native Rust installer
181            category: Environment,
182            required: false,
183            selected: true,
184            installed: false,
185            progress: 0.0,
186            estimate: "1-2 min".into(),
187            needs_sudo: true,
188            experimental: false,
189            note: Some(
190                "Auto-sourced into bash/zsh/fish on every shell launch when \
191                 installed via the Global option (iGPU filtered, ROCm env always \
192                 active). Isolated/named envs are written but NOT auto-sourced \
193                 into the global shell — source them manually for that env."
194                    .into(),
195            ),
196        },
197        // ── Foundation ──
198        Component {
199            id: "rocm".into(),
200            name: "ROCm Platform".into(),
201            description: "AMD ROCm GPU computing platform".into(),
202            script: String::new(), // Native Rust installer
203            category: Foundation,
204            required: true,
205            selected: true,
206            installed: false,
207            progress: 0.0,
208            estimate: "30-45 min".into(),
209            needs_sudo: true,
210            experimental: false,
211            note: None,
212        },
213        Component {
214            id: "pytorch".into(),
215            name: "PyTorch with ROCm".into(),
216            description: "PyTorch optimized for AMD GPUs".into(),
217            script: String::new(), // Native Rust installer
218            category: Foundation,
219            required: true,
220            selected: true,
221            installed: false,
222            progress: 0.0,
223            estimate: "10-15 min".into(),
224            // pip-install of the ROCm wheel into the managed venv — no system
225            // writes, no sudo. (Was `true`, which made run_installation's sudo
226            // gate spawn `sudo -n true` and leak "a password is required" when
227            // the sudo timestamp lapsed, even though pip never needs root.)
228            needs_sudo: false,
229            experimental: false,
230            note: None,
231        },
232        Component {
233            id: "triton".into(),
234            name: "Triton".into(),
235            description: "Compiler for parallel programming".into(),
236            script: String::new(), // Native Rust installer
237            category: Foundation,
238            required: true,
239            selected: true,
240            installed: false,
241            progress: 0.0,
242            estimate: "5-10 min".into(),
243            // pip-install of the triton wheel — no system writes, no sudo.
244            needs_sudo: false,
245            experimental: false,
246            note: None,
247        },
248        Component {
249            id: "mpi4py".into(),
250            name: "MPI4Py".into(),
251            description: "MPI bindings for Python".into(),
252            script: String::new(), // Native Rust installer
253            category: Foundation,
254            required: true,
255            selected: true,
256            installed: false,
257            progress: 0.0,
258            estimate: "3-5 min".into(),
259            // pip-install against an EXISTING system openmpi (the installer only
260            // reads its path, never apt-installs it). No sudo.
261            needs_sudo: false,
262            experimental: false,
263            note: None,
264        },
265        Component {
266            id: "deepspeed".into(),
267            name: "DeepSpeed".into(),
268            description: "Deep learning optimization library".into(),
269            script: String::new(), // Native Rust installer
270            category: Foundation,
271            required: true,
272            selected: true,
273            installed: false,
274            progress: 0.0,
275            estimate: "8-12 min".into(),
276            // pip-install of the deepspeed wheel — no sudo.
277            needs_sudo: false,
278            experimental: false,
279            note: None,
280        },
281        Component {
282            id: "rocm-smi".into(),
283            name: "ROCm SMI".into(),
284            description: "System monitoring for AMD GPUs".into(),
285            script: String::new(), // Native Rust installer
286            category: Foundation,
287            required: false,
288            selected: true,
289            installed: false,
290            progress: 0.0,
291            estimate: "2-3 min".into(),
292            needs_sudo: true,
293            experimental: false,
294            note: None,
295        },
296        Component {
297            id: "pytorch-profiler".into(),
298            name: "PyTorch Profiler".into(),
299            description: "Performance analysis for PyTorch".into(),
300            script: String::new(), // Native Rust installer
301            category: Foundation,
302            required: false,
303            selected: false,
304            installed: false,
305            progress: 0.0,
306            estimate: "3-5 min".into(),
307            // pip-install of profiler wheels — no sudo.
308            needs_sudo: false,
309            experimental: false,
310            note: None,
311        },
312        // ── Core ──
313        // Flash Attention ships two backends from ROCm/flash-attention. They
314        // install the SAME `flash_attn` package → mutually exclusive; only the
315        // last-installed is active (tracked by ~/.mlstack/flash-attention/.backend).
316        Component {
317            id: "flash-attn-triton".into(),
318            name: "Flash Attention (Triton)".into(),
319            description: "Flash Attention 2 via the ROCm Triton backend".into(),
320            script: String::new(), // Native Rust installer
321            category: Core,
322            required: false,
323            selected: false,
324            installed: false,
325            progress: 0.0,
326            estimate: "20-30 min".into(),
327            // pip build-from-source into the venv — no sudo.
328            needs_sudo: false,
329            experimental: false,
330            note: Some(
331                "Full forward + backward pass — the only Flash Attention backend \
332                 with a backward pass on RDNA3, so it is the choice for \
333                 training/backprop (CDNA + RDNA, fp16/bf16/fp32; causal, MQA/GQA, \
334                 rotary, ALiBi, paged, FP8). Mutually exclusive with Flash Attention \
335                 (CK): both install the identical flash_attn package, so installing \
336                 this replaces CK (the active backend is tracked by the \
337                 ~/.mlstack/flash-attention/.backend marker). Source: ROCm/flash-attention \
338                 Triton backend."
339                    .to_string(),
340            ),
341        },
342        Component {
343            id: "flash-attn-ck".into(),
344            name: "Flash Attention (CK)".into(),
345            description: "Flash Attention 2 via the ROCm composable-kernel backend".into(),
346            script: String::new(), // Native Rust installer
347            category: Core,
348            required: false,
349            selected: false,
350            installed: false,
351            progress: 0.0,
352            estimate: "20-30 min".into(),
353            // pip build-from-source into the venv — no sudo.
354            needs_sudo: false,
355            experimental: true,
356            note: Some(
357                "EXPERIMENTAL — RDNA3 forward-pass only. The composable-kernel \
358                 backward pass is not implemented on RDNA3 \
359                 (ROCm/composable_kernel#1434). Inference, generation, and forward \
360                 attention are accelerated; training/backprop through this backend \
361                 falls back to unfused PyTorch SDPA (higher VRAM, slower). RDNA4 \
362                 gains backward with deterministic=False. Mutually exclusive with \
363                 the Triton backend — installing this replaces it. \
364                 Source: ROCm/flash-attention CK backend."
365                    .to_string(),
366            ),
367        },
368        Component {
369            id: "migraphx".into(),
370            name: "MIGraphX".into(),
371            description: "AMD graph inference engine".into(),
372            script: String::new(), // Native Rust installer
373            category: Core,
374            required: false,
375            selected: false,
376            installed: false,
377            progress: 0.0,
378            estimate: "10-15 min".into(),
379            // prebuilt/wheel install — no sudo.
380            needs_sudo: false,
381            experimental: false,
382            note: None,
383        },
384        Component {
385            // Standalone AMDMIGraphX Python bindings. The C++ core + onnxruntime
386            // MIGraphX EP cover ONNX inference without these bindings, so this is
387            // opt-in (experimental). Must be present in default_components() so
388            // DirectInstallerExecutor::component_for_id can resolve it — the
389            // installer dispatch (installer.rs "migraphx-python" arm) and the
390            // registry/manifest both advertise it; without this entry an explicit
391            // `rusty-stack update migraphx-python` fails with "Unknown component
392            // ID" before reaching the native installer.
393            id: "migraphx-python".into(),
394            name: "MIGraphX Python".into(),
395            description: "AMDMIGraphX Python bindings (source build)".into(),
396            script: String::new(), // Native Rust installer
397            category: Core,
398            required: false,
399            selected: false,
400            installed: false,
401            progress: 0.0,
402            estimate: "15-25 min".into(),
403            // cmake build from source into user space — no sudo.
404            needs_sudo: false,
405            experimental: true,
406            note: Some(
407                "Standalone AMDMIGraphX Python bindings built from source \
408                 (MLSTACK_MIGRAPHX_BUILD_PYTHON=1). The C++ core + onnxruntime \
409                 MIGraphX EP already cover ONNX inference, so these bindings are \
410                 only needed for direct Python migraphx API access. Source: \
411                 ROCm/AMDMIGraphX."
412                    .to_string(),
413            ),
414        },
415        Component {
416            id: "llama-cpp".into(),
417            name: "Rusty Llama (llama.cpp)".into(),
418            description: "Rusty Llama — llama.cpp fork with HIP/ROCm GPU acceleration".into(),
419            script: String::new(), // Native Rust installer
420            category: Core,
421            required: false,
422            selected: false,
423            installed: false,
424            progress: 0.0,
425            estimate: "10-15 min".into(),
426            // cmake build + git clone into user space — no sudo.
427            needs_sudo: false,
428            experimental: false,
429            note: None,
430        },
431        Component {
432            id: "megatron".into(),
433            name: "Megatron-LM".into(),
434            description: "Large-scale training framework".into(),
435            script: String::new(), // Native Rust installer
436            category: Core,
437            required: false,
438            selected: false,
439            installed: false,
440            progress: 0.0,
441            estimate: "25-40 min".into(),
442            // git clone + `pip install -e .` into the managed venv — no sudo.
443            // Same mis-flag as pytorch; flipping stops the spurious sudo prompt.
444            needs_sudo: false,
445            experimental: false,
446            note: None,
447        },
448        Component {
449            id: "aiter".into(),
450            name: "AITER".into(),
451            description: "AMD AITER optimization tooling".into(),
452            script: String::new(), // Native Rust installer
453            category: Core,
454            required: false,
455            selected: false,
456            installed: false,
457            progress: 0.0,
458            estimate: "10-20 min".into(),
459            // pip-install of the aiter wheel — no sudo.
460            needs_sudo: false,
461            experimental: false,
462            note: None,
463        },
464        // ── Extension ──
465        Component {
466            id: "vllm".into(),
467            name: "vLLM".into(),
468            description: "High-throughput inference engine".into(),
469            script: String::new(), // Native Rust installer
470            category: Extension,
471            required: false,
472            selected: false,
473            installed: false,
474            progress: 0.0,
475            estimate: "15-25 min".into(),
476            // pip-install of the vllm wheel — no sudo.
477            needs_sudo: false,
478            experimental: false,
479            note: None,
480        },
481        Component {
482            id: "onnx".into(),
483            name: "ONNX Runtime".into(),
484            description: "Cross-platform inference accelerator".into(),
485            script: String::new(), // Native Rust installer
486            category: Extension,
487            required: false,
488            selected: false,
489            installed: false,
490            progress: 0.0,
491            estimate: "2-5 min".into(),
492            needs_sudo: false,
493            experimental: false,
494            note: None,
495        },
496        Component {
497            id: "bitsandbytes".into(),
498            name: "BITSANDBYTES".into(),
499            description: "Efficient quantization for deep learning".into(),
500            script: String::new(), // Native Rust installer
501            category: Extension,
502            required: false,
503            selected: false,
504            installed: false,
505            progress: 0.0,
506            estimate: "3-5 min".into(),
507            // pip-install of the bitsandbytes wheel — no sudo.
508            needs_sudo: false,
509            experimental: false,
510            note: None,
511        },
512        Component {
513            id: "wandb".into(),
514            name: "Weights & Biases".into(),
515            description: "Experiment tracking and visualization".into(),
516            script: String::new(), // Native Rust installer
517            category: Extension,
518            required: false,
519            selected: false,
520            installed: false,
521            progress: 0.0,
522            estimate: "5-8 min".into(),
523            // pip-install of the wandb wheel — no sudo.
524            needs_sudo: false,
525            experimental: false,
526            note: None,
527        },
528        Component {
529            id: "fastvideo".into(),
530            name: "FastVideo".into(),
531            description: "Video generation framework with ROCm gfx11 optimizations".into(),
532            script: String::new(), // Native Rust installer
533            category: Extension,
534            required: false,
535            selected: false,
536            installed: false,
537            progress: 0.0,
538            estimate: "10-20 min".into(),
539            needs_sudo: false,
540            experimental: false,
541            note: None,
542        },
543        // ── UI/UX ──
544        Component {
545            id: "vllm-studio".into(),
546            name: "vLLM Studio".into(),
547            description: "Model lifecycle manager for vLLM/SGLang".into(),
548            script: String::new(), // Native Rust installer
549            category: UiUx,
550            required: false,
551            selected: false,
552            installed: false,
553            progress: 0.0,
554            estimate: "10-20 min".into(),
555            needs_sudo: false,
556            experimental: false,
557            note: None,
558        },
559        Component {
560            id: "comfyui".into(),
561            name: "ComfyUI".into(),
562            description: "Node-based AI image generation UI with ROCm support".into(),
563            script: String::new(), // Native Rust installer
564            category: UiUx,
565            required: false,
566            selected: false,
567            installed: false,
568            progress: 0.0,
569            estimate: "5-10 min".into(),
570            needs_sudo: false,
571            experimental: false,
572            note: None,
573        },
574        Component {
575            id: "textgen".into(),
576            name: "text-generation-webui".into(),
577            description: "LLM chat/inference web UI with ROCm support (oobabooga)".into(),
578            script: String::new(), // Native Rust installer
579            category: UiUx,
580            required: false,
581            selected: false,
582            installed: false,
583            progress: 0.0,
584            estimate: "10-20 min".into(),
585            needs_sudo: false,
586            experimental: false,
587            note: None,
588        },
589        // ── Maintenance (verify + repair) ──
590        Component {
591            id: "verify-basic".into(),
592            name: "Verify Installation".into(),
593            description: "Basic verification".into(),
594            script: String::new(), // Native Rust verification
595            category: Maintenance,
596            required: false,
597            selected: false,
598            installed: false,
599            progress: 0.0,
600            estimate: "2-5 min".into(),
601            needs_sudo: true,
602            experimental: false,
603            note: None,
604        },
605        Component {
606            id: "verify-enhanced".into(),
607            name: "Enhanced Verify Installation".into(),
608            description: "Advanced verification".into(),
609            script: String::new(), // Native Rust verification
610            category: Maintenance,
611            required: false,
612            selected: false,
613            installed: false,
614            progress: 0.0,
615            estimate: "5-10 min".into(),
616            needs_sudo: true,
617            experimental: false,
618            note: None,
619        },
620        Component {
621            id: "verify-build".into(),
622            name: "Verify and Build".into(),
623            description: "Verify + build components".into(),
624            script: String::new(), // Native Rust verification
625            category: Maintenance,
626            required: false,
627            selected: false,
628            installed: false,
629            progress: 0.0,
630            estimate: "10-15 min".into(),
631            needs_sudo: true,
632            experimental: false,
633            note: None,
634        },
635        Component {
636            id: "repair-stack".into(),
637            name: "Repair ML Stack".into(),
638            description: "Repair ML Stack installation".into(),
639            script: String::new(), // Native Rust installer
640            category: Maintenance,
641            required: false,
642            selected: false,
643            installed: false,
644            progress: 0.0,
645            estimate: "5-10 min".into(),
646            needs_sudo: true,
647            experimental: false,
648            note: None,
649        },
650        Component {
651            id: "rccl-repair".into(),
652            name: "Repair RCCL Multi-GPU".into(),
653            description: "Probe and repair ROCm RCCL multi-GPU collectives".into(),
654            script: String::new(), // Native Rust repair action
655            category: Maintenance,
656            required: false,
657            selected: false,
658            installed: false,
659            progress: 0.0,
660            estimate: "30-90 min".into(),
661            needs_sudo: false,
662            experimental: false,
663            note: None,
664        },
665        // ── Performance (native Rust via benchmark_runners module) ──
666        Component {
667            id: "mlperf-inference".into(),
668            name: "MLPerf Inference".into(),
669            description: "MLPerf benchmark suite for inference performance".into(),
670            script: String::new(), // Native Rust benchmark
671            category: Performance,
672            required: false,
673            selected: false,
674            installed: false,
675            progress: 0.0,
676            estimate: "30-60 min".into(),
677            needs_sudo: false,
678            experimental: false,
679            note: None,
680        },
681        Component {
682            id: "rocm-benchmarks".into(),
683            name: "ROCm Benchmarks".into(),
684            description: "ROCm-specific performance benchmarks".into(),
685            script: String::new(), // Native Rust benchmark
686            category: Performance,
687            required: false,
688            selected: false,
689            installed: false,
690            progress: 0.0,
691            estimate: "20-40 min".into(),
692            needs_sudo: false,
693            experimental: false,
694            note: None,
695        },
696        Component {
697            id: "gpu-memory-bandwidth".into(),
698            name: "GPU Memory Bandwidth".into(),
699            description: "Memory bandwidth performance testing".into(),
700            script: String::new(), // Native Rust benchmark
701            category: Performance,
702            required: false,
703            selected: false,
704            installed: false,
705            progress: 0.0,
706            estimate: "10-15 min".into(),
707            needs_sudo: false,
708            experimental: false,
709            note: None,
710        },
711        Component {
712            id: "rocm-smi-bench".into(),
713            name: "ROCm SMI Benchmarks".into(),
714            description: "ROCm SMI performance monitoring".into(),
715            script: String::new(), // Native Rust benchmark
716            category: Performance,
717            required: false,
718            selected: false,
719            installed: false,
720            progress: 0.0,
721            estimate: "15-25 min".into(),
722            needs_sudo: false,
723            experimental: false,
724            note: None,
725        },
726        Component {
727            id: "vllm-performance".into(),
728            name: "vLLM Performance".into(),
729            description: "High-throughput vLLM inference benchmark".into(),
730            script: String::new(), // Native Rust benchmark
731            category: Performance,
732            required: false,
733            selected: false,
734            installed: false,
735            progress: 0.0,
736            estimate: "15-25 min".into(),
737            needs_sudo: false,
738            experimental: false,
739            note: None,
740        },
741        Component {
742            id: "deepspeed-performance".into(),
743            name: "DeepSpeed Performance".into(),
744            description: "DeepSpeed ZeRO optimization throughput benchmark".into(),
745            script: String::new(), // Native Rust benchmark
746            category: Performance,
747            required: false,
748            selected: false,
749            installed: false,
750            progress: 0.0,
751            estimate: "10-20 min".into(),
752            needs_sudo: false,
753            experimental: false,
754            note: None,
755        },
756        Component {
757            id: "megatron-performance".into(),
758            name: "Megatron-LM Performance".into(),
759            description: "Megatron-LM import and throughput benchmark".into(),
760            script: String::new(), // Native Rust benchmark
761            category: Performance,
762            required: false,
763            selected: false,
764            installed: false,
765            progress: 0.0,
766            estimate: "10-20 min".into(),
767            needs_sudo: false,
768            experimental: false,
769            note: None,
770        },
771        Component {
772            id: "onnx-performance".into(),
773            name: "ONNX Runtime Performance".into(),
774            description: "ONNX Runtime inference benchmark".into(),
775            script: String::new(), // Native Rust benchmark
776            category: Performance,
777            required: false,
778            selected: false,
779            installed: false,
780            progress: 0.0,
781            estimate: "1-2 min".into(),
782            needs_sudo: false,
783            experimental: false,
784            note: None,
785        },
786        Component {
787            id: "flash-attention-ck-performance".into(),
788            name: "Flash Attention (CK) Performance".into(),
789            description: "Genuine-model forward throughput via the CK backend".into(),
790            script: String::new(), // Native Rust benchmark
791            category: Performance,
792            required: false,
793            selected: false,
794            installed: false,
795            progress: 0.0,
796            estimate: "1-2 min".into(),
797            needs_sudo: false,
798            experimental: true,
799            note: Some(
800                "RDNA3 forward-only: measures inference throughput of a genuine \
801                 Llama-style decoder through the composable-kernel flash_attn_func."
802                    .into(),
803            ),
804        },
805        Component {
806            id: "rusty-llama-performance".into(),
807            name: "Rusty Llama Performance".into(),
808            description: "Rusty Llama (llama.cpp) inference benchmark".into(),
809            script: String::new(), // Native Rust benchmark
810            category: Performance,
811            required: false,
812            selected: false,
813            installed: false,
814            progress: 0.0,
815            estimate: "1-2 min".into(),
816            needs_sudo: false,
817            experimental: false,
818            note: Some(
819                "Runs llama-bench against the installed Rusty Llama binary — \
820                 downloads a small verification model if needed, runs NO installs."
821                    .into(),
822            ),
823        },
824        Component {
825            id: "all-benchmarks".into(),
826            name: "Full Suite Benchmark".into(),
827            description: "Run all post-installation performance tests".into(),
828            script: String::new(), // Native Rust benchmark
829            category: Performance,
830            required: false,
831            selected: false,
832            installed: false,
833            progress: 0.0,
834            estimate: "45-90 min".into(),
835            needs_sudo: false,
836            experimental: false,
837            note: None,
838        },
839    ]
840}
841
842#[cfg(test)]
843mod tests {
844    use super::*;
845
846    #[test]
847    fn onnx_performance_is_exposed_as_frontend_benchmark_option() {
848        let component = default_components()
849            .into_iter()
850            .find(|component| component.id == "onnx-performance")
851            .expect("ONNX benchmark should be exposed in component list");
852        assert_eq!(component.category, Category::Performance);
853        assert_eq!(component.name, "ONNX Runtime Performance");
854    }
855}