Skip to content

Commit be06fdd

Browse files
author
SMKRV
committed
fix: Display only last Q&A in sensor state to prevent data truncation
- Show only the latest question and answer in sensor state - Keep full conversation history in attributes - Fix truncation issues in Home Assistant UI - Maintain backwards compatibility - No configuration changes required
1 parent 5f0bd86 commit be06fdd

File tree

2 files changed

+47
-24
lines changed

2 files changed

+47
-24
lines changed

custom_components/ha_text_ai/const.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@
5656
DEFAULT_NAME_PREFIX = "ha_text_ai"
5757
DEFAULT_CONTEXT_MESSAGES: Final = 5
5858

59+
TRUNCATION_INDICATOR = " … "
60+
5961
# Parameter constraints
6062
MIN_TEMPERATURE: Final = 0.0
6163
MAX_TEMPERATURE: Final = 2.0

custom_components/ha_text_ai/coordinator.py

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
ABSOLUTE_MAX_HISTORY_SIZE,
4242
MAX_ATTRIBUTE_SIZE,
4343
MAX_HISTORY_FILE_SIZE,
44+
TRUNCATION_INDICATOR,
4445
)
4546

4647
_LOGGER = logging.getLogger(__name__)
@@ -647,15 +648,14 @@ async def _rotate_history_files(self) -> None:
647648

648649
async def _async_update_data(self) -> Dict[str, Any]:
649650
"""Update coordinator data with improved error handling and performance."""
650-
651651
try:
652652
async with asyncio.Semaphore(1):
653653
current_state = self._get_current_state()
654654

655-
limited_history = await self._get_limited_history()
655+
# Get limited history with info
656+
history_data = await self._get_limited_history()
656657

657658
metrics = await self._get_current_metrics()
658-
659659
if metrics is None:
660660
metrics = {}
661661

@@ -670,47 +670,68 @@ async def _async_update_data(self) -> Dict[str, Any]:
670670
"uptime": self._calculate_uptime(),
671671
"system_prompt": self._get_truncated_system_prompt(),
672672
"history_size": len(self._conversation_history),
673-
"conversation_history": limited_history,
673+
"conversation_history": history_data["entries"],
674+
"history_info": history_data["info"],
674675
"normalized_name": self.normalized_name,
675676
}
676677

677678
await self._validate_update_data(data)
678-
679679
return data
680680

681-
except asyncio.CancelledError:
682-
_LOGGER.warning("Update was cancelled")
683-
raise
684681
except Exception as err:
685682
_LOGGER.error(f"Error updating data: {err}", exc_info=True)
686683
return self._get_safe_initial_state()
687684

688-
async def _get_limited_history(self) -> List[Dict[str, Any]]:
689-
"""Get limited conversation history with size constraints."""
685+
async def _get_limited_history(self) -> Dict[str, Any]:
686+
"""Get limited conversation history showing only last Q&A."""
690687
limited_history = []
688+
691689
if self._conversation_history:
692-
for entry in self._conversation_history[-3:]:
693-
limited_entry = {
694-
"timestamp": entry["timestamp"],
695-
"question": self._truncate_text(entry["question"]),
696-
"response": self._truncate_text(entry["response"]),
697-
}
698-
limited_history.append(limited_entry)
699-
return limited_history
690+
last_entry = self._conversation_history[-1]
691+
limited_entry = {
692+
"timestamp": last_entry["timestamp"],
693+
"question": last_entry["question"][:4096] + (TRUNCATION_INDICATOR if len(last_entry["question"]) > 4096 else ""),
694+
"response": last_entry["response"][:4096] + (TRUNCATION_INDICATOR if len(last_entry["response"]) > 4096 else ""),
695+
}
696+
limited_history.append(limited_entry)
700697

701-
def _truncate_text(self, text: str, max_length: int = MAX_ATTRIBUTE_SIZE) -> str:
702-
"""Safely truncate text to maximum length."""
703-
return text[:max_length] if text else ""
698+
history_info = {
699+
"total_entries": len(self._conversation_history),
700+
"displayed_entries": len(limited_history),
701+
"full_history_available": True,
702+
"history_path": self._history_file,
703+
}
704+
705+
return {
706+
"entries": limited_history,
707+
"full_history": self._conversation_history,
708+
"info": history_info
709+
}
704710

705711
async def _get_sanitized_last_response(self) -> Dict[str, Any]:
706-
"""Get sanitized version of last response."""
712+
"""Get sanitized version of last response with truncation indicators."""
707713
response = self.last_response.copy()
714+
708715
if "response" in response:
709-
response["response"] = self._truncate_text(response["response"])
716+
original_response = response["response"]
717+
is_response_truncated = len(original_response) > 4096
718+
response["response"] = original_response[:4096] + (TRUNCATION_INDICATOR if is_response_truncated else "")
719+
response["is_response_truncated"] = is_response_truncated
720+
response["full_response_length"] = len(original_response)
721+
710722
if "question" in response:
711-
response["question"] = self._truncate_text(response["question"])
723+
original_question = response["question"]
724+
is_question_truncated = len(original_question) > 4096
725+
response["question"] = original_question[:4096] + (TRUNCATION_INDICATOR if is_question_truncated else "")
726+
response["is_question_truncated"] = is_question_truncated
727+
response["full_question_length"] = len(original_question)
728+
712729
return response
713730

731+
def _truncate_text(self, text: str, max_length: int = MAX_ATTRIBUTE_SIZE) -> str:
732+
"""Safely truncate text to maximum length."""
733+
return text[:max_length] if text else ""
734+
714735
def _calculate_uptime(self) -> float:
715736
"""Calculate current uptime in seconds."""
716737
return (dt_util.utcnow() - self._start_time).total_seconds()

0 commit comments

Comments
 (0)