use serde_json::{Map, Value};
use lean_ctx::core::config::{CompressionLevel, Config};
use lean_ctx::core::context_ir::ContextIrSourceKindV1;
pub(super) fn context_ir_source_kind(name: &str) -> ContextIrSourceKindV1 {
match name {
n if n.contains("read") => ContextIrSourceKindV1::Read,
"ctx_shell" => ContextIrSourceKindV1::Shell,
"ctx_search" => ContextIrSourceKindV1::Search,
"ctx_provider" => ContextIrSourceKindV1::Provider,
_ => ContextIrSourceKindV1::Other,
}
}
fn skip_terse(name: &str, args: Option<&Map<String, Value>>, is_raw_shell: bool) -> bool {
let mode = crate::server::helpers::get_str(args, "mode");
is_raw_shell
|| lean_ctx::core::terse::is_verbatim_read(name, mode.as_deref())
|| name == "ctx_edit"
|| name == "ctx_expand"
|| (name == "ctx_shell"
&& crate::server::helpers::get_str(args, "command")
.is_some_and(|c| lean_ctx::shell::compress::has_structural_output(&c)))
}
pub(super) fn compress_terse(
text: String,
name: &str,
args: Option<&Map<String, Value>>,
config: &Config,
is_raw_shell: bool,
) -> String {
if skip_terse(name, args, is_raw_shell) {
return text;
}
let compression = CompressionLevel::effective(config);
if !compression.is_active() {
return text;
}
let terse_result = lean_ctx::core::terse::pipeline::compress(&text, &compression, None);
if terse_result.quality_passed && terse_result.savings_pct >= 3.0 {
terse_result.output
} else {
text
}
}
pub(super) fn finalize_token_count_and_adjust(
name: &str,
result_text: &str,
pre_terse_len: usize,
output_tokens: u64,
tool_saved_tokens: usize,
) -> usize {
#[allow(clippy::cast_possible_truncation)]
let output_token_count = if result_text.len() == pre_terse_len {
output_tokens as usize
} else {
lean_ctx::core::tokens::count_tokens(result_text)
};
if result_text.len() != pre_terse_len && output_tokens > 0 {
let delta = terse_savings_delta(
output_tokens as usize,
output_token_count,
tool_saved_tokens,
);
if delta != 0 {
lean_ctx::core::stats::adjust_savings(name, delta);
}
}
output_token_count
}
fn terse_savings_delta(pre_sent: usize, actual_sent: usize, pre_savings: usize) -> i64 {
let original = pre_sent + pre_savings;
let actual_savings = original.saturating_sub(actual_sent);
pre_savings as i64 - actual_savings as i64
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn context_ir_source_kind_maps_tools() {
assert!(matches!(
context_ir_source_kind("ctx_read"),
ContextIrSourceKindV1::Read
));
assert!(matches!(
context_ir_source_kind("ctx_shell"),
ContextIrSourceKindV1::Shell
));
assert!(matches!(
context_ir_source_kind("ctx_search"),
ContextIrSourceKindV1::Search
));
assert!(matches!(
context_ir_source_kind("ctx_provider"),
ContextIrSourceKindV1::Provider
));
assert!(matches!(
context_ir_source_kind("ctx_knowledge"),
ContextIrSourceKindV1::Other
));
}
#[test]
fn skip_terse_for_raw_shell_and_reads() {
assert!(skip_terse("ctx_shell", None, true), "raw shell skips terse");
assert!(
skip_terse("ctx_read", None, false),
"full/verbatim read (0 savings) must still skip terse"
);
assert!(
!skip_terse("ctx_grep", None, false),
"ordinary tool output is eligible for terse"
);
assert!(
skip_terse("ctx_edit", None, false),
"edit evidence must stay byte-accurate"
);
}
#[test]
fn skip_terse_mode_based_guard_protects_verbatim() {
use serde_json::json;
let full_args = json!({"mode": "full"}).as_object().unwrap().clone();
let lines_args = json!({"mode": "lines:1-20"}).as_object().unwrap().clone();
let map_args = json!({"mode": "map"}).as_object().unwrap().clone();
assert!(skip_terse("ctx_future_reader", Some(&full_args), false));
assert!(skip_terse("ctx_x", Some(&lines_args), false));
assert!(!skip_terse("ctx_search", Some(&map_args), false));
}
#[test]
fn compress_terse_keeps_reads_byte_identical() {
let content = "\u{feff}fn run() {\n\n // command execution pipeline\n let command = execution();\n return command;\n}\n";
let cfg = Config {
compression_level: CompressionLevel::Max,
..Config::default()
};
let out = compress_terse(content.to_string(), "ctx_read", None, &cfg, false);
assert_eq!(
out, content,
"ctx_read output must be byte-identical (#404)"
);
}
#[test]
fn compress_terse_keeps_ctx_expand_byte_identical() {
assert!(skip_terse("ctx_expand", None, false));
let content = "Archive abc lines 40-44:\n 40| // command execution pipeline\n 41| let command = execution();\n\n 42| return command;\n 43| return command;\n";
let cfg = Config {
compression_level: CompressionLevel::Max,
..Config::default()
};
let out = compress_terse(content.to_string(), "ctx_expand", None, &cfg, false);
assert_eq!(out, content, "ctx_expand output must be byte-identical");
}
#[test]
fn finalize_token_count_uses_cached_count_when_unchanged() {
let text = "hello world";
let n = finalize_token_count_and_adjust("ctx_shell", text, text.len(), 42, 0);
assert_eq!(n, 42);
}
#[test]
fn terse_delta_reconstructs_from_pre_terse_count() {
assert_eq!(terse_savings_delta(100, 60, 20), -40);
assert_eq!(terse_savings_delta(60, 60, 20), 0);
assert_eq!(terse_savings_delta(100, 70, 0), -30);
assert_eq!(terse_savings_delta(80, 80, 0), 0);
}
}