mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-21 16:04:41 +00:00
fix(codex): keep large-request ttfb watchdog active
This commit is contained in:
parent
d6c14a952f
commit
a7784f11fb
2 changed files with 59 additions and 17 deletions
|
|
@ -534,25 +534,28 @@ def interruptible_api_call(agent, api_kwargs: dict):
|
|||
and _ttfb_disable_above > 0
|
||||
and _est_tokens_for_codex_watchdog >= _ttfb_disable_above
|
||||
):
|
||||
_ttfb_enabled = False
|
||||
logger.info(
|
||||
"Disabling openai-codex no-byte TTFB watchdog for large request "
|
||||
"(context=~%s tokens >= %.0f). Waiting for backend response instead. "
|
||||
"Set HERMES_CODEX_TTFB_STRICT=1 to force early reconnects.",
|
||||
f"{_est_tokens_for_codex_watchdog:,}",
|
||||
_ttfb_disable_above,
|
||||
)
|
||||
else:
|
||||
_ttfb_cap = _env_float("HERMES_CODEX_TTFB_MAX_SECONDS", 120.0)
|
||||
if _ttfb_cap > 0 and _ttfb_timeout > _ttfb_cap:
|
||||
_large_request_ttfb_timeout = _codex_idle_timeout_default
|
||||
if _ttfb_timeout < _large_request_ttfb_timeout:
|
||||
logger.info(
|
||||
"Capping openai-codex no-byte TTFB timeout from %.0fs to %.0fs "
|
||||
"(context=~%s tokens). Set HERMES_CODEX_TTFB_MAX_SECONDS to tune.",
|
||||
"Scaling openai-codex no-byte TTFB watchdog from %.0fs to %.0fs "
|
||||
"for large request (context=~%s tokens >= %.0f). "
|
||||
"Set HERMES_CODEX_TTFB_STRICT=1 to keep the smaller cutoff.",
|
||||
_ttfb_timeout,
|
||||
_ttfb_cap,
|
||||
_large_request_ttfb_timeout,
|
||||
f"{_est_tokens_for_codex_watchdog:,}",
|
||||
_ttfb_disable_above,
|
||||
)
|
||||
_ttfb_timeout = _ttfb_cap
|
||||
_ttfb_timeout = _large_request_ttfb_timeout
|
||||
_ttfb_cap = _env_float("HERMES_CODEX_TTFB_MAX_SECONDS", 120.0)
|
||||
if _ttfb_cap > 0 and _ttfb_timeout > _ttfb_cap:
|
||||
logger.info(
|
||||
"Capping openai-codex no-byte TTFB timeout from %.0fs to %.0fs "
|
||||
"(context=~%s tokens). Set HERMES_CODEX_TTFB_MAX_SECONDS to tune.",
|
||||
_ttfb_timeout,
|
||||
_ttfb_cap,
|
||||
f"{_est_tokens_for_codex_watchdog:,}",
|
||||
)
|
||||
_ttfb_timeout = _ttfb_cap
|
||||
|
||||
_codex_idle_enabled = _codex_watchdog_enabled
|
||||
_codex_idle_timeout = _env_float(
|
||||
|
|
|
|||
|
|
@ -353,8 +353,8 @@ def test_ttfb_disabled_via_env_zero(tmp_path, monkeypatch):
|
|||
|
||||
def test_large_codex_request_waits_instead_of_ttfb_reconnect(tmp_path, monkeypatch):
|
||||
"""Large Codex inputs can legitimately take longer than the small-request
|
||||
first-byte cutoff before the first SSE frame. Preserve the full input and
|
||||
wait instead of killing/retrying at TTFB."""
|
||||
first-byte cutoff before the first SSE frame. Scale the TTFB timeout up
|
||||
for those requests instead of killing/retrying at the small-request cutoff."""
|
||||
from agent import chat_completion_helpers as h
|
||||
|
||||
agent = _make_codex_agent(tmp_path, monkeypatch)
|
||||
|
|
@ -386,6 +386,45 @@ def test_large_codex_request_waits_instead_of_ttfb_reconnect(tmp_path, monkeypat
|
|||
assert "codex_ttfb_kill" not in closes
|
||||
|
||||
|
||||
def test_large_codex_request_can_still_ttfb_reconnect_when_capped(tmp_path, monkeypatch):
|
||||
"""Large Codex requests should keep a finite TTFB watchdog instead of
|
||||
disabling it entirely. A low max cap should still force an early reconnect."""
|
||||
from agent import chat_completion_helpers as h
|
||||
|
||||
agent = _make_codex_agent(tmp_path, monkeypatch)
|
||||
monkeypatch.setenv("HERMES_CODEX_TTFB_TIMEOUT_SECONDS", "1")
|
||||
monkeypatch.setenv("HERMES_CODEX_TTFB_MAX_SECONDS", "1")
|
||||
|
||||
closes: list = []
|
||||
dummy_client = SimpleNamespace()
|
||||
monkeypatch.setattr(agent, "_create_request_openai_client", lambda **k: dummy_client)
|
||||
monkeypatch.setattr(
|
||||
agent, "_abort_request_openai_client", lambda c, reason=None: closes.append(reason)
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
agent, "_close_request_openai_client", lambda c, reason=None: closes.append(reason)
|
||||
)
|
||||
|
||||
stop = {"flag": False}
|
||||
|
||||
def fake_hang(api_kwargs, client=None, on_first_delta=None):
|
||||
deadline = time.time() + 30
|
||||
while time.time() < deadline and not stop["flag"] and not agent._interrupt_requested:
|
||||
time.sleep(0.02)
|
||||
raise RuntimeError("connection closed")
|
||||
|
||||
monkeypatch.setattr(agent, "_run_codex_stream", fake_hang)
|
||||
|
||||
large_input = "x" * 44_000 # ~11k estimated tokens, above the large-request gate.
|
||||
try:
|
||||
with pytest.raises(TimeoutError) as excinfo:
|
||||
h.interruptible_api_call(agent, {"model": "gpt-5.5", "input": large_input})
|
||||
assert "TTFB threshold: 1s" in str(excinfo.value)
|
||||
assert "codex_ttfb_kill" in closes
|
||||
finally:
|
||||
stop["flag"] = True
|
||||
|
||||
|
||||
def test_large_codex_request_strict_ttfb_env_still_reconnects(tmp_path, monkeypatch):
|
||||
"""Operators can force the old early-reconnect behavior for large inputs
|
||||
with HERMES_CODEX_TTFB_STRICT=1."""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue