Skip to main content

reliary_core/
session.rs

1/// Session state: accumulated from Pi JSONL session file events
2use serde::{Deserialize, Serialize};
3use rustc_hash::FxHashMap;
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: FxHashMap<String, u64>,
38}
39
40impl SessionState {
41    pub fn read_summary(&self) -> Vec<ReadRecord> {
42        // D19: Borrow instead of clone. Dedup key is (path, hash) borrowed from the record.
43        let mut seen: FxHashMap<(&str, &str), ()> = FxHashMap::default();
44        let mut unique: Vec<&ReadRecord> = Vec::with_capacity(self.reads.len());
45        for r in self.reads.iter().rev() {
46            if seen.insert((r.path.as_str(), r.hash.as_str()), ()).is_none() {
47                unique.push(r);
48            }
49        }
50        unique.into_iter().rev().cloned().collect()
51    }
52}