1pub use lean_ctx::core::ccr::*;
10
11#[cfg(feature = "http-server")]
12use serde_json::Value;
13
14#[cfg(feature = "http-server")]
17fn recover(hash: &str) -> Option<String> {
18 if hash.len() != 16 || !hash.bytes().all(|b| b.is_ascii_hexdigit()) {
19 return None;
20 }
21 read_tee(hash)
22}
23
24#[cfg(feature = "http-server")]
37fn splice_str(s: &str) -> Option<String> {
38 if !s.contains(EXPAND_OPEN) {
39 return None;
40 }
41 let mut out = String::with_capacity(s.len());
42 let mut rest = s;
43 let mut changed = false;
44 while let Some(pos) = rest.find(EXPAND_OPEN) {
45 let after = &rest[pos + EXPAND_OPEN.len()..];
46 match after.find(EXPAND_CLOSE) {
47 Some(end) => {
48 let hash = &after[..end];
49 if let Some(original) = recover(hash) {
50 out.push_str(&rest[..pos]);
51 out.push_str(&original);
52 rest = &after[end + EXPAND_CLOSE.len_utf8()..];
53 changed = true;
54 } else {
55 out.push_str(&rest[..pos + EXPAND_OPEN.len()]);
58 rest = after;
59 }
60 }
61 None => break,
63 }
64 }
65 out.push_str(rest);
66 changed.then_some(out)
67}
68
69#[cfg(feature = "http-server")]
78pub(crate) fn splice_inband_in_place(value: &mut Value) -> bool {
79 match value {
80 Value::String(s) => {
81 if let Some(spliced) = splice_str(s) {
82 *s = spliced;
83 true
84 } else {
85 false
86 }
87 }
88 Value::Array(items) => {
89 let mut changed = false;
90 for item in items {
91 changed |= splice_inband_in_place(item);
92 }
93 changed
94 }
95 Value::Object(map) => {
96 let mut changed = false;
97 for (_, v) in map.iter_mut() {
98 changed |= splice_inband_in_place(v);
99 }
100 changed
101 }
102 _ => false,
103 }
104}
105
106#[cfg(all(test, feature = "http-server"))]
107mod tests {
108 use super::*;
109 use lean_ctx::core::ccr::test_support::big;
110 use lean_ctx::core::policy::content::protected_for_test as protected;
111
112 #[test]
113 fn splice_replaces_marker_with_verbatim_original() {
114 let _lock = lean_ctx::core::data_dir::test_env_lock();
115 let _community = lean_ctx::core::policy::runtime::TestPolicyOverride::set(None);
116 let content = big("the historical verbatim line");
117 let handle = persist(&content).expect("persisted");
118 let marker = inband_marker(&handle).expect("marker");
119
120 let mut doc = serde_json::json!({
121 "messages": [{ "role": "assistant", "content": format!("recall {marker} please") }]
122 });
123 assert!(splice_inband_in_place(&mut doc), "a marker must splice");
124 let spliced = doc["messages"][0]["content"].as_str().unwrap();
125 assert!(
126 spliced.contains("the historical verbatim line"),
127 "verbatim original must be spliced in: {spliced}"
128 );
129 assert!(
130 !spliced.contains("<lc_expand:"),
131 "the marker must be consumed, not left behind"
132 );
133 }
134
135 #[test]
136 fn splice_is_byte_identical_no_op_without_marker() {
137 let _lock = lean_ctx::core::data_dir::test_env_lock();
138 let mut doc = serde_json::json!({
139 "messages": [{ "role": "user", "content": "no marker here" }],
140 "system": "plain"
141 });
142 let before = doc.clone();
143 assert!(
144 !splice_inband_in_place(&mut doc),
145 "no marker → must report no change"
146 );
147 assert_eq!(
148 doc, before,
149 "marker-less body must stay byte-identical (cache-safe)"
150 );
151 }
152
153 #[test]
154 fn splice_keeps_unresolvable_marker_verbatim() {
155 let _lock = lean_ctx::core::data_dir::test_env_lock();
156 let mut doc = serde_json::json!({ "t": "before <lc_expand:deadbeefdeadbeef> after" });
159 assert!(!splice_inband_in_place(&mut doc));
160 assert_eq!(
161 doc["t"].as_str().unwrap(),
162 "before <lc_expand:deadbeefdeadbeef> after"
163 );
164 }
165
166 #[test]
167 fn splice_recurses_and_handles_multiple_markers() {
168 let _lock = lean_ctx::core::data_dir::test_env_lock();
169 let _community = lean_ctx::core::policy::runtime::TestPolicyOverride::set(None);
170 let a = big("first recovered body");
171 let b = big("second recovered body");
172 let ma = inband_marker(&persist(&a).unwrap()).unwrap();
173 let mb = inband_marker(&persist(&b).unwrap()).unwrap();
174
175 let mut doc = serde_json::json!({
177 "contents": [
178 { "parts": [{ "text": format!("{ma} and {mb}") }] }
179 ]
180 });
181 assert!(splice_inband_in_place(&mut doc));
182 let text = doc["contents"][0]["parts"][0]["text"].as_str().unwrap();
183 assert!(text.contains("first recovered body"));
184 assert!(text.contains("second recovered body"));
185 assert!(!text.contains("<lc_expand:"));
186 }
187
188 #[test]
191 fn tee_selectors_and_inband_do_not_reopen_originless_history() {
192 let _data = lean_ctx::core::data_dir::isolated_data_dir();
193 let body = "visible marker\nordinary data\n".repeat(32) + "CONFIDENTIAL\n";
194 let handle = {
195 let _community = lean_ctx::core::policy::runtime::TestPolicyOverride::set(None);
196 let handle = lean_ctx::core::ccr::persist(&body).unwrap();
197 assert!(
198 lean_ctx_server::tools::ctx_expand::handle(
199 &serde_json::json!({"id": handle, "head": 1})
200 )
201 .contains("visible marker")
202 );
203 handle
204 };
205 let marker = lean_ctx::core::ccr::inband_marker(&handle).unwrap();
206 let mut tracker =
207 lean_ctx::core::relevance_tracker::RelevanceTracker::with_config(200, 0.0);
208 tracker.register(handle.clone(), &body, "ctx_shell", 300, 0);
209 {
210 let _community = lean_ctx::core::policy::runtime::TestPolicyOverride::set(None);
211 assert!(
212 tracker
213 .expand_if_relevant("visible")
214 .unwrap()
215 .contains("visible marker")
216 );
217 }
218 for rules in [
219 "[filters]\nclassification='block'",
220 "[redaction]\ncustomer='K-[0-9]{6}'",
221 ] {
222 let _policy = protected(rules);
223 assert!(tracker.expand_if_relevant("visible").is_none());
224 for selector in [
225 serde_json::json!({}),
226 serde_json::json!({"head":1}),
227 serde_json::json!({"tail":2}),
228 serde_json::json!({"search":"visible"}),
229 serde_json::json!({"start_line":1,"end_line":2}),
230 serde_json::json!({"json_keys":true}),
231 serde_json::json!({"json_path":"safe"}),
232 ] {
233 let mut args = selector;
234 args["id"] = handle.clone().into();
235 let result = lean_ctx_server::tools::ctx_expand::handle(&args);
236 assert!(result.starts_with("ERROR:"), "{result}");
237 assert!(!result.contains("visible marker"));
238 }
239 let mut request =
240 serde_json::json!({"messages":[{"role":"assistant","content":marker}]});
241 let before = request.clone();
242 assert!(!splice_inband_in_place(&mut request));
243 assert_eq!(request, before);
244 assert!(
245 lean_ctx::core::ccr::retrieve_litellm(&lean_ctx::core::ccr::litellm_hash(&body))
246 .is_none()
247 );
248 }
249 let _community = lean_ctx::core::policy::runtime::TestPolicyOverride::set(None);
252 assert_eq!(
253 lean_ctx::core::ccr::read_checked_tee(std::path::Path::new(&handle)).unwrap(),
254 body
255 );
256 }
257}