fix(agent): finalize max-iteration turns without tools
This commit is contained in:
@@ -64,7 +64,8 @@ async def test_loop_goal_turn_uses_standard_iteration_budget(tmp_path):
|
||||
)
|
||||
|
||||
assert stop_reason == "max_iterations"
|
||||
assert loop.provider.chat_with_retry.await_count == 2
|
||||
assert loop.provider.chat_with_retry.await_count == 3
|
||||
assert loop.provider.chat_with_retry.await_args_list[-1].kwargs["tools"] is None
|
||||
assert final_content == (
|
||||
"I reached the maximum number of tool call iterations (2) "
|
||||
"without completing the task. You can try breaking the task into smaller steps."
|
||||
|
||||
@@ -101,6 +101,61 @@ async def test_runner_returns_max_iterations_fallback():
|
||||
)
|
||||
assert result.messages[-1]["role"] == "assistant"
|
||||
assert result.messages[-1]["content"] == result.final_content
|
||||
assert provider.chat_with_retry.await_count == 3
|
||||
assert provider.chat_with_retry.await_args_list[-1].kwargs["tools"] is None
|
||||
assert tools.execute.await_count == 2
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_runner_uses_no_tools_finalization_after_max_iterations():
|
||||
from nanobot.agent.runner import AgentRunner, AgentRunSpec
|
||||
|
||||
provider = MagicMock(spec=LLMProvider)
|
||||
calls: list[dict] = []
|
||||
|
||||
async def chat_with_retry(*, messages, tools=None, **kwargs):
|
||||
calls.append({"messages": messages, "tools": tools})
|
||||
if len(calls) <= 2:
|
||||
return LLMResponse(
|
||||
content="still working",
|
||||
tool_calls=[
|
||||
ToolCallRequest(
|
||||
id=f"call_{len(calls)}",
|
||||
name="list_dir",
|
||||
arguments={"path": "."},
|
||||
)
|
||||
],
|
||||
)
|
||||
return LLMResponse(
|
||||
content="Read the directory twice. More investigation remains.",
|
||||
tool_calls=[],
|
||||
usage={"prompt_tokens": 10, "completion_tokens": 7},
|
||||
)
|
||||
|
||||
provider.chat_with_retry = chat_with_retry
|
||||
tools = MagicMock()
|
||||
tools.get_definitions.return_value = []
|
||||
tools.execute = AsyncMock(return_value="tool result")
|
||||
|
||||
runner = AgentRunner(provider)
|
||||
result = await runner.run(AgentRunSpec(
|
||||
initial_messages=[{"role": "user", "content": "inspect the repo"}],
|
||||
tools=tools,
|
||||
model="test-model",
|
||||
max_iterations=2,
|
||||
max_tool_result_chars=_MAX_TOOL_RESULT_CHARS,
|
||||
))
|
||||
|
||||
assert result.stop_reason == "max_iterations"
|
||||
assert result.final_content == "Read the directory twice. More investigation remains."
|
||||
assert result.messages[-1] == {
|
||||
"role": "assistant",
|
||||
"content": "Read the directory twice. More investigation remains.",
|
||||
}
|
||||
assert len(calls) == 3
|
||||
assert calls[-1]["tools"] is None
|
||||
assert "tool-call budget" in calls[-1]["messages"][-1]["content"]
|
||||
assert tools.execute.await_count == 2
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
||||
@@ -150,6 +150,7 @@ async def test_runner_goal_continue_not_limited_by_injection_cycle_cap():
|
||||
max_iterations=max_iterations,
|
||||
max_tool_result_chars=_MAX_TOOL_RESULT_CHARS,
|
||||
goal_active_predicate=lambda: True,
|
||||
finalize_on_max_iterations=False,
|
||||
))
|
||||
|
||||
assert result.stop_reason == "max_iterations"
|
||||
|
||||
@@ -17,6 +17,7 @@ from nanobot.session.turn_continuation import (
|
||||
internal_continuation_pending,
|
||||
internal_continuation_run_started_at,
|
||||
maybe_continue_turn,
|
||||
should_finalize_on_max_iterations,
|
||||
should_stream_budget_response,
|
||||
)
|
||||
|
||||
@@ -125,3 +126,15 @@ def test_internal_continuation_requires_budget_boundary_and_queue():
|
||||
pending_queue_available=False,
|
||||
session_metadata=meta,
|
||||
)
|
||||
assert not should_finalize_on_max_iterations(
|
||||
pending_queue_available=True,
|
||||
session_metadata=meta,
|
||||
)
|
||||
assert should_finalize_on_max_iterations(
|
||||
pending_queue_available=False,
|
||||
session_metadata=meta,
|
||||
)
|
||||
assert should_finalize_on_max_iterations(
|
||||
pending_queue_available=True,
|
||||
session_metadata={},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user