From be24475cee71d3369d3975da12afd3709d47056b Mon Sep 17 00:00:00 2001 From: Denis Shulyaka Date: Tue, 30 Jul 2024 18:24:03 +0300 Subject: [PATCH] Update selector converters for llm script tools (#122830) --- homeassistant/helpers/llm.py | 4 +- tests/helpers/test_llm.py | 73 ++++++++++++++++++++++++++++++++++-- 2 files changed, 71 insertions(+), 6 deletions(-) diff --git a/homeassistant/helpers/llm.py b/homeassistant/helpers/llm.py index 4c8e2df06a4..8ad576b7ea5 100644 --- a/homeassistant/helpers/llm.py +++ b/homeassistant/helpers/llm.py @@ -521,7 +521,7 @@ def _selector_serializer(schema: Any) -> Any: # noqa: C901 return convert(cv.CONDITIONS_SCHEMA) if isinstance(schema, selector.ConstantSelector): - return {"enum": [schema.config["value"]]} + return convert(vol.Schema(schema.config["value"])) result: dict[str, Any] if isinstance(schema, selector.ColorTempSelector): @@ -573,7 +573,7 @@ def _selector_serializer(schema: Any) -> Any: # noqa: C901 return result if isinstance(schema, selector.ObjectSelector): - return {"type": "object"} + return {"type": "object", "additionalProperties": True} if isinstance(schema, selector.SelectSelector): options = [ diff --git a/tests/helpers/test_llm.py b/tests/helpers/test_llm.py index 3ad5b23b731..ea6e628d1d4 100644 --- a/tests/helpers/test_llm.py +++ b/tests/helpers/test_llm.py @@ -842,13 +842,22 @@ async def test_selector_serializer( assert selector_serializer( selector.ColorTempSelector({"min_mireds": 100, "max_mireds": 1000}) ) == {"type": "number", "minimum": 100, "maximum": 1000} + assert selector_serializer(selector.ConditionSelector()) == { + "type": "array", + "items": {"nullable": True, "type": "string"}, + } assert selector_serializer(selector.ConfigEntrySelector()) == {"type": "string"} assert selector_serializer(selector.ConstantSelector({"value": "test"})) == { - "enum": ["test"] + "type": "string", + "enum": ["test"], + } + assert selector_serializer(selector.ConstantSelector({"value": 1})) == { + "type": "integer", + "enum": [1], } - assert selector_serializer(selector.ConstantSelector({"value": 1})) == {"enum": [1]} assert selector_serializer(selector.ConstantSelector({"value": True})) == { - "enum": [True] + "type": "boolean", + "enum": [True], } assert selector_serializer(selector.QrCodeSelector({"data": "test"})) == { "type": "string" @@ -876,6 +885,17 @@ async def test_selector_serializer( "type": "array", "items": {"type": "string"}, } + assert selector_serializer(selector.DurationSelector()) == { + "type": "object", + "properties": { + "days": {"type": "number"}, + "hours": {"type": "number"}, + "minutes": {"type": "number"}, + "seconds": {"type": "number"}, + "milliseconds": {"type": "number"}, + }, + "required": [], + } assert selector_serializer(selector.EntitySelector()) == { "type": "string", "format": "entity_id", @@ -929,7 +949,10 @@ async def test_selector_serializer( "minimum": 30, "maximum": 100, } - assert selector_serializer(selector.ObjectSelector()) == {"type": "object"} + assert selector_serializer(selector.ObjectSelector()) == { + "type": "object", + "additionalProperties": True, + } assert selector_serializer( selector.SelectSelector( { @@ -951,6 +974,48 @@ async def test_selector_serializer( assert selector_serializer( selector.StateSelector({"entity_id": "sensor.test"}) ) == {"type": "string"} + target_schema = selector_serializer(selector.TargetSelector()) + target_schema["properties"]["entity_id"]["anyOf"][0][ + "enum" + ].sort() # Order is not deterministic + assert target_schema == { + "type": "object", + "properties": { + "area_id": { + "anyOf": [ + {"type": "string", "enum": ["none"]}, + {"type": "array", "items": {"type": "string", "nullable": True}}, + ] + }, + "device_id": { + "anyOf": [ + {"type": "string", "enum": ["none"]}, + {"type": "array", "items": {"type": "string", "nullable": True}}, + ] + }, + "entity_id": { + "anyOf": [ + {"type": "string", "enum": ["all", "none"], "format": "lower"}, + {"type": "string", "nullable": True}, + {"type": "array", "items": {"type": "string"}}, + ] + }, + "floor_id": { + "anyOf": [ + {"type": "string", "enum": ["none"]}, + {"type": "array", "items": {"type": "string", "nullable": True}}, + ] + }, + "label_id": { + "anyOf": [ + {"type": "string", "enum": ["none"]}, + {"type": "array", "items": {"type": "string", "nullable": True}}, + ] + }, + }, + "required": [], + } + assert selector_serializer(selector.TemplateSelector()) == { "type": "string", "format": "jinja2",