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