Skip to content

Releases: NodeJSmith/hassette

v0.23.0

20 Feb 15:28
8b9390d

Choose a tag to compare

[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.css with [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-expanded for accessibility (#262)
  • E2E tests now run by default with uv run pytest instead of requiring -m e2e; added nox -s e2e session for CI
  • HassetteHarness now 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_utils public API; tests import from the package instead of submodules (#253)
  • Replaced 28 asyncio.sleep() synchronization calls across 8 integration test files with wait_for polling helper for deterministic, faster tests (#253)
  • Renamed create_mock_hassette() to create_hassette_stub() and mock_hassette.py to web_mocks.py to 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-code background (#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() and model_dump_json() on AppManifest and HassetteConfig no 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)
  • IntFlag enums (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--ghost and ht-btn--xs button modifier classes (#262)
  • extras property and extra() helper on BaseState and AttributesBase for 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:js tasks (#251)

Removed

  • Bulma CSS CDN dependency (#262)
  • Entity Browser page and related partials (#262)

Full Changelog: v0.22.1...v0.23.0

v0.22.1

15 Feb 22:14
e4166ec

Choose a tag to compare

[0.22.1] - 2026-02-15

Added

  • Issue template migration from Markdown to YAML form templates (bug report, feature request, task, documentation)
  • /triage-issues Claude 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_reload config 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

14 Feb 01:02
d669ec9

Choose a tag to compare

[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_ui config option to enable/disable the UI independently from the API
    • Added section to docs covering the web UI
  • FastAPI web backend replacing the standalone HealthService with a full REST API and WebSocket server
    • GET /api/health, GET /api/healthz — system health and container healthchecks
    • GET /api/entities, GET /api/entities/{entity_id}, GET /api/entities/domain/{domain} — entity state access
    • GET /api/apps, GET /api/apps/{app_key}, GET /api/apps/manifests — app status and manifests
    • POST /api/apps/{app_key}/start|stop|reload — app management
    • GET /api/scheduler/jobs, GET /api/scheduler/history — scheduled jobs and execution history
    • GET /api/bus/listeners, GET /api/bus/metrics — per-listener execution metrics and aggregate summary
    • GET /api/events/recent, GET /api/logs/recent, GET /api/services, GET /api/config — events, logs, HA services, config
    • GET /api/ws — WebSocket endpoint for real-time state/event/log streaming with subscription controls
    • GET /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 ServiceWatcher
    • service_restart_max_attempts, service_restart_backoff_seconds, service_restart_max_backoff_seconds, service_restart_backoff_multiplier config options
  • scheduler_behind_schedule_threshold_seconds config 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 HealthService with WebApiService backed by FastAPI
  • Breaking: Config renames: run_health_servicerun_web_api, health_service_portweb_api_port, health_service_log_levelweb_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
  • Service base class now properly sequences serve() task lifecycle: spawns after on_initialize(), cancels before on_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

07 Feb 01:30
e4f074d

Choose a tag to compare

[0.21.0] - 2026-02-06

Changed

  • Refactored AppHandler into four focused components: AppRegistry (state tracking), AppFactory (instance creation), AppLifecycleManager (init/shutdown orchestration), and AppChangeDetector (configuration diffing)
  • File watcher now batches multiple file change events to prevent race conditions (changed_file_path payload is now changed_file_paths: frozenset[Path])
  • Renamed active_apps_config to active_manifests on AppRegistry
  • AppManifest.app_config now accepts both "config" and "app_config" keys

Added

  • HassetteAppStateEvent emitted when app instances change status (includes app_key, status, previous_status, exception details)
  • New Bus convenience methods: on_app_state_changed(), on_app_running(), on_app_stopping()
  • BlockReason enum and blocked app tracking in AppRegistry to distinguish "enabled but excluded by @only_app" from "not configured"
  • ResourceStatus.STOPPING enum value
  • enabled_manifests property on AppRegistry for querying enabled apps regardless of only_app filter
  • StateManager.get(entity_id) for generic entity access with automatic domain-type resolution and BaseState fallback

Fixed

  • Removing @only_app decorator now correctly starts previously-blocked apps during hot reload

Full Changelog: v0.20.4...v0.21.0

v0.20.4

06 Feb 05:01
0952c75

Choose a tag to compare

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

02 Feb 00:59
3f369bf

Choose a tag to compare

What's Changed

Full Changelog: v0.20.2...v0.20.3

v0.20.2

01 Feb 19:59
b34e5f9

Choose a tag to compare

What's Changed

Full Changelog: v0.20.1...v0.20.2

v0.20.1

01 Feb 19:24
7cbedf5

Choose a tag to compare

What's Changed

Full Changelog: v0.20.0...v0.20.1

v0.20.0

01 Feb 19:00
7c74d92

Choose a tag to compare

[0.20.0] - 2026-02-01

Added

  • Add --version/-v argument to Hassette to allow displaying the current version
  • Add __iter__, __contains__, keys, values, and items methods to StateManager and StateRegistry
  • Add functionality to route state_change events to more specific handlers based on domain and/or entity_id
    • This is done automatically by the Bus by 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
  • Add AnnotationConverter class and TypeMatcher class for more robust validation/conversion during DI
  • Add A, P, C, and D aliases to hassette.__init__ for simpler imports
    • A = hassette.event_handling.accessors
    • P = hassette.event_handling.predicates
    • C = hassette.event_handling.conditions
    • D = hassette.event_handling.dependencies
  • Add new Comparison condition 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 attrs
    • get_all_attrs_<old|new|old_new> - get all attributes as a dict
  • Add get_all_changes accessor 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 BaseState when we do not find a class in the StateRegistry
    • This does not work because BaseState doesn't have a domain
    • Error is now raised instead
  • 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
  • MediaPlayerState now has attributes using the correct type

Changed

  • BREAKING: Replaced StateManager.get_states with __getitem__ that accepts a state class
    • The error raised in StateManager when a state class is not found in the StateRegistry now advises to use this method
  • Renamed LOG_LEVELS to LOG_LEVEL_TYPE
  • Renamed get_default_dict to get_defaults_dict to be more clear this is not referring to defaultdict class
  • Use same validation for AppConfig log level as we do for Hassette config log level
  • Extracted nested Attributes classes for each state out of class definition to make them first class citizens
    • e.g. MediaPlayerState.Attributes is now MediaPlayerAttributes

Docs

  • Remove Why Hassette page
  • Remove docker networking page
  • Very large cleanup/reorg/addition of docs

Full Changelog: v0.19.2...v0.20.0

v0.19.2

26 Jan 05:12
089ccd3

Choose a tag to compare

[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