Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add conversation_id parameter to conversation.process service #106078

Merged
merged 3 commits into from
Jan 4, 2024
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
4 changes: 3 additions & 1 deletion homeassistant/components/conversation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
ATTR_TEXT = "text"
ATTR_LANGUAGE = "language"
ATTR_AGENT_ID = "agent_id"
ATTR_CONVERSATION_ID = "conversation_id"

DOMAIN = "conversation"

Expand All @@ -66,6 +67,7 @@ def agent_id_validator(value: Any) -> str:
vol.Required(ATTR_TEXT): cv.string,
vol.Optional(ATTR_LANGUAGE): cv.string,
vol.Optional(ATTR_AGENT_ID): agent_id_validator,
vol.Optional(ATTR_CONVERSATION_ID): cv.string,
}
)

Expand Down Expand Up @@ -164,7 +166,7 @@ async def handle_process(service: core.ServiceCall) -> core.ServiceResponse:
result = await async_converse(
hass=hass,
text=text,
conversation_id=None,
conversation_id=service.data.get(ATTR_CONVERSATION_ID),
context=service.context,
language=service.data.get(ATTR_LANGUAGE),
agent_id=service.data.get(ATTR_AGENT_ID),
Expand Down
4 changes: 4 additions & 0 deletions homeassistant/components/conversation/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ process:
example: homeassistant
selector:
conversation_agent:
conversation_id:
example: my_conversation_1
selector:
text:

reload:
fields:
Expand Down
4 changes: 4 additions & 0 deletions homeassistant/components/conversation/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
"agent_id": {
"name": "Agent",
"description": "Conversation agent to process your request. The conversation agent is the brains of your assistant. It processes the incoming text commands."
},
"conversation_id": {
"name": "Conversation ID",
"description": "ID of the conversation, to be able to continue a previous conversation"
}
}
},
Expand Down
128 changes: 124 additions & 4 deletions tests/components/conversation/snapshots/test_init.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@
]),
})
# ---
# name: test_turn_on_intent[turn kitchen on-None]
# name: test_turn_on_intent[None-turn kitchen on-None]
dict({
'conversation_id': None,
'response': dict({
Expand Down Expand Up @@ -255,7 +255,7 @@
}),
})
# ---
# name: test_turn_on_intent[turn kitchen on-homeassistant]
# name: test_turn_on_intent[None-turn kitchen on-homeassistant]
dict({
'conversation_id': None,
'response': dict({
Expand Down Expand Up @@ -285,7 +285,7 @@
}),
})
# ---
# name: test_turn_on_intent[turn on kitchen-None]
# name: test_turn_on_intent[None-turn on kitchen-None]
dict({
'conversation_id': None,
'response': dict({
Expand Down Expand Up @@ -315,7 +315,127 @@
}),
})
# ---
# name: test_turn_on_intent[turn on kitchen-homeassistant]
# name: test_turn_on_intent[None-turn on kitchen-homeassistant]
dict({
'conversation_id': None,
'response': dict({
'card': dict({
}),
'data': dict({
'failed': list([
]),
'success': list([
dict({
'id': 'light.kitchen',
'name': 'kitchen',
'type': <IntentResponseTargetType.ENTITY: 'entity'>,
}),
]),
'targets': list([
]),
}),
'language': 'en',
'response_type': 'action_done',
'speech': dict({
'plain': dict({
'extra_data': None,
'speech': 'Turned on light',
}),
}),
}),
})
# ---
# name: test_turn_on_intent[my_new_conversation-turn kitchen on-None]
dict({
'conversation_id': None,
'response': dict({
'card': dict({
}),
'data': dict({
'failed': list([
]),
'success': list([
dict({
'id': 'light.kitchen',
'name': 'kitchen',
'type': <IntentResponseTargetType.ENTITY: 'entity'>,
}),
]),
'targets': list([
]),
}),
'language': 'en',
'response_type': 'action_done',
'speech': dict({
'plain': dict({
'extra_data': None,
'speech': 'Turned on light',
}),
}),
}),
})
# ---
# name: test_turn_on_intent[my_new_conversation-turn kitchen on-homeassistant]
dict({
'conversation_id': None,
'response': dict({
'card': dict({
}),
'data': dict({
'failed': list([
]),
'success': list([
dict({
'id': 'light.kitchen',
'name': 'kitchen',
'type': <IntentResponseTargetType.ENTITY: 'entity'>,
}),
]),
'targets': list([
]),
}),
'language': 'en',
'response_type': 'action_done',
'speech': dict({
'plain': dict({
'extra_data': None,
'speech': 'Turned on light',
}),
}),
}),
})
# ---
# name: test_turn_on_intent[my_new_conversation-turn on kitchen-None]
dict({
'conversation_id': None,
'response': dict({
'card': dict({
}),
'data': dict({
'failed': list([
]),
'success': list([
dict({
'id': 'light.kitchen',
'name': 'kitchen',
'type': <IntentResponseTargetType.ENTITY: 'entity'>,
}),
]),
'targets': list([
]),
}),
'language': 'en',
'response_type': 'action_done',
'speech': dict({
'plain': dict({
'extra_data': None,
'speech': 'Turned on light',
}),
}),
}),
})
# ---
# name: test_turn_on_intent[my_new_conversation-turn on kitchen-homeassistant]
dict({
'conversation_id': None,
'response': dict({
Expand Down
5 changes: 4 additions & 1 deletion tests/components/conversation/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -873,8 +873,9 @@ async def test_http_processing_intent_conversion_not_expose_new(

@pytest.mark.parametrize("agent_id", AGENT_ID_OPTIONS)
@pytest.mark.parametrize("sentence", ("turn on kitchen", "turn kitchen on"))
@pytest.mark.parametrize("conversation_id", ("my_new_conversation", None))
async def test_turn_on_intent(
hass: HomeAssistant, init_components, sentence, agent_id, snapshot
hass: HomeAssistant, init_components, conversation_id, sentence, agent_id, snapshot
) -> None:
"""Test calling the turn on intent."""
hass.states.async_set("light.kitchen", "off")
Expand All @@ -883,6 +884,8 @@ async def test_turn_on_intent(
data = {conversation.ATTR_TEXT: sentence}
if agent_id is not None:
data[conversation.ATTR_AGENT_ID] = agent_id
if conversation_id is not None:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of adding this check, we can refactor the parameter to be a dict that we always use to update the service data. The two cases would be a dict with the conversation id and an empty dict.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be something like this then for data?

{
  "conversation_id": { "value": "..." }
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like this:

pytest.mark.parametrize("conversation_data", [{"conversation_id": "my_new_conversation"} , {}])

We can replace agent_id similarly.

data[conversation.ATTR_CONVERSATION_ID] = conversation_id
result = await hass.services.async_call(
"conversation",
"process",
Expand Down