#![allow(clippy::unwrap_used)]
use std::io::{self, BufRead, Write};
use std::sync::Arc;
use loopctl::config::SessionConfig;
use loopctl::engine::BareLoop;
use loopctl::engine::RunConfig;
use loopctl::engine::core::Loop;
use loopctl::testing::MockApiClient;
use loopctl::tool::ToolRegistry;
#[tokio::main]
async fn main() {
let stdin = io::stdin();
let mut stdout = io::stdout();
loop {
write!(&mut stdout, "> ").unwrap();
stdout.flush().unwrap();
let mut input = String::new();
if stdin.lock().read_line(&mut input).unwrap_or(0) == 0 {
break; }
let input = input.trim();
if input.is_empty() {
continue;
}
if input == "quit" || input == "exit" {
break;
}
let client =
MockApiClient::new("repl-model").with_text_response(&format!("You said: {input}"));
let mut agent = BareLoop::new(
Arc::new(client),
ToolRegistry::new(),
SessionConfig::default(),
);
let cancel_signal = agent.cancel_signal();
let listener = tokio::spawn(async move {
if tokio::signal::ctrl_c().await.is_ok() {
cancel_signal.cancel();
}
});
match agent.run(input, &RunConfig::default()).await {
Ok(result) => {
listener.abort();
let output = result.output.unwrap_or_default();
writeln!(&mut stdout, "{output}\n").unwrap();
}
Err(e) => {
listener.abort();
writeln!(&mut stdout, "Error: {e}\n").unwrap();
}
}
}
writeln!(&mut stdout, "Goodbye!").unwrap();
}