From bfd973bbff498a8003a5457496680fbc866b43a2 Mon Sep 17 00:00:00 2001 From: techartdev Date: Fri, 20 Feb 2026 22:18:05 +0200 Subject: [PATCH] Update version to 0.1.36 and enhance changelog with fixes for voice mode and message deduplication --- CHANGELOG.md | 6 +++++ custom_components/openclaw/__init__.py | 2 +- custom_components/openclaw/manifest.json | 2 +- .../openclaw/www/openclaw-chat-card.js | 22 ++++++++++++------- www/openclaw-chat-card.js | 2 +- 5 files changed, 23 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fbf864a..dbc669b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to the OpenClaw Home Assistant Integration will be documented in this file. +## [0.1.36] - 2026-02-20 + +### Fixed +- Voice mode now auto-falls back to browser speech when `voice_provider` is `assist_stt`, instead of blocking continuous mode with an error message. +- Reduced duplicated assistant replies in the chat card by deduplicating repeated `openclaw_message_received` payloads. + ## [0.1.35] - 2026-02-20 ### Fixed diff --git a/custom_components/openclaw/__init__.py b/custom_components/openclaw/__init__.py index a139464..9adefcc 100644 --- a/custom_components/openclaw/__init__.py +++ b/custom_components/openclaw/__init__.py @@ -78,7 +78,7 @@ _CARD_PATH = Path(__file__).parent / "www" / _CARD_FILENAME # URL at which the card JS is served (registered via register_static_path) _CARD_STATIC_URL = f"/openclaw/{_CARD_FILENAME}" # Versioned URL used for Lovelace resource registration to avoid stale browser cache -_CARD_URL = f"{_CARD_STATIC_URL}?v=0.1.35" +_CARD_URL = f"{_CARD_STATIC_URL}?v=0.1.36" OpenClawConfigEntry = ConfigEntry diff --git a/custom_components/openclaw/manifest.json b/custom_components/openclaw/manifest.json index 0b62234..470305b 100644 --- a/custom_components/openclaw/manifest.json +++ b/custom_components/openclaw/manifest.json @@ -8,7 +8,7 @@ "iot_class": "local_polling", "issue_tracker": "https://github.com/techartdev/OpenClawHomeAssistant/issues", "requirements": [], - "version": "0.1.35", + "version": "0.1.36", "dependencies": ["conversation"], "after_dependencies": ["hassio", "lovelace"] } diff --git a/custom_components/openclaw/www/openclaw-chat-card.js b/custom_components/openclaw/www/openclaw-chat-card.js index 48060b0..0d76cab 100644 --- a/custom_components/openclaw/www/openclaw-chat-card.js +++ b/custom_components/openclaw/www/openclaw-chat-card.js @@ -13,7 +13,7 @@ * + subscribes to openclaw_message_received events. */ -const CARD_VERSION = "0.3.3"; +const CARD_VERSION = "0.3.4"; // Max time (ms) to show the thinking indicator before falling back to an error const THINKING_TIMEOUT_MS = 120_000; @@ -86,6 +86,7 @@ class OpenClawChatCard extends HTMLElement { this._assistAudioChunks = []; this._assistInputSampleRate = 16000; this._assistAutoStopTimer = null; + this._lastAssistantEventSignature = null; } // ── HA card interface ─────────────────────────────────────────────── @@ -181,6 +182,12 @@ class OpenClawChatCard extends HTMLElement { const sessionId = this._getSessionId(); if (data.session_id && data.session_id !== sessionId) return; + const signature = `${sessionId}|${data.timestamp || ""}|${String(data.message)}`; + if (signature === this._lastAssistantEventSignature) { + return; + } + this._lastAssistantEventSignature = signature; + const thinkingIdx = this._messages.findIndex((m) => m._thinking); if (thinkingIdx >= 0) { this._messages[thinkingIdx] = { @@ -569,6 +576,12 @@ class OpenClawChatCard extends HTMLElement { _startVoiceRecognition() { const provider = this._getVoiceProvider(); + if (this._isVoiceMode && provider === "assist_stt") { + this._voiceStatus = + "Voice mode uses browser speech for continuous listening (Assist STT remains available for manual mic)."; + this._startBrowserVoiceRecognition(); + return; + } if (provider === "assist_stt") { this._startAssistSttRecognition(); return; @@ -1150,13 +1163,6 @@ class OpenClawChatCard extends HTMLElement { } _toggleVoiceMode() { - if (!this._isVoiceMode && this._getVoiceProvider() === "assist_stt") { - this._voiceStatus = - "Continuous voice mode is only available with browser voice provider."; - this._render(); - return; - } - this._isVoiceMode = !this._isVoiceMode; if (this._isVoiceMode) { this._startVoiceRecognition(); diff --git a/www/openclaw-chat-card.js b/www/openclaw-chat-card.js index caa3545..c219949 100644 --- a/www/openclaw-chat-card.js +++ b/www/openclaw-chat-card.js @@ -1,7 +1,7 @@ (async () => { try { if (!customElements.get("openclaw-chat-card")) { - const src = "/openclaw/openclaw-chat-card.js?v=0.1.35"; + const src = "/openclaw/openclaw-chat-card.js?v=0.1.36"; console.info("OpenClaw loader importing", src); await import(src); }