use std::collections::HashMap;
use std::sync::Arc;
use codex_convert_proxy::cli::{Cli, Commands, StartArgs};
use codex_convert_proxy::config::{BackendRouter, ProxyConfig};
use codex_convert_proxy::logger;
use codex_convert_proxy::proxy::CodexProxy;
use codex_convert_proxy::providers::create_provider;
use codex_convert_proxy::providers::Provider;
use codex_convert_proxy::server;
fn main() {
let cli = Cli::parse_args();
match cli.command {
Commands::Start(args) => {
if let Err(e) = run_proxy(args) {
eprintln!("Error: {}", e);
std::process::exit(1);
}
}
Commands::Init(args) => {
if let Err(e) = generate_config(&args.output) {
eprintln!("Error: {}", e);
std::process::exit(1);
}
}
}
}
fn run_proxy(args: StartArgs) -> anyhow::Result<()> {
let config = args.to_proxy_config()?;
let log_dir = std::path::PathBuf::from(&config.log_dir);
logger::init_logging(&log_dir, config.log_body, true)?;
if config.backends.is_empty() {
anyhow::bail!("No backend configured");
}
let router = Arc::new(BackendRouter::new(config.backends.clone())?);
let listen = &config.listen;
let mut providers: HashMap<String, Arc<dyn Provider>> = HashMap::new();
for backend in &config.backends {
let name = backend.name.clone();
if let std::collections::hash_map::Entry::Vacant(e) = providers.entry(name.clone()) {
match create_provider(&name) {
Ok(p) => {
e.insert(p);
}
Err(e) => {
eprintln!("Warning: Failed to create provider for {}: {}", name, e);
}
}
}
}
eprintln!("Starting Codex Convert Proxy");
eprintln!(" Listen: {}", listen);
eprintln!(" Backends:");
for name in router.backend_names() {
let has_provider = providers.contains_key(name);
eprintln!(" - {} {}", name, if has_provider { "(provider OK)" } else { "(NO PROVIDER)" });
}
eprintln!();
let log_dir = std::path::PathBuf::from(&config.log_dir);
let proxy = CodexProxy::new(router, providers, config.log_body, log_dir);
server::start_proxy_server(proxy, listen);
Ok(())
}
fn generate_config(output: &std::path::Path) -> anyhow::Result<()> {
let config = ProxyConfig::default();
let json = serde_json::to_string_pretty(&config)?;
std::fs::write(output, json)?;
println!("Config file generated: {}", output.display());
println!();
println!("Edit the config file to add your backends.");
Ok(())
}