1use std::path::Path;
2
3pub fn shorten_path(path: &str) -> String {
4 let p = Path::new(path);
5 if let Some(name) = p.file_name() {
6 return name.to_string_lossy().to_string();
7 }
8 path.to_string()
9}
10
11#[allow(dead_code)]
12pub fn format_type_short(ty: &str) -> String {
13 match ty {
14 "string" | "String" => ":s".to_string(),
15 "number" | "i32" | "i64" | "u32" | "u64" | "usize" | "f32" | "f64" => ":n".to_string(),
16 "boolean" | "bool" => ":b".to_string(),
17 "void" | "()" => "".to_string(),
18 t if t.starts_with("Promise<") => format!("→{}", &t[8..t.len() - 1]),
19 t if t.starts_with("Option<") => format!(":?{}", &t[7..t.len() - 1]),
20 t if t.starts_with("Vec<") => format!(":[{}]", &t[4..t.len() - 1]),
21 t if t.starts_with("Result<") => format!("→!{}", &t[7..t.len() - 1]),
22 _ => format!(":{ty}"),
23 }
24}
25
26pub fn format_savings(original: usize, compressed: usize) -> String {
27 let saved = original.saturating_sub(compressed);
28 if original == 0 {
29 return "0 tok saved".to_string();
30 }
31 let pct = (saved as f64 / original as f64 * 100.0).round() as usize;
32 format!("[{saved} tok saved ({pct}%)]")
33}
34
35pub struct InstructionTemplate {
36 pub code: &'static str,
37 pub full: &'static str,
38}
39
40const TEMPLATES: &[InstructionTemplate] = &[
41 InstructionTemplate {
42 code: "ACT1",
43 full: "Act immediately, report result in one line",
44 },
45 InstructionTemplate {
46 code: "BRIEF",
47 full: "Summarize approach in 1-2 lines, then act",
48 },
49 InstructionTemplate {
50 code: "FULL",
51 full: "Outline approach, consider edge cases, then act",
52 },
53 InstructionTemplate {
54 code: "DELTA",
55 full: "Only show changed lines, not full files",
56 },
57 InstructionTemplate {
58 code: "NOREPEAT",
59 full: "Never repeat known context. Reference cached files by Fn ID",
60 },
61 InstructionTemplate {
62 code: "STRUCT",
63 full: "Use notation, not sentences. Changes: +line/-line/~line",
64 },
65 InstructionTemplate {
66 code: "1LINE",
67 full: "One line per action. Summarize, don't explain",
68 },
69 InstructionTemplate {
70 code: "NODOC",
71 full: "Don't add comments that narrate what code does",
72 },
73 InstructionTemplate {
74 code: "ACTFIRST",
75 full: "Execute tool calls immediately. Never narrate before acting",
76 },
77 InstructionTemplate {
78 code: "QUALITY",
79 full: "Never skip edge case analysis or error handling to save tokens",
80 },
81 InstructionTemplate {
82 code: "NOMOCK",
83 full: "Never use mock data, fake values, or placeholder code",
84 },
85 InstructionTemplate {
86 code: "FREF",
87 full: "Reference files by Fn refs only, never full paths",
88 },
89 InstructionTemplate {
90 code: "DIFF",
91 full: "For code changes: show only diff lines, not full files",
92 },
93 InstructionTemplate {
94 code: "ABBREV",
95 full: "Use abbreviations: fn, cfg, impl, deps, req, res, ctx, err",
96 },
97 InstructionTemplate {
98 code: "SYMBOLS",
99 full: "Use TDD notation: +=add -=remove ~=modify ->=returns ok/fail for status",
100 },
101];
102
103pub fn instruction_decoder_block() -> String {
105 let mut lines = vec!["INSTRUCTION CODES:".to_string()];
106 for t in TEMPLATES {
107 lines.push(format!(" {} = {}", t.code, t.full));
108 }
109 lines.join("\n")
110}
111
112pub fn encode_instructions(complexity: &str) -> String {
115 match complexity {
116 "mechanical" => "MODE: ACT1 DELTA 1LINE | BUDGET: <=50 tokens, 1 line answer".to_string(),
117 "simple" => "MODE: BRIEF DELTA 1LINE | BUDGET: <=100 tokens, structured".to_string(),
118 "standard" => "MODE: BRIEF DELTA NOREPEAT STRUCT | BUDGET: <=200 tokens".to_string(),
119 "complex" => {
120 "MODE: FULL QUALITY NOREPEAT STRUCT FREF DIFF | BUDGET: <=500 tokens".to_string()
121 }
122 "architectural" => {
123 "MODE: FULL QUALITY NOREPEAT STRUCT FREF | BUDGET: unlimited".to_string()
124 }
125 _ => "MODE: BRIEF | BUDGET: <=200 tokens".to_string(),
126 }
127}
128
129pub fn encode_instructions_with_snr(complexity: &str, compression_pct: f64) -> String {
131 let snr = if compression_pct > 0.0 {
132 1.0 - (compression_pct / 100.0)
133 } else {
134 1.0
135 };
136 let base = encode_instructions(complexity);
137 format!("{base} | SNR: {snr:.2}")
138}
139
140#[allow(dead_code)]
142pub fn instruction_encoding_savings() -> (usize, usize) {
143 use super::tokens::count_tokens;
144 let decoder = instruction_decoder_block();
145 let decoder_cost = count_tokens(&decoder);
146
147 let full_mechanical = "TASK COMPLEXITY: mechanical\nMinimal reasoning needed. Act immediately, report result in one line.";
148 let encoded_mechanical = "MODE: ACT1 DELTA 1LINE | BUDGET: <=50 tokens, 1 line answer";
149
150 let saving_per_call =
151 count_tokens(full_mechanical).saturating_sub(count_tokens(encoded_mechanical));
152 (decoder_cost, saving_per_call.max(1))
153}
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158
159 #[test]
160 fn decoder_block_contains_all_codes() {
161 let block = instruction_decoder_block();
162 for t in TEMPLATES {
163 assert!(
164 block.contains(t.code),
165 "decoder should contain code {}",
166 t.code
167 );
168 }
169 }
170
171 #[test]
172 fn encoded_instructions_are_compact() {
173 use super::super::tokens::count_tokens;
174 let full = "TASK COMPLEXITY: mechanical\nMinimal reasoning needed. Act immediately, report result in one line. Show only changed lines, not full files.";
175 let encoded = encode_instructions("mechanical");
176 assert!(
177 count_tokens(&encoded) <= count_tokens(full),
178 "encoded ({}) should be <= full ({})",
179 count_tokens(&encoded),
180 count_tokens(full)
181 );
182 }
183
184 #[test]
185 fn encoding_has_positive_savings() {
186 let (decoder_cost, saving_per_call) = instruction_encoding_savings();
187 assert!(decoder_cost > 0);
188 assert!(saving_per_call > 0);
189 }
190
191 #[test]
192 fn all_complexity_levels_encode() {
193 for level in &["mechanical", "standard", "architectural"] {
194 let encoded = encode_instructions(level);
195 assert!(encoded.starts_with("MODE:"), "should start with MODE:");
196 }
197 }
198}