@@ -238,6 +238,189 @@ def test_prepare_seeds_overrides_store(
238238 assert call_args .kwargs .get ("tag" ) == "latest"
239239
240240
241+ class TestTriviaAgentLoopPreprocessing :
242+ """Tests for TriviaAgentLoop.preprocess_request() method."""
243+
244+ def test_preprocess_request_returns_unchanged_by_default (
245+ self ,
246+ fake_mailboxes : TriviaMailboxes ,
247+ ) -> None :
248+ """Test that preprocess_request returns request unchanged by default."""
249+ mock_adapter : ProviderAdapter [TriviaResponse ] = MagicMock ()
250+
251+ loop = TriviaAgentLoop (
252+ adapter = mock_adapter ,
253+ requests = fake_mailboxes .requests ,
254+ )
255+
256+ request = TriviaRequest (question = "test question" )
257+ result = loop .preprocess_request (request )
258+
259+ assert result is request
260+
261+ def test_preprocess_request_can_be_overridden (
262+ self ,
263+ fake_mailboxes : TriviaMailboxes ,
264+ ) -> None :
265+ """Test that preprocess_request can be overridden in subclass."""
266+
267+ class CustomLoop (TriviaAgentLoop ):
268+ def preprocess_request (self , request : TriviaRequest ) -> TriviaRequest :
269+ return TriviaRequest (question = request .question .upper ())
270+
271+ mock_adapter : ProviderAdapter [TriviaResponse ] = MagicMock ()
272+
273+ loop = CustomLoop (
274+ adapter = mock_adapter ,
275+ requests = fake_mailboxes .requests ,
276+ )
277+
278+ request = TriviaRequest (question = "hello world" )
279+ result = loop .preprocess_request (request )
280+
281+ assert result .question == "HELLO WORLD"
282+
283+
284+ class TestTriviaAgentLoopPostprocessing :
285+ """Tests for TriviaAgentLoop.postprocess_response() method."""
286+
287+ def test_postprocess_response_returns_unchanged_by_default (
288+ self ,
289+ fake_mailboxes : TriviaMailboxes ,
290+ ) -> None :
291+ """Test that postprocess_response returns response unchanged by default."""
292+ mock_adapter : ProviderAdapter [TriviaResponse ] = MagicMock ()
293+
294+ loop = TriviaAgentLoop (
295+ adapter = mock_adapter ,
296+ requests = fake_mailboxes .requests ,
297+ )
298+
299+ response = TriviaResponse (answer = "42" )
300+ result = loop .postprocess_response (response )
301+
302+ assert result is response
303+
304+ def test_postprocess_response_can_be_overridden (
305+ self ,
306+ fake_mailboxes : TriviaMailboxes ,
307+ ) -> None :
308+ """Test that postprocess_response can be overridden in subclass."""
309+
310+ class CustomLoop (TriviaAgentLoop ):
311+ def postprocess_response (self , response : TriviaResponse ) -> TriviaResponse :
312+ return TriviaResponse (answer = f"Answer: { response .answer } " )
313+
314+ mock_adapter : ProviderAdapter [TriviaResponse ] = MagicMock ()
315+
316+ loop = CustomLoop (
317+ adapter = mock_adapter ,
318+ requests = fake_mailboxes .requests ,
319+ )
320+
321+ response = TriviaResponse (answer = "42" )
322+ result = loop .postprocess_response (response )
323+
324+ assert result .answer == "Answer: 42"
325+
326+
327+ class TestTriviaAgentLoopExecute :
328+ """Tests for TriviaAgentLoop.execute() with preprocessing/postprocessing."""
329+
330+ def test_execute_calls_preprocess_request (
331+ self ,
332+ fake_mailboxes : TriviaMailboxes ,
333+ ) -> None :
334+ """Test that execute() calls preprocess_request."""
335+ from weakincentives .runtime import MainLoop
336+
337+ class CustomLoop (TriviaAgentLoop ):
338+ def preprocess_request (self , request : TriviaRequest ) -> TriviaRequest :
339+ return TriviaRequest (question = request .question .strip ())
340+
341+ mock_adapter : ProviderAdapter [TriviaResponse ] = MagicMock ()
342+
343+ loop = CustomLoop (
344+ adapter = mock_adapter ,
345+ requests = fake_mailboxes .requests ,
346+ )
347+
348+ mock_response = MagicMock ()
349+ mock_response .output = TriviaResponse (answer = "42" )
350+ mock_session = MagicMock ()
351+
352+ captured_requests : list [TriviaRequest ] = []
353+
354+ def capture_execute (self_arg , request , ** kwargs ):
355+ captured_requests .append (request )
356+ return (mock_response , mock_session )
357+
358+ with patch .object (MainLoop , "execute" , capture_execute ):
359+ request = TriviaRequest (question = " What is the answer? " )
360+ loop .execute (request )
361+
362+ assert len (captured_requests ) == 1
363+ assert captured_requests [0 ].question == "What is the answer?"
364+
365+ def test_execute_calls_postprocess_response (
366+ self ,
367+ fake_mailboxes : TriviaMailboxes ,
368+ ) -> None :
369+ """Test that execute() calls postprocess_response."""
370+ from weakincentives .runtime import MainLoop
371+
372+ class CustomLoop (TriviaAgentLoop ):
373+ def postprocess_response (self , response : TriviaResponse ) -> TriviaResponse :
374+ return TriviaResponse (answer = response .answer .strip ())
375+
376+ mock_adapter : ProviderAdapter [TriviaResponse ] = MagicMock ()
377+
378+ loop = CustomLoop (
379+ adapter = mock_adapter ,
380+ requests = fake_mailboxes .requests ,
381+ )
382+
383+ mock_response = MagicMock ()
384+ mock_response .output = TriviaResponse (answer = " 42 " )
385+ mock_response .update = MagicMock (return_value = mock_response )
386+ mock_session = MagicMock ()
387+
388+ with patch .object (MainLoop , "execute" , return_value = (mock_response , mock_session )):
389+ request = TriviaRequest (question = "What is the answer?" )
390+ loop .execute (request )
391+
392+ mock_response .update .assert_called_once ()
393+ call_kwargs = mock_response .update .call_args .kwargs
394+ assert call_kwargs ["output" ].answer == "42"
395+
396+ def test_execute_skips_postprocessing_when_output_is_none (
397+ self ,
398+ fake_mailboxes : TriviaMailboxes ,
399+ ) -> None :
400+ """Test that execute() skips postprocessing when output is None."""
401+ from weakincentives .runtime import MainLoop
402+
403+ mock_adapter : ProviderAdapter [TriviaResponse ] = MagicMock ()
404+
405+ loop = TriviaAgentLoop (
406+ adapter = mock_adapter ,
407+ requests = fake_mailboxes .requests ,
408+ )
409+
410+ mock_response = MagicMock ()
411+ mock_response .output = None
412+ mock_response .update = MagicMock ()
413+ mock_session = MagicMock ()
414+
415+ with patch .object (MainLoop , "execute" , return_value = (mock_response , mock_session )):
416+ request = TriviaRequest (question = "What is the answer?" )
417+ result_response , result_session = loop .execute (request )
418+
419+ mock_response .update .assert_not_called ()
420+ assert result_response is mock_response
421+ assert result_session is mock_session
422+
423+
241424class TestTriviaRuntime :
242425 """Tests for TriviaRuntime dataclass."""
243426
0 commit comments