ra_cli/
lib.rs

1use anyhow::{anyhow, bail, Result};
2use clap::CommandFactory;
3use clap::Parser;
4use std::env;
5
6mod agent;
7mod cli;
8mod constants;
9mod logger;
10mod prompt;
11mod protocol;
12mod run;
13mod tools;
14
15pub fn run_cli() -> Result<()> {
16    let raw_args: Vec<String> = env::args().collect();
17    if raw_args.len() == 1 || (raw_args.len() == 2 && raw_args[1] == "help") {
18        let mut cmd = crate::cli::Args::command();
19        cmd.print_help()?;
20        println!();
21        return Ok(());
22    }
23
24    let args = crate::cli::Args::parse();
25    if args.json && args.stream_json {
26        bail!("--json and --stream-json cannot both be set");
27    }
28    let cwd = crate::run::resolve_and_validate_cwd(&args)
29        .map_err(|e| anyhow!("failed to resolve cwd {}: {}", args.cwd.display(), e))?;
30
31    let api_key = args
32        .api_key
33        .clone()
34        .or_else(|| env::var("OPENROUTER_API_KEY").ok());
35    let api_key = match api_key {
36        Some(key) => key,
37        None => {
38            bail!("missing API key: set --api-key or OPENROUTER_API_KEY");
39        }
40    };
41
42    if api_key.is_empty() {
43        bail!("missing API key: set --api-key or OPENROUTER_API_KEY");
44    }
45
46    let answer = crate::run::run_prompt(&args, &cwd, &api_key)?;
47    if args.stream_json {
48        // In streaming JSON mode, stdout is reserved for JSONL events.
49        return Ok(());
50    }
51    if args.json {
52        // In buffered JSON mode, we print the JSONL stream at the end (and suppress plain output).
53        // The logger is already buffering and will flush to stdout on successful completion.
54        // Note: run_prompt writes events to the buffer; emitting happens there on success/failure.
55        return Ok(());
56    }
57    println!("{answer}");
58    Ok(())
59}