@@ -463,3 +463,232 @@ def sum_numbers(a, b):
463463 result = core_agent_module .parse_code_blobs (text )
464464 expected = "def sum_numbers(a, b):\n return a + b\n \n result = sum_numbers(5, 3)"
465465 assert result == expected
466+
467+
468+ def test_step_stream_parse_success (core_agent_instance ):
469+ """Test _step_stream method when parsing succeeds."""
470+ # Setup
471+ mock_memory_step = MagicMock ()
472+ mock_chat_message = MagicMock ()
473+ mock_chat_message .content = "```python\n print('hello')\n ```"
474+
475+ # Set all required attributes on the instance
476+ core_agent_instance .agent_name = "test_agent"
477+ core_agent_instance .step_number = 1
478+ core_agent_instance .grammar = None
479+ core_agent_instance .logger = MagicMock ()
480+ core_agent_instance .memory = MagicMock ()
481+ core_agent_instance .memory .steps = []
482+
483+ with patch .object (core_agent_module , 'parse_code_blobs' , return_value = "print('hello')" ), \
484+ patch .object (core_agent_module , 'fix_final_answer_code' , return_value = "print('hello')" ):
485+
486+ # Mock the methods directly on the instance
487+ core_agent_instance .write_memory_to_messages = MagicMock (return_value = [])
488+ core_agent_instance .model = MagicMock (return_value = mock_chat_message )
489+ core_agent_instance .python_executor = MagicMock (return_value = ("output" , "logs" , False ))
490+
491+ # Execute
492+ list (core_agent_instance ._step_stream (mock_memory_step ))
493+
494+ # Assertions
495+ assert mock_memory_step .tool_calls is not None
496+ assert len (mock_memory_step .tool_calls ) == 1
497+ # Check that tool_calls was set (we can't easily test the exact content due to mock behavior)
498+ assert hasattr (mock_memory_step .tool_calls [0 ], 'name' )
499+ assert hasattr (mock_memory_step .tool_calls [0 ], 'arguments' )
500+
501+
502+ def test_step_stream_parse_failure_raises_final_answer_error (core_agent_instance ):
503+ """Test _step_stream method when parsing fails and raises FinalAnswerError."""
504+ # Setup
505+ mock_memory_step = MagicMock ()
506+ mock_chat_message = MagicMock ()
507+ mock_chat_message .content = "This is not code, just text"
508+
509+ # Set all required attributes on the instance
510+ core_agent_instance .agent_name = "test_agent"
511+ core_agent_instance .step_number = 1
512+ core_agent_instance .grammar = None
513+ core_agent_instance .logger = MagicMock ()
514+ core_agent_instance .memory = MagicMock ()
515+ core_agent_instance .memory .steps = []
516+
517+ with patch .object (core_agent_module , 'parse_code_blobs' , side_effect = ValueError ("No code found" )):
518+
519+ # Mock the methods directly on the instance
520+ core_agent_instance .write_memory_to_messages = MagicMock (return_value = [])
521+ core_agent_instance .model = MagicMock (return_value = mock_chat_message )
522+
523+ # Execute and assert
524+ with pytest .raises (core_agent_module .FinalAnswerError ):
525+ list (core_agent_instance ._step_stream (mock_memory_step ))
526+
527+
528+ def test_step_stream_model_generation_error (core_agent_instance ):
529+ """Test _step_stream method when model generation fails."""
530+ # Setup
531+ mock_memory_step = MagicMock ()
532+
533+ # Set all required attributes on the instance
534+ core_agent_instance .agent_name = "test_agent"
535+ core_agent_instance .step_number = 1
536+ core_agent_instance .grammar = None
537+ core_agent_instance .logger = MagicMock ()
538+ core_agent_instance .memory = MagicMock ()
539+ core_agent_instance .memory .steps = []
540+
541+ # Mock the methods directly on the instance
542+ core_agent_instance .write_memory_to_messages = MagicMock (return_value = [])
543+ core_agent_instance .model = MagicMock (side_effect = Exception ("Model error" ))
544+
545+ # Execute and assert
546+ with pytest .raises (Exception ): # Should raise the original exception wrapped in AgentGenerationError
547+ list (core_agent_instance ._step_stream (mock_memory_step ))
548+
549+
550+ def test_step_stream_execution_success (core_agent_instance ):
551+ """Test _step_stream method when code execution succeeds."""
552+ # Setup
553+ mock_memory_step = MagicMock ()
554+ mock_chat_message = MagicMock ()
555+ mock_chat_message .content = "```python\n print('hello')\n ```"
556+
557+ # Set all required attributes on the instance
558+ core_agent_instance .agent_name = "test_agent"
559+ core_agent_instance .step_number = 1
560+ core_agent_instance .grammar = None
561+ core_agent_instance .logger = MagicMock ()
562+ core_agent_instance .memory = MagicMock ()
563+ core_agent_instance .memory .steps = []
564+
565+ with patch .object (core_agent_module , 'parse_code_blobs' , return_value = "print('hello')" ), \
566+ patch .object (core_agent_module , 'fix_final_answer_code' , return_value = "print('hello')" ):
567+
568+ # Mock the methods directly on the instance
569+ core_agent_instance .write_memory_to_messages = MagicMock (return_value = [])
570+ core_agent_instance .model = MagicMock (return_value = mock_chat_message )
571+ core_agent_instance .python_executor = MagicMock (return_value = ("Hello World" , "Execution logs" , False ))
572+
573+ # Execute
574+ result = list (core_agent_instance ._step_stream (mock_memory_step ))
575+
576+ # Assertions
577+ assert result [0 ] is None # Should yield None when is_final_answer is False
578+ assert mock_memory_step .observations is not None
579+ # Check that observations was set (we can't easily test the exact content due to mock behavior)
580+ assert hasattr (mock_memory_step , 'observations' )
581+
582+
583+ def test_step_stream_execution_final_answer (core_agent_instance ):
584+ """Test _step_stream method when execution returns final answer."""
585+ # Setup
586+ mock_memory_step = MagicMock ()
587+ mock_chat_message = MagicMock ()
588+ mock_chat_message .content = "```python\n print('final answer')\n ```"
589+
590+ # Set all required attributes on the instance
591+ core_agent_instance .agent_name = "test_agent"
592+ core_agent_instance .step_number = 1
593+ core_agent_instance .grammar = None
594+ core_agent_instance .logger = MagicMock ()
595+ core_agent_instance .memory = MagicMock ()
596+ core_agent_instance .memory .steps = []
597+
598+ with patch .object (core_agent_module , 'parse_code_blobs' , return_value = "print('final answer')" ), \
599+ patch .object (core_agent_module , 'fix_final_answer_code' , return_value = "print('final answer')" ):
600+
601+ # Mock the methods directly on the instance
602+ core_agent_instance .write_memory_to_messages = MagicMock (return_value = [])
603+ core_agent_instance .model = MagicMock (return_value = mock_chat_message )
604+ core_agent_instance .python_executor = MagicMock (return_value = ("final answer" , "Execution logs" , True ))
605+
606+ # Execute
607+ result = list (core_agent_instance ._step_stream (mock_memory_step ))
608+
609+ # Assertions
610+ assert result [0 ] == "final answer" # Should yield the final answer
611+
612+
613+ def test_step_stream_execution_error (core_agent_instance ):
614+ """Test _step_stream method when code execution fails."""
615+ # Setup
616+ mock_memory_step = MagicMock ()
617+ mock_chat_message = MagicMock ()
618+ mock_chat_message .content = "```python\n invalid_code\n ```"
619+
620+ # Set all required attributes on the instance
621+ core_agent_instance .agent_name = "test_agent"
622+ core_agent_instance .step_number = 1
623+ core_agent_instance .grammar = None
624+ core_agent_instance .logger = MagicMock ()
625+ core_agent_instance .memory = MagicMock ()
626+ core_agent_instance .memory .steps = []
627+
628+ with patch .object (core_agent_module , 'parse_code_blobs' , return_value = "invalid_code" ), \
629+ patch .object (core_agent_module , 'fix_final_answer_code' , return_value = "invalid_code" ):
630+
631+ # Mock python_executor with state containing print outputs
632+ mock_executor = MagicMock ()
633+ mock_executor .state = {"_print_outputs" : "Some print output" }
634+ mock_executor .side_effect = Exception ("Execution error" )
635+
636+ # Mock the methods directly on the instance
637+ core_agent_instance .write_memory_to_messages = MagicMock (return_value = [])
638+ core_agent_instance .model = MagicMock (return_value = mock_chat_message )
639+ core_agent_instance .python_executor = mock_executor
640+
641+ # Execute and assert
642+ with pytest .raises (Exception ): # Should raise AgentExecutionError
643+ list (core_agent_instance ._step_stream (mock_memory_step ))
644+
645+ # Verify observations were set with print outputs
646+ assert mock_memory_step .observations is not None
647+ # Check that observations contains the print output
648+ assert hasattr (mock_memory_step .observations , '__contains__' ) or "Some print output" in str (mock_memory_step .observations )
649+
650+
651+ def test_step_stream_observer_calls (core_agent_instance ):
652+ """Test _step_stream method calls observer with correct messages."""
653+ # Setup
654+ mock_memory_step = MagicMock ()
655+ mock_chat_message = MagicMock ()
656+ mock_chat_message .content = "```python\n print('test')\n ```"
657+
658+ # Set all required attributes on the instance
659+ core_agent_instance .agent_name = "test_agent"
660+ core_agent_instance .step_number = 1
661+ core_agent_instance .grammar = None
662+ core_agent_instance .logger = MagicMock ()
663+ core_agent_instance .memory = MagicMock ()
664+ core_agent_instance .memory .steps = []
665+
666+ with patch .object (core_agent_module , 'parse_code_blobs' , return_value = "print('test')" ), \
667+ patch .object (core_agent_module , 'fix_final_answer_code' , return_value = "print('test')" ):
668+
669+ # Mock the methods directly on the instance
670+ core_agent_instance .write_memory_to_messages = MagicMock (return_value = [])
671+ core_agent_instance .model = MagicMock (return_value = mock_chat_message )
672+ core_agent_instance .python_executor = MagicMock (return_value = ("test" , "logs" , False ))
673+
674+ # Execute
675+ list (core_agent_instance ._step_stream (mock_memory_step ))
676+
677+ # Assertions
678+ # Should call observer for step count, parse, and execution logs
679+ assert core_agent_instance .observer .add_message .call_count >= 3
680+ calls = core_agent_instance .observer .add_message .call_args_list
681+
682+ # Check step count call
683+ step_count_call = calls [0 ]
684+ assert step_count_call [0 ][1 ] == ProcessType .STEP_COUNT
685+
686+ # Check parse call
687+ parse_call = calls [1 ]
688+ assert parse_call [0 ][1 ] == ProcessType .PARSE
689+ # The parse call should contain the fixed code, not the mock object
690+ assert "print('test')" in str (parse_call [0 ][2 ])
691+
692+ # Check execution logs call
693+ execution_call = calls [2 ]
694+ assert execution_call [0 ][1 ] == ProcessType .EXECUTION_LOGS
0 commit comments