fix: read工具单行超长时内容被完全丢弃
单行超过 MAX_CHARS(128K) 时,截断循环 end_idx=0 导致 lines[..0] 为空, 整行内容丢失。改为当首行就超长时使用 take_prefix_chars 字符级截断。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
182bebdaef
commit
5d3a583915
@ -3,6 +3,7 @@ use std::path::Path;
|
||||
use async_trait::async_trait;
|
||||
use serde_json::json;
|
||||
|
||||
use crate::text::take_prefix_chars;
|
||||
use crate::tools::traits::{Tool, ToolResult};
|
||||
use crate::tools::extract_u64;
|
||||
|
||||
@ -187,8 +188,13 @@ impl Tool for FileReadTool {
|
||||
}
|
||||
end_idx = i + 1;
|
||||
}
|
||||
if end_idx == 0 && !lines.is_empty() {
|
||||
// First line alone exceeds MAX_CHARS — take its prefix
|
||||
result = take_prefix_chars(&lines[0], MAX_CHARS.saturating_sub(100));
|
||||
} else {
|
||||
result = lines[..end_idx].join("\n");
|
||||
let truncated_amount = original_len - result.len();
|
||||
}
|
||||
let truncated_amount = original_len.saturating_sub(result.len());
|
||||
result.push_str(&format!(
|
||||
"\n\n... ({} chars truncated) ...",
|
||||
truncated_amount
|
||||
@ -312,4 +318,28 @@ mod tests {
|
||||
assert!(!result.success);
|
||||
assert!(result.error.unwrap().contains("Not a file"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_read_single_long_line() {
|
||||
let mut file = NamedTempFile::new().unwrap();
|
||||
// Write a single line longer than MAX_CHARS
|
||||
let long_line = "A".repeat(150_000);
|
||||
file.write_all(long_line.as_bytes()).unwrap();
|
||||
|
||||
let tool = FileReadTool::new();
|
||||
let result = tool
|
||||
.execute(json!({ "path": file.path().to_str().unwrap() }))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert!(result.success);
|
||||
// Should contain the line number prefix and the beginning of the content
|
||||
assert!(result.output.starts_with("1| AAAA"));
|
||||
// Should contain truncation notice since content exceeds MAX_CHARS
|
||||
assert!(result.output.contains("chars truncated"));
|
||||
// Should contain end-of-file notice (1 line total)
|
||||
assert!(result.output.contains("End of file — 1 lines total"));
|
||||
// Should NOT be empty content — the fix ensures the prefix is preserved
|
||||
assert!(result.output.len() > 100);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user