Skip to main content

capo_agent/
config.rs

1use crate::error::{AppError, Result};
2
3#[derive(Debug, Clone)]
4pub struct Config {
5    pub model: ModelConfig,
6    pub anthropic: AnthropicConfig,
7}
8
9#[derive(Debug, Clone)]
10pub struct ModelConfig {
11    pub provider: String,
12    pub name: String,
13    pub max_tokens: u32,
14}
15
16#[derive(Debug, Clone)]
17pub struct AnthropicConfig {
18    pub api_key: Option<String>,
19    pub base_url: String,
20}
21
22impl Default for Config {
23    fn default() -> Self {
24        Self {
25            model: ModelConfig {
26                provider: "anthropic".to_string(),
27                name: "claude-sonnet-4-6".to_string(),
28                max_tokens: 8192,
29            },
30            anthropic: AnthropicConfig {
31                api_key: None,
32                base_url: "https://api.anthropic.com".to_string(),
33            },
34        }
35    }
36}
37
38impl Config {
39    pub fn from_env() -> Result<Self> {
40        Self::from_env_with(|name| std::env::var(name).ok())
41    }
42
43    pub fn from_env_with<F>(lookup: F) -> Result<Self>
44    where
45        F: Fn(&str) -> Option<String>,
46    {
47        let mut cfg = Self::default();
48        if let Some(name) = lookup("CAPO_MODEL_NAME") {
49            cfg.model.name = name.trim().to_string();
50        }
51        if let Some(provider) = lookup("CAPO_MODEL_PROVIDER") {
52            cfg.model.provider = provider.trim().to_string();
53        }
54        if let Some(max_tokens) = lookup("CAPO_MODEL_MAX_TOKENS") {
55            let max_tokens = max_tokens.trim().to_string();
56            cfg.model.max_tokens = max_tokens.parse().map_err(|_| {
57                AppError::Config(format!(
58                    "CAPO_MODEL_MAX_TOKENS not an integer: {max_tokens}"
59                ))
60            })?;
61        }
62        if let Some(key) = lookup("ANTHROPIC_API_KEY") {
63            cfg.anthropic.api_key = Some(key.trim().to_string());
64        }
65        if let Some(url) = lookup("CAPO_ANTHROPIC_BASE_URL") {
66            cfg.anthropic.base_url = url.trim().to_string();
67        }
68        Ok(cfg)
69    }
70}