1use console::{style, Term};
4use indicatif::{ProgressBar, ProgressStyle};
5use std::time::Duration;
6
7pub const CELLSTATE_ASCII: &str = r#"
12 ██████╗ █████╗ ██╗ ██╗██████╗ ███████╗██████╗
13 ██╔════╝██╔══██╗██║ ██║██╔══██╗██╔════╝██╔══██╗
14 ██║ ███████║██║ ██║██████╔╝█████╗ ██████╔╝
15 ██║ ██╔══██║██║ ██║██╔══██╗██╔══╝ ██╔══██╗
16 ╚██████╗██║ ██║███████╗██║██████╔╝███████╗██║ ██║
17 ╚═════╝╚═╝ ╚═╝╚══════╝╚═╝╚═════╝ ╚══════╝╚═╝ ╚═╝
18"#;
19
20pub const TAGLINE: &str = "Agent memory that doesn't forget, lie, or black-box you.";
21
22pub fn print_header() {
24 let term = Term::stdout();
25 let _ = term.clear_screen();
26
27 for line in CELLSTATE_ASCII.lines() {
29 println!("{}", style(line).cyan().bold());
30 }
31 println!(" {}", style(TAGLINE).dim());
32 println!();
33}
34
35pub fn print_banner() {
37 println!("{}", style("◆ CELLSTATE").cyan().bold());
38 println!(" {}", style(TAGLINE).dim());
39 println!();
40}
41
42pub fn ok(msg: &str) {
47 println!(" {} {}", style("✓").green().bold(), msg);
48}
49
50pub fn warn(msg: &str) {
51 println!(" {} {}", style("⚠").yellow().bold(), msg);
52}
53
54pub fn fail(msg: &str) {
55 println!(" {} {}", style("✗").red().bold(), msg);
56}
57
58pub fn info(msg: &str) {
59 println!(" {} {}", style("·").dim(), msg);
60}
61
62pub fn step(msg: &str) {
63 println!();
64 println!("{}", style(msg).bold());
65}
66
67pub fn section(msg: &str) {
68 println!();
69 println!(
70 "{}",
71 style(format!("── {msg} ──────────────────────────────")).dim()
72 );
73 println!();
74}
75
76pub fn success_box(title: &str, lines: &[&str]) {
77 println!();
78 println!(
79 "{}",
80 style("╭─────────────────────────────────────────────────────────╮").green()
81 );
82 println!(
83 "{} {:<57} {}",
84 style("│").green(),
85 style(title).green().bold(),
86 style("│").green()
87 );
88 for line in lines {
89 println!("{} {:<57} {}", style("│").green(), line, style("│").green());
90 }
91 println!(
92 "{}",
93 style("╰─────────────────────────────────────────────────────────╯").green()
94 );
95 println!();
96}
97
98pub fn spinner(msg: &str) -> ProgressBar {
103 let pb = ProgressBar::new_spinner();
104 pb.enable_steady_tick(Duration::from_millis(80));
105 pb.set_style(
106 ProgressStyle::with_template(" {spinner:.cyan} {msg}")
107 .unwrap()
108 .tick_strings(&["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]),
109 );
110 pb.set_message(msg.to_string());
111 pb
112}
113
114pub fn finish_spinner(pb: ProgressBar, msg: &str) {
115 pb.finish_with_message(format!("{} {}", style("✓").green().bold(), msg));
116}
117
118pub fn fail_spinner(pb: ProgressBar, msg: &str) {
119 pb.finish_with_message(format!("{} {}", style("✗").red().bold(), msg));
120}
121
122pub fn kv(key: &str, value: &str) {
127 println!(" {:<20} {}", style(key).dim(), style(value).cyan());
128}
129
130pub fn kv_ok(key: &str, value: &str) {
131 println!(
132 " {:<20} {} {}",
133 style(key).dim(),
134 style("✓").green(),
135 value
136 );
137}
138
139pub fn kv_missing(key: &str) {
140 println!(
141 " {:<20} {}",
142 style(key).dim(),
143 style("not found").dim().italic()
144 );
145}