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