@@ -278,6 +278,84 @@ def test_progressive_truncation(self, large_messages):
278278 assert current_count >= 1
279279 prev_count = current_count
280280
281+ def test_individual_message_truncation (self ):
282+ large_content = "This is a very long message. " * 1000
283+
284+ messages = [
285+ {"role" : "system" , "content" : "You are a helpful assistant." },
286+ {"role" : "user" , "content" : large_content },
287+ ]
288+
289+ result , truncation_index = truncate_messages_by_size (
290+ messages , max_bytes = MAX_GEN_AI_MESSAGE_BYTES
291+ )
292+
293+ assert len (result ) > 0
294+
295+ total_size = len (json .dumps (result , separators = ("," , ":" )).encode ("utf-8" ))
296+ assert total_size <= MAX_GEN_AI_MESSAGE_BYTES
297+
298+ for msg in result :
299+ msg_size = len (json .dumps (msg , separators = ("," , ":" )).encode ("utf-8" ))
300+ assert msg_size <= MAX_GEN_AI_MESSAGE_BYTES
301+
302+ # If the last message is too large, the system message is not present
303+ system_msgs = [m for m in result if m .get ("role" ) == "system" ]
304+ assert len (system_msgs ) == 0
305+
306+ # Confirm the user message is truncated with '...'
307+ user_msgs = [m for m in result if m .get ("role" ) == "user" ]
308+ assert len (user_msgs ) == 1
309+ assert user_msgs [0 ]["content" ].endswith ("..." )
310+ assert len (user_msgs [0 ]["content" ]) < len (large_content )
311+
312+ def test_combined_individual_and_array_truncation (self ):
313+ huge_content = "X" * 25000
314+ medium_content = "Y" * 5000
315+
316+ messages = [
317+ {"role" : "system" , "content" : medium_content },
318+ {"role" : "user" , "content" : huge_content },
319+ {"role" : "assistant" , "content" : medium_content },
320+ {"role" : "user" , "content" : "small" },
321+ ]
322+
323+ result , truncation_index = truncate_messages_by_size (
324+ messages , max_bytes = MAX_GEN_AI_MESSAGE_BYTES
325+ )
326+
327+ assert len (result ) > 0
328+
329+ total_size = len (json .dumps (result , separators = ("," , ":" )).encode ("utf-8" ))
330+ assert total_size <= MAX_GEN_AI_MESSAGE_BYTES
331+
332+ for msg in result :
333+ msg_size = len (json .dumps (msg , separators = ("," , ":" )).encode ("utf-8" ))
334+ assert msg_size <= MAX_GEN_AI_MESSAGE_BYTES
335+
336+ # The last user "small" message should always be present and untruncated
337+ last_user_msgs = [
338+ m for m in result if m .get ("role" ) == "user" and m ["content" ] == "small"
339+ ]
340+ assert len (last_user_msgs ) == 1
341+
342+ # If the huge message is present, it must be truncated
343+ for user_msg in [
344+ m for m in result if m .get ("role" ) == "user" and "X" in m ["content" ]
345+ ]:
346+ assert user_msg ["content" ].endswith ("..." )
347+ assert len (user_msg ["content" ]) < len (huge_content )
348+
349+ # The medium messages, if present, should not be truncated
350+ for expected_role in ["system" , "assistant" ]:
351+ role_msgs = [m for m in result if m .get ("role" ) == expected_role ]
352+ if role_msgs :
353+ assert role_msgs [0 ]["content" ].startswith ("Y" )
354+ assert len (role_msgs [0 ]["content" ]) <= len (medium_content )
355+ assert not role_msgs [0 ]["content" ].endswith ("..." ) or len (
356+ role_msgs [0 ]["content" ]
357+ ) == len (medium_content )
358+
281359
282360class TestTruncateAndAnnotateMessages :
283361 def test_no_truncation_returns_list (self , sample_messages ):
0 commit comments