ha-mcp-dev 7.8.0.dev701__tar.gz → 7.8.0.dev702__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.dev701/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.8.0.dev702}/PKG-INFO +1 -1
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/pyproject.toml +1 -1
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/settings.css +7 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/settings.js +71 -17
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/settings_ui.py +19 -16
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/LICENSE +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/MANIFEST.in +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/README.md +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/setup.cfg +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/__main__.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/_pypi_marker +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/_version.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/auth/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/auth/consent_form.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/auth/provider.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/backup_manager.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/client/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/client/rest_client.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/client/supervisor_client.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/client/websocket_client.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/client/websocket_listener.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/config.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/dashboard_screenshot/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/dashboard_screenshot/capture.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/dashboard_screenshot/provision.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/errors.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/policy/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/policy/approval_queue.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/policy/evaluator.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/policy/handlers.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/policy/middleware.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/policy/model.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/policy/persistence.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/policy/value_sources.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/py.typed +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/read_only.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/.github/pull_request_template.md +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/yaml-only-integrations.md +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/server.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/smoke_test.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/stdio_settings_sidecar.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/auto_backup.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/backup.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/best_practice_checker.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/config_entry_flow.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/device_control.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/enhanced.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/helpers.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/reference_validator.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/registry.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/smart_search/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/smart_search/_base.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/smart_search/_config.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/smart_search/_deep.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/smart_search/_entities.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/smart_search/_fetch.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/smart_search/_overview.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/smart_search/_scenes.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/smart_search/_scoring.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tool_search_hint_middleware.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_addons.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_areas.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_blueprints.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_bug_report.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_calendar.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_camera.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_categories.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_code.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_config_automations.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_dashboard_screenshot.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_energy.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_entities.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_filesystem.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_groups.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_hacs.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_history.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_integrations.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_labels.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_registry.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_resources.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_search.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_service.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_services.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_system.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_themes.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_todo.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_traces.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_updates.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_utility.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_zones.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/util_helpers.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/validation_middleware.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/transforms/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/transforms/categorized_search.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/utils/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/utils/config_hash.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/utils/data_paths.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/utils/domain_handlers.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/utils/fuzzy_search.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/utils/operation_manager.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/utils/python_sandbox.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/utils/skill_loader.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/utils/usage_logger.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/tests/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/tests/test_constants.py +0 -0
- {ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/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.dev702"
|
|
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"
|
|
@@ -415,6 +415,13 @@
|
|
|
415
415
|
fieldset.a11y-options { border: 0; padding: 0; margin: 0; min-inline-size: auto; }
|
|
416
416
|
.visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0;
|
|
417
417
|
margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
|
|
418
|
+
/* Skip-to-content link: visually hidden until focused, then pinned to the
|
|
419
|
+
top-left so keyboard users can bypass the header. */
|
|
420
|
+
.skip-link { position: absolute; left: 8px; top: -56px; z-index: 100;
|
|
421
|
+
padding: 8px 16px; border-radius: 8px; font-size: 0.875rem; font-weight: 600;
|
|
422
|
+
background: var(--surface); color: var(--text); border: 1px solid var(--border);
|
|
423
|
+
transition: top 0.15s ease; }
|
|
424
|
+
.skip-link:focus { top: 8px; outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
418
425
|
.a11y-option { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px;
|
|
419
426
|
border: 1px solid var(--border); border-radius: 8px; cursor: pointer; font-size: 0.85rem;
|
|
420
427
|
background: var(--bg); user-select: none; }
|
|
@@ -9,11 +9,13 @@ window.addEventListener('error', (e) => {
|
|
|
9
9
|
const el = document.getElementById('status');
|
|
10
10
|
if (!el) return;
|
|
11
11
|
const where = e.filename ? `${e.filename}:${e.lineno}:${e.colno}` : 'inline';
|
|
12
|
+
setStatusAlert(el, true);
|
|
12
13
|
el.textContent = `JS error: ${e.message} @ ${where}`;
|
|
13
14
|
});
|
|
14
15
|
window.addEventListener('unhandledrejection', (e) => {
|
|
15
16
|
const el = document.getElementById('status');
|
|
16
17
|
if (!el) return;
|
|
18
|
+
setStatusAlert(el, true);
|
|
17
19
|
el.textContent = `Async error: ${e.reason && e.reason.message ? e.reason.message : String(e.reason)}`;
|
|
18
20
|
});
|
|
19
21
|
|
|
@@ -135,18 +137,18 @@ async function loadTools() {
|
|
|
135
137
|
try {
|
|
136
138
|
resp = await fetch('./api/settings/tools');
|
|
137
139
|
} catch (e) {
|
|
138
|
-
updateStatus('Network error reaching /api/settings/tools: ' + e.message);
|
|
140
|
+
updateStatus('Network error reaching /api/settings/tools: ' + e.message, false, true);
|
|
139
141
|
return;
|
|
140
142
|
}
|
|
141
143
|
if (!resp.ok) {
|
|
142
|
-
updateStatus(`/api/settings/tools returned HTTP ${resp.status} ${resp.statusText}
|
|
144
|
+
updateStatus(`/api/settings/tools returned HTTP ${resp.status} ${resp.statusText}`, false, true);
|
|
143
145
|
return;
|
|
144
146
|
}
|
|
145
147
|
let data;
|
|
146
148
|
try {
|
|
147
149
|
data = await resp.json();
|
|
148
150
|
} catch (e) {
|
|
149
|
-
updateStatus('Failed to parse /api/settings/tools response as JSON: ' + e.message);
|
|
151
|
+
updateStatus('Failed to parse /api/settings/tools response as JSON: ' + e.message, false, true);
|
|
150
152
|
return;
|
|
151
153
|
}
|
|
152
154
|
toolData = data.tools || [];
|
|
@@ -169,14 +171,15 @@ async function loadTools() {
|
|
|
169
171
|
// the user where to look instead of leaving them on "Loading".
|
|
170
172
|
updateStatus(
|
|
171
173
|
'No tools found. The sidecar reads ~/.ha-mcp/tool_metadata.json — ' +
|
|
172
|
-
'if missing/empty, restart your MCP client. See ~/.ha-mcp/sidecar.log for details.'
|
|
174
|
+
'if missing/empty, restart your MCP client. See ~/.ha-mcp/sidecar.log for details.',
|
|
175
|
+
false, true
|
|
173
176
|
);
|
|
174
177
|
return;
|
|
175
178
|
}
|
|
176
179
|
try {
|
|
177
180
|
render();
|
|
178
181
|
} catch (e) {
|
|
179
|
-
updateStatus('Render failed: ' + e.message + ' (open browser devtools for the stack)');
|
|
182
|
+
updateStatus('Render failed: ' + e.message + ' (open browser devtools for the stack)', false, true);
|
|
180
183
|
throw e;
|
|
181
184
|
}
|
|
182
185
|
updateStatus('Loaded');
|
|
@@ -765,14 +768,24 @@ async function saveConfig() {
|
|
|
765
768
|
// are on.
|
|
766
769
|
if (restartChannel) restartChannel.postMessage({type: 'restart-required'});
|
|
767
770
|
} else {
|
|
768
|
-
updateStatus('Save failed!');
|
|
771
|
+
updateStatus('Save failed!', false, true);
|
|
769
772
|
}
|
|
770
773
|
}
|
|
771
774
|
|
|
772
|
-
|
|
775
|
+
// Reflect success/error semantics on a status span for assistive tech:
|
|
776
|
+
// failures switch to role=alert/assertive so screen readers interrupt; all
|
|
777
|
+
// other updates stay role=status/polite (matching the static markup). (#1596)
|
|
778
|
+
function setStatusAlert(el, isError) {
|
|
779
|
+
if (!el) return;
|
|
780
|
+
el.setAttribute('role', isError ? 'alert' : 'status');
|
|
781
|
+
el.setAttribute('aria-live', isError ? 'assertive' : 'polite');
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
function updateStatus(text, saved, isError) {
|
|
773
785
|
const el = document.getElementById('status');
|
|
774
|
-
el
|
|
786
|
+
setStatusAlert(el, isError);
|
|
775
787
|
el.className = saved ? 'status saved' : 'status';
|
|
788
|
+
el.textContent = text;
|
|
776
789
|
}
|
|
777
790
|
|
|
778
791
|
function applyToolSearch() {
|
|
@@ -916,6 +929,7 @@ async function saveBackupConfig() {
|
|
|
916
929
|
return;
|
|
917
930
|
}
|
|
918
931
|
btn.disabled = true;
|
|
932
|
+
setStatusAlert(statusEl, false);
|
|
919
933
|
statusEl.textContent = 'Saving…';
|
|
920
934
|
try {
|
|
921
935
|
const resp = await fetch('./api/settings/backup-config', {
|
|
@@ -931,6 +945,7 @@ async function saveBackupConfig() {
|
|
|
931
945
|
if (typeof data.error === 'string') msg = data.error;
|
|
932
946
|
else if (data.error.message) msg = data.error.message;
|
|
933
947
|
}
|
|
948
|
+
setStatusAlert(statusEl, true);
|
|
934
949
|
statusEl.textContent = msg;
|
|
935
950
|
return;
|
|
936
951
|
}
|
|
@@ -958,6 +973,7 @@ async function saveBackupConfig() {
|
|
|
958
973
|
}
|
|
959
974
|
} catch (err) {
|
|
960
975
|
btn.disabled = false;
|
|
976
|
+
setStatusAlert(statusEl, true);
|
|
961
977
|
statusEl.textContent = 'Network error: ' + String(err);
|
|
962
978
|
}
|
|
963
979
|
}
|
|
@@ -1050,6 +1066,8 @@ function renderFsCustomPathsSubForm(parentEl, masterOn, fsOn) {
|
|
|
1050
1066
|
const status = document.createElement('div');
|
|
1051
1067
|
status.id = 'fsCustomPathsStatus';
|
|
1052
1068
|
status.className = 'feature-help';
|
|
1069
|
+
status.setAttribute('role', 'status');
|
|
1070
|
+
status.setAttribute('aria-live', 'polite');
|
|
1053
1071
|
control.appendChild(ta);
|
|
1054
1072
|
control.appendChild(btn);
|
|
1055
1073
|
control.appendChild(status);
|
|
@@ -1070,6 +1088,7 @@ async function saveFsCustomPaths() {
|
|
|
1070
1088
|
.map(s => s.trim())
|
|
1071
1089
|
.filter(s => s.length);
|
|
1072
1090
|
btn.disabled = true;
|
|
1091
|
+
setStatusAlert(statusEl, false);
|
|
1073
1092
|
statusEl.textContent = 'Saving…';
|
|
1074
1093
|
try {
|
|
1075
1094
|
const resp = await fetch('./api/settings/fs-custom-paths', {
|
|
@@ -1085,6 +1104,7 @@ async function saveFsCustomPaths() {
|
|
|
1085
1104
|
if (typeof data.error === 'string') msg = data.error;
|
|
1086
1105
|
else if (data.error.message) msg = data.error.message;
|
|
1087
1106
|
}
|
|
1107
|
+
setStatusAlert(statusEl, true);
|
|
1088
1108
|
statusEl.textContent = msg;
|
|
1089
1109
|
return;
|
|
1090
1110
|
}
|
|
@@ -1101,6 +1121,7 @@ async function saveFsCustomPaths() {
|
|
|
1101
1121
|
: 'Saved.';
|
|
1102
1122
|
} catch (err) {
|
|
1103
1123
|
btn.disabled = false;
|
|
1124
|
+
setStatusAlert(statusEl, true);
|
|
1104
1125
|
statusEl.textContent = 'Network error: ' + String(err);
|
|
1105
1126
|
}
|
|
1106
1127
|
}
|
|
@@ -2453,15 +2474,18 @@ async function removePolicyRule(toolName) {
|
|
|
2453
2474
|
|
|
2454
2475
|
async function saveGlobalSettings() {
|
|
2455
2476
|
const statusEl = document.getElementById('policy-global-save-status');
|
|
2477
|
+
setStatusAlert(statusEl, false);
|
|
2456
2478
|
statusEl.textContent = 'Saving...';
|
|
2457
2479
|
let resp;
|
|
2458
2480
|
try {
|
|
2459
2481
|
resp = await fetch('./api/policy/config');
|
|
2460
2482
|
} catch (e) {
|
|
2483
|
+
setStatusAlert(statusEl, true);
|
|
2461
2484
|
statusEl.textContent = 'Network error: ' + e.message;
|
|
2462
2485
|
return;
|
|
2463
2486
|
}
|
|
2464
2487
|
if (!resp.ok) {
|
|
2488
|
+
setStatusAlert(statusEl, true);
|
|
2465
2489
|
statusEl.textContent = 'Load failed: ' + resp.status;
|
|
2466
2490
|
return;
|
|
2467
2491
|
}
|
|
@@ -2472,6 +2496,7 @@ async function saveGlobalSettings() {
|
|
|
2472
2496
|
await policyPut(policy, 'Save global settings');
|
|
2473
2497
|
statusEl.textContent = 'Saved.';
|
|
2474
2498
|
} catch (e) {
|
|
2499
|
+
setStatusAlert(statusEl, true);
|
|
2475
2500
|
statusEl.textContent = e.message;
|
|
2476
2501
|
}
|
|
2477
2502
|
}
|
|
@@ -2629,10 +2654,18 @@ setInterval(() => {
|
|
|
2629
2654
|
// Generic dispatcher — every .tab button names its target panel via
|
|
2630
2655
|
// data-panel, every .panel has matching id="panel-<name>". Adding a
|
|
2631
2656
|
// new tab is one button + one panel div; no JS change needed.
|
|
2632
|
-
function activateTab(target) {
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2657
|
+
function activateTab(target, opts) {
|
|
2658
|
+
const focusTab = opts && opts.focusTab;
|
|
2659
|
+
document.querySelectorAll('.tab').forEach(t => {
|
|
2660
|
+
const selected = t.dataset.panel === target;
|
|
2661
|
+
t.classList.toggle('active', selected);
|
|
2662
|
+
// Expose tab state + roving tabindex to assistive tech (WAI-ARIA APG
|
|
2663
|
+
// tabs pattern). Only the selected tab stays in the Tab sequence;
|
|
2664
|
+
// arrow keys move between the rest. (#1596)
|
|
2665
|
+
t.setAttribute('aria-selected', selected ? 'true' : 'false');
|
|
2666
|
+
t.tabIndex = selected ? 0 : -1;
|
|
2667
|
+
if (selected && focusTab) t.focus();
|
|
2668
|
+
});
|
|
2636
2669
|
document.querySelectorAll('.panel').forEach(p =>
|
|
2637
2670
|
p.classList.toggle('active', p.id === 'panel-' + target)
|
|
2638
2671
|
);
|
|
@@ -2649,6 +2682,27 @@ document.querySelectorAll('.tab').forEach(tab => {
|
|
|
2649
2682
|
tab.addEventListener('click', () => activateTab(tab.dataset.panel));
|
|
2650
2683
|
});
|
|
2651
2684
|
|
|
2685
|
+
// Keyboard navigation for the tablist (WAI-ARIA APG tabs pattern): Left/Right
|
|
2686
|
+
// move + activate the adjacent tab, Home/End jump to the ends. (#1596)
|
|
2687
|
+
{
|
|
2688
|
+
const tablist = document.querySelector('.tabs[role="tablist"]');
|
|
2689
|
+
if (tablist) {
|
|
2690
|
+
tablist.addEventListener('keydown', (e) => {
|
|
2691
|
+
const tabs = Array.from(tablist.querySelectorAll('.tab'));
|
|
2692
|
+
const currentIndex = tabs.indexOf(document.activeElement);
|
|
2693
|
+
if (currentIndex === -1) return;
|
|
2694
|
+
let nextIndex = null;
|
|
2695
|
+
if (e.key === 'ArrowRight') nextIndex = (currentIndex + 1) % tabs.length;
|
|
2696
|
+
else if (e.key === 'ArrowLeft') nextIndex = (currentIndex - 1 + tabs.length) % tabs.length;
|
|
2697
|
+
else if (e.key === 'Home') nextIndex = 0;
|
|
2698
|
+
else if (e.key === 'End') nextIndex = tabs.length - 1;
|
|
2699
|
+
if (nextIndex === null) return;
|
|
2700
|
+
e.preventDefault();
|
|
2701
|
+
activateTab(tabs[nextIndex].dataset.panel, { focusTab: true });
|
|
2702
|
+
});
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
|
|
2652
2706
|
// Cross-tab links — any <a data-panel-link="<name>"> switches tabs
|
|
2653
2707
|
// in-page rather than following the href (used by the "no gated
|
|
2654
2708
|
// tools" empty state to point users at the Tools tab).
|
|
@@ -2858,8 +2912,8 @@ function _advSaveStatusEls() {
|
|
|
2858
2912
|
document.getElementById('advSaveStatusTop'),
|
|
2859
2913
|
].filter(Boolean);
|
|
2860
2914
|
}
|
|
2861
|
-
function _setAdvSaveStatus(text) {
|
|
2862
|
-
_advSaveStatusEls().forEach(el => { el.textContent = text; });
|
|
2915
|
+
function _setAdvSaveStatus(text, isError) {
|
|
2916
|
+
_advSaveStatusEls().forEach(el => { setStatusAlert(el, isError); el.textContent = text; });
|
|
2863
2917
|
}
|
|
2864
2918
|
function _setAdvSaveDisabled(disabled) {
|
|
2865
2919
|
_advSaveBtns().forEach(b => { b.disabled = disabled; });
|
|
@@ -2934,7 +2988,7 @@ async function saveAdvancedSettings() {
|
|
|
2934
2988
|
data = {restart_required: true};
|
|
2935
2989
|
} else {
|
|
2936
2990
|
_setAdvSaveDisabled(false);
|
|
2937
|
-
_setAdvSaveStatus(`Save failed (HTTP ${resp.status}, non-JSON body)
|
|
2991
|
+
_setAdvSaveStatus(`Save failed (HTTP ${resp.status}, non-JSON body)`, true);
|
|
2938
2992
|
return;
|
|
2939
2993
|
}
|
|
2940
2994
|
}
|
|
@@ -2945,7 +2999,7 @@ async function saveAdvancedSettings() {
|
|
|
2945
2999
|
if (typeof data.error === 'string') msg = data.error;
|
|
2946
3000
|
else if (data.error.message) msg = data.error.message;
|
|
2947
3001
|
}
|
|
2948
|
-
_setAdvSaveStatus(msg);
|
|
3002
|
+
_setAdvSaveStatus(msg, true);
|
|
2949
3003
|
return;
|
|
2950
3004
|
}
|
|
2951
3005
|
}
|
|
@@ -2973,7 +3027,7 @@ async function saveAdvancedSettings() {
|
|
|
2973
3027
|
}
|
|
2974
3028
|
} catch (err) {
|
|
2975
3029
|
_setAdvSaveDisabled(false);
|
|
2976
|
-
_setAdvSaveStatus('Network error: ' + String(err));
|
|
3030
|
+
_setAdvSaveStatus('Network error: ' + String(err), true);
|
|
2977
3031
|
}
|
|
2978
3032
|
}
|
|
2979
3033
|
|
|
@@ -787,6 +787,7 @@ _SETTINGS_HTML = (
|
|
|
787
787
|
+ """</style>
|
|
788
788
|
</head>
|
|
789
789
|
<body>
|
|
790
|
+
<a href="#main-content" class="skip-link">Skip to content</a>
|
|
790
791
|
<div class="header">
|
|
791
792
|
<h1>HA-MCP Settings</h1>
|
|
792
793
|
<div style="display:flex;align-items:center;gap:8px">
|
|
@@ -798,15 +799,16 @@ _SETTINGS_HTML = (
|
|
|
798
799
|
<option value="dark">Dark</option>
|
|
799
800
|
</select>
|
|
800
801
|
</label>
|
|
801
|
-
<span id="status" class="status">Loading...</span>
|
|
802
|
+
<span id="status" class="status" role="status" aria-live="polite">Loading...</span>
|
|
802
803
|
</div>
|
|
803
804
|
</div>
|
|
804
|
-
<
|
|
805
|
-
|
|
806
|
-
<button class="tab" data-panel="
|
|
807
|
-
<button class="tab" data-panel="
|
|
808
|
-
<button class="tab" data-panel="
|
|
809
|
-
<button class="tab" data-panel="
|
|
805
|
+
<main id="main-content" tabindex="-1" style="outline:none">
|
|
806
|
+
<div class="tabs" role="tablist" aria-label="Settings sections">
|
|
807
|
+
<button class="tab active" data-panel="tools" role="tab" id="tab-tools" aria-controls="panel-tools" aria-selected="true">Tools</button>
|
|
808
|
+
<button class="tab" data-panel="server" role="tab" id="tab-server" aria-controls="panel-server" aria-selected="false" tabindex="-1">Server Settings</button>
|
|
809
|
+
<button class="tab" data-panel="backups" role="tab" id="tab-backups" aria-controls="panel-backups" aria-selected="false" tabindex="-1">Backups</button>
|
|
810
|
+
<button class="tab" data-panel="tool-security-policies" role="tab" id="tab-tool-security-policies" aria-controls="panel-tool-security-policies" aria-selected="false" tabindex="-1">Tool Security Policies</button>
|
|
811
|
+
<button class="tab" data-panel="accessibility" role="tab" id="tab-accessibility" aria-controls="panel-accessibility" aria-selected="false" tabindex="-1">Accessibility</button>
|
|
810
812
|
</div>
|
|
811
813
|
<div class="restart-notice" id="restartNotice">
|
|
812
814
|
<span class="restart-notice-text" id="restartNoticeText">
|
|
@@ -819,7 +821,7 @@ _SETTINGS_HTML = (
|
|
|
819
821
|
</span>
|
|
820
822
|
<button class="restart-btn" id="restartBtn" style="display:none">Restart Add-on</button>
|
|
821
823
|
</div>
|
|
822
|
-
<div class="panel active" id="panel-tools">
|
|
824
|
+
<div class="panel active" id="panel-tools" role="tabpanel" aria-labelledby="tab-tools" tabindex="0">
|
|
823
825
|
<div class="readonly-notice">
|
|
824
826
|
Server-wide features (Tool Search, YAML config editing, filesystem
|
|
825
827
|
tools, etc.) appear in both the <strong>Server Settings</strong>
|
|
@@ -859,7 +861,7 @@ _SETTINGS_HTML = (
|
|
|
859
861
|
<input type="text" class="search" id="search" placeholder="Search tools...">
|
|
860
862
|
<div id="groups"></div>
|
|
861
863
|
</div>
|
|
862
|
-
<div class="panel" id="panel-server">
|
|
864
|
+
<div class="panel" id="panel-server" role="tabpanel" aria-labelledby="tab-server" tabindex="0">
|
|
863
865
|
<div class="features-sub">
|
|
864
866
|
Tool Search, advanced settings. Changes take effect only after you
|
|
865
867
|
restart the add-on (applies the change server-side) AND reconnect or
|
|
@@ -880,7 +882,7 @@ _SETTINGS_HTML = (
|
|
|
880
882
|
</div>
|
|
881
883
|
<div id="advSaveRowTop" class="adv-save-row" style="display:none;">
|
|
882
884
|
<button id="advSaveBtnTop" class="adv-save-btn">💾 Save advanced settings</button>
|
|
883
|
-
<span id="advSaveStatusTop" class="status"></span>
|
|
885
|
+
<span id="advSaveStatusTop" class="status" role="status" aria-live="polite"></span>
|
|
884
886
|
</div>
|
|
885
887
|
<div id="featuresBody"></div>
|
|
886
888
|
|
|
@@ -917,7 +919,7 @@ _SETTINGS_HTML = (
|
|
|
917
919
|
</div>
|
|
918
920
|
<div id="advSaveRow" class="adv-save-row" style="display:none;">
|
|
919
921
|
<button id="advSaveBtn" class="adv-save-btn">💾 Save advanced settings</button>
|
|
920
|
-
<span id="advSaveStatus" class="status"></span>
|
|
922
|
+
<span id="advSaveStatus" class="status" role="status" aria-live="polite"></span>
|
|
921
923
|
</div>
|
|
922
924
|
|
|
923
925
|
<div id="sidecarStopRow" style="display:none; margin: 16px 0; text-align: right;">
|
|
@@ -926,13 +928,13 @@ _SETTINGS_HTML = (
|
|
|
926
928
|
>Permanently disable settings server</button>
|
|
927
929
|
</div>
|
|
928
930
|
</div>
|
|
929
|
-
<div class="panel" id="panel-backups">
|
|
931
|
+
<div class="panel" id="panel-backups" role="tabpanel" aria-labelledby="tab-backups" tabindex="0">
|
|
930
932
|
<div class="backup-state" id="backupState">Loading backup state…</div>
|
|
931
933
|
<div class="backup-config" id="backupConfig">
|
|
932
934
|
<div class="backup-config-form" id="backupConfigForm"></div>
|
|
933
935
|
<div class="backup-config-actions" id="backupConfigActions" style="display:none">
|
|
934
936
|
<button id="backupConfigSave">Save settings</button>
|
|
935
|
-
<span id="backupConfigStatus" class="status"></span>
|
|
937
|
+
<span id="backupConfigStatus" class="status" role="status" aria-live="polite"></span>
|
|
936
938
|
</div>
|
|
937
939
|
</div>
|
|
938
940
|
<div class="backup-filters">
|
|
@@ -943,7 +945,7 @@ _SETTINGS_HTML = (
|
|
|
943
945
|
</div>
|
|
944
946
|
<div id="backupList"></div>
|
|
945
947
|
</div>
|
|
946
|
-
<div class="panel" id="panel-tool-security-policies">
|
|
948
|
+
<div class="panel" id="panel-tool-security-policies" role="tabpanel" aria-labelledby="tab-tool-security-policies" tabindex="0">
|
|
947
949
|
<h2>Tool Security Policies</h2>
|
|
948
950
|
<p class="features-sub">
|
|
949
951
|
Per-tool approval gating for high-stakes calls. Use the
|
|
@@ -991,7 +993,7 @@ _SETTINGS_HTML = (
|
|
|
991
993
|
</div>
|
|
992
994
|
<div style="margin-top:10px; display:flex; align-items:center; gap:12px">
|
|
993
995
|
<button id="policy-save-global-btn" class="restart-btn">Save global settings</button>
|
|
994
|
-
<span id="policy-global-save-status" class="status"></span>
|
|
996
|
+
<span id="policy-global-save-status" class="status" role="status" aria-live="polite"></span>
|
|
995
997
|
</div>
|
|
996
998
|
</section>
|
|
997
999
|
|
|
@@ -1010,7 +1012,7 @@ _SETTINGS_HTML = (
|
|
|
1010
1012
|
<div id="policy-rules-list"></div>
|
|
1011
1013
|
</section>
|
|
1012
1014
|
</div>
|
|
1013
|
-
<div class="panel" id="panel-accessibility">
|
|
1015
|
+
<div class="panel" id="panel-accessibility" role="tabpanel" aria-labelledby="tab-accessibility" tabindex="0">
|
|
1014
1016
|
<p class="tool-desc" style="margin-bottom:16px">
|
|
1015
1017
|
These settings apply immediately and are saved in this browser and on the
|
|
1016
1018
|
server, so they survive restarts in every mode (including stdio, where the
|
|
@@ -1064,6 +1066,7 @@ _SETTINGS_HTML = (
|
|
|
1064
1066
|
<button id="a11y-reset" class="restart-btn" type="button">Reset to defaults</button>
|
|
1065
1067
|
</section>
|
|
1066
1068
|
</div>
|
|
1069
|
+
</main>
|
|
1067
1070
|
<div class="modal-backdrop" id="modalBackdrop">
|
|
1068
1071
|
<div class="modal">
|
|
1069
1072
|
<div class="modal-header">
|
|
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.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/dashboard_screenshot/__init__.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/dashboard_screenshot/capture.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/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.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/AGENTS.md
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/CLAUDE.md
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/LICENSE
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/resources/skills-vendor/README.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/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.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/smart_search/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/smart_search/_config.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/smart_search/_entities.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/smart_search/_overview.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/smart_search/_scenes.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/smart_search/_scoring.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/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.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_config_automations.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_config_dashboards.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_config_helpers.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/tools_config_scripts.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/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.dev701 → ha_mcp_dev-7.8.0.dev702}/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.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/tools/validation_middleware.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp/transforms/categorized_search.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/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.dev701 → ha_mcp_dev-7.8.0.dev702}/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.dev701 → ha_mcp_dev-7.8.0.dev702}/src/ha_mcp_dev.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev701 → ha_mcp_dev-7.8.0.dev702}/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
|