From 053e76a0a2bd8a049f020204661ea3916c8097d4 Mon Sep 17 00:00:00 2001 From: "Rodrigo Rodriguez (Pragmatismo)" Date: Fri, 7 Nov 2025 09:54:04 -0300 Subject: [PATCH] feat(prompt-compaction): add compacted message handling and forced compaction Refactored prompt compaction to use a special compacted message type (9) instead of clearing old messages. Added support for forced compaction when threshold is negative and updated history retrieval to skip messages before the last compacted marker. This improves efficiency and preserves summary continuity. --- src/automation/compact_prompt.rs | 23 +++++++++++------------ src/bot/mod.rs | 26 +++++++++++++++++--------- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/src/automation/compact_prompt.rs b/src/automation/compact_prompt.rs index ee8cd54b..bfa80ee5 100644 --- a/src/automation/compact_prompt.rs +++ b/src/automation/compact_prompt.rs @@ -84,11 +84,14 @@ async fn compact_prompt_for_bot( let config_manager = ConfigManager::new(Arc::clone(&state.conn)); let compact_threshold = config_manager .get_config(&automation.bot_id, "prompt-compact", None)? - .parse::() + .parse::() .unwrap_or(0); + // Compact if threshold is negative (always compact) or positive (conditional) if compact_threshold == 0 { return Ok(()); + } else if compact_threshold < 0 { + info!("Compaction forced for bot {} (threshold = {})", automation.bot_id, compact_threshold); } // Get sessions without holding lock @@ -153,17 +156,13 @@ async fn compact_prompt_for_bot( history.len() ); - // Remove all old messages and save only the summary - { - let mut session_manager = state.session_manager.lock().await; - // First delete all existing messages for this session - if let Err(e) = session_manager.clear_messages(session.id) { - error!("Failed to clear messages for session {}: {}", session.id, e); - return Err(e); - } - // Then save just the summary - session_manager.save_message(session.id, session.user_id, 3, &summarized, 1)?; - } + // Instead of clearing messages, insert a compacted marker message + { + let mut session_manager = state.session_manager.lock().await; + // Save a special compacted message type (9) + session_manager.save_message(session.id, session.user_id, 9, &summarized, 1)?; + trace!("Inserted compacted message for session {}", session.id); + } } Ok(()) diff --git a/src/bot/mod.rs b/src/bot/mod.rs index a97382fe..210c4562 100644 --- a/src/bot/mod.rs +++ b/src/bot/mod.rs @@ -405,15 +405,23 @@ impl BotOrchestrator { }; // Acquire lock briefly for history retrieval with configurable limit - let history = { - let mut sm = self.state.session_manager.lock().await; - let mut history = sm.get_conversation_history(session.id, user_id)?; - if history_limit > 0 && history.len() > history_limit as usize { - let start = history.len() - history_limit as usize; - history.drain(0..start); - } - history - }; +let history = { + let mut sm = self.state.session_manager.lock().await; + let mut history = sm.get_conversation_history(session.id, user_id)?; + + // Skip all messages before the most recent compacted message (type 9) + if let Some(last_compacted_index) = history.iter().rposition(|(role, content)| { + role == "COMPACTED" || content.starts_with("SUMMARY:") + }) { + history = history.split_off(last_compacted_index); + } + + if history_limit > 0 && history.len() > history_limit as usize { + let start = history.len() - history_limit as usize; + history.drain(0..start); + } + history +}; let mut prompt = String::new(); if !system_prompt.is_empty() {