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
4 changes: 2 additions & 2 deletions homeassistant/components/anthropic/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
CONF_RECOMMENDED = "recommended"
CONF_PROMPT = "prompt"
CONF_CHAT_MODEL = "chat_model"
RECOMMENDED_CHAT_MODEL = "claude-3-haiku-20240307"
RECOMMENDED_CHAT_MODEL = "claude-3-5-haiku-latest"
CONF_MAX_TOKENS = "max_tokens"
RECOMMENDED_MAX_TOKENS = 1024
RECOMMENDED_MAX_TOKENS = 3000
CONF_TEMPERATURE = "temperature"
RECOMMENDED_TEMPERATURE = 1.0
CONF_THINKING_BUDGET = "thinking_budget"
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/google_cloud/stt.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ async def request_generator() -> AsyncGenerator[
try:
responses = await self._client.streaming_recognize(
requests=request_generator(),
timeout=10,
timeout=30,
retry=AsyncRetry(initial=0.1, maximum=2.0, multiplier=2.0),
)

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/google_cloud/tts.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ async def _async_get_tts_audio(

response = await self._client.synthesize_speech(
request,
timeout=10,
timeout=30,
retry=AsyncRetry(initial=0.1, maximum=2.0, multiplier=2.0),
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
CONF_TOP_K = "top_k"
RECOMMENDED_TOP_K = 64
CONF_MAX_TOKENS = "max_tokens"
RECOMMENDED_MAX_TOKENS = 1500
RECOMMENDED_MAX_TOKENS = 3000
CONF_HARASSMENT_BLOCK_THRESHOLD = "harassment_block_threshold"
CONF_HATE_BLOCK_THRESHOLD = "hate_block_threshold"
CONF_SEXUAL_BLOCK_THRESHOLD = "sexual_block_threshold"
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/ollama/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@
"yi",
"zephyr",
]
DEFAULT_MODEL = "llama3.2:latest"
DEFAULT_MODEL = "qwen3:4b"

DEFAULT_CONVERSATION_NAME = "Ollama Conversation"
DEFAULT_AI_TASK_NAME = "Ollama AI Task"
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/openai_conversation/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
CONF_WEB_SEARCH_COUNTRY = "country"
CONF_WEB_SEARCH_TIMEZONE = "timezone"
RECOMMENDED_CHAT_MODEL = "gpt-4o-mini"
RECOMMENDED_MAX_TOKENS = 150
RECOMMENDED_MAX_TOKENS = 3000
RECOMMENDED_REASONING_EFFORT = "low"
RECOMMENDED_TEMPERATURE = 1.0
RECOMMENDED_TOP_P = 1.0
Expand Down
21 changes: 15 additions & 6 deletions homeassistant/helpers/device_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,21 @@ class DeviceInfo(TypedDict, total=False):
LOW_PRIO_CONFIG_ENTRY_DOMAINS = {"homekit_controller", "matter", "mqtt", "upnp"}


class _EventDeviceRegistryUpdatedData_CreateRemove(TypedDict):
"""EventDeviceRegistryUpdated data for action type 'create' and 'remove'."""
class _EventDeviceRegistryUpdatedData_Create(TypedDict):
"""EventDeviceRegistryUpdated data for action type 'create'."""

action: Literal["create", "remove"]
action: Literal["create"]
device_id: str


class _EventDeviceRegistryUpdatedData_Remove(TypedDict):
"""EventDeviceRegistryUpdated data for action type 'remove'."""

action: Literal["remove"]
device_id: str
device: DeviceEntry


class _EventDeviceRegistryUpdatedData_Update(TypedDict):
"""EventDeviceRegistryUpdated data for action type 'update'."""

Expand All @@ -160,7 +168,8 @@ class _EventDeviceRegistryUpdatedData_Update(TypedDict):


type EventDeviceRegistryUpdatedData = (
_EventDeviceRegistryUpdatedData_CreateRemove
_EventDeviceRegistryUpdatedData_Create
| _EventDeviceRegistryUpdatedData_Remove
| _EventDeviceRegistryUpdatedData_Update
)

Expand Down Expand Up @@ -1309,8 +1318,8 @@ def async_remove_device(self, device_id: str) -> None:
self.async_update_device(other_device.id, via_device_id=None)
self.hass.bus.async_fire_internal(
EVENT_DEVICE_REGISTRY_UPDATED,
_EventDeviceRegistryUpdatedData_CreateRemove(
action="remove", device_id=device_id
_EventDeviceRegistryUpdatedData_Remove(
action="remove", device_id=device_id, device=device
),
)
self.async_schedule_save()
Expand Down
60 changes: 39 additions & 21 deletions homeassistant/helpers/entity_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -1103,8 +1103,17 @@ def async_device_modified(
entities = async_entries_for_device(
self, event.data["device_id"], include_disabled_entities=True
)
removed_device = event.data["device"]
for entity in entities:
self.async_remove(entity.entity_id)
config_entry_id = entity.config_entry_id
if (
config_entry_id in removed_device.config_entries
and entity.config_subentry_id
in removed_device.config_entries_subentries[config_entry_id]
):
self.async_remove(entity.entity_id)
else:
self.async_update_entity(entity.entity_id, device_id=None)
return

if event.data["action"] != "update":
Expand All @@ -1121,29 +1130,38 @@ def async_device_modified(

# Remove entities which belong to config entries no longer associated with the
# device
entities = async_entries_for_device(
self, event.data["device_id"], include_disabled_entities=True
)
for entity in entities:
if (
entity.config_entry_id is not None
and entity.config_entry_id not in device.config_entries
):
self.async_remove(entity.entity_id)
if old_config_entries := event.data["changes"].get("config_entries"):
entities = async_entries_for_device(
self, event.data["device_id"], include_disabled_entities=True
)
for entity in entities:
config_entry_id = entity.config_entry_id
if (
entity.config_entry_id in old_config_entries
and entity.config_entry_id not in device.config_entries
):
self.async_remove(entity.entity_id)

# Remove entities which belong to config subentries no longer associated with the
# device
entities = async_entries_for_device(
self, event.data["device_id"], include_disabled_entities=True
)
for entity in entities:
if (
(config_entry_id := entity.config_entry_id) is not None
and config_entry_id in device.config_entries
and entity.config_subentry_id
not in device.config_entries_subentries[config_entry_id]
):
self.async_remove(entity.entity_id)
if old_config_entries_subentries := event.data["changes"].get(
"config_entries_subentries"
):
entities = async_entries_for_device(
self, event.data["device_id"], include_disabled_entities=True
)
for entity in entities:
config_entry_id = entity.config_entry_id
config_subentry_id = entity.config_subentry_id
if (
config_entry_id in device.config_entries
and config_entry_id in old_config_entries_subentries
and config_subentry_id
in old_config_entries_subentries[config_entry_id]
and config_subentry_id
not in device.config_entries_subentries[config_entry_id]
):
self.async_remove(entity.entity_id)

# Re-enable disabled entities if the device is no longer disabled
if not device.disabled:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
'dangerous_block_threshold': 'BLOCK_MEDIUM_AND_ABOVE',
'harassment_block_threshold': 'BLOCK_MEDIUM_AND_ABOVE',
'hate_block_threshold': 'BLOCK_MEDIUM_AND_ABOVE',
'max_tokens': 1500,
'max_tokens': 3000,
'prompt': 'Speak like a pirate',
'recommended': False,
'sexual_block_threshold': 'BLOCK_MEDIUM_AND_ABOVE',
Expand Down
2 changes: 1 addition & 1 deletion tests/components/openai_conversation/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ async def test_generate_content_service(
"""Test generate content service."""
service_data["config_entry"] = mock_config_entry.entry_id
expected_args["model"] = "gpt-4o-mini"
expected_args["max_output_tokens"] = 150
expected_args["max_output_tokens"] = 3000
expected_args["top_p"] = 1.0
expected_args["temperature"] = 1.0
expected_args["user"] = None
Expand Down
13 changes: 12 additions & 1 deletion tests/helpers/test_device_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -1652,6 +1652,7 @@ async def test_removing_config_entries(
assert update_events[4].data == {
"action": "remove",
"device_id": entry3.id,
"device": entry3,
}


Expand Down Expand Up @@ -1724,10 +1725,12 @@ async def test_deleted_device_removing_config_entries(
assert update_events[3].data == {
"action": "remove",
"device_id": entry.id,
"device": entry2,
}
assert update_events[4].data == {
"action": "remove",
"device_id": entry3.id,
"device": entry3,
}

device_registry.async_clear_config_entry(config_entry_1.entry_id)
Expand Down Expand Up @@ -1973,6 +1976,7 @@ async def test_removing_config_subentries(
assert update_events[7].data == {
"action": "remove",
"device_id": entry.id,
"device": entry,
}


Expand Down Expand Up @@ -2102,6 +2106,7 @@ async def test_deleted_device_removing_config_subentries(
assert update_events[4].data == {
"action": "remove",
"device_id": entry.id,
"device": entry4,
}

device_registry.async_clear_config_subentry(config_entry_1.entry_id, None)
Expand Down Expand Up @@ -2925,6 +2930,7 @@ async def test_update_remove_config_entries(
assert update_events[6].data == {
"action": "remove",
"device_id": entry3.id,
"device": entry3,
}


Expand Down Expand Up @@ -3104,6 +3110,7 @@ async def test_update_remove_config_subentries(
config_entry_3.entry_id: {None},
}

entry_before_remove = entry
entry = device_registry.async_update_device(
entry_id,
remove_config_entry_id=config_entry_3.entry_id,
Expand Down Expand Up @@ -3201,6 +3208,7 @@ async def test_update_remove_config_subentries(
assert update_events[7].data == {
"action": "remove",
"device_id": entry_id,
"device": entry_before_remove,
}


Expand Down Expand Up @@ -3422,7 +3430,7 @@ async def test_restore_device(
)

# Apply user customizations
device_registry.async_update_device(
entry = device_registry.async_update_device(
entry.id,
area_id="12345A",
disabled_by=dr.DeviceEntryDisabler.USER,
Expand Down Expand Up @@ -3543,6 +3551,7 @@ async def test_restore_device(
assert update_events[2].data == {
"action": "remove",
"device_id": entry.id,
"device": entry,
}
assert update_events[3].data == {
"action": "create",
Expand Down Expand Up @@ -3865,6 +3874,7 @@ async def test_restore_shared_device(
assert update_events[3].data == {
"action": "remove",
"device_id": entry.id,
"device": updated_device,
}
assert update_events[4].data == {
"action": "create",
Expand All @@ -3873,6 +3883,7 @@ async def test_restore_shared_device(
assert update_events[5].data == {
"action": "remove",
"device_id": entry.id,
"device": entry2,
}
assert update_events[6].data == {
"action": "create",
Expand Down
35 changes: 21 additions & 14 deletions tests/helpers/test_entity_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -1684,20 +1684,23 @@ async def test_remove_config_entry_from_device_removes_entities_2(
await hass.async_block_till_done()

assert device_registry.async_get(device_entry.id)
# Entities which are not tied to the removed config entry should not be removed
assert entity_registry.async_is_registered(entry_1.entity_id)
# Entities with a config entry not in the device are removed
assert not entity_registry.async_is_registered(entry_2.entity_id)
assert entity_registry.async_is_registered(entry_2.entity_id)

# Remove the second config entry from the device
# Remove the second config entry from the device (this removes the device)
device_registry.async_update_device(
device_entry.id, remove_config_entry_id=config_entry_2.entry_id
)
await hass.async_block_till_done()

assert not device_registry.async_get(device_entry.id)
# The device is removed, both entities are now removed
assert not entity_registry.async_is_registered(entry_1.entity_id)
assert not entity_registry.async_is_registered(entry_2.entity_id)
# Entities which are not tied to a config entry in the device should not be removed
assert entity_registry.async_is_registered(entry_1.entity_id)
assert entity_registry.async_is_registered(entry_2.entity_id)
# Check the device link is set to None
assert entity_registry.async_get(entry_1.entity_id).device_id is None
assert entity_registry.async_get(entry_2.entity_id).device_id is None


async def test_remove_config_subentry_from_device_removes_entities(
Expand Down Expand Up @@ -1921,12 +1924,12 @@ async def test_remove_config_subentry_from_device_removes_entities_2(
await hass.async_block_till_done()

assert device_registry.async_get(device_entry.id)
# Entities with a config subentry not in the device are not removed
assert entity_registry.async_is_registered(entry_1.entity_id)
# Entities with a config subentry not in the device are removed
assert not entity_registry.async_is_registered(entry_2.entity_id)
assert not entity_registry.async_is_registered(entry_3.entity_id)
assert entity_registry.async_is_registered(entry_2.entity_id)
assert entity_registry.async_is_registered(entry_3.entity_id)

# Remove the second config subentry from the device
# Remove the second config subentry from the device, this removes the device
device_registry.async_update_device(
device_entry.id,
remove_config_entry_id=config_entry_1.entry_id,
Expand All @@ -1935,10 +1938,14 @@ async def test_remove_config_subentry_from_device_removes_entities_2(
await hass.async_block_till_done()

assert not device_registry.async_get(device_entry.id)
# All entities are now removed
assert not entity_registry.async_is_registered(entry_1.entity_id)
assert not entity_registry.async_is_registered(entry_2.entity_id)
assert not entity_registry.async_is_registered(entry_3.entity_id)
# Entities with a config subentry not in the device are not removed
assert entity_registry.async_is_registered(entry_1.entity_id)
assert entity_registry.async_is_registered(entry_2.entity_id)
assert entity_registry.async_is_registered(entry_3.entity_id)
# Check the device link is set to None
assert entity_registry.async_get(entry_1.entity_id).device_id is None
assert entity_registry.async_get(entry_2.entity_id).device_id is None
assert entity_registry.async_get(entry_3.entity_id).device_id is None


async def test_update_device_race(
Expand Down
Loading