atman-runtime 1.9.1

atman flow execution runtime: evaluator, tool dispatch, provider dispatch, executor, memory stores
Documentation
use std::fmt;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SettingSource {
    Default,
    Global,
    Project,
    Session,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Activation {
    Immediate,
    NextSession,
    RestartRequired,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SettingDescriptor {
    pub key: &'static str,
    pub title: &'static str,
    pub description: &'static str,
    pub source: SettingSource,
    pub activation: Activation,
    pub sensitive: bool,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SettingValue {
    pub descriptor: SettingDescriptor,
    pub value: String,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SettingMutationError {
    EmptyValue,
    UnsupportedKey(String),
}

impl fmt::Display for SettingMutationError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::EmptyValue => write!(f, "setting value cannot be empty"),
            Self::UnsupportedKey(key) => write!(f, "unsupported setting: {key}"),
        }
    }
}

impl std::error::Error for SettingMutationError {}

pub fn catalog() -> Vec<SettingDescriptor> {
    vec![
        SettingDescriptor {
            key: "session.context_budget",
            title: "Context budget",
            description: "Maximum provider context window budget.",
            source: SettingSource::Global,
            activation: Activation::NextSession,
            sensitive: false,
        },
        SettingDescriptor {
            key: "tools.output.max_bytes",
            title: "Tool output bytes",
            description: "Maximum inline tool output before continuation is offered.",
            source: SettingSource::Global,
            activation: Activation::Immediate,
            sensitive: false,
        },
        SettingDescriptor {
            key: "trust.mode",
            title: "Trust mode",
            description: "Controls approval behavior for tool execution.",
            source: SettingSource::Project,
            activation: Activation::NextSession,
            sensitive: false,
        },
        SettingDescriptor {
            key: "provider.api_key",
            title: "Provider API key",
            description: "Credential used by the selected provider.",
            source: SettingSource::Global,
            activation: Activation::Immediate,
            sensitive: true,
        },
    ]
}

pub fn descriptor(key: &str) -> Option<SettingDescriptor> {
    catalog().into_iter().find(|item| item.key == key)
}

pub fn validate_mutation(key: &str, value: &str) -> Result<(), SettingMutationError> {
    if descriptor(key).is_none() {
        return Err(SettingMutationError::UnsupportedKey(key.to_owned()));
    }
    if value.trim().is_empty() {
        return Err(SettingMutationError::EmptyValue);
    }
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn catalog_exposes_source_activation_and_sensitive_metadata() {
        let item = descriptor("provider.api_key").unwrap();
        assert_eq!(item.source, SettingSource::Global);
        assert_eq!(item.activation, Activation::Immediate);
        assert!(item.sensitive);
    }

    #[test]
    fn mutation_validation_rejects_unknown_and_empty_values() {
        assert_eq!(
            validate_mutation("unknown", "x"),
            Err(SettingMutationError::UnsupportedKey("unknown".into()))
        );
        assert_eq!(
            validate_mutation("trust.mode", " "),
            Err(SettingMutationError::EmptyValue)
        );
    }
}