1use 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 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}