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:
honor2030
2026-05-15 15:13:11 +09:00
committed by Teknium
parent 36bbb41d6c
commit fe483de4d3
2 changed files with 51 additions and 2 deletions
+15 -2
View File
@@ -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()}"
+36
View File
@@ -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."