Skip to main content

retro_core/
observer.rs

1use std::path::{Path, PathBuf};
2use std::time::SystemTime;
3
4/// A session file that has been modified since last check.
5#[derive(Debug, Clone)]
6pub struct ModifiedSession {
7    pub path: PathBuf,
8    pub mtime: SystemTime,
9}
10
11/// Scan the Claude Code projects directory for session files modified since `since`.
12/// If `since` is None, returns all session files.
13pub fn find_modified_sessions(claude_dir: &Path, since: Option<SystemTime>) -> Vec<ModifiedSession> {
14    let projects_dir = claude_dir.join("projects");
15    if !projects_dir.exists() {
16        return Vec::new();
17    }
18
19    let mut results = Vec::new();
20    let pattern = format!("{}/**/*.jsonl", projects_dir.display());
21    for entry in glob::glob(&pattern).unwrap_or_else(|_| glob::glob("").unwrap()) {
22        if let Ok(path) = entry {
23            if let Ok(metadata) = std::fs::metadata(&path) {
24                if let Ok(mtime) = metadata.modified() {
25                    let dominated = match since {
26                        Some(since_time) => mtime > since_time,
27                        None => true,
28                    };
29                    if dominated {
30                        results.push(ModifiedSession { path, mtime });
31                    }
32                }
33            }
34        }
35    }
36    results
37}
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42    use tempfile::TempDir;
43    use std::fs;
44
45    #[test]
46    fn test_find_modified_sessions_detects_new_files() {
47        let dir = TempDir::new().unwrap();
48        let sessions_dir = dir.path().join("projects").join("test-project");
49        fs::create_dir_all(&sessions_dir).unwrap();
50
51        let session_file = sessions_dir.join("session1.jsonl");
52        fs::write(&session_file, "{}\n").unwrap();
53
54        let modified = find_modified_sessions(dir.path(), None);
55        assert_eq!(modified.len(), 1);
56        assert!(modified[0].path.ends_with("session1.jsonl"));
57    }
58
59    #[test]
60    fn test_find_modified_sessions_skips_unchanged() {
61        let dir = TempDir::new().unwrap();
62        let sessions_dir = dir.path().join("projects").join("test-project");
63        fs::create_dir_all(&sessions_dir).unwrap();
64
65        let session_file = sessions_dir.join("session1.jsonl");
66        fs::write(&session_file, "{}\n").unwrap();
67
68        let mtime = fs::metadata(&session_file).unwrap()
69            .modified().unwrap();
70
71        let modified = find_modified_sessions(dir.path(), Some(mtime));
72        assert_eq!(modified.len(), 0);
73    }
74}