LazyBoy2/crates/grokboy/src/main.rs

91 lines
2.4 KiB
Rust
Raw Normal View History

use anyhow::{Context, Result};
use grokboy_core::{ChatMessage, Config, stream_chat};
use std::io::{self, Write};
use std::process::ExitCode;
const SYSTEM: &str = "You are GrokBoy, a concise local coding assistant. Prefer clear, short answers. Traditional Chinese is welcome when the user writes in Chinese.";
#[tokio::main]
async fn main() -> ExitCode {
if let Err(err) = run().await {
eprintln!("error: {err:#}");
return ExitCode::FAILURE;
}
ExitCode::SUCCESS
}
async fn run() -> Result<()> {
let mut args = std::env::args().skip(1);
let cmd = args.next().unwrap_or_else(|| "help".into());
match cmd.as_str() {
"chat" => cmd_chat().await,
"version" | "-V" | "--version" => {
println!("grokboy {}", env!("CARGO_PKG_VERSION"));
Ok(())
}
"help" | "-h" | "--help" | _ => {
print_help();
Ok(())
}
}
}
fn print_help() {
println!(
"\
GrokBoy minimal local CLI agent (P0: chat)
USAGE:
grokboy chat Interactive streaming chat
grokboy version
grokboy help
ENV:
GROKBOY_API_KEY API key (or XAI_API_KEY / OPENAI_API_KEY)
GROKBOY_BASE_URL default https://api.x.ai/v1
GROKBOY_MODEL default grok-4
P0 has no tools yet. P1 will add shell/files + ReAct.
"
);
}
async fn cmd_chat() -> Result<()> {
let config = Config::from_env().map_err(anyhow::Error::msg)?;
println!(
"GrokBoy chat model={} base={}",
config.model, config.base_url
);
println!("Type a message. Empty line or /exit to quit.\n");
let mut history = vec![ChatMessage::system(SYSTEM)];
let stdin = io::stdin();
let mut stdout = io::stdout();
loop {
print!("you> ");
stdout.flush().ok();
let mut line = String::new();
if stdin.read_line(&mut line).context("stdin")? == 0 {
println!();
break;
}
let input = line.trim();
if input.is_empty() || input == "/exit" || input == "/quit" {
break;
}
history.push(ChatMessage::user(input));
print!("assistant> ");
stdout.flush().ok();
let reply = stream_chat(&config, &history, |delta| {
print!("{delta}");
let _ = io::stdout().flush();
})
.await?;
println!("\n");
history.push(ChatMessage::assistant(reply));
}
Ok(())
}