use clap::{Parser, Subcommand};
use dotenvy::dotenv;
use std::env;
use std::io::Read;
mod files;
mod openai;
mod scan;
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
Scan {
#[arg(required = true)]
pattern: String,
#[arg(long, default_value = "0")]
chunk_size: usize,
#[arg(long, default_value = "0")]
overlap_size: usize,
#[arg(long, default_value = "false")]
embed_metadata: bool,
},
#[command(trailing_var_arg = true)]
Ask {
#[arg(trailing_var_arg = true)]
prompt: Vec<String>,
},
Expand {
#[arg(required = true)]
system_prompt: String,
#[arg(trailing_var_arg = true)]
prompt: Vec<String>,
},
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
dotenv().ok();
let api_key = env::var("OPENAI_API_KEY").expect("OPENAI_API_KEY not found in environment");
let cli = Cli::parse();
match cli.command {
Commands::Scan {
pattern,
chunk_size,
overlap_size,
embed_metadata,
} => {
if chunk_size > 0 && overlap_size >= chunk_size {
eprintln!("Error: overlap_size must be less than chunk_size");
std::process::exit(1);
}
scan::scan_files(&pattern, &api_key, chunk_size, overlap_size, embed_metadata).await?;
}
Commands::Ask { prompt } => {
let prompt_text = if prompt.is_empty() {
let mut buffer = String::new();
std::io::stdin().read_to_string(&mut buffer)?;
buffer.trim().to_string()
} else {
prompt.join(" ")
};
if prompt_text.is_empty() {
eprintln!("Error: No input provided via arguments or stdin");
std::process::exit(1);
}
match openai::get_embedding(&prompt_text, &api_key).await {
Ok(embedding) => {
let _related_files = openai::find_related_files(embedding).await;
}
Err(e) => {
eprintln!("Error getting embedding: {}", e);
}
}
}
Commands::Expand {
prompt,
system_prompt,
} => {
let prompt_text = if prompt.is_empty() {
let mut buffer = String::new();
std::io::stdin().read_line(&mut buffer)?;
buffer
} else {
prompt.join(" ")
};
if !prompt_text.trim().is_empty() {
match openai::get_openai_chat_completion(&prompt_text, &system_prompt, &api_key)
.await
{
Ok(expanded) => println!("{}", expanded),
Err(e) => eprintln!("Error expanding prompt: {}", e),
}
} else {
eprintln!("Error: No prompt provided via arguments or stdin");
std::process::exit(1);
}
}
}
Ok(())
}