use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentOvenConfig {
#[serde(default = "default_url")]
pub url: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub api_key: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub token: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub token_expires_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub kitchen: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub edition: Option<String>,
#[serde(default)]
pub telemetry: TelemetryConfig,
}
impl Default for AgentOvenConfig {
fn default() -> Self {
Self {
url: default_url(),
api_key: None,
token: None,
token_expires_at: None,
kitchen: None,
edition: None,
telemetry: TelemetryConfig::default(),
}
}
}
fn default_url() -> String {
"http://localhost:8080".into()
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TelemetryConfig {
#[serde(default = "default_true")]
pub enabled: bool,
#[serde(default = "default_otlp_endpoint")]
pub otlp_endpoint: String,
}
impl Default for TelemetryConfig {
fn default() -> Self {
Self {
enabled: true,
otlp_endpoint: default_otlp_endpoint(),
}
}
}
fn default_true() -> bool {
true
}
fn default_otlp_endpoint() -> String {
"http://localhost:4317".into()
}
impl AgentOvenConfig {
pub fn config_path() -> Option<PathBuf> {
dirs_next::home_dir().map(|h| h.join(".agentoven").join("config.toml"))
}
pub fn load() -> Self {
let mut cfg = Self::load_from_file().unwrap_or_default();
if let Ok(url) = std::env::var("AGENTOVEN_URL") {
cfg.url = url;
}
if let Ok(key) = std::env::var("AGENTOVEN_API_KEY") {
cfg.api_key = Some(key);
}
if let Ok(kitchen) = std::env::var("AGENTOVEN_KITCHEN") {
cfg.kitchen = Some(kitchen);
}
cfg
}
pub fn load_from_file() -> Option<Self> {
let path = Self::config_path()?;
let content = std::fs::read_to_string(&path).ok()?;
toml::from_str(&content).ok()
}
pub fn save(&self) -> anyhow::Result<()> {
let path = Self::config_path()
.ok_or_else(|| anyhow::anyhow!("Cannot determine home directory"))?;
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent)?;
}
let content = toml::to_string_pretty(self)?;
std::fs::write(&path, content)?;
Ok(())
}
pub fn set_url(&mut self, url: &str) -> anyhow::Result<()> {
self.url = url.to_string();
self.edition = None; self.save()
}
pub fn set_api_key(&mut self, key: &str) -> anyhow::Result<()> {
self.api_key = Some(key.to_string());
self.save()
}
pub fn set_kitchen(&mut self, kitchen: &str) -> anyhow::Result<()> {
self.kitchen = Some(kitchen.to_string());
self.save()
}
pub fn auth_credential(&self) -> Option<&str> {
if let Some(ref token) = self.token {
if !token.is_empty() {
return Some(token);
}
}
self.api_key.as_deref()
}
}