ha-mcp-dev 7.13.0.dev2037__tar.gz → 7.13.0.dev2039__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.
Files changed (187) hide show
  1. {ha_mcp_dev-7.13.0.dev2037/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.13.0.dev2039}/PKG-INFO +1 -1
  2. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/pyproject.toml +1 -1
  3. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/smart_search/_deep.py +12 -12
  4. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/smart_search/_fetch.py +36 -14
  5. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/smart_search/_scenes.py +6 -4
  6. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
  7. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/LICENSE +0 -0
  8. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/MANIFEST.in +0 -0
  9. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/README.md +0 -0
  10. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/setup.cfg +0 -0
  11. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/__init__.py +0 -0
  12. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/__main__.py +0 -0
  13. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/_pypi_marker +0 -0
  14. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/_version.py +0 -0
  15. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/auth/__init__.py +0 -0
  16. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/auth/consent_form.py +0 -0
  17. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/auth/provider.py +0 -0
  18. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/backup_manager.py +0 -0
  19. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/browser_landing.py +0 -0
  20. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/client/__init__.py +0 -0
  21. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/client/rest_client.py +0 -0
  22. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/client/supervisor_client.py +0 -0
  23. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/client/websocket_client.py +0 -0
  24. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/client/websocket_listener.py +0 -0
  25. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/config.py +0 -0
  26. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/dashboard_screenshot/__init__.py +0 -0
  27. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/dashboard_screenshot/capture.py +0 -0
  28. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/dashboard_screenshot/content.py +0 -0
  29. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/dashboard_screenshot/paths.py +0 -0
  30. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/dashboard_screenshot/provision.py +0 -0
  31. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/dashboard_screenshot/theme_guard.py +0 -0
  32. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/errors.py +0 -0
  33. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/llm_exposure.py +0 -0
  34. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/policy/__init__.py +0 -0
  35. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/policy/approval_queue.py +0 -0
  36. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/policy/evaluator.py +0 -0
  37. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/policy/handlers.py +0 -0
  38. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/policy/middleware.py +0 -0
  39. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/policy/model.py +0 -0
  40. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/policy/persistence.py +0 -0
  41. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/policy/value_sources.py +0 -0
  42. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/py.typed +0 -0
  43. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/read_only.py +0 -0
  44. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
  45. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
  46. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
  47. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
  48. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/.github/pull_request_template.md +0 -0
  49. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
  50. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
  51. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
  52. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
  53. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
  54. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
  55. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
  56. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/appdaemon.md +0 -0
  57. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
  58. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/blueprint-guide.md +0 -0
  59. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
  60. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
  61. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
  62. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
  63. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
  64. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
  65. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
  66. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/scenes.md +0 -0
  67. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
  68. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/yaml-only-integrations.md +0 -0
  69. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/server.py +0 -0
  70. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/settings_ui/__init__.py +0 -0
  71. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/settings_ui/_handlers_advanced.py +0 -0
  72. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/settings_ui/_handlers_backups.py +0 -0
  73. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/settings_ui/_handlers_fs.py +0 -0
  74. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/settings_ui/_handlers_server.py +0 -0
  75. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/settings_ui/_handlers_theme.py +0 -0
  76. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/settings_ui/_handlers_tools.py +0 -0
  77. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/settings_ui/_i18n.py +0 -0
  78. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/settings_ui/_persistence.py +0 -0
  79. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/settings_ui/_supervisor.py +0 -0
  80. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/settings_ui/_theme.py +0 -0
  81. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/settings_ui/_tools_meta.py +0 -0
  82. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/settings_ui/locales/README.md +0 -0
  83. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/settings_ui/locales/de.json +0 -0
  84. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/settings_ui/locales/en.json +0 -0
  85. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/settings_ui/locales/ru.json +0 -0
  86. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/settings_ui/settings.css +0 -0
  87. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/settings_ui/settings.html +0 -0
  88. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/settings_ui/settings.js +0 -0
  89. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/smoke_test.py +0 -0
  90. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/stdio_settings_sidecar.py +0 -0
  91. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/strict_bps.py +0 -0
  92. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/__init__.py +0 -0
  93. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/auto_backup.py +0 -0
  94. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/backup.py +0 -0
  95. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/best_practice_checker.py +0 -0
  96. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/component_api.py +0 -0
  97. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/component_config_reads.py +0 -0
  98. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/component_devices.py +0 -0
  99. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/component_registries.py +0 -0
  100. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/component_registry_lookup.py +0 -0
  101. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/config_entry_flow.py +0 -0
  102. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/device_control.py +0 -0
  103. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/enhanced.py +0 -0
  104. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/helpers.py +0 -0
  105. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/radio/__init__.py +0 -0
  106. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/radio/base.py +0 -0
  107. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/radio/matter.py +0 -0
  108. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/radio/thread.py +0 -0
  109. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/radio/zigbee.py +0 -0
  110. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/radio/zwave.py +0 -0
  111. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/reference_validator.py +0 -0
  112. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/registry.py +0 -0
  113. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/smart_search/__init__.py +0 -0
  114. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/smart_search/_base.py +0 -0
  115. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/smart_search/_config.py +0 -0
  116. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/smart_search/_entities.py +0 -0
  117. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/smart_search/_overview.py +0 -0
  118. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/smart_search/_scoring.py +0 -0
  119. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tool_search_hint_middleware.py +0 -0
  120. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_addons.py +0 -0
  121. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_areas.py +0 -0
  122. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_blueprints.py +0 -0
  123. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_bug_report.py +0 -0
  124. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_calendar.py +0 -0
  125. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_camera.py +0 -0
  126. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_categories.py +0 -0
  127. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_code.py +0 -0
  128. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_config_automations.py +0 -0
  129. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
  130. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
  131. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
  132. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
  133. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_dashboard_screenshot.py +0 -0
  134. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_dev.py +0 -0
  135. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_energy.py +0 -0
  136. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_entities.py +0 -0
  137. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_filesystem.py +0 -0
  138. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_groups.py +0 -0
  139. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_hacs.py +0 -0
  140. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_history.py +0 -0
  141. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_integrations.py +0 -0
  142. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_labels.py +0 -0
  143. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_radio.py +0 -0
  144. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_registry.py +0 -0
  145. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_resources.py +0 -0
  146. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_search.py +0 -0
  147. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_service.py +0 -0
  148. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_services.py +0 -0
  149. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_system.py +0 -0
  150. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_themes.py +0 -0
  151. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_todo.py +0 -0
  152. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_traces.py +0 -0
  153. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_updates.py +0 -0
  154. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_utility.py +0 -0
  155. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
  156. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
  157. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_yaml_read.py +0 -0
  158. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/tools_zones.py +0 -0
  159. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/util_helpers.py +0 -0
  160. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/tools/validation_middleware.py +0 -0
  161. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/transforms/__init__.py +0 -0
  162. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/transforms/categorized_search.py +0 -0
  163. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
  164. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/transport_security.py +0 -0
  165. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/update_check.py +0 -0
  166. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/utils/__init__.py +0 -0
  167. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/utils/config_hash.py +0 -0
  168. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/utils/data_paths.py +0 -0
  169. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/utils/domain_handlers.py +0 -0
  170. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/utils/fuzzy_search.py +0 -0
  171. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
  172. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/utils/operation_manager.py +0 -0
  173. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/utils/python_sandbox.py +0 -0
  174. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/utils/skill_loader.py +0 -0
  175. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/utils/usage_logger.py +0 -0
  176. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/visibility/__init__.py +0 -0
  177. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/visibility/model.py +0 -0
  178. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/visibility/persistence.py +0 -0
  179. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp/visibility/resolver.py +0 -0
  180. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
  181. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
  182. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
  183. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
  184. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
  185. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/tests/__init__.py +0 -0
  186. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/tests/test_constants.py +0 -0
  187. {ha_mcp_dev-7.13.0.dev2037 → ha_mcp_dev-7.13.0.dev2039}/tests/test_env_manager.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ha-mcp-dev
