fix: make the integration work against a Claude proxy
validate / hassfest (push) Failing after 32s
validate / hacs (push) Failing after 1m50s
test / pytest (push) Successful in 3m56s

- Treat an empty tool argument string as no parameters instead of raising
  JSONDecodeError; the proxy sends "" for tools like the timer status
  (upstream issue #3).
- Do not replay earlier web searches in the history. The chat log keeps only
  their status, and a search without results makes the model disown the
  answers it based on it and search again (upstream issue #4).
- Look up the home location for web search with the subentry's model instead
  of gpt-4o-mini, and save the options without city/region if the lookup
  fails (upstream issue #5).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
pc-heiniandClaude Opus 5.5 committed 2026-10-22 08:38:01 +02:00
1 parent 8737e5d4ec
commit 235c536cab
6 files changed
+224 -70

No files matched your search

+68
View File
@@ -1274,6 +1274,74 @@ async def test_subentry_web_search_user_location(
}
async def test_subentry_web_search_user_location_lookup_fails(
hass: HomeAssistant,
mock_config_entry,
mock_init_component,
) -> None:
"""Test the location lookup uses the subentry's model and may fail.
An endpoint that only serves other providers' models rejects the OpenAI
default; saving must still succeed with country and time zone only.
"""
subentry = next(
sub
for sub in mock_config_entry.subentries.values()
if sub.subentry_type == "conversation"
)
subentry_flow = await mock_config_entry.start_subentry_reconfigure_flow(
hass, subentry.subentry_id
)
subentry_flow = await hass.config_entries.subentries.async_configure(
subentry_flow["flow_id"],
{
CONF_RECOMMENDED: False,
CONF_PROMPT: "Speak like a pirate",
CONF_CHAT_MODEL: "claude-sonnet-5-5",
},
)
subentry_flow = await hass.config_entries.subentries.async_configure(
subentry_flow["flow_id"],
{
CONF_TEMPERATURE: 1.0,
CONF_TOP_P: RECOMMENDED_TOP_P,
CONF_MAX_TOKENS: RECOMMENDED_MAX_TOKENS,
CONF_STORE_RESPONSES: False,
},
)
await hass.async_block_till_done()
assert subentry_flow["step_id"] == "model"
hass.config.country = "DE"
hass.config.time_zone = "Europe/Berlin"
hass.states.async_set("zone.home", "0", {"latitude": 50.9, "longitude": 12.1})
with patch(
"openai.resources.responses.AsyncResponses.create",
new_callable=AsyncMock,
side_effect=BadRequestError(
response=httpx.Response(status_code=400, request=httpx.Request("POST", "")),
body=None,
message="unknown provider for model",
),
) as mock_create:
subentry_flow = await hass.config_entries.subentries.async_configure(
subentry_flow["flow_id"],
{
CONF_WEB_SEARCH: True,
CONF_WEB_SEARCH_CONTEXT_SIZE: "medium",
CONF_WEB_SEARCH_USER_LOCATION: True,
},
)
await hass.async_block_till_done()
assert mock_create.call_args.kwargs["model"] == "claude-sonnet-5-5"
assert subentry_flow["type"] is FlowResultType.ABORT
assert subentry_flow["reason"] == "reconfigure_successful"
assert CONF_WEB_SEARCH_CITY not in subentry.data
assert CONF_WEB_SEARCH_REGION not in subentry.data
assert subentry.data[CONF_WEB_SEARCH_COUNTRY] == "DE"
assert subentry.data[CONF_WEB_SEARCH_TIMEZONE] == "Europe/Berlin"
async def test_creating_ai_task_subentry(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,