1use std::fs::{self, OpenOptions};
7use std::io::Write;
8use std::path::{Path, PathBuf};
9
10use crate::paths;
11
12pub fn events_dir() -> PathBuf {
14 paths::events_dir()
15}
16
17pub fn write_event(session_id: &str, cwd: &str, pane_id: &str, state: &str) -> Result<(), String> {
19 write_event_to(&events_dir(), session_id, cwd, pane_id, state)
20}
21
22pub fn write_event_to(
24 dir: &Path,
25 session_id: &str,
26 cwd: &str,
27 pane_id: &str,
28 state: &str,
29) -> Result<(), String> {
30 fs::create_dir_all(dir).map_err(|e| format!("create events dir: {e}"))?;
31
32 let path = dir.join(format!("{session_id}.jsonl"));
33 let mut file = OpenOptions::new()
34 .create(true)
35 .append(true)
36 .open(&path)
37 .map_err(|e| format!("open event file: {e}"))?;
38
39 let ts = std::time::SystemTime::now()
40 .duration_since(std::time::UNIX_EPOCH)
41 .unwrap_or_default()
42 .as_secs();
43
44 let line = format!(r#"{{"state":"{state}","cwd":"{cwd}","pane_id":"{pane_id}","ts":{ts}}}"#);
45 writeln!(file, "{line}").map_err(|e| format!("write event: {e}"))?;
46
47 Ok(())
48}
49
50pub fn find_session_id(pane_id: &str) -> Option<String> {
54 find_session_id_in(&events_dir(), pane_id)
55}
56
57pub fn find_session_id_in(dir: &Path, pane_id: &str) -> Option<String> {
59 let entries = fs::read_dir(dir).ok()?;
60
61 let mut best: Option<(String, u64)> = None;
62 for entry in entries.flatten() {
63 let path = entry.path();
64 if path.extension().and_then(|e| e.to_str()) != Some("jsonl") {
65 continue;
66 }
67 let content = fs::read_to_string(&path).unwrap_or_default();
68 let last_line = content.lines().rev().find(|l| !l.trim().is_empty());
69 if let Some(line) = last_line {
70 if let Ok(event) = serde_json::from_str::<serde_json::Value>(line) {
71 if event.get("pane_id").and_then(|v| v.as_str()) == Some(pane_id) {
72 let ts = event.get("ts").and_then(|v| v.as_u64()).unwrap_or(0);
73 if best.as_ref().is_none_or(|(_, prev_ts)| ts > *prev_ts) {
74 if let Some(sid) = path.file_stem().and_then(|s| s.to_str()) {
75 best = Some((sid.to_string(), ts));
76 }
77 }
78 }
79 }
80 }
81 }
82
83 best.map(|(sid, _)| sid)
84}