ha-mcp-dev 7.6.0.dev674__tar.gz → 7.6.0.dev675__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 (140) hide show
  1. {ha_mcp_dev-7.6.0.dev674/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.6.0.dev675}/PKG-INFO +1 -1
  2. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/pyproject.toml +1 -1
  3. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/config.py +102 -1
  4. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/settings.js +10 -0
  5. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/smart_search/_config.py +12 -21
  6. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/smart_search/_deep.py +6 -4
  7. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/smart_search/_scenes.py +3 -2
  8. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
  9. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/LICENSE +0 -0
  10. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/MANIFEST.in +0 -0
  11. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/README.md +0 -0
  12. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/setup.cfg +0 -0
  13. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/__init__.py +0 -0
  14. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/__main__.py +0 -0
  15. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/_pypi_marker +0 -0
  16. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/_version.py +0 -0
  17. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/auth/__init__.py +0 -0
  18. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/auth/consent_form.py +0 -0
  19. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/auth/provider.py +0 -0
  20. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/backup_manager.py +0 -0
  21. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/client/__init__.py +0 -0
  22. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/client/rest_client.py +0 -0
  23. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/client/supervisor_client.py +0 -0
  24. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/client/websocket_client.py +0 -0
  25. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/client/websocket_listener.py +0 -0
  26. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/dashboard_screenshot/__init__.py +0 -0
  27. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/dashboard_screenshot/capture.py +0 -0
  28. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/dashboard_screenshot/provision.py +0 -0
  29. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/errors.py +0 -0
  30. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/policy/__init__.py +0 -0
  31. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/policy/approval_queue.py +0 -0
  32. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/policy/evaluator.py +0 -0
  33. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/policy/handlers.py +0 -0
  34. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/policy/middleware.py +0 -0
  35. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/policy/model.py +0 -0
  36. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/policy/persistence.py +0 -0
  37. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/policy/value_sources.py +0 -0
  38. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/py.typed +0 -0
  39. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
  40. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
  41. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
  42. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
  43. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/resources/skills-vendor/.github/pull_request_template.md +0 -0
  44. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
  45. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
  46. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
  47. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
  48. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
  49. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
  50. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
  51. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
  52. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
  53. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
  54. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
  55. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
  56. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
  57. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
  58. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
  59. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
  60. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/yaml-only-integrations.md +0 -0
  61. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/server.py +0 -0
  62. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/settings.css +0 -0
  63. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/settings_ui.py +0 -0
  64. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/smoke_test.py +0 -0
  65. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/stdio_settings_sidecar.py +0 -0
  66. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/__init__.py +0 -0
  67. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/auto_backup.py +0 -0
  68. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/backup.py +0 -0
  69. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/best_practice_checker.py +0 -0
  70. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/device_control.py +0 -0
  71. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/enhanced.py +0 -0
  72. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/helpers.py +0 -0
  73. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/reference_validator.py +0 -0
  74. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/registry.py +0 -0
  75. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/smart_search/__init__.py +0 -0
  76. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/smart_search/_base.py +0 -0
  77. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/smart_search/_entities.py +0 -0
  78. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/smart_search/_fetch.py +0 -0
  79. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/smart_search/_overview.py +0 -0
  80. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/smart_search/_scoring.py +0 -0
  81. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_addons.py +0 -0
  82. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_areas.py +0 -0
  83. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_blueprints.py +0 -0
  84. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_bug_report.py +0 -0
  85. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_calendar.py +0 -0
  86. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_camera.py +0 -0
  87. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_categories.py +0 -0
  88. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_code.py +0 -0
  89. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_config_automations.py +0 -0
  90. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
  91. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_config_entry_flow.py +0 -0
  92. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
  93. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
  94. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
  95. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_dashboard_screenshot.py +0 -0
  96. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_energy.py +0 -0
  97. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_entities.py +0 -0
  98. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_filesystem.py +0 -0
  99. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_groups.py +0 -0
  100. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_hacs.py +0 -0
  101. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_history.py +0 -0
  102. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_integrations.py +0 -0
  103. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_labels.py +0 -0
  104. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
  105. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_registry.py +0 -0
  106. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_resources.py +0 -0
  107. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_search.py +0 -0
  108. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_service.py +0 -0
  109. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_services.py +0 -0
  110. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_system.py +0 -0
  111. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_todo.py +0 -0
  112. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_traces.py +0 -0
  113. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_updates.py +0 -0
  114. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_utility.py +0 -0
  115. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
  116. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
  117. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/tools_zones.py +0 -0
  118. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/util_helpers.py +0 -0
  119. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/tools/validation_middleware.py +0 -0
  120. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/transforms/__init__.py +0 -0
  121. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/transforms/categorized_search.py +0 -0
  122. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
  123. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/utils/__init__.py +0 -0
  124. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/utils/config_hash.py +0 -0
  125. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/utils/data_paths.py +0 -0
  126. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/utils/domain_handlers.py +0 -0
  127. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/utils/fuzzy_search.py +0 -0
  128. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
  129. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/utils/operation_manager.py +0 -0
  130. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/utils/python_sandbox.py +0 -0
  131. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/utils/skill_loader.py +0 -0
  132. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp/utils/usage_logger.py +0 -0
  133. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
  134. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
  135. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
  136. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
  137. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
  138. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/tests/__init__.py +0 -0
  139. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/tests/test_constants.py +0 -0
  140. {ha_mcp_dev-7.6.0.dev674 → ha_mcp_dev-7.6.0.dev675}/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.6.0.dev674
