Skip to main content

reliary_core/
session.rs

1/// Session state: accumulated from Pi JSONL session file events
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4
5#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6pub struct ReadRecord {
7    pub path: String,
8    pub size: usize,
9    pub hash: String,
10    pub is_rerun: bool,
11}
12
13#[derive(Debug, Clone, Default, Serialize, Deserialize)]
14pub struct EditRecord {
15    pub file: String,
16    pub line: String,
17    pub attempt: usize,
18    pub old_snippet: String,
19    pub new_snippet: String,
20    pub success: bool,
21}
22
23#[derive(Debug, Clone, Default, Serialize, Deserialize)]
24pub struct ErrorRecord {
25    pub turn: usize,
26    pub summary: String,
27}
28
29#[derive(Debug, Clone, Default, Serialize, Deserialize)]
30pub struct SessionState {
31    pub turn_count: usize,
32    pub reads: Vec<ReadRecord>,
33    pub edits: Vec<EditRecord>,
34    pub last_test_output: Option<String>,
35    pub last_test_pass: bool,
36    pub errors: Vec<ErrorRecord>,
37    pub file_hashes: HashMap<String, u64>,
38}
39
40impl SessionState {
41    pub fn read_summary(&self) -> Vec<ReadRecord> {
42        let mut seen = HashMap::new();
43        let mut unique: Vec<ReadRecord> = Vec::new();
44        for r in self.reads.iter().rev() {
45            let key = format!("{}{}", r.path, r.hash);
46            if let std::collections::hash_map::Entry::Vacant(e) = seen.entry(key) {
47                e.insert(true);
48                unique.push(r.clone());
49            }
50        }
51        unique.into_iter().rev().collect()
52    }
53
54    pub fn edited_files(&self) -> Vec<String> {
55        let mut files: Vec<String> = self.edits.iter().map(|e| e.file.clone()).collect();
56        files.sort();
57        files.dedup();
58        files
59    }
60}