use anyhow::Result;
use clap::Parser;
use tracing_subscriber::{EnvFilter, fmt, prelude::*};
mod banner;
mod cli;
mod commands;
mod mcp;
mod update;
use cli::Cli;
#[tokio::main]
async fn main() -> Result<()> {
let cli = Cli::parse();
let filter = if cli.verbose > 0 {
match cli.verbose {
1 => "rigg=debug",
_ => "rigg=trace,rigg_client=debug",
}
} else if cli.quiet {
"error"
} else {
"rigg=info"
};
tracing_subscriber::registry()
.with(fmt::layer().with_target(false).without_time())
.with(EnvFilter::new(filter))
.init();
if cli.no_color {
colored::control::set_override(false);
}
let is_mcp = matches!(cli.command, cli::Commands::Mcp(_));
let check_update = if cli.quiet || is_mcp || std::env::var_os("RIGG_NO_UPDATE_CHECK").is_some()
{
None
} else {
Some(tokio::spawn(update::check_for_update()))
};
let result = cli.run().await;
if let Some(handle) = check_update {
if let Ok(Some(message)) = handle.await {
eprintln!();
eprintln!("{message}");
}
}
match result {
Ok(()) => Ok(()),
Err(err) => {
if let Some(client_err) = err.downcast_ref::<rigg_client::ClientError>() {
eprintln!();
eprintln!("Error: {}", client_err);
eprintln!();
for line in client_err.suggestion().lines() {
eprintln!(" {}", line);
}
write_error_log(client_err);
std::process::exit(1);
}
Err(err)
}
}
}
fn write_error_log(err: &rigg_client::ClientError) {
use std::io::Write;
let timestamp = chrono::Local::now().format("%Y-%m-%d %H:%M:%S");
let mut lines = Vec::new();
lines.push(format!("[{}] Error: {}", timestamp, err));
{
use std::error::Error;
let mut source = err.source();
while let Some(cause) = source {
lines.push(format!(" Caused by: {}", cause));
source = cause.source();
}
}
if let Some(body) = err.raw_body() {
if !body.is_empty() {
lines.push(format!("Response body: {}", body));
}
}
lines.push(format!("Suggestion: {}", err.suggestion()));
lines.push(String::new());
match std::fs::OpenOptions::new()
.create(true)
.append(true)
.open("rigg-error.log")
{
Ok(mut file) => {
for line in &lines {
let _ = writeln!(file, "{}", line);
}
eprintln!(" Error details written to rigg-error.log");
}
Err(_) => {
if let Some(body) = err.raw_body() {
if !body.is_empty() {
eprintln!(" Response: {}", body);
}
}
}
}
}