3
+ Version: 7.6.0.dev675
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.6.0.dev674"
7
+ version = "7.6.0.dev675"
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"
@@ -11,7 +11,7 @@ from pathlib import Path
11
11
  from typing import Any, Literal, NamedTuple
12
12
 
13
13
  from dotenv import load_dotenv
14
- from pydantic import Field, field_validator
14
+ from pydantic import Field, ValidationInfo, field_validator
15
15
  from pydantic_settings import BaseSettings, SettingsConfigDict
16
16
 
17
17
  from ha_mcp._version import get_version
@@ -65,6 +65,24 @@ class Settings(BaseSettings):
65
65
  fuzzy_threshold: int = Field(60, alias="FUZZY_THRESHOLD")
66
66
  entity_search_limit: int = Field(20, alias="ENTITY_SEARCH_LIMIT")
67
67
 
68
+ # Smart-search config-fetch time budgets (seconds). Bound how long
69
+ # ha_search / ha_deep_search spends fetching automation/script/scene
70
+ # definitions during the per-id fallback before reporting a partial
71
+ # result. Surfaced in the Advanced settings panel (issue #1538) so
72
+ # add-on users — who cannot set raw env vars — can tune them. Consumed
73
+ # as import-time module constants in tools/smart_search/_config.py, so
74
+ # a change requires an MCP-host restart to take effect (advanced
75
+ # settings already carry a restart-required notice in the UI).
76
+ automation_config_time_budget: float = Field(
77
+ 30.0, alias="HAMCP_AUTOMATION_CONFIG_TIME_BUDGET"
78
+ )
79
+ script_config_time_budget: float = Field(
80
+ 20.0, alias="HAMCP_SCRIPT_CONFIG_TIME_BUDGET"
81
+ )
82
+ scene_config_time_budget: float = Field(
83
+ 20.0, alias="HAMCP_SCENE_CONFIG_TIME_BUDGET"
84
+ )
85
+
68
86
  # Backup tool configuration
69
87
  backup_hint: str = Field("normal", alias="BACKUP_HINT")
70
88
 
@@ -293,6 +311,51 @@ class Settings(BaseSettings):
293
311
  return False
294
312
  return v
295
313
 
