capo-agent 0.6.0

Coding-agent library built on motosan-agent-loop. Composable, embeddable.
Documentation
use crate::error::{AppError, Result};

#[derive(Debug, Clone)]
pub struct Config {
    pub model: ModelConfig,
    pub anthropic: AnthropicConfig,
}

#[derive(Debug, Clone)]
pub struct ModelConfig {
    pub provider: String,
    pub name: String,
    pub max_tokens: u32,
}

#[derive(Debug, Clone)]
pub struct AnthropicConfig {
    pub api_key: Option<String>,
    pub base_url: String,
}

impl Default for Config {
    fn default() -> Self {
        Self {
            model: ModelConfig {
                provider: "anthropic".to_string(),
                name: "claude-sonnet-4-6".to_string(),
                max_tokens: 8192,
            },
            anthropic: AnthropicConfig {
                api_key: None,
                base_url: "https://api.anthropic.com".to_string(),
            },
        }
    }
}

impl Config {
    pub fn from_env() -> Result<Self> {
        Self::from_env_with(|name| std::env::var(name).ok())
    }

    pub fn from_env_with<F>(lookup: F) -> Result<Self>
    where
        F: Fn(&str) -> Option<String>,
    {
        let mut cfg = Self::default();
        if let Some(name) = lookup("CAPO_MODEL_NAME") {
            cfg.model.name = name.trim().to_string();
        }
        if let Some(provider) = lookup("CAPO_MODEL_PROVIDER") {
            cfg.model.provider = provider.trim().to_string();
        }
        if let Some(max_tokens) = lookup("CAPO_MODEL_MAX_TOKENS") {
            let max_tokens = max_tokens.trim().to_string();
            cfg.model.max_tokens = max_tokens.parse().map_err(|_| {
                AppError::Config(format!(
                    "CAPO_MODEL_MAX_TOKENS not an integer: {max_tokens}"
                ))
            })?;
        }
        if let Some(key) = lookup("ANTHROPIC_API_KEY") {
            cfg.anthropic.api_key = Some(key.trim().to_string());
        }
        if let Some(url) = lookup("CAPO_ANTHROPIC_BASE_URL") {
            cfg.anthropic.base_url = url.trim().to_string();
        }
        Ok(cfg)
    }
}