use agent_client_protocol_schema::ToolCallId;
use super::{ToolResult, oversized_rejection_text, reject_oversized_results};
use crate::llm::ToolResultBody;
fn result_with_chars(chars: usize) -> ToolResult {
ToolResult {
id: ToolCallId::new("call-1".to_string()),
name: "search".to_string(),
tool_use_id: "tu-1".to_string(),
body: ToolResultBody::Text {
text: "x".repeat(chars),
},
is_error: false,
fields: None,
error: None,
}
}
fn body_text(r: &ToolResult) -> &str {
match &r.body {
ToolResultBody::Text { text } => text,
_ => panic!("expected text body"),
}
}
#[test]
fn rejects_result_exceeding_context_window() {
let mut results = vec![result_with_chars(4000)];
let rejected = reject_oversized_results(&mut results, Some(100));
assert_eq!(rejected, 1);
assert!(
results[0].is_error,
"oversized result must be flagged as error"
);
assert!(
body_text(&results[0]).contains("exceeds the model context window"),
"body should be replaced with the actionable rejection message"
);
}
#[test]
fn keeps_result_within_context_window() {
let mut results = vec![result_with_chars(40)];
let rejected = reject_oversized_results(&mut results, Some(100));
assert_eq!(rejected, 0);
assert!(!results[0].is_error);
assert_eq!(
body_text(&results[0]).len(),
40,
"body must be left untouched"
);
}
#[test]
fn no_window_means_no_ceiling() {
let mut results = vec![result_with_chars(40_000)];
let rejected = reject_oversized_results(&mut results, None);
assert_eq!(rejected, 0);
assert!(!results[0].is_error);
}
#[test]
fn rejects_only_the_oversized_ones_in_a_batch() {
let mut results = vec![
result_with_chars(40), result_with_chars(4000), result_with_chars(80), ];
let rejected = reject_oversized_results(&mut results, Some(100));
assert_eq!(rejected, 1);
assert!(!results[0].is_error);
assert!(results[1].is_error);
assert!(!results[2].is_error);
}
#[test]
fn rejection_message_names_the_numbers() {
let msg = oversized_rejection_text(1234, 100);
assert!(msg.contains("1234"));
assert!(msg.contains("100"));
}