fix: Pinned session TypeError, dead default models, get_history compat, i18n sync

- create_pinned_session built directly on aiohttp: the HA helper injects
  its own connector and raised TypeError on every setup and config flow
- session lifecycle: closed in APIClient.shutdown, on failed setup, and
  in config flow validators; allow_redirects=False everywhere so 3xx
  cannot route past the pinned resolver
- defaults: gemini-2.0-flash (shut down 2026-06-01) -> gemini-3.5-flash,
  deepseek-chat (retires 2026-07-24) -> deepseek-v4-flash
- DeepSeek V4 disable_thinking via thinking request parameter
- Gemini 3.x disable_thinking via thinking_level (MINIMAL, LOW for Pro)
- get_history limit: no forced default/max in schema, storage layer clamps
- translations: 6 locales caught up with strings.json, 2 orphan keys dropped
- README: manual install path matches zip layout, model sections updated
This commit is contained in:
SMKRV
2026-07-07 01:23:01 +03:00
parent 9d4d2d5cd1
commit bcfe69b5f7
12 changed files with 209 additions and 68 deletions
+30 -20
View File
@@ -255,23 +255,28 @@ class HATextAIConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
return False
return True
# Pinned session ensures the reachability check goes to the same
# IP that will later be used by api_client (no DNS rebinding).
session = create_pinned_session(self.hass, endpoint, resolved_ips)
headers = build_auth_headers(self._provider, user_input[CONF_API_KEY])
from .providers import get_provider_config
check_path = get_provider_config(self._provider).get("check_path", "/models")
check_url = f"{endpoint}{check_path}"
async with session.get(check_url, headers=headers) as response:
if response.status == 401:
self._errors["base"] = "invalid_auth"
return False
elif response.status != 200:
self._errors["base"] = "cannot_connect"
return False
return True
# Pinned session ensures the reachability check goes to the same
# IP that will later be used by api_client (no DNS rebinding).
session = create_pinned_session(endpoint, resolved_ips)
try:
async with session.get(
check_url, headers=headers, allow_redirects=False
) as response:
if response.status == 401:
self._errors["base"] = "invalid_auth"
return False
elif response.status != 200:
self._errors["base"] = "cannot_connect"
return False
return True
finally:
await session.close()
except Exception as err:
_LOGGER.error("API validation error: %s", str(err))
@@ -340,21 +345,26 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
if provider == API_PROVIDER_GEMINI:
return True
session = create_pinned_session(self.hass, endpoint, resolved_ips)
headers = build_auth_headers(provider, api_key)
from .providers import get_provider_config
check_path = get_provider_config(provider).get("check_path", "/models")
check_url = f"{endpoint}{check_path}"
async with session.get(check_url, headers=headers) as response:
if response.status == 401:
self._errors["base"] = "invalid_auth"
return False
elif response.status != 200:
self._errors["base"] = "cannot_connect"
return False
return True
session = create_pinned_session(endpoint, resolved_ips)
try:
async with session.get(
check_url, headers=headers, allow_redirects=False
) as response:
if response.status == 401:
self._errors["base"] = "invalid_auth"
return False
elif response.status != 200:
self._errors["base"] = "cannot_connect"
return False
return True
finally:
await session.close()
except Exception as err:
_LOGGER.error("API validation error: %s", str(err))