Skip to main content

opencode_ralph_loop_cli/
config.rs

1use std::path::PathBuf;
2
3use serde::{Deserialize, Serialize};
4
5use crate::error::CliError;
6
7#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8pub struct TelemetryConfig {
9    #[serde(default)]
10    pub enabled: bool,
11}
12
13#[derive(Debug, Clone, Serialize, Deserialize, Default)]
14pub struct Config {
15    pub default_output: Option<String>,
16    pub default_force: Option<bool>,
17    pub plugin_version: Option<String>,
18    pub template_version: Option<String>,
19    #[serde(default)]
20    pub telemetry: TelemetryConfig,
21}
22
23impl Config {
24    pub fn load(config_file: Option<&PathBuf>) -> Self {
25        if let Some(path) = config_file {
26            return Self::load_from_path(path).unwrap_or_else(|e| {
27                tracing::warn!("failed to load config from {}: {e}", path.display());
28                Self::default()
29            });
30        }
31
32        if let Some(path) = Self::default_config_path() {
33            if path.exists() {
34                return Self::load_from_path(&path).unwrap_or_else(|e| {
35                    tracing::warn!("failed to load default config: {e}");
36                    Self::default()
37                });
38            }
39        }
40
41        Self::default()
42    }
43
44    fn load_from_path(path: &PathBuf) -> Result<Self, CliError> {
45        let content = std::fs::read_to_string(path)
46            .map_err(|e| CliError::io(path.to_string_lossy().into_owned(), e))?;
47        toml::from_str(&content)
48            .map_err(|e| CliError::ConfigParse(format!("invalid configuration: {e}")))
49    }
50
51    pub fn default_config_path() -> Option<PathBuf> {
52        directories::ProjectDirs::from("", "", "opencode-ralph-loop-cli")
53            .map(|d| d.config_dir().join("config.toml"))
54    }
55
56    pub fn config_path_display() -> String {
57        Self::default_config_path()
58            .map(|p| p.display().to_string())
59            .unwrap_or_else(|| "unavailable".to_string())
60    }
61}