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