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() + "..." } }