mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-13 03:52:00 +00:00
fix(auxiliary): enforce Codex Responses stream timeout
## Summary - Forwards chat-completions `timeout` into the Codex Responses stream call. - Adds total elapsed-time enforcement while the Responses stream is still yielding events. - Closes the underlying client on timeout to unblock stalled streams, then raises `TimeoutError`. - Adds focused tests for timeout forwarding and total timeout enforcement. ## Why The Codex auxiliary adapter can be used by non-interactive auxiliary work such as context compression. If the stream keeps yielding progress-like events but never completes, SDK socket/read timeouts do not necessarily protect the full operation. This makes the CLI look stuck until the user force-interrupts the whole session. This is a refreshed upstream-ready version of the earlier fork fix around `d3f08e9a0` / PR #3. ## Verification - `python -m py_compile agent/auxiliary_client.py tests/agent/test_auxiliary_client.py` - `python -m pytest -o addopts='' tests/agent/test_auxiliary_client.py::TestCodexAuxiliaryAdapterTimeout -q` - `git diff --check`
This commit is contained in:
parent
fd13b7d2b9
commit
5533ad7644
2 changed files with 133 additions and 0 deletions
|
|
@ -3,7 +3,9 @@
|
|||
import json
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import patch, MagicMock, AsyncMock
|
||||
|
||||
import pytest
|
||||
|
|
@ -24,6 +26,7 @@ from agent.auxiliary_client import (
|
|||
_normalize_aux_provider,
|
||||
_try_payment_fallback,
|
||||
_resolve_auto,
|
||||
_CodexCompletionsAdapter,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -1894,6 +1897,85 @@ class TestVisionAutoSkipsKimiCoding:
|
|||
})
|
||||
|
||||
|
||||
class TestCodexAuxiliaryAdapterTimeout:
|
||||
def test_forwards_timeout_to_responses_stream(self):
|
||||
class FakeStream:
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc, tb):
|
||||
return False
|
||||
|
||||
def __iter__(self):
|
||||
return iter(())
|
||||
|
||||
def get_final_response(self):
|
||||
return SimpleNamespace(
|
||||
output=[SimpleNamespace(
|
||||
type="message",
|
||||
content=[SimpleNamespace(type="output_text", text="summary")],
|
||||
)],
|
||||
usage=None,
|
||||
)
|
||||
|
||||
class FakeResponses:
|
||||
def __init__(self):
|
||||
self.kwargs = None
|
||||
|
||||
def stream(self, **kwargs):
|
||||
self.kwargs = kwargs
|
||||
return FakeStream()
|
||||
|
||||
fake_client = SimpleNamespace(responses=FakeResponses())
|
||||
adapter = _CodexCompletionsAdapter(fake_client, "gpt-5.5")
|
||||
|
||||
response = adapter.create(
|
||||
messages=[{"role": "user", "content": "summarize this"}],
|
||||
timeout=12.5,
|
||||
)
|
||||
|
||||
assert fake_client.responses.kwargs["timeout"] == 12.5
|
||||
assert response.choices[0].message.content == "summary"
|
||||
|
||||
def test_enforces_total_timeout_while_stream_keeps_emitting_events(self):
|
||||
class SlowAliveStream:
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc, tb):
|
||||
return False
|
||||
|
||||
def __iter__(self):
|
||||
for _ in range(5):
|
||||
time.sleep(0.03)
|
||||
yield SimpleNamespace(type="response.in_progress")
|
||||
|
||||
def get_final_response(self):
|
||||
return SimpleNamespace(
|
||||
output=[SimpleNamespace(
|
||||
type="message",
|
||||
content=[SimpleNamespace(type="output_text", text="late")],
|
||||
)],
|
||||
usage=None,
|
||||
)
|
||||
|
||||
class FakeResponses:
|
||||
def stream(self, **kwargs):
|
||||
return SlowAliveStream()
|
||||
|
||||
fake_client = SimpleNamespace(responses=FakeResponses(), close=lambda: None)
|
||||
adapter = _CodexCompletionsAdapter(fake_client, "gpt-5.5")
|
||||
|
||||
started = time.monotonic()
|
||||
with pytest.raises(TimeoutError):
|
||||
adapter.create(
|
||||
messages=[{"role": "user", "content": "summarize this"}],
|
||||
timeout=0.05,
|
||||
)
|
||||
|
||||
assert time.monotonic() - started < 0.14
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# _build_call_kwargs — tool dedup at API boundary
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue