use std::path::PathBuf;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Config {
pub llm: LlmConfig,
pub mcp: McpConfig,
pub store: StoreConfig,
pub sandbox: SandboxConfig,
pub tui: TuiConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LlmConfig {
pub backend: String,
pub endpoint: String,
pub model: String,
pub timeout_secs: u64,
}
impl Default for LlmConfig {
fn default() -> Self {
Self {
backend: "ollama".into(),
endpoint: "http://127.0.0.1:11434".into(),
model: "llama3.1".into(),
timeout_secs: 120,
}
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct McpConfig {
#[serde(default)]
pub servers: Vec<McpServerSpec>,
#[serde(default = "default_approval_timeout")]
pub approval_timeout_secs: u64,
}
const fn default_approval_timeout() -> u64 {
30
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct McpServerSpec {
pub name: String,
pub command: String,
#[serde(default)]
pub args: Vec<String>,
#[serde(default = "default_true")]
pub sandbox: bool,
pub profile: Option<PathBuf>,
}
const fn default_true() -> bool {
true
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct StoreConfig {
pub root: Option<PathBuf>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SandboxConfig {
pub strict: bool,
}
impl Default for SandboxConfig {
fn default() -> Self {
Self { strict: true }
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TuiConfig {
pub tick_ms: u64,
pub mouse: bool,
}
impl Default for TuiConfig {
fn default() -> Self {
Self {
tick_ms: 16,
mouse: true,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn defaults_roundtrip_through_toml() {
let cfg = Config::default();
let s = toml::to_string(&cfg).expect("serialize default config to toml");
let back: Config = toml::from_str(&s).expect("parse back default config");
assert_eq!(back.llm.backend, cfg.llm.backend);
assert_eq!(back.tui.tick_ms, cfg.tui.tick_ms);
}
}