From fadb6a39790c688501d8415d94e0047aca40057b Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 7 Nov 2019 12:21:12 -0800 Subject: [PATCH] Add support for conversation ID (#28620) --- homeassistant/components/almond/__init__.py | 7 +++++-- homeassistant/components/conversation/__init__.py | 14 +++++++++----- homeassistant/components/conversation/agent.py | 5 ++++- .../components/conversation/default_agent.py | 5 ++++- tests/components/conversation/test_init.py | 14 ++++++++++++-- 5 files changed, 34 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/almond/__init__.py b/homeassistant/components/almond/__init__.py index 115e0d24de4..5eb305e6795 100644 --- a/homeassistant/components/almond/__init__.py +++ b/homeassistant/components/almond/__init__.py @@ -3,6 +3,7 @@ import asyncio from datetime import timedelta import logging import time +from typing import Optional import async_timeout from aiohttp import ClientSession, ClientError @@ -205,9 +206,11 @@ class AlmondAgent(conversation.AbstractConversationAgent): """Initialize the agent.""" self.api = api - async def async_process(self, text: str) -> intent.IntentResponse: + async def async_process( + self, text: str, conversation_id: Optional[str] = None + ) -> intent.IntentResponse: """Process a sentence.""" - response = await self.api.async_converse_text(text) + response = await self.api.async_converse_text(text, conversation_id) buffer = "" for message in response["messages"]: diff --git a/homeassistant/components/conversation/__init__.py b/homeassistant/components/conversation/__init__.py index 798fc926e0f..f875ec2822c 100644 --- a/homeassistant/components/conversation/__init__.py +++ b/homeassistant/components/conversation/__init__.py @@ -53,7 +53,7 @@ def async_set_agent(hass: core.HomeAssistant, agent: AbstractConversationAgent): async def async_setup(hass, config): """Register the process service.""" - async def process(hass, text): + async def process(hass, text, conversation_id): """Process a line of text.""" agent = hass.data.get(DATA_AGENT) @@ -61,14 +61,14 @@ async def async_setup(hass, config): agent = hass.data[DATA_AGENT] = DefaultAgent(hass) await agent.async_initialize(config) - return await agent.async_process(text) + return await agent.async_process(text, conversation_id) async def handle_service(service): """Parse text into commands.""" text = service.data[ATTR_TEXT] _LOGGER.debug("Processing: <%s>", text) try: - await process(hass, text) + await process(hass, text, service.context.id) except intent.IntentHandleError as err: _LOGGER.error("Error processing %s: %s", text, err) @@ -91,13 +91,17 @@ class ConversationProcessView(http.HomeAssistantView): """Initialize the conversation process view.""" self._process = process - @RequestDataValidator(vol.Schema({vol.Required("text"): str})) + @RequestDataValidator( + vol.Schema({vol.Required("text"): str, vol.Optional("conversation_id"): str}) + ) async def post(self, request, data): """Send a request for processing.""" hass = request.app["hass"] try: - intent_result = await self._process(hass, data["text"]) + intent_result = await self._process( + hass, data["text"], data.get("conversation_id") + ) except intent.IntentHandleError as err: intent_result = intent.IntentResponse() intent_result.async_set_speech(str(err)) diff --git a/homeassistant/components/conversation/agent.py b/homeassistant/components/conversation/agent.py index eae6402530c..1875ab5b9b9 100644 --- a/homeassistant/components/conversation/agent.py +++ b/homeassistant/components/conversation/agent.py @@ -1,5 +1,6 @@ """Agent foundation for conversation integration.""" from abc import ABC, abstractmethod +from typing import Optional from homeassistant.helpers import intent @@ -8,5 +9,7 @@ class AbstractConversationAgent(ABC): """Abstract conversation agent.""" @abstractmethod - async def async_process(self, text: str) -> intent.IntentResponse: + async def async_process( + self, text: str, conversation_id: Optional[str] = None + ) -> intent.IntentResponse: """Process a sentence.""" diff --git a/homeassistant/components/conversation/default_agent.py b/homeassistant/components/conversation/default_agent.py index e93afcfaf65..c202cdf1e65 100644 --- a/homeassistant/components/conversation/default_agent.py +++ b/homeassistant/components/conversation/default_agent.py @@ -1,6 +1,7 @@ """Standard conversastion implementation for Home Assistant.""" import logging import re +from typing import Optional from homeassistant import core from homeassistant.components.cover import INTENT_CLOSE_COVER, INTENT_OPEN_COVER @@ -107,7 +108,9 @@ class DefaultAgent(AbstractConversationAgent): for intent_type, sentences in UTTERANCES[component].items(): async_register(self.hass, intent_type, sentences) - async def async_process(self, text) -> intent.IntentResponse: + async def async_process( + self, text: str, conversation_id: Optional[str] = None + ) -> intent.IntentResponse: """Process a sentence.""" intents = self.hass.data[DOMAIN] diff --git a/tests/components/conversation/test_init.py b/tests/components/conversation/test_init.py index a9116ac0d98..ff44eaccc8e 100644 --- a/tests/components/conversation/test_init.py +++ b/tests/components/conversation/test_init.py @@ -266,11 +266,14 @@ async def test_http_api_wrong_data(hass, hass_client): async def test_custom_agent(hass, hass_client): """Test a custom conversation agent.""" + calls = [] + class MyAgent(conversation.AbstractConversationAgent): """Test Agent.""" - async def async_process(self, text): + async def async_process(self, text, conversation_id): """Process some text.""" + calls.append((text, conversation_id)) response = intent.IntentResponse() response.async_set_speech("Test response") return response @@ -281,9 +284,16 @@ async def test_custom_agent(hass, hass_client): client = await hass_client() - resp = await client.post("/api/conversation/process", json={"text": "Test Text"}) + resp = await client.post( + "/api/conversation/process", + json={"text": "Test Text", "conversation_id": "test-conv-id"}, + ) assert resp.status == 200 assert await resp.json() == { "card": {}, "speech": {"plain": {"extra_data": None, "speech": "Test response"}}, } + + assert len(calls) == 1 + assert calls[0][0] == "Test Text" + assert calls[0][1] == "test-conv-id"