Skip to main content

zeph_config/
root.rs

1// SPDX-FileCopyrightText: 2026 Andrei G <bug-ops>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4use std::collections::HashMap;
5
6use serde::{Deserialize, Serialize};
7use zeph_common::secret::Secret;
8use zeph_tools::ToolsConfig;
9
10use crate::agent::{AgentConfig, FocusConfig, SubAgentConfig};
11use crate::channels::{A2aServerConfig, DiscordConfig, McpConfig, SlackConfig, TelegramConfig};
12use crate::classifiers::ClassifiersConfig;
13use crate::cli::CliConfig;
14use crate::defaults::{default_skill_paths, default_sqlite_path_field};
15use crate::experiment::{ExperimentConfig, OrchestrationConfig};
16use crate::features::{
17    CostConfig, DaemonConfig, DebugConfig, GatewayConfig, IndexConfig, SchedulerConfig,
18    SkillPromptMode, SkillsConfig, VaultConfig,
19};
20use crate::hooks::HooksConfig;
21use crate::learning::LearningConfig;
22use crate::logging::LoggingConfig;
23use crate::memory::{
24    CompressionConfig, DocumentConfig, GraphConfig, MagicDocsConfig, MemoryConfig, SemanticConfig,
25    SessionsConfig, SidequestConfig, TierConfig, VectorBackend,
26};
27use crate::metrics::MetricsConfig;
28use crate::notifications::NotificationsConfig;
29use crate::providers::{
30    LlmConfig, get_default_embedding_model, get_default_response_cache_ttl_secs,
31    get_default_router_ema_alpha, get_default_router_reorder_interval,
32};
33use crate::security::TrustConfig;
34use crate::security::{SecurityConfig, TimeoutConfig};
35use crate::telemetry::TelemetryConfig;
36use crate::ui::LspConfig;
37use crate::ui::{AcpConfig, TuiConfig};
38
39/// Top-level agent configuration.
40///
41/// Loaded from a TOML file via [`Config::load`]. Env-var overrides can be applied
42/// via `apply_env_overrides`. Secret resolution via `VaultProvider`
43/// is handled in `zeph-core` through the `SecretResolver` trait.
44#[derive(Debug, Deserialize, Serialize)]
45pub struct Config {
46    pub agent: AgentConfig,
47    pub llm: LlmConfig,
48    pub skills: SkillsConfig,
49    pub memory: MemoryConfig,
50    #[serde(skip_serializing_if = "Option::is_none")]
51    pub telegram: Option<TelegramConfig>,
52    #[serde(skip_serializing_if = "Option::is_none")]
53    pub discord: Option<DiscordConfig>,
54    #[serde(skip_serializing_if = "Option::is_none")]
55    pub slack: Option<SlackConfig>,
56    #[serde(default)]
57    pub tools: ToolsConfig,
58    #[serde(default)]
59    pub a2a: A2aServerConfig,
60    #[serde(default)]
61    pub mcp: McpConfig,
62    #[serde(default)]
63    pub index: IndexConfig,
64    #[serde(default)]
65    pub vault: VaultConfig,
66    #[serde(default)]
67    pub security: SecurityConfig,
68    #[serde(default)]
69    pub timeouts: TimeoutConfig,
70    #[serde(default)]
71    pub cost: CostConfig,
72    #[serde(default)]
73    pub gateway: GatewayConfig,
74    #[serde(default)]
75    pub daemon: DaemonConfig,
76    #[serde(default)]
77    pub scheduler: SchedulerConfig,
78    #[serde(default)]
79    pub tui: TuiConfig,
80    #[serde(default)]
81    pub acp: AcpConfig,
82    #[serde(default)]
83    pub agents: SubAgentConfig,
84    #[serde(default)]
85    pub orchestration: OrchestrationConfig,
86    #[serde(default)]
87    pub classifiers: ClassifiersConfig,
88    #[serde(default)]
89    pub experiments: ExperimentConfig,
90    #[serde(default)]
91    pub debug: DebugConfig,
92    #[serde(default)]
93    pub logging: LoggingConfig,
94    #[serde(default)]
95    pub hooks: HooksConfig,
96    #[serde(default)]
97    pub lsp: LspConfig,
98    /// `MagicDocs` auto-maintained markdown (#2702).
99    #[serde(default)]
100    pub magic_docs: MagicDocsConfig,
101    /// Profiling and distributed tracing configuration.
102    #[serde(default)]
103    pub telemetry: TelemetryConfig,
104    /// Prometheus metrics export configuration.
105    #[serde(default)]
106    pub metrics: MetricsConfig,
107    /// Session UX settings (recap-on-resume, etc.).
108    #[serde(default)]
109    pub session: crate::session::SessionConfig,
110    /// Session-scoped CLI overrides (bare mode, JSON output, auto-approve).
111    #[serde(default)]
112    pub cli: CliConfig,
113    /// MARCH self-check quality pipeline configuration.
114    #[serde(default)]
115    pub quality: crate::quality::QualityConfig,
116    /// Per-turn completion notification settings (macOS banners, ntfy webhook).
117    #[serde(default)]
118    pub notifications: NotificationsConfig,
119    /// Resolved secrets from vault. Never serialized — populated at runtime.
120    #[serde(skip)]
121    pub secrets: ResolvedSecrets,
122}
123
124/// Secrets resolved from the vault at runtime.
125///
126/// Populated by `SecretResolver::resolve_secrets()` in `zeph-core`.
127/// Never serialized to TOML.
128#[derive(Debug, Default)]
129pub struct ResolvedSecrets {
130    pub claude_api_key: Option<Secret>,
131    pub openai_api_key: Option<Secret>,
132    pub gemini_api_key: Option<Secret>,
133    pub compatible_api_keys: HashMap<String, Secret>,
134    pub discord_token: Option<Secret>,
135    pub slack_bot_token: Option<Secret>,
136    pub slack_signing_secret: Option<Secret>,
137    /// Arbitrary skill secrets resolved from `ZEPH_SECRET_*` vault keys.
138    /// Key is the lowercased name after stripping the prefix (e.g. `github_token`).
139    pub custom: HashMap<String, Secret>,
140}
141
142impl Default for Config {
143    #[allow(clippy::too_many_lines)] // flat struct literal with one field per config section — no meaningful split exists
144    fn default() -> Self {
145        Self {
146            agent: AgentConfig {
147                name: "Zeph".into(),
148                max_tool_iterations: 10,
149                auto_update_check: true,
150                instruction_files: Vec::new(),
151                instruction_auto_detect: true,
152                max_tool_retries: 2,
153                tool_repeat_threshold: 2,
154                max_retry_duration_secs: 30,
155                focus: FocusConfig::default(),
156                tool_filter: crate::agent::ToolFilterConfig::default(),
157                budget_hint_enabled: true,
158                supervisor: crate::agent::TaskSupervisorConfig::default(),
159            },
160            llm: LlmConfig {
161                providers: Vec::new(),
162                routing: crate::providers::LlmRoutingStrategy::None,
163                embedding_model: get_default_embedding_model(),
164                candle: None,
165                stt: None,
166                response_cache_enabled: false,
167                response_cache_ttl_secs: get_default_response_cache_ttl_secs(),
168                semantic_cache_enabled: false,
169                semantic_cache_threshold: 0.95,
170                semantic_cache_max_candidates: 10,
171                router_ema_enabled: false,
172                router_ema_alpha: get_default_router_ema_alpha(),
173                router_reorder_interval: get_default_router_reorder_interval(),
174                router: None,
175                instruction_file: None,
176                summary_model: None,
177                summary_provider: None,
178                complexity_routing: None,
179                coe: None,
180            },
181            skills: SkillsConfig {
182                paths: default_skill_paths(),
183                max_active_skills: 5,
184                disambiguation_threshold: 0.20,
185                min_injection_score: 0.20,
186                cosine_weight: 0.7,
187                hybrid_search: true,
188                learning: LearningConfig::default(),
189                trust: TrustConfig::default(),
190                prompt_mode: SkillPromptMode::Auto,
191                two_stage_matching: false,
192                confusability_threshold: 0.0,
193                rl_routing_enabled: false,
194                rl_learning_rate: 0.01,
195                rl_weight: 0.3,
196                rl_persist_interval: 10,
197                rl_warmup_updates: 50,
198                rl_embed_dim: None,
199                generation_provider: crate::providers::ProviderName::default(),
200                generation_output_dir: None,
201                mining: crate::features::SkillMiningConfig::default(),
202                evaluation: crate::features::SkillEvaluationConfig::default(),
203                proactive_exploration: crate::features::ProactiveExplorationConfig::default(),
204            },
205            memory: MemoryConfig {
206                sqlite_path: default_sqlite_path_field(),
207                history_limit: 50,
208                qdrant_url: "http://localhost:6334".into(),
209                semantic: SemanticConfig::default(),
210                summarization_threshold: 50,
211                context_budget_tokens: 0,
212                soft_compaction_threshold: 0.60,
213                hard_compaction_threshold: 0.90,
214                compaction_preserve_tail: 6,
215                compaction_cooldown_turns: 2,
216                auto_budget: true,
217                prune_protect_tokens: 40_000,
218                cross_session_score_threshold: 0.35,
219                vector_backend: VectorBackend::default(),
220                token_safety_margin: 1.0,
221                redact_credentials: true,
222                autosave_assistant: true,
223                autosave_min_length: 20,
224                tool_call_cutoff: 6,
225                sqlite_pool_size: 5,
226                sessions: SessionsConfig::default(),
227                documents: DocumentConfig::default(),
228                eviction: zeph_memory::EvictionConfig::default(),
229                compression: CompressionConfig::default(),
230                sidequest: SidequestConfig::default(),
231                graph: GraphConfig::default(),
232                compression_guidelines: zeph_memory::CompressionGuidelinesConfig::default(),
233                shutdown_summary: true,
234                shutdown_summary_min_messages: 4,
235                shutdown_summary_max_messages: 20,
236                shutdown_summary_timeout_secs: 10,
237                structured_summaries: false,
238                tiers: TierConfig::default(),
239                admission: crate::memory::AdmissionConfig::default(),
240                digest: crate::memory::DigestConfig::default(),
241                context_strategy: crate::memory::ContextStrategy::default(),
242                crossover_turn_threshold: 20,
243                consolidation: crate::memory::ConsolidationConfig::default(),
244                forgetting: crate::memory::ForgettingConfig::default(),
245                database_url: None,
246                store_routing: crate::memory::StoreRoutingConfig::default(),
247                persona: crate::memory::PersonaConfig::default(),
248                trajectory: crate::memory::TrajectoryConfig::default(),
249                category: crate::memory::CategoryConfig::default(),
250                tree: crate::memory::TreeConfig::default(),
251                microcompact: crate::memory::MicrocompactConfig::default(),
252                autodream: crate::memory::AutoDreamConfig::default(),
253                key_facts_dedup_threshold: 0.95,
254                compression_spectrum: crate::features::CompressionSpectrumConfig::default(),
255                retrieval: crate::memory::RetrievalConfig::default(),
256                reasoning: crate::memory::ReasoningConfig::default(),
257                hebbian: crate::memory::HebbianConfig::default(),
258            },
259            telegram: None,
260            discord: None,
261            slack: None,
262            tools: ToolsConfig::default(),
263            a2a: A2aServerConfig::default(),
264            mcp: McpConfig::default(),
265            index: IndexConfig::default(),
266            vault: VaultConfig::default(),
267            security: SecurityConfig::default(),
268            timeouts: TimeoutConfig::default(),
269            cost: CostConfig::default(),
270            gateway: GatewayConfig::default(),
271            daemon: DaemonConfig::default(),
272            scheduler: SchedulerConfig::default(),
273            tui: TuiConfig::default(),
274            acp: AcpConfig::default(),
275            agents: SubAgentConfig::default(),
276            orchestration: OrchestrationConfig::default(),
277            classifiers: ClassifiersConfig::default(),
278            experiments: ExperimentConfig::default(),
279            debug: DebugConfig::default(),
280            logging: LoggingConfig::default(),
281            lsp: LspConfig::default(),
282            hooks: HooksConfig::default(),
283            magic_docs: MagicDocsConfig::default(),
284            telemetry: TelemetryConfig::default(),
285            metrics: MetricsConfig::default(),
286            session: crate::session::SessionConfig::default(),
287            cli: CliConfig::default(),
288            quality: crate::quality::QualityConfig::default(),
289            notifications: NotificationsConfig::default(),
290            secrets: ResolvedSecrets::default(),
291        }
292    }
293}