From 30d033e1d1d785f6fb9d392673f5019e6e350806 Mon Sep 17 00:00:00 2001 From: ooodc <549496103@qq.com> Date: Wed, 22 Apr 2026 13:03:23 +0800 Subject: [PATCH] =?UTF-8?q?feat(agent=5Floop):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=B7=A5=E5=85=B7=E7=BB=93=E6=9E=9C=E6=88=AA=E6=96=AD=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=8C=E7=A1=AE=E4=BF=9D=E6=AD=A3=E7=A1=AE=E5=A4=84?= =?UTF-8?q?=E7=90=86UTF-8=E5=AD=97=E7=AC=A6=E8=BE=B9=E7=95=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/agent/agent_loop.rs | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/agent/agent_loop.rs b/src/agent/agent_loop.rs index 3f6ead5..70aae0a 100644 --- a/src/agent/agent_loop.rs +++ b/src/agent/agent_loop.rs @@ -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 {