@@ -334,3 +334,148 @@ async def test_extract_bot_thinking_returns_none_when_not_present():
334334
335335 result = extract_bot_thinking_from_events (events )
336336 assert result is None
337+
338+
339+ @pytest .mark .asyncio
340+ async def test_extract_bot_thinking_with_empty_events_list ():
341+ from nemoguardrails .actions .llm .utils import extract_bot_thinking_from_events
342+
343+ events = []
344+
345+ result = extract_bot_thinking_from_events (events )
346+ assert result is None
347+
348+
349+ @pytest .mark .asyncio
350+ async def test_extract_bot_thinking_returns_first_when_multiple ():
351+ from nemoguardrails .actions .llm .utils import extract_bot_thinking_from_events
352+
353+ first_thinking = "First thought process"
354+ second_thinking = "Second thought process"
355+
356+ events = [
357+ {"type" : "UserMessage" , "text" : "Hello" },
358+ {"type" : "BotThinking" , "content" : first_thinking },
359+ {"type" : "BotMessage" , "text" : "Response" },
360+ {"type" : "BotThinking" , "content" : second_thinking },
361+ ]
362+
363+ result = extract_bot_thinking_from_events (events )
364+ assert result == first_thinking
365+
366+
367+ @pytest .mark .asyncio
368+ async def test_extract_bot_thinking_with_empty_content ():
369+ from nemoguardrails .actions .llm .utils import extract_bot_thinking_from_events
370+
371+ events = [
372+ {"type" : "UserMessage" , "text" : "Hello" },
373+ {"type" : "BotThinking" , "content" : "" },
374+ {"type" : "BotMessage" , "text" : "Response" },
375+ ]
376+
377+ result = extract_bot_thinking_from_events (events )
378+ assert result == ""
379+
380+
381+ @pytest .mark .asyncio
382+ async def test_extract_bot_thinking_with_none_content ():
383+ from nemoguardrails .actions .llm .utils import extract_bot_thinking_from_events
384+
385+ events = [
386+ {"type" : "UserMessage" , "text" : "Hello" },
387+ {"type" : "BotThinking" , "content" : None },
388+ {"type" : "BotMessage" , "text" : "Response" },
389+ ]
390+
391+ result = extract_bot_thinking_from_events (events )
392+ assert result is None
393+
394+
395+ @pytest .mark .asyncio
396+ async def test_extract_bot_thinking_without_content_field ():
397+ from nemoguardrails .actions .llm .utils import extract_bot_thinking_from_events
398+
399+ events = [
400+ {"type" : "UserMessage" , "text" : "Hello" },
401+ {"type" : "BotThinking" },
402+ {"type" : "BotMessage" , "text" : "Response" },
403+ ]
404+
405+ result = extract_bot_thinking_from_events (events )
406+ assert result is None
407+
408+
409+ @pytest .mark .asyncio
410+ async def test_extract_bot_thinking_with_multiline_content ():
411+ from nemoguardrails .actions .llm .utils import extract_bot_thinking_from_events
412+
413+ multiline_thinking = """Step 1: Analyze the request
414+ Step 2: Consider the context
415+ Step 3: Formulate response"""
416+
417+ events = [
418+ {"type" : "UserMessage" , "text" : "Hello" },
419+ {"type" : "BotThinking" , "content" : multiline_thinking },
420+ {"type" : "BotMessage" , "text" : "Response" },
421+ ]
422+
423+ result = extract_bot_thinking_from_events (events )
424+ assert result == multiline_thinking
425+
426+
427+ @pytest .mark .asyncio
428+ async def test_extract_bot_thinking_with_special_characters ():
429+ from nemoguardrails .actions .llm .utils import extract_bot_thinking_from_events
430+
431+ special_thinking = "Thinking: <test> \" quoted\" 'text' & symbols!"
432+
433+ events = [
434+ {"type" : "UserMessage" , "text" : "Hello" },
435+ {"type" : "BotThinking" , "content" : special_thinking },
436+ {"type" : "BotMessage" , "text" : "Response" },
437+ ]
438+
439+ result = extract_bot_thinking_from_events (events )
440+ assert result == special_thinking
441+
442+
443+ @pytest .mark .asyncio
444+ async def test_extract_bot_thinking_with_numeric_content ():
445+ from nemoguardrails .actions .llm .utils import extract_bot_thinking_from_events
446+
447+ events = [
448+ {"type" : "UserMessage" , "text" : "Hello" },
449+ {"type" : "BotThinking" , "content" : 12345 },
450+ {"type" : "BotMessage" , "text" : "Response" },
451+ ]
452+
453+ result = extract_bot_thinking_from_events (events )
454+ assert result == 12345
455+
456+
457+ @pytest .mark .asyncio
458+ async def test_extract_bot_thinking_with_only_bot_thinking_event ():
459+ from nemoguardrails .actions .llm .utils import extract_bot_thinking_from_events
460+
461+ thinking = "Isolated thought"
462+
463+ events = [{"type" : "BotThinking" , "content" : thinking }]
464+
465+ result = extract_bot_thinking_from_events (events )
466+ assert result == thinking
467+
468+
469+ @pytest .mark .asyncio
470+ async def test_extract_bot_thinking_ignores_similar_event_types ():
471+ from nemoguardrails .actions .llm .utils import extract_bot_thinking_from_events
472+
473+ events = [
474+ {"type" : "UserMessage" , "text" : "Hello" },
475+ {"type" : "BotThinkingStarted" , "content" : "Should be ignored" },
476+ {"type" : "PreBotThinking" , "content" : "Should be ignored" },
477+ {"type" : "BotMessage" , "text" : "Response" },
478+ ]
479+
480+ result = extract_bot_thinking_from_events (events )
481+ assert result is None
0 commit comments