use std::path::PathBuf;
use clap::{CommandFactory, FromArgMatches, Parser};
use rand::Rng;
use tracing::{info, warn};
use jarvish::{engine, logging, shell};
#[derive(Parser)]
#[command(name = "jarvish", version)]
struct Args {
#[arg(long)]
debug: bool,
#[arg(short = 'c', allow_hyphen_values = true)]
command: Option<String>,
}
#[tokio::main]
async fn main() {
dotenvy::dotenv().ok();
let args = Args::from_arg_matches(
&Args::command()
.disable_version_flag(true)
.arg(
clap::Arg::new("version")
.short('v')
.long("version")
.action(clap::ArgAction::Version),
)
.get_matches(),
)
.expect("failed to parse args");
let log_dir_override = if args.debug {
Some(PathBuf::from("./var/logs"))
} else {
None
};
let session_id: i64 = rand::rng().random_range(0..i64::MAX);
let session_key = format!("{:06x}", (session_id as u64) & 0xFFFFFF);
let (_guard, logging_ok) = logging::init_logging(log_dir_override, &session_key);
logging::start_cpu_monitor();
info!(
"\n\n==== J.A.R.V.I.S.H. STARTED at [{}] ====\n",
session_key
);
let mut shell = shell::Shell::new(logging_ok, session_id);
let (exit_code, action) = if let Some(ref command) = args.command {
(shell.run_command(command).await, engine::LoopAction::Exit)
} else {
shell.run().await
};
info!(
"\n\n==== [{}] J.A.R.V.I.S.H. SHUTTING DOWN ====\n\n",
session_key
);
if action == engine::LoopAction::Restart {
drop(_guard);
let err = shell.exec_restart();
warn!(error = %err, "exec_restart failed");
eprintln!("jarvish: restart failed: {err}");
std::process::exit(1);
}
std::process::exit(exit_code);
}