ai-agent 0.88.0

Idiomatic agent sdk inspired by the claude code source leak
Documentation
use std::io::{self, Write};

pub enum LogLevel {
    Debug,
    Info,
    Warning,
    Error,
}

impl LogLevel {
    fn to_string(&self) -> &str {
        match self {
            LogLevel::Debug => "DEBUG",
            LogLevel::Info => "INFO",
            LogLevel::Warning => "WARN",
            LogLevel::Error => "ERROR",
        }
    }
}

pub struct Logger {
    level: LogLevel,
    prefix: String,
}

impl Logger {
    pub fn new() -> Self {
        Logger {
            level: LogLevel::Info,
            prefix: String::new(),
        }
    }

    pub fn with_prefix(mut self, prefix: &str) -> Self {
        self.prefix = prefix.to_string();
        self
    }

    pub fn with_level(mut self, level: LogLevel) -> Self {
        self.level = level;
        self
    }

    fn should_log(&self, level: &LogLevel) -> bool {
        let self_level = match self.level {
            LogLevel::Debug => 0,
            LogLevel::Info => 1,
            LogLevel::Warning => 2,
            LogLevel::Error => 3,
        };
        let target_level = match level {
            LogLevel::Debug => 0,
            LogLevel::Info => 1,
            LogLevel::Warning => 2,
            LogLevel::Error => 3,
        };
        target_level >= self_level
    }

    pub fn debug(&self, message: &str) {
        if self.should_log(&LogLevel::Debug) {
            self.log(&LogLevel::Debug, message);
        }
    }

    pub fn info(&self, message: &str) {
        if self.should_log(&LogLevel::Info) {
            self.log(&LogLevel::Info, message);
        }
    }

    pub fn warning(&self, message: &str) {
        if self.should_log(&LogLevel::Warning) {
            self.log(&LogLevel::Warning, message);
        }
    }

    pub fn error(&self, message: &str) {
        if self.should_log(&LogLevel::Error) {
            self.log(&LogLevel::Error, message);
        }
    }

    fn log(&self, level: &LogLevel, message: &str) {
        let timestamp = chrono::Local::now().format("%Y-%m-%d %H:%M:%S");
        let prefix = if self.prefix.is_empty() {
            String::new()
        } else {
            format!("[{}] ", self.prefix)
        };
        eprintln!("{} {} {}{}", timestamp, level.to_string(), prefix, message);
    }
}

impl Default for Logger {
    fn default() -> Self {
        Self::new()
    }
}