vtcode_core/utils/
transcript.rs

1use 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}