mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-27 11:22:03 +00:00
fix(gateway): surface retry hint instead of silently dropping turn after /stop (#31884)
After /stop, the next user message can hit a stale generation token and return with api_calls=0, no failure, no interruption. _normalize_empty_agent_response fell through to an empty string, so the gateway logged "response=0 chars" and sent nothing — the message was silently lost while internal work sometimes continued. Add the api_calls==0 / not-failed / not-interrupted / not-partial branch to the single normalization chokepoint so the user gets a short retry hint instead of silence. Regression test asserts the hint surfaces. Salvaged from #33851 (re-applied on current main; original was 1401 commits behind and the function had moved).
This commit is contained in:
parent
35e9c63d89
commit
b41d9b845d
2 changed files with 47 additions and 0 deletions
|
|
@ -2332,6 +2332,12 @@ def _normalize_empty_agent_response(
|
|||
Consolidates the existing ``failed`` handler and adds a catch-all for
|
||||
the case where the agent did work (api_calls > 0) but returned no text.
|
||||
Fix for #18765.
|
||||
|
||||
Also surfaces a retry hint when the agent never ran at all
|
||||
(api_calls == 0) for a non-interrupted, non-failed turn -- this is the
|
||||
silent-drop pattern observed after ``/stop`` where the next user
|
||||
message hits a stale generation token and returns an empty result,
|
||||
leaving the platform with nothing to send. (#31884)
|
||||
"""
|
||||
if response:
|
||||
return response
|
||||
|
|
@ -2364,6 +2370,22 @@ def _normalize_empty_agent_response(
|
|||
"This may be a transient error — try sending your message again."
|
||||
)
|
||||
|
||||
# api_calls == 0, not failed, not interrupted: the agent never ran for
|
||||
# this turn. This is the post-/stop generation-race pattern where the
|
||||
# gateway would otherwise silently drop the turn (response=0 chars) and
|
||||
# the user sees no reply at all. Surface a short retry hint so the
|
||||
# message isn't lost in silence. (#31884)
|
||||
if (
|
||||
api_calls == 0
|
||||
and not agent_result.get("interrupted")
|
||||
and not agent_result.get("failed")
|
||||
and not agent_result.get("partial")
|
||||
):
|
||||
return (
|
||||
"⚠️ Your message wasn't processed (the previous turn was still "
|
||||
"being cleaned up). Please send it again."
|
||||
)
|
||||
|
||||
return response
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -415,6 +415,31 @@ class TestGatewaySurfacesNullResponse:
|
|||
|
||||
assert result == "Hello!"
|
||||
|
||||
def test_silent_drop_after_stop_surfaces_hint(self):
|
||||
"""Regression for #31884: after /stop, the next user message hits a
|
||||
stale generation token in _run_agent and returns with api_calls=0,
|
||||
no failure, no interruption. Without normalization the gateway
|
||||
silently drops the turn (response=0 chars). Surface a retry hint
|
||||
so the user knows the message was lost."""
|
||||
from gateway.run import _normalize_empty_agent_response
|
||||
|
||||
agent_result = {
|
||||
"final_response": "",
|
||||
"api_calls": 0,
|
||||
"failed": False,
|
||||
"interrupted": False,
|
||||
"partial": False,
|
||||
}
|
||||
|
||||
response = agent_result.get("final_response") or ""
|
||||
result = _normalize_empty_agent_response(
|
||||
agent_result, response, history_len=10,
|
||||
)
|
||||
|
||||
assert result, "Silent-drop turn must surface a user-facing hint"
|
||||
lowered = result.lower()
|
||||
assert "send it again" in lowered or "try again" in lowered
|
||||
|
||||
|
||||
# ===========================================================================
|
||||
# Prune: finalize_orphaned_compression_sessions
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue