1use crate::{
2 cli::{Cli, Command, ConfigCommand, ConnectionCommand},
3 commands, config, interactive,
4};
5use std::{io::IsTerminal, path::Path};
6
7pub fn run(cli: Cli) -> i32 {
8 match dispatch(cli) {
9 Ok(code) => code,
10 Err(error) => {
11 eprintln!("Error: {error}");
12 2
13 }
14 }
15}
16
17fn dispatch(cli: Cli) -> Result<i32, Box<dyn std::error::Error>> {
18 let Some(command) = cli.command.clone() else {
19 if cli.options.non_interactive {
20 return Err("non-interactive mode requires a subcommand".into());
21 }
22 return interactive::run(cli);
23 };
24 if matches!(
25 &command,
26 Command::Config {
27 command: ConfigCommand::Init
28 }
29 ) {
30 return commands::run_config_init(cli.options.format.into());
31 }
32 if cli.options.verbose {
37 crate::agent::extraction_trace::enable();
38 }
39 let options = command_options(&cli.options, &command);
40 let runtime = config::runtime::load(&options, Path::new("."))?;
41 let approval = config::runtime::approval_mode(&options)?;
42 let format = config::runtime::format_name(&options, &runtime.resolved);
43 let can_prompt = !options.non_interactive && std::io::stdin().is_terminal();
44 tokio::runtime::Builder::new_current_thread()
45 .enable_all()
46 .build()?
47 .block_on(commands::run(
48 command,
49 &runtime,
50 format,
51 approval,
52 can_prompt,
53 options.include_profiles.clone(),
54 ))
55}
56
57fn command_options(
58 options: &crate::cli::GlobalOptions,
59 command: &Command,
60) -> crate::cli::GlobalOptions {
61 let mut options = options.clone();
62 if options.profile.is_none() {
63 let profile = match command {
64 Command::Connection {
65 command:
66 ConnectionCommand::Test { profile_name }
67 | ConnectionCommand::Schema { profile_name, .. },
68 } => Some(profile_name.clone()),
69 _ => None,
70 };
71 options.profile = profile;
72 }
73 options
74}