#![allow(dead_code)]
#![allow(clippy::boxed_local)]
#![allow(clippy::clone_on_copy)]
#![allow(clippy::collapsible_else_if)]
#![allow(clippy::collapsible_if)]
#![allow(clippy::explicit_auto_deref)]
#![allow(clippy::filter_map_bool_then)]
#![allow(clippy::manual_clamp)]
#![allow(clippy::manual_range_contains)]
#![allow(clippy::manual_unwrap_or)]
#![allow(clippy::needless_return)]
#![allow(clippy::should_implement_trait)]
#![allow(clippy::too_many_arguments)]
#![allow(clippy::type_complexity)]
#![allow(clippy::unnecessary_map_or)]
#[macro_use]
pub mod ui;
mod agent;
mod batch;
mod cmd;
mod config;
mod cost;
mod prompt;
mod store;
mod types;
mod typesafe;
mod cli;
mod support;
mod runtime;
mod routing;
mod task;
mod workspace;
use crate::cli::{Cli, Commands};
use anyhow::Result;
use std::sync::Arc;
fn main() -> Result<()> {
let result = run_cli(cli::diagnostics::parse());
if let Err(error) = &result {
cli::diagnostics::record_error(error);
}
result
}
fn run_cli(cli: Cli) -> Result<()> {
if let Some(Commands::Errors(args)) = cli.command.as_ref() {
return cli::diagnostics::show(args);
}
if matches!(cli.command.as_ref(), Some(Commands::InternalRunTask(_)))
&& runtime::background::daemonize_worker_if_requested()?
{
return Ok(());
}
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()?
.block_on(async_main(cli))
}
async fn async_main(cli: Cli) -> Result<()> {
ui::output::init();
if cli.quiet {
ui::output::set_quiet(true);
}
let command = match cli.command {
Some(Commands::Advise(args)) => {
if support::paths::db_path().exists() {
cost::maybe_refresh_prices();
}
let store = store::Store::open_read_only(&support::paths::db_path())?;
cmd::advise::run(store.as_ref(), args)?;
return Ok(());
}
Some(Commands::Classify(args)) => std::process::exit(cmd::classify::run(args)),
other => other,
};
support::paths::ensure_dirs()?;
let config = config::load_config().unwrap_or_default();
if config.updates.check {
support::update_check::maybe_check_update();
}
cost::maybe_refresh_prices();
let store = Arc::new(store::Store::open(&support::paths::db_path())?);
cost::warm_gemini_default_from_store(store.as_ref());
let _ = runtime::background::check_zombie_tasks(&store);
let outcome = match command {
Some(command) => cli::dispatch::dispatch(store.clone(), command).await?,
None => cli::dispatch::dispatch(store.clone(), Commands::Board(Default::default())).await?,
};
if let Some(run_status) = outcome.run_exit_status(store.as_ref())? {
println!("{}", run_status.summary_line());
if run_status.exit_code() != 0 {
std::process::exit(run_status.exit_code());
}
}
Ok(())
}