fix(agent): keep max-iteration warnings out of quiet stdout
Route the max-iterations diagnostic through logging when quiet_mode is active so automation wrappers keep stdout machine-readable. Add a regression test covering quiet max-iteration summary handling.
This commit is contained in:
@@ -2848,8 +2848,21 @@ def try_activate_fallback(agent, reason: "FailoverReason | None" = None) -> bool
|
||||
|
||||
def handle_max_iterations(agent, messages: list, api_call_count: int) -> str:
|
||||
"""Request a summary when max iterations are reached. Returns the final response text."""
|
||||
agent._safe_print(
|
||||
f"⚠️ Reached maximum iterations ({agent.max_iterations}). Requesting summary..."
|
||||
warning = f"⚠️ Reached maximum iterations ({agent.max_iterations}). Requesting summary..."
|
||||
if getattr(agent, "suppress_status_output", False):
|
||||
# Strict machine-readable mode (hermes chat -Q, oneshot, background
|
||||
# review): keep diagnostics out of stdout so wrappers receive only
|
||||
# the final assistant content (#93220 class). Note: plain quiet_mode
|
||||
# is NOT the right gate — the interactive CLI runs quiet_mode=True by
|
||||
# default and should still see this warning.
|
||||
logger.warning(warning)
|
||||
else:
|
||||
agent._safe_print(warning)
|
||||
|
||||
summary_request = (
|
||||
"You've reached the maximum number of tool-calling iterations allowed. "
|
||||
"Please provide a final response summarizing what you've found and accomplished so far, "
|
||||
"without calling any more tools."
|
||||
)
|
||||
|
||||
summary_api_request_id = f"iteration-summary:{uuid.uuid4()}"
|
||||
|
||||
@@ -2689,6 +2689,42 @@ class TestHandleMaxIterations:
|
||||
outcome="success",
|
||||
)
|
||||
|
||||
def test_suppress_status_output_keeps_iteration_warning_off_stdout(self, agent, capsys):
|
||||
"""Machine-readable mode (-Q/oneshot) must not contaminate stdout (#26155)."""
|
||||
resp = _mock_response(content="Summary")
|
||||
agent.client.chat.completions.create.return_value = resp
|
||||
agent._cached_system_prompt = "You are helpful."
|
||||
agent.suppress_status_output = True
|
||||
|
||||
result = agent._handle_max_iterations(
|
||||
[{"role": "user", "content": "do stuff"}],
|
||||
1,
|
||||
)
|
||||
|
||||
captured = capsys.readouterr()
|
||||
assert result == "Summary"
|
||||
assert "Reached maximum iterations" not in captured.out
|
||||
|
||||
def test_plain_quiet_mode_still_prints_iteration_warning(self, agent, capsys):
|
||||
"""Interactive CLI runs quiet_mode=True by default — the warning must
|
||||
still show there; only suppress_status_output gates it (#26155)."""
|
||||
resp = _mock_response(content="Summary")
|
||||
agent.client.chat.completions.create.return_value = resp
|
||||
agent._cached_system_prompt = "You are helpful."
|
||||
agent.quiet_mode = True
|
||||
agent.suppress_status_output = False
|
||||
printed = []
|
||||
agent._print_fn = lambda *a, **k: printed.append(" ".join(str(x) for x in a))
|
||||
|
||||
result = agent._handle_max_iterations(
|
||||
[{"role": "user", "content": "do stuff"}],
|
||||
1,
|
||||
)
|
||||
|
||||
assert result == "Summary"
|
||||
combined = "\n".join(printed) + capsys.readouterr().out
|
||||
assert "Reached maximum iterations" in combined
|
||||
|
||||
def test_api_failure_returns_error(self, agent):
|
||||
agent.client.chat.completions.create.side_effect = Exception("API down")
|
||||
agent._cached_system_prompt = "You are helpful."
|
||||
|
||||
Reference in New Issue
Block a user