Skip to main content

codetether_agent/session/
listing_all.rs

1use super::codex_import::discover_codex_sessions_for_directory;
2use super::listing::{SessionSummary, list_sessions_for_directory};
3use anyhow::Result;
4use std::collections::HashMap;
5use std::path::Path;
6
7pub fn list_codex_sessions_for_directory(dir: &Path) -> Result<Vec<SessionSummary>> {
8    Ok(discover_codex_sessions_for_directory(dir)?
9        .into_iter()
10        .map(|session| SessionSummary {
11            id: session.id.clone(),
12            title: Some(format!("[Codex] {}", session.title.unwrap_or(session.id))),
13            created_at: session.created_at,
14            updated_at: session.updated_at,
15            message_count: session.message_count,
16            agent: session.agent,
17            directory: session.directory,
18        })
19        .collect())
20}
21
22pub async fn list_all_sessions_for_directory(dir: &Path) -> Result<Vec<SessionSummary>> {
23    tracing::info!(dir = %dir.display(), "list_all_sessions_for_directory: starting");
24    let mut merged = HashMap::<String, SessionSummary>::new();
25
26    let native = list_sessions_for_directory(dir).await?;
27    tracing::info!(
28        native_count = native.len(),
29        "list_all_sessions_for_directory: native sessions"
30    );
31
32    for session in native {
33        merged.insert(session.id.clone(), session);
34    }
35
36    let codex = match list_codex_sessions_for_directory(dir) {
37        Ok(c) => {
38            tracing::info!(
39                codex_count = c.len(),
40                "list_all_sessions_for_directory: codex sessions"
41            );
42            c
43        }
44        Err(err) => {
45            tracing::warn!(error = %err, "list_all_sessions_for_directory: codex discovery failed");
46            Vec::new()
47        }
48    };
49
50    for session in codex {
51        match merged.get(&session.id) {
52            Some(existing) if existing.updated_at >= session.updated_at => {}
53            _ => {
54                merged.insert(session.id.clone(), session);
55            }
56        }
57    }
58
59    let mut sessions = merged.into_values().collect::<Vec<_>>();
60    sessions.sort_by(|a, b| b.updated_at.cmp(&a.updated_at));
61    tracing::info!(
62        total = sessions.len(),
63        "list_all_sessions_for_directory: done"
64    );
65    Ok(sessions)
66}
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71    use std::path::Path;
72
73    #[tokio::test]
74    async fn test_list_sessions_real_directory() {
75        let dir = Path::new("/home/riley/A2A-Server-MCP/codetether-agent");
76        let result = list_all_sessions_for_directory(dir).await;
77        match &result {
78            Ok(sessions) => eprintln!("Found {} sessions", sessions.len()),
79            Err(err) => eprintln!("Error: {err}"),
80        }
81        assert!(
82            result.is_ok(),
83            "list_all_sessions_for_directory should not error"
84        );
85    }
86
87    #[test]
88    fn test_list_codex_sessions_real_directory() {
89        let dir = Path::new("/home/riley/A2A-Server-MCP/codetether-agent");
90        let result = list_codex_sessions_for_directory(dir);
91        match &result {
92            Ok(sessions) => eprintln!("Found {} codex sessions", sessions.len()),
93            Err(err) => eprintln!("Codex error: {err}"),
94        }
95        assert!(
96            result.is_ok(),
97            "list_codex_sessions_for_directory should not error"
98        );
99    }
100}