Skip to main content

offline_intelligence/cache_management/
cache_bridge.rs

1//! Creates smooth transitions between cached and retrieved content
2use tracing::debug;
3
4/// Creates bridging sentences for smooth cache context transitions
5pub struct CacheContextBridge {
6    cache_history: Vec<CacheTransition>,
7    _max_history: usize, // Reserved for future adaptive history sizing
8    // Memory limits to prevent unbounded growth
9    max_transition_history: usize,
10}
11
12#[derive(Debug, Clone)]
13pub struct CacheTransition {
14    pub transition_type: TransitionType,
15    pub preserved_entries: usize,
16    pub retrieved_entries: usize,
17    pub timestamp: chrono::DateTime<chrono::Utc>,
18    pub keywords: Vec<String>,
19}
20
21#[derive(Debug, Clone)]
22pub enum TransitionType {
23    CacheCleared,
24    CacheRetrieved,
25    CacheRestored,
26    CacheExtended,
27}
28
29#[derive(Debug, Clone)]
30pub struct CacheBridgeStats {
31    pub total_transitions: usize,
32    pub avg_preserved_entries: f32,
33    pub avg_retrieved_entries: f32,
34    pub last_transition_type: Option<TransitionType>,
35}
36
37impl CacheContextBridge {
38    /// Create a new cache context bridge
39    pub fn new(max_history: usize) -> Self {
40        Self {
41            cache_history: Vec::new(),
42            _max_history: max_history,
43            max_transition_history: 50,
44        }
45    }
46
47    /// Create a bridge message when cache is cleared
48    pub fn create_clear_bridge(
49        &mut self,
50        cleared_count: usize,
51        preserved_count: usize,
52        keywords: &[String],
53    ) -> String {
54        self.record_transition(
55            TransitionType::CacheCleared,
56            preserved_count,
57            0,
58            keywords,
59        );
60        
61        let keyword_list = if keywords.is_empty() {
62            "various topics".to_string()
63        } else {
64            keywords.iter().take(3).cloned().collect::<Vec<_>>().join(", ")
65        };
66        
67        format!(
68            "[Cache Management] Cleared {} entries from cache, preserved {} important entries related to: {}. Continuing with optimized context.",
69            cleared_count, preserved_count, keyword_list
70        )
71    }
72
73    /// Create a bridge message when content is retrieved
74    pub fn create_retrieval_bridge(
75        &mut self,
76        retrieved_count: usize,
77        source_tier: u8,
78        keywords: &[String],
79        similarity_score: Option<f32>,
80    ) -> String {
81        self.record_transition(
82            TransitionType::CacheRetrieved,
83            0,
84            retrieved_count,
85            keywords,
86        );
87        
88        let source_desc = match source_tier {
89            1 => "active cache",
90            2 => "recent snapshots", 
91            3 => "long-term memory",
92            _ => "storage",
93        };
94        
95        let similarity_text = similarity_score
96            .map(|s| format!(" (similarity: {:.2})", s))
97            .unwrap_or_default();
98        
99        let keyword_list = if keywords.is_empty() {
100            "relevant context".to_string()
101        } else {
102            format!("'{}'", keywords.iter().take(3).cloned().collect::<Vec<_>>().join("', '"))
103        };
104        
105        format!(
106            "[Memory Retrieval] Retrieved {} entries from {} for {}{}. Integrating into current context.",
107            retrieved_count, source_desc, keyword_list, similarity_text
108        )
109    }
110
111    /// Create a bridge message when cache is restored
112    pub fn create_restore_bridge(
113        &mut self,
114        restored_count: usize,
115        snapshot_age: Option<std::time::Duration>,
116    ) -> String {
117        self.record_transition(
118            TransitionType::CacheRestored,
119            restored_count,
120            0,
121            &[],
122        );
123        
124        let age_text = snapshot_age
125            .map(|d| {
126                let minutes = d.as_secs() / 60;
127                if minutes > 0 {
128                    format!(" ({} minutes old)", minutes)
129                } else {
130                    String::new()
131                }
132            })
133            .unwrap_or_default();
134        
135        format!(
136            "[Cache Restoration] Restored {} entries from previous snapshot{}. Context has been expanded.",
137            restored_count, age_text
138        )
139    }
140
141    fn record_transition(
142        &mut self,
143        transition_type: TransitionType,
144        preserved: usize,
145        retrieved: usize,
146        keywords: &[String],
147    ) {
148        let transition = CacheTransition {
149            transition_type: transition_type.clone(),
150            preserved_entries: preserved,
151            retrieved_entries: retrieved,
152            timestamp: chrono::Utc::now(),
153            keywords: keywords.to_vec(),
154        };
155        
156        self.cache_history.push(transition);
157        
158        // Enforce memory limits
159        if self.cache_history.len() > self.max_transition_history {
160            let excess = self.cache_history.len() - self.max_transition_history;
161            self.cache_history.drain(0..excess);
162        }
163        
164        debug!("Recorded cache transition: {:?}", transition_type);
165    }
166
167    /// Get transition statistics
168    pub fn get_stats(&self) -> CacheBridgeStats {
169        let total = self.cache_history.len();
170        let avg_preserved = if total > 0 {
171            self.cache_history.iter().map(|t| t.preserved_entries).sum::<usize>() as f32 / total as f32
172        } else { 0.0 };
173        let avg_retrieved = if total > 0 {
174            self.cache_history.iter().map(|t| t.retrieved_entries).sum::<usize>() as f32 / total as f32
175        } else { 0.0 };
176        
177        CacheBridgeStats {
178            total_transitions: total,
179            avg_preserved_entries: avg_preserved,
180            avg_retrieved_entries: avg_retrieved,
181            last_transition_type: self.cache_history.last().map(|t| t.transition_type.clone()),
182        }
183    }
184
185    /// Clear transition history
186    pub fn clear_history(&mut self) {
187        self.cache_history.clear();
188        self.cache_history.shrink_to_fit();
189    }
190}