From 72ca4c89f09b5cedb87344441606f03dce73fdac Mon Sep 17 00:00:00 2001 From: Crocmagnon Date: Mon, 5 Oct 2026 13:07:28 +0200 Subject: [PATCH] Filter removed LLM APIs when reconfiguring OVHcloud AI Endpoints (#184249) --- .../ovhcloud_ai_endpoints/config_flow.py | 13 +++-- .../ovhcloud_ai_endpoints/test_config_flow.py | 55 +++++++++++++++++++ 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/ovhcloud_ai_endpoints/config_flow.py b/homeassistant/components/ovhcloud_ai_endpoints/config_flow.py index 6a8d38f7f3c0..b25757d470fd 100644 --- a/homeassistant/components/ovhcloud_ai_endpoints/config_flow.py +++ b/homeassistant/components/ovhcloud_ai_endpoints/config_flow.py @@ -187,6 +187,14 @@ class ConversationFlowHandler(ConfigSubentryFlow): SelectOptionDict(label=api.name, value=api.id) for api in llm.async_get_apis(self.hass) ] + valid_api_ids = {api["value"] for api in hass_apis} + selected_apis = [ + api + for api in existing.get( + CONF_LLM_HASS_API, RECOMMENDED_CONVERSATION_OPTIONS[CONF_LLM_HASS_API] + ) + if api in valid_api_ids + ] return self.async_show_form( step_id="reconfigure", data_schema=probatio.Schema( @@ -202,10 +210,7 @@ class ConversationFlowHandler(ConfigSubentryFlow): ): TemplateSelector(), probatio.Optional( CONF_LLM_HASS_API, - default=existing.get( - CONF_LLM_HASS_API, - RECOMMENDED_CONVERSATION_OPTIONS[CONF_LLM_HASS_API], - ), + default=selected_apis, ): SelectSelector( SelectSelectorConfig(options=hass_apis, multiple=True) ), diff --git a/tests/components/ovhcloud_ai_endpoints/test_config_flow.py b/tests/components/ovhcloud_ai_endpoints/test_config_flow.py index c342c96378a4..6b8d7bece76d 100644 --- a/tests/components/ovhcloud_ai_endpoints/test_config_flow.py +++ b/tests/components/ovhcloud_ai_endpoints/test_config_flow.py @@ -474,6 +474,61 @@ async def test_reconfigure_conversation_agent( assert subentry.data[CONF_MODEL] == "Meta-Llama-3_3-70B-Instruct" +@pytest.mark.parametrize( + ("stored_apis", "expected_apis"), + [ + pytest.param(["assist"], ["assist"], id="valid-api"), + pytest.param(["mcp-deleted-entry"], [], id="removed-api"), + pytest.param( + ["assist", "mcp-deleted-entry"], ["assist"], id="valid-and-removed-api" + ), + ], +) +async def test_reconfigure_conversation_agent_filters_removed_llm_api( + hass: HomeAssistant, + mock_openai_client: AsyncMock, + mock_config_entry: MockConfigEntry, + stored_apis: list[str], + expected_apis: list[str], +) -> None: + """Test reconfiguration drops unavailable LLM APIs from the form default.""" + await setup_integration(hass, mock_config_entry, mock_openai_client) + + subentry = next(iter(mock_config_entry.subentries.values())) + hass.config_entries.async_update_subentry( + mock_config_entry, + subentry, + data={**subentry.data, CONF_LLM_HASS_API: stored_apis}, + ) + await hass.async_block_till_done() + + result = await mock_config_entry.start_subentry_reconfigure_flow( + hass, subentry.subentry_id + ) + assert result["type"] is FlowResultType.FORM + assert result["step_id"] == "reconfigure" + + schema = result["data_schema"].schema + key = next(k for k in schema if k == CONF_LLM_HASS_API) + assert [option["value"] for option in schema[key].config["options"]] == ["assist"] + assert key.default() == expected_apis + + # An unchanged form submission must pass the selector's validation. + user_input = result["data_schema"]( + {CONF_PROMPT: subentry.data[CONF_PROMPT], CONF_LLM_HASS_API: key.default()} + ) + result = await hass.config_entries.subentries.async_configure( + result["flow_id"], user_input + ) + + assert result["type"] is FlowResultType.ABORT + assert result["reason"] == "reconfigure_successful" + updated_subentry = mock_config_entry.subentries[subentry.subentry_id] + assert updated_subentry.data[CONF_LLM_HASS_API] == expected_apis + assert updated_subentry.data[CONF_PROMPT] == subentry.data[CONF_PROMPT] + assert updated_subentry.data[CONF_MODEL] == subentry.data[CONF_MODEL] + + async def test_reconfigure_conversation_agent_clears_llm_api( hass: HomeAssistant, mock_openai_client: AsyncMock,