use clap::{Parser, Subcommand};
use llmsim::cli::{Config, ConfigError};
use llmsim::tui::{run_dashboard, DashboardConfig};
#[derive(Parser)]
#[command(name = "llmsim")]
#[command(author, version, about = "LLM Traffic Simulator", long_about = None)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
Serve {
#[arg(short, long)]
config: Option<String>,
#[arg(short, long, default_value = "8080")]
port: u16,
#[arg(long, default_value = "0.0.0.0")]
host: String,
#[arg(long, default_value = "lorem")]
generator: String,
#[arg(long, default_value = "100")]
target_tokens: usize,
#[arg(long)]
tui: bool,
},
}
fn build_config(
config_file: Option<String>,
port: u16,
host: String,
generator: String,
target_tokens: usize,
) -> Result<Config, ConfigError> {
let mut config = if let Some(path) = config_file {
Config::from_file(&path)?
} else {
Config::default()
};
config.server.port = port;
config.server.host = host;
config.response.generator = generator;
config.response.target_tokens = target_tokens;
Ok(config)
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let cli = Cli::parse();
match cli.command {
Commands::Serve {
config,
port,
host,
generator,
target_tokens,
tui,
} => {
let config = build_config(config, port, host.clone(), generator, target_tokens)?;
if tui {
let stats = llmsim::new_shared_stats();
let server_url = format!("http://127.0.0.1:{}", port);
let dashboard_config = DashboardConfig {
server_url,
refresh_ms: 200,
};
tokio::select! {
result = llmsim::cli::run_server_with_stats(config, stats) => {
result?;
}
result = run_dashboard(dashboard_config) => {
result?;
}
}
} else {
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::from_default_env()
.add_directive("llmsim=info".parse().unwrap())
.add_directive("tower_http=debug".parse().unwrap()),
)
.init();
llmsim::cli::run_server(config).await?;
}
}
}
Ok(())
}