use anyhow::Result;
use inferno::{
cli::{Commands, enhanced_parser::EnhancedCliParser, help::HelpSystem},
config::Config,
upgrade::{
ApplicationVersion, background_service::BackgroundUpdateService, init_upgrade_system,
},
};
use std::sync::Arc;
use tokio::sync::broadcast;
use tracing::{error, info, warn};
use tracing_subscriber::{EnvFilter, fmt};
#[tokio::main]
async fn main() -> Result<()> {
let cli = match EnhancedCliParser::try_parse() {
Ok(cli) => cli,
Err(e) => {
if e.kind() == clap::error::ErrorKind::DisplayHelp
|| e.kind() == clap::error::ErrorKind::DisplayVersion
{
e.exit();
}
eprintln!("{}", e);
eprintln!("\n💡 For help with commands, try:");
eprintln!(" inferno --help");
eprintln!(" inferno [command] --help");
std::process::exit(e.exit_code());
}
};
let config = Config::load().unwrap_or_else(|e| {
eprintln!("Warning: Failed to load config: {}", e);
Config::default()
});
setup_logging();
info!(
"Starting Inferno AI/ML model runner v{}",
std::env::var("CARGO_PKG_VERSION").unwrap_or_else(|_| "0.1.0".to_string())
);
let background_service = if should_start_background_service(&cli.command) {
match init_background_update_service(&config).await {
Ok(service) => {
info!("Background update service initialized");
Some(service)
}
Err(e) => {
warn!("Failed to initialize background update service: {}", e);
None
}
}
} else {
None
};
let result = match cli.command {
Commands::Run(args) => inferno::cli::run::execute(args, &config).await,
Commands::Batch(args) => inferno::cli::batch::execute(args, &config).await,
Commands::Serve(args) => inferno::cli::serve::execute(args, &config).await,
Commands::Models(args) => inferno::cli::models::execute(args, &config).await,
Commands::Metrics(args) => inferno::cli::metrics::execute(args, &config).await,
Commands::Bench(args) => inferno::cli::bench::execute(args, &config).await,
Commands::Validate(args) => inferno::cli::validate::execute(args, &config).await,
Commands::Config(args) => inferno::cli::config::handle_config_command(args).await,
Commands::Cache(args) => inferno::cli::cache::execute(args, &config).await,
Commands::Convert(args) => inferno::cli::convert::execute(args, &config).await,
Commands::ResponseCache(args) => inferno::cli::response_cache::execute(args, &config).await,
Commands::Monitor(args) => inferno::cli::monitoring::execute(args, &config).await,
Commands::Distributed(args) => inferno::cli::distributed::execute(args, &config).await,
Commands::ABTest(args) => inferno::cli::ab_testing::execute(args, &config).await,
Commands::Audit(args) => inferno::cli::audit::execute(args, &config).await,
Commands::Queue(args) => inferno::cli::batch_queue::execute(args, &config).await,
Commands::Version(args) => inferno::cli::versioning::execute(args, &config).await,
Commands::Gpu(args) => inferno::cli::gpu::execute(args, &config).await,
Commands::Resilience(args) => inferno::cli::resilience::execute(args, &config).await,
Commands::Streaming(args) => inferno::cli::streaming::execute(args, &config).await,
Commands::Security(args) => inferno::cli::security::execute(args, &config).await,
Commands::Observability(args) => inferno::cli::observability::execute(args, &config).await,
Commands::Optimization(args) => {
inferno::cli::optimization::execute_optimization_command(args).await
}
Commands::MultiModal(args) => inferno::cli::multimodal::handle_multimodal_command(args)
.await
.map_err(|e| anyhow::anyhow!(e)),
Commands::Deployment(args) => {
inferno::cli::deployment::handle_deployment_command(args).await
}
Commands::Marketplace(args) => {
inferno::cli::marketplace::handle_marketplace_command(args).await
}
Commands::Package(args) => inferno::cli::package::handle_package_command(args).await,
Commands::Install(args) => inferno::cli::package::handle_install_simple(args).await,
Commands::Remove(args) => inferno::cli::package::handle_remove_simple(args).await,
Commands::Search(args) => inferno::cli::package::handle_search_simple(args).await,
Commands::List(args) => inferno::cli::package::handle_list_simple(args).await,
Commands::Repo(args) => inferno::cli::repo::handle_repo_command(args).await,
Commands::Dashboard(args) => inferno::cli::dashboard::handle_dashboard_command(args).await,
Commands::AdvancedMonitoring(args) => {
inferno::cli::advanced_monitoring::execute(args, &config).await
}
Commands::ModelVersioning(args) => {
inferno::cli::model_versioning::execute(args, &config).await
}
Commands::BackupRecovery(args) => {
inferno::cli::backup_recovery::execute(args, &config).await
}
Commands::LoggingAudit(args) => inferno::cli::logging_audit::execute(args, &config).await,
Commands::PerformanceOptimization(args) => {
inferno::cli::performance_optimization::execute(args, &config).await
}
Commands::AdvancedCache(args) => inferno::cli::advanced_cache::execute(args, &config).await,
Commands::PerformanceBenchmark(args) => {
inferno::cli::performance_benchmark::execute_performance_benchmark(args).await
}
Commands::Upgrade(args) => inferno::cli::upgrade::execute(args, &config).await,
Commands::Tui => inferno::tui::launch(&config).await,
};
if let Err(e) = result {
if let Some(service) = background_service {
if let Err(stop_err) = service.stop().await {
warn!("Failed to stop background service: {}", stop_err);
}
}
let helpful_message = HelpSystem::handle_error(&e);
eprintln!("{}", helpful_message);
error!("Command failed: {}", e);
std::process::exit(1);
}
Ok(())
}
fn should_start_background_service(command: &Commands) -> bool {
matches!(
command,
Commands::Serve(_) | Commands::Tui | Commands::Dashboard(_) )
}
async fn init_background_update_service(config: &Config) -> Result<BackgroundUpdateService> {
let upgrade_manager = match init_upgrade_system(config).await {
Ok(manager) => Arc::new(manager),
Err(e) => {
warn!("Failed to initialize upgrade system: {}", e);
return Err(e);
}
};
let (event_sender, _) = broadcast::channel(1000);
let upgrade_config = match inferno::upgrade::config::UpgradeConfig::from_config(config) {
Ok(config) => config,
Err(e) => {
warn!("Failed to load upgrade config, using defaults: {}", e);
inferno::upgrade::config::UpgradeConfig::default()
}
};
let service = BackgroundUpdateService::new(upgrade_manager, upgrade_config, event_sender);
let service_handle = service.clone();
tokio::spawn(async move {
if let Err(e) = service_handle.start().await {
error!("Background update service failed: {}", e);
}
});
info!(
"Background update service started for {}",
ApplicationVersion::current().to_string()
);
Ok(service)
}
fn setup_logging() {
let subscriber = fmt::Subscriber::builder()
.with_env_filter(
EnvFilter::from_default_env()
.add_directive("inferno=info".parse().unwrap())
.add_directive("warn".parse().unwrap()),
)
.with_target(false)
.with_thread_ids(true)
.with_file(true)
.with_line_number(true)
.finish();
tracing::subscriber::set_global_default(subscriber)
.expect("Failed to initialize tracing subscriber");
}