diff --git a/src/app/runtime/context/dedup.rs b/src/app/runtime/context/dedup.rs index 42d389a..f9ef4c8 100644 --- a/src/app/runtime/context/dedup.rs +++ b/src/app/runtime/context/dedup.rs @@ -82,7 +82,7 @@ pub fn collapse(messages: &[ChatMessage]) -> (Vec, bool) { /// /// Why hash the arguments: keeps the key a fixed, short size regardless /// of argument payload size. `serde_json::to_string` is already -/// canonical here — this codebase doesn't enable serde_json's +/// canonical here — this codebase doesn't enable `serde_json`'s /// `preserve_order` feature, so `Value::Object` is backed by a /// `BTreeMap` and always serializes keys in sorted order. fn dedup_key(tool_name: &str, canonical_args: &str) -> String { diff --git a/src/app/runtime/context/squash.rs b/src/app/runtime/context/squash.rs index 22ff12d..2b91555 100644 --- a/src/app/runtime/context/squash.rs +++ b/src/app/runtime/context/squash.rs @@ -12,6 +12,7 @@ //! overall budget. use std::collections::HashSet; +use std::fmt::Write; /// Below this size, compression isn't worth the risk of losing detail — /// pass the output through unchanged. @@ -249,7 +250,7 @@ fn squash_generic(text: &str, budget: usize) -> String { let mut prev = ""; for (i, &line) in lines.iter().enumerate().take(tail_start).skip(head_end) { let non_trivial = !line.trim().is_empty() && line != prev; - if non_trivial && used + line.len() + 1 <= budget { + if non_trivial && used + line.len() < budget { keep.insert(i); used += line.len() + 1; } @@ -269,14 +270,14 @@ fn render_kept_lines(lines: &[&str], keep: &HashSet) -> String { let mut cursor = 0usize; for &i in &kept_sorted { if i > cursor { - out.push_str(&format!("[{} lines omitted]\n", i - cursor)); + let _ = writeln!(out, "[{} lines omitted]", i - cursor); } out.push_str(lines[i]); out.push('\n'); cursor = i + 1; } if cursor < lines.len() { - out.push_str(&format!("[{} lines omitted]\n", lines.len() - cursor)); + let _ = writeln!(out, "[{} lines omitted]", lines.len() - cursor); } out }