3
- Version: 7.13.0.dev2037
3
+ Version: 7.13.0.dev2039
4
4
  Summary: Home Assistant MCP Server - Complete control of Home Assistant through MCP
5
5
  Author-email: Julien <github@qc-h.net>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ha-mcp-dev"
7
- version = "7.13.0.dev2037"
7
+ version = "7.13.0.dev2039"
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
@@ -393,12 +393,12 @@ class DeepSearchMixin(SceneSearchMixin):
393
393
  failed_count = 0
394
394
  yaml_skipped_count = 0
395
395
  timeout_count = 0
396
- # One representative summary — only the FIRST ``failed``-class
397
- # exception is kept (the fetch closure guards the append); it rides
398
- # partial_reason as an ``e.g.`` (#1784 follow-up). The remaining
399
- # failures are counted (``failed_count``) but not summarized, so the
400
- # motivating "every per-id fetch 500s" case does N-1 fewer
401
- # ``summarize_fetch_error`` calls.
396
+ # One representative summary — ``record_first_failure`` (which holds
397
+ # the guard) keeps the first ``failed``-class exception, upgrading
398
+ # once to the first HTTP 500 so a fast-failing outlier can't suppress
399
+ # the 500 diagnosis hint; it rides partial_reason as an ``e.g.``
400
+ # (#1784 follow-up). The remaining failures are counted
401
+ # (``failed_count``) but not summarized.
402
402
  failed_errors: list[str] = []
