vtcode_core/utils/
transcript.rs1use once_cell::sync::Lazy;
2use parking_lot::RwLock;
3
4const MAX_LINES: usize = 4000;
5
6static TRANSCRIPT: Lazy<RwLock<Vec<String>>> = Lazy::new(|| RwLock::new(Vec::new()));
7
8pub fn append(line: &str) {
9 let mut log = TRANSCRIPT.write();
10 if log.len() == MAX_LINES {
11 let drop_count = MAX_LINES / 5;
12 log.drain(0..drop_count);
13 }
14 log.push(line.to_string());
15}
16
17pub fn snapshot() -> Vec<String> {
18 TRANSCRIPT.read().clone()
19}
20
21pub fn len() -> usize {
22 TRANSCRIPT.read().len()
23}
24
25pub fn clear() {
26 TRANSCRIPT.write().clear();
27}
28
29#[cfg(test)]
30mod tests {
31 use super::*;
32
33 #[test]
34 fn append_and_snapshot_store_lines() {
35 clear();
36 append("first");
37 append("second");
38 assert_eq!(len(), 2);
39 let snap = snapshot();
40 assert_eq!(snap, vec!["first".to_string(), "second".to_string()]);
41 clear();
42 }
43
44 #[test]
45 fn transcript_drops_oldest_chunk_when_full() {
46 clear();
47 for idx in 0..MAX_LINES {
48 append(&format!("line {idx}"));
49 }
50 assert_eq!(len(), MAX_LINES);
51 for extra in 0..10 {
52 append(&format!("extra {extra}"));
53 }
54 assert_eq!(len(), MAX_LINES - (MAX_LINES / 5) + 10);
55 let snap = snapshot();
56 assert_eq!(snap.first().unwrap(), &format!("line {}", MAX_LINES / 5));
57 clear();
58 }
59}