1use std::sync::Arc;
5
6use crate::config::{
7 Config, DebugConfig, DocumentConfig, GraphConfig, LearningConfig, OrchestrationConfig,
8 PersonaConfig, SecurityConfig, TimeoutConfig,
9};
10use crate::vault::Secret;
11
12pub const CONTEXT_BUDGET_RESERVE_RATIO: f32 = 0.20;
16
17#[derive(Clone)]
49#[allow(clippy::struct_excessive_bools)] pub struct AgentSessionConfig {
51 pub max_tool_iterations: usize,
53 pub max_tool_retries: usize,
54 pub max_retry_duration_secs: u64,
55 pub retry_base_ms: u64,
56 pub retry_max_ms: u64,
57 pub parameter_reformat_provider: String,
58 pub tool_repeat_threshold: usize,
59 pub tool_summarization: bool,
60 pub tool_call_cutoff: usize,
61 pub max_tool_calls_per_session: Option<u32>,
62 pub overflow_config: zeph_tools::OverflowConfig,
63 pub permission_policy: zeph_tools::PermissionPolicy,
64
65 pub model_name: String,
67 pub embed_model: String,
68
69 pub semantic_cache_enabled: bool,
71 pub semantic_cache_threshold: f32,
72 pub semantic_cache_max_candidates: u32,
73
74 pub budget_tokens: usize,
76 pub soft_compaction_threshold: f32,
77 pub hard_compaction_threshold: f32,
78 pub compaction_preserve_tail: usize,
79 pub compaction_cooldown_turns: u8,
80 pub prune_protect_tokens: usize,
81 pub redact_credentials: bool,
82
83 pub security: SecurityConfig,
85 pub timeouts: TimeoutConfig,
86
87 pub learning: LearningConfig,
89 pub document_config: DocumentConfig,
90 pub graph_config: GraphConfig,
91 pub persona_config: PersonaConfig,
92 pub trajectory_config: crate::config::TrajectoryConfig,
93 pub category_config: crate::config::CategoryConfig,
94 pub reasoning_config: zeph_config::ReasoningConfig,
95 pub memcot_config: zeph_config::MemCotConfig,
96 pub tree_config: crate::config::TreeConfig,
97 pub microcompact_config: crate::config::MicrocompactConfig,
98 pub autodream_config: crate::config::AutoDreamConfig,
99 pub magic_docs_config: crate::config::MagicDocsConfig,
100 pub acon_config: zeph_config::AconConfig,
102 pub arc_config: zeph_config::ArcCompactionConfig,
104 pub anomaly_config: zeph_tools::AnomalyConfig,
105 pub result_cache_config: zeph_tools::ResultCacheConfig,
106 pub utility_config: zeph_tools::UtilityScoringConfig,
107 pub orchestration_config: OrchestrationConfig,
108 pub debug_config: DebugConfig,
109 pub server_compaction: bool,
110
111 pub budget_hint_enabled: bool,
113
114 pub recap: zeph_config::RecapConfig,
116
117 pub loop_min_interval_secs: u64,
119
120 pub goal_config: zeph_config::GoalConfig,
122
123 pub secrets: Arc<[(String, Secret)]>,
129
130 pub fidelity_config: Option<zeph_config::FidelityConfig>,
132}
133
134impl AgentSessionConfig {
135 #[must_use]
140 pub fn from_config(config: &Config, budget_tokens: usize) -> Self {
141 Self {
142 max_tool_iterations: config.agent.max_tool_iterations,
143 max_tool_retries: config.tools.retry.max_attempts,
144 max_retry_duration_secs: config.tools.retry.budget_secs,
145 retry_base_ms: config.tools.retry.base_ms,
146 retry_max_ms: config.tools.retry.max_ms,
147 parameter_reformat_provider: config.tools.retry.parameter_reformat_provider.to_string(),
148 tool_repeat_threshold: config.agent.tool_repeat_threshold,
149 tool_summarization: config.tools.summarize_output,
150 tool_call_cutoff: config.memory.tool_call_cutoff,
151 max_tool_calls_per_session: config.tools.max_tool_calls_per_session,
152 overflow_config: config.tools.overflow.clone(),
153 permission_policy: zeph_tools::build_permission_policy(
154 &config.tools,
155 config.security.autonomy_level,
156 ),
157 model_name: config.llm.effective_model().to_owned(),
158 embed_model: config.llm.stable_skill_embedding_model(),
159 semantic_cache_enabled: config.llm.semantic_cache_enabled,
160 semantic_cache_threshold: config.llm.semantic_cache_threshold,
161 semantic_cache_max_candidates: config.llm.semantic_cache_max_candidates,
162 budget_tokens,
163 soft_compaction_threshold: config.memory.soft_compaction_threshold,
164 hard_compaction_threshold: config.memory.hard_compaction_threshold,
165 compaction_preserve_tail: config.memory.compaction_preserve_tail,
166 compaction_cooldown_turns: config.memory.compaction_cooldown_turns,
167 prune_protect_tokens: config.memory.prune_protect_tokens,
168 redact_credentials: config.memory.redact_credentials,
169 security: config.security.clone(),
170 timeouts: config.timeouts,
171 learning: config.skills.learning.clone(),
172 document_config: config.memory.documents.clone(),
173 graph_config: config.memory.graph.clone(),
174 persona_config: config.memory.persona.clone(),
175 trajectory_config: config.memory.trajectory.clone(),
176 category_config: config.memory.category.clone(),
177 reasoning_config: config.memory.reasoning.clone(),
178 memcot_config: config.memory.memcot.clone(),
179 tree_config: config.memory.tree.clone(),
180 microcompact_config: config.memory.microcompact.clone(),
181 autodream_config: config.memory.autodream.clone(),
182 magic_docs_config: config.magic_docs.clone(),
183 acon_config: config.memory.compression.acon.clone(),
184 arc_config: config.memory.compression.arc.clone(),
185 anomaly_config: config.tools.anomaly.clone(),
186 result_cache_config: config.tools.result_cache.clone(),
187 utility_config: config.tools.utility.clone(),
188 orchestration_config: config.orchestration.clone(),
189 debug_config: config.debug.clone(),
190 server_compaction: config.llm.providers.iter().any(|e| e.server_compaction),
191 budget_hint_enabled: config.agent.budget_hint_enabled,
192 secrets: config
193 .secrets
194 .custom
195 .iter()
196 .map(|(k, v)| (k.clone(), Secret::new(v.expose().to_owned())))
197 .collect::<Vec<_>>()
198 .into(),
199 recap: config.session.recap.clone(),
200 loop_min_interval_secs: config.cli.loop_.min_interval_secs,
201 goal_config: config.goals.clone(),
202 fidelity_config: {
203 let fc = config.memory.fidelity.clone();
204 if let Some(ref cfg) = fc
205 && let Err(e) = cfg.validate()
206 {
207 tracing::warn!("fidelity config invalid, scoring disabled: {e}");
208 }
209 fc
210 },
211 }
212 }
213}
214
215#[cfg(test)]
216mod tests {
217 use super::*;
218
219 #[test]
220 fn from_config_maps_all_fields() {
221 let config = Config::default();
222 let budget = 100_000;
223 let sc = AgentSessionConfig::from_config(&config, budget);
224
225 assert_eq!(sc.max_tool_iterations, config.agent.max_tool_iterations);
226 assert_eq!(sc.max_tool_retries, config.tools.retry.max_attempts);
227 assert_eq!(sc.max_retry_duration_secs, config.tools.retry.budget_secs);
228 assert_eq!(sc.retry_base_ms, config.tools.retry.base_ms);
229 assert_eq!(sc.retry_max_ms, config.tools.retry.max_ms);
230 assert_eq!(
231 sc.parameter_reformat_provider,
232 config.tools.retry.parameter_reformat_provider.as_str()
233 );
234 assert_eq!(sc.tool_repeat_threshold, config.agent.tool_repeat_threshold);
235 assert_eq!(sc.tool_summarization, config.tools.summarize_output);
236 assert_eq!(sc.tool_call_cutoff, config.memory.tool_call_cutoff);
237 assert_eq!(sc.model_name, config.llm.effective_model());
238 assert_eq!(sc.embed_model, config.llm.stable_skill_embedding_model());
239 assert_eq!(sc.semantic_cache_enabled, config.llm.semantic_cache_enabled);
240 assert!(
241 (sc.semantic_cache_threshold - config.llm.semantic_cache_threshold).abs()
242 < f32::EPSILON
243 );
244 assert_eq!(
245 sc.semantic_cache_max_candidates,
246 config.llm.semantic_cache_max_candidates
247 );
248 assert_eq!(sc.budget_tokens, budget);
249 assert!(
250 (sc.soft_compaction_threshold - config.memory.soft_compaction_threshold).abs()
251 < f32::EPSILON
252 );
253 assert!(
254 (sc.hard_compaction_threshold - config.memory.hard_compaction_threshold).abs()
255 < f32::EPSILON
256 );
257 assert_eq!(
258 sc.compaction_preserve_tail,
259 config.memory.compaction_preserve_tail
260 );
261 assert_eq!(
262 sc.compaction_cooldown_turns,
263 config.memory.compaction_cooldown_turns
264 );
265 assert_eq!(sc.prune_protect_tokens, config.memory.prune_protect_tokens);
266 assert_eq!(sc.redact_credentials, config.memory.redact_credentials);
267 assert_eq!(sc.graph_config.enabled, config.memory.graph.enabled);
268 assert_eq!(
269 sc.orchestration_config.enabled,
270 config.orchestration.enabled
271 );
272 assert_eq!(
273 sc.orchestration_config.max_tasks,
274 config.orchestration.max_tasks
275 );
276 assert_eq!(sc.anomaly_config.enabled, config.tools.anomaly.enabled);
277 assert_eq!(
278 sc.result_cache_config.enabled,
279 config.tools.result_cache.enabled
280 );
281 assert_eq!(
282 sc.result_cache_config.ttl_secs,
283 config.tools.result_cache.ttl_secs
284 );
285 assert_eq!(sc.debug_config.enabled, config.debug.enabled);
286 assert_eq!(
287 sc.document_config.rag_enabled,
288 config.memory.documents.rag_enabled
289 );
290 assert_eq!(
291 sc.overflow_config.threshold,
292 config.tools.overflow.threshold
293 );
294 assert_eq!(
295 sc.permission_policy.autonomy_level(),
296 config.security.autonomy_level
297 );
298 assert_eq!(sc.security.autonomy_level, config.security.autonomy_level);
299 assert_eq!(sc.timeouts.llm_seconds, config.timeouts.llm_seconds);
300 assert_eq!(sc.learning.enabled, config.skills.learning.enabled);
301 assert_eq!(
302 sc.server_compaction,
303 config.llm.providers.iter().any(|e| e.server_compaction)
304 );
305 assert_eq!(sc.secrets.len(), config.secrets.custom.len());
306 assert_eq!(sc.recap.on_resume, config.session.recap.on_resume);
307 assert_eq!(sc.recap.max_tokens, config.session.recap.max_tokens);
308 assert_eq!(sc.goal_config.enabled, config.goals.enabled);
309 assert_eq!(sc.goal_config.max_text_chars, config.goals.max_text_chars);
310 assert_eq!(
311 sc.fidelity_config.is_some(),
312 config.memory.fidelity.is_some()
313 );
314 }
315}