Skip to content

Commit b20a31e

Browse files
committed
fix(open_responses): preserve spec stream details
1 parent 732f029 commit b20a31e

2 files changed

Lines changed: 40 additions & 6 deletions

File tree

homeassistant/components/open_responses/entity.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ async def _transform_stream(
256256
"native": {
257257
"type": "reasoning",
258258
"id": item.get("id"),
259-
"summary": [],
259+
"summary": item.get("summary") or [],
260260
"encrypted_content": item.get("encrypted_content"),
261261
}
262262
}
@@ -324,9 +324,9 @@ async def _transform_stream(
324324
reason = error.get("message") or reason
325325
raise HomeAssistantError(f"Open Responses response failed: {reason}")
326326
elif event_type == "response.error":
327-
raise HomeAssistantError(
328-
f"Open Responses response error: {event['message']}"
329-
)
327+
error = cast(dict[str, Any], event.get("error") or {})
328+
reason = error.get("message") or event.get("message") or "unknown reason"
329+
raise HomeAssistantError(f"Open Responses response error: {reason}")
330330

331331

332332
class OpenResponsesEntity(Entity):

tests/components/open_responses/test_entity.py

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from pathlib import Path
55
from unittest.mock import Mock
66

7+
import pytest
78
import voluptuous as vol
89

910
from homeassistant.components import conversation
@@ -14,6 +15,7 @@
1415
_transform_stream,
1516
)
1617
from homeassistant.core import HomeAssistant
18+
from homeassistant.exceptions import HomeAssistantError
1719
from homeassistant.helpers import llm
1820

1921

@@ -344,7 +346,11 @@ async def stream() -> AsyncGenerator[dict]:
344346

345347
async def test_transform_stream_starts_new_message_for_reasoning_item() -> None:
346348
"""Test each reasoning item starts a separate assistant message."""
347-
first_reasoning = {"id": "reasoning_1", "summary": [], "type": "reasoning"}
349+
first_reasoning = {
350+
"id": "reasoning_1",
351+
"summary": [{"type": "summary_text", "text": "Checked the state."}],
352+
"type": "reasoning",
353+
}
348354
second_reasoning = {"id": "reasoning_2", "summary": [], "type": "reasoning"}
349355

350356
async def stream() -> AsyncGenerator[dict]:
@@ -387,7 +393,7 @@ async def stream() -> AsyncGenerator[dict]:
387393
"native": {
388394
"encrypted_content": None,
389395
"id": "reasoning_1",
390-
"summary": [],
396+
"summary": [{"type": "summary_text", "text": "Checked the state."}],
391397
"type": "reasoning",
392398
}
393399
},
@@ -401,3 +407,31 @@ async def stream() -> AsyncGenerator[dict]:
401407
}
402408
},
403409
]
410+
411+
412+
async def test_transform_stream_handles_spec_error_envelope() -> None:
413+
"""Test streaming error events use the Open Responses error envelope."""
414+
415+
async def stream() -> AsyncGenerator[dict]:
416+
yield {
417+
"error": {
418+
"code": "invalid_request",
419+
"message": "Invalid tool result.",
420+
"param": "input",
421+
"type": "invalid_request_error",
422+
},
423+
"sequence_number": 0,
424+
"type": "response.error",
425+
}
426+
427+
with pytest.raises(
428+
HomeAssistantError,
429+
match="Open Responses response error: Invalid tool result.",
430+
):
431+
[
432+
delta
433+
async for delta in _transform_stream(
434+
Mock(),
435+
stream(),
436+
)
437+
]

0 commit comments

Comments
 (0)