314
+ @field_validator(
315
+ "automation_config_time_budget",
316
+ "script_config_time_budget",
317
+ "scene_config_time_budget",
318
+ mode="before",
319
+ )
320
+ @classmethod
321
+ def _lenient_time_budget(cls, v: object, info: ValidationInfo) -> object:
322
+ """Coerce the three smart-search time budgets, falling back to the
323
+ field default (with a warning) instead of crashing startup.
324
+
325
+ Preserves the parse-tolerance of the removed ``_env_float`` helper
326
+ (empty / unparseable -> default) and additionally enforces the same
327
+ ``_ADVANCED_SETTINGS_BOUNDS`` range as the override-file / UI-POST
328
+ path, so the env-var path can't smuggle in an out-of-range or
329
+ non-finite budget. A ``<= 0`` budget would silently disable the
330
+ per-id config-fetch scan, and ``inf`` / ``nan`` would uncap it; the
331
+ ``lo <= val <= hi`` test rejects all three (NaN comparisons are
332
+ False), keeping the env and override-file paths consistent."""
333
+ field_name = info.field_name
334
+ if field_name is None: # always set for field_validator; defensive
335
+ return v
336
+ default = cls.model_fields[field_name].default
337
+ if v is None or (isinstance(v, str) and not v.strip()):
338
+ return default
339
+ try:
340
+ val = float(v) # type: ignore[arg-type]
341
+ except (ValueError, TypeError):
342
+ logger.warning(
343
+ "Invalid value for %s=%r; using default %s", field_name, v, default
344
+ )
345
+ return default
346
+ lo, hi = _ADVANCED_SETTINGS_BOUNDS[field_name]
347
+ if not (lo <= val <= hi):
348
+ logger.warning(
349
+ "%s=%r is outside %s-%s; using default %s",
350
+ field_name,
351
+ v,
352
+ lo,
353
+ hi,
354
+ default,
355
+ )
356
+ return default
357
+ return val
358
+
296
359
  @property
297
360
  def env_file_name(self) -> str:
298
361
  """Get the current environment file name."""
