feat: 增强参数截断逻辑,确保在截断时遵循UTF-8字符边界,并添加相关单元测试

This commit is contained in:
oudecheng 2026-05-12 17:44:39 +08:00
parent 7238bd20d8
commit 4473c9fc47
2 changed files with 23 additions and 5 deletions

View File

@ -1055,8 +1055,8 @@ impl AgentLoop {
let error = result.error.unwrap_or_default(); let error = result.error.unwrap_or_default();
tracing::error!( tracing::error!(
tool = %tool_call.name, tool = %tool_call.name,
args = %truncate_args(&tool_call.arguments, 2_000), args = %truncate_args(&tool_call.arguments, 4_000),
normalized_args = %truncate_args(&normalized_arguments, 2_000), normalized_args = %truncate_args(&normalized_arguments, 4_000),
error = %error, error = %error,
output = %result.output, output = %result.output,
"Tool returned an error result" "Tool returned an error result"
@ -1067,8 +1067,8 @@ impl AgentLoop {
Err(e) => { Err(e) => {
tracing::error!( tracing::error!(
tool = %tool_call.name, tool = %tool_call.name,
args = %truncate_args(&tool_call.arguments, 2_000), args = %truncate_args(&tool_call.arguments, 4_000),
normalized_args = %truncate_args(&normalized_arguments, 2_000), normalized_args = %truncate_args(&normalized_arguments, 4_000),
error = %e, error = %e,
error_details = %format!("{:#}", e), error_details = %format!("{:#}", e),
"Tool execution failed" "Tool execution failed"

View File

@ -187,7 +187,14 @@ pub fn truncate_args(args: &serde_json::Value, max_len: usize) -> String {
if args_str.len() <= max_len { if args_str.len() <= max_len {
return args_str; return args_str;
} }
format!("{}...truncated", &args_str[..max_len]) // Find the last valid char boundary before max_len to avoid splitting UTF-8 chars
let truncate_at = args_str
.char_indices()
.take_while(|(idx, _)| *idx < max_len)
.last()
.map(|(idx, c)| idx + c.len_utf8())
.unwrap_or(0);
format!("{}...truncated", &args_str[..truncate_at])
} }
#[cfg(test)] #[cfg(test)]
@ -288,4 +295,15 @@ mod tests {
assert!(truncated.ends_with("...truncated")); assert!(truncated.ends_with("...truncated"));
assert!(truncated.len() < long_args.to_string().len()); assert!(truncated.len() < long_args.to_string().len());
} }
#[test]
fn test_truncate_args_utf8_boundary() {
// Test that truncation respects UTF-8 character boundaries
// Each Chinese character is 3 bytes in UTF-8
let long_args = serde_json::json!({"key": "测试测试测试测试测试测试测试测试测试测试测试测试测试测试"});
let truncated = truncate_args(&long_args, 50);
assert!(truncated.ends_with("...truncated"));
// Verify the truncated string is valid UTF-8 (no panic occurred)
assert!(truncated.is_char_boundary(truncated.len()));
}
} }