Skip to main content

walrus_daemon/config/
mod.rs

1//! Daemon configuration loaded from TOML.
2
3pub use crate::hook::{
4    mcp::McpServerConfig,
5    os::{PermissionConfig, ToolPermission},
6    system::SystemConfig,
7};
8pub use ::model::{ModelConfig, ProviderDef, ProviderRegistry};
9use anyhow::Result;
10pub use loader::{load_agents_dir, scaffold_config_dir};
11use serde::{Deserialize, Serialize};
12use std::collections::BTreeMap;
13pub use wcore::{
14    AgentConfig, HeartbeatConfig,
15    paths::{AGENTS_DIR, CONFIG_DIR, DATA_DIR, HOME_DIR, MEMORY_DB, SKILLS_DIR, SOCKET_PATH},
16};
17
18mod loader;
19
20/// Top-level daemon configuration.
21#[derive(Debug, Clone, Serialize, Deserialize, Default)]
22pub struct DaemonConfig {
23    /// Provider definitions (`[provider.<name>]`).
24    #[serde(default)]
25    pub provider: BTreeMap<String, ProviderDef>,
26    /// Model configuration (embedding model).
27    #[serde(default)]
28    pub model: ModelConfig,
29    /// MCP server configurations.
30    #[serde(default)]
31    pub mcps: BTreeMap<String, McpServerConfig>,
32    /// System configuration (tasks + memory).
33    #[serde(default)]
34    pub system: SystemConfig,
35    /// Per-agent configurations (name → config).
36    #[serde(default)]
37    pub agents: BTreeMap<String, AgentConfig>,
38    /// Permission configuration: global defaults + per-agent overrides.
39    #[serde(default)]
40    pub permissions: PermissionConfig,
41    /// Managed child services (`[services.<name>]`).
42    #[serde(default)]
43    pub services: BTreeMap<String, crate::service::ServiceConfig>,
44}
45
46impl DaemonConfig {
47    /// Parse a TOML string into a `DaemonConfig`.
48    pub fn from_toml(toml_str: &str) -> Result<Self> {
49        let mut config: Self = toml::from_str(toml_str)?;
50        config.mcps.iter_mut().for_each(|(name, server)| {
51            if server.name.is_empty() {
52                server.name = name.clone();
53            }
54        });
55        if config.system.walrus.model.is_none() {
56            config.system.walrus.model = Some(::model::default_model().into());
57        }
58        ModelConfig::validate(&config.provider)?;
59        Ok(config)
60    }
61
62    /// Load configuration from a file path.
63    pub fn load(path: &std::path::Path) -> Result<Self> {
64        let content = std::fs::read_to_string(path)?;
65        Self::from_toml(&content)
66    }
67}