Skip to main content

walrus_daemon/config/
mod.rs

1//! Daemon configuration loaded from TOML.
2
3pub use ::model::{ProviderConfig, ProviderManager};
4use anyhow::Result;
5pub use default::{
6    AGENTS_DIR, DATA_DIR, GLOBAL_CONFIG_DIR, SKILLS_DIR, SOCKET_PATH, WORK_DIR,
7    scaffold_config_dir, scaffold_work_dir,
8};
9use serde::{Deserialize, Serialize};
10use std::collections::BTreeMap;
11use std::path::PathBuf;
12pub use {channel::ChannelConfig, mcp::McpServerConfig};
13pub use {loader::load_agents_dir, model::ModelConfig};
14
15mod default;
16mod loader;
17mod mcp;
18mod model;
19
20/// Top-level daemon configuration.
21#[derive(Debug, Clone, Serialize, Deserialize, Default)]
22pub struct DaemonConfig {
23    /// Model configurations.
24    #[serde(default)]
25    pub model: ModelConfig,
26    /// Channel configuration (Telegram bot).
27    #[serde(default)]
28    pub channel: ChannelConfig,
29    /// MCP server configurations.
30    #[serde(default)]
31    pub mcp_servers: BTreeMap<String, mcp::McpServerConfig>,
32    /// Optional symlink path for the workspace sandbox root (`~/.walrus/work/`).
33    ///
34    /// When set, a symlink is created at this path pointing to `~/.walrus/work/`.
35    #[serde(default)]
36    pub work_dir: Option<PathBuf>,
37}
38
39impl DaemonConfig {
40    /// Parse a TOML string into a `DaemonConfig`.
41    pub fn from_toml(toml_str: &str) -> Result<Self> {
42        let mut config: Self = toml::from_str(toml_str)?;
43        config
44            .model
45            .providers
46            .iter_mut()
47            .for_each(|(key, provider)| {
48                if provider.model.is_empty() {
49                    provider.model = key.clone();
50                }
51            });
52        config.mcp_servers.iter_mut().for_each(|(name, server)| {
53            if server.name.is_empty() {
54                server.name = name.clone().into();
55            }
56        });
57        Ok(config)
58    }
59
60    /// Load configuration from a file path.
61    pub fn load(path: &std::path::Path) -> Result<Self> {
62        let content = std::fs::read_to_string(path)?;
63        Self::from_toml(&content)
64    }
65}