systemprompt-cli 0.1.22

systemprompt.io OS - CLI for agent orchestration, AI operations, and system management
Documentation
use std::env;
use std::io::IsTerminal;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OutputFormat {
    Table,
    Json,
    Yaml,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum VerbosityLevel {
    Quiet,
    Normal,
    Verbose,
    Debug,
}

impl VerbosityLevel {
    pub const fn as_tracing_filter(&self) -> Option<&'static str> {
        match self {
            Self::Quiet => Some("error"),
            Self::Normal => None,
            Self::Verbose => Some("debug"),
            Self::Debug => Some("trace"),
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ColorMode {
    Auto,
    Always,
    Never,
}

#[derive(Debug, Clone)]
pub struct CliConfig {
    pub output_format: OutputFormat,
    pub verbosity: VerbosityLevel,
    pub color_mode: ColorMode,
    pub interactive: bool,
    pub profile_override: Option<String>,
}

impl Default for CliConfig {
    fn default() -> Self {
        Self {
            output_format: OutputFormat::Table,
            verbosity: VerbosityLevel::Normal,
            color_mode: ColorMode::Auto,
            interactive: true,
            profile_override: None,
        }
    }
}

impl CliConfig {
    pub fn new() -> Self {
        let mut config = Self::default();
        config.apply_environment_variables();
        config
    }

    pub const fn with_output_format(mut self, format: OutputFormat) -> Self {
        self.output_format = format;
        self
    }

    pub const fn with_verbosity(mut self, level: VerbosityLevel) -> Self {
        self.verbosity = level;
        self
    }

    pub const fn with_color_mode(mut self, mode: ColorMode) -> Self {
        self.color_mode = mode;
        self
    }

    pub const fn with_interactive(mut self, interactive: bool) -> Self {
        self.interactive = interactive;
        self
    }

    pub fn with_profile_override(mut self, profile: Option<String>) -> Self {
        self.profile_override = profile;
        self
    }

    fn apply_environment_variables(&mut self) {
        if let Ok(format) = env::var("SYSTEMPROMPT_OUTPUT_FORMAT") {
            self.output_format = match format.to_lowercase().as_str() {
                "json" => OutputFormat::Json,
                "yaml" => OutputFormat::Yaml,
                "table" => OutputFormat::Table,
                _ => self.output_format,
            };
        }

        if let Ok(level) = env::var("SYSTEMPROMPT_LOG_LEVEL") {
            self.verbosity = match level.to_lowercase().as_str() {
                "quiet" => VerbosityLevel::Quiet,
                "normal" => VerbosityLevel::Normal,
                "verbose" => VerbosityLevel::Verbose,
                "debug" => VerbosityLevel::Debug,
                _ => self.verbosity,
            };
        }

        if env::var("SYSTEMPROMPT_NO_COLOR").is_ok() || env::var("NO_COLOR").is_ok() {
            self.color_mode = ColorMode::Never;
        }

        if env::var("SYSTEMPROMPT_NON_INTERACTIVE").is_ok() {
            self.interactive = false;
        }
    }

    pub fn should_use_color(&self) -> bool {
        match self.color_mode {
            ColorMode::Always => true,
            ColorMode::Never => false,
            ColorMode::Auto => std::io::stdout().is_terminal(),
        }
    }

    pub fn is_json_output(&self) -> bool {
        self.output_format == OutputFormat::Json
    }

    pub fn should_show_verbose(&self) -> bool {
        self.verbosity >= VerbosityLevel::Verbose
    }

    pub fn is_interactive(&self) -> bool {
        self.interactive && std::io::stdin().is_terminal() && std::io::stdout().is_terminal()
    }

    pub const fn output_format(&self) -> OutputFormat {
        self.output_format
    }
}

thread_local! {
    static CLI_CONFIG: std::cell::RefCell<CliConfig> = std::cell::RefCell::new(CliConfig::new());
}

pub fn set_global_config(config: CliConfig) {
    CLI_CONFIG.with(|c| {
        *c.borrow_mut() = config;
    });
}

pub fn get_global_config() -> CliConfig {
    CLI_CONFIG.with(|c| c.borrow().clone())
}