diff --git a/custom_components/openai_compatible/__init__.py b/custom_components/openai_compatible/__init__.py index 459338a..f7de9bc 100644 --- a/custom_components/openai_compatible/__init__.py +++ b/custom_components/openai_compatible/__init__.py @@ -49,6 +49,7 @@ from .const import ( CONF_TEMPERATURE, CONF_TOP_P, DEFAULT_AI_TASK_NAME, + DEFAULT_BASE_URL, DEFAULT_NAME, DEFAULT_STT_NAME, DEFAULT_TTS_NAME, @@ -489,6 +490,16 @@ async def async_migrate_entry(hass: HomeAssistant, entry: OpenAIConfigEntry) -> ) hass.config_entries.async_update_entry(entry, minor_version=7) + if entry.version == 2 and entry.minor_version == 7: + # base_url is this fork's addition, so an entry written by a build + # from before it existed has no such key, and async_setup_entry's + # lookup raises KeyError. Such an install was implicitly talking to + # OpenAI, which is what DEFAULT_BASE_URL is, so backfilling it keeps + # the endpoint it was already using. + data = dict(entry.data) + data.setdefault(CONF_BASE_URL, DEFAULT_BASE_URL) + hass.config_entries.async_update_entry(entry, data=data, minor_version=8) + LOGGER.debug( "Migration to version %s:%s successful", entry.version, entry.minor_version ) diff --git a/custom_components/openai_compatible/config_flow.py b/custom_components/openai_compatible/config_flow.py index 06575ab..4f0df15 100644 --- a/custom_components/openai_compatible/config_flow.py +++ b/custom_components/openai_compatible/config_flow.py @@ -134,7 +134,7 @@ class OpenAIConfigFlow(ConfigFlow, domain=DOMAIN): """Handle a config flow for OpenAI Conversation.""" VERSION = 2 - MINOR_VERSION = 7 + MINOR_VERSION = 8 @override async def async_step_user( diff --git a/tests/test_base_url.py b/tests/test_base_url.py index 2da5d6a..6824f89 100644 --- a/tests/test_base_url.py +++ b/tests/test_base_url.py @@ -5,7 +5,11 @@ from unittest.mock import AsyncMock, patch from homeassistant.core import HomeAssistant from pytest_homeassistant_custom_component.common import MockConfigEntry -from custom_components.openai_compatible.const import CONF_BASE_URL, DOMAIN +from custom_components.openai_compatible.const import ( + CONF_BASE_URL, + DEFAULT_BASE_URL, + DOMAIN, +) async def test_client_built_with_base_url(hass: HomeAssistant) -> None: @@ -48,3 +52,31 @@ async def test_api_key_optional(hass: HomeAssistant) -> None: await hass.async_block_till_done() assert mock_client.call_args.kwargs["api_key"] == "not-required" + + +async def test_migration_backfills_missing_base_url(hass: HomeAssistant) -> None: + """An entry stored before base_url existed must still set up. + + Entries written by an earlier build of this fork have no base_url key at + all, so anything that indexes entry.data[CONF_BASE_URL] raises KeyError + and the integration fails to load on restart. + """ + entry = MockConfigEntry( + domain=DOMAIN, + data={"api_key": "sk-test"}, + version=2, + minor_version=7, + ) + entry.add_to_hass(hass) + + with patch( + "custom_components.openai_compatible.openai.AsyncOpenAI" + ) as mock_client: + mock_client.return_value.platform_headers = lambda: {} + mock_client.return_value.with_options.return_value.models.list = AsyncMock() + assert await hass.config_entries.async_setup(entry.entry_id) + await hass.async_block_till_done() + + assert entry.data[CONF_BASE_URL] == DEFAULT_BASE_URL + assert entry.minor_version == 8 + assert mock_client.call_args.kwargs["base_url"] == DEFAULT_BASE_URL diff --git a/tests/test_config_flow.py b/tests/test_config_flow.py index 9585815..37cc3ee 100644 --- a/tests/test_config_flow.py +++ b/tests/test_config_flow.py @@ -122,7 +122,7 @@ async def test_form(hass: HomeAssistant) -> None: }, ] assert result2["version"] == 2 - assert result2["minor_version"] == 7 + assert result2["minor_version"] == 8 assert len(mock_setup_entry.mock_calls) == 1