use serde::Deserialize;
use std::fs;
use std::path::Path;
use anyhow::{Result, Context};
use tracing::info;
#[derive(Debug, Deserialize, Clone)]
pub struct AccountConfig {
pub id: String,
pub name: String,
pub role: Option<String>,
pub api_key: Option<String>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct WorkspaceConfig {
pub id: String,
pub name: String,
pub members: Option<Vec<String>>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct McpServerConfig {
pub name: String,
pub base_url: String,
pub alias: Option<String>,
pub token: Option<String>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct Jug0Config {
pub base_url: String,
}
#[derive(Debug, Deserialize, Clone)]
pub struct JuglansConfig {
pub account: AccountConfig,
pub workspace: Option<WorkspaceConfig>,
#[serde(default = "default_jug0_config")]
pub jug0: Jug0Config,
#[serde(default)]
pub mcp_servers: Vec<McpServerConfig>,
#[serde(default)]
pub env: std::collections::HashMap<String, String>,
}
fn default_jug0_config() -> Jug0Config {
Jug0Config {
base_url: "https://api.jug0.com".to_string(),
}
}
impl JuglansConfig {
pub fn load() -> Result<Self> {
let path = Path::new("juglans.toml");
if !path.exists() {
info!("⚠️ 'juglans.toml' not found. Using default dev configuration.");
return Ok(JuglansConfig {
account: AccountConfig {
id: "dev_user".to_string(),
name: "Developer".to_string(),
role: Some("admin".to_string()),
api_key: None,
},
workspace: Some(WorkspaceConfig {
id: "default_ws".to_string(),
name: "Default Workspace".to_string(),
members: Some(vec!["dev_user".to_string()]),
}),
jug0: default_jug0_config(),
mcp_servers: vec![],
env: Default::default(),
});
}
let content = fs::read_to_string(path)
.context("Failed to read juglans.toml")?;
let config: JuglansConfig = toml::from_str(&content)
.context("Failed to parse juglans.toml")?;
info!("🔧 Loaded configuration for user: {}", config.account.name);
Ok(config)
}
}