agentic_memory/cli/
repl.rs1use crate::cli::repl_commands;
7use crate::cli::repl_complete;
8use rustyline::config::CompletionType;
9use rustyline::error::ReadlineError;
10use rustyline::{Config, Editor};
11
12fn history_path() -> std::path::PathBuf {
14 let home = std::env::var("HOME")
15 .or_else(|_| std::env::var("USERPROFILE"))
16 .unwrap_or_else(|_| ".".to_string());
17 std::path::PathBuf::from(home).join(".amem_history")
18}
19
20fn print_banner() {
22 eprintln!();
23 eprintln!(
24 " \x1b[32m\u{25c9}\x1b[0m \x1b[1mamem v{}\x1b[0m \x1b[90m\u{2014} Binary Graph Memory for AI Agents\x1b[0m",
25 env!("CARGO_PKG_VERSION")
26 );
27 eprintln!();
28 eprintln!(
29 " Press \x1b[36m/\x1b[0m to browse commands, \x1b[90mTab\x1b[0m to complete, \x1b[90m/exit\x1b[0m to quit."
30 );
31 eprintln!();
32}
33
34pub fn run() -> Result<(), Box<dyn std::error::Error>> {
36 print_banner();
37
38 let config = Config::builder()
39 .history_ignore_space(true)
40 .auto_add_history(true)
41 .completion_type(CompletionType::List)
42 .completion_prompt_limit(20)
43 .build();
44
45 let helper = repl_complete::AmemHelper::new();
46 let mut rl: Editor<repl_complete::AmemHelper, rustyline::history::DefaultHistory> =
47 Editor::with_config(config)?;
48 rl.set_helper(Some(helper));
49 repl_complete::bind_keys(&mut rl);
50
51 let hist_path = history_path();
52 if hist_path.exists() {
53 let _ = rl.load_history(&hist_path);
54 }
55
56 let mut state = repl_commands::ReplState::new();
57 let prompt = " \x1b[36mamem>\x1b[0m ";
58
59 loop {
60 match rl.readline(prompt) {
61 Ok(line) => {
62 let line = line.trim();
63 if line.is_empty() {
64 continue;
65 }
66 match repl_commands::execute(line, &mut state) {
67 Ok(true) => {
68 eprintln!(" \x1b[90m\u{2728}\x1b[0m Goodbye!");
69 break;
70 }
71 Ok(false) => {}
72 Err(e) => {
73 eprintln!(" Error: {e}");
74 }
75 }
76 }
77 Err(ReadlineError::Interrupted) => {
78 eprintln!(" \x1b[90m(Ctrl+C)\x1b[0m Type \x1b[1m/exit\x1b[0m to quit.");
79 }
80 Err(ReadlineError::Eof) => {
81 eprintln!(" \x1b[90m\u{2728}\x1b[0m Goodbye!");
82 break;
83 }
84 Err(err) => {
85 eprintln!(" Error: {err}");
86 break;
87 }
88 }
89 }
90
91 let _ = std::fs::create_dir_all(hist_path.parent().unwrap_or(std::path::Path::new(".")));
92 let _ = rl.save_history(&hist_path);
93
94 Ok(())
95}