1use 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::defaults::{default_skill_paths, default_sqlite_path_field};
14use crate::experiment::{ExperimentConfig, OrchestrationConfig};
15use crate::features::{
16 CostConfig, DaemonConfig, DebugConfig, GatewayConfig, IndexConfig, ObservabilityConfig,
17 SchedulerConfig, SkillPromptMode, SkillsConfig, VaultConfig,
18};
19use crate::learning::LearningConfig;
20use crate::logging::LoggingConfig;
21use crate::memory::{
22 CompressionConfig, DocumentConfig, GraphConfig, MemoryConfig, RoutingConfig, SemanticConfig,
23 SessionsConfig, SidequestConfig, TierConfig, VectorBackend,
24};
25use crate::providers::{
26 LlmConfig, get_default_embedding_model, get_default_response_cache_ttl_secs,
27 get_default_router_ema_alpha, get_default_router_reorder_interval,
28};
29use crate::security::TrustConfig;
30use crate::security::{SecurityConfig, TimeoutConfig};
31use crate::ui::{AcpConfig, TuiConfig};
32
33#[cfg(feature = "lsp-context")]
34use crate::ui::LspConfig;
35
36#[derive(Debug, Deserialize, Serialize)]
42pub struct Config {
43 pub agent: AgentConfig,
44 pub llm: LlmConfig,
45 pub skills: SkillsConfig,
46 pub memory: MemoryConfig,
47 #[serde(skip_serializing_if = "Option::is_none")]
48 pub telegram: Option<TelegramConfig>,
49 #[serde(skip_serializing_if = "Option::is_none")]
50 pub discord: Option<DiscordConfig>,
51 #[serde(skip_serializing_if = "Option::is_none")]
52 pub slack: Option<SlackConfig>,
53 #[serde(default)]
54 pub tools: ToolsConfig,
55 #[serde(default)]
56 pub a2a: A2aServerConfig,
57 #[serde(default)]
58 pub mcp: McpConfig,
59 #[serde(default)]
60 pub index: IndexConfig,
61 #[serde(default)]
62 pub vault: VaultConfig,
63 #[serde(default)]
64 pub security: SecurityConfig,
65 #[serde(default)]
66 pub timeouts: TimeoutConfig,
67 #[serde(default)]
68 pub cost: CostConfig,
69 #[serde(default)]
70 pub observability: ObservabilityConfig,
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 #[cfg(feature = "lsp-context")]
94 #[serde(default)]
95 pub lsp: LspConfig,
96 #[serde(skip)]
98 pub secrets: ResolvedSecrets,
99}
100
101#[derive(Debug, Default)]
106pub struct ResolvedSecrets {
107 pub claude_api_key: Option<Secret>,
108 pub openai_api_key: Option<Secret>,
109 pub gemini_api_key: Option<Secret>,
110 pub compatible_api_keys: HashMap<String, Secret>,
111 pub discord_token: Option<Secret>,
112 pub slack_bot_token: Option<Secret>,
113 pub slack_signing_secret: Option<Secret>,
114 pub custom: HashMap<String, Secret>,
117}
118
119impl Default for Config {
120 #[allow(clippy::too_many_lines)] fn default() -> Self {
122 Self {
123 agent: AgentConfig {
124 name: "Zeph".into(),
125 max_tool_iterations: 10,
126 auto_update_check: true,
127 instruction_files: Vec::new(),
128 instruction_auto_detect: true,
129 max_tool_retries: 2,
130 tool_repeat_threshold: 2,
131 max_retry_duration_secs: 30,
132 focus: FocusConfig::default(),
133 tool_filter: crate::agent::ToolFilterConfig::default(),
134 },
135 llm: LlmConfig {
136 providers: Vec::new(),
137 routing: crate::providers::LlmRoutingStrategy::None,
138 routes: std::collections::HashMap::new(),
139 embedding_model: get_default_embedding_model(),
140 candle: None,
141 stt: None,
142 response_cache_enabled: false,
143 response_cache_ttl_secs: get_default_response_cache_ttl_secs(),
144 semantic_cache_enabled: false,
145 semantic_cache_threshold: 0.95,
146 semantic_cache_max_candidates: 10,
147 router_ema_enabled: false,
148 router_ema_alpha: get_default_router_ema_alpha(),
149 router_reorder_interval: get_default_router_reorder_interval(),
150 router: None,
151 instruction_file: None,
152 summary_model: None,
153 summary_provider: None,
154 complexity_routing: None,
155 },
156 skills: SkillsConfig {
157 paths: default_skill_paths(),
158 max_active_skills: 5,
159 disambiguation_threshold: 0.05,
160 cosine_weight: 0.7,
161 hybrid_search: true,
162 learning: LearningConfig::default(),
163 trust: TrustConfig::default(),
164 prompt_mode: SkillPromptMode::Auto,
165 },
166 memory: MemoryConfig {
167 sqlite_path: default_sqlite_path_field(),
168 history_limit: 50,
169 qdrant_url: "http://localhost:6334".into(),
170 semantic: SemanticConfig::default(),
171 summarization_threshold: 50,
172 context_budget_tokens: 0,
173 soft_compaction_threshold: 0.60,
174 hard_compaction_threshold: 0.90,
175 compaction_preserve_tail: 6,
176 compaction_cooldown_turns: 2,
177 auto_budget: true,
178 prune_protect_tokens: 40_000,
179 cross_session_score_threshold: 0.35,
180 vector_backend: VectorBackend::default(),
181 token_safety_margin: 1.0,
182 redact_credentials: true,
183 autosave_assistant: true,
184 autosave_min_length: 20,
185 tool_call_cutoff: 6,
186 sqlite_pool_size: 5,
187 sessions: SessionsConfig::default(),
188 documents: DocumentConfig::default(),
189 eviction: zeph_memory::EvictionConfig::default(),
190 compression: CompressionConfig::default(),
191 sidequest: SidequestConfig::default(),
192 routing: RoutingConfig::default(),
193 graph: GraphConfig::default(),
194 compression_guidelines: zeph_memory::CompressionGuidelinesConfig::default(),
195 shutdown_summary: true,
196 shutdown_summary_min_messages: 4,
197 shutdown_summary_max_messages: 20,
198 shutdown_summary_timeout_secs: 10,
199 structured_summaries: false,
200 tiers: TierConfig::default(),
201 },
202 telegram: None,
203 discord: None,
204 slack: None,
205 tools: ToolsConfig::default(),
206 a2a: A2aServerConfig::default(),
207 mcp: McpConfig::default(),
208 index: IndexConfig::default(),
209 vault: VaultConfig::default(),
210 security: SecurityConfig::default(),
211 timeouts: TimeoutConfig::default(),
212 cost: CostConfig::default(),
213 observability: ObservabilityConfig::default(),
214 gateway: GatewayConfig::default(),
215 daemon: DaemonConfig::default(),
216 scheduler: SchedulerConfig::default(),
217 tui: TuiConfig::default(),
218 acp: AcpConfig::default(),
219 agents: SubAgentConfig::default(),
220 orchestration: OrchestrationConfig::default(),
221 classifiers: ClassifiersConfig::default(),
222 experiments: ExperimentConfig::default(),
223 debug: DebugConfig::default(),
224 logging: LoggingConfig::default(),
225 #[cfg(feature = "lsp-context")]
226 lsp: LspConfig::default(),
227 secrets: ResolvedSecrets::default(),
228 }
229 }
230}