codetether_agent/tui/ui/chat_view/
format_cache.rs1use std::cell::RefCell;
8use std::collections::HashMap;
9
10use ratatui::text::Line;
11
12use crate::tui::chat::message::ChatMessage;
13use crate::tui::message_formatter::MessageFormatter;
14
15type Key = (u128, usize, usize, u8);
16const CACHE_CAP: usize = 512;
17
18thread_local! {
19 static FORMAT_CACHE: RefCell<HashMap<Key, Vec<Line<'static>>>> =
20 RefCell::new(HashMap::with_capacity(128));
21}
22
23fn role_discrim(r: &str) -> u8 {
24 match r {
25 "user" => 1,
26 "assistant" => 2,
27 "system" => 3,
28 "error" => 4,
29 _ => 0,
30 }
31}
32
33fn ts_nanos(m: &ChatMessage) -> u128 {
34 m.timestamp
35 .duration_since(std::time::UNIX_EPOCH)
36 .map(|d| d.as_nanos())
37 .unwrap_or(0)
38}
39
40pub fn format_message_cached(
42 message: &ChatMessage,
43 role: &str,
44 formatter: &MessageFormatter,
45 max_width: usize,
46) -> Vec<Line<'static>> {
47 let key = (
48 ts_nanos(message),
49 message.content.len(),
50 max_width,
51 role_discrim(role),
52 );
53 FORMAT_CACHE.with(|c| {
54 if let Some(l) = c.borrow().get(&key) {
55 return l.clone();
56 }
57 let lines = formatter.format_content(&message.content, role);
58 let mut m = c.borrow_mut();
59 if m.len() >= CACHE_CAP {
60 m.clear();
61 }
62 m.insert(key, lines.clone());
63 lines
64 })
65}
66
67pub fn reset_format_cache() {
69 FORMAT_CACHE.with(|c| c.borrow_mut().clear());
70}