ha-mcp-dev 7.5.0.dev517__tar.gz → 7.5.0.dev518__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ha_mcp_dev-7.5.0.dev517/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.5.0.dev518}/PKG-INFO +1 -1
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/pyproject.toml +1 -1
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_config_helpers.py +197 -64
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/LICENSE +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/MANIFEST.in +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/README.md +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/setup.cfg +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/__init__.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/__main__.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/_pypi_marker +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/_version.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/auth/__init__.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/auth/consent_form.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/auth/provider.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/client/__init__.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/client/rest_client.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/client/supervisor_client.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/client/websocket_client.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/client/websocket_listener.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/config.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/errors.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/py.typed +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/server.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/settings_ui.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/smoke_test.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/__init__.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/backup.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/best_practice_checker.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/device_control.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/enhanced.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/helpers.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/reference_validator.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/registry.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/smart_search.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_addons.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_areas.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_blueprints.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_bug_report.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_calendar.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_camera.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_categories.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_code.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_config_automations.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_config_entry_flow.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_energy.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_entities.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_filesystem.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_groups.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_hacs.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_history.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_integrations.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_labels.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_registry.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_resources.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_search.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_service.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_services.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_system.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_todo.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_traces.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_updates.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_utility.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_zones.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/util_helpers.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/transforms/__init__.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/transforms/categorized_search.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/utils/__init__.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/utils/config_hash.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/utils/data_paths.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/utils/domain_handlers.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/utils/fuzzy_search.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/utils/operation_manager.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/utils/python_sandbox.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/utils/usage_logger.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/tests/__init__.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/tests/test_constants.py +0 -0
- {ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/tests/test_env_manager.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ha-mcp-dev"
|
|
7
|
-
version = "7.5.0.
|
|
7
|
+
version = "7.5.0.dev518"
|
|
8
8
|
description = "Home Assistant MCP Server - Complete control of Home Assistant through MCP"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.13,<3.14"
|
{ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_config_helpers.py
RENAMED
|
@@ -1472,6 +1472,69 @@ async def _apply_registry_updates_to_entity(
|
|
|
1472
1472
|
return applied
|
|
1473
1473
|
|
|
1474
1474
|
|
|
1475
|
+
class HelperResponse(TypedDict, total=False):
|
|
1476
|
+
"""Uniform response contract for ``ha_config_set_helper`` (issue #1293).
|
|
1477
|
+
|
|
1478
|
+
Documents the legal key set across all three branches (create, update,
|
|
1479
|
+
flow). ``total=False`` because per-branch fields (entity_id, flow extras,
|
|
1480
|
+
warnings) are conditional. Consumed by ``_helper_response`` below — all
|
|
1481
|
+
return literals in this module funnel through that builder so the shape
|
|
1482
|
+
has a single point of construction.
|
|
1483
|
+
"""
|
|
1484
|
+
|
|
1485
|
+
success: bool
|
|
1486
|
+
action: str # "create" | "update"
|
|
1487
|
+
helper_type: str
|
|
1488
|
+
data: dict[str, Any]
|
|
1489
|
+
entity_id: str # absent on flow branch (use entity_ids[] for multi-entity)
|
|
1490
|
+
message: str | None
|
|
1491
|
+
warnings: list[str] # omitted when empty
|
|
1492
|
+
# Flow-helper convenience accessors (only set on the flow branch).
|
|
1493
|
+
method: str
|
|
1494
|
+
entry_id: str | None
|
|
1495
|
+
title: str | None
|
|
1496
|
+
updated: bool
|
|
1497
|
+
entity_ids: list[str]
|
|
1498
|
+
area_id: str | None
|
|
1499
|
+
labels: list[str]
|
|
1500
|
+
category: str
|
|
1501
|
+
applied: list[dict[str, Any]]
|
|
1502
|
+
|
|
1503
|
+
|
|
1504
|
+
def _helper_response(
|
|
1505
|
+
action: str,
|
|
1506
|
+
helper_type: str,
|
|
1507
|
+
*,
|
|
1508
|
+
data: dict[str, Any],
|
|
1509
|
+
entity_id: str | None = None,
|
|
1510
|
+
message: str | None = None,
|
|
1511
|
+
warnings: list[str] | None = None,
|
|
1512
|
+
**extras: Any,
|
|
1513
|
+
) -> dict[str, Any]:
|
|
1514
|
+
"""Single construction point for the ``ha_config_set_helper`` response.
|
|
1515
|
+
|
|
1516
|
+
Enforces the uniform shape from issue #1293: ``success`` → ``action`` →
|
|
1517
|
+
``helper_type`` → ``data`` → ``entity_id`` (when present) → ``message`` →
|
|
1518
|
+
flow-helper extras → ``warnings`` (only when non-empty). Returning
|
|
1519
|
+
``dict[str, Any]`` rather than ``HelperResponse`` keeps the call sites
|
|
1520
|
+
free of mypy gymnastics around the dynamic ``**extras`` keys; the
|
|
1521
|
+
TypedDict serves as the readable contract anchor instead.
|
|
1522
|
+
"""
|
|
1523
|
+
resp: dict[str, Any] = {
|
|
1524
|
+
"success": True,
|
|
1525
|
+
"action": action,
|
|
1526
|
+
"helper_type": helper_type,
|
|
1527
|
+
"data": data,
|
|
1528
|
+
}
|
|
1529
|
+
if entity_id is not None:
|
|
1530
|
+
resp["entity_id"] = entity_id
|
|
1531
|
+
resp["message"] = message
|
|
1532
|
+
resp.update(extras)
|
|
1533
|
+
if warnings:
|
|
1534
|
+
resp["warnings"] = warnings
|
|
1535
|
+
return resp
|
|
1536
|
+
|
|
1537
|
+
|
|
1475
1538
|
async def _handle_flow_helper(
|
|
1476
1539
|
client: Any,
|
|
1477
1540
|
helper_type: str,
|
|
@@ -1625,18 +1688,15 @@ async def _handle_flow_helper(
|
|
|
1625
1688
|
helper_id, # type: ignore[arg-type]
|
|
1626
1689
|
)
|
|
1627
1690
|
|
|
1691
|
+
# Cache the flow_result keys read multiple times below (issue #1293
|
|
1692
|
+
# follow-up: reduces three .get() lookups for entry_id and two for title
|
|
1693
|
+
# to one each, and makes the post-flow logic readable as a sequence of
|
|
1694
|
+
# named values rather than repeated dict access). ``.get()`` is kept —
|
|
1695
|
+
# ``create_flow_helper`` propagates HA's optional entry_id via ``.get()``
|
|
1696
|
+
# too (tools_config_entry_flow.py:L700), so a missing key must surface as
|
|
1697
|
+
# None for the ``if entry_id:`` guard below, not raise KeyError.
|
|
1628
1698
|
entry_id = flow_result.get("entry_id")
|
|
1629
|
-
|
|
1630
|
-
"success": True,
|
|
1631
|
-
"action": action,
|
|
1632
|
-
"helper_type": helper_type,
|
|
1633
|
-
"method": "config_flow",
|
|
1634
|
-
"entry_id": entry_id,
|
|
1635
|
-
"title": flow_result.get("title"),
|
|
1636
|
-
"message": flow_result.get("message"),
|
|
1637
|
-
}
|
|
1638
|
-
if action == "update":
|
|
1639
|
-
result["updated"] = True
|
|
1699
|
+
title = flow_result.get("title")
|
|
1640
1700
|
|
|
1641
1701
|
# Resolve all entities for this config entry (multi-entity helpers handled naturally).
|
|
1642
1702
|
# For create with wait=True, poll briefly for at least one entity to appear —
|
|
@@ -1680,7 +1740,22 @@ async def _handle_flow_helper(
|
|
|
1680
1740
|
else:
|
|
1681
1741
|
entities = await _get_entities_for_config_entry(client, entry_id, warnings)
|
|
1682
1742
|
entity_ids = [e["entity_id"] for e in entities if e.get("entity_id")]
|
|
1683
|
-
|
|
1743
|
+
|
|
1744
|
+
# ``data`` mirrors the HA flow_result payload for cross-action uniformity
|
|
1745
|
+
# with the create/update branches (issue #1293). ``entry_id`` and ``title``
|
|
1746
|
+
# also stay flat as convenience accessors — they are the primary identifiers
|
|
1747
|
+
# callers reach for, and remain heavily used by per-action metadata
|
|
1748
|
+
# consumers throughout the codebase. Per-entity registry-write outcomes
|
|
1749
|
+
# live in the ``applied`` flat array, not nested in ``data``, because one
|
|
1750
|
+
# flow can yield N entities with different per-entity results.
|
|
1751
|
+
extras: dict[str, Any] = {
|
|
1752
|
+
"method": "config_flow",
|
|
1753
|
+
"entry_id": entry_id,
|
|
1754
|
+
"title": title,
|
|
1755
|
+
"entity_ids": entity_ids,
|
|
1756
|
+
}
|
|
1757
|
+
if action == "update":
|
|
1758
|
+
extras["updated"] = True
|
|
1684
1759
|
|
|
1685
1760
|
# Apply registry updates (area_id / labels / category) to every entity.
|
|
1686
1761
|
# Use `is not None` so an explicit empty value (area_id="" or labels=[])
|
|
@@ -1703,17 +1778,21 @@ async def _handle_flow_helper(
|
|
|
1703
1778
|
)
|
|
1704
1779
|
)
|
|
1705
1780
|
if area_id is not None:
|
|
1706
|
-
|
|
1781
|
+
extras["area_id"] = area_id if area_id else None
|
|
1707
1782
|
if labels_list is not None:
|
|
1708
|
-
|
|
1783
|
+
extras["labels"] = labels_list
|
|
1709
1784
|
if category:
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1785
|
+
extras["category"] = category
|
|
1786
|
+
extras["applied"] = applied_per_entity
|
|
1787
|
+
|
|
1788
|
+
return _helper_response(
|
|
1789
|
+
action,
|
|
1790
|
+
helper_type,
|
|
1791
|
+
data={"entry_id": entry_id, "title": title},
|
|
1792
|
+
message=flow_result.get("message"),
|
|
1793
|
+
warnings=warnings,
|
|
1794
|
+
**extras,
|
|
1795
|
+
)
|
|
1717
1796
|
|
|
1718
1797
|
|
|
1719
1798
|
def _format_schedule_days(
|
|
@@ -2660,6 +2739,12 @@ def register_config_helper_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
|
|
|
2660
2739
|
if not entity_id and helper_data.get("id"):
|
|
2661
2740
|
entity_id = f"{helper_type}.{helper_data['id']}"
|
|
2662
2741
|
|
|
2742
|
+
# Issue #1293: collect warnings in a top-level list rather
|
|
2743
|
+
# than nest them in the payload dict. Aligns this branch
|
|
2744
|
+
# with the flow-helper path and lets callers do
|
|
2745
|
+
# ``result.get("warnings", [])`` uniformly.
|
|
2746
|
+
warnings: list[str] = []
|
|
2747
|
+
|
|
2663
2748
|
# Wait for entity to be properly registered before proceeding
|
|
2664
2749
|
wait_bool = coerce_bool_param(wait, "wait", default=True)
|
|
2665
2750
|
if wait_bool and entity_id:
|
|
@@ -2668,11 +2753,11 @@ def register_config_helper_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
|
|
|
2668
2753
|
client, entity_id
|
|
2669
2754
|
)
|
|
2670
2755
|
if not registered:
|
|
2671
|
-
|
|
2756
|
+
warnings.append(
|
|
2672
2757
|
f"Helper created but {entity_id} not yet queryable. It may take a moment to become available."
|
|
2673
2758
|
)
|
|
2674
2759
|
except Exception as e:
|
|
2675
|
-
|
|
2760
|
+
warnings.append(
|
|
2676
2761
|
f"Helper created but verification failed: {e}"
|
|
2677
2762
|
)
|
|
2678
2763
|
|
|
@@ -2691,6 +2776,11 @@ def register_config_helper_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
|
|
|
2691
2776
|
update_message
|
|
2692
2777
|
)
|
|
2693
2778
|
if update_result.get("success"):
|
|
2779
|
+
# Mirror the update branch's icon propagation
|
|
2780
|
+
# (line ~3343) so the create response's ``data``
|
|
2781
|
+
# carries the same registry-write echo set.
|
|
2782
|
+
if icon is not None:
|
|
2783
|
+
helper_data["icon"] = icon if icon else None
|
|
2694
2784
|
if area_id is not None:
|
|
2695
2785
|
helper_data["area_id"] = area_id if area_id else None
|
|
2696
2786
|
if labels is not None:
|
|
@@ -2702,29 +2792,39 @@ def register_config_helper_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
|
|
|
2702
2792
|
if isinstance(error_detail, dict)
|
|
2703
2793
|
else str(error_detail)
|
|
2704
2794
|
)
|
|
2705
|
-
|
|
2795
|
+
warnings.append(
|
|
2706
2796
|
f"Helper created but entity registry update failed: {error_msg}"
|
|
2707
2797
|
)
|
|
2708
2798
|
|
|
2709
|
-
# Apply category via shared helper (consistent with automations/scripts)
|
|
2799
|
+
# Apply category via shared helper (consistent with automations/scripts).
|
|
2800
|
+
# Issue #1293: route the success/failure through ``cat_result`` so any
|
|
2801
|
+
# ``category_warning`` lands in the top-level ``warnings`` list instead
|
|
2802
|
+
# of leaking nested into ``helper_data``. Mirrors the precedent in
|
|
2803
|
+
# ``_handle_flow_helper`` (the ``cat_result`` block near the end of
|
|
2804
|
+
# ``_apply_registry_updates_to_entity``).
|
|
2710
2805
|
if category and entity_id:
|
|
2806
|
+
cat_result: dict[str, Any] = {}
|
|
2711
2807
|
await apply_entity_category(
|
|
2712
2808
|
client,
|
|
2713
2809
|
entity_id,
|
|
2714
2810
|
category,
|
|
2715
2811
|
"helpers",
|
|
2716
|
-
|
|
2812
|
+
cat_result,
|
|
2717
2813
|
"helper",
|
|
2718
2814
|
)
|
|
2815
|
+
if "category" in cat_result:
|
|
2816
|
+
helper_data["category"] = cat_result["category"]
|
|
2817
|
+
elif "category_warning" in cat_result:
|
|
2818
|
+
warnings.append(cat_result["category_warning"])
|
|
2719
2819
|
|
|
2720
|
-
return
|
|
2721
|
-
"
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
"
|
|
2726
|
-
|
|
2727
|
-
|
|
2820
|
+
return _helper_response(
|
|
2821
|
+
"create",
|
|
2822
|
+
helper_type,
|
|
2823
|
+
data=helper_data,
|
|
2824
|
+
entity_id=entity_id,
|
|
2825
|
+
message=f"Successfully created {helper_type}: {name}",
|
|
2826
|
+
warnings=warnings,
|
|
2827
|
+
)
|
|
2728
2828
|
else:
|
|
2729
2829
|
raise_tool_error(
|
|
2730
2830
|
create_error_response(
|
|
@@ -2772,6 +2872,11 @@ def register_config_helper_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
|
|
|
2772
2872
|
}
|
|
2773
2873
|
|
|
2774
2874
|
updated_data: dict[str, Any] = {}
|
|
2875
|
+
# Issue #1293: collect warnings in a top-level list for the
|
|
2876
|
+
# update path too, mirroring create + flow-helper branches.
|
|
2877
|
+
# (No re-annotation — the create branch above already defined
|
|
2878
|
+
# ``warnings: list[str]``; mypy treats this as the same binding.)
|
|
2879
|
+
warnings = []
|
|
2775
2880
|
|
|
2776
2881
|
if helper_type == "tag":
|
|
2777
2882
|
# Tags use their own registry — no entity registry entries.
|
|
@@ -2806,14 +2911,19 @@ def register_config_helper_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
|
|
|
2806
2911
|
|
|
2807
2912
|
# Tags don't have entity registry entries, so return directly
|
|
2808
2913
|
# without wait_for_entity_registered (they're not entities).
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
"
|
|
2816
|
-
|
|
2914
|
+
# Issue #1293: same uniform builder as the sibling create/update
|
|
2915
|
+
# branches. No producer appends to ``warnings`` on the tag path
|
|
2916
|
+
# today, but ``_helper_response`` already omits the key when the
|
|
2917
|
+
# list is empty — future warnings flow through the same contract
|
|
2918
|
+
# without further plumbing.
|
|
2919
|
+
return _helper_response(
|
|
2920
|
+
"update",
|
|
2921
|
+
helper_type,
|
|
2922
|
+
data=updated_data,
|
|
2923
|
+
entity_id=entity_id,
|
|
2924
|
+
message=f"Successfully updated {helper_type}: {entity_id}",
|
|
2925
|
+
warnings=warnings,
|
|
2926
|
+
)
|
|
2817
2927
|
|
|
2818
2928
|
elif helper_type in config_store_types:
|
|
2819
2929
|
# Person and zone: look up unique_id from entity registry
|
|
@@ -3290,30 +3400,49 @@ def register_config_helper_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
|
|
|
3290
3400
|
reg_result = await client.send_websocket_message(
|
|
3291
3401
|
registry_update
|
|
3292
3402
|
)
|
|
3293
|
-
if
|
|
3403
|
+
if reg_result.get("success"):
|
|
3404
|
+
# Issue #1293: mirror the create branch by propagating the
|
|
3405
|
+
# registry writes into ``updated_data`` so the response's
|
|
3406
|
+
# ``data`` reflects the post-update state.
|
|
3407
|
+
if icon is not None:
|
|
3408
|
+
updated_data["icon"] = icon if icon else None
|
|
3409
|
+
if area_id is not None:
|
|
3410
|
+
updated_data["area_id"] = area_id if area_id else None
|
|
3411
|
+
if labels is not None:
|
|
3412
|
+
updated_data["labels"] = labels
|
|
3413
|
+
else:
|
|
3294
3414
|
error_detail = reg_result.get("error", {})
|
|
3295
3415
|
error_msg = (
|
|
3296
3416
|
error_detail.get("message", "Unknown error")
|
|
3297
3417
|
if isinstance(error_detail, dict)
|
|
3298
3418
|
else str(error_detail)
|
|
3299
3419
|
)
|
|
3300
|
-
logger.warning
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3420
|
+
# No ``logger.warning`` here — the create-branch and
|
|
3421
|
+
# flow-helper registry-update failure paths surface this
|
|
3422
|
+
# via ``warnings.append`` only, and the response carries
|
|
3423
|
+
# the message to the caller in the top-level ``warnings``
|
|
3424
|
+
# list. Logging again would double-report.
|
|
3425
|
+
warnings.append(
|
|
3304
3426
|
f"Config updated but entity registry update failed: {error_msg}"
|
|
3305
3427
|
)
|
|
3306
3428
|
|
|
3307
|
-
# Apply category via shared helper
|
|
3429
|
+
# Apply category via shared helper. Issue #1293: route through
|
|
3430
|
+
# ``cat_result`` so any ``category_warning`` lands in the top-level
|
|
3431
|
+
# ``warnings`` list instead of nested in ``updated_data``.
|
|
3308
3432
|
if category:
|
|
3433
|
+
cat_result = {}
|
|
3309
3434
|
await apply_entity_category(
|
|
3310
3435
|
client,
|
|
3311
3436
|
entity_id,
|
|
3312
3437
|
category,
|
|
3313
3438
|
"helpers",
|
|
3314
|
-
|
|
3439
|
+
cat_result,
|
|
3315
3440
|
"helper",
|
|
3316
3441
|
)
|
|
3442
|
+
if "category" in cat_result:
|
|
3443
|
+
updated_data["category"] = cat_result["category"]
|
|
3444
|
+
elif "category_warning" in cat_result:
|
|
3445
|
+
warnings.append(cat_result["category_warning"])
|
|
3317
3446
|
|
|
3318
3447
|
else:
|
|
3319
3448
|
# Fallback for unknown/future helper types: entity registry update only
|
|
@@ -3347,39 +3476,43 @@ def register_config_helper_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
|
|
|
3347
3476
|
)
|
|
3348
3477
|
)
|
|
3349
3478
|
|
|
3350
|
-
# Apply category via shared helper
|
|
3479
|
+
# Apply category via shared helper. Issue #1293: same temp-dict
|
|
3480
|
+
# routing as the simple-helper branch above.
|
|
3351
3481
|
if category:
|
|
3482
|
+
cat_result = {}
|
|
3352
3483
|
await apply_entity_category(
|
|
3353
3484
|
client,
|
|
3354
3485
|
entity_id,
|
|
3355
3486
|
category,
|
|
3356
3487
|
"helpers",
|
|
3357
|
-
|
|
3488
|
+
cat_result,
|
|
3358
3489
|
"helper",
|
|
3359
3490
|
)
|
|
3491
|
+
if "category" in cat_result:
|
|
3492
|
+
updated_data["category"] = cat_result["category"]
|
|
3493
|
+
elif "category_warning" in cat_result:
|
|
3494
|
+
warnings.append(cat_result["category_warning"])
|
|
3360
3495
|
|
|
3361
3496
|
# Wait for entity to reflect the update
|
|
3362
3497
|
wait_bool = coerce_bool_param(wait, "wait", default=True)
|
|
3363
|
-
response: dict[str, Any] = {
|
|
3364
|
-
"success": True,
|
|
3365
|
-
"action": "update",
|
|
3366
|
-
"helper_type": helper_type,
|
|
3367
|
-
"entity_id": entity_id,
|
|
3368
|
-
"updated_data": updated_data,
|
|
3369
|
-
"message": f"Successfully updated {helper_type}: {entity_id}",
|
|
3370
|
-
}
|
|
3371
3498
|
if wait_bool:
|
|
3372
3499
|
try:
|
|
3373
3500
|
registered = await wait_for_entity_registered(client, entity_id)
|
|
3374
3501
|
if not registered:
|
|
3375
|
-
|
|
3502
|
+
warnings.append(
|
|
3376
3503
|
f"Update applied but {entity_id} not yet queryable."
|
|
3377
3504
|
)
|
|
3378
3505
|
except Exception as e:
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3506
|
+
warnings.append(f"Update applied but verification failed: {e}")
|
|
3507
|
+
|
|
3508
|
+
return _helper_response(
|
|
3509
|
+
"update",
|
|
3510
|
+
helper_type,
|
|
3511
|
+
data=updated_data,
|
|
3512
|
+
entity_id=entity_id,
|
|
3513
|
+
message=f"Successfully updated {helper_type}: {entity_id}",
|
|
3514
|
+
warnings=warnings,
|
|
3515
|
+
)
|
|
3383
3516
|
|
|
3384
3517
|
# This should never be reached since action is either "create" or "update"
|
|
3385
3518
|
raise_tool_error(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/AGENTS.md
RENAMED
|
File without changes
|
{ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/CLAUDE.md
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/LICENSE
RENAMED
|
File without changes
|
{ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/resources/skills-vendor/README.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/best_practice_checker.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_config_automations.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_config_dashboards.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_config_entry_flow.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_config_scripts.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/tools/tools_voice_assistant.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/transforms/categorized_search.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/transforms/lite_docstrings.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp/utils/kill_signal_diagnostics.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp_dev.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{ha_mcp_dev-7.5.0.dev517 → ha_mcp_dev-7.5.0.dev518}/src/ha_mcp_dev.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|