mirror of
https://github.com/smkrv/ha-text-ai.git
synced 2026-07-21 22:54:00 +08:00
fix: Address code review findings for v2.4.0
- Fix 404 accepted as valid API response in config_flow validation (both ConfigFlow and OptionsFlow) - Sanitize catch-all exception in config_flow (str(e) → "unknown" error key) - Add exception chaining (from err) to ConfigEntryNotReady raise - Replace datetime.now() with dt_util.utcnow() for HA timezone convention - Add defensive raise after retry loop in api_client._make_request - Remove unused CONF_API_KEY/CONF_NAME imports from const.py - Restore google-genai dependency in manifest (required for Gemini provider)
This commit is contained in:
@@ -9,7 +9,6 @@ The HA Text AI integration.
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from datetime import datetime
|
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
@@ -22,6 +21,7 @@ from homeassistant.core import HomeAssistant, ServiceCall, SupportsResponse
|
|||||||
from homeassistant.exceptions import ConfigEntryNotReady, HomeAssistantError
|
from homeassistant.exceptions import ConfigEntryNotReady, HomeAssistantError
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
from homeassistant.helpers import aiohttp_client
|
from homeassistant.helpers import aiohttp_client
|
||||||
|
from homeassistant.util import dt as dt_util
|
||||||
|
|
||||||
from .coordinator import HATextAICoordinator
|
from .coordinator import HATextAICoordinator
|
||||||
from .api_client import APIClient
|
from .api_client import APIClient
|
||||||
@@ -140,7 +140,7 @@ async def async_setup(hass: HomeAssistant, config: Dict[str, Any]) -> bool:
|
|||||||
"model_used": call.data.get("model", ""),
|
"model_used": call.data.get("model", ""),
|
||||||
"instance": call.data["instance"],
|
"instance": call.data["instance"],
|
||||||
"question": call.data["question"],
|
"question": call.data["question"],
|
||||||
"timestamp": datetime.now().isoformat(),
|
"timestamp": dt_util.utcnow().isoformat(),
|
||||||
"success": False,
|
"success": False,
|
||||||
"error": "Service call failed"
|
"error": "Service call failed"
|
||||||
}
|
}
|
||||||
@@ -266,7 +266,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
endpoint = validate_endpoint(raw_endpoint)
|
endpoint = validate_endpoint(raw_endpoint)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
_LOGGER.error("Invalid API endpoint %s: %s", raw_endpoint, err)
|
_LOGGER.error("Invalid API endpoint %s: %s", raw_endpoint, err)
|
||||||
raise ConfigEntryNotReady(f"Invalid API endpoint: {err}")
|
raise ConfigEntryNotReady(f"Invalid API endpoint: {err}") from err
|
||||||
# API key can now be updated via options
|
# API key can now be updated via options
|
||||||
api_key = config.get(CONF_API_KEY, entry.data.get(CONF_API_KEY))
|
api_key = config.get(CONF_API_KEY, entry.data.get(CONF_API_KEY))
|
||||||
instance_name = entry.data.get(CONF_NAME, entry.entry_id)
|
instance_name = entry.data.get(CONF_NAME, entry.entry_id)
|
||||||
|
|||||||
@@ -138,6 +138,8 @@ class APIClient:
|
|||||||
raise
|
raise
|
||||||
await asyncio.sleep(2 ** attempt)
|
await asyncio.sleep(2 ** attempt)
|
||||||
|
|
||||||
|
raise HomeAssistantError("API request failed after all retries")
|
||||||
|
|
||||||
async def create(
|
async def create(
|
||||||
self,
|
self,
|
||||||
model: str,
|
model: str,
|
||||||
|
|||||||
@@ -306,7 +306,7 @@ class HATextAIConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
vol.Required(CONF_API_ENDPOINT, default=input_copy.get(CONF_API_ENDPOINT, get_default_endpoint(self._provider))): str,
|
vol.Required(CONF_API_ENDPOINT, default=input_copy.get(CONF_API_ENDPOINT, get_default_endpoint(self._provider))): str,
|
||||||
# Other fields remain the same
|
# Other fields remain the same
|
||||||
}),
|
}),
|
||||||
errors={"base": str(e)}
|
errors={"base": "unknown"}
|
||||||
)
|
)
|
||||||
|
|
||||||
# All validation passed, create the entry
|
# All validation passed, create the entry
|
||||||
@@ -378,7 +378,7 @@ class HATextAIConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
if response.status == 401:
|
if response.status == 401:
|
||||||
self._errors["base"] = "invalid_auth"
|
self._errors["base"] = "invalid_auth"
|
||||||
return False
|
return False
|
||||||
elif response.status not in [200, 404]:
|
elif response.status != 200:
|
||||||
self._errors["base"] = "cannot_connect"
|
self._errors["base"] = "cannot_connect"
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
@@ -514,7 +514,7 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
|
|||||||
if response.status == 401:
|
if response.status == 401:
|
||||||
self._errors["base"] = "invalid_auth"
|
self._errors["base"] = "invalid_auth"
|
||||||
return False
|
return False
|
||||||
elif response.status not in [200, 404]:
|
elif response.status != 200:
|
||||||
self._errors["base"] = "cannot_connect"
|
self._errors["base"] = "cannot_connect"
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ Constants for the HA text AI integration.
|
|||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
from typing import Final
|
from typing import Final
|
||||||
from homeassistant.const import Platform, CONF_API_KEY, CONF_NAME
|
from homeassistant.const import Platform
|
||||||
import logging
|
import logging
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
"loggers": ["custom_components.ha_text_ai"],
|
"loggers": ["custom_components.ha_text_ai"],
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"aiofiles>=23.0.0",
|
"aiofiles>=23.0.0",
|
||||||
"aiohttp>=3.8.0"
|
"aiohttp>=3.8.0",
|
||||||
|
"google-genai>=1.16.0"
|
||||||
],
|
],
|
||||||
"single_config_entry": false,
|
"single_config_entry": false,
|
||||||
"version": "2.4.0"
|
"version": "2.4.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user