diff --git a/CHANGELOG.md b/CHANGELOG.md index c676441..7f999e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to the OpenClaw Home Assistant Integration will be documented in this file. +## [0.1.24] - 2026-02-20 + +### Fixed +- Added proactive Brave browser guard for card voice input to avoid recurring `SpeechRecognition` `network` failures. +- Voice is now disabled by default on Brave with a clear status message and opt-in override (`allow_brave_webspeech: true`). +- Reduced noisy console output for `network` speech errors. + ## [0.1.23] - 2026-02-20 ### Fixed diff --git a/README.md b/README.md index bdd89b3..62d29d0 100644 --- a/README.md +++ b/README.md @@ -1,106 +1,234 @@ # OpenClaw Integration for Home Assistant -A native Home Assistant integration for communicating with the -[OpenClaw Assistant](https://github.com/techartdev/OpenClawHomeAssistant) addon. +OpenClaw is a Home Assistant custom integration that connects your HA instance to the OpenClaw assistant backend and provides: -## Features +- A native conversation agent for Assist +- A Lovelace chat card with session history +- Service and event APIs for automations +- Optional voice mode in the card -- **Chat card** — Lovelace card with streaming AI responses, file attachments, and voice mode -- **Sensors** — `openclaw_status`, `openclaw_model`, `openclaw_session_count`, `openclaw_last_activity`, `openclaw_connected` -- **Conversation agent** — appears in Assist & Voice PE as a native agent -- **Service calls** — `openclaw.send_message` for automations -- **Events** — `openclaw_message_received` for triggering automations from AI responses -- **Zero-config** — auto-discovers the addon via Supervisor API, no tokens or URLs to enter +--- + +## What it includes + +- **Conversation agent** (`openclaw`) in Assist / Voice Assistants +- **Lovelace chat card** (`custom:openclaw-chat-card`) with: + - message history restore, + - typing indicator, + - optional voice input, + - wake-word handling for continuous mode +- **Services** + - `openclaw.send_message` + - `openclaw.clear_history` +- **Event** + - `openclaw_message_received` +- **Sensors / status entities** for model and connection state + +--- + +## Requirements + +- Home Assistant with Supervisor support for addon discovery +- OpenClaw Assistant addon installed and running + +The integration auto-detects the addon. You do not need to manually set an API base URL. + +--- ## Installation -### HACS (recommended) +### Option A: HACS (recommended) -1. Open HACS → Integrations → **+ Explore & Download Repositories** -2. Search for **OpenClaw** and install -3. Restart Home Assistant -4. Go to Settings → Devices & Services → **Add Integration → OpenClaw** +1. Open **HACS → Integrations** +2. Select **Explore & Download Repositories** +3. Search for **OpenClaw** and install +4. Restart Home Assistant +5. Open **Settings → Devices & Services → Add Integration** +6. Add **OpenClaw** -### Manual +### Option B: Manual + +1. Copy `custom_components/openclaw` into your HA config directory: + + ``` + config/custom_components/openclaw + ``` -1. Copy `custom_components/openclaw/` into your HA `config/custom_components/` directory 2. Restart Home Assistant -3. Add the integration via Settings → Devices & Services +3. Add **OpenClaw** from **Settings → Devices & Services** -## Prerequisites +--- -The **OpenClaw Assistant** addon must be installed and running. -The integration will auto-detect it — no manual configuration needed. +## Dashboard card -## Exposed entities (important) +The card is registered automatically by the integration. -OpenClaw uses Home Assistant's native **Assist entity exposure** controls. -Only entities exposed to Assist are included in the context sent to OpenClaw. +```yaml +type: custom:openclaw-chat-card +title: OpenClaw Chat +height: 500px +show_timestamps: true +show_voice_button: true +show_clear_button: true +session_id: default +``` -Configure this in Home Assistant: - -1. Go to **Settings → Voice assistants** -2. Open the **Expose** tab -3. Select which entities are exposed to **Assist** - -## Advanced options - -Open **Settings → Devices & Services → OpenClaw → Configure** to tune: - -- Include exposed entities context -- Max context characters -- Context overflow strategy (`truncate` or `clear`) -- Enable tool calls (execute HA services from model tool-call responses) -- Require wake word -- Wake word text (for example: `hey openclaw`) -- Always-on voice mode (continuous listening while the card is open) - -## Chat Card - -The chat card is registered automatically when the integration loads — no -manual resource configuration needed. Just add it to any dashboard: +Minimal config: ```yaml type: custom:openclaw-chat-card ``` +--- + +## Assist entity exposure context + +OpenClaw can include Home Assistant entity context based on Assist exposure. + +Configure exposure in: + +**Settings → Voice assistants → Expose** + +Only entities exposed there are included when this feature is enabled. + +--- + +## Integration options + +Open **Settings → Devices & Services → OpenClaw → Configure**. + +### Context options + +- **Include exposed entities context** +- **Max context characters** +- **Context strategy** + - `truncate`: keep the first part up to max length + - `clear`: remove context when it exceeds max length + +### Tool call option + +- **Enable tool calls** + +When enabled, OpenClaw tool-call responses can execute Home Assistant services. + +### Voice options + +- **Wake word enabled** +- **Wake word** (default: `hey openclaw`) +- **Always voice mode** (continuous listening while card is open) + +--- + +## Browser voice note (important) + +Card voice input uses browser speech recognition APIs (`SpeechRecognition` / `webkitSpeechRecognition`). + +- Behavior depends on browser support and provider availability +- In Brave, repeated `network` errors can occur even with mic permission +- The card now detects repeated backend failures and stops endless retries with a clear status message + +If voice is unreliable in Brave, use Chrome/Edge for card voice input or continue with typed chat. + +--- + ## Services ### `openclaw.send_message` -Send a message to OpenClaw from an automation or script. +Send a message to OpenClaw. + +Fields: + +- `message` (required) +- `session_id` (optional) +- `attachments` (optional) + +Example: ```yaml service: openclaw.send_message data: - message: "What's the weather like today?" - session_id: "optional-session-id" + message: "Turn on the living room lights" + session_id: "living-room-session" ``` ### `openclaw.clear_history` +Clear stored conversation history for a session. + +Fields: + +- `session_id` (optional; defaults to `default` session) + +Example: + ```yaml service: openclaw.clear_history data: - session_id: "optional-session-id" + session_id: "living-room-session" ``` -## Events +--- + +## Event ### `openclaw_message_received` -Fired whenever OpenClaw sends a response. Use in automations: +Fired when OpenClaw returns a response. + +Event data includes: + +- `message` +- `session_id` +- `timestamp` + +Automation example: ```yaml trigger: - platform: event event_type: openclaw_message_received action: - - service: notify.mobile_app + - service: notify.mobile_app_phone data: message: "{{ trigger.event.data.message }}" ``` +--- + +## Troubleshooting + +### Card does not appear + +- Restart Home Assistant after updating +- Hard refresh browser cache +- Confirm Integration is loaded in **Settings → Devices & Services** + +### Voice button is active but no transcript is sent + +- Check browser mic permission for your HA URL +- Open browser console for `OpenClaw: Speech recognition error` +- If you see repeated `network`, this is usually browser speech backend failure + +### Responses do not appear after sending + +- Verify `openclaw_message_received` is being fired in Developer Tools → Events +- Confirm session IDs match between card and service calls + +--- + +## Development notes + +- Main card source is: + + ``` + custom_components/openclaw/www/openclaw-chat-card.js + ``` + +- Root `www/openclaw-chat-card.js` is a loader shim that imports the packaged card script. + +--- + ## License -See [LICENSE](LICENSE). +MIT. See [LICENSE](LICENSE). diff --git a/custom_components/openclaw/__init__.py b/custom_components/openclaw/__init__.py index 5c065a0..9d4e564 100644 --- a/custom_components/openclaw/__init__.py +++ b/custom_components/openclaw/__init__.py @@ -74,7 +74,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.23" +_CARD_URL = f"{_CARD_STATIC_URL}?v=0.1.24" type OpenClawConfigEntry = ConfigEntry diff --git a/custom_components/openclaw/manifest.json b/custom_components/openclaw/manifest.json index 566b995..d302bbd 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.23", + "version": "0.1.24", "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 6cef6d7..eb4dbf4 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.3"; +const CARD_VERSION = "0.2.4"; // Max time (ms) to show the thinking indicator before falling back to an error const THINKING_TIMEOUT_MS = 120_000; @@ -88,6 +88,7 @@ class OpenClawChatCard extends HTMLElement { show_timestamps: config.show_timestamps !== false, show_voice_button: config.show_voice_button !== false, show_clear_button: config.show_clear_button !== false, + allow_brave_webspeech: config.allow_brave_webspeech === true, session_id: config.session_id || null, ...config, }; @@ -458,6 +459,13 @@ class OpenClawChatCard extends HTMLElement { _startVoiceRecognition() { this._voiceBackendBlocked = false; + if (this._isLikelyBraveBrowser() && !this._config.allow_brave_webspeech) { + this._voiceStatus = + "Voice input disabled on Brave by default due browser SpeechRecognition network failures. Use Chrome/Edge, or set allow_brave_webspeech: true in card config to force-enable experimental mode."; + this._render(); + return; + } + if (!("webkitSpeechRecognition" in window) && !("SpeechRecognition" in window)) { console.warn("OpenClaw: Speech recognition not supported in this browser"); this._voiceStatus = "Speech recognition not supported by this browser."; @@ -512,8 +520,12 @@ class OpenClawChatCard extends HTMLElement { }; this._recognition.onerror = (event) => { - console.error("OpenClaw: Speech recognition error:", event.error); const err = event?.error || "unknown"; + if (err === "network") { + console.warn("OpenClaw: Speech recognition network error"); + } else { + console.error("OpenClaw: Speech recognition error:", err); + } if (err === "network") { this._voiceNetworkErrorCount += 1; const browserLocale = this._normalizeSpeechLanguage(navigator.language || "en-US"); diff --git a/www/openclaw-chat-card.js b/www/openclaw-chat-card.js index 879e87c..7d71b67 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.23"; + const src = "/openclaw/openclaw-chat-card.js?v=0.1.24"; console.info("OpenClaw loader importing", src); await import(src); }