@@ -4,7 +4,10 @@ use serde::{
44 Deserialize ,
55 Serialize ,
66} ;
7- use tracing:: error;
7+ use tracing:: {
8+ error,
9+ warn,
10+ } ;
811
912use super :: consts:: MAX_CURRENT_WORKING_DIRECTORY_LEN ;
1013use super :: tools:: {
@@ -15,6 +18,7 @@ use super::util::{
1518 document_to_serde_value,
1619 serde_value_to_document,
1720 truncate_safe,
21+ truncate_safe_in_place,
1822} ;
1923use crate :: api_client:: model:: {
2024 AssistantResponseMessage ,
@@ -55,6 +59,30 @@ pub enum UserMessageContent {
5559 } ,
5660}
5761
62+ impl UserMessageContent {
63+ fn truncate_safe ( & mut self , max_bytes : usize ) {
64+ match self {
65+ UserMessageContent :: Prompt { prompt } => {
66+ truncate_safe_in_place ( prompt, max_bytes) ;
67+ } ,
68+ UserMessageContent :: CancelledToolUses {
69+ prompt,
70+ tool_use_results,
71+ } => {
72+ if let Some ( prompt) = prompt {
73+ truncate_safe_in_place ( prompt, max_bytes / 2 ) ;
74+ truncate_safe_tool_use_results ( tool_use_results. as_mut_slice ( ) , max_bytes / 2 ) ;
75+ } else {
76+ truncate_safe_tool_use_results ( tool_use_results. as_mut_slice ( ) , max_bytes) ;
77+ }
78+ } ,
79+ UserMessageContent :: ToolUseResults { tool_use_results } => {
80+ truncate_safe_tool_use_results ( tool_use_results. as_mut_slice ( ) , max_bytes) ;
81+ } ,
82+ }
83+ }
84+ }
85+
5886impl UserMessage {
5987 /// Creates a new [UserMessage::Prompt], automatically detecting and adding the user's
6088 /// environment [UserEnvContext].
@@ -193,6 +221,14 @@ impl UserMessage {
193221 UserMessageContent :: ToolUseResults { .. } => None ,
194222 }
195223 }
224+
225+ /// Truncates the content contained in this user message to a maximum length of `max_bytes`.
226+ ///
227+ /// This isn't a perfect truncation - JSON tool use results are ignored, and only the content
228+ /// of the user message is truncated, ignoring extra context fields.
229+ pub fn truncate_safe ( & mut self , max_bytes : usize ) {
230+ self . content . truncate_safe ( max_bytes) ;
231+ }
196232}
197233
198234#[ derive( Debug , Clone , Serialize , Deserialize ) ]
@@ -225,6 +261,20 @@ impl From<ToolUseResult> for ToolResult {
225261 }
226262}
227263
264+ fn truncate_safe_tool_use_results ( tool_use_results : & mut [ ToolUseResult ] , max_bytes : usize ) {
265+ let max_bytes = max_bytes / tool_use_results. len ( ) ;
266+ for result in tool_use_results {
267+ for content in & mut result. content {
268+ match content {
269+ ToolUseResultBlock :: Json ( _) => {
270+ warn ! ( "Unable to truncate JSON safely" ) ;
271+ } ,
272+ ToolUseResultBlock :: Text ( t) => truncate_safe_in_place ( t, max_bytes) ,
273+ }
274+ }
275+ }
276+ }
277+
228278#[ derive( Debug , Clone , Serialize , Deserialize ) ]
229279pub enum ToolUseResultBlock {
230280 Json ( serde_json:: Value ) ,
0 commit comments