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:
64
homeassistant/components/anthropic/diagnostics.py
Normal file
64
homeassistant/components/anthropic/diagnostics.py
Normal 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
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -46,7 +46,7 @@ rules:
|
|||||||
test-coverage: done
|
test-coverage: done
|
||||||
# Gold
|
# Gold
|
||||||
devices: done
|
devices: done
|
||||||
diagnostics: todo
|
diagnostics: done
|
||||||
discovery-update-info:
|
discovery-update-info:
|
||||||
status: exempt
|
status: exempt
|
||||||
comment: |
|
comment: |
|
||||||
|
|||||||
87
tests/components/anthropic/snapshots/test_diagnostics.ambr
Normal file
87
tests/components/anthropic/snapshots/test_diagnostics.ambr
Normal 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',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
44
tests/components/anthropic/test_diagnostics.py
Normal file
44
tests/components/anthropic/test_diagnostics.py
Normal 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
|
||||||
Reference in New Issue
Block a user