lean_ctx_proxy/
verbosity.rs1use serde_json::{Map, Value};
25
26pub const STEER: &str =
29 "Be concise: answer directly and do not restate the question or surrounding context.";
30
31fn string_suffix() -> String {
33 format!("\n\n{STEER}")
34}
35
36fn already_steered(text: &str) -> bool {
39 text.trim_end().ends_with(STEER)
40}
41
42fn steer_text_block() -> Value {
44 let mut m = Map::new();
45 m.insert("type".to_string(), Value::String("text".to_string()));
46 m.insert("text".to_string(), Value::String(STEER.to_string()));
47 Value::Object(m)
48}
49
50fn steer_input_text_block() -> Value {
53 let mut m = Map::new();
54 m.insert("type".to_string(), Value::String("input_text".to_string()));
55 m.insert("text".to_string(), Value::String(STEER.to_string()));
56 Value::Object(m)
57}
58
59fn steer_gemini_part() -> Value {
61 let mut m = Map::new();
62 m.insert("text".to_string(), Value::String(STEER.to_string()));
63 Value::Object(m)
64}
65
66fn append_to_content(content: &mut Value, block: impl FnOnce() -> Value) -> bool {
70 match content {
71 Value::String(s) => {
72 if already_steered(s) {
73 return false;
74 }
75 s.push_str(&string_suffix());
76 true
77 }
78 Value::Array(parts) => {
79 let last_text = parts
81 .iter()
82 .rev()
83 .find_map(|p| p.get("text").and_then(Value::as_str));
84 if last_text.is_some_and(already_steered) {
85 return false;
86 }
87 parts.push(block());
88 true
89 }
90 _ => false,
91 }
92}
93
94fn last_role_index(messages: &[Value], role: &str) -> Option<usize> {
96 messages
97 .iter()
98 .rposition(|m| m.get("role").and_then(Value::as_str) == Some(role))
99}
100
101pub fn apply_anthropic(doc: &mut Value) -> bool {
104 let Some(messages) = doc.get_mut("messages").and_then(Value::as_array_mut) else {
105 return false;
106 };
107 let Some(idx) = last_role_index(messages, "user") else {
108 return false;
109 };
110 let Some(content) = messages[idx].get_mut("content") else {
111 return false;
112 };
113 let changed = append_to_content(content, steer_text_block);
114 if changed {
115 record();
116 }
117 changed
118}
119
120pub fn apply_openai_chat(doc: &mut Value) -> bool {
124 let Some(messages) = doc.get_mut("messages").and_then(Value::as_array_mut) else {
125 return false;
126 };
127 let Some(idx) = last_role_index(messages, "user") else {
128 return false;
129 };
130 let Some(content) = messages[idx].get_mut("content") else {
131 return false;
132 };
133 let changed = append_to_content(content, steer_text_block);
134 if changed {
135 record();
136 }
137 changed
138}
139
140pub fn apply_openai_responses(doc: &mut Value) -> bool {
143 let changed = match doc.get_mut("input") {
144 Some(Value::String(s)) => {
145 if already_steered(s) {
146 false
147 } else {
148 s.push_str(&string_suffix());
149 true
150 }
151 }
152 Some(Value::Array(items)) => {
153 let Some(idx) = last_role_index(items, "user") else {
154 return false;
155 };
156 match items[idx].get_mut("content") {
157 Some(content) => append_to_content(content, steer_input_text_block),
158 None => false,
159 }
160 }
161 _ => false,
162 };
163 if changed {
164 record();
165 }
166 changed
167}
168
169pub fn apply_google(doc: &mut Value) -> bool {
172 let Some(contents) = doc.get_mut("contents").and_then(Value::as_array_mut) else {
173 return false;
174 };
175 let Some(idx) = last_role_index(contents, "user") else {
176 return false;
177 };
178 let Some(parts) = contents[idx].get_mut("parts").and_then(Value::as_array_mut) else {
179 return false;
180 };
181 let last_text = parts
182 .iter()
183 .rev()
184 .find_map(|p| p.get("text").and_then(Value::as_str));
185 if last_text.is_some_and(already_steered) {
186 return false;
187 }
188 parts.push(steer_gemini_part());
189 record();
190 true
191}
192
193use std::sync::atomic::{AtomicU64, Ordering};
194
195static STEERED: AtomicU64 = AtomicU64::new(0);
197
198fn record() {
199 STEERED.fetch_add(1, Ordering::Relaxed);
200}
201
202#[must_use]
204pub fn steered_count() -> u64 {
205 STEERED.load(Ordering::Relaxed)
206}
207
208#[cfg(test)]
209mod tests {
210 use super::*;
211 use serde_json::json;
212
213 #[test]
214 fn anthropic_appends_block_to_last_user() {
215 let mut doc = json!({
216 "messages": [
217 {"role": "user", "content": "first"},
218 {"role": "assistant", "content": "ok"},
219 {"role": "user", "content": [{"type": "text", "text": "second"}]}
220 ]
221 });
222 assert!(apply_anthropic(&mut doc));
223 let last = &doc["messages"][2]["content"];
224 let arr = last.as_array().unwrap();
225 assert_eq!(arr.len(), 2, "new steer block appended");
226 assert_eq!(arr[1]["text"], STEER);
227 assert_eq!(doc["messages"][0]["content"], "first");
229 }
230
231 #[test]
232 fn anthropic_string_content_concatenates() {
233 let mut doc = json!({"messages": [{"role": "user", "content": "hello"}]});
234 assert!(apply_anthropic(&mut doc));
235 let s = doc["messages"][0]["content"].as_str().unwrap();
236 assert!(s.starts_with("hello"));
237 assert!(s.ends_with(STEER));
238 }
239
240 #[test]
241 fn never_modifies_cache_control_blocks() {
242 let mut doc = json!({
243 "messages": [{
244 "role": "user",
245 "content": [
246 {"type": "text", "text": "cached", "cache_control": {"type": "ephemeral"}}
247 ]
248 }]
249 });
250 assert!(apply_anthropic(&mut doc));
251 let arr = doc["messages"][0]["content"].as_array().unwrap();
252 assert_eq!(arr.len(), 2);
255 assert!(arr[0].get("cache_control").is_some());
256 assert_eq!(arr[0]["text"], "cached");
257 assert_eq!(arr[1]["text"], STEER);
258 assert!(arr[1].get("cache_control").is_none());
259 }
260
261 #[test]
262 fn idempotent_no_double_append() {
263 let mut doc = json!({"messages": [{"role": "user", "content": "hi"}]});
264 assert!(apply_anthropic(&mut doc));
265 let once = doc.clone();
266 assert!(!apply_anthropic(&mut doc), "second pass is a no-op");
267 assert_eq!(doc, once, "byte-identical after a redundant pass");
268 }
269
270 #[test]
271 fn deterministic_constant_suffix() {
272 let mk = || json!({"messages": [{"role": "user", "content": "ask"}]});
273 let mut a = mk();
274 let mut b = mk();
275 apply_anthropic(&mut a);
276 apply_anthropic(&mut b);
277 assert_eq!(a, b, "constant steer ⇒ byte-identical rewrite");
278 }
279
280 #[test]
281 fn openai_chat_appends_to_last_user() {
282 let mut doc = json!({
283 "messages": [
284 {"role": "system", "content": "sys"},
285 {"role": "user", "content": "q"}
286 ]
287 });
288 assert!(apply_openai_chat(&mut doc));
289 let s = doc["messages"][1]["content"].as_str().unwrap();
290 assert!(s.ends_with(STEER));
291 assert_eq!(doc["messages"][0]["content"], "sys", "system untouched");
292 }
293
294 #[test]
295 fn responses_string_and_array_input() {
296 let mut s = json!({"input": "plain"});
297 assert!(apply_openai_responses(&mut s));
298 assert!(s["input"].as_str().unwrap().ends_with(STEER));
299
300 let mut a =
301 json!({"input": [{"role": "user", "content": [{"type": "input_text", "text": "q"}]}]});
302 assert!(apply_openai_responses(&mut a));
303 let parts = a["input"][0]["content"].as_array().unwrap();
304 assert_eq!(parts.last().unwrap()["type"], "input_text");
305 assert_eq!(parts.last().unwrap()["text"], STEER);
306 }
307
308 #[test]
309 fn google_appends_part_to_last_user() {
310 let mut doc = json!({
311 "contents": [
312 {"role": "user", "parts": [{"text": "q1"}]},
313 {"role": "model", "parts": [{"text": "a1"}]},
314 {"role": "user", "parts": [{"text": "q2"}]}
315 ]
316 });
317 assert!(apply_google(&mut doc));
318 let parts = doc["contents"][2]["parts"].as_array().unwrap();
319 assert_eq!(parts.len(), 2);
320 assert_eq!(parts[1]["text"], STEER);
321 }
322
323 #[test]
324 fn no_user_turn_is_noop() {
325 let mut doc = json!({"messages": [{"role": "assistant", "content": "x"}]});
326 assert!(!apply_anthropic(&mut doc));
327 }
328}