diff --git a/src/clean_agent_preview.py b/src/clean_agent_preview.py index 4404d0889..42d7d6d11 100644 --- a/src/clean_agent_preview.py +++ b/src/clean_agent_preview.py @@ -4196,7 +4196,7 @@ async def stream_preview(*, endpoint_url, model, messages, headers, turn_contrac successful_editor_writer = None successful_artifact_write = False artifact_recovery_attempts = 0 - artifact_body_handoff_attempted = False + artifact_body_handoff_attempts = 0 artifact_body_handoff_target = '' artifact_off_contract_failures = 0 artifact_write_phase = False @@ -5444,9 +5444,9 @@ async def stream_preview(*, endpoint_url, model, messages, headers, turn_contrac ) if ( repeated_handoff_target - and not artifact_body_handoff_attempted + and artifact_body_handoff_attempts < 2 ): - artifact_body_handoff_attempted = True + artifact_body_handoff_attempts += 1 artifact_body_handoff_target = repeated_handoff_target if str(exc).startswith('The calendar read has not succeeded yet.'): # Remove the dependent writer for one correction @@ -5459,9 +5459,9 @@ async def stream_preview(*, endpoint_url, model, messages, headers, turn_contrac if ( handoff_target and canonical(name) == 'write_file' - and not artifact_body_handoff_attempted + and artifact_body_handoff_attempts < 2 ): - artifact_body_handoff_attempted = True + artifact_body_handoff_attempts += 1 artifact_body_handoff_target = handoff_target result = {'error': str(exc).splitlines()[0][:300], 'exit_code': 1} output = preview_tool_result_text(result, block.tool_type if block is not None else name, args) diff --git a/tests/test_clean_agent_preview.py b/tests/test_clean_agent_preview.py index e41146cfe..23fdf86c9 100644 --- a/tests/test_clean_agent_preview.py +++ b/tests/test_clean_agent_preview.py @@ -548,6 +548,13 @@ async def test_repeated_off_contract_calls_recover_via_required_artifact_body(mo 'code': 'print("nope")', })}, }]}}]}, + {'choices': [{'delta': {'content': ''}}]}, + {'choices': [{'delta': {'tool_calls': [{ + 'index': 0, 'id': 'bad-inspect', + 'function': {'name': 'inspect_media', 'arguments': json.dumps({ + 'path': '/workspace/input.png', + })}, + }]}}]}, {'choices': [{'delta': {'content': 'Recovered'}}]}, ]) @@ -604,7 +611,7 @@ async def test_repeated_off_contract_calls_recover_via_required_artifact_body(mo event.get('type') == 'tool_output' and event.get('execution_attempted') is False for event in events - ) == 2 + ) == 3 assert any( event.get('type') == 'artifact_body_handoff' and event.get('path') == '/workspace/output.html'