mod commands;
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(name = "jammi", version, about = "Jammi AI — inference engine CLI")]
struct Cli {
#[arg(long, global = true)]
config: Option<String>,
#[command(subcommand)]
command: Option<Commands>,
}
#[derive(Subcommand)]
enum Commands {
Serve,
Sources {
#[command(subcommand)]
action: commands::sources::SourceAction,
},
Models {
#[command(subcommand)]
action: commands::models::ModelAction,
},
Query {
sql: String,
},
Explain {
sql: String,
},
}
#[tokio::main]
async fn main() {
let cli = Cli::parse();
let config_path = cli.config.as_deref();
if let Err(e) = run(cli.command, config_path).await {
eprintln!("Error: {e}");
std::process::exit(1);
}
}
async fn run(
command: Option<Commands>,
config_path: Option<&str>,
) -> Result<(), Box<dyn std::error::Error>> {
let config = jammi_engine::config::JammiConfig::load(config_path.map(std::path::Path::new))?;
match command {
Some(Commands::Serve) => commands::serve::run(config).await,
Some(Commands::Sources { action }) => commands::sources::run(config, action).await,
Some(Commands::Models { action }) => commands::models::run(config, action).await,
Some(Commands::Query { sql }) => commands::query::run(config, &sql).await,
Some(Commands::Explain { sql }) => commands::query::explain(config, &sql).await,
None => {
use clap::CommandFactory;
Cli::command().print_help()?;
println!();
Ok(())
}
}
}