use crate::serve::backends::PrivacyTier;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct BancoConfig {
#[serde(default)]
pub server: ServerConfig,
#[serde(default)]
pub inference: InferenceConfig,
#[serde(default)]
pub budget: BudgetConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServerConfig {
#[serde(default = "default_host")]
pub host: String,
#[serde(default = "default_port")]
pub port: u16,
#[serde(default)]
pub privacy_tier: PrivacyTierConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InferenceConfig {
#[serde(default = "default_temperature")]
pub temperature: f32,
#[serde(default = "default_top_p")]
pub top_p: f32,
#[serde(default = "default_max_tokens")]
pub max_tokens: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BudgetConfig {
#[serde(default = "default_daily_limit")]
pub daily_limit_usd: f64,
#[serde(default = "default_max_request")]
pub max_request_usd: f64,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum PrivacyTierConfig {
Sovereign,
Private,
#[default]
Standard,
}
impl From<PrivacyTierConfig> for PrivacyTier {
fn from(c: PrivacyTierConfig) -> Self {
match c {
PrivacyTierConfig::Sovereign => Self::Sovereign,
PrivacyTierConfig::Private => Self::Private,
PrivacyTierConfig::Standard => Self::Standard,
}
}
}
fn default_host() -> String {
"127.0.0.1".to_string()
}
fn default_port() -> u16 {
8090
}
fn default_temperature() -> f32 {
0.7
}
fn default_top_p() -> f32 {
1.0
}
fn default_max_tokens() -> u32 {
256
}
fn default_daily_limit() -> f64 {
10.0
}
fn default_max_request() -> f64 {
1.0
}
impl Default for ServerConfig {
fn default() -> Self {
Self {
host: default_host(),
port: default_port(),
privacy_tier: PrivacyTierConfig::default(),
}
}
}
impl Default for InferenceConfig {
fn default() -> Self {
Self {
temperature: default_temperature(),
top_p: default_top_p(),
max_tokens: default_max_tokens(),
}
}
}
impl Default for BudgetConfig {
fn default() -> Self {
Self { daily_limit_usd: default_daily_limit(), max_request_usd: default_max_request() }
}
}
impl BancoConfig {
#[must_use]
pub fn config_dir() -> Option<PathBuf> {
dirs::home_dir().map(|h| h.join(".banco"))
}
#[must_use]
pub fn config_path() -> Option<PathBuf> {
Self::config_dir().map(|d| d.join("config.toml"))
}
#[must_use]
pub fn load() -> Self {
let Some(path) = Self::config_path() else {
return Self::default();
};
match std::fs::read_to_string(&path) {
Ok(content) => match toml::from_str(&content) {
Ok(config) => config,
Err(e) => {
eprintln!("[banco] Warning: failed to parse {}: {e}", path.display());
Self::default()
}
},
Err(_) => Self::default(),
}
}
pub fn save(&self) -> anyhow::Result<()> {
let Some(dir) = Self::config_dir() else {
anyhow::bail!("Cannot determine home directory");
};
std::fs::create_dir_all(&dir)?;
let content = toml::to_string_pretty(self)?;
let path = dir.join("config.toml");
std::fs::write(&path, content)?;
Ok(())
}
}