1use serde::{Deserialize, Serialize};
5
6use crate::defaults::{default_skill_paths, default_true};
7use crate::learning::LearningConfig;
8use crate::security::TrustConfig;
9
10fn default_disambiguation_threshold() -> f32 {
11 0.20
12}
13
14fn default_min_injection_score() -> f32 {
15 0.20
16}
17
18fn default_cosine_weight() -> f32 {
19 0.7
20}
21
22fn default_hybrid_search() -> bool {
23 true
24}
25
26fn default_max_active_skills() -> usize {
27 5
28}
29
30fn default_index_watch() -> bool {
31 true
32}
33
34fn default_index_search_enabled() -> bool {
35 true
36}
37
38fn default_index_max_chunks() -> usize {
39 12
40}
41
42fn default_index_score_threshold() -> f32 {
43 0.25
44}
45
46fn default_index_budget_ratio() -> f32 {
47 0.40
48}
49
50fn default_index_repo_map_tokens() -> usize {
51 500
52}
53
54fn default_repo_map_ttl_secs() -> u64 {
55 300
56}
57
58fn default_vault_backend() -> String {
59 "env".into()
60}
61
62fn default_max_daily_cents() -> u32 {
63 0
64}
65
66fn default_otlp_endpoint() -> String {
67 "http://localhost:4317".into()
68}
69
70fn default_pid_file() -> String {
71 "~/.zeph/zeph.pid".into()
72}
73
74fn default_health_interval() -> u64 {
75 30
76}
77
78fn default_max_restart_backoff() -> u64 {
79 60
80}
81
82fn default_scheduler_tick_interval() -> u64 {
83 60
84}
85
86fn default_scheduler_max_tasks() -> usize {
87 100
88}
89
90fn default_gateway_bind() -> String {
91 "127.0.0.1".into()
92}
93
94fn default_gateway_port() -> u16 {
95 8090
96}
97
98fn default_gateway_rate_limit() -> u32 {
99 120
100}
101
102fn default_gateway_max_body() -> usize {
103 1_048_576
104}
105
106#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Deserialize, Serialize)]
108#[serde(rename_all = "lowercase")]
109pub enum SkillPromptMode {
110 Full,
111 Compact,
112 #[default]
113 Auto,
114}
115
116#[derive(Debug, Deserialize, Serialize)]
117pub struct SkillsConfig {
118 #[serde(default = "default_skill_paths")]
119 pub paths: Vec<String>,
120 #[serde(default = "default_max_active_skills")]
121 pub max_active_skills: usize,
122 #[serde(default = "default_disambiguation_threshold")]
123 pub disambiguation_threshold: f32,
124 #[serde(default = "default_min_injection_score")]
125 pub min_injection_score: f32,
126 #[serde(default = "default_cosine_weight")]
127 pub cosine_weight: f32,
128 #[serde(default = "default_hybrid_search")]
129 pub hybrid_search: bool,
130 #[serde(default)]
131 pub learning: LearningConfig,
132 #[serde(default)]
133 pub trust: TrustConfig,
134 #[serde(default)]
135 pub prompt_mode: SkillPromptMode,
136 #[serde(default)]
139 pub two_stage_matching: bool,
140 #[serde(default)]
143 pub confusability_threshold: f32,
144}
145
146#[derive(Debug, Deserialize, Serialize)]
147pub struct IndexConfig {
148 #[serde(default)]
149 pub enabled: bool,
150 #[serde(default = "default_index_search_enabled")]
151 pub search_enabled: bool,
152 #[serde(default = "default_index_watch")]
153 pub watch: bool,
154 #[serde(default = "default_index_max_chunks")]
155 pub max_chunks: usize,
156 #[serde(default = "default_index_score_threshold")]
157 pub score_threshold: f32,
158 #[serde(default = "default_index_budget_ratio")]
159 pub budget_ratio: f32,
160 #[serde(default = "default_index_repo_map_tokens")]
161 pub repo_map_tokens: usize,
162 #[serde(default = "default_repo_map_ttl_secs")]
163 pub repo_map_ttl_secs: u64,
164}
165
166impl Default for IndexConfig {
167 fn default() -> Self {
168 Self {
169 enabled: false,
170 search_enabled: default_index_search_enabled(),
171 watch: default_index_watch(),
172 max_chunks: default_index_max_chunks(),
173 score_threshold: default_index_score_threshold(),
174 budget_ratio: default_index_budget_ratio(),
175 repo_map_tokens: default_index_repo_map_tokens(),
176 repo_map_ttl_secs: default_repo_map_ttl_secs(),
177 }
178 }
179}
180
181#[derive(Debug, Deserialize, Serialize)]
182pub struct VaultConfig {
183 #[serde(default = "default_vault_backend")]
184 pub backend: String,
185}
186
187impl Default for VaultConfig {
188 fn default() -> Self {
189 Self {
190 backend: default_vault_backend(),
191 }
192 }
193}
194
195#[derive(Debug, Deserialize, Serialize)]
196pub struct CostConfig {
197 #[serde(default = "default_true")]
198 pub enabled: bool,
199 #[serde(default = "default_max_daily_cents")]
200 pub max_daily_cents: u32,
201}
202
203impl Default for CostConfig {
204 fn default() -> Self {
205 Self {
206 enabled: true,
207 max_daily_cents: default_max_daily_cents(),
208 }
209 }
210}
211
212#[derive(Debug, Deserialize, Serialize)]
213pub struct ObservabilityConfig {
214 #[serde(default)]
215 pub exporter: String,
216 #[serde(default = "default_otlp_endpoint")]
217 pub endpoint: String,
218}
219
220impl Default for ObservabilityConfig {
221 fn default() -> Self {
222 Self {
223 exporter: String::new(),
224 endpoint: default_otlp_endpoint(),
225 }
226 }
227}
228
229#[derive(Debug, Clone, Deserialize, Serialize)]
230pub struct GatewayConfig {
231 #[serde(default)]
232 pub enabled: bool,
233 #[serde(default = "default_gateway_bind")]
234 pub bind: String,
235 #[serde(default = "default_gateway_port")]
236 pub port: u16,
237 #[serde(default)]
238 pub auth_token: Option<String>,
239 #[serde(default = "default_gateway_rate_limit")]
240 pub rate_limit: u32,
241 #[serde(default = "default_gateway_max_body")]
242 pub max_body_size: usize,
243}
244
245impl Default for GatewayConfig {
246 fn default() -> Self {
247 Self {
248 enabled: false,
249 bind: default_gateway_bind(),
250 port: default_gateway_port(),
251 auth_token: None,
252 rate_limit: default_gateway_rate_limit(),
253 max_body_size: default_gateway_max_body(),
254 }
255 }
256}
257
258#[derive(Debug, Clone, Deserialize, Serialize)]
259pub struct DaemonConfig {
260 #[serde(default)]
261 pub enabled: bool,
262 #[serde(default = "default_pid_file")]
263 pub pid_file: String,
264 #[serde(default = "default_health_interval")]
265 pub health_interval_secs: u64,
266 #[serde(default = "default_max_restart_backoff")]
267 pub max_restart_backoff_secs: u64,
268}
269
270impl Default for DaemonConfig {
271 fn default() -> Self {
272 Self {
273 enabled: false,
274 pid_file: default_pid_file(),
275 health_interval_secs: default_health_interval(),
276 max_restart_backoff_secs: default_max_restart_backoff(),
277 }
278 }
279}
280
281#[derive(Debug, Clone, Deserialize, Serialize)]
282pub struct SchedulerConfig {
283 #[serde(default)]
284 pub enabled: bool,
285 #[serde(default = "default_scheduler_tick_interval")]
286 pub tick_interval_secs: u64,
287 #[serde(default = "default_scheduler_max_tasks")]
288 pub max_tasks: usize,
289 #[serde(default)]
290 pub tasks: Vec<ScheduledTaskConfig>,
291}
292
293impl Default for SchedulerConfig {
294 fn default() -> Self {
295 Self {
296 enabled: true,
297 tick_interval_secs: default_scheduler_tick_interval(),
298 max_tasks: default_scheduler_max_tasks(),
299 tasks: Vec::new(),
300 }
301 }
302}
303
304#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
308#[serde(rename_all = "snake_case")]
309pub enum ScheduledTaskKind {
310 MemoryCleanup,
311 SkillRefresh,
312 HealthCheck,
313 UpdateCheck,
314 Experiment,
315 Custom(String),
316}
317
318#[derive(Debug, Clone, Deserialize, Serialize)]
319pub struct ScheduledTaskConfig {
320 pub name: String,
321 #[serde(default, skip_serializing_if = "Option::is_none")]
322 pub cron: Option<String>,
323 #[serde(default, skip_serializing_if = "Option::is_none")]
324 pub run_at: Option<String>,
325 pub kind: ScheduledTaskKind,
326 #[serde(default)]
327 pub config: serde_json::Value,
328}
329
330fn default_trace_service_name() -> String {
331 "zeph".into()
332}
333
334#[derive(Debug, Clone, Deserialize, Serialize)]
341#[serde(default)]
342pub struct TraceConfig {
343 #[serde(default = "default_otlp_endpoint")]
346 pub otlp_endpoint: String,
347 #[serde(default = "default_trace_service_name")]
349 pub service_name: String,
350 #[serde(default = "default_true")]
352 pub redact: bool,
353}
354
355impl Default for TraceConfig {
356 fn default() -> Self {
357 Self {
358 otlp_endpoint: default_otlp_endpoint(),
359 service_name: default_trace_service_name(),
360 redact: true,
361 }
362 }
363}
364
365#[derive(Debug, Clone, Deserialize, Serialize)]
366#[serde(default)]
367pub struct DebugConfig {
368 pub enabled: bool,
370 #[serde(default = "crate::defaults::default_debug_output_dir")]
372 pub output_dir: std::path::PathBuf,
373 pub format: crate::dump_format::DumpFormat,
375 pub traces: TraceConfig,
377}
378
379impl Default for DebugConfig {
380 fn default() -> Self {
381 Self {
382 enabled: false,
383 output_dir: super::defaults::default_debug_output_dir(),
384 format: crate::dump_format::DumpFormat::default(),
385 traces: TraceConfig::default(),
386 }
387 }
388}