@@ -598,9 +661,44 @@ ADVANCED_SETTINGS_FIELDS: tuple[AdvancedField, ...] = (
598
661
  # Search & matching.
599
662
  AdvancedField("fuzzy_threshold", "FUZZY_THRESHOLD", int, "search", True),
600
663
  AdvancedField("entity_search_limit", "ENTITY_SEARCH_LIMIT", int, "search", True),
664
+ # Smart-search config-fetch time budgets (#1538). Restart-required
665
+ # (consumed as import-time constants in smart_search/_config.py).
666
+ AdvancedField(
667
+ "automation_config_time_budget",
668
+ "HAMCP_AUTOMATION_CONFIG_TIME_BUDGET",
669
+ float,
670
+ "search",
671
+ True,
672
+ ),
673
+ AdvancedField(
674
+ "script_config_time_budget",
675
+ "HAMCP_SCRIPT_CONFIG_TIME_BUDGET",
676
+ float,
677
+ "search",
678
+ True,
679
+ ),
680
+ AdvancedField(
681
+ "scene_config_time_budget",
682
+ "HAMCP_SCENE_CONFIG_TIME_BUDGET",
683
+ float,
684
+ "search",
685
+ True,
686
+ ),
601
687
  # Operations.
602
688
  AdvancedField("backup_hint", "BACKUP_HINT", str, "operations", True),
603
689
  AdvancedField("enable_websocket", "ENABLE_WEBSOCKET", bool, "operations", True),
690
+ # Dashboard-screenshot engine URL (#1538): docker/.env users could set
691
+ # HAMCP_DASHBOARD_SCREENSHOT_ENGINE_URL, but add-on users had no path to
692
+ # it. It is resolved live per capture (resolve_engine_url), so unlike the
693
+ # time budgets it takes effect without a restart. Blank = auto-discover
694
+ # the Puppet add-on via the Supervisor.
695
+ AdvancedField(
696
+ "dashboard_screenshot_engine_url",
697
+ "HAMCP_DASHBOARD_SCREENSHOT_ENGINE_URL",
698
+ str,
699
+ "operations",
700
+ True,
701
+ ),
604
702
  AdvancedField(
605
703
  "enabled_tool_modules", "ENABLED_TOOL_MODULES", str, "tools_surface", True
606
704
  ),
@@ -660,6 +758,9 @@ _ADVANCED_SETTINGS_BOUNDS: dict[str, tuple[float, float]] = {
660
758
  "max_retries": (0, 20),
661
759
  "fuzzy_threshold": (0, 100),
662
760
  "entity_search_limit": (1, 1000),
761
+ "automation_config_time_budget": (1.0, 600.0),
762
+ "script_config_time_budget": (1.0, 600.0),
763
+ "scene_config_time_budget": (1.0, 600.0),
663
764
  "code_mode_max_duration": (1.0, 300.0),
664
765
  "code_mode_max_memory": (1_048_576, 268_435_456),
665
766
  "code_mode_max_recursion": (1, 10_000),
@@ -2400,7 +2400,11 @@ const ADVANCED_FIELD_META = {
2400
2400
  verify_ssl: { label: "Verify SSL certificates", help: "Skip TLS verification only on trusted networks (self-signed certs, hostname mismatch). Restart required." },
2401
2401
  fuzzy_threshold: { label: "Fuzzy-search threshold", help: "Lower = looser entity match. Range 0–100." },
2402
2402
  entity_search_limit: { label: "Entity search result limit", help: "Max entities returned by ha_search_entities. Range 1–1000." },
2403
+ automation_config_time_budget: { label: "Automation config time budget (s)", help: "Max seconds ha_search/ha_deep_search spends fetching automation configs before returning a partial result. Raise on instances with many automations. Range 1–600. Restart required." },
2404
+ script_config_time_budget: { label: "Script config time budget (s)", help: "Max seconds ha_search/ha_deep_search spends fetching script configs before returning a partial result. Range 1–600. Restart required." },
2405
+ scene_config_time_budget: { label: "Scene config time budget (s)", help: "Max seconds ha_search/ha_deep_search spends fetching scene configs before returning a partial result. Range 1–600. Restart required." },
2403
2406
  backup_hint: { label: "Backup-hint level", help: "Tunes how strongly the LLM is prompted to take a full-HA snapshot before risky writes." },
2407
+ dashboard_screenshot_engine_url: { label: "Dashboard screenshot engine URL", help: "Base URL of the screenshot engine (e.g. http://puppet:10000). Leave blank to auto-discover the Puppet add-on via the Supervisor (HA OS / Supervised). Only used when the Dashboard Screenshot beta feature is enabled. Takes effect without a restart." },
2404
2408
  enable_websocket: { label: "Enable WebSocket", help: "WebSocket-based state monitoring. Disabling falls back to polling — many tools degrade. Restart required." },
2405
2409
  enabled_tool_modules: { label: "Enabled tool modules", help: "Comma-separated module names, or 'all'. Restricts which tool registry modules load at startup. Restart required." },
2406
2410
  enable_dashboard_partial_tools: { label: "Dashboard partial-update tools", help: "Token-efficient partial dashboard tools. Disable for clients with programmatic tool use." },
@@ -2430,6 +2434,12 @@ const ADVANCED_RESTART_REQUIRED = new Set([
2430
2434
  // lazy-init singleton (tools/smart_search.py) — changes
2431
2435
  // need restart to rebuild the searcher.
2432
2436
  "fuzzy_threshold",
2437
+ // The three smart-search time budgets are read once at import by
2438
+ // SmartSearchTools' _config module (singleton), so a change needs a
2439
+ // restart. dashboard_screenshot_engine_url is intentionally absent —
2440
+ // it is resolved live per capture, so it takes effect immediately.
2441
+ "automation_config_time_budget", "script_config_time_budget",
2442
+ "scene_config_time_budget",
2433
2443
  "code_mode_max_duration", "code_mode_max_memory",
2434
2444
  "code_mode_max_recursion", "code_mode_max_invocations",
2435
2445
  "code_mode_saved_tools_path",
@@ -5,11 +5,7 @@ smart-search mixins and the public ``smart_search`` shell can both depend
5
5
  on it without creating an import cycle.
6
6
  """
7
7
 
8
- import logging
9
- import os
10
-
11
- logger = logging.getLogger(__name__)
12
-
8
+ from ha_mcp.config import get_global_settings
13
9
 
14
10
  # Default concurrency limit for parallel operations
15
11
  DEFAULT_CONCURRENCY_LIMIT = 20
@@ -20,22 +16,17 @@ BULK_WEBSOCKET_TIMEOUT = 3.0 # Timeout for bulk WebSocket calls
20
16
  INDIVIDUAL_CONFIG_TIMEOUT = 5.0 # Timeout for individual config fetches
21
17
 
22
18
 
23
- # Time budgets for fallback individual fetching (in seconds).
24
- # Configurable via env vars for instances with many automations/scripts.
25
- def _env_float(key: str, default: float) -> float:
26
- raw = os.environ.get(key)
27
- if raw is None:
28
- return default
29
- try:
30
- return float(raw)
31
- except (ValueError, TypeError):
32
- logger.warning(f"Invalid value for {key}={raw!r}, using default {default}")
33
- return default
34
-
35
-
36
- AUTOMATION_CONFIG_TIME_BUDGET = _env_float("HAMCP_AUTOMATION_CONFIG_TIME_BUDGET", 30.0)
37
- SCRIPT_CONFIG_TIME_BUDGET = _env_float("HAMCP_SCRIPT_CONFIG_TIME_BUDGET", 20.0)
38
- SCENE_CONFIG_TIME_BUDGET = _env_float("HAMCP_SCENE_CONFIG_TIME_BUDGET", 20.0)
19
+ # Time budgets for fallback individual fetching (in seconds). Sourced from
20
+ # the resolved Settings (issue #1538) so the env var, the web Settings UI
21
+ # override file, and the field defaults all flow through one precedence path
22
+ # — and so add-on users (who cannot set raw env vars) can tune them from the
23
+ # Advanced panel. Read once at import as module-level constants; a change
24
+ # takes effect on the next MCP-host restart (advanced settings already
25
+ # carry a restart-required notice in the UI).
26
+ _settings = get_global_settings()
27
+ AUTOMATION_CONFIG_TIME_BUDGET = _settings.automation_config_time_budget
28
+ SCRIPT_CONFIG_TIME_BUDGET = _settings.script_config_time_budget
29
+ SCENE_CONFIG_TIME_BUDGET = _settings.scene_config_time_budget
39
30
 
40
31
  # Batch size for parallel individual config fetches (Attempt C fallback)
41
32
  INDIVIDUAL_FETCH_BATCH_SIZE = 10
@@ -903,8 +903,9 @@ class DeepSearchMixin(SceneSearchMixin):
903
903
  f"{automation_skipped} automation(s) not scanned (time budget "
904
904
  "exhausted) — their match status is unknown; this result is "
905
905
  "not exhaustive. Pass `config_time_budget=` on `ha_search` to "
906
- "raise the per-call limit (or set "
907
- "HAMCP_AUTOMATION_CONFIG_TIME_BUDGET for the default)."
906
+ "raise the per-call limit (or, for the default, set "
907
+ "HAMCP_AUTOMATION_CONFIG_TIME_BUDGET or the matching field in "
908
+ "the web Settings UI's Advanced section)."
908
909
  )
909
910
  if automation_failed:
910
911
  reasons.append(
@@ -925,8 +926,9 @@ class DeepSearchMixin(SceneSearchMixin):
925
926
  f"{script_skipped} script(s) not scanned (time budget "
926
927
  "exhausted) — their match status is unknown; this result is "
927
928
  "not exhaustive. Pass `config_time_budget=` on `ha_search` to "
928
- "raise the per-call limit (or set "
929
- "HAMCP_SCRIPT_CONFIG_TIME_BUDGET for the default)."
929
+ "raise the per-call limit (or, for the default, set "
930
+ "HAMCP_SCRIPT_CONFIG_TIME_BUDGET or the matching field in "
931
+ "the web Settings UI's Advanced section)."
930
932
  )
931
933
  if script_failed:
932
934
  reasons.append(
@@ -347,8 +347,9 @@ class SceneSearchMixin(ConfigFetchMixin):
347
347
  f"{skipped} scene(s) not scanned (time budget exhausted) — "
348
348
  "their match status is unknown; this result is not exhaustive. "
349
349
  "Pass `config_time_budget=` on `ha_search` to raise the "
350
- "per-call limit (or set HAMCP_SCENE_CONFIG_TIME_BUDGET for "
351
- "the default)."
350
+ "per-call limit (or, for the default, set "
351
+ "HAMCP_SCENE_CONFIG_TIME_BUDGET or the matching field in the "
352
+ "web Settings UI's Advanced section)."
352
353
  )
353
354
  if scene_stats["integration_skipped"]:
354
355
  # Informational, not an unknown-match-status condition: these
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ha-mcp-dev
3
- Version: 7.6.0.dev674
3
+ Version: 7.6.0.dev675
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