voice fixes when conversation is stopped
This commit is contained in:
@@ -2,6 +2,19 @@
|
|||||||
|
|
||||||
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.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
|
## [0.1.26] - 2026-02-20
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -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)
|
# URL at which the card JS is served (registered via register_static_path)
|
||||||
_CARD_STATIC_URL = f"/openclaw/{_CARD_FILENAME}"
|
_CARD_STATIC_URL = f"/openclaw/{_CARD_FILENAME}"
|
||||||
# Versioned URL used for Lovelace resource registration to avoid stale browser cache
|
# 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
|
# Service call schemas
|
||||||
|
|||||||
@@ -14,7 +14,17 @@ from typing import Any
|
|||||||
|
|
||||||
import voluptuous as vol
|
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.core import HomeAssistant
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
|
|
||||||
|
|||||||
@@ -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.26",
|
"version": "0.1.28",
|
||||||
"dependencies": ["conversation"],
|
"dependencies": ["conversation"],
|
||||||
"after_dependencies": ["hassio", "lovelace"]
|
"after_dependencies": ["hassio", "lovelace"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
* + subscribes to openclaw_message_received events.
|
* + 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
|
// Max time (ms) to show the thinking indicator before falling back to an error
|
||||||
const THINKING_TIMEOUT_MS = 120_000;
|
const THINKING_TIMEOUT_MS = 120_000;
|
||||||
@@ -72,6 +72,7 @@ class OpenClawChatCard extends HTMLElement {
|
|||||||
this._integrationVoiceLanguage = null;
|
this._integrationVoiceLanguage = null;
|
||||||
this._allowBraveWebSpeechIntegration = false;
|
this._allowBraveWebSpeechIntegration = false;
|
||||||
this._voiceBackendBlocked = false;
|
this._voiceBackendBlocked = false;
|
||||||
|
this._voiceStopRequested = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── HA card interface ───────────────────────────────────────────────
|
// ── HA card interface ───────────────────────────────────────────────
|
||||||
@@ -491,6 +492,7 @@ class OpenClawChatCard extends HTMLElement {
|
|||||||
|
|
||||||
_startVoiceRecognition() {
|
_startVoiceRecognition() {
|
||||||
this._voiceBackendBlocked = false;
|
this._voiceBackendBlocked = false;
|
||||||
|
this._voiceStopRequested = false;
|
||||||
const allowBraveWebSpeech =
|
const allowBraveWebSpeech =
|
||||||
this._config.allow_brave_webspeech || this._allowBraveWebSpeechIntegration;
|
this._config.allow_brave_webspeech || this._allowBraveWebSpeechIntegration;
|
||||||
|
|
||||||
@@ -556,6 +558,13 @@ class OpenClawChatCard extends HTMLElement {
|
|||||||
|
|
||||||
this._recognition.onerror = (event) => {
|
this._recognition.onerror = (event) => {
|
||||||
const err = event?.error || "unknown";
|
const err = event?.error || "unknown";
|
||||||
|
if (err === "aborted") {
|
||||||
|
if (this._voiceStopRequested) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.debug("OpenClaw: Speech recognition aborted");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (err === "network") {
|
if (err === "network") {
|
||||||
console.warn("OpenClaw: Speech recognition network error");
|
console.warn("OpenClaw: Speech recognition network error");
|
||||||
} else {
|
} else {
|
||||||
@@ -594,6 +603,15 @@ class OpenClawChatCard extends HTMLElement {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this._recognition.onend = () => {
|
this._recognition.onend = () => {
|
||||||
|
if (this._voiceStopRequested) {
|
||||||
|
this._voiceStopRequested = false;
|
||||||
|
if (!this._isVoiceMode) {
|
||||||
|
this._voiceStatus = "";
|
||||||
|
this._render();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (this._isVoiceMode) {
|
if (this._isVoiceMode) {
|
||||||
// Restart recognition in voice mode
|
// Restart recognition in voice mode
|
||||||
try {
|
try {
|
||||||
@@ -613,6 +631,7 @@ class OpenClawChatCard extends HTMLElement {
|
|||||||
|
|
||||||
_stopVoiceRecognition() {
|
_stopVoiceRecognition() {
|
||||||
if (this._recognition) {
|
if (this._recognition) {
|
||||||
|
this._voiceStopRequested = true;
|
||||||
this._recognition.abort();
|
this._recognition.abort();
|
||||||
this._recognition = null;
|
this._recognition = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
if (!customElements.get("openclaw-chat-card")) {
|
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);
|
console.info("OpenClaw loader importing", src);
|
||||||
await import(src);
|
await import(src);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user