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