1use crate::types::*;
4use crate::parser::FafFile;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum CompressionLevel {
9 Minimal = 1,
11 Standard = 2,
13 Full = 3,
15}
16
17pub fn compress(faf: &FafFile, level: CompressionLevel) -> FafData {
45 match level {
46 CompressionLevel::Minimal => compress_minimal(faf),
47 CompressionLevel::Standard => compress_standard(faf),
48 CompressionLevel::Full => faf.data.clone(),
49 }
50}
51
52fn compress_minimal(faf: &FafFile) -> FafData {
53 FafData {
54 faf_version: faf.data.faf_version.clone(),
55 project: Project {
56 name: faf.data.project.name.clone(),
57 goal: faf.data.project.goal.clone(),
58 main_language: None,
59 approach: None,
60 version: None,
61 license: None,
62 },
63 ai_score: None,
64 ai_confidence: None,
65 ai_tldr: None,
66 instant_context: faf.data.instant_context.as_ref().map(|ic| InstantContext {
67 what_building: None,
68 tech_stack: ic.tech_stack.clone(),
69 deployment: None,
70 key_files: Vec::new(),
71 commands: Default::default(),
72 }),
73 context_quality: None,
74 stack: None,
75 human_context: None,
76 preferences: None,
77 state: None,
78 tags: Vec::new(),
79 }
80}
81
82fn compress_standard(faf: &FafFile) -> FafData {
83 FafData {
84 faf_version: faf.data.faf_version.clone(),
85 project: faf.data.project.clone(),
86 ai_score: faf.data.ai_score.clone(),
87 ai_confidence: None,
88 ai_tldr: None,
89 instant_context: faf.data.instant_context.as_ref().map(|ic| InstantContext {
90 what_building: ic.what_building.clone(),
91 tech_stack: ic.tech_stack.clone(),
92 deployment: None,
93 key_files: ic.key_files.iter().take(5).cloned().collect(),
94 commands: Default::default(),
95 }),
96 context_quality: None,
97 stack: faf.data.stack.clone(),
98 human_context: None,
99 preferences: None,
100 state: None,
101 tags: Vec::new(),
102 }
103}
104
105pub fn estimate_tokens(level: CompressionLevel) -> usize {
107 match level {
108 CompressionLevel::Minimal => 150,
109 CompressionLevel::Standard => 400,
110 CompressionLevel::Full => 800,
111 }
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117 use crate::parse;
118
119 #[test]
120 fn test_compress_minimal() {
121 let content = r#"
122faf_version: 2.5.0
123project:
124 name: test
125 goal: Testing
126instant_context:
127 what_building: App
128 tech_stack: Rust
129 key_files:
130 - a.rs
131 - b.rs
132stack:
133 backend: Rust
134human_context:
135 who: Devs
136"#;
137 let faf = parse(content).unwrap();
138 let compressed = compress(&faf, CompressionLevel::Minimal);
139
140 assert_eq!(compressed.project.name, "test");
141 assert!(compressed.instant_context.as_ref().unwrap().tech_stack.is_some());
142 assert!(compressed.stack.is_none());
143 assert!(compressed.human_context.is_none());
144 }
145
146 #[test]
147 fn test_compress_standard() {
148 let content = r#"
149faf_version: 2.5.0
150project:
151 name: test
152 goal: Testing
153instant_context:
154 what_building: App
155 tech_stack: Rust
156 key_files:
157 - a.rs
158 - b.rs
159 - c.rs
160 - d.rs
161 - e.rs
162 - f.rs
163 - g.rs
164stack:
165 backend: Rust
166human_context:
167 who: Devs
168"#;
169 let faf = parse(content).unwrap();
170 let compressed = compress(&faf, CompressionLevel::Standard);
171
172 assert!(compressed.stack.is_some());
173 assert_eq!(compressed.instant_context.as_ref().unwrap().key_files.len(), 5);
175 assert!(compressed.human_context.is_none());
177 }
178}