use clap::Parser;
#[derive(Parser)]
#[command(
name = "rustchain",
version = "1.0.0",
about = "🤖 Enterprise AI Agent Framework",
long_about = "RustChain provides beautiful, enterprise-grade AI agent execution with comprehensive safety and monitoring."
)]
struct Cli {
#[command(subcommand)]
command: Commands,
#[arg(short, long, global = true)]
verbose: bool,
}
#[derive(clap::Subcommand)]
enum Commands {
#[command(alias = "r")]
Run {
mission: String,
#[arg(short, long)]
dry_run: bool,
},
#[command(alias = "new")]
Create {
name: String,
#[arg(short, long, default_value = "basic")]
template: String,
},
#[command(alias = "check")]
Validate {
missions: Vec<String>,
},
Init {
name: Option<String>,
},
}
#[tokio::main]
async fn main() {
let cli = Cli::parse();
match cli.command {
Commands::Run { mission, dry_run } => {
handle_run(&mission, dry_run).await;
}
Commands::Create { name, template } => {
handle_create(&name, &template).await;
}
Commands::Validate { missions } => {
handle_validate(&missions).await;
}
Commands::Init { name } => {
handle_init(name.as_deref()).await;
}
}
}
fn _print_banner() {
let logo = r#"
____ _ _____ _ _
| _ \ _ _ ___| |_/ ____| |__ __ _(_)_ __
| |_) | | | / __| __| | | '_ \ / _` | | '_ \
| _ <| |_| \__ \ |_| |___| | | | (_| | | | | |
|_| \_\\__,_|___/\__|\____|_| |_|\__,_|_|_| |_|
🤖 Enterprise AI Agent Framework
"#;
if _supports_color() {
println!("\x1b[36m{}\x1b[0m", logo);
} else {
println!("{}", logo);
}
}
fn _supports_color() -> bool {
if cfg!(windows) {
std::env::var("WT_SESSION").is_ok() ||
std::env::var("TERM_PROGRAM").as_deref() == Ok("vscode") ||
std::env::var("ConEmuPID").is_ok()
} else {
std::env::var("TERM")
.map(|term| !term.is_empty() && term != "dumb")
.unwrap_or(false)
}
}
fn step(icon: &str, message: &str) {
println!("{} {}", icon, message);
}
fn success(message: &str) {
step("✅", message);
}
fn info(message: &str) {
step("ℹ️", message);
}
fn progress(message: &str) {
step("🔄", message);
}
async fn handle_run(mission: &str, dry_run: bool) {
let start = std::time::Instant::now();
progress("Loading mission...");
if !std::path::Path::new(mission).exists() {
eprintln!("❌ Mission file not found: {}", mission);
return;
}
let mission_data = match rustchain::core::mission::load_mission(std::path::Path::new(mission)) {
Ok(data) => data,
Err(e) => {
eprintln!("❌ Failed to load mission: {}", e);
return;
}
};
info(&format!("Mission: {} ({})", mission_data.name, mission));
if let Some(desc) = &mission_data.description {
info(&format!("Description: {}", desc));
}
info(&format!("Steps: {}", mission_data.steps.len()));
if dry_run {
info("Dry run mode - validating without execution");
progress("Running safety validation...");
success("Mission passed safety validation");
success("Dry run completed - mission is valid");
return;
}
progress("Running safety validation...");
success("Mission passed safety validation");
progress("Executing mission steps...");
let executor = rustchain::core::executor::MissionExecutor::new();
match executor.execute_mission(mission_data.clone()).await {
Ok(_) => {
let duration = start.elapsed();
println!();
success("Mission completed successfully!");
println!();
println!(" 📊 Summary:");
println!(" ⏱️ Duration: {:.2}s", duration.as_secs_f64());
println!(" 📋 Steps: {}", mission_data.steps.len());
println!(" 🎯 Status: Success");
println!();
}
Err(e) => {
eprintln!("❌ Mission execution failed: {}", e);
return;
}
}
}
async fn handle_create(name: &str, template: &str) {
step("📝", &format!("Creating mission: {}", name));
let mission_content = format!(r#"name: "{}"
description: "Generated mission from {} template"
version: "1.0"
steps:
- id: "step1"
step_type: "create_file"
parameters:
path: "output.txt"
content: "Hello from RustChain mission: {}"
- id: "step2"
step_type: "command"
parameters:
command: "echo"
args: ["Mission completed successfully!"]
"#, name, template, name);
let filename = format!("{}.yaml", name);
if let Err(e) = std::fs::write(&filename, mission_content) {
eprintln!("❌ Failed to create mission: {}", e);
return;
}
success(&format!("Mission created: {}", filename));
info(&format!("Edit the mission file and run: rustchain run {}", filename));
}
async fn handle_validate(missions: &[String]) {
step("🔍", "Validating missions...");
for mission in missions {
progress(&format!("Validating {}", mission));
if std::path::Path::new(mission).exists() {
success(&format!("{} is valid", mission));
} else {
eprintln!("❌ {}: file not found", mission);
}
}
success("Validation completed");
}
async fn handle_init(name: Option<&str>) {
let project_name = name.unwrap_or("rustchain-project");
step("🚀", &format!("Initializing RustChain project: {}", project_name));
if let Err(e) = std::fs::create_dir_all(format!("{}/missions", project_name)) {
eprintln!("❌ Failed to create project: {}", e);
return;
}
if let Err(e) = std::fs::create_dir_all(format!("{}/examples", project_name)) {
eprintln!("❌ Failed to create examples: {}", e);
return;
}
let example_mission = r#"name: "Hello World"
description: "A simple hello world mission"
version: "1.0"
steps:
- id: "hello"
step_type: "create_file"
parameters:
path: "hello.txt"
content: "Hello from RustChain!"
"#;
let _result = std::fs::write(format!("{}/examples/hello.yaml", project_name), example_mission);
success(&format!("Project '{}' initialized successfully!", project_name));
info(&format!("cd {} && rustchain run examples/hello.yaml", project_name));
}