tool_output_truncate/lib.rs
1//! # tool-output-truncate
2//!
3//! Truncate tool output before adding it to LLM message history.
4//!
5//! When an agent runs `cat large_file.log`, `ripgrep`, or a database query,
6//! the result can be megabytes. Naively appending it to the conversation
7//! blows the context window. The standard fix is to keep the head and the
8//! tail and replace the middle with an elision marker. This crate gives
9//! you that, char-aware (UTF-8 safe) and line-aware, with zero deps.
10//!
11//! ## Quick example
12//!
13//! ```
14//! use tool_output_truncate::truncate_middle;
15//!
16//! let big = (0..1000).map(|i| format!("row {i}\n")).collect::<String>();
17//! let trimmed = truncate_middle(&big, 200);
18//! assert!(trimmed.len() <= 200 + 64); // text + elision marker overhead
19//! assert!(trimmed.starts_with("row 0"));
20//! assert!(trimmed.contains("truncated"));
21//! ```
22//!
23//! ## Strategies
24//!
25//! - [`truncate_middle`] - keep half at the start, half at the end.
26//! Best default for arbitrary text where head and tail both carry signal
27//! (logs, stack traces, file contents).
28//! - [`truncate_head`] - keep the first N chars only.
29//! Use when the tail is noise (e.g. very long lists where order matters).
30//! - [`truncate_tail`] - keep the last N chars only.
31//! Use when the head is preamble (e.g. command output with banner lines).
32//! - [`truncate_middle_lines`] - line-aware version of `truncate_middle`.
33//! Splits at line boundaries so you don't show half a line of JSON.
34//!
35//! All functions are no-op when the input already fits.
36//!
37//! ## What it does NOT do
38//!
39//! - No tokenization. Pass a char cap; if you need token caps use
40//! `chars * 4` as a rough Anthropic/OpenAI proxy.
41//! - No structured truncation (JSON, YAML, XML). For JSON specifically,
42//! parse first and decide which fields to keep.
43//! - No summarization. This is byte/char arithmetic only.
44
45#![deny(missing_docs)]
46
47mod chars;
48mod lines;
49
50pub use chars::{truncate_head, truncate_middle, truncate_tail};
51pub use lines::truncate_middle_lines;