ha-mcp-dev 7.8.0.dev713__tar.gz → 7.8.0.dev714__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.8.0.dev713/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.8.0.dev714}/PKG-INFO +1 -1
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/pyproject.toml +1 -1
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/config.py +61 -1
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/settings.css +7 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/settings.js +36 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/settings_ui.py +26 -2
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/stdio_settings_sidecar.py +38 -11
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/LICENSE +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/MANIFEST.in +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/README.md +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/setup.cfg +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/__main__.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/_pypi_marker +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/_version.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/auth/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/auth/consent_form.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/auth/provider.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/backup_manager.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/client/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/client/rest_client.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/client/supervisor_client.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/client/websocket_client.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/client/websocket_listener.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/dashboard_screenshot/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/dashboard_screenshot/capture.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/dashboard_screenshot/provision.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/errors.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/policy/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/policy/approval_queue.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/policy/evaluator.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/policy/handlers.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/policy/middleware.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/policy/model.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/policy/persistence.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/policy/value_sources.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/py.typed +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/read_only.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/.github/pull_request_template.md +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/yaml-only-integrations.md +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/server.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/smoke_test.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/auto_backup.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/backup.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/best_practice_checker.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/config_entry_flow.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/device_control.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/enhanced.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/helpers.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/reference_validator.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/registry.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/smart_search/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/smart_search/_base.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/smart_search/_config.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/smart_search/_deep.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/smart_search/_entities.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/smart_search/_fetch.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/smart_search/_overview.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/smart_search/_scenes.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/smart_search/_scoring.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tool_search_hint_middleware.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_addons.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_areas.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_blueprints.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_bug_report.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_calendar.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_camera.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_categories.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_code.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_config_automations.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_dashboard_screenshot.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_energy.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_entities.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_filesystem.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_groups.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_hacs.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_history.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_integrations.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_labels.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_registry.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_resources.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_search.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_service.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_services.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_system.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_themes.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_todo.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_traces.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_updates.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_utility.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_zones.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/util_helpers.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/validation_middleware.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/transforms/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/transforms/categorized_search.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/utils/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/utils/config_hash.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/utils/data_paths.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/utils/domain_handlers.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/utils/fuzzy_search.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/utils/operation_manager.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/utils/python_sandbox.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/utils/skill_loader.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/utils/usage_logger.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/tests/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/tests/test_constants.py +0 -0
- {ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/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.8.0.
|
|
7
|
+
version = "7.8.0.dev714"
|
|
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"
|
|
@@ -89,6 +89,13 @@ class Settings(BaseSettings):
|
|
|
89
89
|
# WebSocket configuration (essential for async operations)
|
|
90
90
|
enable_websocket: bool = Field(True, alias="ENABLE_WEBSOCKET")
|
|
91
91
|
|
|
92
|
+
# Settings UI sidecar (stdio mode only, #1587). 0 = pick a free
|
|
93
|
+
# ephemeral port at every spawn (default); 1024-65535 pins the sidecar
|
|
94
|
+
# to a fixed port so the settings URL/origin stays stable across
|
|
95
|
+
# restarts (bookmarks, browser localStorage). Read by run_main() in
|
|
96
|
+
# stdio_settings_sidecar.py.
|
|
97
|
+
sidecar_pin_port: int = Field(0, alias="HA_MCP_SIDECAR_PORT")
|
|
98
|
+
|
|
92
99
|
# Development/Debug configuration
|
|
93
100
|
debug: bool = Field(False, alias="DEBUG")
|
|
94
101
|
log_level: str = Field("INFO", alias="LOG_LEVEL")
|
|
@@ -437,6 +444,37 @@ class Settings(BaseSettings):
|
|
|
437
444
|
raise ValueError(f"Backup hint must be one of {valid_hints}")
|
|
438
445
|
return v.lower()
|
|
439
446
|
|
|
447
|
+
@field_validator("sidecar_pin_port", mode="before")
|
|
448
|
+
@classmethod
|
|
449
|
+
def _lenient_sidecar_pin_port(cls, v: object) -> int:
|
|
450
|
+
"""0 (default) = ephemeral port; otherwise a non-privileged port.
|
|
451
|
+
|
|
452
|
+
Lenient like the time-budget validators: an empty / unparseable /
|
|
453
|
+
out-of-range value falls back to 0 (ephemeral) with a warning rather
|
|
454
|
+
than raising, so a bad ``HA_MCP_SIDECAR_PORT`` can never crash the MCP
|
|
455
|
+
server or the best-effort settings sidecar.
|
|
456
|
+
"""
|
|
457
|
+
if isinstance(v, str):
|
|
458
|
+
v = v.strip()
|
|
459
|
+
if not v:
|
|
460
|
+
return 0
|
|
461
|
+
# bool is an int subclass but never a meaningful port; reject it
|
|
462
|
+
# along with anything that isn't int/str-parseable.
|
|
463
|
+
if v is None or isinstance(v, bool) or not isinstance(v, int | str):
|
|
464
|
+
logger.warning("Invalid HA_MCP_SIDECAR_PORT=%r; using ephemeral port", v)
|
|
465
|
+
return 0
|
|
466
|
+
try:
|
|
467
|
+
port = int(v)
|
|
468
|
+
except (ValueError, TypeError):
|
|
469
|
+
logger.warning("Invalid HA_MCP_SIDECAR_PORT=%r; using ephemeral port", v)
|
|
470
|
+
return 0
|
|
471
|
+
if port != 0 and not 1024 <= port <= 65535:
|
|
472
|
+
logger.warning(
|
|
473
|
+
"HA_MCP_SIDECAR_PORT=%r outside 1024-65535; using ephemeral port", v
|
|
474
|
+
)
|
|
475
|
+
return 0
|
|
476
|
+
return port
|
|
477
|
+
|
|
440
478
|
model_config = SettingsConfigDict(
|
|
441
479
|
env_file=".env", env_file_encoding="utf-8", case_sensitive=False, extra="allow"
|
|
442
480
|
)
|
|
@@ -505,6 +543,7 @@ AdvancedSection = Literal[
|
|
|
505
543
|
"operations",
|
|
506
544
|
"diagnostics",
|
|
507
545
|
"tools_surface",
|
|
546
|
+
"sidecar",
|
|
508
547
|
"beta_codemode",
|
|
509
548
|
]
|
|
510
549
|
|
|
@@ -728,6 +767,10 @@ ADVANCED_SETTINGS_FIELDS: tuple[AdvancedField, ...] = (
|
|
|
728
767
|
AdvancedField("environment", "ENVIRONMENT", str, "diagnostics", True),
|
|
729
768
|
AdvancedField("log_level", "LOG_LEVEL", str, "diagnostics", True),
|
|
730
769
|
AdvancedField("debug", "DEBUG", bool, "diagnostics", True),
|
|
770
|
+
# Settings UI sidecar (stdio-only). Pin the sidecar's port so the
|
|
771
|
+
# settings URL/origin is stable across restarts; 0 = ephemeral
|
|
772
|
+
# (default). #1587.
|
|
773
|
+
AdvancedField("sidecar_pin_port", "HA_MCP_SIDECAR_PORT", int, "sidecar", True),
|
|
731
774
|
# NOTE: ``auto_backup_dir`` and ``auto_backup_calendar_lookahead_days``
|
|
732
775
|
# are NOT in this tuple. They are in ``BACKUP_OVERRIDE_FIELDS`` (defined
|
|
733
776
|
# below) so they persist to ``backup_settings.json`` alongside the
|
|
@@ -778,6 +821,18 @@ _ADVANCED_SETTINGS_BOUNDS: dict[str, tuple[float, float]] = {
|
|
|
778
821
|
"code_mode_max_memory": (1_048_576, 268_435_456),
|
|
779
822
|
"code_mode_max_recursion": (1, 10_000),
|
|
780
823
|
"code_mode_max_invocations": (1, 10_000),
|
|
824
|
+
# 0 is the "off" sentinel (ephemeral); the range below is the valid
|
|
825
|
+
# PINNED range. See _ADVANCED_SETTINGS_SENTINELS.
|
|
826
|
+
"sidecar_pin_port": (1024, 65535),
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
|
|
830
|
+
# Fields where a specific value is a valid "off" sentinel that bypasses the
|
|
831
|
+
# _ADVANCED_SETTINGS_BOUNDS range (sidecar_pin_port: 0 = ephemeral). The UI
|
|
832
|
+
# emits min=sentinel so the number input can still express "off"; the
|
|
833
|
+
# override-apply and UI-POST paths accept the sentinel OR the bounded range.
|
|
834
|
+
_ADVANCED_SETTINGS_SENTINELS: dict[str, int] = {
|
|
835
|
+
"sidecar_pin_port": 0,
|
|
781
836
|
}
|
|
782
837
|
|
|
783
838
|
|
|
@@ -1159,7 +1214,12 @@ def _apply_advanced_overrides(settings: "Settings") -> None:
|
|
|
1159
1214
|
continue
|
|
1160
1215
|
|
|
1161
1216
|
bounds = _ADVANCED_SETTINGS_BOUNDS.get(fname)
|
|
1162
|
-
|
|
1217
|
+
sentinel = _ADVANCED_SETTINGS_SENTINELS.get(fname)
|
|
1218
|
+
if (
|
|
1219
|
+
bounds is not None
|
|
1220
|
+
and coerced != sentinel
|
|
1221
|
+
and not (bounds[0] <= coerced <= bounds[1])
|
|
1222
|
+
):
|
|
1163
1223
|
logger.warning(
|
|
1164
1224
|
"Advanced override for %r is %s, outside %s-%s — ignoring.",
|
|
1165
1225
|
fname,
|
|
@@ -284,6 +284,13 @@
|
|
|
284
284
|
.adv-save-btn:disabled { opacity: 0.55; cursor: not-allowed;
|
|
285
285
|
box-shadow: none; }
|
|
286
286
|
.adv-section { border-top: 1px solid var(--border); }
|
|
287
|
+
/* Sidecar section greys out in non-stdio deployments (no sidecar to pin),
|
|
288
|
+
mirroring the .feature-row.*-sub.dimmed treatment. */
|
|
289
|
+
.adv-section.dimmed { opacity: 0.55; }
|
|
290
|
+
.adv-section.dimmed input, .adv-section.dimmed select { cursor: not-allowed; }
|
|
291
|
+
.adv-section-title.dimmed { opacity: 0.55; }
|
|
292
|
+
.adv-section-note { font-size: 0.72rem; color: var(--text-secondary);
|
|
293
|
+
margin: 4px 0 8px; line-height: 1.4; }
|
|
287
294
|
.adv-row { display: flex; align-items: flex-start; justify-content: space-between;
|
|
288
295
|
gap: 12px; padding: 10px 0; border-top: 1px solid var(--border); }
|
|
289
296
|
.adv-row:first-child { border-top: none; }
|
|
@@ -2740,6 +2740,7 @@ const ADVANCED_FIELD_META = {
|
|
|
2740
2740
|
code_mode_max_recursion: { label: "Code-mode max recursion", help: "Recursion-depth cap per sandbox run. Restart required." },
|
|
2741
2741
|
code_mode_max_invocations: { label: "Code-mode max invocations", help: "API/tool-call cap per sandbox run. Restart required." },
|
|
2742
2742
|
code_mode_saved_tools_path:{ label: "Saved-tools path", help: "JSON file where ha_manage_custom_tool persists saved tools across restarts. Restart required." },
|
|
2743
|
+
sidecar_pin_port: { label: "Settings UI sidecar port", help: "0 = a new free port each restart (default); set 1024–65535 to pin a fixed port so the settings URL stays stable across restarts. Falls back to a free port if the pinned one is busy. Restart required." },
|
|
2743
2744
|
};
|
|
2744
2745
|
|
|
2745
2746
|
// Fields that require an MCP-host restart to take effect when changed
|
|
@@ -2765,6 +2766,9 @@ const ADVANCED_RESTART_REQUIRED = new Set([
|
|
|
2765
2766
|
"code_mode_max_duration", "code_mode_max_memory",
|
|
2766
2767
|
"code_mode_max_recursion", "code_mode_max_invocations",
|
|
2767
2768
|
"code_mode_saved_tools_path",
|
|
2769
|
+
// The sidecar binds its port once at spawn (run_main), so changing the
|
|
2770
|
+
// pin needs a restart to respawn the sidecar on the new port.
|
|
2771
|
+
"sidecar_pin_port",
|
|
2768
2772
|
]);
|
|
2769
2773
|
|
|
2770
2774
|
let _advancedFields = [];
|
|
@@ -2825,6 +2829,8 @@ async function loadAdvancedSettings() {
|
|
|
2825
2829
|
renderAdvancedSection('advOperations', bySection.operations || []);
|
|
2826
2830
|
renderAdvancedSection('advToolsSurface', bySection.tools_surface || []);
|
|
2827
2831
|
renderAdvancedSection('advDiagnostics', bySection.diagnostics || []);
|
|
2832
|
+
renderAdvancedSection('advSidecar', bySection.sidecar || []);
|
|
2833
|
+
applySidecarAvailability(data.is_stdio !== false);
|
|
2828
2834
|
document.getElementById('advSaveRow').style.display = '';
|
|
2829
2835
|
const topRow = document.getElementById('advSaveRowTop');
|
|
2830
2836
|
if (topRow) topRow.style.display = '';
|
|
@@ -2840,6 +2846,36 @@ async function loadAdvancedSettings() {
|
|
|
2840
2846
|
}
|
|
2841
2847
|
}
|
|
2842
2848
|
|
|
2849
|
+
function applySidecarAvailability(isStdio) {
|
|
2850
|
+
// The sidecar-port setting only applies when this settings page is served
|
|
2851
|
+
// by the stdio settings-UI sidecar. In HTTP/SSE/OAuth/addon deployments
|
|
2852
|
+
// there is no sidecar, so dim + disable the section and explain why, rather
|
|
2853
|
+
// than letting a user save a value that does nothing.
|
|
2854
|
+
// Remove any note from a prior load first, so the <h3> title is once again
|
|
2855
|
+
// the section's previousElementSibling (an injected note would otherwise
|
|
2856
|
+
// shadow it on a re-render).
|
|
2857
|
+
const prevNote = document.getElementById('advSidecarNote');
|
|
2858
|
+
if (prevNote) prevNote.remove();
|
|
2859
|
+
const section = document.getElementById('advSidecar');
|
|
2860
|
+
if (!section) return;
|
|
2861
|
+
const title = section.previousElementSibling;
|
|
2862
|
+
if (isStdio) {
|
|
2863
|
+
section.classList.remove('dimmed');
|
|
2864
|
+
if (title) title.classList.remove('dimmed');
|
|
2865
|
+
return;
|
|
2866
|
+
}
|
|
2867
|
+
section.classList.add('dimmed');
|
|
2868
|
+
if (title) title.classList.add('dimmed');
|
|
2869
|
+
section.querySelectorAll('input, select').forEach((el) => { el.disabled = true; });
|
|
2870
|
+
const note = document.createElement('div');
|
|
2871
|
+
note.id = 'advSidecarNote';
|
|
2872
|
+
note.className = 'adv-section-note';
|
|
2873
|
+
note.textContent =
|
|
2874
|
+
'Available in stdio mode only. This server runs over HTTP, which has '
|
|
2875
|
+
+ 'no settings-UI sidecar to pin.';
|
|
2876
|
+
section.parentNode.insertBefore(note, section);
|
|
2877
|
+
}
|
|
2878
|
+
|
|
2843
2879
|
function renderAdvancedSection(containerId, fields) {
|
|
2844
2880
|
const el = document.getElementById(containerId);
|
|
2845
2881
|
if (!el) return;
|
|
@@ -902,6 +902,8 @@ _SETTINGS_HTML = (
|
|
|
902
902
|
<div id="advToolsSurface" class="adv-section"></div>
|
|
903
903
|
<h3 class="adv-section-title">Diagnostics</h3>
|
|
904
904
|
<div id="advDiagnostics" class="adv-section"></div>
|
|
905
|
+
<h3 class="adv-section-title">Settings UI sidecar</h3>
|
|
906
|
+
<div id="advSidecar" class="adv-section"></div>
|
|
905
907
|
|
|
906
908
|
<!-- Beta features sit at the bottom of the panel — these can damage
|
|
907
909
|
the HA system, so they come last and the user sees safer
|
|
@@ -2650,6 +2652,7 @@ def build_settings_handlers(
|
|
|
2650
2652
|
from .config import (
|
|
2651
2653
|
_ADVANCED_SETTINGS_BOUNDS,
|
|
2652
2654
|
_ADVANCED_SETTINGS_CHOICES,
|
|
2655
|
+
_ADVANCED_SETTINGS_SENTINELS,
|
|
2653
2656
|
ADVANCED_SETTINGS_FIELDS,
|
|
2654
2657
|
OAUTH_MODE_TOKEN,
|
|
2655
2658
|
_read_feature_flag_override_file,
|
|
@@ -2692,11 +2695,26 @@ def build_settings_handlers(
|
|
|
2692
2695
|
bounds = _ADVANCED_SETTINGS_BOUNDS.get(fname)
|
|
2693
2696
|
if bounds is not None:
|
|
2694
2697
|
row["min"], row["max"] = bounds
|
|
2698
|
+
# Sentinel fields (e.g. sidecar_pin_port: 0 = off) need the
|
|
2699
|
+
# number input to reach below the bounded range, so expose
|
|
2700
|
+
# the sentinel as the UI minimum.
|
|
2701
|
+
sentinel = _ADVANCED_SETTINGS_SENTINELS.get(fname)
|
|
2702
|
+
if sentinel is not None:
|
|
2703
|
+
row["min"] = sentinel
|
|
2695
2704
|
choices = _ADVANCED_SETTINGS_CHOICES.get(fname)
|
|
2696
2705
|
if choices is not None:
|
|
2697
2706
|
row["choices"] = list(choices)
|
|
2698
2707
|
fields.append(row)
|
|
2699
|
-
|
|
2708
|
+
# is_stdio: the sidecar-port field only applies when this settings
|
|
2709
|
+
# page is served by the stdio settings-UI sidecar. In HTTP/SSE/OAuth
|
|
2710
|
+
# /addon deployments there is no sidecar, so the UI greys the section.
|
|
2711
|
+
return JSONResponse(
|
|
2712
|
+
{
|
|
2713
|
+
"fields": fields,
|
|
2714
|
+
"is_addon": is_running_in_addon(),
|
|
2715
|
+
"is_stdio": get_http_settings_prefix() is None,
|
|
2716
|
+
}
|
|
2717
|
+
)
|
|
2700
2718
|
|
|
2701
2719
|
def _origin_for_advanced_field(
|
|
2702
2720
|
env_name: str, overrides: dict[str, Any] | None = None
|
|
@@ -2770,6 +2788,7 @@ def build_settings_handlers(
|
|
|
2770
2788
|
from .config import (
|
|
2771
2789
|
_ADVANCED_SETTINGS_BOUNDS,
|
|
2772
2790
|
_ADVANCED_SETTINGS_CHOICES,
|
|
2791
|
+
_ADVANCED_SETTINGS_SENTINELS,
|
|
2773
2792
|
_FEATURE_FLAG_OVERRIDE_FILENAME,
|
|
2774
2793
|
ADVANCED_SETTINGS_FIELDS,
|
|
2775
2794
|
)
|
|
@@ -2890,7 +2909,12 @@ def build_settings_handlers(
|
|
|
2890
2909
|
return _bad_advanced_type(fname, ftype, raw)
|
|
2891
2910
|
|
|
2892
2911
|
bounds = _ADVANCED_SETTINGS_BOUNDS.get(fname)
|
|
2893
|
-
|
|
2912
|
+
sentinel = _ADVANCED_SETTINGS_SENTINELS.get(fname)
|
|
2913
|
+
if (
|
|
2914
|
+
bounds is not None
|
|
2915
|
+
and coerced != sentinel
|
|
2916
|
+
and not (bounds[0] <= coerced <= bounds[1])
|
|
2917
|
+
):
|
|
2894
2918
|
return JSONResponse(
|
|
2895
2919
|
create_error_response(
|
|
2896
2920
|
ErrorCode.VALIDATION_INVALID_PARAMETER,
|
|
@@ -266,19 +266,40 @@ def _spawn_lock() -> Iterator[bool]:
|
|
|
266
266
|
os.close(fd)
|
|
267
267
|
|
|
268
268
|
|
|
269
|
-
def _pick_free_port() -> int:
|
|
270
|
-
"""
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
269
|
+
def _pick_free_port(pinned: int = 0) -> int:
|
|
270
|
+
"""Return the port the sidecar listener should bind.
|
|
271
|
+
|
|
272
|
+
``pinned == 0`` (default): bind a transient socket to an ephemeral
|
|
273
|
+
port and return it. The socket is closed before the sidecar opens its
|
|
274
|
+
own listener. The OS may hand out the same port again; if another
|
|
275
|
+
process snatches it in the gap, the sidecar startup will fail and log
|
|
276
|
+
to ``sidecar.log`` — the parent moves on (settings UI is advisory, not
|
|
277
|
+
required for MCP operation).
|
|
278
|
+
|
|
279
|
+
``pinned != 0``: try to reserve the requested fixed port with
|
|
280
|
+
``SO_REUSEADDR`` so the settings URL/origin survives restarts (#1587).
|
|
281
|
+
``SO_REUSEADDR`` lets the bind succeed even if a crashed sidecar left
|
|
282
|
+
the port in ``TIME_WAIT``. If the port is genuinely unavailable (in
|
|
283
|
+
use by another process), log a warning and fall back to an ephemeral
|
|
284
|
+
port rather than failing the sidecar.
|
|
277
285
|
"""
|
|
286
|
+
if pinned:
|
|
287
|
+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
|
288
|
+
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
289
|
+
try:
|
|
290
|
+
sock.bind(("127.0.0.1", pinned))
|
|
291
|
+
return int(sock.getsockname()[1])
|
|
292
|
+
except OSError as exc:
|
|
293
|
+
logger.warning(
|
|
294
|
+
"Sidecar pin port %d unavailable (%s); "
|
|
295
|
+
"falling back to an ephemeral port",
|
|
296
|
+
pinned,
|
|
297
|
+
exc,
|
|
298
|
+
)
|
|
299
|
+
return _pick_free_port(0)
|
|
278
300
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
|
279
301
|
sock.bind(("127.0.0.1", 0))
|
|
280
|
-
|
|
281
|
-
return port
|
|
302
|
+
return int(sock.getsockname()[1])
|
|
282
303
|
|
|
283
304
|
|
|
284
305
|
def maybe_spawn() -> None:
|
|
@@ -795,7 +816,13 @@ def run_main() -> int:
|
|
|
795
816
|
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
|
|
796
817
|
)
|
|
797
818
|
|
|
798
|
-
port
|
|
819
|
+
# Effective pin port honours both the env var (HA_MCP_SIDECAR_PORT) and
|
|
820
|
+
# a value set via the settings UI Advanced tab (persisted to the override
|
|
821
|
+
# file and applied by get_global_settings). 0 = ephemeral. The lenient
|
|
822
|
+
# validator in config.Settings has already clamped any bad value to 0.
|
|
823
|
+
from .config import get_global_settings
|
|
824
|
+
|
|
825
|
+
port = _pick_free_port(get_global_settings().sidecar_pin_port)
|
|
799
826
|
secret_token = secrets.token_urlsafe(16)
|
|
800
827
|
secret_path = f"/private_{secret_token}"
|
|
801
828
|
url = f"http://127.0.0.1:{port}{secret_path}/settings"
|
|
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.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/dashboard_screenshot/__init__.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/dashboard_screenshot/capture.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/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
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/AGENTS.md
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/CLAUDE.md
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/resources/skills-vendor/LICENSE
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/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.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/best_practice_checker.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/smart_search/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/smart_search/_config.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/smart_search/_entities.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/smart_search/_overview.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/smart_search/_scenes.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/smart_search/_scoring.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tool_search_hint_middleware.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
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_config_automations.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_config_dashboards.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_config_helpers.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_config_scripts.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_dashboard_screenshot.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/tools_voice_assistant.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/tools/validation_middleware.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/transforms/categorized_search.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/transforms/lite_docstrings.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp/utils/kill_signal_diagnostics.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp_dev.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev713 → ha_mcp_dev-7.8.0.dev714}/src/ha_mcp_dev.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|