ha-mcp-dev 7.14.2.dev2113__tar.gz → 7.14.2.dev2115__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.14.2.dev2113/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.14.2.dev2115}/PKG-INFO +1 -1
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/pyproject.toml +1 -1
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/smart_search/_deep.py +160 -3
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_config_dashboards.py +8 -5
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_search.py +35 -2
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/LICENSE +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/MANIFEST.in +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/README.md +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/setup.cfg +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/__main__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/_pypi_marker +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/_version.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/auth/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/auth/consent_form.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/auth/provider.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/backup_manager.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/browser_landing.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/client/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/client/rest_client.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/client/supervisor_client.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/client/websocket_client.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/client/websocket_listener.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/config.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/dashboard_screenshot/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/dashboard_screenshot/capture.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/dashboard_screenshot/content.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/dashboard_screenshot/paths.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/dashboard_screenshot/provision.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/dashboard_screenshot/theme_guard.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/errors.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/llm_exposure.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/policy/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/policy/approval_queue.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/policy/evaluator.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/policy/handlers.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/policy/middleware.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/policy/model.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/policy/persistence.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/policy/value_sources.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/py.typed +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/read_only.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/.github/pull_request_template.md +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/appdaemon.md +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/blueprint-guide.md +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/scenes.md +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/yaml-only-integrations.md +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/server.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/_handlers_advanced.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/_handlers_backups.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/_handlers_fs.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/_handlers_server.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/_handlers_theme.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/_handlers_tools.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/_i18n.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/_persistence.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/_supervisor.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/_theme.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/_tools_meta.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/locales/README.md +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/locales/de.json +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/locales/en.json +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/locales/ru.json +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/locales/zh-Hans.json +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/settings.css +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/settings.html +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/settings.js +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/smoke_test.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/stdio_settings_sidecar.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/strict_bps.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/auto_backup.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/backup.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/best_practice_checker.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/component_api.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/component_config_reads.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/component_devices.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/component_registries.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/component_registry_lookup.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/config_entry_flow.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/device_control.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/enhanced.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/helpers.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/radio/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/radio/base.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/radio/matter.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/radio/thread.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/radio/zigbee.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/radio/zwave.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/reference_validator.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/registry.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/smart_search/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/smart_search/_base.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/smart_search/_config.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/smart_search/_entities.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/smart_search/_fetch.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/smart_search/_overview.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/smart_search/_scenes.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/smart_search/_scoring.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tool_search_hint_middleware.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_addons.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_areas.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_blueprints.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_bug_report.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_calendar.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_camera.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_categories.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_code.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_config_automations.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_dashboard_screenshot.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_dev.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_energy.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_entities.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_filesystem.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_groups.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_hacs.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_history.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_integrations.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_labels.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_radio.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_registry.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_resources.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_service.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_services.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_system.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_themes.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_todo.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_traces.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_updates.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_utility.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_yaml_read.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_zones.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/util_helpers.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/validation_middleware.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/transforms/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/transforms/categorized_search.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/transport_security.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/update_check.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/utils/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/utils/config_hash.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/utils/config_write_lock.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/utils/data_paths.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/utils/domain_handlers.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/utils/fuzzy_search.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/utils/operation_manager.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/utils/python_sandbox.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/utils/skill_loader.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/utils/usage_logger.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/visibility/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/visibility/enforcement.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/visibility/model.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/visibility/persistence.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/visibility/resolver.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/tests/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/tests/test_constants.py +0 -0
- {ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/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.14.2.
|
|
7
|
+
version = "7.14.2.dev2115"
|
|
8
8
|
description = "Home Assistant MCP Server - Complete control of Home Assistant through MCP"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
# Upper bound widened to <3.15 so the package installs on Home Assistant's
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/smart_search/_deep.py
RENAMED
|
@@ -9,9 +9,14 @@ from fastmcp import Context
|
|
|
9
9
|
from fastmcp.exceptions import ToolError
|
|
10
10
|
|
|
11
11
|
from ...client.rest_client import HomeAssistantAPIError
|
|
12
|
+
from ...errors import get_error_code, get_error_message
|
|
13
|
+
from ..component_api import component_supports, get_component_caps
|
|
12
14
|
from ..config_entry_flow import FLOW_HELPER_TYPES
|
|
13
15
|
from ..helpers import exception_to_structured_error, safe_info, safe_progress
|
|
14
|
-
from ..tools_config_dashboards import
|
|
16
|
+
from ..tools_config_dashboards import (
|
|
17
|
+
_dashboards_via_component,
|
|
18
|
+
fetch_dashboards_list,
|
|
19
|
+
)
|
|
15
20
|
from ..tools_integrations import fetch_entry_options_with_status
|
|
16
21
|
from ._config import (
|
|
17
22
|
AUTOMATION_CONFIG_TIME_BUDGET,
|
|
@@ -55,6 +60,40 @@ async def _scrub_results_for_enforce(
|
|
|
55
60
|
results[category] = scrub_records(items, enforce_regex)
|
|
56
61
|
|
|
57
62
|
|
|
63
|
+
# The ``lovelace/config`` messages meaning "this dashboard has no stored
|
|
64
|
+
# config" — bare (nested error shape) and as ``send_websocket_message``'s
|
|
65
|
+
# flat envelope prefixes it. Mirrors ``dashboard_screenshot/paths.py``.
|
|
66
|
+
_NO_STORED_CONFIG_MESSAGES = frozenset(
|
|
67
|
+
{"No config found.", "Command failed: No config found."}
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _is_no_stored_config(resp: dict[str, Any]) -> bool:
|
|
72
|
+
"""True when a failed ``lovelace/config`` envelope means the dashboard
|
|
73
|
+
has no stored config — an auto-generated dashboard that was never taken
|
|
74
|
+
control of — which is a clean no-match for a config scan rather than a
|
|
75
|
+
backend failure (issue #2008).
|
|
76
|
+
|
|
77
|
+
HA reports the ``config_not_found`` code for two distinct causes
|
|
78
|
+
(``homeassistant/components/lovelace/websocket.py``, ``_handle_errors``):
|
|
79
|
+
no stored config ("No config found.") and an unresolvable url_path
|
|
80
|
+
("Unknown config specified: ..."), e.g. a dashboard deleted between the
|
|
81
|
+
registry-list snapshot and this fetch. Only the former is a clean skip,
|
|
82
|
+
so the message is matched too; the latter stays a counted failure.
|
|
83
|
+
|
|
84
|
+
``send_websocket_message`` normalizes command failures to a flat envelope
|
|
85
|
+
(code top-level as ``error_code``, message as the ``error`` string); the
|
|
86
|
+
nested ``error.code``/``error.message`` shape is accepted defensively via
|
|
87
|
+
the canonical :func:`get_error_code` / :func:`get_error_message`
|
|
88
|
+
extractors, matching ``dashboard_screenshot/paths.py``'s detection of the
|
|
89
|
+
same HA error.
|
|
90
|
+
"""
|
|
91
|
+
code = resp.get("error_code") or get_error_code(resp)
|
|
92
|
+
if code != "config_not_found":
|
|
93
|
+
return False
|
|
94
|
+
return get_error_message(resp) in _NO_STORED_CONFIG_MESSAGES
|
|
95
|
+
|
|
96
|
+
|
|
58
97
|
class DeepSearchMixin(SceneSearchMixin):
|
|
59
98
|
"""deep_search orchestration + per-type automation/script/helper/dashboard/flow search."""
|
|
60
99
|
|
|
@@ -279,8 +318,11 @@ class DeepSearchMixin(SceneSearchMixin):
|
|
|
279
318
|
(
|
|
280
319
|
results["dashboards"],
|
|
281
320
|
dashboard_failed,
|
|
282
|
-
) = await self.
|
|
283
|
-
query_lower,
|
|
321
|
+
) = await self._search_dashboards_surface(
|
|
322
|
+
query_lower,
|
|
323
|
+
exact_match,
|
|
324
|
+
semaphore,
|
|
325
|
+
include_config=include_config,
|
|
284
326
|
)
|
|
285
327
|
phase_done += 1
|
|
286
328
|
await safe_progress(
|
|
@@ -896,6 +938,106 @@ class DeepSearchMixin(SceneSearchMixin):
|
|
|
896
938
|
failed_type_count += flow_failed_count
|
|
897
939
|
return results, failed_type_count
|
|
898
940
|
|
|
941
|
+
async def _search_dashboards_surface(
|
|
942
|
+
self,
|
|
943
|
+
query_lower: str,
|
|
944
|
+
exact_match: bool,
|
|
945
|
+
semaphore: asyncio.Semaphore,
|
|
946
|
+
*,
|
|
947
|
+
include_config: bool,
|
|
948
|
+
) -> tuple[list[dict[str, Any]], int]:
|
|
949
|
+
"""The dashboard bucket: component-first, legacy fallback.
|
|
950
|
+
|
|
951
|
+
Returns ``(records, failed_count)``. The component's in-process
|
|
952
|
+
``search`` frame (issue #2008) serves the exact-match, no-body shape
|
|
953
|
+
— the default ``ha_search`` call — mirroring the
|
|
954
|
+
``ha_config_get_dashboard(mode="search")`` routing; fuzzy scoring and
|
|
955
|
+
``include_config`` bodies are legacy-only (the component walk is
|
|
956
|
+
substring and its matches carry no bodies), as is every ``None``
|
|
957
|
+
fallback case of :meth:`_component_dashboard_search` — including a
|
|
958
|
+
YAML-bearing install, so component-vs-legacy never changes which
|
|
959
|
+
dashboards a search covers.
|
|
960
|
+
"""
|
|
961
|
+
if exact_match and not include_config:
|
|
962
|
+
component = await self._component_dashboard_search(query_lower)
|
|
963
|
+
if component is not None:
|
|
964
|
+
return component
|
|
965
|
+
return await self._deep_search_dashboards(query_lower, exact_match, semaphore)
|
|
966
|
+
|
|
967
|
+
async def _component_dashboard_search(
|
|
968
|
+
self, query_lower: str
|
|
969
|
+
) -> tuple[list[dict[str, Any]], int] | None:
|
|
970
|
+
"""The dashboard bucket via the component's in-process ``search`` frame.
|
|
971
|
+
|
|
972
|
+
Returns ``(records, failed_count)`` — one legacy-shaped record per
|
|
973
|
+
matching dashboard from the component's ``document_matches`` (a
|
|
974
|
+
whole-document substring verdict per storage dashboard, ported from
|
|
975
|
+
``_search_in_dict`` leaf for leaf, so view titles and dashboard-level
|
|
976
|
+
keys match exactly as the legacy walk matches them); ``failed_count``
|
|
977
|
+
is the component's ``load_failed`` (storage dashboards whose config
|
|
978
|
+
load raised — surfaced as the same ``dashboard(s) not scanned``
|
|
979
|
+
partial the legacy scan reports). A config-less auto-generated
|
|
980
|
+
dashboard is skipped in-process (nothing to scan), consistent with
|
|
981
|
+
:func:`_is_no_stored_config`.
|
|
982
|
+
|
|
983
|
+
``None`` ⇒ run the legacy per-dashboard walk instead: the component
|
|
984
|
+
lacks the ``dashboards_doc_search`` capability (older components
|
|
985
|
+
emit only the card-scoped ``matches``, which would silently narrow
|
|
986
|
+
coverage), any ``_dashboards_via_component`` fallback (capability
|
|
987
|
+
miss / command error / lovelace unavailable), an empty query, a
|
|
988
|
+
malformed ``document_matches`` — or a non-zero ``yaml_skipped``.
|
|
989
|
+
The component never reads YAML-mode dashboard bodies, but the legacy
|
|
990
|
+
walk this path replaces does (``lovelace/config`` loads them, and the
|
|
991
|
+
fuzzy / ``include_config`` routes still read the same resolved
|
|
992
|
+
configs), so serving the component result on a YAML-bearing install
|
|
993
|
+
would make the DEFAULT call shape permanently narrower and
|
|
994
|
+
permanently ``partial``. Falling back keeps coverage identical to
|
|
995
|
+
the pre-component behaviour; storage-only installs — where the
|
|
996
|
+
exclusion costs nothing — keep the single-frame win (review
|
|
997
|
+
follow-up on issue #2008).
|
|
998
|
+
"""
|
|
999
|
+
if not query_lower:
|
|
1000
|
+
return None
|
|
1001
|
+
caps = await get_component_caps(self.client)
|
|
1002
|
+
if not component_supports(caps, "dashboards_doc_search"):
|
|
1003
|
+
return None
|
|
1004
|
+
result = await _dashboards_via_component(
|
|
1005
|
+
self.client, "search", query=query_lower
|
|
1006
|
+
)
|
|
1007
|
+
if result is None:
|
|
1008
|
+
return None
|
|
1009
|
+
document_matches = result.get("document_matches")
|
|
1010
|
+
if not isinstance(document_matches, list):
|
|
1011
|
+
return None
|
|
1012
|
+
if int(result.get("yaml_skipped", 0) or 0) > 0:
|
|
1013
|
+
return None
|
|
1014
|
+
failed = int(result.get("load_failed", 0) or 0)
|
|
1015
|
+
|
|
1016
|
+
records: dict[str, dict[str, Any]] = {}
|
|
1017
|
+
for match in document_matches:
|
|
1018
|
+
if not isinstance(match, dict):
|
|
1019
|
+
continue
|
|
1020
|
+
raw_url_path = match.get("url_path")
|
|
1021
|
+
url_path = raw_url_path or "default"
|
|
1022
|
+
if url_path in records:
|
|
1023
|
+
continue
|
|
1024
|
+
# The default dashboard: the legacy walk always labels it
|
|
1025
|
+
# ("default", "Default Dashboard") — a taken-control default
|
|
1026
|
+
# may carry its own body title, but emitting it would change
|
|
1027
|
+
# the record shape between the component and legacy paths.
|
|
1028
|
+
title = (
|
|
1029
|
+
"Default Dashboard"
|
|
1030
|
+
if not raw_url_path
|
|
1031
|
+
else (match.get("title") or url_path)
|
|
1032
|
+
)
|
|
1033
|
+
records[url_path] = {
|
|
1034
|
+
"dashboard_url": url_path,
|
|
1035
|
+
"dashboard_title": title,
|
|
1036
|
+
"score": 100,
|
|
1037
|
+
"match_in_config": True,
|
|
1038
|
+
}
|
|
1039
|
+
return list(records.values()), failed
|
|
1040
|
+
|
|
899
1041
|
async def _search_one_dashboard(
|
|
900
1042
|
self,
|
|
901
1043
|
url_path: str,
|
|
@@ -912,6 +1054,15 @@ class DeepSearchMixin(SceneSearchMixin):
|
|
|
912
1054
|
distinct from a successful no-match. Surfacing it lets
|
|
913
1055
|
``ha_search(search_types=["dashboard"])`` report ``partial`` instead
|
|
914
1056
|
of a complete-looking empty result.
|
|
1057
|
+
|
|
1058
|
+
The no-stored-config envelope (``config_not_found`` + "No config
|
|
1059
|
+
found.", see :func:`_is_no_stored_config`) is the deliberate
|
|
1060
|
+
exception: an auto-generated dashboard (strategy-backed, never taken
|
|
1061
|
+
control of) has nothing to scan, so it reads as a clean no-match.
|
|
1062
|
+
Counting it as failed made every dashboard search on a stock install
|
|
1063
|
+
report ``partial`` (issue #2008). The code's other cause — "Unknown
|
|
1064
|
+
config specified", a dashboard deleted since the registry-list
|
|
1065
|
+
snapshot — stays a counted failure.
|
|
915
1066
|
"""
|
|
916
1067
|
async with semaphore:
|
|
917
1068
|
try:
|
|
@@ -932,6 +1083,12 @@ class DeepSearchMixin(SceneSearchMixin):
|
|
|
932
1083
|
# shape explicitly (``success is False``) so a missing-success
|
|
933
1084
|
# raw response still falls through to the ``result`` fallback.
|
|
934
1085
|
if isinstance(resp, dict) and resp.get("success") is False:
|
|
1086
|
+
if _is_no_stored_config(resp):
|
|
1087
|
+
logger.debug(
|
|
1088
|
+
f"Dashboard has no stored config ({url_path}); "
|
|
1089
|
+
"auto-generated — nothing to scan"
|
|
1090
|
+
)
|
|
1091
|
+
return [], False
|
|
935
1092
|
logger.debug(
|
|
936
1093
|
f"Dashboard config returned non-success ({url_path}): {resp!r}"
|
|
937
1094
|
)
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_config_dashboards.py
RENAMED
|
@@ -813,10 +813,12 @@ def _card_matches(
|
|
|
813
813
|
#
|
|
814
814
|
# Source: homeassistant/components/lovelace/websocket.py, _handle_errors —
|
|
815
815
|
# emits f"Unknown config specified: {url_path}" paired with structured
|
|
816
|
-
# error.code "config_not_found". The
|
|
817
|
-
#
|
|
818
|
-
#
|
|
819
|
-
#
|
|
816
|
+
# error.code "config_not_found". The client envelope does surface that code
|
|
817
|
+
# top-level (``error_code``), but HA reuses it for the no-stored-config case
|
|
818
|
+
# ("No config found." — an auto-generated dashboard), so the code alone cannot
|
|
819
|
+
# identify an unresolved identifier; the message substring remains the only
|
|
820
|
+
# discriminating signal. If HA reformats this string, the lazy fallback
|
|
821
|
+
# regresses silently to never firing — re-verify with major HA upgrades.
|
|
820
822
|
_LAZY_RESOLVE_TRIGGER = "Unknown config specified"
|
|
821
823
|
|
|
822
824
|
|
|
@@ -1283,7 +1285,8 @@ async def fetch_dashboards_list(
|
|
|
1283
1285
|
every fetch site rather than silently degrading.
|
|
1284
1286
|
|
|
1285
1287
|
When the ``ha_mcp_tools`` component advertises the ``dashboards`` capability
|
|
1286
|
-
the
|
|
1288
|
+
the rows — YAML rows included, tagged with ``mode`` (see
|
|
1289
|
+
``_component_dashboard_rows``) — are served from one in-process ``list`` frame (the
|
|
1287
1290
|
``_resolve_dashboard`` / ``_lookup_existing_dashboards`` / list-mode callers
|
|
1288
1291
|
all funnel here); otherwise the legacy ``lovelace/dashboards/list`` WS read
|
|
1289
1292
|
runs unchanged.
|
|
@@ -917,6 +917,33 @@ def _normalize_component_config_record(
|
|
|
917
917
|
return out
|
|
918
918
|
|
|
919
919
|
|
|
920
|
+
# Body surfaces the ``ha_mcp_tools`` component's ``search`` command accepts
|
|
921
|
+
# (its voluptuous allowlist also has ``entity``, appended separately by
|
|
922
|
+
# ``_build_component_search_request``). ``dashboard`` is deliberately absent:
|
|
923
|
+
# the component has no dashboard scanner, so a request naming it must stay on
|
|
924
|
+
# the legacy path — forwarding it just bounced off the component schema into a
|
|
925
|
+
# warning-laden fallback on every call (issue #2008).
|
|
926
|
+
_COMPONENT_BODY_SEARCH_TYPES: frozenset[str] = frozenset(
|
|
927
|
+
{"automation", "script", "scene", "helper"}
|
|
928
|
+
)
|
|
929
|
+
|
|
930
|
+
|
|
931
|
+
def _component_serves_search_types(req: _ResolvedSearch) -> bool:
|
|
932
|
+
"""True when the component's search command accepts every requested surface.
|
|
933
|
+
|
|
934
|
+
Only an explicit ``search_types`` list can name an unsupported surface, and
|
|
935
|
+
only the body-eligible branch forwards it to the component — a
|
|
936
|
+
body-ineligible request sends the entity surface alone, which the component
|
|
937
|
+
always accepts. Routing is all-or-nothing per command, so one unsupported
|
|
938
|
+
surface sends the whole request to the legacy path, silently — the same
|
|
939
|
+
treatment as the other route-ineligible modes, not the warning-emitting
|
|
940
|
+
failure fallback.
|
|
941
|
+
"""
|
|
942
|
+
if not req.body_eligible or req.parsed_search_types is None:
|
|
943
|
+
return True
|
|
944
|
+
return all(t in _COMPONENT_BODY_SEARCH_TYPES for t in req.parsed_search_types)
|
|
945
|
+
|
|
946
|
+
|
|
920
947
|
def _build_component_search_request(req: _ResolvedSearch) -> dict[str, Any]:
|
|
921
948
|
"""Translate resolved ha_search inputs into an ``ha_mcp_tools/search`` request.
|
|
922
949
|
|
|
@@ -1958,7 +1985,9 @@ class SearchTools:
|
|
|
1958
1985
|
# response keys) — keep the legacy path: their response contracts
|
|
1959
1986
|
# differ per mode, and after the request-dedup work they are cheap
|
|
1960
1987
|
# registry-only calls, so the component round-trip buys nothing worth
|
|
1961
|
-
# the shape risk.
|
|
1988
|
+
# the shape risk. A ``search_types`` naming a surface the component
|
|
1989
|
+
# lacks (``dashboard``) also stays legacy — see
|
|
1990
|
+
# ``_component_serves_search_types`` (issue #2008).
|
|
1962
1991
|
#
|
|
1963
1992
|
# Entity-visibility gate. A plain ``search`` component applies no
|
|
1964
1993
|
# filtering, so an install with an ACTIVE visibility filter would leak
|
|
@@ -1973,7 +2002,11 @@ class SearchTools:
|
|
|
1973
2002
|
# needs no analogous gate — it re-applies the filter server-side over the
|
|
1974
2003
|
# component's raw slices. Checked only when the component would otherwise
|
|
1975
2004
|
# serve, so the common (no-component / filter-off) install pays nothing.
|
|
1976
|
-
if
|
|
2005
|
+
if (
|
|
2006
|
+
req.query_text
|
|
2007
|
+
and not (req.area_filter or "").strip()
|
|
2008
|
+
and _component_serves_search_types(req)
|
|
2009
|
+
):
|
|
1977
2010
|
caps = await get_component_caps(self._client)
|
|
1978
2011
|
if component_supports(caps, "search"):
|
|
1979
2012
|
(
|
|
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.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/client/supervisor_client.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/client/websocket_client.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/client/websocket_listener.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/dashboard_screenshot/__init__.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/dashboard_screenshot/capture.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/dashboard_screenshot/content.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/dashboard_screenshot/paths.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/dashboard_screenshot/provision.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
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/AGENTS.md
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/CLAUDE.md
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/resources/skills-vendor/LICENSE
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/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
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/_handlers_advanced.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/_handlers_backups.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/_handlers_fs.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/_handlers_server.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/_handlers_theme.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/_handlers_tools.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/_persistence.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/_supervisor.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/_tools_meta.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/locales/README.md
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/locales/de.json
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/locales/en.json
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/locales/ru.json
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/locales/zh-Hans.json
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/settings_ui/settings.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/stdio_settings_sidecar.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/best_practice_checker.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/component_config_reads.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/component_devices.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/component_registries.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/config_entry_flow.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
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/reference_validator.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/smart_search/__init__.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/smart_search/_base.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/smart_search/_config.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/smart_search/_entities.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/smart_search/_fetch.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/smart_search/_overview.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/smart_search/_scenes.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/smart_search/_scoring.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_blueprints.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_bug_report.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_categories.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_config_automations.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_config_helpers.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_config_scenes.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_config_scripts.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_filesystem.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_integrations.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
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_voice_assistant.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/tools_yaml_config.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/tools/validation_middleware.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/transforms/categorized_search.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/transforms/lite_docstrings.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/utils/config_write_lock.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/utils/kill_signal_diagnostics.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/utils/operation_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/visibility/enforcement.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp/visibility/persistence.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp_dev.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp_dev.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp_dev.egg-info/requires.txt
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2113 → ha_mcp_dev-7.14.2.dev2115}/src/ha_mcp_dev.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|