Update changelog for version 0.1.17, improve chat history recovery, implement retry logic for backend history sync, and enhance message merging logic.

This commit is contained in:
techartdev
2026-02-20 17:31:58 +02:00
parent 0445c595ef
commit 9a22cea159
4 changed files with 58 additions and 5 deletions
+7
View File
@@ -2,6 +2,13 @@
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.17] - 2026-02-20
### Fixed
- Improved chat history recovery after leaving and returning to dashboard.
- Card now retries backend history sync when websocket is not yet ready.
- History merge now updates when message count is unchanged but latest message content/timestamp differs.
## [0.1.16] - 2026-02-20 ## [0.1.16] - 2026-02-20
### Added ### Added
+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.16", "version": "0.1.17",
"dependencies": ["conversation"], "dependencies": ["conversation"],
"after_dependencies": ["hassio", "lovelace"] "after_dependencies": ["hassio", "lovelace"]
} }
@@ -59,6 +59,7 @@ class OpenClawChatCard extends HTMLElement {
this._recognition = null; this._recognition = null;
this._eventUnsubscribe = null; this._eventUnsubscribe = null;
this._thinkingTimer = null; this._thinkingTimer = null;
this._historySyncRetryTimer = null;
this._wakeWordEnabled = false; this._wakeWordEnabled = false;
this._wakeWord = "hey openclaw"; this._wakeWord = "hey openclaw";
this._alwaysVoiceMode = false; this._alwaysVoiceMode = false;
@@ -114,6 +115,10 @@ class OpenClawChatCard extends HTMLElement {
this._unsubscribeEvents(); this._unsubscribeEvents();
this._stopVoiceRecognition(); this._stopVoiceRecognition();
this._clearThinkingTimer(); this._clearThinkingTimer();
if (this._historySyncRetryTimer) {
clearTimeout(this._historySyncRetryTimer);
this._historySyncRetryTimer = null;
}
} }
// ── Event subscription ────────────────────────────────────────────── // ── Event subscription ──────────────────────────────────────────────
@@ -217,7 +222,7 @@ class OpenClawChatCard extends HTMLElement {
} }
} }
async _syncHistoryFromBackend() { async _syncHistoryFromBackend(retries = 6) {
if (!this._hass) return; if (!this._hass) return;
const sessionId = this._getSessionId(); const sessionId = this._getSessionId();
@@ -244,7 +249,17 @@ class OpenClawChatCard extends HTMLElement {
); );
if (!validMessages.length) return; if (!validMessages.length) return;
if (validMessages.length > this._messages.length) { const shouldReplace =
validMessages.length > this._messages.length ||
(validMessages.length === this._messages.length &&
validMessages.length > 0 &&
this._messages.length > 0 &&
(validMessages[validMessages.length - 1].content !==
this._messages[this._messages.length - 1].content ||
validMessages[validMessages.length - 1].timestamp !==
this._messages[this._messages.length - 1].timestamp));
if (shouldReplace) {
this._messages = validMessages; this._messages = validMessages;
this._isProcessing = false; this._isProcessing = false;
this._clearThinkingTimer(); this._clearThinkingTimer();
@@ -254,6 +269,14 @@ class OpenClawChatCard extends HTMLElement {
} }
} catch (err) { } catch (err) {
console.debug("OpenClaw: history sync skipped:", err); console.debug("OpenClaw: history sync skipped:", err);
if (retries > 0) {
if (this._historySyncRetryTimer) {
clearTimeout(this._historySyncRetryTimer);
}
this._historySyncRetryTimer = setTimeout(() => {
this._syncHistoryFromBackend(retries - 1);
}, 1500);
}
} }
} }
+25 -2
View File
@@ -59,6 +59,7 @@ class OpenClawChatCard extends HTMLElement {
this._recognition = null; this._recognition = null;
this._eventUnsubscribe = null; this._eventUnsubscribe = null;
this._thinkingTimer = null; this._thinkingTimer = null;
this._historySyncRetryTimer = null;
this._wakeWordEnabled = false; this._wakeWordEnabled = false;
this._wakeWord = "hey openclaw"; this._wakeWord = "hey openclaw";
this._alwaysVoiceMode = false; this._alwaysVoiceMode = false;
@@ -114,6 +115,10 @@ class OpenClawChatCard extends HTMLElement {
this._unsubscribeEvents(); this._unsubscribeEvents();
this._stopVoiceRecognition(); this._stopVoiceRecognition();
this._clearThinkingTimer(); this._clearThinkingTimer();
if (this._historySyncRetryTimer) {
clearTimeout(this._historySyncRetryTimer);
this._historySyncRetryTimer = null;
}
} }
// ── Event subscription ────────────────────────────────────────────── // ── Event subscription ──────────────────────────────────────────────
@@ -217,7 +222,7 @@ class OpenClawChatCard extends HTMLElement {
} }
} }
async _syncHistoryFromBackend() { async _syncHistoryFromBackend(retries = 6) {
if (!this._hass) return; if (!this._hass) return;
const sessionId = this._getSessionId(); const sessionId = this._getSessionId();
@@ -244,7 +249,17 @@ class OpenClawChatCard extends HTMLElement {
); );
if (!validMessages.length) return; if (!validMessages.length) return;
if (validMessages.length > this._messages.length) { const shouldReplace =
validMessages.length > this._messages.length ||
(validMessages.length === this._messages.length &&
validMessages.length > 0 &&
this._messages.length > 0 &&
(validMessages[validMessages.length - 1].content !==
this._messages[this._messages.length - 1].content ||
validMessages[validMessages.length - 1].timestamp !==
this._messages[this._messages.length - 1].timestamp));
if (shouldReplace) {
this._messages = validMessages; this._messages = validMessages;
this._isProcessing = false; this._isProcessing = false;
this._clearThinkingTimer(); this._clearThinkingTimer();
@@ -254,6 +269,14 @@ class OpenClawChatCard extends HTMLElement {
} }
} catch (err) { } catch (err) {
console.debug("OpenClaw: history sync skipped:", err); console.debug("OpenClaw: history sync skipped:", err);
if (retries > 0) {
if (this._historySyncRetryTimer) {
clearTimeout(this._historySyncRetryTimer);
}
this._historySyncRetryTimer = setTimeout(() => {
this._syncHistoryFromBackend(retries - 1);
}, 1500);
}
} }
} }