1
0
mirror of https://github.com/home-assistant/core.git synced 2026-04-02 00:20:30 +01:00

Add diagnostics to Anthropic integration (#166739)

This commit is contained in:
Denis Shulyaka
2026-03-31 22:35:09 +03:00
committed by GitHub
parent 3ba985f771
commit 962d5386c7
4 changed files with 196 additions and 1 deletions

View File

@@ -0,0 +1,64 @@
"""Diagnostics support for Anthropic."""
from __future__ import annotations
from typing import TYPE_CHECKING, Any
from anthropic import __title__, __version__
from homeassistant.components.diagnostics import async_redact_data
from homeassistant.const import CONF_API_KEY
from homeassistant.helpers import entity_registry as er
from .const import (
CONF_PROMPT,
CONF_WEB_SEARCH_CITY,
CONF_WEB_SEARCH_COUNTRY,
CONF_WEB_SEARCH_REGION,
CONF_WEB_SEARCH_TIMEZONE,
)
if TYPE_CHECKING:
from homeassistant.core import HomeAssistant
from . import AnthropicConfigEntry
TO_REDACT = {
CONF_API_KEY,
CONF_PROMPT,
CONF_WEB_SEARCH_CITY,
CONF_WEB_SEARCH_REGION,
CONF_WEB_SEARCH_COUNTRY,
CONF_WEB_SEARCH_TIMEZONE,
}
async def async_get_config_entry_diagnostics(
hass: HomeAssistant, entry: AnthropicConfigEntry
) -> dict[str, Any]:
"""Return diagnostics for a config entry."""
return {
"client": f"{__title__}=={__version__}",
"title": entry.title,
"entry_id": entry.entry_id,
"entry_version": f"{entry.version}.{entry.minor_version}",
"state": entry.state.value,
"data": async_redact_data(entry.data, TO_REDACT),
"options": async_redact_data(entry.options, TO_REDACT),
"subentries": {
subentry.subentry_id: {
"title": subentry.title,
"subentry_type": subentry.subentry_type,
"data": async_redact_data(subentry.data, TO_REDACT),
}
for subentry in entry.subentries.values()
},
"entities": {
entity_entry.entity_id: entity_entry.extended_dict
for entity_entry in er.async_entries_for_config_entry(
er.async_get(hass), entry.entry_id
)
},
}

View File

@@ -46,7 +46,7 @@ rules:
test-coverage: done
# Gold
devices: done
diagnostics: todo
diagnostics: done
discovery-update-info:
status: exempt
comment: |

View File

@@ -0,0 +1,87 @@
# serializer version: 1
# name: test_entry_diagnostics
dict({
'data': dict({
'api_key': '**REDACTED**',
}),
'entities': dict({
'ai_task.claude_ai_task': dict({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': None,
'categories': dict({
}),
'device_class': None,
'disabled_by': None,
'entity_category': None,
'entity_id': 'ai_task.claude_ai_task',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'labels': list([
]),
'name': None,
'options': dict({
'conversation': dict({
'should_expose': False,
}),
}),
'original_device_class': None,
'original_icon': None,
'original_name': None,
'platform': 'anthropic',
'translation_key': 'ai_task_data',
}),
'conversation.claude_conversation': dict({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': None,
'categories': dict({
}),
'device_class': None,
'disabled_by': None,
'entity_category': None,
'entity_id': 'conversation.claude_conversation',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'labels': list([
]),
'name': None,
'options': dict({
'conversation': dict({
'should_expose': False,
}),
}),
'original_device_class': None,
'original_icon': None,
'original_name': None,
'platform': 'anthropic',
'translation_key': 'conversation',
}),
}),
'entry_version': '2.3',
'options': dict({
}),
'state': 'loaded',
'subentries': list([
dict({
'data': dict({
}),
'subentry_type': 'conversation',
'title': 'Claude conversation',
}),
dict({
'data': dict({
}),
'subentry_type': 'ai_task_data',
'title': 'Claude AI Task',
}),
]),
'title': 'Claude',
})
# ---

View File

@@ -0,0 +1,44 @@
"""Test Anthropic diagnostics."""
from syrupy.assertion import SnapshotAssertion
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry
from tests.components.diagnostics import get_diagnostics_for_config_entry
from tests.typing import ClientSessionGenerator
async def test_entry_diagnostics(
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
mock_config_entry: MockConfigEntry,
mock_init_component: None,
snapshot: SnapshotAssertion,
) -> None:
"""Test config entry diagnostics."""
diagnostics = await get_diagnostics_for_config_entry(
hass, hass_client, mock_config_entry
)
# Remove non-deterministic values from diagnostics.
assert diagnostics.pop("client").startswith("anthropic==")
diagnostics.pop("entry_id")
subentries = diagnostics.pop("subentries")
diagnostics["subentries"] = [
subentry for subentry_id, subentry in subentries.items()
]
for entity_id, entity in diagnostics["entities"].copy().items():
for key in (
"config_entry_id",
"config_subentry_id",
"created_at",
"device_id",
"id",
"modified_at",
"unique_id",
):
if key in entity:
entity.pop(key)
diagnostics["entities"][entity_id] = entity
assert diagnostics == snapshot