refactor(agent): name the Codex first-progress budget; reuse the watchdog test helper

`HIGH_EFFORT_SILENCE_FLOOR_SECONDS` is documented as the reasoning-effort
>= high floor and gated on effort by `_high_effort_silence_floor()`, yet
the first-progress budget applied it to every large official-Codex
request regardless of effort. Someone tuning the high-effort floor would
silently retune the first-progress fuse. `CODEX_FIRST_PROGRESS_TIMEOUT_SECONDS`
carries the same 300s, so no behaviour changes; it just gets its own knob
and rationale.

The new lifecycle-only test re-implemented `_shorten_implicit_idle_watchdog`
inline. The helper now accepts field overrides, and the test also inherits
its env cleanup so a polluted runner env cannot push the resolver off the
implicit branch.
This commit is contained in:
kshitijk4poor
2026-09-24 15:18:53 +05:30
committed by kshitij
parent 8b9de5592d
commit 67e0912369
2 changed files with 15 additions and 12 deletions

View File

@@ -1098,6 +1098,13 @@ class _RequestClientRegistry:
# timeout's run-budget cap is applied AFTER this floor (AIAgent._compute_non_stream_stale_timeout).
HIGH_EFFORT_SILENCE_FLOOR_SECONDS = 300.0
# First-progress budget for a lifecycle-only stream on an official-Codex large request: the
# stream opened but no substantive model event has arrived. Measured from the physical-attempt
# start (a reconnect restarts it; lifecycle frames do not), and applied regardless of reasoning
# effort. Equal to the high-effort floor today, but a separate knob so tuning one cannot silently
# retune the other.
CODEX_FIRST_PROGRESS_TIMEOUT_SECONDS = 300.0
def _high_effort_silence_floor(agent) -> float:
"""``HIGH_EFFORT_SILENCE_FLOOR_SECONDS`` when the wire reasoning config is enabled at ``high`` or any
@@ -1216,7 +1223,7 @@ def _resolve_nonstream_watchdogs(agent, api_kwargs: dict) -> _NonStreamWatchdogs
idle_timeout=idle_timeout, idle_requires_progress=progress_gated,
# A lifecycle frame proves transport liveness, not model progress. Bound that phase
# from the physical-attempt start; events cannot restart the grace period.
progress_timeout=HIGH_EFFORT_SILENCE_FLOOR_SECONDS if progress_gated else 0.0)
progress_timeout=CODEX_FIRST_PROGRESS_TIMEOUT_SECONDS if progress_gated else 0.0)
def _codex_silent_hang_hint(agent, api_kwargs: dict) -> Optional[str]:

View File

@@ -71,14 +71,18 @@ def _make_codex_agent(
return agent
def _shorten_implicit_idle_watchdog(monkeypatch, helpers, timeout=2.0):
"""Keep the resolver on its implicit branch while scaling time for tests."""
def _shorten_implicit_idle_watchdog(monkeypatch, helpers, timeout=2.0, **overrides):
"""Keep the resolver on its implicit branch while scaling time for tests.
``timeout`` shortens ``idle_timeout``; ``overrides`` set any other resolved field."""
monkeypatch.delenv("HERMES_CODEX_EVENT_STALE_TIMEOUT_SECONDS", raising=False)
original = helpers._resolve_nonstream_watchdogs
def resolve(agent, api_kwargs):
watchdogs = original(agent, api_kwargs)
watchdogs.idle_timeout = timeout
for field, value in overrides.items():
setattr(watchdogs, field, value)
return watchdogs
monkeypatch.setattr(helpers, "_resolve_nonstream_watchdogs", resolve)
@@ -343,15 +347,7 @@ def test_large_codex_lifecycle_only_stream_hits_attempt_progress_budget(tmp_path
from agent import chat_completion_helpers as h
agent = _make_codex_agent(tmp_path, monkeypatch)
original = h._resolve_nonstream_watchdogs
def resolve(agent, kwargs):
wd = original(agent, kwargs)
wd.ttfb_timeout = 0.9
wd.progress_timeout = 0.9
return wd
monkeypatch.setattr(h, "_resolve_nonstream_watchdogs", resolve)
_shorten_implicit_idle_watchdog(monkeypatch, h, ttfb_timeout=0.9, progress_timeout=0.9)
closes = []
def stream_attempt():