tenseleyflow/loader / fcbd279

Browse files

Cover honest no-tool completion behavior

Authored by espadonne
SHA
fcbd2795f26deece0f38f8fcabf5fdff6af603e7
Parents
51dbee4
Tree
2a523b7

1 changed file

StatusFile+-
M tests/test_turn_completion.py 116 0
tests/test_turn_completion.pymodified
@@ -129,3 +129,119 @@ async def test_turn_completion_marks_non_mutating_response_done(
129129
         event.type == "dod_status" and event.dod_status == "done"
130130
         for event in events
131131
     )
132
+
133
+
134
+@pytest.mark.asyncio
135
+async def test_turn_completion_handles_fake_tool_narration_without_reroute(
136
+    temp_dir: Path,
137
+) -> None:
138
+    backend = ScriptedBackend()
139
+    config = non_streaming_config()
140
+    config.reasoning.completion_check = False
141
+    agent = Agent(
142
+        backend=backend,
143
+        config=config,
144
+        project_root=temp_dir,
145
+    )
146
+    runtime = ConversationRuntime(agent)
147
+    events = []
148
+
149
+    async def capture(event) -> None:
150
+        events.append(event)
151
+
152
+    prepared = await runtime.turn_preparation.prepare(
153
+        task="Summarize the current test status.",
154
+        emit=capture,
155
+        requested_mode="execute",
156
+        original_task=None,
157
+        on_user_question=None,
158
+    )
159
+    await runtime.phase_tracker.enter(
160
+        TurnPhase.ASSISTANT,
161
+        capture,
162
+        detail="Requesting assistant response",
163
+        reason_code="request_assistant_response",
164
+    )
165
+
166
+    narrated = "Used bash tool with command `pytest -q` and everything passed."
167
+    decision = await runtime.turn_completion.handle_text_response(
168
+        content=narrated,
169
+        response_content=narrated,
170
+        task=prepared.task,
171
+        effective_task=prepared.effective_task,
172
+        iterations=1,
173
+        max_iterations=agent.config.max_iterations,
174
+        actions_taken=[],
175
+        continuation_count=0,
176
+        dod=prepared.definition_of_done,
177
+        emit=capture,
178
+        summary=prepared.summary,
179
+        executor=prepared.executor,
180
+        rollback_plan=prepared.rollback_plan,
181
+    )
182
+
183
+    assert decision.action == TurnCompletionAction.COMPLETE
184
+    assert prepared.summary.final_response == narrated
185
+    assert not any(
186
+        "PRETENDING to use tools" in message.content
187
+        for message in agent.session.messages
188
+    )
189
+    assert any(event.type == "response" and event.content == narrated for event in events)
190
+
191
+
192
+@pytest.mark.asyncio
193
+async def test_turn_completion_handles_deflection_text_without_repair_prompt(
194
+    temp_dir: Path,
195
+) -> None:
196
+    backend = ScriptedBackend()
197
+    config = non_streaming_config()
198
+    config.reasoning.completion_check = False
199
+    agent = Agent(
200
+        backend=backend,
201
+        config=config,
202
+        project_root=temp_dir,
203
+    )
204
+    runtime = ConversationRuntime(agent)
205
+    events = []
206
+
207
+    async def capture(event) -> None:
208
+        events.append(event)
209
+
210
+    prepared = await runtime.turn_preparation.prepare(
211
+        task="What should I verify next?",
212
+        emit=capture,
213
+        requested_mode="execute",
214
+        original_task=None,
215
+        on_user_question=None,
216
+    )
217
+    await runtime.phase_tracker.enter(
218
+        TurnPhase.ASSISTANT,
219
+        capture,
220
+        detail="Requesting assistant response",
221
+        reason_code="request_assistant_response",
222
+    )
223
+
224
+    deflection = "You can run pytest -q to verify the current state."
225
+    decision = await runtime.turn_completion.handle_text_response(
226
+        content=deflection,
227
+        response_content=deflection,
228
+        task=prepared.task,
229
+        effective_task=prepared.effective_task,
230
+        iterations=1,
231
+        max_iterations=agent.config.max_iterations,
232
+        actions_taken=[],
233
+        continuation_count=0,
234
+        dod=prepared.definition_of_done,
235
+        emit=capture,
236
+        summary=prepared.summary,
237
+        executor=prepared.executor,
238
+        rollback_plan=prepared.rollback_plan,
239
+    )
240
+
241
+    assert decision.action == TurnCompletionAction.COMPLETE
242
+    assert prepared.summary.final_response == deflection
243
+    assert not any(
244
+        "Please use your tools to execute the task" in message.content
245
+        for message in agent.session.messages
246
+    )
247
+    assert any(event.type == "response" and event.content == deflection for event in events)