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. 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 ## [0.1.11] - 2026-02-20
### Fixed ### Fixed
+36 -30
View File
@@ -380,8 +380,11 @@ def _get_first_entry_data(hass: HomeAssistant) -> dict[str, Any] | None:
return None return None
def _coerce_text(value: Any) -> str | None: def _extract_text_recursive(value: Any, depth: int = 0) -> str | None:
"""Convert known message content shapes to plain text.""" """Recursively extract assistant text from nested response payloads."""
if depth > 8:
return None
if isinstance(value, str): if isinstance(value, str):
text = value.strip() text = value.strip()
return text or None return text or None
@@ -389,38 +392,41 @@ def _coerce_text(value: Any) -> str | None:
if isinstance(value, list): if isinstance(value, list):
parts: list[str] = [] parts: list[str] = []
for item in value: for item in value:
if isinstance(item, str): extracted = _extract_text_recursive(item, depth + 1)
if item.strip(): if extracted:
parts.append(item.strip()) parts.append(extracted)
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())
if parts: if parts:
return "\n".join(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 return None
def _extract_assistant_message(response: dict[str, Any]) -> str | None: def _extract_assistant_message(response: dict[str, Any]) -> str | None:
"""Extract assistant text from multiple OpenAI-compatible response shapes.""" """Extract assistant text from modern/legacy OpenAI-compatible responses."""
choices = response.get("choices") return _extract_text_recursive(response)
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
+48 -4
View File
@@ -174,10 +174,54 @@ class OpenClawConversationAgent(conversation.AbstractConversationAgent):
message=message, message=message,
session_id=conversation_id, session_id=conversation_id,
) )
choices = response.get("choices", []) extracted = self._extract_text_recursive(response)
if choices: return extracted or ""
return choices[0].get("message", {}).get("content", "")
return "" 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( def _error_result(
self, self,
+1 -1
View File
@@ -8,7 +8,7 @@
"iot_class": "local_polling", "iot_class": "local_polling",
"issue_tracker": "https://github.com/techartdev/OpenClawHomeAssistant/issues", "issue_tracker": "https://github.com/techartdev/OpenClawHomeAssistant/issues",
"requirements": [], "requirements": [],
"version": "0.1.11", "version": "0.1.12",
"dependencies": ["conversation"], "dependencies": ["conversation"],
"after_dependencies": ["hassio", "lovelace"] "after_dependencies": ["hassio", "lovelace"]
} }