Skip to content

Commit 5c5ac79

Browse files
Patch76claude
andcommitted
fix: surface ha_deep_search scene-fetch partial failures + scenes bucket in response
Addresses kingpanther13's PR homeassistant-ai#1168 review Boy-Scout finding on silent failures in the deep_search scene branch, plus two latent bugs the DEEP_SEARCH_KEYS test gap had been hiding: 1. final_results dict was missing the 'scenes' key — any scene match reaching pagination would KeyError on final_results['scenes'].append. Added the missing initialization. 2. response dict didn't include the 'scenes' field at all. Made it conditional on 'scene' in search_types, mirroring the dashboards pattern. 3. Scene Attempt-C fetch tracked failed_count and a budget-exhaustion skipped count locally but never surfaced them. Now promoted to outer scope and merged into response as 'partial: True' plus a 'partial_reason' string when either count is non-zero. Pre-existing in the script branch; KP13 asked for it at least in the new scene branch (this PR's scope). The tuning hint in the partial_reason references the configurable HAMCP_SCENE_CONFIG_TIME_BUDGET env var so callers know how to raise the budget if the wall-clock keeps tripping. ruff + mypy clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent ac2c213 commit 5c5ac79

1 file changed

Lines changed: 27 additions & 3 deletions

File tree

src/ha_mcp/tools/smart_search.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,6 +1185,8 @@ async def _fetch_script_config(
11851185
# uses the same shape today; treat them as parallel implementations
11861186
# that can diverge if either domain's listing primitive lands later.
11871187
# ================================================================
1188+
scene_fetch_failed_count = 0
1189+
scene_fetch_skipped_count = 0
11881190
if "scene" in search_types:
11891191
scene_entities = [
11901192
e
@@ -1322,12 +1324,15 @@ async def _fetch_scene_config(
13221324
time.perf_counter() - budget_start
13231325
> SCENE_CONFIG_TIME_BUDGET
13241326
):
1325-
skipped = total_to_fetch - fetched_count - failed_count
1327+
scene_fetch_skipped_count = (
1328+
total_to_fetch - fetched_count - failed_count
1329+
)
13261330
logger.warning(
13271331
f"Scene config fetch budget exhausted "
13281332
f"({SCENE_CONFIG_TIME_BUDGET}s). "
13291333
f"Fetched {fetched_count}/{total_to_fetch} "
1330-
f"({failed_count} failed), skipped {skipped} scenes."
1334+
f"({failed_count} failed), "
1335+
f"skipped {scene_fetch_skipped_count} scenes."
13311336
)
13321337
break
13331338
batch = sids_to_fetch[i : i + INDIVIDUAL_FETCH_BATCH_SIZE]
@@ -1340,6 +1345,7 @@ async def _fetch_scene_config(
13401345
fetched_count += 1
13411346
else:
13421347
failed_count += 1
1348+
scene_fetch_failed_count = failed_count
13431349

13441350
# Phase 3: Score scenes
13451351
for (
@@ -1565,6 +1571,7 @@ async def search_dashboard(
15651571
final_results: dict[str, list[dict[str, Any]]] = {
15661572
"automations": [],
15671573
"scripts": [],
1574+
"scenes": [],
15681575
"helpers": [],
15691576
"dashboards": [],
15701577
}
@@ -1590,10 +1597,27 @@ async def search_dashboard(
15901597
"search_types": search_types,
15911598
}
15921599

1593-
# Only include dashboards key when dashboard search was requested
1600+
# Only include scenes/dashboards keys when those searches were requested
1601+
if "scene" in search_types:
1602+
response["scenes"] = final_results["scenes"]
15941603
if "dashboard" in search_types:
15951604
response["dashboards"] = final_results["dashboards"]
15961605

1606+
# Surface partial results from the scene Attempt-C fetch so the
1607+
# caller can distinguish "no scene matched" from "matches may be
1608+
# missing because some configs failed or timed out". Only set
1609+
# ``partial: True`` when something actually went wrong; downstream
1610+
# consumers should treat absence as success.
1611+
if scene_fetch_failed_count or scene_fetch_skipped_count:
1612+
response["partial"] = True
1613+
response["partial_reason"] = (
1614+
f"Scene config fetch incomplete: "
1615+
f"{scene_fetch_failed_count} failed, "
1616+
f"{scene_fetch_skipped_count} skipped (time budget). "
1617+
f"Some scene matches may be missing config data; tune "
1618+
f"HAMCP_SCENE_CONFIG_TIME_BUDGET to raise the budget."
1619+
)
1620+
15971621
return response
15981622

15991623
except Exception as e:

0 commit comments

Comments
 (0)