use std::io::{self, Write};
use std::time::Instant;
pub struct PrettyOutput {
start_time: Instant,
supports_color: bool,
}
impl PrettyOutput {
pub fn new() -> Self {
Self {
start_time: Instant::now(),
supports_color: supports_color(),
}
}
pub fn banner(&self) {
let logo = r#"
____ _ _____ _ _
| _ \ _ _ ___| |_/ ____| |__ __ _(_)_ __
| |_) | | | / __| __| | | '_ \ / _` | | '_ \
| _ <| |_| \__ \ |_| |___| | | | (_| | | | | |
|_| \_\\__,_|___/\__|\____|_| |_|\__,_|_|_| |_|
đ¤ Enterprise AI Agent Framework
"#;
if self.supports_color {
println!("{}", self.cyan(logo));
} else {
println!("{}", logo);
}
}
pub fn step(&self, icon: &str, message: &str) {
let formatted = if self.supports_color {
format!("{} {}", icon, self.white(message))
} else {
format!("{} {}", icon, message)
};
println!("{}", formatted);
let _ = io::stdout().flush();
}
pub fn success(&self, message: &str) {
self.step("â
", message);
}
pub fn info(&self, message: &str) {
self.step("âšī¸", message);
}
pub fn warning(&self, message: &str) {
self.step("â ī¸", message);
}
pub fn error(&self, message: &str) {
self.step("â", message);
}
pub fn progress(&self, message: &str) {
self.step("đ", message);
}
pub fn completion_summary(&self, mission_name: &str, duration_secs: f64, steps: usize, status: &str) {
println!();
self.success(&format!("Mission '{}' completed!", mission_name));
println!();
let summary = format!(
" đ Summary:\n âąī¸ Duration: {:.2}s\n đ Steps: {}\n đ¯ Status: {}",
duration_secs, steps, status
);
if self.supports_color {
println!("{}", self.dim(&summary));
} else {
println!("{}", summary);
}
println!();
}
pub fn mission_start(&self, mission_name: &str, description: &str) {
println!();
self.step("đ", &format!("Executing mission: {}", mission_name));
if !description.is_empty() {
if self.supports_color {
println!(" {}", self.dim(description));
} else {
println!(" {}", description);
}
}
println!();
}
pub fn divider(&self) {
if self.supports_color {
println!("{}", self.dim("ââââââââââââââââââââââââââââââââââââââââ"));
} else {
println!("ââââââââââââââââââââââââââââââââââââââââ");
}
}
fn cyan(&self, text: &str) -> String {
if self.supports_color {
format!("\x1b[36m{}\x1b[0m", text)
} else {
text.to_string()
}
}
fn white(&self, text: &str) -> String {
if self.supports_color {
format!("\x1b[37m{}\x1b[0m", text)
} else {
text.to_string()
}
}
fn dim(&self, text: &str) -> String {
if self.supports_color {
format!("\x1b[2m{}\x1b[0m", text)
} else {
text.to_string()
}
}
}
impl Default for PrettyOutput {
fn default() -> Self {
Self::new()
}
}
fn supports_color_simple() -> bool {
if cfg!(windows) {
std::env::var("WT_SESSION").is_ok() || std::env::var("TERM_PROGRAM").as_deref() == Ok("vscode") || std::env::var("ConEmuPID").is_ok() || std::env::var("ANSICON").is_ok() } else {
std::env::var("TERM")
.map(|term| !term.is_empty() && term != "dumb")
.unwrap_or(false)
}
}
fn supports_color() -> bool {
supports_color_simple()
}