1use 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, 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::experiment::{ExperimentConfig, OrchestrationConfig};
17use crate::features::{
18 CostConfig, DaemonConfig, DebugConfig, GatewayConfig, IndexConfig, SchedulerConfig,
19 SkillPromptMode, SkillsConfig, VaultConfig,
20};
21use crate::hooks::HooksConfig;
22use crate::learning::LearningConfig;
23use crate::logging::LoggingConfig;
24use crate::memory::{
25 CompressionConfig, DocumentConfig, GraphConfig, MagicDocsConfig, MemoryConfig, SemanticConfig,
26 SessionsConfig, SidequestConfig, TierConfig, VectorBackend,
27};
28use crate::metrics::MetricsConfig;
29use crate::notifications::NotificationsConfig;
30use crate::providers::{
31 LlmConfig, get_default_embedding_model, get_default_response_cache_ttl_secs,
32 get_default_router_ema_alpha, get_default_router_reorder_interval,
33};
34use crate::security::TrustConfig;
35use crate::security::{SecurityConfig, TimeoutConfig};
36use crate::telemetry::TelemetryConfig;
37use crate::ui::LspConfig;
38use crate::ui::{AcpConfig, TuiConfig};
39
40#[derive(Debug, Deserialize, Serialize)]
46pub struct Config {
47 pub agent: AgentConfig,
48 pub llm: LlmConfig,
49 pub skills: SkillsConfig,
50 pub memory: MemoryConfig,
51 #[serde(skip_serializing_if = "Option::is_none")]
52 pub telegram: Option<TelegramConfig>,
53 #[serde(skip_serializing_if = "Option::is_none")]
54 pub discord: Option<DiscordConfig>,
55 #[serde(skip_serializing_if = "Option::is_none")]
56 pub slack: Option<SlackConfig>,
57 #[serde(default)]
58 pub tools: ToolsConfig,
59 #[serde(default)]
60 pub a2a: A2aServerConfig,
61 #[serde(default)]
62 pub mcp: McpConfig,
63 #[serde(default)]
64 pub index: IndexConfig,
65 #[serde(default)]
66 pub vault: VaultConfig,
67 #[serde(default)]
68 pub security: SecurityConfig,
69 #[serde(default)]
70 pub timeouts: TimeoutConfig,
71 #[serde(default)]
72 pub cost: CostConfig,
73 #[serde(default)]
74 pub gateway: GatewayConfig,
75 #[serde(default)]
76 pub daemon: DaemonConfig,
77 #[serde(default)]
78 pub scheduler: SchedulerConfig,
79 #[serde(default)]
80 pub tui: TuiConfig,
81 #[serde(default)]
82 pub acp: AcpConfig,
83 #[serde(default)]
84 pub agents: SubAgentConfig,
85 #[serde(default)]
86 pub orchestration: OrchestrationConfig,
87 #[serde(default)]
88 pub classifiers: ClassifiersConfig,
89 #[serde(default)]
90 pub experiments: ExperimentConfig,
91 #[serde(default)]
92 pub debug: DebugConfig,
93 #[serde(default)]
94 pub logging: LoggingConfig,
95 #[serde(default)]
96 pub hooks: HooksConfig,
97 #[serde(default)]
98 pub lsp: LspConfig,
99 #[serde(default)]
101 pub magic_docs: MagicDocsConfig,
102 #[serde(default)]
104 pub telemetry: TelemetryConfig,
105 #[serde(default)]
107 pub metrics: MetricsConfig,
108 #[serde(default)]
110 pub session: crate::session::SessionConfig,
111 #[serde(default)]
113 pub cli: CliConfig,
114 #[serde(default)]
116 pub quality: crate::quality::QualityConfig,
117 #[serde(default)]
119 pub notifications: NotificationsConfig,
120 #[serde(skip)]
122 pub secrets: ResolvedSecrets,
123}
124
125#[derive(Debug, Default)]
130pub struct ResolvedSecrets {
131 pub claude_api_key: Option<Secret>,
132 pub openai_api_key: Option<Secret>,
133 pub gemini_api_key: Option<Secret>,
134 pub compatible_api_keys: HashMap<String, Secret>,
135 pub discord_token: Option<Secret>,
136 pub slack_bot_token: Option<Secret>,
137 pub slack_signing_secret: Option<Secret>,
138 pub custom: HashMap<String, Secret>,
141}
142
143impl Default for Config {
144 #[allow(clippy::too_many_lines)] fn default() -> Self {
146 Self {
147 agent: AgentConfig {
148 name: "Zeph".into(),
149 max_tool_iterations: 10,
150 auto_update_check: true,
151 instruction_files: Vec::new(),
152 instruction_auto_detect: true,
153 max_tool_retries: 2,
154 tool_repeat_threshold: 2,
155 max_retry_duration_secs: 30,
156 focus: FocusConfig::default(),
157 tool_filter: crate::agent::ToolFilterConfig::default(),
158 budget_hint_enabled: true,
159 supervisor: crate::agent::TaskSupervisorConfig::default(),
160 },
161 llm: LlmConfig {
162 providers: Vec::new(),
163 routing: crate::providers::LlmRoutingStrategy::None,
164 embedding_model: get_default_embedding_model(),
165 candle: None,
166 stt: None,
167 response_cache_enabled: false,
168 response_cache_ttl_secs: get_default_response_cache_ttl_secs(),
169 semantic_cache_enabled: false,
170 semantic_cache_threshold: 0.95,
171 semantic_cache_max_candidates: 10,
172 router_ema_enabled: false,
173 router_ema_alpha: get_default_router_ema_alpha(),
174 router_reorder_interval: get_default_router_reorder_interval(),
175 router: None,
176 instruction_file: None,
177 summary_model: None,
178 summary_provider: None,
179 complexity_routing: None,
180 coe: None,
181 },
182 skills: SkillsConfig {
183 paths: default_skill_paths(),
184 max_active_skills: NonZeroUsize::new(5).expect("5 is non-zero"),
185 disambiguation_threshold: 0.20,
186 min_injection_score: 0.20,
187 cosine_weight: 0.7,
188 hybrid_search: true,
189 learning: LearningConfig::default(),
190 trust: TrustConfig::default(),
191 prompt_mode: SkillPromptMode::Auto,
192 two_stage_matching: false,
193 confusability_threshold: 0.0,
194 rl_routing_enabled: false,
195 rl_learning_rate: 0.01,
196 rl_weight: 0.3,
197 rl_persist_interval: 10,
198 rl_warmup_updates: 50,
199 rl_embed_dim: None,
200 generation_provider: crate::providers::ProviderName::default(),
201 generation_output_dir: None,
202 mining: crate::features::SkillMiningConfig::default(),
203 evaluation: crate::features::SkillEvaluationConfig::default(),
204 proactive_exploration: crate::features::ProactiveExplorationConfig::default(),
205 },
206 memory: MemoryConfig {
207 sqlite_path: default_sqlite_path_field(),
208 history_limit: 50,
209 qdrant_url: "http://localhost:6334".into(),
210 qdrant_api_key: None,
211 semantic: SemanticConfig::default(),
212 summarization_threshold: 50,
213 context_budget_tokens: 0,
214 soft_compaction_threshold: 0.60,
215 hard_compaction_threshold: 0.90,
216 compaction_preserve_tail: 6,
217 compaction_cooldown_turns: 2,
218 auto_budget: true,
219 prune_protect_tokens: 40_000,
220 cross_session_score_threshold: 0.35,
221 vector_backend: VectorBackend::default(),
222 token_safety_margin: 1.0,
223 redact_credentials: true,
224 autosave_assistant: true,
225 autosave_min_length: 20,
226 tool_call_cutoff: 6,
227 sqlite_pool_size: 5,
228 sessions: SessionsConfig::default(),
229 documents: DocumentConfig::default(),
230 eviction: crate::memory::EvictionConfig::default(),
231 compression: CompressionConfig::default(),
232 sidequest: SidequestConfig::default(),
233 graph: GraphConfig::default(),
234 compression_guidelines: crate::memory::CompressionGuidelinesConfig::default(),
235 shutdown_summary: true,
236 shutdown_summary_min_messages: 4,
237 shutdown_summary_max_messages: 20,
238 shutdown_summary_timeout_secs: 30,
239 structured_summaries: false,
240 tiers: TierConfig::default(),
241 admission: crate::memory::AdmissionConfig::default(),
242 digest: crate::memory::DigestConfig::default(),
243 context_strategy: crate::memory::ContextStrategy::default(),
244 crossover_turn_threshold: 20,
245 consolidation: crate::memory::ConsolidationConfig::default(),
246 forgetting: crate::memory::ForgettingConfig::default(),
247 database_url: None,
248 store_routing: crate::memory::StoreRoutingConfig::default(),
249 persona: crate::memory::PersonaConfig::default(),
250 trajectory: crate::memory::TrajectoryConfig::default(),
251 category: crate::memory::CategoryConfig::default(),
252 tree: crate::memory::TreeConfig::default(),
253 microcompact: crate::memory::MicrocompactConfig::default(),
254 autodream: crate::memory::AutoDreamConfig::default(),
255 key_facts_dedup_threshold: 0.95,
256 compression_spectrum: crate::features::CompressionSpectrumConfig::default(),
257 retrieval: crate::memory::RetrievalConfig::default(),
258 reasoning: crate::memory::ReasoningConfig::default(),
259 hebbian: crate::memory::HebbianConfig::default(),
260 },
261 telegram: None,
262 discord: None,
263 slack: None,
264 tools: ToolsConfig::default(),
265 a2a: A2aServerConfig::default(),
266 mcp: McpConfig::default(),
267 index: IndexConfig::default(),
268 vault: VaultConfig::default(),
269 security: SecurityConfig::default(),
270 timeouts: TimeoutConfig::default(),
271 cost: CostConfig::default(),
272 gateway: GatewayConfig::default(),
273 daemon: DaemonConfig::default(),
274 scheduler: SchedulerConfig::default(),
275 tui: TuiConfig::default(),
276 acp: AcpConfig::default(),
277 agents: SubAgentConfig::default(),
278 orchestration: OrchestrationConfig::default(),
279 classifiers: ClassifiersConfig::default(),
280 experiments: ExperimentConfig::default(),
281 debug: DebugConfig::default(),
282 logging: LoggingConfig::default(),
283 lsp: LspConfig::default(),
284 hooks: HooksConfig::default(),
285 magic_docs: MagicDocsConfig::default(),
286 telemetry: TelemetryConfig::default(),
287 metrics: MetricsConfig::default(),
288 session: crate::session::SessionConfig::default(),
289 cli: CliConfig::default(),
290 quality: crate::quality::QualityConfig::default(),
291 notifications: NotificationsConfig::default(),
292 secrets: ResolvedSecrets::default(),
293 }
294 }
295}