feat(agent_loop): 优化工具结果截断逻辑,确保正确处理UTF-8字符边界

This commit is contained in:
ooodc 2026-04-22 13:03:23 +08:00
parent c58644e7bc
commit 30d033e1d1

View File

@ -72,24 +72,28 @@ fn encode_image_to_base64(path: &str) -> Result<(String, String), std::io::Error
/// Truncate tool result if it exceeds MAX_TOOL_RESULT_CHARS.
/// Preserves the end of the output as it often contains the conclusion/useful result.
fn truncate_tool_result(output: &str) -> String {
if output.len() <= MAX_TOOL_RESULT_CHARS {
let char_count = output.chars().count();
if char_count <= MAX_TOOL_RESULT_CHARS {
return output.to_string();
}
let truncated_start_len = output.len().saturating_sub(TRUNCATION_SUFFIX_LEN);
let truncated_start_len = char_count.saturating_sub(TRUNCATION_SUFFIX_LEN);
if truncated_start_len > MAX_TOOL_RESULT_CHARS {
// Even after removing suffix, still too long - take from beginning
let head_len = MAX_TOOL_RESULT_CHARS - 100;
let head: String = output.chars().take(head_len).collect();
format!(
"{}...\n\n[Output truncated - {} characters removed]",
&output[..MAX_TOOL_RESULT_CHARS - 100],
output.len() - MAX_TOOL_RESULT_CHARS + 100
head,
char_count - MAX_TOOL_RESULT_CHARS + 100
)
} else {
// Keep most of the end which usually contains the useful result
let tail: String = output.chars().skip(truncated_start_len).collect();
format!(
"...\n\n[Output truncated - {} characters removed]\n\n{}",
truncated_start_len,
&output[truncated_start_len..]
tail
)
}
}
@ -1036,6 +1040,16 @@ mod tests {
assert_eq!(provider_message.tool_calls.as_ref().unwrap()[0].name, "calculator");
}
#[test]
fn test_truncate_tool_result_handles_utf8_char_boundaries() {
let input = "".repeat(MAX_TOOL_RESULT_CHARS + 500);
let output = truncate_tool_result(&input);
assert!(output.contains("Output truncated"));
assert!(output.is_char_boundary(output.len()));
}
#[test]
fn test_did_successfully_write_memory_only_accepts_successful_put_or_update() {
let tool_call = ToolCall {