Use media selector for Assist Satellite actions (#147767)

Co-authored-by: Michael Hansen <mike@rhasspy.org>
This commit is contained in:
Paulus Schoutsen 2025-06-30 20:12:03 +02:00 committed by Franck Nijhof
parent 62a1c8af11
commit 328e838351
No known key found for this signature in database
GPG Key ID: AB33ADACE7101952
3 changed files with 128 additions and 12 deletions

View File

@ -71,9 +71,9 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
cv.make_entity_service_schema(
{
vol.Optional("message"): str,
vol.Optional("media_id"): str,
vol.Optional("media_id"): _media_id_validator,
vol.Optional("preannounce"): bool,
vol.Optional("preannounce_media_id"): str,
vol.Optional("preannounce_media_id"): _media_id_validator,
}
),
cv.has_at_least_one_key("message", "media_id"),
@ -81,15 +81,16 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"async_internal_announce",
[AssistSatelliteEntityFeature.ANNOUNCE],
)
component.async_register_entity_service(
"start_conversation",
vol.All(
cv.make_entity_service_schema(
{
vol.Optional("start_message"): str,
vol.Optional("start_media_id"): str,
vol.Optional("start_media_id"): _media_id_validator,
vol.Optional("preannounce"): bool,
vol.Optional("preannounce_media_id"): str,
vol.Optional("preannounce_media_id"): _media_id_validator,
vol.Optional("extra_system_prompt"): str,
}
),
@ -135,9 +136,9 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
{
vol.Required(ATTR_ENTITY_ID): cv.entity_domain(DOMAIN),
vol.Optional("question"): str,
vol.Optional("question_media_id"): str,
vol.Optional("question_media_id"): _media_id_validator,
vol.Optional("preannounce"): bool,
vol.Optional("preannounce_media_id"): str,
vol.Optional("preannounce_media_id"): _media_id_validator,
vol.Optional("answers"): [
{
vol.Required("id"): str,
@ -204,3 +205,20 @@ def has_one_non_empty_item(value: list[str]) -> list[str]:
raise vol.Invalid("sentences cannot be empty")
return value
# Validator for media_id fields that accepts both string and media selector format
_media_id_validator = vol.Any(
cv.string, # Plain string format
vol.All(
vol.Schema(
{
vol.Required("media_content_id"): cv.string,
vol.Required("media_content_type"): cv.string,
vol.Remove("metadata"): dict, # Ignore metadata if present
}
),
# Extract media_content_id from media selector format
lambda x: x["media_content_id"],
),
)

View File

@ -14,7 +14,9 @@ announce:
media_id:
required: false
selector:
text:
media:
accept:
- audio/*
preannounce:
required: false
default: true
@ -23,7 +25,9 @@ announce:
preannounce_media_id:
required: false
selector:
text:
media:
accept:
- audio/*
start_conversation:
target:
entity:
@ -40,7 +44,9 @@ start_conversation:
start_media_id:
required: false
selector:
text:
media:
accept:
- audio/*
extra_system_prompt:
required: false
selector:
@ -53,7 +59,9 @@ start_conversation:
preannounce_media_id:
required: false
selector:
text:
media:
accept:
- audio/*
ask_question:
fields:
entity_id:
@ -72,7 +80,9 @@ ask_question:
question_media_id:
required: false
selector:
text:
media:
accept:
- audio/*
preannounce:
required: false
default: true
@ -81,7 +91,9 @@ ask_question:
preannounce_media_id:
required: false
selector:
text:
media:
accept:
- audio/*
answers:
required: false
selector:

View File

@ -235,6 +235,43 @@ async def test_new_pipeline_cancels_pipeline(
preannounce_media_id="http://example.com/preannounce.mp3",
),
),
(
{
"message": "Hello",
"media_id": {
"media_content_id": "media-source://given",
"media_content_type": "provider",
},
"preannounce": False,
},
AssistSatelliteAnnouncement(
message="Hello",
media_id="https://www.home-assistant.io/resolved.mp3",
original_media_id="media-source://given",
tts_token=None,
media_id_source="media_id",
),
),
(
{
"media_id": {
"media_content_id": "http://example.com/bla.mp3",
"media_content_type": "audio",
},
"preannounce_media_id": {
"media_content_id": "http://example.com/preannounce.mp3",
"media_content_type": "audio",
},
},
AssistSatelliteAnnouncement(
message="",
media_id="http://example.com/bla.mp3",
original_media_id="http://example.com/bla.mp3",
tts_token=None,
media_id_source="url",
preannounce_media_id="http://example.com/preannounce.mp3",
),
),
],
)
async def test_announce(
@ -610,6 +647,51 @@ async def test_vad_sensitivity_entity_not_found(
),
),
),
(
{
"start_message": "Hello",
"start_media_id": {
"media_content_id": "media-source://given",
"media_content_type": "provider",
},
"preannounce": False,
},
(
"mock-conversation-id",
"Hello",
AssistSatelliteAnnouncement(
message="Hello",
media_id="https://www.home-assistant.io/resolved.mp3",
tts_token=None,
original_media_id="media-source://given",
media_id_source="media_id",
),
),
),
(
{
"start_media_id": {
"media_content_id": "http://example.com/given.mp3",
"media_content_type": "audio",
},
"preannounce_media_id": {
"media_content_id": "http://example.com/preannounce.mp3",
"media_content_type": "audio",
},
},
(
"mock-conversation-id",
None,
AssistSatelliteAnnouncement(
message="",
media_id="http://example.com/given.mp3",
tts_token=None,
original_media_id="http://example.com/given.mp3",
media_id_source="url",
preannounce_media_id="http://example.com/preannounce.mp3",
),
),
),
],
)
@pytest.mark.usefixtures("mock_chat_session_conversation_id")
@ -731,6 +813,10 @@ async def test_start_conversation_default_preannounce(
),
(
{
"question_media_id": {
"media_content_id": "media-source://tts/cloud?message=What+kind+of+music+would+you+like+to+listen+to%3F&language=en-US&gender=female",
"media_content_type": "provider",
},
"answers": [
{
"id": "genre",