From e29bbdb12810cda557b0d9d9e4f08ae7d2eabd0c Mon Sep 17 00:00:00 2001 From: techartdev Date: Fri, 20 Feb 2026 20:36:25 +0200 Subject: [PATCH] voice fixes when conversation is stopped --- CHANGELOG.md | 13 ++++++++++++ custom_components/openclaw/__init__.py | 4 ++-- custom_components/openclaw/config_flow.py | 12 ++++++++++- custom_components/openclaw/manifest.json | 2 +- .../openclaw/www/openclaw-chat-card.js | 21 ++++++++++++++++++- www/openclaw-chat-card.js | 2 +- 6 files changed, 48 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e91cee..66d151c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,19 @@ All notable changes to the OpenClaw Home Assistant Integration will be documented in this file. +## [0.1.28] - 2026-02-20 + +### Fixed +- Treat `SpeechRecognition` `aborted` events as expected stop behavior (no error status/no noisy console error) when voice is intentionally stopped. +- Added a stop-request guard to avoid restart/error churn during recognition shutdown. +- Synchronized release versioning so manifest, frontend loader URL, and backend card resource URL all use the same cache-busting version. + +## [0.1.27] - 2026-02-20 + +### Changed +- Improved backward compatibility for older Home Assistant Core builds by removing Python 3.12-only type alias syntax in integration runtime code. +- Added fallback import handling for `ConfigFlowResult` in config flow type hints. + ## [0.1.26] - 2026-02-20 ### Added diff --git a/custom_components/openclaw/__init__.py b/custom_components/openclaw/__init__.py index b5d360d..a94ed2f 100644 --- a/custom_components/openclaw/__init__.py +++ b/custom_components/openclaw/__init__.py @@ -76,9 +76,9 @@ _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.26" +_CARD_URL = f"{_CARD_STATIC_URL}?v=0.1.28" -type OpenClawConfigEntry = ConfigEntry +OpenClawConfigEntry = ConfigEntry # Service call schemas diff --git a/custom_components/openclaw/config_flow.py b/custom_components/openclaw/config_flow.py index 50463e1..6507048 100644 --- a/custom_components/openclaw/config_flow.py +++ b/custom_components/openclaw/config_flow.py @@ -14,7 +14,17 @@ from typing import Any import voluptuous as vol -from homeassistant.config_entries import ConfigEntry, ConfigFlow, ConfigFlowResult, OptionsFlow +try: + from homeassistant.config_entries import ( + ConfigEntry, + ConfigFlow, + ConfigFlowResult, + OptionsFlow, + ) +except ImportError: + from homeassistant.config_entries import ConfigEntry, ConfigFlow, OptionsFlow + + ConfigFlowResult = dict[str, Any] from homeassistant.core import HomeAssistant from homeassistant.helpers.aiohttp_client import async_get_clientsession diff --git a/custom_components/openclaw/manifest.json b/custom_components/openclaw/manifest.json index cd429af..9cb2e08 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.26", + "version": "0.1.28", "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 440a74d..6eda8cc 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.2.6"; +const CARD_VERSION = "0.2.7"; // Max time (ms) to show the thinking indicator before falling back to an error const THINKING_TIMEOUT_MS = 120_000; @@ -72,6 +72,7 @@ class OpenClawChatCard extends HTMLElement { this._integrationVoiceLanguage = null; this._allowBraveWebSpeechIntegration = false; this._voiceBackendBlocked = false; + this._voiceStopRequested = false; } // ── HA card interface ─────────────────────────────────────────────── @@ -491,6 +492,7 @@ class OpenClawChatCard extends HTMLElement { _startVoiceRecognition() { this._voiceBackendBlocked = false; + this._voiceStopRequested = false; const allowBraveWebSpeech = this._config.allow_brave_webspeech || this._allowBraveWebSpeechIntegration; @@ -556,6 +558,13 @@ class OpenClawChatCard extends HTMLElement { this._recognition.onerror = (event) => { const err = event?.error || "unknown"; + if (err === "aborted") { + if (this._voiceStopRequested) { + return; + } + console.debug("OpenClaw: Speech recognition aborted"); + return; + } if (err === "network") { console.warn("OpenClaw: Speech recognition network error"); } else { @@ -594,6 +603,15 @@ class OpenClawChatCard extends HTMLElement { }; this._recognition.onend = () => { + if (this._voiceStopRequested) { + this._voiceStopRequested = false; + if (!this._isVoiceMode) { + this._voiceStatus = ""; + this._render(); + } + return; + } + if (this._isVoiceMode) { // Restart recognition in voice mode try { @@ -613,6 +631,7 @@ class OpenClawChatCard extends HTMLElement { _stopVoiceRecognition() { if (this._recognition) { + this._voiceStopRequested = true; this._recognition.abort(); this._recognition = null; } diff --git a/www/openclaw-chat-card.js b/www/openclaw-chat-card.js index c44948b..dd67800 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.26"; + const src = "/openclaw/openclaw-chat-card.js?v=0.1.28"; console.info("OpenClaw loader importing", src); await import(src); }