Releases: NodeJSmith/hassette
Releases · NodeJSmith/hassette
v0.23.0
[0.23.0] - 2026-02-19
Changed
- Replaced Bulma CSS framework with a custom
ht-prefixed design system featuring cool slate surfaces, warm amber accent, and Space Grotesk + JetBrains Mono typography (#262) - Extracted all design tokens into
tokens.csswith[data-theme]selector support for future theming (#262) - Redesigned dashboard with app status chip grid, activity timeline, and streamlined layout (#262)
- App detail pages now use a flat single-page layout with collapsible metadata, inline tracebacks, and instance switcher dropdown (#262)
- Bus listener and scheduler job tables show expanded detail rows with predicate, rate-limiting, and trigger information (#262)
- Replaced hardcoded CSS fallback colors in alerts and detail panels with proper design tokens (
--ht-surface-inset,--ht-surface-code,--ht-warning-*,--ht-danger-*) - Toggle buttons now show fallback text before Alpine.js initializes and expose
aria-expandedfor accessibility (#262) - E2E tests now run by default with
uv run pytestinstead of requiring-m e2e; addednox -s e2esession for CI HassetteHarnessnow uses a fluent builder API (with_bus(),with_state_proxy(), etc.) with automatic dependency resolution instead of boolean flags (#253)- Consolidated duplicate mock Hassette, DataSyncService, and web test helper fixtures into shared factories in
test_utils/(#253) - All test helper functions now exported from
hassette.test_utilspublic API; tests import from the package instead of submodules (#253) - Replaced 28
asyncio.sleep()synchronization calls across 8 integration test files withwait_forpolling helper for deterministic, faster tests (#253) - Renamed
create_mock_hassette()tocreate_hassette_stub()andmock_hassette.pytoweb_mocks.pyto clarify web/API stub vs harness distinction (#259) - Added autouse cleanup fixtures for bus, scheduler, and mock API to prevent test pollution in module-scoped fixtures (#256)
Fixed
- WebSocket service now fires disconnect event and marks not-ready immediately on unexpected connection loss, preventing stale state in StateProxy (#270)
- App detail page now uses the actual instance index instead of hardcoded 0, fixing data/URL desync for non-zero instances (#262)
- Detail panel labels now have proper text contrast on dark
--ht-surface-codebackground (#262) - Collapsible panels and tracebacks no longer flash visible before Alpine.js initializes (#262)
- Entity browser "Load more" button now appends rows instead of replacing existing ones on domain-filtered views (#247)
model_dump()andmodel_dump_json()onAppManifestandHassetteConfigno longer leak extra fields (e.g. tokens from environment variables)
Added
supports_*boolean properties on light, climate, cover, fan, media_player, and vacuum attribute classes for checking entity capabilities without manual bitmask operations (#272)IntFlagenums (LightEntityFeature,ClimateEntityFeature, etc.) matching Home Assistant core feature flags (#272)- Global alert banner showing HA disconnect warnings and failed app errors with expandable tracebacks (#262)
ht-btn--ghostandht-btn--xsbutton modifier classes (#262)extrasproperty andextra()helper onBaseStateandAttributesBasefor safe access to integration-specific attributes (#271)- JSDoc comments across all web UI JavaScript files (#251)
- ESLint linting, TypeScript type-checking, and
mise run lint:js/mise run typecheck:jstasks (#251)
Removed
Full Changelog: v0.22.1...v0.23.0
v0.22.1
[0.22.1] - 2026-02-15
Added
- Issue template migration from Markdown to YAML form templates (bug report, feature request, task, documentation)
/triage-issuesClaude command for auditing and cleaning up GitHub issues against project conventions- Updated CLAUDE.md with GitHub Issues conventions (title, labels, milestones, body sections)
web_ui_hot_reloadconfig option — watches web UI static files and templates for changes, pushing live reloads to the browser via WebSocket. CSS changes are hot-swapped without a page reload; template and JS changes trigger a full reload.- Collapsible sidebar with persistent icon rail on desktop and mobile — click the toggle or press Escape to expand/collapse
- SPA-like page navigation via HTMX boost — page transitions without full reloads
Changed
- Live dashboard/page updates now use WebSocket push with idiomorph DOM morphing instead of 30-second polling intervals
Full Changelog: v0.22.0...v0.22.1
v0.22.0
[0.22.0] - 2026-02-13
Added
- Web UI — server-rendered monitoring dashboard at
/ui/using Jinja2, HTMX, Alpine.js, and Bulma CSS- Dashboard — system health, apps summary, bus metrics, and recent events with WebSocket-driven live updates
- Apps page — shows all configured app manifests with status badges, start/stop/reload controls, and status filter tabs; single-instance apps link directly to instance detail
- App detail (
/ui/apps/{key}) — manifest config, bus listener metrics, scheduled jobs, and filtered log viewer; multi-instance apps show expandable instance table - Instance detail (
/ui/apps/{key}/{index}) — per-instance bus listeners, jobs, and logs - Log viewer (
/ui/logs) — client-side filtering by level/app/text, sortable columns, and real-time WebSocket log streaming - Scheduler page (
/ui/scheduler) — scheduled jobs and execution history, filterable by app - Entity browser (
/ui/entities) — browse entities by domain with text search and pagination - Event Bus page (
/ui/bus) — bus listener metrics, filterable by app run_web_uiconfig option to enable/disable the UI independently from the API- Added section to docs covering the web UI
- FastAPI web backend replacing the standalone
HealthServicewith a full REST API and WebSocket serverGET /api/health,GET /api/healthz— system health and container healthchecksGET /api/entities,GET /api/entities/{entity_id},GET /api/entities/domain/{domain}— entity state accessGET /api/apps,GET /api/apps/{app_key},GET /api/apps/manifests— app status and manifestsPOST /api/apps/{app_key}/start|stop|reload— app managementGET /api/scheduler/jobs,GET /api/scheduler/history— scheduled jobs and execution historyGET /api/bus/listeners,GET /api/bus/metrics— per-listener execution metrics and aggregate summaryGET /api/events/recent,GET /api/logs/recent,GET /api/services,GET /api/config— events, logs, HA services, configGET /api/ws— WebSocket endpoint for real-time state/event/log streaming with subscription controlsGET /api/docs— interactive OpenAPI documentation
- Event handler execution metrics — per-listener aggregate counters (invocations, successes, failures, DI failures, timing) exposed via REST API and web UI
- Scheduler job execution history — per-job execution records with timing and error details
- Configurable service restart with exponential backoff in
ServiceWatcherservice_restart_max_attempts,service_restart_backoff_seconds,service_restart_max_backoff_seconds,service_restart_backoff_multiplierconfig options
scheduler_behind_schedule_threshold_secondsconfig option (default: 5) — configurable threshold before a "behind schedule" warning is logged for a job (previously hard-coded to 1 second)- Playwright e2e test suite for the web UI (34 tests; run with
pytest -m e2e)
Changed
- Breaking: Replaced
HealthServicewithWebApiServicebacked by FastAPI - Breaking: Config renames:
run_health_service→run_web_api,health_service_port→web_api_port,health_service_log_level→web_api_log_level - New config options:
web_api_host,web_api_cors_origins,web_api_event_buffer_size,web_api_log_buffer_size,web_api_job_history_size Servicebase class now properly sequencesserve()task lifecycle: spawns afteron_initialize(), cancels beforeon_shutdown()
Fixed
- WebSocket disconnect handling no longer produces spurious ERROR logs during normal page navigation
- Scheduler dispatch loop uses single lock acquisition per cycle, reducing scheduling latency
Removed
HealthService(src/hassette/core/health_service.py) — replaced by FastAPI web backend
v0.21.0
[0.21.0] - 2026-02-06
Changed
- Refactored
AppHandlerinto four focused components:AppRegistry(state tracking),AppFactory(instance creation),AppLifecycleManager(init/shutdown orchestration), andAppChangeDetector(configuration diffing) - File watcher now batches multiple file change events to prevent race conditions (
changed_file_pathpayload is nowchanged_file_paths: frozenset[Path]) - Renamed
active_apps_configtoactive_manifestsonAppRegistry AppManifest.app_confignow accepts both"config"and"app_config"keys
Added
HassetteAppStateEventemitted when app instances change status (includes app_key, status, previous_status, exception details)- New
Busconvenience methods:on_app_state_changed(),on_app_running(),on_app_stopping() BlockReasonenum and blocked app tracking inAppRegistryto distinguish "enabled but excluded by@only_app" from "not configured"ResourceStatus.STOPPINGenum valueenabled_manifestsproperty onAppRegistryfor querying enabled apps regardless ofonly_appfilterStateManager.get(entity_id)for generic entity access with automatic domain-type resolution andBaseStatefallback
Fixed
- Removing
@only_appdecorator now correctly starts previously-blocked apps during hot reload
Full Changelog: v0.20.4...v0.21.0
v0.20.4
What's Changed
- Add Claude Code GitHub Workflow by @NodeJSmith in #226
- Improve documentation with persistent storage guide and cross-references by @NodeJSmith in #227
- Fix docker_start.sh handling of requirements.txt files by @mlsteele in #228
- Add tests for Docker requirements.txt discovery by @NodeJSmith in #229
New Contributors
Full Changelog: v0.20.3...v0.20.4
v0.20.3
What's Changed
- another round of docs/examples cleanup by @NodeJSmith in #221
- Fix/source optional by @NodeJSmith in #223
Full Changelog: v0.20.2...v0.20.3
v0.20.2
What's Changed
- improve tags action by @NodeJSmith in #217
- Improve landing page text, rename parameter in Comparison by @NodeJSmith in #220
Full Changelog: v0.20.1...v0.20.2
v0.20.1
What's Changed
- add flavor: latest=false to prevent latest tag by @NodeJSmith in #215
- Fix/add back venv activate by @NodeJSmith in #216
Full Changelog: v0.20.0...v0.20.1
v0.20.0
[0.20.0] - 2026-02-01
Added
- Add --version/-v argument to Hassette to allow displaying the current version
- Add
__iter__,__contains__,keys,values, anditemsmethods to StateManager and StateRegistry - Add functionality to route
state_changeevents to more specific handlers based on domain and/or entity_id- This is done automatically by the
Busby adding the entity_id to the topic when creating the listener - Matched listeners are deduplicated to ensure delivery only happens one time
- Events are dispatched to the most specific route if there are multiple matches
- This is done automatically by the
- Add
AnnotationConverterclass andTypeMatcherclass for more robust validation/conversion during DI - Add A, P, C, and D aliases to
hassette.__init__for simpler importsA=hassette.event_handling.accessorsP=hassette.event_handling.predicatesC=hassette.event_handling.conditionsD=hassette.event_handling.dependencies
- Add new
Comparisoncondition for basic operators (e.g.==,!=,<,>, etc.) to compare values in state/attribute change listeners - Add new accessors for getting multiple/all attributes at once from state change events
get_attrs_<old|new|old_new>- specify a list of attrsget_all_attrs_<old|new|old_new>- get all attributes as a dict
- Add
get_all_changesaccessor that returns a dictionary of all changes, including state and all attributes
Fixed
- Fix AppHandler reporting failed apps as successful by using status attribute
- This is due to some issues with how we're tracking apps, further fixes will need to happen in future releases
- Fix StateManager using
BaseStatewhen we do not find a class in theStateRegistry- This does not work because
BaseStatedoesn't have adomain - Error is now raised instead
- This does not work because
- Log level is now used by Apps if set directly in AppConfig in Python code (as opposed to config file)
- Fix HassPayload's context attribute not being a HassContext instance
MediaPlayerStatenow hasattributesusing the correct type
Changed
- BREAKING: Replaced
StateManager.get_stateswith__getitem__that accepts a state class- The error raised in StateManager when a state class is not found in the
StateRegistrynow advises to use this method
- The error raised in StateManager when a state class is not found in the
- Renamed
LOG_LEVELStoLOG_LEVEL_TYPE - Renamed
get_default_dicttoget_defaults_dictto be more clear this is not referring todefaultdictclass - Use same validation for
AppConfiglog level as we do forHassetteconfig log level - Extracted nested Attributes classes for each state out of class definition to make them first class citizens
- e.g.
MediaPlayerState.Attributesis nowMediaPlayerAttributes
- e.g.
Docs
- Remove
Why Hassettepage - Remove docker networking page
- Very large cleanup/reorg/addition of docs
Full Changelog: v0.19.2...v0.20.0
v0.19.2
[0.19.2] - 2026-01-25
Fixed
- Change log level for state cache loading message from INFO to DEBUG
Full Changelog: v0.19.1...v0.19.2