From e29e66dbc7bf0093a4ab93c6a964594aac39b78b Mon Sep 17 00:00:00 2001 From: worldmozara Date: Sat, 1 Aug 2026 01:05:09 +0800 Subject: [PATCH] core/agent: surface openai responses stream error events --- src/plyngent/agent/responses_dispatch.py | 6 ++++++ src/plyngent/lmproto/openai/model.py | 3 +++ tests/test_agent/test_responses_dispatch.py | 14 ++++++++++++++ 3 files changed, 23 insertions(+) diff --git a/src/plyngent/agent/responses_dispatch.py b/src/plyngent/agent/responses_dispatch.py index f4db34b..32f66ff 100644 --- a/src/plyngent/agent/responses_dispatch.py +++ b/src/plyngent/agent/responses_dispatch.py @@ -62,6 +62,12 @@ async def _stream_as_chat_chunks( final: ResponseModel | None = None async for event in stream: etype = event.type + if etype == "error": + code = event.code if event.code is not UNSET else "" + message = event.message if event.message is not UNSET else "" + detail = message.strip() or code + label = detail.strip() or etype + raise RuntimeError(f"openai responses stream error: {label}") # noqa: TRY003 — transport failure if etype == "response.output_text.delta" and isinstance(event.delta, str) and event.delta: yield text_delta_chunk(model=model, content=event.delta) continue diff --git a/src/plyngent/lmproto/openai/model.py b/src/plyngent/lmproto/openai/model.py index 661c47f..7cb464b 100644 --- a/src/plyngent/lmproto/openai/model.py +++ b/src/plyngent/lmproto/openai/model.py @@ -282,6 +282,9 @@ class ResponseStreamEvent(Struct, omit_defaults=True): name: str | Unset = UNSET arguments: str | Unset = UNSET call_id: str | Unset = UNSET + # error events (type == "error") + code: str | Unset = UNSET + message: str | Unset = UNSET # --- Helpers ----------------------------------------------------------------------- diff --git a/tests/test_agent/test_responses_dispatch.py b/tests/test_agent/test_responses_dispatch.py index 01f7338..65edfae 100644 --- a/tests/test_agent/test_responses_dispatch.py +++ b/tests/test_agent/test_responses_dispatch.py @@ -314,3 +314,17 @@ async def test_unknown_kind_not_implemented() -> None: stream=False, ): pass + + +async def test_dispatch_stream_raises_on_error_event() -> None: + import pytest + + events = [ + ResponseStreamEvent(type="error", code="server_error", message="boom"), + ] + client = ScriptedResponsesClient(stream_events=[events]) + param = ChatCompletionsParam(model="gpt-test", messages=[UserChatMessage(content="x")]) + stream = await dispatch_responses(cast("Any", client), param, stream=True) + with pytest.raises(RuntimeError, match="boom"): + async for _ in cast("Any", stream): + pass