1use clap::Parser;
2use oy_agent::infrastructure::tools::edit::EditTool;
3use oy_agent::infrastructure::tools::read::ReadTool;
4use oy_agent::infrastructure::tools::write::WriteTool;
5use oy_agent::infrastructure::tools::{ToolRegistry, bash::BashTool};
6use oy_ai::AiConfig;
7use serde::Deserialize;
8use std::env;
9
10#[derive(Parser, Debug)]
12#[command(author, version, about)]
13pub struct CliArgs {
14 #[arg(short = 'p', long)]
16 pub prompt: Option<String>,
17
18 #[arg(short = 'm', long)]
19 pub model: Option<String>,
20}
21
22#[derive(Debug, Deserialize, Default)]
24pub struct CliConfig {
25 pub api_key: Option<String>,
26 pub base_url: Option<String>,
27 pub model: Option<String>,
28}
29
30impl CliConfig {
31 pub fn load() -> Self {
33 let home = match dirs::home_dir() {
34 Some(h) => h,
35 None => return Self::default(),
36 };
37 let config_path = home.join(".oy-ai-agent").join("config.toml");
38 if !config_path.exists() {
39 return Self::default();
40 }
41 match std::fs::read_to_string(&config_path) {
42 Ok(content) => toml::from_str(&content).unwrap_or_default(),
43 Err(_) => Self::default(),
44 }
45 }
46}
47
48pub fn build_provider_config(cli_config: &CliConfig, cli_args: &CliArgs) -> AiConfig {
58 let api_key = cli_config
59 .api_key
60 .clone()
61 .or_else(|| env::var("OPENROUTER_API_KEY").ok())
62 .unwrap_or_else(|| {
63 eprintln!(
64 "OPENROUTER_API_KEY is not set. Set it in ~/.oy-ai-agent/config.toml \
65 or the OPENROUTER_API_KEY environment variable."
66 );
67 std::process::exit(1);
68 });
69
70 let base_url = cli_config
71 .base_url
72 .clone()
73 .or_else(|| env::var("OPENROUTER_BASE_URL").ok())
74 .unwrap_or_else(|| "https://openrouter.ai/api/v1".to_string());
75
76 let model = cli_args
77 .model
78 .clone()
79 .or_else(|| cli_config.model.clone())
80 .or_else(|| env::var("OPENROUTER_MODEL").ok())
81 .unwrap_or_else(|| "anthropic/claude-haiku-4.5".to_string());
82
83 AiConfig::new(base_url, api_key, model)
84}
85
86pub fn register_default_tools(registry: &mut ToolRegistry) {
88 registry.register(ReadTool);
89 registry.register(WriteTool);
90 registry.register(EditTool);
91 registry.register(BashTool);
92}
93
94pub async fn run(args: CliArgs) -> Result<(), anyhow::Error> {
96 if args.prompt.is_none() {
98 oy_tui::run_tui()
99 .await
100 .map_err(|e| anyhow::Error::msg(format!("{}", e)))?;
101 return Ok(());
102 }
103
104 Ok(())
105}