1use serde::{Deserialize, Serialize};
5
6use crate::defaults::{default_skill_paths, default_true};
7use crate::learning::LearningConfig;
8use crate::providers::ProviderName;
9use crate::security::TrustConfig;
10
11fn default_disambiguation_threshold() -> f32 {
12 0.20
13}
14
15fn default_rl_learning_rate() -> f32 {
16 0.01
17}
18
19fn default_rl_weight() -> f32 {
20 0.3
21}
22
23fn default_rl_persist_interval() -> u32 {
24 10
25}
26
27fn default_rl_warmup_updates() -> u32 {
28 50
29}
30
31fn default_min_injection_score() -> f32 {
32 0.20
33}
34
35fn default_cosine_weight() -> f32 {
36 0.7
37}
38
39fn default_hybrid_search() -> bool {
40 true
41}
42
43fn default_max_active_skills() -> usize {
44 5
45}
46
47fn default_index_watch() -> bool {
48 true
49}
50
51fn default_index_search_enabled() -> bool {
52 true
53}
54
55fn default_index_max_chunks() -> usize {
56 12
57}
58
59fn default_index_score_threshold() -> f32 {
60 0.25
61}
62
63fn default_index_budget_ratio() -> f32 {
64 0.40
65}
66
67fn default_index_repo_map_tokens() -> usize {
68 500
69}
70
71fn default_repo_map_ttl_secs() -> u64 {
72 300
73}
74
75fn default_vault_backend() -> String {
76 "env".into()
77}
78
79fn default_max_daily_cents() -> u32 {
80 0
81}
82
83fn default_otlp_endpoint() -> String {
84 "http://localhost:4317".into()
85}
86
87fn default_pid_file() -> String {
88 "~/.zeph/zeph.pid".into()
89}
90
91fn default_health_interval() -> u64 {
92 30
93}
94
95fn default_max_restart_backoff() -> u64 {
96 60
97}
98
99fn default_scheduler_tick_interval() -> u64 {
100 60
101}
102
103fn default_scheduler_max_tasks() -> usize {
104 100
105}
106
107fn default_gateway_bind() -> String {
108 "127.0.0.1".into()
109}
110
111fn default_gateway_port() -> u16 {
112 8090
113}
114
115fn default_gateway_rate_limit() -> u32 {
116 120
117}
118
119fn default_gateway_max_body() -> usize {
120 1_048_576
121}
122
123#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Deserialize, Serialize)]
125#[serde(rename_all = "lowercase")]
126pub enum SkillPromptMode {
127 Full,
128 Compact,
129 #[default]
130 Auto,
131}
132
133#[derive(Debug, Deserialize, Serialize)]
134pub struct SkillsConfig {
135 #[serde(default = "default_skill_paths")]
136 pub paths: Vec<String>,
137 #[serde(default = "default_max_active_skills")]
138 pub max_active_skills: usize,
139 #[serde(default = "default_disambiguation_threshold")]
140 pub disambiguation_threshold: f32,
141 #[serde(default = "default_min_injection_score")]
142 pub min_injection_score: f32,
143 #[serde(default = "default_cosine_weight")]
144 pub cosine_weight: f32,
145 #[serde(default = "default_hybrid_search")]
146 pub hybrid_search: bool,
147 #[serde(default)]
148 pub learning: LearningConfig,
149 #[serde(default)]
150 pub trust: TrustConfig,
151 #[serde(default)]
152 pub prompt_mode: SkillPromptMode,
153 #[serde(default)]
156 pub two_stage_matching: bool,
157 #[serde(default)]
160 pub confusability_threshold: f32,
161
162 #[serde(default)]
165 pub rl_routing_enabled: bool,
166 #[serde(default = "default_rl_learning_rate")]
168 pub rl_learning_rate: f32,
169 #[serde(default = "default_rl_weight")]
171 pub rl_weight: f32,
172 #[serde(default = "default_rl_persist_interval")]
174 pub rl_persist_interval: u32,
175 #[serde(default = "default_rl_warmup_updates")]
177 pub rl_warmup_updates: u32,
178 #[serde(default)]
182 pub rl_embed_dim: Option<usize>,
183
184 #[serde(default)]
187 pub generation_provider: ProviderName,
188 #[serde(default)]
190 pub generation_output_dir: Option<String>,
191 #[serde(default)]
193 pub mining: SkillMiningConfig,
194}
195
196fn default_max_repos_per_query() -> usize {
197 20
198}
199
200fn default_dedup_threshold() -> f32 {
201 0.85
202}
203
204fn default_rate_limit_rpm() -> u32 {
205 25
206}
207
208#[derive(Debug, Default, Deserialize, Serialize)]
210pub struct SkillMiningConfig {
211 #[serde(default)]
213 pub queries: Vec<String>,
214 #[serde(default = "default_max_repos_per_query")]
216 pub max_repos_per_query: usize,
217 #[serde(default = "default_dedup_threshold")]
219 pub dedup_threshold: f32,
220 #[serde(default)]
222 pub output_dir: Option<String>,
223 #[serde(default)]
225 pub generation_provider: ProviderName,
226 #[serde(default)]
228 pub embedding_provider: ProviderName,
229 #[serde(default = "default_rate_limit_rpm")]
231 pub rate_limit_rpm: u32,
232}
233
234#[derive(Debug, Deserialize, Serialize)]
235#[allow(clippy::struct_excessive_bools)]
236pub struct IndexConfig {
237 #[serde(default)]
238 pub enabled: bool,
239 #[serde(default = "default_index_search_enabled")]
240 pub search_enabled: bool,
241 #[serde(default = "default_index_watch")]
242 pub watch: bool,
243 #[serde(default = "default_index_max_chunks")]
244 pub max_chunks: usize,
245 #[serde(default = "default_index_score_threshold")]
246 pub score_threshold: f32,
247 #[serde(default = "default_index_budget_ratio")]
248 pub budget_ratio: f32,
249 #[serde(default = "default_index_repo_map_tokens")]
250 pub repo_map_tokens: usize,
251 #[serde(default = "default_repo_map_ttl_secs")]
252 pub repo_map_ttl_secs: u64,
253 #[serde(default)]
257 pub mcp_enabled: bool,
258}
259
260impl Default for IndexConfig {
261 fn default() -> Self {
262 Self {
263 enabled: false,
264 search_enabled: default_index_search_enabled(),
265 watch: default_index_watch(),
266 max_chunks: default_index_max_chunks(),
267 score_threshold: default_index_score_threshold(),
268 budget_ratio: default_index_budget_ratio(),
269 repo_map_tokens: default_index_repo_map_tokens(),
270 repo_map_ttl_secs: default_repo_map_ttl_secs(),
271 mcp_enabled: false,
272 }
273 }
274}
275
276#[derive(Debug, Deserialize, Serialize)]
277pub struct VaultConfig {
278 #[serde(default = "default_vault_backend")]
279 pub backend: String,
280}
281
282impl Default for VaultConfig {
283 fn default() -> Self {
284 Self {
285 backend: default_vault_backend(),
286 }
287 }
288}
289
290#[derive(Debug, Deserialize, Serialize)]
291pub struct CostConfig {
292 #[serde(default = "default_true")]
293 pub enabled: bool,
294 #[serde(default = "default_max_daily_cents")]
295 pub max_daily_cents: u32,
296}
297
298impl Default for CostConfig {
299 fn default() -> Self {
300 Self {
301 enabled: true,
302 max_daily_cents: default_max_daily_cents(),
303 }
304 }
305}
306
307#[derive(Debug, Deserialize, Serialize)]
308pub struct ObservabilityConfig {
309 #[serde(default)]
310 pub exporter: String,
311 #[serde(default = "default_otlp_endpoint")]
312 pub endpoint: String,
313}
314
315impl Default for ObservabilityConfig {
316 fn default() -> Self {
317 Self {
318 exporter: String::new(),
319 endpoint: default_otlp_endpoint(),
320 }
321 }
322}
323
324#[derive(Debug, Clone, Deserialize, Serialize)]
325pub struct GatewayConfig {
326 #[serde(default)]
327 pub enabled: bool,
328 #[serde(default = "default_gateway_bind")]
329 pub bind: String,
330 #[serde(default = "default_gateway_port")]
331 pub port: u16,
332 #[serde(default)]
333 pub auth_token: Option<String>,
334 #[serde(default = "default_gateway_rate_limit")]
335 pub rate_limit: u32,
336 #[serde(default = "default_gateway_max_body")]
337 pub max_body_size: usize,
338}
339
340impl Default for GatewayConfig {
341 fn default() -> Self {
342 Self {
343 enabled: false,
344 bind: default_gateway_bind(),
345 port: default_gateway_port(),
346 auth_token: None,
347 rate_limit: default_gateway_rate_limit(),
348 max_body_size: default_gateway_max_body(),
349 }
350 }
351}
352
353#[derive(Debug, Clone, Deserialize, Serialize)]
354pub struct DaemonConfig {
355 #[serde(default)]
356 pub enabled: bool,
357 #[serde(default = "default_pid_file")]
358 pub pid_file: String,
359 #[serde(default = "default_health_interval")]
360 pub health_interval_secs: u64,
361 #[serde(default = "default_max_restart_backoff")]
362 pub max_restart_backoff_secs: u64,
363}
364
365impl Default for DaemonConfig {
366 fn default() -> Self {
367 Self {
368 enabled: false,
369 pid_file: default_pid_file(),
370 health_interval_secs: default_health_interval(),
371 max_restart_backoff_secs: default_max_restart_backoff(),
372 }
373 }
374}
375
376#[derive(Debug, Clone, Deserialize, Serialize)]
377pub struct SchedulerConfig {
378 #[serde(default)]
379 pub enabled: bool,
380 #[serde(default = "default_scheduler_tick_interval")]
381 pub tick_interval_secs: u64,
382 #[serde(default = "default_scheduler_max_tasks")]
383 pub max_tasks: usize,
384 #[serde(default)]
385 pub tasks: Vec<ScheduledTaskConfig>,
386}
387
388impl Default for SchedulerConfig {
389 fn default() -> Self {
390 Self {
391 enabled: true,
392 tick_interval_secs: default_scheduler_tick_interval(),
393 max_tasks: default_scheduler_max_tasks(),
394 tasks: Vec::new(),
395 }
396 }
397}
398
399#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
403#[serde(rename_all = "snake_case")]
404pub enum ScheduledTaskKind {
405 MemoryCleanup,
406 SkillRefresh,
407 HealthCheck,
408 UpdateCheck,
409 Experiment,
410 Custom(String),
411}
412
413#[derive(Debug, Clone, Deserialize, Serialize)]
414pub struct ScheduledTaskConfig {
415 pub name: String,
416 #[serde(default, skip_serializing_if = "Option::is_none")]
417 pub cron: Option<String>,
418 #[serde(default, skip_serializing_if = "Option::is_none")]
419 pub run_at: Option<String>,
420 pub kind: ScheduledTaskKind,
421 #[serde(default)]
422 pub config: serde_json::Value,
423}
424
425fn default_trace_service_name() -> String {
426 "zeph".into()
427}
428
429#[derive(Debug, Clone, Deserialize, Serialize)]
436#[serde(default)]
437pub struct TraceConfig {
438 #[serde(default = "default_otlp_endpoint")]
441 pub otlp_endpoint: String,
442 #[serde(default = "default_trace_service_name")]
444 pub service_name: String,
445 #[serde(default = "default_true")]
447 pub redact: bool,
448}
449
450impl Default for TraceConfig {
451 fn default() -> Self {
452 Self {
453 otlp_endpoint: default_otlp_endpoint(),
454 service_name: default_trace_service_name(),
455 redact: true,
456 }
457 }
458}
459
460#[derive(Debug, Clone, Deserialize, Serialize)]
461#[serde(default)]
462pub struct DebugConfig {
463 pub enabled: bool,
465 #[serde(default = "crate::defaults::default_debug_output_dir")]
467 pub output_dir: std::path::PathBuf,
468 pub format: crate::dump_format::DumpFormat,
470 pub traces: TraceConfig,
472}
473
474impl Default for DebugConfig {
475 fn default() -> Self {
476 Self {
477 enabled: false,
478 output_dir: super::defaults::default_debug_output_dir(),
479 format: crate::dump_format::DumpFormat::default(),
480 traces: TraceConfig::default(),
481 }
482 }
483}