Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions homeassistant/components/esphome/assist_satellite.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
VoiceAssistantEventType.VOICE_ASSISTANT_STT_START: PipelineEventType.STT_START,
VoiceAssistantEventType.VOICE_ASSISTANT_STT_END: PipelineEventType.STT_END,
VoiceAssistantEventType.VOICE_ASSISTANT_INTENT_START: PipelineEventType.INTENT_START,
VoiceAssistantEventType.VOICE_ASSISTANT_INTENT_PROGRESS: PipelineEventType.INTENT_PROGRESS,
VoiceAssistantEventType.VOICE_ASSISTANT_INTENT_END: PipelineEventType.INTENT_END,
VoiceAssistantEventType.VOICE_ASSISTANT_TTS_START: PipelineEventType.TTS_START,
VoiceAssistantEventType.VOICE_ASSISTANT_TTS_END: PipelineEventType.TTS_END,
Expand Down Expand Up @@ -282,6 +283,12 @@ def on_pipeline_event(self, event: PipelineEvent) -> None:
elif event_type == VoiceAssistantEventType.VOICE_ASSISTANT_STT_END:
assert event.data is not None
data_to_send = {"text": event.data["stt_output"]["text"]}
elif event_type == VoiceAssistantEventType.VOICE_ASSISTANT_INTENT_PROGRESS:
data_to_send = {
"tts_start_streaming": bool(
event.data and event.data.get("tts_start_streaming")
),
}
elif event_type == VoiceAssistantEventType.VOICE_ASSISTANT_INTENT_END:
assert event.data is not None
data_to_send = {
Expand Down
9 changes: 6 additions & 3 deletions homeassistant/helpers/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,6 @@ async def async_get_all_descriptions(
for service_name in services_by_domain
}
# If we have a complete cache, check if it is still valid
all_cache: tuple[set[tuple[str, str]], dict[str, dict[str, Any]]] | None
if all_cache := hass.data.get(ALL_SERVICE_DESCRIPTIONS_CACHE):
previous_all_services, previous_descriptions_cache = all_cache
# If the services are the same, we can return the cache
Expand All @@ -744,7 +743,11 @@ async def async_get_all_descriptions(
continue
if TYPE_CHECKING:
assert isinstance(int_or_exc, Exception)
_LOGGER.error("Failed to load integration: %s", domain, exc_info=int_or_exc)
_LOGGER.error(
"Failed to load services.yaml for integration: %s",
domain,
exc_info=int_or_exc,
)

if integrations:
loaded = await hass.async_add_executor_job(
Expand Down Expand Up @@ -772,7 +775,7 @@ async def async_get_all_descriptions(
# Cache missing descriptions
domain_yaml = loaded.get(domain) or {}
# The YAML may be empty for dynamically defined
# services (ie shell_command) that never call
# services (e.g. shell_command) that never call
# service.async_set_service_schema for the dynamic
# service

Expand Down
11 changes: 11 additions & 0 deletions tests/components/esphome/test_assist_satellite.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,17 @@ async def async_pipeline_from_audio_stream(*args, device_id, **kwargs):
)
assert satellite.state == AssistSatelliteState.PROCESSING

event_callback(
PipelineEvent(
type=PipelineEventType.INTENT_PROGRESS,
data={"tts_start_streaming": True},
)
)
assert mock_client.send_voice_assistant_event.call_args_list[-1].args == (
VoiceAssistantEventType.VOICE_ASSISTANT_INTENT_PROGRESS,
{"tts_start_streaming": True},
)

event_callback(
PipelineEvent(
type=PipelineEventType.INTENT_END,
Expand Down
2 changes: 1 addition & 1 deletion tests/helpers/test_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -1141,7 +1141,7 @@ async def wrap_get_translations(
descriptions = await service.async_get_all_descriptions(hass)

assert len(descriptions) == 3
assert "Failed to load integration: logger" in caplog.text
assert "Failed to load services.yaml for integration: logger" in caplog.text

# Services are empty defaults if the load fails but should
# not raise
Expand Down
Loading