v1.2.0-preview.14 - Pulsar
Pre-releaseRelease Notes - 1.2.0
Release Date: March 2026
Code Name: "Pulsar"
ποΈ Overview
"Pulsar" introduces the Wyoming Voice Platform β a full local speech pipeline that turns Lucia into a Wyoming protocol-compatible voice satellite for Home Assistant. This release delivers streaming speech-to-text, speaker verification, wake word detection, speech enhancement, a multi-engine model management system, and a new dashboard Voice Platform page for configuring everything from one surface. In addition, we introduce the Conversation Command Parser β a fast-path processing pipeline that pattern-matches common voice commands (lights, climate, scenes) and executes them directly against Home Assistant, bypassing the LLM entirely for sub-50ms response times. We also introduce user-facing personalization to Lucia's orchestration layer, letting users define a personality prompt that rewrites all agent responses through an LLM before delivery, and introduces Pluggable Data Providers β an agnostic persistence layer that enables mono-container deployment as a Home Assistant add-on with InMemory caching and SQLite storage, eliminating the need for Redis and MongoDB on resource-constrained devices.
π Highlights
- Wyoming Protocol Server β Native TCP server implementing the Home Assistant Wyoming satellite protocol for real-time voice processing.
- Multi-Engine STT Pipeline β Hybrid streaming STT with progressive re-transcription, Sherpa streaming, Sherpa offline (Parakeet TDT/CTC), and IBM Granite 4.0 1B Speech ONNX engines.
- Speaker Verification & Profiling β Cosine-similarity speaker identification with enrolled profiles, provisional auto-discovery, adaptive profile updates, and guided voice enrollment onboarding.
- ONNX Auto-Detection β Automatic GPU/accelerator selection (CUDA, ROCm, OpenVINO, DirectML, CoreML) across all six inference engines β no manual configuration required.
- GTCRN Speech Enhancement β Real-time streaming noise reduction for cleaner audio in noisy environments.
- Voice Platform Dashboard β New unified control room for model management, speaker profiles, wake words, engine status, and real-time session monitoring.
- Personality Prompt β Configurable system prompt that rewrites the fan-in aggregated response through an LLM, giving Lucia a customizable personality (pirate speak, formal assistant, casual friend β you name it).
- Conversation Command Parser β New
POST /api/conversationendpoint with pattern-matching pipeline that executes common smart home commands (lights, climate, scenes) directly via skills β zero LLM latency for recognized commands, SSE-streamed LLM fallback for everything else. - Response Templates β Customizable response templates stored in MongoDB with
{placeholder}interpolation. Manage templates per skill/action from the dashboard with guided dropdowns and token insertion buttons. - Home Assistant Component v1.2 β Simplified integration migrated from A2A JSON-RPC to structured REST. No more agent catalog selection β just point to the host and go.
- Separate Model Support β Personality rewriting can use a different (cheaper/faster) model than the orchestrator, selectable from a dropdown of configured chat-type providers.
- Zero-Cost Opt-In β When no personality is configured, the pipeline is unchanged β no LLM call, no added latency.
- Pluggable Data Providers β Agnostic persistence layer with InMemory (replaces Redis) and SQLite (replaces MongoDB) alternatives, configurable via
DataProvider:CacheandDataProvider:Store. - Home Assistant Mono-Container β New
Dockerfile.hafor single-container deployment with zero external dependencies, CPU-only ONNX, and embedded dashboard. - CpuOnly Build Flag β MSBuild property
/p:CpuOnly=trueexcludes GPU ONNX packages for clean CPU-only container builds.
β¨ Features
Wyoming Protocol Server
- Full Wyoming satellite protocol implementation (audio-start, audio-chunk, audio-stop, transcribe, transcript, detect, not-detected)
- Persistent TCP connections with per-session state management
- Zeroconf/mDNS service advertisement for automatic Home Assistant discovery
- VAD-driven voice activity detection with configurable speech/silence thresholds
- Wake word detection with custom phrase support and per-speaker calibration
Multi-Engine Speech-to-Text
- HybridSttEngine β Streams audio through a lightweight online model, then re-transcribes the full utterance with a high-accuracy offline model for best-of-both-worlds latency and accuracy
- SherpaSttEngine β Pure streaming CTC/transducer inference for ultra-low-latency transcription
- SherpaOfflineSttEngine β Offline NeMo Parakeet TDT+CTC support for high-quality batch transcription
- GraniteOnnxEngine β IBM Granite 4.0 1B Speech ONNX with 3-model pipeline (audio encoder, embed tokens, auto-regressive decoder with 40-layer KV cache)
- Progressive re-transcription with burst detection and stability-based early stopping
- Per-engine model catalog with download, install, activate, and delete lifecycle
Speaker Verification & Voice Profiles
- Sherpa-onnx speaker embedding extraction with cosine similarity matching
- Enrolled speaker profiles with configurable verification threshold
- Provisional auto-discovery profiles for unknown speakers with interaction tracking
- Adaptive profile updates (exponential moving average) for high-confidence matches
- Guided onboarding flow with audio quality validation (SNR, duration checks)
- Profile merge, rename, and provisional-to-enrolled promotion via API and dashboard
- Audio clip capture, playback, reassignment, and per-profile management
- Redis-cached enrolled profiles for sub-millisecond lookup latency
- MongoDB-backed persistent storage with in-memory fallback
ONNX Provider Auto-Detection
OnnxProviderDetectorsingleton probesOrtEnv.Instance().GetAvailableProviders()at startup- Automatic selection priority: CUDA β ROCm β OpenVINO β DirectML β CoreML β CPU
- Applied to all six engines: SherpaDiarization, HybridSTT, SherpaStt, SherpaOfflineSTT, GraniteOnnx, GtcrnSpeechEnhancer
- Detected provider exposed in
/api/wyoming/statusand displayed on the dashboard status card with GPU badge - Graceful fallback β if an accelerated provider fails to initialize, falls through to CPU
Speech Enhancement
- GTCRN (Gated Temporal Convolutional Recurrent Network) streaming noise reduction
- Per-session enhancement with isolated overlap-add state
- Raw audio preserved separately for speaker verification to avoid spectral mismatch with enrollment data
Model Management System
- Centralized model catalog with architecture-aware compatibility filtering
- Background download with real-time progress tracking via SSE
- Multi-stage progress bars (download β extract β validate)
- Hot-reload model activation via
ActiveModelChangedevents β no restart required - Per-engine model views (STT, VAD, Wake Word, Speaker Embedding, Speech Enhancement)
- Startup model validation with dummy inference warmup
Voice Platform Dashboard
- Status tab β Engine readiness tiles, active model indicators, ONNX provider detection display, and guided next-steps checklist
- Models tab β Browse, download, activate, and delete models per engine type with real-time download progress
- Profiles tab β View enrolled and provisional speaker profiles, inline rename, promote to enrolled, merge profiles, manage audio clips with playback
- Wake Words tab β Register custom wake phrases with optional speaker enrollment, manage and delete entries
- Monitor tab β Real-time session monitoring via SSE with audio level meters, transcript log, and connection status
- Config panel β Voice verification threshold, provisional profile settings, adaptive profiles, and retention controls β persisted to MongoDB via ConfigStoreWriter
π Personality Prompt (PR #80)
Users can now define a personality prompt on the /configuration page under the new Personality Prompt section. When set, the ResultAggregatorExecutor passes the composed multi-agent response through an LLM with the personality instructions as the system prompt, rewriting the output to match the desired tone.
PersonalityPromptOptionsβ New config model withInstructions(the personality system prompt) andModelConnectionName(optional separate LLM for rewriting)WorkflowFactoryβ AcceptsIOptionsMonitor<PersonalityPromptOptions>for live config reload without restart. Conditionally resolves a separateIChatClientwhenModelConnectionNameis set, or falls back to the orchestrator's default model.ResultAggregatorExecutorβ After composing the raw message from agent responses, calls the personality LLM withsystem=instructions+user=composed message. Graceful fallback to raw message on LLM failure or empty response.- Resilient resolution β A misconfigured
ModelConnectionNamelogs a warning and disables personality for that request instead of failing the entire orchestration pipeline. - Cancellation-safe β
OperationCanceledExceptionpropagates correctly through the personality rewrite path.
π₯οΈ Dashboard
- Model provider dropdown β The
ModelConnectionNamefield renders as a searchable dropdown populated from configured chat-type model providers, matching the pattern used in Agent Definitions. - Textarea field type β New
textareafield type in the configuration page for multi-line prompt editing with vertical resize support. - Auto-discovery β The Personality Prompt section appears automatically in the configuration sidebar via schema API.
- Conversation Test Page β Interactive chat interface at
/conversationfor testing the command parser endpoint directly from the dashboard, with HA context simulation, SSE streaming, and response metadata badges showing whether commands were parsed locally or handled by the LLM. - Response Templates Page β Full CRUD management of response templates at
/response-templates, grouped by skill. Features pattern-driven SkillId/Action dropdowns populated from the parser, token insertion buttons for{entity},{action},{area}placeholders, and template preview with sample values. - Activity Dashboard Metrics β Three new summary cards: Command Parsed count, LLM Fallback count, and Parser Rate percentage showing the ratio of commands handled locally vs forwarded to the LLM.
π¬ Conversation Command Parser
POST /api/conversationβ New REST endpoint accepting structured JSON with user text and separated device/session context object. Returns instant JSON for parsed commands or SSE streaming for LLM fallback.- True LLM Bypass β Pattern-matched commands call skill methods (LightControlSkill, ClimateControlSkill, SceneControlSkill) directly against Home Assistant β zero LLM involvement, sub-50ms execution.
- Command Pattern Matching β Leverages the existing
CommandPatternRouterwith template syntax ({name},{name:opt1|opt2},[optional]), confidence scoring, and priority-based tiebreaking. - DirectSkillExecutor β Dispatches matched routes to concrete skill methods: light toggle/brightness, climate set temperature/adjust, scene activate. Resolves entities via captured text and device area context.
- Response Template System β MongoDB-stored templates with simple
{placeholder}interpolation, random variant selection for natural variety, and seed defaults for all supported commands. Managed via CRUD API and dashboard. - Context Reconstructor β Rebuilds system prompt from structured context JSON for LLM fallback, matching the format the orchestrator expects.
- Conversation Telemetry β OpenTelemetry counters (
conversation.command_parsed,conversation.llm_fallback,conversation.command_parsed.errors) and duration histograms, plus in-memory stats for the activity dashboard. - Multi-Turn Continuity β Server generates stable
conversationId(GUID) when client doesn't provide one, used consistently across command and LLM paths. GET /api/conversation/patternsβ Exposes registered command patterns with their SkillId, Action, placeholder tokens, and example templates for dashboard tooling.
π Home Assistant Component (v1.2.0-preview.1)
- REST Migration β Component migrated from A2A JSON-RPC 2.0 to the new
POST /api/conversationendpoint with structured context objects. - Simplified Setup β Removed agent catalog fetch and agent selection. Configuration requires only host URL + API key.
- SSE Streaming β Handles both instant JSON (command parsed) and SSE event streams (LLM fallback) from the conversation endpoint.
- Structured Context β Device ID, area, type, user ID, timestamp, and location sent as typed JSON fields instead of embedded in prompt text.
- Auto-Generated Conversation IDs β Generates UUID for first-turn conversations, maintaining multi-turn continuity via the tracker.
- Optional Prompt Override β Configurable prompt template override in the HA options flow.
π§Ί Project Laundry
- SDK Pinned β Pinned .NET 10 to the latest appropriate minimal SDK
- Removed outdated docs β Removed a lot of outdated docs and old AI assistance templates and prompts.
- Package Updates β Updated all central projects to the latest versions from .NET 10.0.4 security patch
π Pluggable Data Providers
The new lucia.Data project introduces provider-agnostic persistence, enabling Lucia to run without Redis or MongoDB:
Cache Providers (replacing Redis):
InMemorySessionCacheServiceβ Multi-turn conversation state with sliding expirationInMemoryDeviceCacheServiceβ Home Assistant entity caching with TTL supportInMemoryPromptCacheServiceβ Routing and response caching with SHA256 + semantic similarity matchingInMemoryTaskStoreβ A2A task persistence with configurable TTL and periodic cleanupInMemoryEntityLocationServiceβ Floor/area/entity graph with hybrid entity matching
Store Providers (replacing MongoDB):
- 17 SQLite repository implementations covering all 4 MongoDB databases (luciaconfig, luciatraces, luciatasks, luciawyoming)
- Hybrid schema: indexed columns for query performance + JSON blob for full document storage
- Code-first migrations with
SqliteMigrationRunnerand versioned schema tracking SqliteConfigurationProviderwith polling-based hot-reload matching the MongoDB provider pattern
Configuration:
{
"DataProvider": {
"Cache": "InMemory",
"Store": "SQLite",
"SqlitePath": "./data/lucia.db"
}
}Interface Abstractions:
IConfigStoreWriterβ New interface for configuration CRUD (extracted fromConfigStoreWriter)ITaskIdIndexβ New interface for task ID enumeration (extracted from Redis-specific key scanning)ConfigSeederrefactored to useIConfigStoreWriterinstead ofIMongoClientTaskArchivalServicerefactored to useITaskIdIndexinstead ofIConnectionMultiplexer- All API endpoints updated to use abstractions (no direct
IMongoClientorIConnectionMultiplexerinjection)
π¦ Home Assistant Mono-Container
New infra/docker/Dockerfile.ha for resource-constrained deployment:
- Zero Dependencies β No Redis, MongoDB, or GPU drivers required
- CPU-Only ONNX β
CpuOnly=trueMSBuild flag excludesMicrosoft.ML.OnnxRuntime.Gpu.Linux, verified ONNX provider detection with graceful CPU fallback - Embedded Dashboard β React SPA built and bundled into
wwwroot/in a multi-stage Docker build - SQLite Persistence β Single
/data/lucia.dbfile for all configuration, traces, tasks, and voice data - Volume Mounts β
/data(SQLite DB),/app/models(Wyoming voice models),/app/plugins(script plugins) - HA Add-on Support β
ha-addon/config.yamlwith ingress, port mapping, and options schema
π ONNX Provider Verification
OnnxProviderDetector now verifies each accelerated provider by attempting SessionOptions.AppendExecutionProvider_*() before selecting it. This prevents sherpa-onnx native crashes when CUDA shared libraries are absent β the detector gracefully falls back to CPUExecutionProvider.
π Bug Fixes
- CUDA GPU acceleration not activating β
Microsoft.ML.OnnxRuntimeNuGet package was CPU-only. Replaced withMicrosoft.ML.OnnxRuntime.Gpu.Linux1.23.2 and aligned managed/native versions (was mismatched 1.23.2/1.22.0), enabling automaticCUDAExecutionProviderdetection on hosts with NVIDIA GPUs. Docker voice image verified working with RTX 4090 + CUDA 12.8 + cuDNN 9.20. - Wyoming describe response missing STT β
WyomingServiceInfoinjected a singleISttEngine?via DI, which resolved to the last registered engine (SherpaSttEngine). If that engine wasn't ready, STT was omitted from theinforesponse even when HybridSttEngine was ready. Now injectsIEnumerable<ISttEngine>and reports STT available if any engine is ready. - Parakeet model download "not found" β
ModelCatalogService.GetModelById(string)only searchedEngineType.Stt, but Parakeet TDT is registered asEngineType.OfflineStt. Now searches all engine types. Also fixed the download endpoint to resolve the model base path per engine type instead of hardcoding the STT path. - Activating Parakeet crashes server β
ModelManager.SwitchActiveModelAsync(string)hardcodedEngineType.Stt, causing the streamingOnlineRecognizerto load an offline transducer model (native crash:'window_size' does not exist in the metadata). Now resolves engine type from the catalog, routing offline models to HybridSttEngine correctly. - Cannot switch back to streaming STT after activating offline model β Both engines remained ready with no user preference tracking, so
FirstOrDefault(e => e.IsReady)always picked HybridSttEngine (registered first). AddedModelManager.PreferredSttEngineTypethat tracks the user's last activation choice. Status endpoint, session engine selection, and active model API all respect the preference. - HuggingFace API key not persisting in dashboard β
ConfigurationPage.entriesToValuesstripped only the first colon segment from stored keys (e.g.,Wyoming:HuggingFace:ApiTokenβHuggingFace:ApiToken). For nested config sections, this didn't match the schema property nameApiToken. Fixed to strip the full section prefix. - Speaker identification always returning unknown β Speech enhancement was altering audio used for embedding extraction, causing ~0.39 cosine similarity against enrollment profiles. Now uses raw (unenhanced) audio for speaker verification.
- Verification threshold changes from GUI ignored β
SpeakerVerificationThresholdconfig was never passed toIdentifySpeaker(). Now read viaIOptionsMonitor.CurrentValueat identification time. - Embedding dimension mismatches silently failed β After model changes,
CosineSimilaritythrew for mismatched dimensions, caught by outer try/catch returning null. Now gracefully skips with a warning log. - Voice config written to local JSON file β
VoiceConfigApiwas writing tovoiceconfig.jsoninstead of the platform's MongoDBConfigStoreWriter. Migrated to match established pattern. - Thread pool deadlock in STT finalization β
GetFinalResultblocked the thread pool. Converted to async with proper continuation. - Aspire resilience timeout killing model downloads β 3-minute default timeout was insufficient for large model downloads. Bypassed Aspire service discovery for external URLs.
- Progressive re-transcription mixing raw and enhanced audio β STT now always receives raw audio; enhanced audio used only for clip storage.
- WAV protocol wire format corrections β Proper transcribe/transcript event ordering per Wyoming protocol spec.
β‘ Performance
- Hybrid STT achieves ~90ms finalization latency at 0% WER on benchmark audio
- Redis-cached speaker profiles reduce diarization lookup from ~500ms to ~1ms
- Short command fast-path skips progressive re-transcription overhead
- ONNX model warmup on startup eliminates cold-start inference latency
- CUDA 12.8 + cuDNN 9 GPU Dockerfile for accelerated voice inference
- Workstation GC mode and thread pool tuning for development responsiveness
- OTEL export frequency reduced from 1s to 5s to lower telemetry overhead
π Test Coverage
| Area | Tests |
|---|---|
| Wyoming session integration | 50+ |
| Speaker verification components | 17 |
| Speech enhancement validation | 20+ |
| Engine hot-reload | 10+ |
| Engine readiness | 10+ |
| Wyoming status API | 2 |
| Command pattern matching | 30+ |
| Profile store (InMemory) | 10+ |
| Conversation command processor | 5 |
| Direct skill executor | 4 |
| Response template renderer | 4 |
| Context reconstructor | 4 |
| Total Wyoming Tests | 230 |
| Total Conversation Tests | 17 |
π Upgrade Notes
- New infrastructure dependencies β MongoDB (
luciaconfigdatabase) is used for speaker profiles, voice config persistence, and response templates. Redis is optional but recommended for profile caching. - Home Assistant component upgrade β The HA custom component has been migrated to v1.2.0-preview.1. Breaking change: remove and re-add the Lucia integration in Home Assistant. The new setup flow only requires the host URL and API key β agent selection is no longer needed.
- Response templates β Default templates are seeded automatically on first launch. Customize them via the Response Templates page in the dashboard or
POST /api/response-templates. - Model downloads required β On first launch, navigate to the Voice Platform β Models tab to download and activate at least one STT model and supporting models (VAD, Wake Word, Speaker Embedding).
- Wyoming integration β Add the Lucia Wyoming satellite in Home Assistant under Settings β Devices & Services β Add Integration β Wyoming. The server advertises via Zeroconf automatically.
- GPU acceleration β The project now ships with
Microsoft.ML.OnnxRuntime.Gpu.Linuxfor automatic CUDA support. For local development, install CUDA Toolkit 12.x and cuDNN 9.x. TheOnnxProviderDetectorwill find and use CUDA automatically β no configuration required. The Docker voice image (Dockerfile.voice) includes all GPU dependencies out of the box. - Existing voice config β If you previously had a
voiceconfig.json, those settings will need to be re-entered through the dashboard Voice Platform config panel (they now persist to MongoDB). - No breaking changes for data providers β Default behavior (Redis + MongoDB) is unchanged. The new
DataProviderconfiguration section is optional; omitting it preserves existing behavior. SetDataProvider:CachetoInMemoryandDataProvider:StoretoSQLiteto switch to the embedded providers.