(
&self,
state: &mut ExecutionLoopState,
response: &LlmResponse,
session_id: Option<&str>,
event_tx: &Option<mpsc::Sender<AgentEvent>>,
)
| 274 | } |
| 275 | |
| 276 | async fn maybe_auto_compact( |
| 277 | &self, |
| 278 | state: &mut ExecutionLoopState, |
| 279 | response: &LlmResponse, |
| 280 | session_id: Option<&str>, |
| 281 | event_tx: &Option<mpsc::Sender<AgentEvent>>, |
| 282 | ) { |
| 283 | if !self.config.auto_compact { |
| 284 | return; |
| 285 | } |
| 286 | |
| 287 | let used = response.usage.prompt_tokens; |
| 288 | let max = self.config.max_context_tokens; |
| 289 | let threshold = self.config.auto_compact_threshold; |
| 290 | |
| 291 | if !crate::compaction::should_auto_compact(used, max, threshold) { |
| 292 | return; |
| 293 | } |
| 294 | |
| 295 | let before_len = state.messages.len(); |
| 296 | let percent_before = used as f32 / max as f32; |
| 297 | |
| 298 | tracing::info!( |
| 299 | used_tokens = used, |
| 300 | max_tokens = max, |
| 301 | percent = percent_before, |
| 302 | threshold = threshold, |
| 303 | "Auto-compact triggered" |
| 304 | ); |
| 305 | |
| 306 | if let Some(pruned) = crate::compaction::prune_tool_outputs(&state.messages) { |
| 307 | state.messages = pruned; |
| 308 | tracing::info!("Tool output pruning applied"); |
| 309 | } |
| 310 | |
| 311 | if let Ok(Some(compacted)) = crate::compaction::compact_messages( |
| 312 | session_id.unwrap_or(""), |
| 313 | &state.messages, |
| 314 | &self.llm_client, |
| 315 | ) |
| 316 | .await |
| 317 | { |
| 318 | state.messages = compacted; |
| 319 | } |
| 320 | |
| 321 | if let Some(tx) = event_tx { |
| 322 | tx.send(AgentEvent::ContextCompacted { |
| 323 | session_id: session_id.unwrap_or("").to_string(), |
| 324 | before_messages: before_len, |
| 325 | after_messages: state.messages.len(), |
| 326 | percent_before, |
| 327 | }) |
| 328 | .await |
| 329 | .ok(); |
| 330 | } |
| 331 | } |
| 332 | |
| 333 | async fn emit_error(&self, event_tx: &Option<mpsc::Sender<AgentEvent>>, message: String) { |
no test coverage detected