403
403
  if not bulk_fetched:
404
404
  uids_to_fetch = [
@@ -547,12 +547,12 @@ class DeepSearchMixin(SceneSearchMixin):
547
547
  failed_count = 0
548
548
  yaml_skipped_count = 0
549
549
  timeout_count = 0
550
- # One representative summary — only the FIRST ``failed``-class
551
- # exception is kept (the fetch closure guards the append); it rides
552
- # partial_reason as an ``e.g.`` (#1784 follow-up). The remaining
553
- # failures are counted (``failed_count``) but not summarized, so the
554
- # motivating "every per-id fetch 500s" case does N-1 fewer
555
- # ``summarize_fetch_error`` calls.
550
+ # One representative summary — ``record_first_failure`` (which holds
551
+ # the guard) keeps the first ``failed``-class exception, upgrading
552
+ # once to the first HTTP 500 so a fast-failing outlier can't suppress
553
+ # the 500 diagnosis hint; it rides partial_reason as an ``e.g.``
554
+ # (#1784 follow-up). The remaining failures are counted
555
+ # (``failed_count``) but not summarized.
556
556
  failed_errors: list[str] = []
557
557
  if not bulk_fetched:
558
558
  sids_to_fetch = [
@@ -40,7 +40,8 @@ def summarize_fetch_error(exc: BaseException) -> str:
40
40
 
41
41
  HTTP errors render as ``HTTP <code>: <first line of the message>`` (the
42
42
  client's own ``API error: <code> - `` prefix is stripped rather than
43
- duplicated); everything else as ``<ExceptionType>: <first line>``.
43
+ duplicated); everything else as ``<ExceptionType>: <first line>``. An
44
+ empty message renders the bare prefix (``HTTP <code>`` / ``<Type>``).
44
45
  """
45
46
  lines = str(exc).strip().splitlines()
46
47
  text = lines[0].strip() if lines else ""
@@ -55,15 +56,24 @@ def summarize_fetch_error(exc: BaseException) -> str:
55
56
  return summary
56
57
 
57
58
 
58
- # Marks a rendered ``summarize_fetch_error`` summary whose cause the sample
59
- # cannot name: an HTTP 500's body is aiohttp's generic "500 Internal Server
60
- # Error" placeholder, so the real error (a YAMLException the per-id config
61
- # view raised, most often a ``!secret`` reference it rejects) lives only in
62
- # the HA log, never in the response.
63
- _HTTP_500_PREFIX = "HTTP 500:"
59
+ # Matches a rendered ``summarize_fetch_error`` HTTP-500 summary — ``HTTP
60
+ # 500: <text>``, or bare ``HTTP 500`` when the error body was empty. An HTTP
61
+ # 500 is the one sample whose cause the summary cannot name (the body is
62
+ # aiohttp's generic "500 Internal Server Error" placeholder; the real error —
63
+ # most often a ``!secret`` reference the per-id config view rejects — lives
64
+ # only in the HA log). Shared by the sample upgrade in
65
+ # ``record_first_failure`` and by ``http_500_diagnosis_hint`` so the two can
66
+ # never disagree on what counts as a 500.
67
+ _HTTP_500_SAMPLE = re.compile(r"HTTP 500(?::|$)")
68
+
69
+
70
+ def _is_http_500_sample(sample: str) -> bool:
71
+ """True when ``sample`` is a rendered HTTP-500 summary (``_HTTP_500_SAMPLE``)."""
72
+ return _HTTP_500_SAMPLE.match(sample) is not None
73
+
64
74
 
65
75
  # Static diagnosis appended to an HTTP-500 failed fragment. The sample names
66
- # the status but not the cause (see ``_HTTP_500_PREFIX``); this points the
76
+ # the status but not the cause (see ``_HTTP_500_SAMPLE``); this points the
67
77
  # reader at the HA log and the single most common cause, delivering the
68
78
  # five-minute diagnosis the #1784 follow-up asked for without claiming a
69
79
  # cause the response can't actually confirm. Kept endpoint-agnostic — this
@@ -84,23 +94,35 @@ def http_500_diagnosis_hint(failed_sample: str | None) -> str:
84
94
  Returns ``""`` for any other sample (or ``None``), so non-500 fragments
85
95
  are byte-identical to before. See ``_HTTP_500_DIAGNOSIS``.
86
96
  """
87
- if failed_sample and failed_sample.startswith(_HTTP_500_PREFIX):
97
+ if failed_sample and _is_http_500_sample(failed_sample):
88
98
  return _HTTP_500_DIAGNOSIS
89
99
  return ""
90
100
 
91
101
 
92
102
  def record_first_failure(failed_errors: list[str], exc: BaseException) -> None:
93
- """Capture ``exc``'s summary as the representative ``failed`` sample, once.
103
+ """Capture ``exc``'s summary as the representative ``failed`` sample.
94
104
 
95
- Only the FIRST generic-``failed`` exception per fetch pass is summarized
105
+ The first generic-``failed`` exception per fetch pass is summarized
96
106
  (subsequent ones are counted but not summarized) — in the motivating
97
107
  "every per-id fetch 500s" case that is N-1 fewer ``summarize_fetch_error``
98
- calls. The append is a no-op once ``failed_errors`` is non-empty. Called
99
- from the per-id fetch closures, which run under ``asyncio.gather`` but
100
- never suspend between the check and the append, so no lock is needed.
108
+ calls. One exception: the first HTTP 500 upgrades a non-500 sample, once —
109
+ failure order tracks latency under ``asyncio.gather``, so a fast-failing
110
+ outlier (e.g. a connection blip losing the race against slower 500
111
+ round-trips) must not claim the slot and suppress the
112
+ ``http_500_diagnosis_hint`` diagnosis this sample exists to deliver. At
113
+ most two summaries are rendered per pass. Called from the per-id fetch
114
+ closures, which run under ``asyncio.gather`` but never suspend between
115
+ the check and the write, so no lock is needed.
101
116
  """
102
117
  if not failed_errors:
103
118
  failed_errors.append(summarize_fetch_error(exc))
119
+ return
120
+ if (
121
+ isinstance(exc, HomeAssistantAPIError)
122
+ and exc.status_code == 500
123
+ and not _is_http_500_sample(failed_errors[0])
124
+ ):
125
+ failed_errors[0] = summarize_fetch_error(exc)
104
126
 
105
127
 
106
128
  def is_timeout_error(exc: BaseException) -> bool:
@@ -273,10 +273,12 @@ class SceneSearchMixin(ConfigFetchMixin):
273
273
  skipped_count = 0
274
274
  integration_skipped = 0
275
275
  timeout_count = 0
276
- # One representative summary — only the FIRST ``failed``-class
277
- # exception is kept (the fetch closure guards the append); it rides
278
- # partial_reason as an ``e.g.`` (#1784 follow-up). The remaining
279
- # failures are counted (``failed_count``) but not summarized.
276
+ # One representative summary — ``record_first_failure`` (which holds
277
+ # the guard) keeps the first ``failed``-class exception, upgrading
278
+ # once to the first HTTP 500 so a fast-failing outlier can't suppress
279
+ # the 500 diagnosis hint; it rides partial_reason as an ``e.g.``
280
+ # (#1784 follow-up). The remaining failures are counted
281
+ # (``failed_count``) but not summarized.
280
282
  failed_errors: list[str] = []
281
283
 
282
284
  # Attempt C: parallel per-id fetch with a wall-clock budget so a few
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ha-mcp-dev
3
- Version: 7.13.0.dev2037
3
+ Version: 7.13.0.dev2039
4
4
  Summary: Home Assistant MCP Server - Complete control of Home Assistant through MCP
5
5
  Author-email: Julien <github@qc-h.net>
6
6
  License: MIT