diff --git a/README.md b/README.md index 806b822..c03e5a1 100644 --- a/README.md +++ b/README.md @@ -95,8 +95,12 @@ will answer. ### Options (⚙ → Configure) - **Route incoming messages to Assist** – turn the chat bridge on/off. -- **Assist agent / language** – pick a specific conversation agent, or leave - blank for the default pipeline. +- **Assist agent / language** – pick the conversation agent from the dropdown. + > **Want free-form chat?** The default *Home Assistant* agent only recognises + > device-control commands and will answer anything else with "Sorry, I + > couldn't understand that". To actually chat, install an LLM conversation + > integration (OpenAI, Google Generative AI, Anthropic, Ollama, …), then + > select that agent here. - **Reply to any sender** / **Allowed sender addresses** – restrict who Assist will answer. - **Default recipient** – address used by the `notify.reticulum` entity. diff --git a/custom_components/reticulum/config_flow.py b/custom_components/reticulum/config_flow.py index b4e58eb..275a036 100644 --- a/custom_components/reticulum/config_flow.py +++ b/custom_components/reticulum/config_flow.py @@ -17,6 +17,10 @@ from homeassistant.core import callback from homeassistant.helpers import config_validation as cv from homeassistant.helpers.selector import ( BooleanSelector, + ConversationAgentSelector, + ConversationAgentSelectorConfig, + LanguageSelector, + LanguageSelectorConfig, NumberSelector, NumberSelectorConfig, NumberSelectorMode, @@ -170,16 +174,14 @@ class ReticulumOptionsFlow(OptionsFlow): ): BooleanSelector(), vol.Optional( CONF_ASSIST_AGENT, - description={ - "suggested_value": opts.get(CONF_ASSIST_AGENT, "") - }, - ): TextSelector(), + description={"suggested_value": opts.get(CONF_ASSIST_AGENT)}, + ): ConversationAgentSelector(ConversationAgentSelectorConfig()), vol.Optional( CONF_ASSIST_LANGUAGE, description={ - "suggested_value": opts.get(CONF_ASSIST_LANGUAGE, "") + "suggested_value": opts.get(CONF_ASSIST_LANGUAGE) }, - ): TextSelector(), + ): LanguageSelector(LanguageSelectorConfig()), vol.Required( CONF_ALLOW_ALL, default=opts.get(CONF_ALLOW_ALL, True) ): BooleanSelector(), diff --git a/custom_components/reticulum/entity.py b/custom_components/reticulum/entity.py index fd06f1a..8f21104 100644 --- a/custom_components/reticulum/entity.py +++ b/custom_components/reticulum/entity.py @@ -2,6 +2,7 @@ from __future__ import annotations +from homeassistant.core import callback from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.entity import DeviceInfo, Entity @@ -35,5 +36,9 @@ class ReticulumEntity(Entity): ) ) + @callback def _handle_update(self) -> None: + # Decorated with @callback so the dispatcher runs it on the event loop + # (a plain sync callback would be offloaded to an executor thread, and + # async_write_ha_state is not thread-safe). self.async_write_ha_state() diff --git a/custom_components/reticulum/manifest.json b/custom_components/reticulum/manifest.json index f8d37dc..cf2b6c7 100644 --- a/custom_components/reticulum/manifest.json +++ b/custom_components/reticulum/manifest.json @@ -12,5 +12,5 @@ "loggers": ["RNS", "LXMF"], "requirements": ["rns>=0.9.0", "lxmf>=0.6.0"], "single_config_entry": true, - "version": "1.0.3" + "version": "1.0.4" }