1use crate::parser::FafFile;
4use crate::types::*;
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
142 .instant_context
143 .as_ref()
144 .unwrap()
145 .tech_stack
146 .is_some());
147 assert!(compressed.stack.is_none());
148 assert!(compressed.human_context.is_none());
149 }
150
151 #[test]
152 fn test_compress_standard() {
153 let content = r#"
154faf_version: 2.5.0
155project:
156 name: test
157 goal: Testing
158instant_context:
159 what_building: App
160 tech_stack: Rust
161 key_files:
162 - a.rs
163 - b.rs
164 - c.rs
165 - d.rs
166 - e.rs
167 - f.rs
168 - g.rs
169stack:
170 backend: Rust
171human_context:
172 who: Devs
173"#;
174 let faf = parse(content).unwrap();
175 let compressed = compress(&faf, CompressionLevel::Standard);
176
177 assert!(compressed.stack.is_some());
178 assert_eq!(
180 compressed.instant_context.as_ref().unwrap().key_files.len(),
181 5
182 );
183 assert!(compressed.human_context.is_none());
185 }
186}