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
40 changes: 39 additions & 1 deletion homeassistant/components/anthropic/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from functools import partial
import json
import logging
import re
from typing import Any

import anthropic
Expand Down Expand Up @@ -283,7 +284,11 @@ async def async_step_advanced(
vol.Optional(
CONF_CHAT_MODEL,
default=RECOMMENDED_CHAT_MODEL,
): str,
): SelectSelector(
SelectSelectorConfig(
options=await self._get_model_list(), custom_value=True
)
),
vol.Optional(
CONF_MAX_TOKENS,
default=RECOMMENDED_MAX_TOKENS,
Expand Down Expand Up @@ -394,6 +399,39 @@ async def async_step_model(
last_step=True,
)

async def _get_model_list(self) -> list[SelectOptionDict]:
"""Get list of available models."""
try:
client = await self.hass.async_add_executor_job(
partial(
anthropic.AsyncAnthropic,
api_key=self._get_entry().data[CONF_API_KEY],
)
)
models = (await client.models.list()).data
except anthropic.AnthropicError:
models = []
_LOGGER.debug("Available models: %s", models)
model_options: list[SelectOptionDict] = []
short_form = re.compile(r"[^\d]-\d$")
for model_info in models:
# Resolve alias from versioned model name:
model_alias = (
model_info.id[:-9]
if model_info.id
not in ("claude-3-haiku-20240307", "claude-3-opus-20240229")
else model_info.id
)
if short_form.search(model_alias):
model_alias += "-0"
model_options.append(
SelectOptionDict(
label=model_info.display_name,
value=model_alias,
)
)
return model_options

async def _get_location_data(self) -> dict[str, str]:
"""Get approximate location data of the user."""
location_data: dict[str, str] = {}
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/dlna_dmr/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"documentation": "https://www.home-assistant.io/integrations/dlna_dmr",
"iot_class": "local_push",
"loggers": ["async_upnp_client"],
"requirements": ["async-upnp-client==0.45.0", "getmac==0.9.5"],
"requirements": ["async-upnp-client==0.46.0", "getmac==0.9.5"],
"ssdp": [
{
"deviceType": "urn:schemas-upnp-org:device:MediaRenderer:1",
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/dlna_dms/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"dependencies": ["ssdp"],
"documentation": "https://www.home-assistant.io/integrations/dlna_dms",
"iot_class": "local_polling",
"requirements": ["async-upnp-client==0.45.0"],
"requirements": ["async-upnp-client==0.46.0"],
"ssdp": [
{
"deviceType": "urn:schemas-upnp-org:device:MediaServer:1",
Expand Down
11 changes: 8 additions & 3 deletions homeassistant/components/openai_conversation/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,16 +338,21 @@ async def async_step_model(
options.pop(CONF_CODE_INTERPRETER)

if model.startswith(("o", "gpt-5")) and not model.startswith("gpt-5-pro"):
if model.startswith("gpt-5.1"):
reasoning_options = ["none", "low", "medium", "high"]
elif model.startswith("gpt-5"):
reasoning_options = ["minimal", "low", "medium", "high"]
else:
reasoning_options = ["low", "medium", "high"]

step_schema.update(
{
vol.Optional(
CONF_REASONING_EFFORT,
default=RECOMMENDED_REASONING_EFFORT,
): SelectSelector(
SelectSelectorConfig(
options=["low", "medium", "high"]
if model.startswith("o")
else ["minimal", "low", "medium", "high"],
options=reasoning_options,
translation_key=CONF_REASONING_EFFORT,
mode=SelectSelectorMode.DROPDOWN,
)
Expand Down
3 changes: 3 additions & 0 deletions homeassistant/components/openai_conversation/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,9 @@ async def _async_handle_chat_log(
"verbosity": options.get(CONF_VERBOSITY, RECOMMENDED_VERBOSITY)
}

if model_args["model"].startswith("gpt-5.1"):
model_args["prompt_cache_retention"] = "24h"

tools: list[ToolParam] = []
if chat_log.llm_api:
tools = [
Expand Down
3 changes: 2 additions & 1 deletion homeassistant/components/openai_conversation/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@
"high": "[%key:common::state::high%]",
"low": "[%key:common::state::low%]",
"medium": "[%key:common::state::medium%]",
"minimal": "Minimal"
"minimal": "Minimal",
"none": "None"
}
},
"search_context_size": {
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/samsungtv/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"samsungctl[websocket]==0.7.1",
"samsungtvws[async,encrypted]==2.7.2",
"wakeonlan==3.1.0",
"async-upnp-client==0.45.0"
"async-upnp-client==0.46.0"
],
"ssdp": [
{
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/ssdp/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"iot_class": "local_push",
"loggers": ["async_upnp_client"],
"quality_scale": "internal",
"requirements": ["async-upnp-client==0.45.0"]
"requirements": ["async-upnp-client==0.46.0"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/upnp/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"integration_type": "device",
"iot_class": "local_polling",
"loggers": ["async_upnp_client"],
"requirements": ["async-upnp-client==0.45.0", "getmac==0.9.5"],
"requirements": ["async-upnp-client==0.46.0", "getmac==0.9.5"],
"ssdp": [
{
"st": "urn:schemas-upnp-org:device:InternetGatewayDevice:1"
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/uptime_kuma/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"iot_class": "cloud_polling",
"loggers": ["pythonkuma"],
"quality_scale": "platinum",
"requirements": ["pythonkuma==0.3.1"]
"requirements": ["pythonkuma==0.3.2"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/yeelight/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
},
"iot_class": "local_push",
"loggers": ["async_upnp_client", "yeelight"],
"requirements": ["yeelight==0.7.16", "async-upnp-client==0.45.0"],
"requirements": ["yeelight==0.7.16", "async-upnp-client==0.46.0"],
"zeroconf": [
{
"name": "yeelink-*",
Expand Down
95 changes: 1 addition & 94 deletions homeassistant/helpers/template/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1166,13 +1166,6 @@ def expand(hass: HomeAssistant, *args: Any) -> Iterable[State]:
return list(found.values())


def device_entities(hass: HomeAssistant, _device_id: str) -> Iterable[str]:
"""Get entity ids for entities tied to a device."""
entity_reg = er.async_get(hass)
entries = er.async_entries_for_device(entity_reg, _device_id)
return [entry.entity_id for entry in entries]


def integration_entities(hass: HomeAssistant, entry_name: str) -> Iterable[str]:
"""Get entity ids for entities tied to an integration/domain.

Expand Down Expand Up @@ -1214,65 +1207,6 @@ def config_entry_id(hass: HomeAssistant, entity_id: str) -> str | None:
return None


def device_id(hass: HomeAssistant, entity_id_or_device_name: str) -> str | None:
"""Get a device ID from an entity ID or device name."""
entity_reg = er.async_get(hass)
entity = entity_reg.async_get(entity_id_or_device_name)
if entity is not None:
return entity.device_id

dev_reg = dr.async_get(hass)
return next(
(
device_id
for device_id, device in dev_reg.devices.items()
if (name := device.name_by_user or device.name)
and (str(entity_id_or_device_name) == name)
),
None,
)


def device_name(hass: HomeAssistant, lookup_value: str) -> str | None:
"""Get the device name from an device id, or entity id."""
device_reg = dr.async_get(hass)
if device := device_reg.async_get(lookup_value):
return device.name_by_user or device.name

ent_reg = er.async_get(hass)
# Import here, not at top-level to avoid circular import
from homeassistant.helpers import config_validation as cv # noqa: PLC0415

try:
cv.entity_id(lookup_value)
except vol.Invalid:
pass
else:
if entity := ent_reg.async_get(lookup_value):
if entity.device_id and (device := device_reg.async_get(entity.device_id)):
return device.name_by_user or device.name

return None


def device_attr(hass: HomeAssistant, device_or_entity_id: str, attr_name: str) -> Any:
"""Get the device specific attribute."""
device_reg = dr.async_get(hass)
if not isinstance(device_or_entity_id, str):
raise TemplateError("Must provide a device or entity ID")
device = None
if (
"." in device_or_entity_id
and (_device_id := device_id(hass, device_or_entity_id)) is not None
):
device = device_reg.async_get(_device_id)
elif "." not in device_or_entity_id:
device = device_reg.async_get(device_or_entity_id)
if device is None or not hasattr(device, attr_name):
return None
return getattr(device, attr_name)


def config_entry_attr(
hass: HomeAssistant, config_entry_id_: str, attr_name: str
) -> Any:
Expand All @@ -1291,13 +1225,6 @@ def config_entry_attr(
return getattr(config_entry, attr_name)


def is_device_attr(
hass: HomeAssistant, device_or_entity_id: str, attr_name: str, attr_value: Any
) -> bool:
"""Test if a device's attribute is a specific value."""
return bool(device_attr(hass, device_or_entity_id, attr_name) == attr_value)


def issues(hass: HomeAssistant) -> dict[tuple[str, str], dict[str, Any]]:
"""Return all open issues."""
current_issues = ir.async_get(hass).issues
Expand Down Expand Up @@ -2260,6 +2187,7 @@ def __init__(
"homeassistant.helpers.template.extensions.CollectionExtension"
)
self.add_extension("homeassistant.helpers.template.extensions.CryptoExtension")
self.add_extension("homeassistant.helpers.template.extensions.DeviceExtension")
self.add_extension("homeassistant.helpers.template.extensions.FloorExtension")
self.add_extension("homeassistant.helpers.template.extensions.LabelExtension")
self.add_extension("homeassistant.helpers.template.extensions.MathExtension")
Expand Down Expand Up @@ -2377,23 +2305,6 @@ def wrapper(_: Any, *args: _P.args, **kwargs: _P.kwargs) -> _R:
self.globals["config_entry_id"] = hassfunction(config_entry_id)
self.filters["config_entry_id"] = self.globals["config_entry_id"]

# Device extensions

self.globals["device_name"] = hassfunction(device_name)
self.filters["device_name"] = self.globals["device_name"]

self.globals["device_attr"] = hassfunction(device_attr)
self.filters["device_attr"] = self.globals["device_attr"]

self.globals["device_entities"] = hassfunction(device_entities)
self.filters["device_entities"] = self.globals["device_entities"]

self.globals["is_device_attr"] = hassfunction(is_device_attr)
self.tests["is_device_attr"] = hassfunction(is_device_attr, pass_eval_context)

self.globals["device_id"] = hassfunction(device_id)
self.filters["device_id"] = self.globals["device_id"]

# Issue extensions

self.globals["issues"] = hassfunction(issues)
Expand All @@ -2415,12 +2326,9 @@ def warn_unsupported(*args: Any, **kwargs: Any) -> NoReturn:
"area_id",
"area_name",
"closest",
"device_attr",
"device_id",
"distance",
"expand",
"has_value",
"is_device_attr",
"is_hidden_entity",
"is_state_attr",
"is_state",
Expand All @@ -2438,7 +2346,6 @@ def warn_unsupported(*args: Any, **kwargs: Any) -> NoReturn:
"area_id",
"area_name",
"closest",
"device_id",
"expand",
"has_value",
]
Expand Down
2 changes: 2 additions & 0 deletions homeassistant/helpers/template/extensions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from .base64 import Base64Extension
from .collection import CollectionExtension
from .crypto import CryptoExtension
from .devices import DeviceExtension
from .floors import FloorExtension
from .labels import LabelExtension
from .math import MathExtension
Expand All @@ -13,6 +14,7 @@
"Base64Extension",
"CollectionExtension",
"CryptoExtension",
"DeviceExtension",
"FloorExtension",
"LabelExtension",
"MathExtension",
Expand Down
Loading
Loading