From 4565988e2ec3fff78a8420fed88f22c26d26ffdc Mon Sep 17 00:00:00 2001 From: Felix <307253927@qq.com> Date: Wed, 1 Apr 2026 18:55:23 +0800 Subject: [PATCH] fix: Fix panic due to UTF-8 character boundary errors --- crates/openfang-runtime/src/context_budget.rs | 8 ++++++-- crates/openfang-runtime/src/llm_errors.rs | 4 +++- crates/openfang-runtime/src/prompt_builder.rs | 4 +++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/crates/openfang-runtime/src/context_budget.rs b/crates/openfang-runtime/src/context_budget.rs index d11f69bd..e0b43e10 100644 --- a/crates/openfang-runtime/src/context_budget.rs +++ b/crates/openfang-runtime/src/context_budget.rs @@ -5,6 +5,7 @@ //! - Layer 2: Context guard that scans all tool results before LLM calls //! and compacts oldest results when total exceeds 75% headroom. +use crate::str_utils::safe_truncate_str; use openfang_types::message::{ContentBlock, Message, MessageContent}; use openfang_types::tool::ToolDefinition; use tracing::debug; @@ -217,11 +218,14 @@ fn truncate_to(content: &str, max_chars: usize) -> String { .rfind('\n') .map(|pos| search_start + pos) .unwrap_or(keep); + + // Use safe_truncate_str as an extra layer of safety + let safe_content = safe_truncate_str(content, break_point); format!( "{}\n\n[COMPACTED: {} → {} chars by context guard]", - &content[..break_point], + safe_content, content.len(), - break_point + safe_content.len() ) } diff --git a/crates/openfang-runtime/src/llm_errors.rs b/crates/openfang-runtime/src/llm_errors.rs index 3ba77281..aee3218a 100644 --- a/crates/openfang-runtime/src/llm_errors.rs +++ b/crates/openfang-runtime/src/llm_errors.rs @@ -11,6 +11,8 @@ use serde::Serialize; +use crate::str_utils::safe_truncate_str; + // --------------------------------------------------------------------------- // Types // --------------------------------------------------------------------------- @@ -534,7 +536,7 @@ fn cap_message(msg: &str, max: usize) -> String { .nth(max - 3) .map(|(i, _)| i) .unwrap_or(msg.len()); - format!("{}...", &msg[..end]) + safe_truncate_str(msg, end).to_string() + "..." } } diff --git a/crates/openfang-runtime/src/prompt_builder.rs b/crates/openfang-runtime/src/prompt_builder.rs index fbe0bdbd..c8e4c18c 100644 --- a/crates/openfang-runtime/src/prompt_builder.rs +++ b/crates/openfang-runtime/src/prompt_builder.rs @@ -4,6 +4,8 @@ //! Replaces the scattered `push_str` prompt injection throughout the codebase //! with a single, testable, ordered prompt builder. +use crate::str_utils::safe_truncate_str; + /// All the context needed to build a system prompt for an agent. #[derive(Debug, Clone, Default)] pub struct PromptContext { @@ -627,7 +629,7 @@ fn cap_str(s: &str, max_chars: usize) -> String { .nth(max_chars) .map(|(i, _)| i) .unwrap_or(s.len()); - format!("{}...", &s[..end]) + safe_truncate_str(s, end).to_string() + "..." } }