diff --git a/custom_components/ha_text_ai/const.py b/custom_components/ha_text_ai/const.py index de2580a..1c660b3 100644 --- a/custom_components/ha_text_ai/const.py +++ b/custom_components/ha_text_ai/const.py @@ -1,6 +1,8 @@ """Constants for the HA text AI integration.""" from typing import Final +import voluptuous as vol from homeassistant.const import Platform +from homeassistant.helpers import config_validation as cv # Domain and platforms DOMAIN: Final = "ha_text_ai" @@ -23,7 +25,7 @@ SUPPORTED_MODELS: Final = [ "claude-3.5-sonnet", "claude-3-haiku", "anthropic/claude-3-5-haiku", - "anthropic/claude-3.5-sonnet", + "anthropic/claude-3.5-sonnet", ] # Default values @@ -188,3 +190,41 @@ SCHEMA_LIMIT: Final = "limit" EVENT_RESPONSE_RECEIVED: Final = f"{DOMAIN}_response_received" EVENT_ERROR_OCCURRED: Final = f"{DOMAIN}_error_occurred" EVENT_STATE_CHANGED: Final = f"{DOMAIN}_state_changed" + +# Service schema constants +SERVICE_SCHEMA_ASK_QUESTION = { + vol.Required("question"): cv.string, + vol.Optional("system_prompt"): cv.string, + vol.Optional("model"): vol.In(SUPPORTED_MODELS), + vol.Optional("temperature"): vol.All( + vol.Coerce(float), + vol.Range(min=MIN_TEMPERATURE, max=MAX_TEMPERATURE) + ), + vol.Optional("max_tokens"): vol.All( + vol.Coerce(int), + vol.Range(min=MIN_MAX_TOKENS, max=MAX_MAX_TOKENS) + ), + vol.Optional("priority"): cv.boolean, +} + +SERVICE_SCHEMA_GET_HISTORY = { + vol.Optional("limit", default=10): vol.All( + vol.Coerce(int), + vol.Range(min=1, max=100) + ), + vol.Optional("filter_model"): vol.In(SUPPORTED_MODELS), + vol.Optional("start_date"): cv.datetime, + vol.Optional("include_metadata"): cv.boolean, +} + +SERVICE_SCHEMA_SET_SYSTEM_PROMPT = { + vol.Required("prompt"): cv.string, +} + +# VSE GPT specific constants +VSE_GPT_ENDPOINT = "https://api.vsegpt.ru" +VSE_GPT_API_VERSION = "2023-06-01" +VSE_GPT_MODELS = [ + "anthropic/claude-3-5-haiku", + "anthropic/claude-3.5-sonnet", +] diff --git a/custom_components/ha_text_ai/coordinator.py b/custom_components/ha_text_ai/coordinator.py index 79cdf88..d7fd6bc 100644 --- a/custom_components/ha_text_ai/coordinator.py +++ b/custom_components/ha_text_ai/coordinator.py @@ -12,7 +12,6 @@ from homeassistant.helpers import aiohttp_client from openai import AsyncOpenAI, APIError, AuthenticationError, RateLimitError from anthropic import AsyncAnthropic from homeassistant.core import HomeAssistant -from homeassistant.helpers import aiohttp_client from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from homeassistant.util import dt as dt_util import async_timeout @@ -30,44 +29,6 @@ _LOGGER = logging.getLogger(__name__) class HATextAICoordinator(DataUpdateCoordinator): """Class to manage fetching data from the API.""" - def __init__( - self, - hass: HomeAssistant, - api_key: str, - endpoint: str, - model: str, - temperature: float, - max_tokens: int, - request_interval: float, - session: Optional[Any] = None, - is_anthropic: bool = False, - ) -> None: - """Initialize coordinator.""" - super().__init__( - hass, - _LOGGER, - name=DOMAIN, - update_interval=timedelta(seconds=request_interval), - ) - def __init__( - self, - hass: HomeAssistant, - api_key: str, - endpoint: str, - model: str, - temperature: float, - max_tokens: int, - request_interval: float, - session: Optional[Any] = None, - is_anthropic: bool = False, - ) -> None: - """Initialize coordinator.""" - super().__init__( - hass, - _LOGGER, - name=DOMAIN, - update_interval=timedelta(seconds=request_interval), - ) def __init__( self, hass: HomeAssistant, @@ -117,8 +78,18 @@ class HATextAICoordinator(DataUpdateCoordinator): self._last_request_time = 0 self._is_anthropic = is_anthropic self._session = session or aiohttp_client.async_get_clientsession(hass) + self.client = None # Initialize client as None - self._init_client() + async def async_initialize(self) -> None: + """Initialize coordinator.""" + try: + await self._init_client() + self._is_ready = True + await self.async_refresh() + except Exception as e: + _LOGGER.error("Failed to initialize coordinator: %s", str(e)) + self._is_ready = False + self._endpoint_status = "error" async def _create_ssl_context(self): """Create an async SSL context."""