Update changelog for version 0.1.12, improve response parsing for nested OpenAI-compatible payloads, and enhance assistant message extraction in conversation agent.

This commit is contained in:
techartdev
2026-02-20 16:43:48 +02:00
parent e6fb9e2914
commit 2331ec0d8d
4 changed files with 91 additions and 35 deletions
+6
View File
@@ -2,6 +2,12 @@
All notable changes to the OpenClaw Home Assistant Integration will be documented in this file.
## [0.1.12] - 2026-02-20
### Fixed
- Improved response parsing for nested/modern OpenAI-compatible payloads (including `output` / nested `content` shapes), which could previously result in missing UI replies.
- Applied the same recursive extraction strategy to both service-based chat responses and Assist conversation fallback parsing.
## [0.1.11] - 2026-02-20
### Fixed
+36 -30
View File
@@ -380,8 +380,11 @@ def _get_first_entry_data(hass: HomeAssistant) -> dict[str, Any] | None:
return None
def _coerce_text(value: Any) -> str | None:
"""Convert known message content shapes to plain text."""
def _extract_text_recursive(value: Any, depth: int = 0) -> str | None:
"""Recursively extract assistant text from nested response payloads."""
if depth > 8:
return None
if isinstance(value, str):
text = value.strip()
return text or None
@@ -389,38 +392,41 @@ def _coerce_text(value: Any) -> str | None:
if isinstance(value, list):
parts: list[str] = []
for item in value:
if isinstance(item, str):
if item.strip():
parts.append(item.strip())
continue
if isinstance(item, dict):
text_part = item.get("text") or item.get("content")
if isinstance(text_part, str) and text_part.strip():
parts.append(text_part.strip())
extracted = _extract_text_recursive(item, depth + 1)
if extracted:
parts.append(extracted)
if parts:
return "\n".join(parts)
return None
if isinstance(value, dict):
priority_keys = (
"output_text",
"text",
"content",
"message",
"response",
"answer",
"choices",
"output",
"delta",
)
for key in priority_keys:
if key not in value:
continue
extracted = _extract_text_recursive(value.get(key), depth + 1)
if extracted:
return extracted
for nested_value in value.values():
extracted = _extract_text_recursive(nested_value, depth + 1)
if extracted:
return extracted
return None
def _extract_assistant_message(response: dict[str, Any]) -> str | None:
"""Extract assistant text from multiple OpenAI-compatible response shapes."""
choices = response.get("choices")
if isinstance(choices, list) and choices:
first = choices[0]
if isinstance(first, dict):
message = first.get("message")
if isinstance(message, dict):
extracted = _coerce_text(message.get("content"))
if extracted:
return extracted
extracted = _coerce_text(first.get("text"))
if extracted:
return extracted
for key in ("output_text", "response", "message", "content", "answer"):
extracted = _coerce_text(response.get(key))
if extracted:
return extracted
return None
"""Extract assistant text from modern/legacy OpenAI-compatible responses."""
return _extract_text_recursive(response)
+48 -4
View File
@@ -174,10 +174,54 @@ class OpenClawConversationAgent(conversation.AbstractConversationAgent):
message=message,
session_id=conversation_id,
)
choices = response.get("choices", [])
if choices:
return choices[0].get("message", {}).get("content", "")
return ""
extracted = self._extract_text_recursive(response)
return extracted or ""
def _extract_text_recursive(self, value: Any, depth: int = 0) -> str | None:
"""Recursively extract assistant text from nested response payloads."""
if depth > 8:
return None
if isinstance(value, str):
text = value.strip()
return text or None
if isinstance(value, list):
parts: list[str] = []
for item in value:
extracted = self._extract_text_recursive(item, depth + 1)
if extracted:
parts.append(extracted)
if parts:
return "\n".join(parts)
return None
if isinstance(value, dict):
priority_keys = (
"output_text",
"text",
"content",
"message",
"response",
"answer",
"choices",
"output",
"delta",
)
for key in priority_keys:
if key not in value:
continue
extracted = self._extract_text_recursive(value.get(key), depth + 1)
if extracted:
return extracted
for nested_value in value.values():
extracted = self._extract_text_recursive(nested_value, depth + 1)
if extracted:
return extracted
return None
def _error_result(
self,
+1 -1
View File
@@ -8,7 +8,7 @@
"iot_class": "local_polling",
"issue_tracker": "https://github.com/techartdev/OpenClawHomeAssistant/issues",
"requirements": [],
"version": "0.1.11",
"version": "0.1.12",
"dependencies": ["conversation"],
"after_dependencies": ["hassio", "lovelace"]
}