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