154 lines
7.1 KiB
Rust
154 lines
7.1 KiB
Rust
use std::env;
|
|
|
|
fn parse_flag(flag: &str) -> Option<String> {
|
|
let args: Vec<String> = env::args().collect();
|
|
args.iter().position(|a| a == flag).and_then(|i| args.get(i + 1).cloned())
|
|
}
|
|
|
|
// ascii-image-converter -W 30 -b ai.png
|
|
const LOGO: &str = "\
|
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣿⣿⣿⣿⣿⣿⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀
|
|
⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⠟⠉⠀⠀⠀⠀⠉⠻⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀
|
|
⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀
|
|
⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀
|
|
⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀
|
|
⠀⠀⠀⠀⣠⣿⣿⣿⣿⣿⣿⣦⣀⠀⠀⠀⠀⣀⣴⣿⣿⣿⣿⣿⣿⣄⠀⠀⠀⠀
|
|
⠀⠀⢀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⡀⠀⠀
|
|
⠀⠀⠈⠁⠀⠀⠀⠀⠀⠀⠉⠛⠿⠿⠿⠿⠿⠿⠛⠉⠀⠀⠀⠀⠀⠀⠈⠁⠀⠀";
|
|
|
|
fn main() {
|
|
match env::args().nth(1).as_deref() {
|
|
Some("v" | "version" | "--version" | "-v") => {
|
|
println!("{}", env!("CARGO_PKG_VERSION"));
|
|
}
|
|
Some("help" | "--help" | "-h") => print_help(),
|
|
None | Some("tui") => {
|
|
// Show logo before entering alternate screen
|
|
eprintln!("\x1b[38;5;226m{}\x1b[0m\n\x1b[1m aishell\x1b[0m v{}\n",
|
|
LOGO, env!("CARGO_PKG_VERSION"));
|
|
|
|
let config_path = parse_flag("-f");
|
|
if let Err(e) = aishell::tui::run(config_path.as_deref()) {
|
|
eprintln!("aishell: {}", e);
|
|
std::process::exit(1);
|
|
}
|
|
}
|
|
Some("run") => {
|
|
// -p preset
|
|
if let Some(preset_name) = parse_flag("-p") {
|
|
match aishell::config::preset(&preset_name) {
|
|
Some(_) => {
|
|
if let Err(e) = aishell::headless::run_preset(&preset_name) {
|
|
eprintln!("aishell: {e}");
|
|
std::process::exit(1);
|
|
}
|
|
}
|
|
None => {
|
|
eprintln!("unknown preset: {preset_name}");
|
|
eprintln!("available: daily, review, improve");
|
|
std::process::exit(1);
|
|
}
|
|
}
|
|
} else {
|
|
let config_or_task = parse_flag("-f")
|
|
.or_else(|| {
|
|
let all: Vec<String> = env::args().skip(2).collect();
|
|
let mut parts = Vec::new();
|
|
let mut skip = false;
|
|
for a in &all {
|
|
if skip { skip = false; continue; }
|
|
if a == "-c" || a == "-n" || a == "-f" || a == "-p" { skip = true; continue; }
|
|
parts.push(a.clone());
|
|
}
|
|
if parts.is_empty() { None } else { Some(parts.join(" ")) }
|
|
})
|
|
.unwrap_or_else(|| {
|
|
eprintln!("usage: aishell run <task>");
|
|
eprintln!(" aishell run -f <config>");
|
|
eprintln!(" aishell run -p <preset> (daily|review|improve)");
|
|
std::process::exit(1);
|
|
});
|
|
let cwd = parse_flag("-c");
|
|
let name = parse_flag("-n");
|
|
if let Err(e) = aishell::headless::run(&config_or_task, cwd.as_deref(), name.as_deref()) {
|
|
eprintln!("aishell: {e}");
|
|
std::process::exit(1);
|
|
}
|
|
}
|
|
}
|
|
Some("status") => {
|
|
let verbose = env::args().any(|a| a == "-v" || a == "--verbose");
|
|
aishell::headless::status(verbose);
|
|
}
|
|
Some("log") => {
|
|
let id = env::args().nth(2).unwrap_or_else(|| {
|
|
eprintln!("usage: aishell log <id|name>");
|
|
std::process::exit(1);
|
|
});
|
|
aishell::headless::log(&id);
|
|
}
|
|
Some("decision") => aishell::headless::decision(),
|
|
Some("commit") => aishell::headless::commit(),
|
|
Some("context") => aishell::headless::context(),
|
|
Some("remember") => aishell::headless::remember(),
|
|
Some("history") => {
|
|
let sub = env::args().nth(2);
|
|
match sub.as_deref() {
|
|
Some("cmd") => {
|
|
let filter = env::args().nth(3);
|
|
aishell::headless::history_cmd(filter.as_deref());
|
|
}
|
|
Some("clean") => aishell::headless::history_clean(),
|
|
other => aishell::headless::history(other),
|
|
}
|
|
}
|
|
Some("watch") => {
|
|
let dir = env::args().nth(2).unwrap_or_else(|| ".".to_string());
|
|
let config = parse_flag("-f");
|
|
if let Err(e) = aishell::watch::run(&dir, config.as_deref()) {
|
|
eprintln!("aishell: {}", e);
|
|
std::process::exit(1);
|
|
}
|
|
}
|
|
Some("next") => {
|
|
let save: Vec<usize> = env::args().skip(2)
|
|
.filter_map(|s| s.parse().ok())
|
|
.collect();
|
|
aishell::headless::signal_next(save);
|
|
}
|
|
Some("stop") => aishell::headless::signal_quit(),
|
|
Some(cmd) => {
|
|
eprintln!("unknown: {cmd}");
|
|
eprintln!("try: aishell help");
|
|
std::process::exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn print_help() {
|
|
println!("aishell v{}\n", env!("CARGO_PKG_VERSION"));
|
|
println!("USAGE:");
|
|
println!(" aishell TUI (AI + Agents + Shell)");
|
|
println!(" aishell run <task> Run single agent");
|
|
println!(" aishell run -p <preset> Preset: daily, review, improve");
|
|
println!(" aishell run -f <config> Custom config file");
|
|
println!(" aishell commit Git commit with AI-suggested message");
|
|
println!(" aishell status [-v] Show agent status");
|
|
println!(" aishell log <id|name> Show agent output");
|
|
println!(" aishell decision Show AI integration result");
|
|
println!(" aishell context Full project context (for AI)");
|
|
println!(" aishell remember Save latest decision to AI memory");
|
|
println!(" aishell history [id] Show past sessions");
|
|
println!(" aishell history cmd [grep] Command history (filterable)");
|
|
println!(" aishell history clean Remove old sessions (keep 10)");
|
|
println!(" aishell watch <dir> [-f cfg] Watch files, auto-trigger loop");
|
|
println!(" aishell next Resume loop");
|
|
println!(" aishell stop Stop the loop");
|
|
println!(" aishell help This help");
|
|
println!(" aishell v Version");
|
|
}
|