@@ -168,6 +168,57 @@ async def test_on_tool_error_callback_max_retries_zero(self):
168168 # Should re-raise the original exception when max_retries is 0
169169 self .assertIs (cm .exception , error )
170170
171+ async def test_on_tool_error_callback_max_retries_zero_without_exception (
172+ self ,
173+ ):
174+ """Test error callback when max_retries is 0 and exception is disabled."""
175+ mock_tool = self .get_mock_tool ()
176+ mock_tool_context = self .get_mock_tool_context ()
177+ sample_tool_args = self .get_sample_tool_args ()
178+ plugin = ReflectAndRetryToolPlugin (
179+ max_retries = 0 , throw_exception_if_retry_exceeded = False
180+ )
181+ error = ValueError ("Test error" )
182+
183+ result = await plugin .on_tool_error_callback (
184+ tool = mock_tool ,
185+ tool_args = sample_tool_args ,
186+ tool_context = mock_tool_context ,
187+ error = error ,
188+ )
189+
190+ # Should return a retry exceeded message instead of raising
191+ self .assertIsNotNone (result )
192+ self .assertEqual (result ["response_type" ], REFLECT_AND_RETRY_RESPONSE_TYPE )
193+ self .assertEqual (result ["error_type" ], "ValueError" )
194+ self .assertEqual (result ["retry_count" ], 0 )
195+ self .assertIn (
196+ "the retry limit has been exceeded" , result ["reflection_guidance" ]
197+ )
198+
199+ async def test_on_tool_error_callback_max_retries_zero_with_dict_error (self ):
200+ """Test error callback when max_retries is 0 and error is a dict."""
201+ mock_tool = self .get_mock_tool ()
202+ mock_tool_context = self .get_mock_tool_context ()
203+ sample_tool_args = self .get_sample_tool_args ()
204+ plugin = CustomErrorExtractionPlugin (
205+ max_retries = 0 , throw_exception_if_retry_exceeded = True
206+ )
207+ dict_error = {"status" : "error" , "message" : "Custom dict error" }
208+ plugin .set_error_condition (lambda result : dict_error )
209+
210+ with self .assertRaises (Exception ) as cm :
211+ await plugin .after_tool_callback (
212+ tool = mock_tool ,
213+ tool_args = sample_tool_args ,
214+ tool_context = mock_tool_context ,
215+ result = {"some" : "result" },
216+ )
217+
218+ # Should raise an Exception wrapping the dict
219+ self .assertNotIsInstance (cm .exception , TypeError )
220+ self .assertIn ("Custom dict error" , str (cm .exception ))
221+
171222 async def test_on_tool_error_callback_first_failure (self ):
172223 """Test first tool failure creates reflection response."""
173224 plugin = self .get_plugin ()
@@ -280,6 +331,40 @@ async def test_max_retries_exceeded_with_exception(self):
280331 # Verify exception properties
281332 self .assertIs (cm .exception , error )
282333
334+ async def test_max_retries_exceeded_with_dict_error (self ):
335+ """Test that Exception is raised when max retries exceeded with dict error."""
336+ mock_tool = self .get_mock_tool ()
337+ mock_tool_context = self .get_mock_tool_context ()
338+ sample_tool_args = self .get_sample_tool_args ()
339+ plugin = CustomErrorExtractionPlugin (
340+ max_retries = 1 , throw_exception_if_retry_exceeded = True
341+ )
342+ dict_error = {"status" : "error" , "message" : "Custom dict error" }
343+ plugin .set_error_condition (lambda result : dict_error )
344+
345+ # First call should fail and return a retry response
346+ result1 = await plugin .after_tool_callback (
347+ tool = mock_tool ,
348+ tool_args = sample_tool_args ,
349+ tool_context = mock_tool_context ,
350+ result = {"some" : "result" },
351+ )
352+ self .assertIsNotNone (result1 )
353+ self .assertEqual (result1 ["retry_count" ], 1 )
354+
355+ # Second call should exceed max_retries and raise
356+ with self .assertRaises (Exception ) as cm :
357+ await plugin .after_tool_callback (
358+ tool = mock_tool ,
359+ tool_args = sample_tool_args ,
360+ tool_context = mock_tool_context ,
361+ result = {"some" : "result" },
362+ )
363+
364+ # Verify exception properties
365+ self .assertNotIsInstance (cm .exception , TypeError )
366+ self .assertIn ("Custom dict error" , str (cm .exception ))
367+
283368 async def test_max_retries_exceeded_without_exception (self ):
284369 """Test max retries exceeded returns failure message when exception is disabled."""
285370 mock_tool = self .get_mock_tool ()
0 commit comments