1#![allow(clippy::all, clippy::pedantic, clippy::disallowed_methods)]
10#![allow(
11 unreachable_code,
12 unused_variables,
13 unused_imports,
14 dead_code,
15 unused_assignments
16)]
17
18use clap::{Parser, Subcommand, ValueEnum};
19use std::path::{Path, PathBuf};
20
21#[macro_use]
23#[allow(unused_macros, clippy::duplicated_attributes)]
24mod generated_contracts;
25
26mod commands;
27pub mod error;
28mod output;
29pub mod pipe;
30
31pub use error::CliError;
32
33pub mod qa_types {
35 pub use crate::commands::qa::{GateResult, QaReport, SystemInfo};
36}
37
38pub mod model_pull {
40 pub use crate::commands::pull::{list, run};
41}
42
43#[cfg(feature = "inference")]
44pub mod federation;
45
46use commands::{
48 bench, canary, canary::CanaryCommands, cbtop, chat, compare_hf, compile, convert, data, debug,
49 diagnose, diff, distill, eval, explain, export, flow, hex, import, inspect, lint, mcp, merge,
50 oracle, pipeline, probar, profile, prune, publish, pull, qa, qualify, quantize, rosetta,
51 rosetta::RosettaCommands, run, serve, showcase, stamp, tensors, tokenize, trace, tree, tui,
52 validate, validate_manifest,
53};
54#[cfg(feature = "training")]
55use commands::{finetune, gpu, train, tune};
56
57#[cfg(feature = "training")]
58pub use commands::pretrain::PretrainMode;
59
60#[derive(Parser, Debug)]
65#[command(name = "apr")]
66#[command(author, version = concat!(env!("CARGO_PKG_VERSION"), " (", env!("APR_GIT_SHA"), ")"), about, long_about = None)]
67#[command(propagate_version = true)]
68pub struct Cli {
69 #[command(subcommand)]
70 pub command: Box<Commands>,
71
72 #[arg(long, global = true)]
74 pub json: bool,
75
76 #[arg(short, long, global = true)]
78 pub verbose: bool,
79
80 #[arg(short, long, global = true)]
82 pub quiet: bool,
83
84 #[arg(long, global = true)]
86 pub offline: bool,
87
88 #[arg(long, global = true)]
90 pub skip_contract: bool,
91}
92
93include!("commands_enum.rs");
94include!("model_ops_commands.rs");
95include!("extended_commands.rs");
96include!("tool_commands.rs");
97include!("data_commands.rs");
98#[cfg(feature = "training")]
99include!("train_commands.rs");
100include!("serve_commands.rs");
101include!("tokenize_commands.rs");
102include!("pipeline_commands.rs");
103include!("validate.rs");
104include!("dispatch_run.rs");
105include!("dispatch.rs");
106include!("dispatch_analysis.rs");
107include!("lib_07.rs");
108
109pub fn cli_main() -> std::process::ExitCode {
115 #[cfg(unix)]
117 #[allow(unsafe_code)]
118 unsafe {
119 libc::signal(libc::SIGPIPE, libc::SIG_DFL);
120 }
121
122 #[cfg(target_arch = "aarch64")]
124 #[allow(unsafe_code)]
125 unsafe {
126 let fpcr: u64;
127 core::arch::asm!("mrs {}, fpcr", out(reg) fpcr);
128 if fpcr & (1 << 19) != 0 {
129 let new_fpcr = fpcr & !(1 << 19);
130 core::arch::asm!("msr fpcr, {}", in(reg) new_fpcr);
131 }
132 }
133
134 let no_color = std::env::var("NO_COLOR").is_ok();
136 let is_tty = std::io::IsTerminal::is_terminal(&std::io::stdout());
137 if no_color || !is_tty {
138 colored::control::set_override(false);
139 }
140
141 let raw: Vec<String> = std::env::args().collect();
148 if raw.iter().any(|a| a == "--version") && raw.iter().any(|a| a == "--json") {
149 emit_version_json();
150 return std::process::ExitCode::SUCCESS;
151 }
152
153 let cli = Cli::parse();
154 match execute_command(&cli) {
155 Ok(()) => std::process::ExitCode::SUCCESS,
156 Err(e) => {
157 eprintln!("error: {e}");
158 e.exit_code()
159 }
160 }
161}
162
163pub fn emit_version_json() {
183 let cuda_feature = cfg!(feature = "cuda");
184
185 let cuda_runtime_available = std::process::Command::new("nvidia-smi")
189 .arg("-L")
190 .output()
191 .map(|o| o.status.success())
192 .unwrap_or(false);
193
194 let visible_devices: Vec<String> = if cuda_runtime_available {
198 std::process::Command::new("nvidia-smi")
199 .arg("-L")
200 .output()
201 .ok()
202 .and_then(|o| String::from_utf8(o.stdout).ok())
203 .map(|s| {
204 s.lines()
205 .filter_map(|line| {
206 line.strip_prefix("GPU ").and_then(|rest| {
208 rest.split_once(':').map(|(idx, _)| idx.trim().to_string())
209 })
210 })
211 .collect()
212 })
213 .unwrap_or_default()
214 } else {
215 Vec::new()
216 };
217
218 let body = serde_json::json!({
219 "name": "apr",
220 "version": env!("CARGO_PKG_VERSION"),
221 "git_sha": env!("APR_GIT_SHA"),
222 "cuda_feature": cuda_feature,
223 "cuda_runtime_available": cuda_runtime_available,
224 "visible_devices": visible_devices,
225 });
226
227 println!(
230 "{}",
231 serde_json::to_string_pretty(&body).expect("build version json")
232 );
233}