ha-mcp-dev 7.6.0.dev617__tar.gz → 7.6.0.dev618__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.6.0.dev617/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.6.0.dev618}/PKG-INFO +1 -1
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/pyproject.toml +1 -1
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/best_practice_checker.py +42 -7
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/LICENSE +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/MANIFEST.in +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/README.md +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/setup.cfg +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/__main__.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/_pypi_marker +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/_version.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/auth/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/auth/consent_form.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/auth/provider.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/backup_manager.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/client/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/client/rest_client.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/client/supervisor_client.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/client/websocket_client.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/client/websocket_listener.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/config.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/errors.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/policy/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/policy/approval_queue.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/policy/evaluator.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/policy/handlers.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/policy/middleware.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/policy/model.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/policy/persistence.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/policy/value_sources.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/py.typed +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/.github/pull_request_template.md +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/yaml-only-integrations.md +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/server.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/settings_ui.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/smoke_test.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/stdio_settings_sidecar.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/auto_backup.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/backup.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/device_control.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/enhanced.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/helpers.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/reference_validator.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/registry.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/smart_search.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_addons.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_areas.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_blueprints.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_bug_report.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_calendar.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_camera.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_categories.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_code.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_config_automations.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_config_entry_flow.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_energy.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_entities.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_filesystem.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_groups.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_hacs.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_history.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_integrations.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_labels.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_registry.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_resources.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_search.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_service.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_services.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_system.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_todo.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_traces.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_updates.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_utility.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_zones.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/util_helpers.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/transforms/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/transforms/categorized_search.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/utils/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/utils/config_hash.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/utils/data_paths.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/utils/domain_handlers.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/utils/fuzzy_search.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/utils/operation_manager.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/utils/python_sandbox.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/utils/usage_logger.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/tests/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/tests/test_constants.py +0 -0
- {ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/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.6.0.
|
|
7
|
+
version = "7.6.0.dev618"
|
|
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.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/best_practice_checker.py
RENAMED
|
@@ -78,11 +78,34 @@ _RE_STATE_IN = re.compile(r"states\s*\([^)]+\)\s+in\s+[\[(]")
|
|
|
78
78
|
# Unsafe direct state access: states.sensor.x.state
|
|
79
79
|
_RE_DIRECT_STATE = re.compile(r"\bstates\.\w+\.\w+\.state\b")
|
|
80
80
|
# Duration/recency checks via last_changed or last_updated arithmetic.
|
|
81
|
-
#
|
|
82
|
-
#
|
|
81
|
+
# Catches the shapes that compute "how long since X changed", all of which map
|
|
82
|
+
# to the native ``for:`` field:
|
|
83
|
+
# now() - X.last_changed (forward subtraction)
|
|
84
|
+
# X.last_changed (<|<=|>|>=) now() - <delta> (reversed; the subtraction is
|
|
85
|
+
# required — a bare ``X.last_changed < now()`` is *always* true and carries
|
|
86
|
+
# no duration, so it is intentionally NOT flagged: ``for:`` cannot express it)
|
|
87
|
+
# now() (<|<=|>|>=) X.last_changed + <delta> (now() on the left)
|
|
88
|
+
# X.last_changed + <delta> (<|<=|>|>=) now() (delta added to the attribute)
|
|
89
|
+
# now().timestamp() - X.last_changed.timestamp() (epoch subtraction)
|
|
90
|
+
# as_timestamp(now()) - as_timestamp(X.last_changed) (function form)
|
|
91
|
+
# as_timestamp(now()) - X.last_changed | as_timestamp (filter form)
|
|
92
|
+
# Every alternation requires a dotted qualifier ending on a word boundary, so
|
|
93
|
+
# bare Jinja variables literally named ``last_changed`` and longer look-alike
|
|
94
|
+
# attributes (``last_changed_at``) are not falsely flagged; a leading ``word.``
|
|
95
|
+
# (``trigger.``, ``states.sensor.x.``) is the minimum.
|
|
96
|
+
# Intentionally NOT matched (heuristic limits, low value): the reversed
|
|
97
|
+
# as_timestamp operand order, the reversed ``.timestamp()`` order, and
|
|
98
|
+
# ``state_attr(e, 'last_changed')`` / ``states('e').last_changed`` — the latter
|
|
99
|
+
# two are not valid ways to read a state's ``last_changed`` in HA anyway. These
|
|
100
|
+
# fall through to the generic template fallback in condition/trigger positions.
|
|
83
101
|
_RE_DURATION_MATH = re.compile(
|
|
84
102
|
r"\bnow\(\)\s*-\s*(?:\w+\.)+last_(?:changed|updated)\b"
|
|
85
|
-
r"|\b(?:\w+\.)+last_(?:changed|updated)\s
|
|
103
|
+
r"|\b(?:\w+\.)+last_(?:changed|updated)\b\s*[<>]=?\s*now\(\)\s*-"
|
|
104
|
+
r"|\bnow\(\)\s*[<>]=?\s*(?:\w+\.)+last_(?:changed|updated)\b\s*\+"
|
|
105
|
+
r"|\b(?:\w+\.)+last_(?:changed|updated)\b\s*\+\s*[^<>{}]+?[<>]=?\s*now\(\)"
|
|
106
|
+
r"|\bnow\(\)\.timestamp\(\)\s*-\s*(?:\w+\.)+last_(?:changed|updated)\.timestamp\(\)"
|
|
107
|
+
r"|\bas_timestamp\(\s*now\(\)\s*\)\s*-\s*as_timestamp\([^)]*\.last_(?:changed|updated)\b"
|
|
108
|
+
r"|\bas_timestamp\(\s*now\(\)\s*\)\s*-\s*(?:\w+\.)+last_(?:changed|updated)\b\s*\|\s*as_timestamp\b"
|
|
86
109
|
)
|
|
87
110
|
# Motion entity pattern
|
|
88
111
|
_RE_MOTION = re.compile(r"binary_sensor\.\w*motion", re.IGNORECASE)
|
|
@@ -220,7 +243,15 @@ def _check_template_string(
|
|
|
220
243
|
initial_count = len(warnings)
|
|
221
244
|
label = position.capitalize()
|
|
222
245
|
|
|
223
|
-
|
|
246
|
+
# Duration/recency math (e.g. `(now() - X.last_changed).total_seconds() > 300`)
|
|
247
|
+
# also contains a numeric comparison, so it matches `_RE_NUMERIC_CMP` too. But its
|
|
248
|
+
# correct native replacement is the `for:` field, NOT `numeric_state`. Suppress the
|
|
249
|
+
# numeric_state suggestion when duration math is present so the user isn't handed
|
|
250
|
+
# two conflicting native alternatives for one template (the duration warning below
|
|
251
|
+
# fires instead).
|
|
252
|
+
duration_match = _RE_DURATION_MATH.search(template)
|
|
253
|
+
|
|
254
|
+
if _RE_NUMERIC_CMP.search(template) and not duration_match:
|
|
224
255
|
warnings.append(
|
|
225
256
|
f"{label} uses template with float/int comparison — use native "
|
|
226
257
|
f"`numeric_state` {position} instead "
|
|
@@ -280,7 +311,7 @@ def _check_template_string(
|
|
|
280
311
|
"function instead (returns 'unknown' if missing rather than raising)."
|
|
281
312
|
+ _ref(skill_prefix, "template-guidelines.md#common-patterns")
|
|
282
313
|
)
|
|
283
|
-
if
|
|
314
|
+
if duration_match:
|
|
284
315
|
warnings.append(
|
|
285
316
|
f"{label} uses template for duration/recency check "
|
|
286
317
|
"(`now() - X.last_changed/last_updated`) — use the native `for:` field "
|
|
@@ -502,7 +533,11 @@ def _check_triggers(
|
|
|
502
533
|
vt = trigger.get("value_template", "")
|
|
503
534
|
if isinstance(vt, str):
|
|
504
535
|
initial = len(warnings)
|
|
505
|
-
|
|
536
|
+
# See `_check_template_string`: duration math also trips the numeric
|
|
537
|
+
# comparison detector, but maps to `for:`, not `numeric_state`. Suppress
|
|
538
|
+
# the numeric_state suggestion when duration math is present.
|
|
539
|
+
duration_match = _RE_DURATION_MATH.search(vt)
|
|
540
|
+
if _RE_NUMERIC_CMP.search(vt) and not duration_match:
|
|
506
541
|
warnings.append(
|
|
507
542
|
"Trigger uses template with float/int comparison — "
|
|
508
543
|
"use native `numeric_state` trigger instead "
|
|
@@ -522,7 +557,7 @@ def _check_triggers(
|
|
|
522
557
|
"automation-patterns.md#trigger-types",
|
|
523
558
|
)
|
|
524
559
|
)
|
|
525
|
-
if
|
|
560
|
+
if duration_match:
|
|
526
561
|
warnings.append(
|
|
527
562
|
"Trigger uses template for duration/recency check "
|
|
528
563
|
"(`now() - X.last_changed/last_updated`) — use the native "
|
|
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
|
|
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.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/AGENTS.md
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/CLAUDE.md
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/resources/skills-vendor/LICENSE
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/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
|
|
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.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_config_automations.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_config_dashboards.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_config_entry_flow.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/tools/tools_config_helpers.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/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.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/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.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp/transforms/categorized_search.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/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.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/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.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/src/ha_mcp_dev.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev617 → ha_mcp_dev-7.6.0.dev618}/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
|