@@ -165,6 +165,87 @@ async def test_handle_api_error_model_not_vlm_after_fallback_raises():
165165 await provider .terminate ()
166166
167167
168+ @pytest .mark .asyncio
169+ async def test_handle_api_error_context_length_removes_orphaned_tool_messages ():
170+ provider = _make_provider ()
171+ try :
172+ payloads = {
173+ "messages" : [
174+ {"role" : "system" , "content" : "system" },
175+ {"role" : "user" , "content" : "Run tool" },
176+ {
177+ "role" : "assistant" ,
178+ "content" : "" ,
179+ "tool_calls" : [
180+ {
181+ "id" : "call_1" ,
182+ "type" : "function" ,
183+ "function" : {"name" : "search" , "arguments" : "{}" },
184+ }
185+ ],
186+ },
187+ {"role" : "tool" , "content" : "Tool result" , "tool_call_id" : "call_1" },
188+ {"role" : "assistant" , "content" : "Final answer" },
189+ ]
190+ }
191+ context_query = payloads ["messages" ]
192+
193+ success , * _rest = await provider ._handle_api_error (
194+ Exception ("maximum context length exceeded" ),
195+ payloads = payloads ,
196+ context_query = context_query ,
197+ func_tool = None ,
198+ chosen_key = "test-key" ,
199+ available_api_keys = ["test-key" ],
200+ retry_cnt = 0 ,
201+ max_retries = 10 ,
202+ )
203+
204+ assert success is False
205+ assert payloads ["messages" ] == [
206+ {"role" : "system" , "content" : "system" },
207+ {"role" : "assistant" , "content" : "Final answer" },
208+ ]
209+ finally :
210+ await provider .terminate ()
211+
212+
213+ @pytest .mark .asyncio
214+ async def test_handle_api_error_context_length_preserves_remaining_valid_messages ():
215+ provider = _make_provider ()
216+ try :
217+ payloads = {
218+ "messages" : [
219+ {"role" : "system" , "content" : "system" },
220+ {"role" : "user" , "content" : "old question" },
221+ {"role" : "assistant" , "content" : "old answer" },
222+ {"role" : "user" , "content" : "new question" },
223+ {"role" : "assistant" , "content" : "new answer" },
224+ ]
225+ }
226+ context_query = payloads ["messages" ]
227+
228+ success , * _rest = await provider ._handle_api_error (
229+ Exception ("maximum context length exceeded" ),
230+ payloads = payloads ,
231+ context_query = context_query ,
232+ func_tool = None ,
233+ chosen_key = "test-key" ,
234+ available_api_keys = ["test-key" ],
235+ retry_cnt = 0 ,
236+ max_retries = 10 ,
237+ )
238+
239+ assert success is False
240+ assert payloads ["messages" ] == [
241+ {"role" : "system" , "content" : "system" },
242+ {"role" : "user" , "content" : "new question" },
243+ {"role" : "assistant" , "content" : "new answer" },
244+ ]
245+ finally :
246+ await provider .terminate ()
247+
248+
168249@pytest .mark .asyncio
169250async def test_handle_api_error_content_moderated_with_unserializable_body ():
170251 provider = _make_provider ({"image_moderation_error_patterns" : ["blocked" ]})
0 commit comments