Skip to main content

mdx_rust_core/
config.rs

1//! Configuration loading and management for mdx-rust
2
3use serde::{Deserialize, Serialize};
4
5/// Root configuration for an mdx-rust project
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct Config {
8    /// Default models to use for different roles
9    pub models: ModelConfig,
10
11    /// Artifact directory name (default: .mdx-rust)
12    #[serde(default = "default_artifact_dir")]
13    pub artifact_dir: String,
14}
15
16impl Default for Config {
17    fn default() -> Self {
18        Self {
19            models: ModelConfig::default(),
20            artifact_dir: default_artifact_dir(),
21        }
22    }
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize, Default)]
26pub struct ModelConfig {
27    /// Model used for deep diagnosis and candidate generation
28    pub analyzer: Option<String>,
29
30    /// Model used for LLM-as-Judge scoring
31    pub judge: Option<String>,
32
33    /// Default model for lighter tasks
34    pub default: Option<String>,
35}
36
37#[cfg(test)]
38mod tests {
39    use super::*;
40    use tempfile::tempdir;
41
42    #[test]
43    fn default_config_uses_standard_artifact_dir() {
44        assert_eq!(Config::default().artifact_dir, ".mdx-rust");
45    }
46
47    #[test]
48    fn missing_project_config_loads_usable_defaults() {
49        let dir = tempdir().unwrap();
50        let config = Config::load_from_project(dir.path()).unwrap();
51
52        assert_eq!(config.artifact_dir, ".mdx-rust");
53    }
54}
55
56fn default_artifact_dir() -> String {
57    ".mdx-rust".to_string()
58}
59
60impl Config {
61    /// Load configuration from the standard location, with sensible defaults.
62    pub fn load_from_project(root: &std::path::Path) -> anyhow::Result<Self> {
63        let config_path = root.join(".mdx-rust/config.toml");
64
65        if !config_path.exists() {
66            return Ok(Self::default());
67        }
68
69        let content = std::fs::read_to_string(config_path)?;
70        let mut cfg: Config = toml::from_str(&content)?;
71
72        if cfg.artifact_dir.is_empty() {
73            cfg.artifact_dir = default_artifact_dir();
74        }
75
76        Ok(cfg)
77    }
78}