Skip to main content

crabtalk_daemon/config/
mod.rs

1//! Daemon configuration loaded from TOML.
2
3pub use crate::hook::{mcp::McpServerConfig, system::SystemConfig};
4pub use ::model::{ProviderDef, ProviderRegistry, validate_providers};
5use anyhow::Result;
6pub use loader::{DEFAULT_CONFIG, scaffold_config_dir};
7use serde::{Deserialize, Serialize};
8use std::collections::BTreeMap;
9pub use wcore::{
10    AgentConfig, HeartbeatConfig, ManifestConfig, ResolvedManifest, load_agents_dir,
11    load_agents_dirs,
12    paths::{AGENTS_DIR, CONFIG_DIR, CONFIG_FILE, SKILLS_DIR, SOCKET_PATH},
13    resolve_manifests,
14};
15
16mod loader;
17
18/// Top-level daemon configuration (`config.toml`).
19///
20/// System-only: providers, system settings, and env vars for MCP processes.
21/// MCPs and agent configs live in manifests (`local/CrabTalk.toml` and
22/// `packages/*/*.toml`), loaded via [`resolve_manifests`].
23#[derive(Debug, Clone, Serialize, Deserialize, Default)]
24pub struct DaemonConfig {
25    /// Provider definitions (`[provider.<name>]`).
26    #[serde(default)]
27    pub provider: BTreeMap<String, ProviderDef>,
28    /// **Deprecated**: MCP configs migrated to `local/CrabTalk.toml`.
29    /// Kept for backwards compatibility during migration.
30    #[serde(default)]
31    pub mcps: BTreeMap<String, McpServerConfig>,
32    /// System configuration (tasks + memory).
33    #[serde(default)]
34    pub system: SystemConfig,
35    /// **Deprecated**: Agent configs migrated to `local/CrabTalk.toml`.
36    /// Kept for backwards compatibility during migration.
37    #[serde(default)]
38    pub agents: BTreeMap<String, AgentConfig>,
39    /// Environment variables passed to all MCP server processes at spawn time.
40    #[serde(default)]
41    pub env: BTreeMap<String, String>,
42}
43
44impl DaemonConfig {
45    /// Parse a TOML string into a `DaemonConfig`.
46    pub fn from_toml(toml_str: &str) -> Result<Self> {
47        let mut config: Self = toml::from_str(toml_str)?;
48        config.mcps.iter_mut().for_each(|(name, server)| {
49            if server.name.is_empty() {
50                server.name = name.clone();
51            }
52        });
53        if !config.mcps.is_empty() {
54            tracing::warn!("[mcps] in config.toml is deprecated — move to local/CrabTalk.toml");
55        }
56        if !config.agents.is_empty() {
57            tracing::warn!("[agents] in config.toml is deprecated — move to local/CrabTalk.toml");
58        }
59        validate_providers(&config.provider)?;
60        Ok(config)
61    }
62
63    /// Load configuration from a file path.
64    pub fn load(path: &std::path::Path) -> Result<Self> {
65        let content = std::fs::read_to_string(path)?;
66        Self::from_toml(&content)
67    }
68}