Skip to main content

tuff_core/
config.rs

1use std::path::Path;
2
3use serde::{Deserialize, Serialize};
4
5use crate::error::Result;
6use crate::paths;
7
8pub const DEFAULT_AGENT: &str = "open-agents";
9
10#[derive(Debug, Serialize, Deserialize)]
11#[serde(default)]
12pub struct TuffConfig {
13    #[serde(rename = "agents", alias = "targets")]
14    pub agents: Vec<String>,
15    #[serde(rename = "defaultAgent", alias = "default_agent")]
16    pub default_agent: String,
17}
18
19impl Default for TuffConfig {
20    fn default() -> Self {
21        Self {
22            agents: vec![],
23            default_agent: DEFAULT_AGENT.to_string(),
24        }
25    }
26}
27
28pub fn read_config(repo_root: &Path) -> Result<TuffConfig> {
29    read_config_at(&paths::project_config(repo_root))
30}
31
32pub fn read_global_config(home: &Path) -> Result<TuffConfig> {
33    read_config_at(&paths::user_config(home))
34}
35
36fn read_config_at(path: &Path) -> Result<TuffConfig> {
37    if path.exists() {
38        let config: TuffConfig = serde_json::from_str(&std::fs::read_to_string(path)?)?;
39        Ok(config)
40    } else {
41        let default = TuffConfig::default();
42        write_config_at(path, &default)?;
43        Ok(default)
44    }
45}
46
47pub fn write_config(repo_root: &Path, config: &TuffConfig) -> Result<()> {
48    write_config_at(&paths::project_config(repo_root), config)
49}
50
51pub fn write_global_config(home: &Path, config: &TuffConfig) -> Result<()> {
52    write_config_at(&paths::user_config(home), config)
53}
54
55fn write_config_at(path: &Path, config: &TuffConfig) -> Result<()> {
56    if let Some(parent) = path.parent() {
57        std::fs::create_dir_all(parent)?;
58    }
59    std::fs::write(path, serde_json::to_string_pretty(config)? + "\n")?;
60    Ok(())
61}