@elizaos/plugin-local-inference 2.0.0-beta.1 → 2.0.3-beta.2
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.
- package/LICENSE +21 -0
- package/README.md +83 -0
- package/package.json +82 -15
- package/src/actions/generate-media.d.ts +59 -0
- package/src/actions/generate-media.d.ts.map +1 -0
- package/src/actions/generate-media.ts +647 -0
- package/src/actions/identify-speaker.d.ts +23 -0
- package/src/actions/identify-speaker.d.ts.map +1 -0
- package/src/actions/identify-speaker.ts +171 -0
- package/src/actions/transcription-control.d.ts +29 -0
- package/src/actions/transcription-control.d.ts.map +1 -0
- package/src/actions/transcription-control.test.ts +100 -0
- package/src/actions/transcription-control.ts +127 -0
- package/src/adapters/capacitor-llama/__tests__/compat-behavior.test.ts +218 -0
- package/src/adapters/capacitor-llama/__tests__/index.test.ts +68 -0
- package/src/adapters/capacitor-llama/__tests__/structured-output.test.ts +215 -0
- package/src/adapters/capacitor-llama/__tests__/text-streaming.test.ts +174 -0
- package/src/adapters/capacitor-llama/environment.ts +71 -0
- package/src/adapters/capacitor-llama/index.browser.ts +83 -0
- package/src/adapters/capacitor-llama/index.ts +807 -0
- package/src/adapters/capacitor-llama/loader.ts +109 -0
- package/src/adapters/capacitor-llama/structured-output.ts +165 -0
- package/src/adapters/capacitor-llama/text-streaming.ts +227 -0
- package/src/adapters/capacitor-llama/types.ts +374 -0
- package/src/backends/apple-foundation.ts +127 -0
- package/src/index.d.ts +8 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.ts +62 -0
- package/src/local-inference-routes.d.ts +38 -0
- package/src/local-inference-routes.d.ts.map +1 -0
- package/src/local-inference-routes.test.ts +344 -0
- package/src/local-inference-routes.ts +1543 -0
- package/src/provider.d.ts +21 -0
- package/src/provider.d.ts.map +1 -0
- package/src/provider.ts +1082 -0
- package/src/routes/compat-helpers.d.ts +18 -0
- package/src/routes/compat-helpers.d.ts.map +1 -0
- package/src/routes/compat-helpers.ts +274 -0
- package/src/routes/family-member-route.d.ts +62 -0
- package/src/routes/family-member-route.d.ts.map +1 -0
- package/src/routes/family-member-route.ts +353 -0
- package/src/routes/index.d.ts +19 -0
- package/src/routes/index.d.ts.map +1 -0
- package/src/routes/index.ts +60 -0
- package/src/routes/live-diarization-route.d.ts +26 -0
- package/src/routes/live-diarization-route.d.ts.map +1 -0
- package/src/routes/live-diarization-route.test.ts +213 -0
- package/src/routes/live-diarization-route.ts +122 -0
- package/src/routes/local-inference-asr-route.d.ts +4 -0
- package/src/routes/local-inference-asr-route.d.ts.map +1 -0
- package/src/routes/local-inference-asr-route.test.ts +205 -0
- package/src/routes/local-inference-asr-route.ts +163 -0
- package/src/routes/local-inference-asr-transcribe.d.ts +20 -0
- package/src/routes/local-inference-asr-transcribe.d.ts.map +1 -0
- package/src/routes/local-inference-asr-transcribe.test.ts +118 -0
- package/src/routes/local-inference-asr-transcribe.ts +97 -0
- package/src/routes/local-inference-compat-routes.d.ts +16 -0
- package/src/routes/local-inference-compat-routes.d.ts.map +1 -0
- package/src/routes/local-inference-compat-routes.test.ts +485 -0
- package/src/routes/local-inference-compat-routes.ts +808 -0
- package/src/routes/local-inference-tts-route.d.ts +7 -0
- package/src/routes/local-inference-tts-route.d.ts.map +1 -0
- package/src/routes/local-inference-tts-route.test.ts +179 -0
- package/src/routes/local-inference-tts-route.ts +230 -0
- package/src/routes/transcript-audio-store.d.ts +15 -0
- package/src/routes/transcript-audio-store.d.ts.map +1 -0
- package/src/routes/transcript-audio-store.ts +27 -0
- package/src/routes/transcripts-routes.d.ts +36 -0
- package/src/routes/transcripts-routes.d.ts.map +1 -0
- package/src/routes/transcripts-routes.test.ts +144 -0
- package/src/routes/transcripts-routes.ts +159 -0
- package/src/routes/voice-first-run-routes.d.ts +62 -0
- package/src/routes/voice-first-run-routes.d.ts.map +1 -0
- package/src/routes/voice-first-run-routes.ts +524 -0
- package/src/routes/voice-models-routes.d.ts +62 -0
- package/src/routes/voice-models-routes.d.ts.map +1 -0
- package/src/routes/voice-models-routes.ts +554 -0
- package/src/routes/voice-profile-plugin-routes.d.ts +19 -0
- package/src/routes/voice-profile-plugin-routes.d.ts.map +1 -0
- package/src/routes/voice-profile-plugin-routes.ts +138 -0
- package/src/routes/voice-profiles-management-routes.d.ts +52 -0
- package/src/routes/voice-profiles-management-routes.d.ts.map +1 -0
- package/src/routes/voice-profiles-management-routes.ts +476 -0
- package/src/routes/voice-speaker-profile-routes.d.ts +57 -0
- package/src/routes/voice-speaker-profile-routes.d.ts.map +1 -0
- package/src/routes/voice-speaker-profile-routes.ts +199 -0
- package/src/runtime/aosp-llama-loader-selection.test.ts +80 -0
- package/src/runtime/capacitor-llama.d.ts +25 -0
- package/src/runtime/embedding-manager-support.d.ts +77 -0
- package/src/runtime/embedding-manager-support.d.ts.map +1 -0
- package/src/runtime/embedding-manager-support.ts +497 -0
- package/src/runtime/embedding-presets.d.ts +16 -0
- package/src/runtime/embedding-presets.d.ts.map +1 -0
- package/src/runtime/embedding-presets.ts +81 -0
- package/src/runtime/embedding-warmup-policy.d.ts +14 -0
- package/src/runtime/embedding-warmup-policy.d.ts.map +1 -0
- package/src/runtime/embedding-warmup-policy.test.ts +53 -0
- package/src/runtime/embedding-warmup-policy.ts +48 -0
- package/src/runtime/ensure-local-inference-handler.d.ts +62 -0
- package/src/runtime/ensure-local-inference-handler.d.ts.map +1 -0
- package/src/runtime/ensure-local-inference-handler.test.ts +528 -0
- package/src/runtime/ensure-local-inference-handler.ts +1448 -0
- package/src/runtime/index.d.ts +15 -0
- package/src/runtime/index.d.ts.map +1 -0
- package/src/runtime/index.ts +33 -0
- package/src/runtime/mobile-local-inference-gate.d.ts +31 -0
- package/src/runtime/mobile-local-inference-gate.d.ts.map +1 -0
- package/src/runtime/mobile-local-inference-gate.test.ts +69 -0
- package/src/runtime/mobile-local-inference-gate.ts +44 -0
- package/src/runtime/voice-entity-binding.d.ts +103 -0
- package/src/runtime/voice-entity-binding.d.ts.map +1 -0
- package/src/runtime/voice-entity-binding.transcript.test.ts +69 -0
- package/src/runtime/voice-entity-binding.ts +328 -0
- package/src/services/README.md +71 -0
- package/src/services/__tests__/backend-selector.test.ts +101 -0
- package/src/services/__tests__/checkpoint-manager.test.ts +376 -0
- package/src/services/__tests__/gpu-autotune.test.ts +400 -0
- package/src/services/__tests__/llm-streaming-binding.test.ts +85 -0
- package/src/services/__tests__/planner-grammar.test.ts +372 -0
- package/src/services/__tests__/runtime-target.test.ts +176 -0
- package/src/services/active-model-switch-rollback.test.ts +183 -0
- package/src/services/active-model.d.ts +282 -0
- package/src/services/active-model.d.ts.map +1 -0
- package/src/services/active-model.ts +1213 -0
- package/src/services/assignments.d.ts +71 -0
- package/src/services/assignments.d.ts.map +1 -0
- package/src/services/assignments.test.ts +80 -0
- package/src/services/assignments.ts +230 -0
- package/src/services/backend-selector.ts +95 -0
- package/src/services/backend.d.ts +346 -0
- package/src/services/backend.d.ts.map +1 -0
- package/src/services/backend.ts +612 -0
- package/src/services/bionic-host-loader.d.ts +46 -0
- package/src/services/bionic-host-loader.d.ts.map +1 -0
- package/src/services/bionic-host-loader.test.ts +133 -0
- package/src/services/bionic-host-loader.ts +180 -0
- package/src/services/bundled-models.d.ts +34 -0
- package/src/services/bundled-models.d.ts.map +1 -0
- package/src/services/bundled-models.ts +129 -0
- package/src/services/cache-bridge.d.ts +206 -0
- package/src/services/cache-bridge.d.ts.map +1 -0
- package/src/services/cache-bridge.test.ts +516 -0
- package/src/services/cache-bridge.ts +423 -0
- package/src/services/catalog.d.ts +10 -0
- package/src/services/catalog.d.ts.map +1 -0
- package/src/services/catalog.test.ts +238 -0
- package/src/services/catalog.ts +27 -0
- package/src/services/checkpoint-client.d.ts +109 -0
- package/src/services/checkpoint-client.d.ts.map +1 -0
- package/src/services/checkpoint-client.ts +258 -0
- package/src/services/checkpoint-manager.ts +474 -0
- package/src/services/cloud-fallback.d.ts +102 -0
- package/src/services/cloud-fallback.d.ts.map +1 -0
- package/src/services/cloud-fallback.ts +230 -0
- package/src/services/conversation-registry.d.ts +142 -0
- package/src/services/conversation-registry.d.ts.map +1 -0
- package/src/services/conversation-registry.test.ts +235 -0
- package/src/services/conversation-registry.ts +264 -0
- package/src/services/desktop-fused-ffi-backend-runtime.d.ts +95 -0
- package/src/services/desktop-fused-ffi-backend-runtime.d.ts.map +1 -0
- package/src/services/desktop-fused-ffi-backend-runtime.ts +339 -0
- package/src/services/device-bridge.d.ts +188 -0
- package/src/services/device-bridge.d.ts.map +1 -0
- package/src/services/device-bridge.ts +1237 -0
- package/src/services/device-resource-metrics.d.ts +149 -0
- package/src/services/device-resource-metrics.d.ts.map +1 -0
- package/src/services/device-resource-metrics.test.ts +98 -0
- package/src/services/device-resource-metrics.ts +346 -0
- package/src/services/device-tier.d.ts +115 -0
- package/src/services/device-tier.d.ts.map +1 -0
- package/src/services/device-tier.test.ts +371 -0
- package/src/services/device-tier.ts +410 -0
- package/src/services/downloader.d.ts +82 -0
- package/src/services/downloader.d.ts.map +1 -0
- package/src/services/downloader.test.ts +747 -0
- package/src/services/downloader.ts +925 -0
- package/src/services/engine-direct-bundle.test.ts +58 -0
- package/src/services/engine-streaming.test.ts +80 -0
- package/src/services/engine.d.ts +540 -0
- package/src/services/engine.d.ts.map +1 -0
- package/src/services/engine.ts +1909 -0
- package/src/services/ensure-local-artifacts.integration.test.ts +273 -0
- package/src/services/ensure-local-artifacts.test.ts +368 -0
- package/src/services/ensure-local-artifacts.ts +351 -0
- package/src/services/external-scanner.d.ts +17 -0
- package/src/services/external-scanner.d.ts.map +1 -0
- package/src/services/external-scanner.ts +312 -0
- package/src/services/ffi-llm-mock.ts +354 -0
- package/src/services/ffi-llm-streaming-abi.ts +442 -0
- package/src/services/ffi-streaming-backend.d.ts +180 -0
- package/src/services/ffi-streaming-backend.d.ts.map +1 -0
- package/src/services/ffi-streaming-backend.ts +382 -0
- package/src/services/ffi-streaming-runner.d.ts +122 -0
- package/src/services/ffi-streaming-runner.d.ts.map +1 -0
- package/src/services/ffi-streaming-runner.test.ts +60 -0
- package/src/services/ffi-streaming-runner.ts +354 -0
- package/src/services/ffi-unload-ordering.test.ts +162 -0
- package/src/services/gpu-autotune.ts +534 -0
- package/src/services/gpu-detect.d.ts +56 -0
- package/src/services/gpu-detect.d.ts.map +1 -0
- package/src/services/gpu-detect.ts +139 -0
- package/src/services/handler-registry.d.ts +72 -0
- package/src/services/handler-registry.d.ts.map +1 -0
- package/src/services/handler-registry.ts +240 -0
- package/src/services/hardware.d.ts +63 -0
- package/src/services/hardware.d.ts.map +1 -0
- package/src/services/hardware.test.ts +231 -0
- package/src/services/hardware.ts +410 -0
- package/src/services/hf-search.d.ts +26 -0
- package/src/services/hf-search.d.ts.map +1 -0
- package/src/services/hf-search.test.ts +69 -0
- package/src/services/hf-search.ts +420 -0
- package/src/services/image-description-runtime.d.ts +14 -0
- package/src/services/image-description-runtime.d.ts.map +1 -0
- package/src/services/image-description-runtime.test.ts +61 -0
- package/src/services/image-description-runtime.ts +118 -0
- package/src/services/imagegen/aosp-unavailable.d.ts +134 -0
- package/src/services/imagegen/aosp-unavailable.d.ts.map +1 -0
- package/src/services/imagegen/aosp-unavailable.ts +229 -0
- package/src/services/imagegen/backend-selector.d.ts +118 -0
- package/src/services/imagegen/backend-selector.d.ts.map +1 -0
- package/src/services/imagegen/backend-selector.ts +277 -0
- package/src/services/imagegen/coreml-unavailable.d.ts +105 -0
- package/src/services/imagegen/coreml-unavailable.d.ts.map +1 -0
- package/src/services/imagegen/coreml-unavailable.ts +237 -0
- package/src/services/imagegen/errors.d.ts +16 -0
- package/src/services/imagegen/errors.d.ts.map +1 -0
- package/src/services/imagegen/errors.ts +40 -0
- package/src/services/imagegen/index.d.ts +58 -0
- package/src/services/imagegen/index.d.ts.map +1 -0
- package/src/services/imagegen/index.ts +144 -0
- package/src/services/imagegen/mflux.d.ts +74 -0
- package/src/services/imagegen/mflux.d.ts.map +1 -0
- package/src/services/imagegen/mflux.ts +313 -0
- package/src/services/imagegen/sd-cpp.d.ts +180 -0
- package/src/services/imagegen/sd-cpp.d.ts.map +1 -0
- package/src/services/imagegen/sd-cpp.ts +718 -0
- package/src/services/imagegen/tensorrt-unavailable.d.ts +83 -0
- package/src/services/imagegen/tensorrt-unavailable.d.ts.map +1 -0
- package/src/services/imagegen/tensorrt-unavailable.ts +295 -0
- package/src/services/imagegen/types.d.ts +181 -0
- package/src/services/imagegen/types.d.ts.map +1 -0
- package/src/services/imagegen/types.ts +193 -0
- package/src/services/index.d.ts +29 -0
- package/src/services/index.d.ts.map +1 -0
- package/src/services/index.ts +211 -0
- package/src/services/inference-capabilities.d.ts +132 -0
- package/src/services/inference-capabilities.d.ts.map +1 -0
- package/src/services/inference-capabilities.test.ts +75 -0
- package/src/services/inference-capabilities.ts +204 -0
- package/src/services/inference-telemetry.d.ts +59 -0
- package/src/services/inference-telemetry.d.ts.map +1 -0
- package/src/services/inference-telemetry.ts +143 -0
- package/src/services/ios-llama-streaming.ts +248 -0
- package/src/services/kv-spill.d.ts +189 -0
- package/src/services/kv-spill.d.ts.map +1 -0
- package/src/services/kv-spill.test.ts +222 -0
- package/src/services/kv-spill.ts +356 -0
- package/src/services/latency-trace.d.ts +346 -0
- package/src/services/latency-trace.d.ts.map +1 -0
- package/src/services/latency-trace.test.ts +266 -0
- package/src/services/latency-trace.ts +844 -0
- package/src/services/llama-server-metrics.ts +304 -0
- package/src/services/llm-streaming-binding.d.ts +96 -0
- package/src/services/llm-streaming-binding.d.ts.map +1 -0
- package/src/services/llm-streaming-binding.ts +136 -0
- package/src/services/load-args.d.ts +82 -0
- package/src/services/load-args.d.ts.map +1 -0
- package/src/services/load-args.ts +81 -0
- package/src/services/manifest/eliza-1.manifest.v1.json +708 -0
- package/src/services/manifest/index.d.ts +4 -0
- package/src/services/manifest/index.d.ts.map +1 -0
- package/src/services/manifest/index.ts +66 -0
- package/src/services/manifest/manifest.test.ts +689 -0
- package/src/services/manifest/schema.d.ts +713 -0
- package/src/services/manifest/schema.d.ts.map +1 -0
- package/src/services/manifest/schema.ts +653 -0
- package/src/services/manifest/types.d.ts +30 -0
- package/src/services/manifest/types.d.ts.map +1 -0
- package/src/services/manifest/types.ts +55 -0
- package/src/services/manifest/validator.d.ts +66 -0
- package/src/services/manifest/validator.d.ts.map +1 -0
- package/src/services/manifest/validator.ts +567 -0
- package/src/services/memory-arbiter.d.ts +318 -0
- package/src/services/memory-arbiter.d.ts.map +1 -0
- package/src/services/memory-arbiter.test.ts +419 -0
- package/src/services/memory-arbiter.ts +925 -0
- package/src/services/memory-monitor.d.ts +122 -0
- package/src/services/memory-monitor.d.ts.map +1 -0
- package/src/services/memory-monitor.test.ts +208 -0
- package/src/services/memory-monitor.ts +297 -0
- package/src/services/memory-pressure.d.ts +130 -0
- package/src/services/memory-pressure.d.ts.map +1 -0
- package/src/services/memory-pressure.ts +414 -0
- package/src/services/mtp-doctor.d.ts +13 -0
- package/src/services/mtp-doctor.d.ts.map +1 -0
- package/src/services/mtp-doctor.ts +78 -0
- package/src/services/network-policy.d.ts +127 -0
- package/src/services/network-policy.d.ts.map +1 -0
- package/src/services/network-policy.ts +346 -0
- package/src/services/paths.d.ts +6 -0
- package/src/services/paths.d.ts.map +1 -0
- package/src/services/paths.ts +25 -0
- package/src/services/planner-skeleton.d.ts +124 -0
- package/src/services/planner-skeleton.d.ts.map +1 -0
- package/src/services/planner-skeleton.ts +175 -0
- package/src/services/providers.d.ts +38 -0
- package/src/services/providers.d.ts.map +1 -0
- package/src/services/providers.ts +507 -0
- package/src/services/ram-budget-cache.test.ts +163 -0
- package/src/services/ram-budget.d.ts +110 -0
- package/src/services/ram-budget.d.ts.map +1 -0
- package/src/services/ram-budget.ts +0 -0
- package/src/services/readiness.d.ts +9 -0
- package/src/services/readiness.d.ts.map +1 -0
- package/src/services/readiness.test.ts +87 -0
- package/src/services/readiness.ts +238 -0
- package/src/services/recommendation.d.ts +111 -0
- package/src/services/recommendation.d.ts.map +1 -0
- package/src/services/recommendation.ts +671 -0
- package/src/services/registry.d.ts +35 -0
- package/src/services/registry.d.ts.map +1 -0
- package/src/services/registry.ts +151 -0
- package/src/services/router-handler.d.ts +92 -0
- package/src/services/router-handler.d.ts.map +1 -0
- package/src/services/router-handler.test.ts +45 -0
- package/src/services/router-handler.ts +407 -0
- package/src/services/routing-policy.d.ts +69 -0
- package/src/services/routing-policy.d.ts.map +1 -0
- package/src/services/routing-policy.test.ts +164 -0
- package/src/services/routing-policy.ts +297 -0
- package/src/services/routing-preferences.d.ts +8 -0
- package/src/services/routing-preferences.d.ts.map +1 -0
- package/src/services/routing-preferences.ts +17 -0
- package/src/services/runtime-target.d.ts +98 -0
- package/src/services/runtime-target.d.ts.map +1 -0
- package/src/services/runtime-target.ts +154 -0
- package/src/services/service.d.ts +128 -0
- package/src/services/service.d.ts.map +1 -0
- package/src/services/service.test.ts +223 -0
- package/src/services/service.ts +735 -0
- package/src/services/session-pool.d.ts +72 -0
- package/src/services/session-pool.d.ts.map +1 -0
- package/src/services/session-pool.ts +153 -0
- package/src/services/structured-output/deterministic-repair.d.ts +23 -0
- package/src/services/structured-output/deterministic-repair.d.ts.map +1 -0
- package/src/services/structured-output/deterministic-repair.test.ts +169 -0
- package/src/services/structured-output/deterministic-repair.ts +443 -0
- package/src/services/structured-output/index.ts +4 -0
- package/src/services/structured-output.d.ts +311 -0
- package/src/services/structured-output.d.ts.map +1 -0
- package/src/services/structured-output.test.ts +483 -0
- package/src/services/structured-output.ts +712 -0
- package/src/services/system-memory.d.ts +33 -0
- package/src/services/system-memory.d.ts.map +1 -0
- package/src/services/system-memory.test.ts +47 -0
- package/src/services/system-memory.ts +67 -0
- package/src/services/transcription-priority.test.ts +211 -0
- package/src/services/types.d.ts +19 -0
- package/src/services/types.d.ts.map +1 -0
- package/src/services/types.ts +55 -0
- package/src/services/verify-on-device.d.ts +34 -0
- package/src/services/verify-on-device.d.ts.map +1 -0
- package/src/services/verify-on-device.test.ts +87 -0
- package/src/services/verify-on-device.ts +127 -0
- package/src/services/verify.d.ts +8 -0
- package/src/services/verify.d.ts.map +1 -0
- package/src/services/verify.ts +13 -0
- package/src/services/vision/aosp-unavailable.d.ts +115 -0
- package/src/services/vision/aosp-unavailable.d.ts.map +1 -0
- package/src/services/vision/aosp-unavailable.ts +163 -0
- package/src/services/vision/capacitor-llama.d.ts +99 -0
- package/src/services/vision/capacitor-llama.d.ts.map +1 -0
- package/src/services/vision/capacitor-llama.ts +255 -0
- package/src/services/vision/cloud-fallback.d.ts +47 -0
- package/src/services/vision/cloud-fallback.d.ts.map +1 -0
- package/src/services/vision/cloud-fallback.test.ts +243 -0
- package/src/services/vision/cloud-fallback.ts +268 -0
- package/src/services/vision/fallback-chain.test.ts +86 -0
- package/src/services/vision/hash.d.ts +71 -0
- package/src/services/vision/hash.d.ts.map +1 -0
- package/src/services/vision/hash.ts +157 -0
- package/src/services/vision/index.d.ts +95 -0
- package/src/services/vision/index.d.ts.map +1 -0
- package/src/services/vision/index.ts +251 -0
- package/src/services/vision/llama-server.d.ts +73 -0
- package/src/services/vision/llama-server.d.ts.map +1 -0
- package/src/services/vision/llama-server.ts +177 -0
- package/src/services/vision/types.d.ts +153 -0
- package/src/services/vision/types.d.ts.map +1 -0
- package/src/services/vision/types.ts +154 -0
- package/src/services/vision/vast-fallback.d.ts +18 -0
- package/src/services/vision/vast-fallback.d.ts.map +1 -0
- package/src/services/vision/vast-fallback.ts +127 -0
- package/src/services/vision-embedding-cache.d.ts +98 -0
- package/src/services/vision-embedding-cache.d.ts.map +1 -0
- package/src/services/vision-embedding-cache.ts +189 -0
- package/src/services/voice/VOICE_WORKBENCH.md +88 -0
- package/src/services/voice/__test-helpers__/fake-ffi.ts +94 -0
- package/src/services/voice/__test-helpers__/synthetic-speech.ts +124 -0
- package/src/services/voice/__tests__/checkpoint-manager.test.ts +241 -0
- package/src/services/voice/__tests__/checkpoint-policy.test.ts +270 -0
- package/src/services/voice/__tests__/eager-context-builder.test.ts +257 -0
- package/src/services/voice/__tests__/eliza1-eot-scorer.test.ts +288 -0
- package/src/services/voice/__tests__/eot-classifier.test.ts +431 -0
- package/src/services/voice/__tests__/optimistic-rollback.test.ts +312 -0
- package/src/services/voice/__tests__/prefill-client.test.ts +266 -0
- package/src/services/voice/__tests__/prefix-preserving-queue.test.ts +208 -0
- package/src/services/voice/__tests__/streaming-asr.test.ts +450 -0
- package/src/services/voice/__tests__/streaming-transcriber.test.ts +339 -0
- package/src/services/voice/__tests__/turn-detector-resolver.test.ts +195 -0
- package/src/services/voice/__tests__/voice-state-machine-prefill.test.ts +275 -0
- package/src/services/voice/__tests__/voice-state-machine.test.ts +354 -0
- package/src/services/voice/asr-timed.real.test.ts +141 -0
- package/src/services/voice/audio-frame-consumer.d.ts +212 -0
- package/src/services/voice/audio-frame-consumer.d.ts.map +1 -0
- package/src/services/voice/audio-frame-consumer.test.ts +343 -0
- package/src/services/voice/audio-frame-consumer.ts +491 -0
- package/src/services/voice/barge-in.d.ts +112 -0
- package/src/services/voice/barge-in.d.ts.map +1 -0
- package/src/services/voice/barge-in.test.ts +244 -0
- package/src/services/voice/barge-in.ts +336 -0
- package/src/services/voice/cancellation-coordinator.d.ts +127 -0
- package/src/services/voice/cancellation-coordinator.d.ts.map +1 -0
- package/src/services/voice/cancellation-coordinator.test.ts +196 -0
- package/src/services/voice/cancellation-coordinator.ts +269 -0
- package/src/services/voice/checkpoint-manager.d.ts +199 -0
- package/src/services/voice/checkpoint-manager.d.ts.map +1 -0
- package/src/services/voice/checkpoint-manager.ts +401 -0
- package/src/services/voice/checkpoint-policy.ts +336 -0
- package/src/services/voice/composite-eot-classifier.test.ts +59 -0
- package/src/services/voice/e2e-harness.test.ts +182 -0
- package/src/services/voice/e2e-harness.ts +743 -0
- package/src/services/voice/eager-context-builder.d.ts +170 -0
- package/src/services/voice/eager-context-builder.d.ts.map +1 -0
- package/src/services/voice/eager-context-builder.ts +262 -0
- package/src/services/voice/eliza1-eot-scorer.d.ts +124 -0
- package/src/services/voice/eliza1-eot-scorer.d.ts.map +1 -0
- package/src/services/voice/eliza1-eot-scorer.ts +242 -0
- package/src/services/voice/embedding-server.ts +200 -0
- package/src/services/voice/embedding.d.ts +133 -0
- package/src/services/voice/embedding.d.ts.map +1 -0
- package/src/services/voice/embedding.test.ts +131 -0
- package/src/services/voice/embedding.ts +243 -0
- package/src/services/voice/emotion-attribution.d.ts +68 -0
- package/src/services/voice/emotion-attribution.d.ts.map +1 -0
- package/src/services/voice/emotion-attribution.test.ts +129 -0
- package/src/services/voice/emotion-attribution.ts +361 -0
- package/src/services/voice/engine-bridge-cancellation.test.ts +422 -0
- package/src/services/voice/engine-bridge.d.ts +759 -0
- package/src/services/voice/engine-bridge.d.ts.map +1 -0
- package/src/services/voice/engine-bridge.test.ts +384 -0
- package/src/services/voice/engine-bridge.ts +2302 -0
- package/src/services/voice/eot-classifier-ggml.d.ts +179 -0
- package/src/services/voice/eot-classifier-ggml.d.ts.map +1 -0
- package/src/services/voice/eot-classifier-ggml.ts +566 -0
- package/src/services/voice/eot-classifier.d.ts +214 -0
- package/src/services/voice/eot-classifier.d.ts.map +1 -0
- package/src/services/voice/eot-classifier.ts +533 -0
- package/src/services/voice/errors.d.ts +20 -0
- package/src/services/voice/errors.d.ts.map +1 -0
- package/src/services/voice/errors.ts +32 -0
- package/src/services/voice/expressive-tags.d.ts +158 -0
- package/src/services/voice/expressive-tags.d.ts.map +1 -0
- package/src/services/voice/expressive-tags.ts +405 -0
- package/src/services/voice/ffi-bindings.d.ts +674 -0
- package/src/services/voice/ffi-bindings.d.ts.map +1 -0
- package/src/services/voice/ffi-bindings.test.ts +728 -0
- package/src/services/voice/ffi-bindings.ts +3225 -0
- package/src/services/voice/first-line-cache.d.ts +181 -0
- package/src/services/voice/first-line-cache.d.ts.map +1 -0
- package/src/services/voice/first-line-cache.ts +725 -0
- package/src/services/voice/fused-eot-scorer.d.ts +51 -0
- package/src/services/voice/fused-eot-scorer.d.ts.map +1 -0
- package/src/services/voice/fused-eot-scorer.ts +135 -0
- package/src/services/voice/index.d.ts +91 -0
- package/src/services/voice/index.d.ts.map +1 -0
- package/src/services/voice/index.ts +481 -0
- package/src/services/voice/kokoro/__tests__/kokoro-backend.test.ts +151 -0
- package/src/services/voice/kokoro/__tests__/kokoro-engine-bridge.real.test.ts +151 -0
- package/src/services/voice/kokoro/__tests__/kokoro-engine-bridge.test.ts +60 -0
- package/src/services/voice/kokoro/__tests__/kokoro-engine-discovery.test.ts +277 -0
- package/src/services/voice/kokoro/__tests__/kokoro-ffi-runtime.test.ts +235 -0
- package/src/services/voice/kokoro/__tests__/kokoro-runtime.test.ts +95 -0
- package/src/services/voice/kokoro/__tests__/phonemizer.test.ts +53 -0
- package/src/services/voice/kokoro/__tests__/runtime-selection.test.ts +231 -0
- package/src/services/voice/kokoro/__tests__/voices.test.ts +57 -0
- package/src/services/voice/kokoro/index.ts +79 -0
- package/src/services/voice/kokoro/kokoro-backend.d.ts +72 -0
- package/src/services/voice/kokoro/kokoro-backend.d.ts.map +1 -0
- package/src/services/voice/kokoro/kokoro-backend.ts +207 -0
- package/src/services/voice/kokoro/kokoro-engine-discovery.d.ts +58 -0
- package/src/services/voice/kokoro/kokoro-engine-discovery.d.ts.map +1 -0
- package/src/services/voice/kokoro/kokoro-engine-discovery.ts +177 -0
- package/src/services/voice/kokoro/kokoro-ffi-runtime.d.ts +75 -0
- package/src/services/voice/kokoro/kokoro-ffi-runtime.d.ts.map +1 -0
- package/src/services/voice/kokoro/kokoro-ffi-runtime.ts +233 -0
- package/src/services/voice/kokoro/kokoro-runtime.d.ts +100 -0
- package/src/services/voice/kokoro/kokoro-runtime.d.ts.map +1 -0
- package/src/services/voice/kokoro/kokoro-runtime.ts +170 -0
- package/src/services/voice/kokoro/phoneme-stream.ts +123 -0
- package/src/services/voice/kokoro/phonemizer.d.ts +50 -0
- package/src/services/voice/kokoro/phonemizer.d.ts.map +1 -0
- package/src/services/voice/kokoro/phonemizer.ts +344 -0
- package/src/services/voice/kokoro/pick-runtime.d.ts +61 -0
- package/src/services/voice/kokoro/pick-runtime.d.ts.map +1 -0
- package/src/services/voice/kokoro/pick-runtime.test.ts +91 -0
- package/src/services/voice/kokoro/pick-runtime.ts +130 -0
- package/src/services/voice/kokoro/runtime-selection.d.ts +92 -0
- package/src/services/voice/kokoro/runtime-selection.d.ts.map +1 -0
- package/src/services/voice/kokoro/runtime-selection.ts +237 -0
- package/src/services/voice/kokoro/types.d.ts +82 -0
- package/src/services/voice/kokoro/types.d.ts.map +1 -0
- package/src/services/voice/kokoro/types.ts +95 -0
- package/src/services/voice/kokoro/voice-presets.d.ts +23 -0
- package/src/services/voice/kokoro/voice-presets.d.ts.map +1 -0
- package/src/services/voice/kokoro/voice-presets.ts +129 -0
- package/src/services/voice/kokoro/voices.d.ts +30 -0
- package/src/services/voice/kokoro/voices.d.ts.map +1 -0
- package/src/services/voice/kokoro/voices.ts +64 -0
- package/src/services/voice/lifecycle.d.ts +135 -0
- package/src/services/voice/lifecycle.d.ts.map +1 -0
- package/src/services/voice/lifecycle.test.ts +315 -0
- package/src/services/voice/lifecycle.ts +301 -0
- package/src/services/voice/live-diarization-session.d.ts +96 -0
- package/src/services/voice/live-diarization-session.d.ts.map +1 -0
- package/src/services/voice/live-diarization-session.ts +289 -0
- package/src/services/voice/mic-source.d.ts +136 -0
- package/src/services/voice/mic-source.d.ts.map +1 -0
- package/src/services/voice/mic-source.test.ts +210 -0
- package/src/services/voice/mic-source.ts +503 -0
- package/src/services/voice/optimistic-policy.d.ts +109 -0
- package/src/services/voice/optimistic-policy.d.ts.map +1 -0
- package/src/services/voice/optimistic-policy.test.ts +101 -0
- package/src/services/voice/optimistic-policy.ts +192 -0
- package/src/services/voice/optimistic-rollback.ts +343 -0
- package/src/services/voice/partial-stabilizer.d.ts +73 -0
- package/src/services/voice/partial-stabilizer.d.ts.map +1 -0
- package/src/services/voice/partial-stabilizer.test.ts +68 -0
- package/src/services/voice/partial-stabilizer.ts +140 -0
- package/src/services/voice/phoneme-tokenizer.d.ts +49 -0
- package/src/services/voice/phoneme-tokenizer.d.ts.map +1 -0
- package/src/services/voice/phoneme-tokenizer.ts +158 -0
- package/src/services/voice/phrase-cache.d.ts +76 -0
- package/src/services/voice/phrase-cache.d.ts.map +1 -0
- package/src/services/voice/phrase-cache.test.ts +242 -0
- package/src/services/voice/phrase-cache.ts +186 -0
- package/src/services/voice/phrase-chunker.d.ts +62 -0
- package/src/services/voice/phrase-chunker.d.ts.map +1 -0
- package/src/services/voice/phrase-chunker.test.ts +239 -0
- package/src/services/voice/phrase-chunker.ts +281 -0
- package/src/services/voice/pipeline-impls.d.ts +151 -0
- package/src/services/voice/pipeline-impls.d.ts.map +1 -0
- package/src/services/voice/pipeline-impls.l6.test.ts +110 -0
- package/src/services/voice/pipeline-impls.test.ts +292 -0
- package/src/services/voice/pipeline-impls.ts +315 -0
- package/src/services/voice/pipeline.d.ts +216 -0
- package/src/services/voice/pipeline.d.ts.map +1 -0
- package/src/services/voice/pipeline.ts +505 -0
- package/src/services/voice/prefill-client.d.ts +123 -0
- package/src/services/voice/prefill-client.d.ts.map +1 -0
- package/src/services/voice/prefill-client.ts +316 -0
- package/src/services/voice/prefix-preserving-queue.d.ts +113 -0
- package/src/services/voice/prefix-preserving-queue.d.ts.map +1 -0
- package/src/services/voice/prefix-preserving-queue.ts +162 -0
- package/src/services/voice/profile-store.d.ts +248 -0
- package/src/services/voice/profile-store.d.ts.map +1 -0
- package/src/services/voice/profile-store.ts +887 -0
- package/src/services/voice/real-audio-decode.test.ts +148 -0
- package/src/services/voice/ring-buffer.d.ts +40 -0
- package/src/services/voice/ring-buffer.d.ts.map +1 -0
- package/src/services/voice/ring-buffer.test.ts +129 -0
- package/src/services/voice/ring-buffer.ts +123 -0
- package/src/services/voice/rollback-queue.d.ts +24 -0
- package/src/services/voice/rollback-queue.d.ts.map +1 -0
- package/src/services/voice/rollback-queue.ts +74 -0
- package/src/services/voice/samantha-preset-placeholder.d.ts +67 -0
- package/src/services/voice/samantha-preset-placeholder.d.ts.map +1 -0
- package/src/services/voice/samantha-preset-placeholder.test.ts +97 -0
- package/src/services/voice/samantha-preset-placeholder.ts +148 -0
- package/src/services/voice/samantha-preset-regenerator.d.ts +87 -0
- package/src/services/voice/samantha-preset-regenerator.d.ts.map +1 -0
- package/src/services/voice/samantha-preset-regenerator.ts +393 -0
- package/src/services/voice/scheduler.d.ts +146 -0
- package/src/services/voice/scheduler.d.ts.map +1 -0
- package/src/services/voice/scheduler.t2.test.ts +141 -0
- package/src/services/voice/scheduler.ts +927 -0
- package/src/services/voice/shared-resources.d.ts +190 -0
- package/src/services/voice/shared-resources.d.ts.map +1 -0
- package/src/services/voice/shared-resources.ts +320 -0
- package/src/services/voice/speaker/attribution-pipeline.d.ts +74 -0
- package/src/services/voice/speaker/attribution-pipeline.d.ts.map +1 -0
- package/src/services/voice/speaker/attribution-pipeline.ts +386 -0
- package/src/services/voice/speaker/diarizer-fused.d.ts +59 -0
- package/src/services/voice/speaker/diarizer-fused.d.ts.map +1 -0
- package/src/services/voice/speaker/diarizer-fused.real.test.ts +100 -0
- package/src/services/voice/speaker/diarizer-fused.ts +154 -0
- package/src/services/voice/speaker/diarizer.d.ts +75 -0
- package/src/services/voice/speaker/diarizer.d.ts.map +1 -0
- package/src/services/voice/speaker/diarizer.ts +218 -0
- package/src/services/voice/speaker/encoder-fused.d.ts +60 -0
- package/src/services/voice/speaker/encoder-fused.d.ts.map +1 -0
- package/src/services/voice/speaker/encoder-fused.real.test.ts +113 -0
- package/src/services/voice/speaker/encoder-fused.ts +138 -0
- package/src/services/voice/speaker/encoder-ggml.d.ts +33 -0
- package/src/services/voice/speaker/encoder-ggml.d.ts.map +1 -0
- package/src/services/voice/speaker/encoder-ggml.ts +79 -0
- package/src/services/voice/speaker/encoder.d.ts +37 -0
- package/src/services/voice/speaker/encoder.d.ts.map +1 -0
- package/src/services/voice/speaker/encoder.ts +105 -0
- package/src/services/voice/speaker-imprint.d.ts +83 -0
- package/src/services/voice/speaker-imprint.d.ts.map +1 -0
- package/src/services/voice/speaker-imprint.test.ts +185 -0
- package/src/services/voice/speaker-imprint.ts +312 -0
- package/src/services/voice/speaker-preset-cache.d.ts +77 -0
- package/src/services/voice/speaker-preset-cache.d.ts.map +1 -0
- package/src/services/voice/speaker-preset-cache.test.ts +154 -0
- package/src/services/voice/speaker-preset-cache.ts +195 -0
- package/src/services/voice/streaming-asr/streaming-pipeline-adapter.ts +292 -0
- package/src/services/voice/system-audio-sink.d.ts +73 -0
- package/src/services/voice/system-audio-sink.d.ts.map +1 -0
- package/src/services/voice/system-audio-sink.test.ts +29 -0
- package/src/services/voice/system-audio-sink.ts +366 -0
- package/src/services/voice/transcriber.d.ts +244 -0
- package/src/services/voice/transcriber.d.ts.map +1 -0
- package/src/services/voice/transcriber.test.ts +392 -0
- package/src/services/voice/transcriber.ts +704 -0
- package/src/services/voice/transcript-knowledge.d.ts +37 -0
- package/src/services/voice/transcript-knowledge.d.ts.map +1 -0
- package/src/services/voice/transcript-knowledge.test.ts +68 -0
- package/src/services/voice/transcript-knowledge.ts +75 -0
- package/src/services/voice/transcript-service.d.ts +41 -0
- package/src/services/voice/transcript-service.d.ts.map +1 -0
- package/src/services/voice/transcript-service.test.ts +137 -0
- package/src/services/voice/transcript-service.ts +141 -0
- package/src/services/voice/transcript-store.d.ts +53 -0
- package/src/services/voice/transcript-store.d.ts.map +1 -0
- package/src/services/voice/transcript-store.test.ts +153 -0
- package/src/services/voice/transcript-store.ts +132 -0
- package/src/services/voice/turn-controller.d.ts +183 -0
- package/src/services/voice/turn-controller.d.ts.map +1 -0
- package/src/services/voice/turn-controller.test.ts +575 -0
- package/src/services/voice/turn-controller.ts +596 -0
- package/src/services/voice/types.d.ts +643 -0
- package/src/services/voice/types.d.ts.map +1 -0
- package/src/services/voice/types.ts +699 -0
- package/src/services/voice/vad.d.ts +282 -0
- package/src/services/voice/vad.d.ts.map +1 -0
- package/src/services/voice/vad.test.ts +480 -0
- package/src/services/voice/vad.ts +827 -0
- package/src/services/voice/vad.v1-v4.test.ts +222 -0
- package/src/services/voice/voice-budget.d.ts +241 -0
- package/src/services/voice/voice-budget.d.ts.map +1 -0
- package/src/services/voice/voice-budget.test.ts +418 -0
- package/src/services/voice/voice-budget.ts +635 -0
- package/src/services/voice/voice-duet.test.ts +375 -0
- package/src/services/voice/voice-emotion-classifier.d.ts +95 -0
- package/src/services/voice/voice-emotion-classifier.d.ts.map +1 -0
- package/src/services/voice/voice-emotion-classifier.test.ts +210 -0
- package/src/services/voice/voice-emotion-classifier.ts +273 -0
- package/src/services/voice/voice-preset-format.d.ts +158 -0
- package/src/services/voice/voice-preset-format.d.ts.map +1 -0
- package/src/services/voice/voice-preset-format.ts +700 -0
- package/src/services/voice/voice-preset-generator.test.ts +89 -0
- package/src/services/voice/voice-profile-artifact.d.ts +116 -0
- package/src/services/voice/voice-profile-artifact.d.ts.map +1 -0
- package/src/services/voice/voice-profile-artifact.test.ts +138 -0
- package/src/services/voice/voice-profile-artifact.ts +518 -0
- package/src/services/voice/voice-profile-routes.d.ts +83 -0
- package/src/services/voice/voice-profile-routes.d.ts.map +1 -0
- package/src/services/voice/voice-profile-routes.test.ts +429 -0
- package/src/services/voice/voice-profile-routes.ts +425 -0
- package/src/services/voice/voice-scenario.ts +154 -0
- package/src/services/voice/voice-settings.d.ts +82 -0
- package/src/services/voice/voice-settings.d.ts.map +1 -0
- package/src/services/voice/voice-settings.ts +172 -0
- package/src/services/voice/voice-state-machine.d.ts +364 -0
- package/src/services/voice/voice-state-machine.d.ts.map +1 -0
- package/src/services/voice/voice-state-machine.ts +727 -0
- package/src/services/voice/voice-workbench-report.test.ts +168 -0
- package/src/services/voice/voice-workbench-report.ts +326 -0
- package/src/services/voice/voice-workbench.test.ts +158 -0
- package/src/services/voice/voice.test.ts +1070 -0
- package/src/services/voice/wake-word-ggml.d.ts +101 -0
- package/src/services/voice/wake-word-ggml.d.ts.map +1 -0
- package/src/services/voice/wake-word-ggml.ts +320 -0
- package/src/services/voice/wake-word.d.ts +255 -0
- package/src/services/voice/wake-word.d.ts.map +1 -0
- package/src/services/voice/wake-word.test.ts +298 -0
- package/src/services/voice/wake-word.ts +554 -0
- package/src/services/voice/wrap-with-first-line-cache.d.ts +70 -0
- package/src/services/voice/wrap-with-first-line-cache.d.ts.map +1 -0
- package/src/services/voice/wrap-with-first-line-cache.ts +267 -0
- package/src/services/voice-model-updater.d.ts +240 -0
- package/src/services/voice-model-updater.d.ts.map +1 -0
- package/src/services/voice-model-updater.ts +724 -0
- package/src/services/voice-prewarm.d.ts +3 -0
- package/src/services/voice-prewarm.d.ts.map +1 -0
- package/src/services/voice-prewarm.ts +51 -0
- package/dist/index.d.ts +0 -37
- package/dist/index.js +0 -1098
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wake-word detection — native runtime binding.
|
|
3
|
+
*
|
|
4
|
+
* Loads the standalone `packages/native/plugins/wakeword-cpp/`
|
|
5
|
+
* library directly via `bun:ffi` and exposes the same `WakeWordModel`
|
|
6
|
+
* interface as the previous `onnxruntime-node`-backed implementation
|
|
7
|
+
* in `./wake-word.ts`, so the voice lifecycle can swap the two without
|
|
8
|
+
* changing anything upstream.
|
|
9
|
+
*
|
|
10
|
+
* Phase 2 status — this binding is now the default when the
|
|
11
|
+
* `libwakeword.{so,dylib,dll}` shared library and three converted
|
|
12
|
+
* GGUFs are present. The C runtime is a pure-fp32 reference
|
|
13
|
+
* implementation of the openWakeWord three-stage pipeline (melspec
|
|
14
|
+
* → embedding CNN → classifier head) — no ggml link, no SIMD; a
|
|
15
|
+
* laptop CPU runs it under 1 % of real time. ABI parity with the
|
|
16
|
+
* upstream openWakeWord ONNX graphs is gated by
|
|
17
|
+
* `packages/native/plugins/wakeword-cpp/test/wakeword_parity_test.py`.
|
|
18
|
+
*
|
|
19
|
+
* The ONNX path in `./wake-word.ts` stays as the fallback while the
|
|
20
|
+
* native binding shakes out. Once the migration is complete the ONNX
|
|
21
|
+
* path can be removed alongside the `onnxruntime-node` dependency.
|
|
22
|
+
*
|
|
23
|
+
* Three GGUFs back one session, mirroring openWakeWord's three ONNX
|
|
24
|
+
* graphs (the C library is the single source of truth on shapes —
|
|
25
|
+
* see `packages/native/plugins/wakeword-cpp/include/wakeword/wakeword.h`):
|
|
26
|
+
*
|
|
27
|
+
* 1. melspec — 16 kHz PCM → 32-bin log-mel frames.
|
|
28
|
+
* 2. embedding — 20-Conv2D CNN over a 76-mel-frame sliding window
|
|
29
|
+
* → 96-dim embedding.
|
|
30
|
+
* 3. classifier — 4-layer MLP over a 16-embedding window → P(wake)
|
|
31
|
+
* ∈ [0, 1].
|
|
32
|
+
*/
|
|
33
|
+
import type { WakeWordModel } from "./types";
|
|
34
|
+
/** Three GGUF paths that back one session. */
|
|
35
|
+
export interface WakeWordGgmlPaths {
|
|
36
|
+
/** Frozen Hann window + mel filter bank + STFT params metadata. */
|
|
37
|
+
melspec: string;
|
|
38
|
+
/** Embedding-CNN weights (fp16) + architecture metadata. */
|
|
39
|
+
embedding: string;
|
|
40
|
+
/** Classifier-head weights (fp16) + (1, 16, 96) input shape. */
|
|
41
|
+
classifier: string;
|
|
42
|
+
}
|
|
43
|
+
export interface WakeWordGgmlConfig {
|
|
44
|
+
/** Detection threshold ∈ [0, 1]. Default 0.5 (matches upstream openWakeWord). */
|
|
45
|
+
threshold?: number;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Thrown when the native ggml backend cannot be used. Distinct from
|
|
49
|
+
* `WakeWordUnavailableError` in `./wake-word.ts` so callers that fall
|
|
50
|
+
* back to the legacy ONNX path can tell the two failure modes apart
|
|
51
|
+
* during the migration.
|
|
52
|
+
*/
|
|
53
|
+
export declare class WakeWordGgmlUnavailableError extends Error {
|
|
54
|
+
readonly code: "not-bun" | "library-load-failed" | "model-load-failed" | "abi-error";
|
|
55
|
+
constructor(code: WakeWordGgmlUnavailableError["code"], message: string);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Streaming wake-word detector backed by `libwakeword`.
|
|
59
|
+
*
|
|
60
|
+
* Implements the same `WakeWordModel` interface as `OpenWakeWordModel`
|
|
61
|
+
* in `./wake-word.ts` so the voice lifecycle can swap implementations
|
|
62
|
+
* without changing anything upstream.
|
|
63
|
+
*/
|
|
64
|
+
export declare class OpenWakeWordGgmlModel implements WakeWordModel {
|
|
65
|
+
private readonly lib;
|
|
66
|
+
private readonly handle;
|
|
67
|
+
readonly frameSamples = 1280;
|
|
68
|
+
readonly sampleRate = 16000;
|
|
69
|
+
private constructor();
|
|
70
|
+
/**
|
|
71
|
+
* Load a wake-word model from its three GGUFs and the
|
|
72
|
+
* `libwakeword` shared library. Returns a ready-to-use detector
|
|
73
|
+
* with a fresh streaming session. Throws
|
|
74
|
+
* `WakeWordGgmlUnavailableError` on dlopen / ABI / GGUF failure.
|
|
75
|
+
*/
|
|
76
|
+
static load(args: {
|
|
77
|
+
libraryPath: string;
|
|
78
|
+
paths: WakeWordGgmlPaths;
|
|
79
|
+
config?: WakeWordGgmlConfig;
|
|
80
|
+
}): Promise<OpenWakeWordGgmlModel>;
|
|
81
|
+
/**
|
|
82
|
+
* Score one 1280-sample (80 ms @ 16 kHz) fp32 mono frame and
|
|
83
|
+
* return the most recent classifier probability ∈ [0, 1]. Early
|
|
84
|
+
* frames (before enough mel + embedding context has accumulated)
|
|
85
|
+
* return 0.
|
|
86
|
+
*/
|
|
87
|
+
scoreFrame(frame: Float32Array): Promise<number>;
|
|
88
|
+
/**
|
|
89
|
+
* Streaming state lives on the native side. The C ABI does not
|
|
90
|
+
* expose a separate `reset` entry point yet (Phase 2 will add one
|
|
91
|
+
* if the ggml-backed implementation needs it); for now, reset is
|
|
92
|
+
* a no-op on the JS side. Callers that need a hard state clear
|
|
93
|
+
* close + reopen the session.
|
|
94
|
+
*/
|
|
95
|
+
reset(): void;
|
|
96
|
+
/** Release the native session and the dlopen handle. */
|
|
97
|
+
close(): void;
|
|
98
|
+
/** Diagnostics: `"native-cpu"` on this build (pure-fp32 reference). */
|
|
99
|
+
activeBackend(): string;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=wake-word-ggml.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wake-word-ggml.d.ts","sourceRoot":"","sources":["wake-word-ggml.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAM7C,8CAA8C;AAC9C,MAAM,WAAW,iBAAiB;IACjC,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IAClC,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,qBAAa,4BAA6B,SAAQ,KAAK;IACtD,QAAQ,CAAC,IAAI,EACV,SAAS,GACT,qBAAqB,GACrB,mBAAmB,GACnB,WAAW,CAAC;gBACH,IAAI,EAAE,4BAA4B,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM;CAKvE;AAkID;;;;;;GAMG;AACH,qBAAa,qBAAsB,YAAW,aAAa;IAKzD,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IALxB,QAAQ,CAAC,YAAY,QAAiB;IACtC,QAAQ,CAAC,UAAU,SAAe;IAElC,OAAO;IAKP;;;;;OAKG;WACU,IAAI,CAAC,IAAI,EAAE;QACvB,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,iBAAiB,CAAC;QACzB,MAAM,CAAC,EAAE,kBAAkB,CAAC;KAC5B,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAyClC;;;;;OAKG;IACG,UAAU,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAuBtD;;;;;;OAMG;IACH,KAAK,IAAI,IAAI;IAIb,wDAAwD;IACxD,KAAK,IAAI,IAAI;IAKb,uEAAuE;IACvE,aAAa,IAAI,MAAM;CAIvB"}
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wake-word detection — native runtime binding.
|
|
3
|
+
*
|
|
4
|
+
* Loads the standalone `packages/native/plugins/wakeword-cpp/`
|
|
5
|
+
* library directly via `bun:ffi` and exposes the same `WakeWordModel`
|
|
6
|
+
* interface as the previous `onnxruntime-node`-backed implementation
|
|
7
|
+
* in `./wake-word.ts`, so the voice lifecycle can swap the two without
|
|
8
|
+
* changing anything upstream.
|
|
9
|
+
*
|
|
10
|
+
* Phase 2 status — this binding is now the default when the
|
|
11
|
+
* `libwakeword.{so,dylib,dll}` shared library and three converted
|
|
12
|
+
* GGUFs are present. The C runtime is a pure-fp32 reference
|
|
13
|
+
* implementation of the openWakeWord three-stage pipeline (melspec
|
|
14
|
+
* → embedding CNN → classifier head) — no ggml link, no SIMD; a
|
|
15
|
+
* laptop CPU runs it under 1 % of real time. ABI parity with the
|
|
16
|
+
* upstream openWakeWord ONNX graphs is gated by
|
|
17
|
+
* `packages/native/plugins/wakeword-cpp/test/wakeword_parity_test.py`.
|
|
18
|
+
*
|
|
19
|
+
* The ONNX path in `./wake-word.ts` stays as the fallback while the
|
|
20
|
+
* native binding shakes out. Once the migration is complete the ONNX
|
|
21
|
+
* path can be removed alongside the `onnxruntime-node` dependency.
|
|
22
|
+
*
|
|
23
|
+
* Three GGUFs back one session, mirroring openWakeWord's three ONNX
|
|
24
|
+
* graphs (the C library is the single source of truth on shapes —
|
|
25
|
+
* see `packages/native/plugins/wakeword-cpp/include/wakeword/wakeword.h`):
|
|
26
|
+
*
|
|
27
|
+
* 1. melspec — 16 kHz PCM → 32-bin log-mel frames.
|
|
28
|
+
* 2. embedding — 20-Conv2D CNN over a 76-mel-frame sliding window
|
|
29
|
+
* → 96-dim embedding.
|
|
30
|
+
* 3. classifier — 4-layer MLP over a 16-embedding window → P(wake)
|
|
31
|
+
* ∈ [0, 1].
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
import type { WakeWordModel } from "./types";
|
|
35
|
+
|
|
36
|
+
/** PCM frame size the streaming pipeline expects (80 ms @ 16 kHz). */
|
|
37
|
+
const FRAME_SAMPLES = 1280;
|
|
38
|
+
const SAMPLE_RATE = 16_000;
|
|
39
|
+
|
|
40
|
+
/** Three GGUF paths that back one session. */
|
|
41
|
+
export interface WakeWordGgmlPaths {
|
|
42
|
+
/** Frozen Hann window + mel filter bank + STFT params metadata. */
|
|
43
|
+
melspec: string;
|
|
44
|
+
/** Embedding-CNN weights (fp16) + architecture metadata. */
|
|
45
|
+
embedding: string;
|
|
46
|
+
/** Classifier-head weights (fp16) + (1, 16, 96) input shape. */
|
|
47
|
+
classifier: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface WakeWordGgmlConfig {
|
|
51
|
+
/** Detection threshold ∈ [0, 1]. Default 0.5 (matches upstream openWakeWord). */
|
|
52
|
+
threshold?: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Thrown when the native ggml backend cannot be used. Distinct from
|
|
57
|
+
* `WakeWordUnavailableError` in `./wake-word.ts` so callers that fall
|
|
58
|
+
* back to the legacy ONNX path can tell the two failure modes apart
|
|
59
|
+
* during the migration.
|
|
60
|
+
*/
|
|
61
|
+
export class WakeWordGgmlUnavailableError extends Error {
|
|
62
|
+
readonly code:
|
|
63
|
+
| "not-bun"
|
|
64
|
+
| "library-load-failed"
|
|
65
|
+
| "model-load-failed"
|
|
66
|
+
| "abi-error";
|
|
67
|
+
constructor(code: WakeWordGgmlUnavailableError["code"], message: string) {
|
|
68
|
+
super(message);
|
|
69
|
+
this.name = "WakeWordGgmlUnavailableError";
|
|
70
|
+
this.code = code;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Runtime detector — `bun:ffi` is Bun-only. */
|
|
75
|
+
function isBunRuntime(): boolean {
|
|
76
|
+
return typeof (globalThis as { Bun?: unknown }).Bun !== "undefined";
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Native session handle. The C side gives us a pointer (`bigint` under
|
|
81
|
+
* `bun:ffi`); we never inspect it on the JS side beyond passing it
|
|
82
|
+
* back through the binding.
|
|
83
|
+
*/
|
|
84
|
+
type NativeHandle = bigint;
|
|
85
|
+
|
|
86
|
+
/** Bound symbols from `libwakeword`. Mirrors `wakeword.h` 1:1. */
|
|
87
|
+
interface WakeWordBindings {
|
|
88
|
+
wakeword_open: (
|
|
89
|
+
melspec: unknown,
|
|
90
|
+
embedding: unknown,
|
|
91
|
+
classifier: unknown,
|
|
92
|
+
outHandle: unknown,
|
|
93
|
+
) => number;
|
|
94
|
+
wakeword_close: (handle: NativeHandle) => number;
|
|
95
|
+
wakeword_process: (
|
|
96
|
+
handle: NativeHandle,
|
|
97
|
+
pcm: unknown,
|
|
98
|
+
nSamples: bigint | number,
|
|
99
|
+
outScore: unknown,
|
|
100
|
+
) => number;
|
|
101
|
+
wakeword_set_threshold: (handle: NativeHandle, threshold: number) => number;
|
|
102
|
+
wakeword_active_backend: () => unknown;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
interface BoundLibrary {
|
|
106
|
+
bindings: WakeWordBindings;
|
|
107
|
+
close(): void;
|
|
108
|
+
libraryPath: string;
|
|
109
|
+
/** `bun:ffi` helper: encode an ArrayBufferView as a native pointer. */
|
|
110
|
+
ptr(value: ArrayBufferView): unknown;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** Minimal shape of the bun:ffi module we use here. */
|
|
114
|
+
interface BunFfiModule {
|
|
115
|
+
dlopen(
|
|
116
|
+
path: string,
|
|
117
|
+
def: Record<string, { args: number[]; returns: number }>,
|
|
118
|
+
): {
|
|
119
|
+
symbols: Record<string, (...args: unknown[]) => unknown>;
|
|
120
|
+
close(): void;
|
|
121
|
+
};
|
|
122
|
+
ptr(value: ArrayBufferView): unknown;
|
|
123
|
+
FFIType: {
|
|
124
|
+
cstring: number;
|
|
125
|
+
ptr: number;
|
|
126
|
+
i32: number;
|
|
127
|
+
u64: number;
|
|
128
|
+
f32: number;
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Resolve `bun:ffi` at runtime via the Bun-injected `require`. Mirrors
|
|
134
|
+
* the loader pattern in `./ffi-bindings.ts` (search for
|
|
135
|
+
* `loadBunFfiModule`) so plain Node test runs that import this file
|
|
136
|
+
* for type-only purposes do not blow up at the import site.
|
|
137
|
+
*/
|
|
138
|
+
function loadBunFfiModule(): BunFfiModule {
|
|
139
|
+
const req: ((id: string) => unknown) | undefined = (
|
|
140
|
+
globalThis as { Bun?: { __require?: (id: string) => unknown } }
|
|
141
|
+
).Bun?.__require;
|
|
142
|
+
if (typeof req === "function") {
|
|
143
|
+
return req("bun:ffi") as BunFfiModule;
|
|
144
|
+
}
|
|
145
|
+
const mod = require("node:module") as {
|
|
146
|
+
createRequire: (filename: string) => (id: string) => unknown;
|
|
147
|
+
};
|
|
148
|
+
const r = mod.createRequire(import.meta.url);
|
|
149
|
+
return r("bun:ffi") as BunFfiModule;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Load `libwakeword` and bind every symbol declared in `wakeword.h`.
|
|
154
|
+
* Throws `WakeWordGgmlUnavailableError({code: "library-load-failed"})`
|
|
155
|
+
* on `dlopen` failure.
|
|
156
|
+
*/
|
|
157
|
+
function loadLibrary(libraryPath: string): BoundLibrary {
|
|
158
|
+
if (!isBunRuntime()) {
|
|
159
|
+
throw new WakeWordGgmlUnavailableError(
|
|
160
|
+
"not-bun",
|
|
161
|
+
"[wake-word-ggml] bun:ffi is required; current runtime is not Bun",
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
if (!libraryPath || libraryPath.length === 0) {
|
|
165
|
+
throw new WakeWordGgmlUnavailableError(
|
|
166
|
+
"library-load-failed",
|
|
167
|
+
"[wake-word-ggml] libraryPath is required",
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
const bunFfi = loadBunFfiModule();
|
|
171
|
+
const T = bunFfi.FFIType;
|
|
172
|
+
const lib = bunFfi.dlopen(libraryPath, {
|
|
173
|
+
wakeword_open: {
|
|
174
|
+
args: [T.ptr, T.ptr, T.ptr, T.ptr],
|
|
175
|
+
returns: T.i32,
|
|
176
|
+
},
|
|
177
|
+
wakeword_close: {
|
|
178
|
+
args: [T.u64],
|
|
179
|
+
returns: T.i32,
|
|
180
|
+
},
|
|
181
|
+
wakeword_process: {
|
|
182
|
+
args: [T.u64, T.ptr, T.u64, T.ptr],
|
|
183
|
+
returns: T.i32,
|
|
184
|
+
},
|
|
185
|
+
wakeword_set_threshold: {
|
|
186
|
+
args: [T.u64, T.f32],
|
|
187
|
+
returns: T.i32,
|
|
188
|
+
},
|
|
189
|
+
wakeword_active_backend: {
|
|
190
|
+
args: [],
|
|
191
|
+
returns: T.cstring,
|
|
192
|
+
},
|
|
193
|
+
});
|
|
194
|
+
return {
|
|
195
|
+
bindings: lib.symbols as unknown as WakeWordBindings,
|
|
196
|
+
close: () => lib.close(),
|
|
197
|
+
libraryPath,
|
|
198
|
+
ptr: (v: ArrayBufferView) => bunFfi.ptr(v),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Streaming wake-word detector backed by `libwakeword`.
|
|
204
|
+
*
|
|
205
|
+
* Implements the same `WakeWordModel` interface as `OpenWakeWordModel`
|
|
206
|
+
* in `./wake-word.ts` so the voice lifecycle can swap implementations
|
|
207
|
+
* without changing anything upstream.
|
|
208
|
+
*/
|
|
209
|
+
export class OpenWakeWordGgmlModel implements WakeWordModel {
|
|
210
|
+
readonly frameSamples = FRAME_SAMPLES;
|
|
211
|
+
readonly sampleRate = SAMPLE_RATE;
|
|
212
|
+
|
|
213
|
+
private constructor(
|
|
214
|
+
private readonly lib: BoundLibrary,
|
|
215
|
+
private readonly handle: NativeHandle,
|
|
216
|
+
) {}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Load a wake-word model from its three GGUFs and the
|
|
220
|
+
* `libwakeword` shared library. Returns a ready-to-use detector
|
|
221
|
+
* with a fresh streaming session. Throws
|
|
222
|
+
* `WakeWordGgmlUnavailableError` on dlopen / ABI / GGUF failure.
|
|
223
|
+
*/
|
|
224
|
+
static async load(args: {
|
|
225
|
+
libraryPath: string;
|
|
226
|
+
paths: WakeWordGgmlPaths;
|
|
227
|
+
config?: WakeWordGgmlConfig;
|
|
228
|
+
}): Promise<OpenWakeWordGgmlModel> {
|
|
229
|
+
const lib = loadLibrary(args.libraryPath);
|
|
230
|
+
const out = new BigUint64Array(1);
|
|
231
|
+
/* Each path string needs a NUL terminator; we encode through
|
|
232
|
+
* Uint8Array and pass an explicit pointer because bun:ffi does
|
|
233
|
+
* not auto-convert Buffer -> cstring on every binding shape. */
|
|
234
|
+
const enc = new TextEncoder();
|
|
235
|
+
const melBuf = enc.encode(`${args.paths.melspec}\0`);
|
|
236
|
+
const embBuf = enc.encode(`${args.paths.embedding}\0`);
|
|
237
|
+
const clsBuf = enc.encode(`${args.paths.classifier}\0`);
|
|
238
|
+
const rc = lib.bindings.wakeword_open(
|
|
239
|
+
lib.ptr(melBuf),
|
|
240
|
+
lib.ptr(embBuf),
|
|
241
|
+
lib.ptr(clsBuf),
|
|
242
|
+
lib.ptr(out),
|
|
243
|
+
);
|
|
244
|
+
if (rc !== 0) {
|
|
245
|
+
lib.close();
|
|
246
|
+
throw new WakeWordGgmlUnavailableError(
|
|
247
|
+
"model-load-failed",
|
|
248
|
+
`[wake-word-ggml] wakeword_open(${args.paths.melspec}, ${args.paths.embedding}, ${args.paths.classifier}) returned ${rc}`,
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
const handle = out[0] as NativeHandle;
|
|
252
|
+
const model = new OpenWakeWordGgmlModel(lib, handle);
|
|
253
|
+
if (args.config?.threshold !== undefined) {
|
|
254
|
+
const setRc = lib.bindings.wakeword_set_threshold(
|
|
255
|
+
handle,
|
|
256
|
+
args.config.threshold,
|
|
257
|
+
);
|
|
258
|
+
if (setRc !== 0) {
|
|
259
|
+
model.close();
|
|
260
|
+
throw new WakeWordGgmlUnavailableError(
|
|
261
|
+
"abi-error",
|
|
262
|
+
`[wake-word-ggml] wakeword_set_threshold(${args.config.threshold}) returned ${setRc}`,
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return model;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Score one 1280-sample (80 ms @ 16 kHz) fp32 mono frame and
|
|
271
|
+
* return the most recent classifier probability ∈ [0, 1]. Early
|
|
272
|
+
* frames (before enough mel + embedding context has accumulated)
|
|
273
|
+
* return 0.
|
|
274
|
+
*/
|
|
275
|
+
async scoreFrame(frame: Float32Array): Promise<number> {
|
|
276
|
+
if (frame.length !== FRAME_SAMPLES) {
|
|
277
|
+
throw new Error(
|
|
278
|
+
`[wake-word-ggml] scoreFrame expects ${FRAME_SAMPLES} samples; got ${frame.length}`,
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
const out = new Float32Array(1);
|
|
282
|
+
const rc = this.lib.bindings.wakeword_process(
|
|
283
|
+
this.handle,
|
|
284
|
+
this.lib.ptr(frame),
|
|
285
|
+
BigInt(frame.length),
|
|
286
|
+
this.lib.ptr(out),
|
|
287
|
+
);
|
|
288
|
+
if (rc !== 0) {
|
|
289
|
+
throw new WakeWordGgmlUnavailableError(
|
|
290
|
+
"abi-error",
|
|
291
|
+
`[wake-word-ggml] wakeword_process returned ${rc}`,
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
const p = out[0] ?? 0;
|
|
295
|
+
return Math.min(1, Math.max(0, p));
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Streaming state lives on the native side. The C ABI does not
|
|
300
|
+
* expose a separate `reset` entry point yet (Phase 2 will add one
|
|
301
|
+
* if the ggml-backed implementation needs it); for now, reset is
|
|
302
|
+
* a no-op on the JS side. Callers that need a hard state clear
|
|
303
|
+
* close + reopen the session.
|
|
304
|
+
*/
|
|
305
|
+
reset(): void {
|
|
306
|
+
// Intentionally empty — see jsdoc above.
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/** Release the native session and the dlopen handle. */
|
|
310
|
+
close(): void {
|
|
311
|
+
this.lib.bindings.wakeword_close(this.handle);
|
|
312
|
+
this.lib.close();
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/** Diagnostics: `"native-cpu"` on this build (pure-fp32 reference). */
|
|
316
|
+
activeBackend(): string {
|
|
317
|
+
const raw = this.lib.bindings.wakeword_active_backend();
|
|
318
|
+
return typeof raw === "string" ? raw : String(raw ?? "");
|
|
319
|
+
}
|
|
320
|
+
}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wake-word detection (openWakeWord) — opt-in, local-mode only.
|
|
3
|
+
*
|
|
4
|
+
* Replaces the previous `onnxruntime-node`-backed implementation with a
|
|
5
|
+
* pure GGML / llama.cpp path. The three-stage openWakeWord pipeline (mel
|
|
6
|
+
* filterbank → speech embedding model → per-phrase classifier head) is
|
|
7
|
+
* compiled into one combined GGUF
|
|
8
|
+
* (`wake/openwakeword.gguf`, produced by
|
|
9
|
+
* `packages/training/scripts/wakeword/convert_openwakeword_to_gguf.py`)
|
|
10
|
+
* and executed natively by the fused `libelizainference` build via the
|
|
11
|
+
* `eliza_inference_wakeword_*` FFI surface (ABI v5).
|
|
12
|
+
*
|
|
13
|
+
* The JS side is now a thin adapter over that surface — there is NO ONNX
|
|
14
|
+
* fallback. When the fused library was built without the wake-word
|
|
15
|
+
* runtime, the JS path throws a structured `WakeWordUnavailableError`
|
|
16
|
+
* (AGENTS.md §3, §8 — no silent fallbacks).
|
|
17
|
+
*
|
|
18
|
+
* Per `packages/inference/AGENTS.md` §1 + the three-mode rules (§1, §5):
|
|
19
|
+
* - openWakeWord (Apache-2.0, ~3 MB) ships in the bundle but is
|
|
20
|
+
* **opt-in**: voice mode works without it (push-to-talk / VAD-gated).
|
|
21
|
+
* - It is **local-mode only**. In `cloud` mode the surface is hidden
|
|
22
|
+
* *and inert* (hide-not-disable §5): the model is not loaded, the
|
|
23
|
+
* setting is rejected by the API, no background job runs it.
|
|
24
|
+
* - Detections feed the same place a push-to-talk press would: they arm
|
|
25
|
+
* a listening window that the VAD gate then bounds.
|
|
26
|
+
*
|
|
27
|
+
* Streaming pipeline shape (16 kHz mono):
|
|
28
|
+
* - 1280-sample (80 ms) PCM frames per `scoreFrame` call.
|
|
29
|
+
* - Internally: mel filterbank → 32-bin frames; embedding model windows
|
|
30
|
+
* 76 mel frames, hop 8 → 96-dim embedding; head windows 16 embeddings
|
|
31
|
+
* → P(wake) in [0, 1].
|
|
32
|
+
* - The native runtime owns the audio tail, mel ring and embedding
|
|
33
|
+
* ring; the JS side feeds frames and reads back probabilities.
|
|
34
|
+
*/
|
|
35
|
+
import type { ElizaInferenceContextHandle, ElizaInferenceFfi } from "./ffi-bindings";
|
|
36
|
+
/** Directory holding the bundled openWakeWord GGUF inside a bundle. */
|
|
37
|
+
export declare const OPENWAKEWORD_DIR_REL_PATH = "wake";
|
|
38
|
+
/**
|
|
39
|
+
* Combined wake-word GGUF: contains the mel filterbank constants, the
|
|
40
|
+
* speech embedding model weights, AND every per-phrase classifier head
|
|
41
|
+
* (`head.<name>.*` tensors). The fused `libelizainference` build mmaps
|
|
42
|
+
* this file from `<bundleRoot>/wake/openwakeword.gguf` (or the shared
|
|
43
|
+
* cache at `<state-dir>/local-inference/wake/openwakeword.gguf`).
|
|
44
|
+
*/
|
|
45
|
+
export declare const OPENWAKEWORD_GGUF_REL_PATH: string;
|
|
46
|
+
/**
|
|
47
|
+
* Default wake-phrase head shipped with a voice bundle. The documented
|
|
48
|
+
* default Eliza-1 wake phrase is **"hey eliza"** — a two-word,
|
|
49
|
+
* four-syllable phrase the openWakeWord TTS-augmented pipeline handles
|
|
50
|
+
* well. It is replaceable: retrain on a different `--phrase` via
|
|
51
|
+
* `packages/training/scripts/wakeword/train_eliza1_wakeword_head.py`,
|
|
52
|
+
* convert to GGUF via
|
|
53
|
+
* `packages/training/scripts/wakeword/convert_openwakeword_to_gguf.py`,
|
|
54
|
+
* and re-point this constant.
|
|
55
|
+
*/
|
|
56
|
+
export declare const OPENWAKEWORD_DEFAULT_HEAD = "hey-eliza";
|
|
57
|
+
/**
|
|
58
|
+
* Heads that are placeholders, not trained on the Eliza-1 wake phrase.
|
|
59
|
+
*
|
|
60
|
+
* `hey-eliza` stays in this set until a head trained against the real
|
|
61
|
+
* phrase ships in every tier bundle (the bundled binary is still the
|
|
62
|
+
* upstream `hey_jarvis_v0.1` weights renamed). `hey_jarvis` stays by
|
|
63
|
+
* definition — it is the wrong phrase.
|
|
64
|
+
*
|
|
65
|
+
* A real "hey eliza" head HAS been trained and verified end-to-end through
|
|
66
|
+
* this exact runtime — ~98% true-accept / ~4-7% false-accept on a held-out set
|
|
67
|
+
* scored via `libwakeword.so` (see
|
|
68
|
+
* `packages/training/scripts/wakeword/HEY_ELIZA_HEAD_PROVENANCE.md`). It must
|
|
69
|
+
* be trained with `train_eliza1_wakeword_head.py --no-mel-rescale` to match
|
|
70
|
+
* this runtime's mel preprocessing.
|
|
71
|
+
*
|
|
72
|
+
* The trained GGUFs are now PUBLISHED to `elizaos/eliza-1` at
|
|
73
|
+
* `voice/wakeword/hey-eliza.{melspec,embedding,classifier}.gguf` and registered
|
|
74
|
+
* in the voice catalog as `wakeword` v0.3.0 (`VOICE_MODEL_VERSIONS` in
|
|
75
|
+
* `@elizaos/shared`). `hey-eliza` nonetheless STAYS in this set until that head
|
|
76
|
+
* ships in every tier BUNDLE's `wake/` dir — the gated `publish_all_eliza1.sh`
|
|
77
|
+
* re-publish — because the bundles users currently download still carry the
|
|
78
|
+
* renamed `hey_jarvis` placeholder; removing the flag before the bundle ships
|
|
79
|
+
* the real head would make the runtime treat the placeholder as authentic.
|
|
80
|
+
* `hey_jarvis` stays by definition (wrong phrase). A future pass should make
|
|
81
|
+
* this data-driven off the bundle manifest's `releaseState` rather than
|
|
82
|
+
* hard-coded.
|
|
83
|
+
*/
|
|
84
|
+
export declare const OPENWAKEWORD_PLACEHOLDER_HEADS: ReadonlySet<string>;
|
|
85
|
+
export declare function isPlaceholderWakeWordHead(head: string): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Per-frame wake-word probability source. openWakeWord runs on 80 ms
|
|
88
|
+
* frames of 16 kHz audio; `scoreFrame` takes one PCM frame and returns
|
|
89
|
+
* the latest P(wake) in [0, 1] (the head only re-runs once enough
|
|
90
|
+
* context has accumulated — early frames return 0). Stateful (the
|
|
91
|
+
* streaming front-end carries its buffers); `reset()` clears it.
|
|
92
|
+
*
|
|
93
|
+
* The default backend (`GgmlWakeWordModel`) calls into the native FFI
|
|
94
|
+
* synchronously; the method is still `async` so the interface fits a
|
|
95
|
+
* async-friendly backend variant (e.g. worker-thread based) and
|
|
96
|
+
* matches the same shape the previous ONNX backend exposed to callers.
|
|
97
|
+
*/
|
|
98
|
+
export type { WakeWordModel } from "./types.js";
|
|
99
|
+
import type { WakeWordModel } from "./types.js";
|
|
100
|
+
export interface WakeWordConfig {
|
|
101
|
+
/** P(wake) above this fires a detection. openWakeWord default ~0.5. */
|
|
102
|
+
threshold?: number;
|
|
103
|
+
/**
|
|
104
|
+
* Refractory frames after a detection during which no new detection
|
|
105
|
+
* fires (debounce a single utterance into one event).
|
|
106
|
+
*/
|
|
107
|
+
refractoryFrames?: number;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Thrown when the native openWakeWord runtime cannot service this call:
|
|
111
|
+
* - `ffi-missing`: the FFI handle was not provided to the loader (the
|
|
112
|
+
* voice lifecycle hands one in via `loadBundledWakeWordModel`).
|
|
113
|
+
* - `runtime-not-ready`: the fused `libelizainference` build does not
|
|
114
|
+
* export `eliza_inference_wakeword_*` — the wake-word GGUF runtime
|
|
115
|
+
* is not yet compiled into this binary. NOT thrown for an absent
|
|
116
|
+
* bundled GGUF (that is "wake word unavailable for this bundle",
|
|
117
|
+
* not a broken build — `resolveWakeWordModel` returns null instead).
|
|
118
|
+
* - `model-load-failed`: the native side rejected the GGUF or the
|
|
119
|
+
* selected head name at session open.
|
|
120
|
+
*/
|
|
121
|
+
export declare class WakeWordUnavailableError extends Error {
|
|
122
|
+
readonly code: "ffi-missing" | "runtime-not-ready" | "model-load-failed";
|
|
123
|
+
constructor(code: WakeWordUnavailableError["code"], message: string);
|
|
124
|
+
}
|
|
125
|
+
/** Path to the combined wake-word GGUF and the name of the head to bind. */
|
|
126
|
+
export interface WakeWordModelPaths {
|
|
127
|
+
/** Absolute path to `wake/openwakeword.gguf`. */
|
|
128
|
+
gguf: string;
|
|
129
|
+
/** Name of the classifier head inside the GGUF (e.g. "hey-eliza"). */
|
|
130
|
+
head: string;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* The real openWakeWord streaming detector, backed by the native FFI.
|
|
134
|
+
* Owns one `eliza_inference_wakeword_*` session; `scoreFrame` consumes
|
|
135
|
+
* exactly `frameSamples` (1280) samples at 16 kHz and returns the most
|
|
136
|
+
* recent head probability the native pipeline produced. The audio tail,
|
|
137
|
+
* mel ring and embedding ring live on the C side; this class is a thin
|
|
138
|
+
* handle.
|
|
139
|
+
*/
|
|
140
|
+
export declare class GgmlWakeWordModel implements WakeWordModel {
|
|
141
|
+
private readonly ffi;
|
|
142
|
+
private readonly handle;
|
|
143
|
+
readonly frameSamples = 1280;
|
|
144
|
+
readonly sampleRate = 16000;
|
|
145
|
+
private closed;
|
|
146
|
+
private constructor();
|
|
147
|
+
/**
|
|
148
|
+
* True only when the fused `libelizainference` build exports the
|
|
149
|
+
* wake-word ABI and advertises support at runtime. The wake-word
|
|
150
|
+
* loader uses this to surface a structured `runtime-not-ready` error
|
|
151
|
+
* before attempting to open a session.
|
|
152
|
+
*/
|
|
153
|
+
static isSupported(ffi: ElizaInferenceFfi | null | undefined): boolean;
|
|
154
|
+
/**
|
|
155
|
+
* Open a native wake-word session. Throws `WakeWordUnavailableError`
|
|
156
|
+
* when the runtime is not present or rejects the head name. No silent
|
|
157
|
+
* fallback (AGENTS.md §3).
|
|
158
|
+
*/
|
|
159
|
+
static load(opts: {
|
|
160
|
+
ffi: ElizaInferenceFfi;
|
|
161
|
+
ctx: ElizaInferenceContextHandle | (() => ElizaInferenceContextHandle);
|
|
162
|
+
headName: string;
|
|
163
|
+
}): Promise<GgmlWakeWordModel>;
|
|
164
|
+
scoreFrame(frame: Float32Array): Promise<number>;
|
|
165
|
+
reset(): void;
|
|
166
|
+
close(): void;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Resolve the bundled wake-word GGUF. Unlike the VAD model this is
|
|
170
|
+
* *optional* — a missing file means "wake word unavailable for this
|
|
171
|
+
* bundle", not "broken bundle". Returns null when the GGUF is absent so
|
|
172
|
+
* callers keep voice mode working (push-to-talk / VAD-gated) without it.
|
|
173
|
+
*
|
|
174
|
+
* Search order:
|
|
175
|
+
* 1. `<bundleRoot>/wake/openwakeword.gguf`
|
|
176
|
+
* 2. `<state-dir>/local-inference/wake/openwakeword.gguf` (shared cache)
|
|
177
|
+
*
|
|
178
|
+
* `head` defaults to the bundle's default wake phrase. The head name is
|
|
179
|
+
* resolved by the native runtime against tensors inside the GGUF, so it
|
|
180
|
+
* is validated at open time, not here.
|
|
181
|
+
*
|
|
182
|
+
* MUST only be called in `local` mode. The cloud-mode router does not
|
|
183
|
+
* reach this (the wake-word setting is rejected there) — see AGENTS.md §5
|
|
184
|
+
* hide-not-disable.
|
|
185
|
+
*/
|
|
186
|
+
export declare function resolveWakeWordModel(opts: {
|
|
187
|
+
bundleRoot?: string;
|
|
188
|
+
head?: string;
|
|
189
|
+
}): WakeWordModelPaths | null;
|
|
190
|
+
/** Resolved triple of standalone wakeword-cpp paths (library + 3 GGUFs). */
|
|
191
|
+
export interface WakeWordStandalonePaths {
|
|
192
|
+
libraryPath: string;
|
|
193
|
+
melspec: string;
|
|
194
|
+
embedding: string;
|
|
195
|
+
classifier: string;
|
|
196
|
+
head: string;
|
|
197
|
+
}
|
|
198
|
+
export declare function resolveWakeWordStandalonePaths(opts: {
|
|
199
|
+
bundleRoot?: string;
|
|
200
|
+
head?: string;
|
|
201
|
+
}): WakeWordStandalonePaths | null;
|
|
202
|
+
/**
|
|
203
|
+
* Open a wake-word session, preferring the fused `libelizainference`
|
|
204
|
+
* wake-word path (the single native engine the whole voice pipeline runs
|
|
205
|
+
* through — the user directive: no separate bun:ffi-musl libs). Falls back to
|
|
206
|
+
* the standalone `wakeword-cpp` build only when the fused build does not carry
|
|
207
|
+
* the wake-word GGUF. Returns `null` when neither provider can serve a session.
|
|
208
|
+
*
|
|
209
|
+
* Provider order:
|
|
210
|
+
* 1. `GgmlWakeWordModel` (this file) — the fused-`libelizainference` path
|
|
211
|
+
* that consumes `wake/openwakeword.gguf` from the bundle cache via the
|
|
212
|
+
* `eliza_inference_wakeword_*` ABI. Tried first whenever the bundled GGUF
|
|
213
|
+
* is on disk; uses the same `ffi`/`ctx` as VAD / speaker / TTS / ASR.
|
|
214
|
+
* 2. `OpenWakeWordGgmlModel` from `./wake-word-ggml.ts` — the standalone
|
|
215
|
+
* `packages/native/plugins/wakeword-cpp` build (three GGUFs). Guarded
|
|
216
|
+
* fallback for paths where the fused build lacks the wake-word runtime.
|
|
217
|
+
*
|
|
218
|
+
* `ffi` and `ctx` come from the voice lifecycle — they are the same
|
|
219
|
+
* `ElizaInferenceFfi` handle and context the VAD / speaker / TTS / ASR paths
|
|
220
|
+
* use. The standalone fallback uses neither.
|
|
221
|
+
*/
|
|
222
|
+
export declare function loadBundledWakeWordModel(opts: {
|
|
223
|
+
ffi: ElizaInferenceFfi;
|
|
224
|
+
ctx: ElizaInferenceContextHandle | (() => ElizaInferenceContextHandle);
|
|
225
|
+
bundleRoot?: string;
|
|
226
|
+
head?: string;
|
|
227
|
+
}): Promise<WakeWordModel | null>;
|
|
228
|
+
/**
|
|
229
|
+
* Streaming wake-word detector. Feed frames; `onWake` fires once per
|
|
230
|
+
* detected utterance (refractory-debounced). The voice loop wires
|
|
231
|
+
* `onWake` to "start a listening window" — exactly what a push-to-talk
|
|
232
|
+
* press does.
|
|
233
|
+
*
|
|
234
|
+
* Only constructed in `local` mode. `cloud` mode never instantiates this
|
|
235
|
+
* (and `resolveWakeWordModel` is never called there), so the surface is
|
|
236
|
+
* inert per the hide-not-disable rule.
|
|
237
|
+
*/
|
|
238
|
+
export declare class OpenWakeWordDetector {
|
|
239
|
+
private readonly model;
|
|
240
|
+
private readonly cfg;
|
|
241
|
+
private cooldown;
|
|
242
|
+
private readonly onWake;
|
|
243
|
+
constructor(args: {
|
|
244
|
+
model: WakeWordModel;
|
|
245
|
+
config?: WakeWordConfig;
|
|
246
|
+
onWake: () => void;
|
|
247
|
+
});
|
|
248
|
+
/**
|
|
249
|
+
* Score one PCM frame; fire `onWake` on a fresh detection. Resolves
|
|
250
|
+
* to true when this frame fired the wake word.
|
|
251
|
+
*/
|
|
252
|
+
pushFrame(frame: Float32Array): Promise<boolean>;
|
|
253
|
+
reset(): void;
|
|
254
|
+
}
|
|
255
|
+
//# sourceMappingURL=wake-word.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wake-word.d.ts","sourceRoot":"","sources":["wake-word.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAKH,OAAO,KAAK,EACX,2BAA2B,EAC3B,iBAAiB,EAEjB,MAAM,gBAAgB,CAAC;AAMxB,uEAAuE;AACvE,eAAO,MAAM,yBAAyB,SAAS,CAAC;AAEhD;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,QAGtC,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,yBAAyB,cAAc,CAAC;AAErD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,8BAA8B,EAAE,WAAW,CAAC,MAAM,CAG7D,CAAC;AAEH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE/D;AAKD;;;;;;;;;;;GAWG;AACH,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,WAAW,cAAc;IAC9B,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1B;AAOD;;;;;;;;;;;GAWG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;IAClD,QAAQ,CAAC,IAAI,EAAE,aAAa,GAAG,mBAAmB,GAAG,mBAAmB,CAAC;gBAC7D,IAAI,EAAE,wBAAwB,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM;CAKnE;AAED,4EAA4E;AAC5E,MAAM,WAAW,kBAAkB;IAClC,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;GAOG;AACH,qBAAa,iBAAkB,YAAW,aAAa;IAMrD,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IANxB,QAAQ,CAAC,YAAY,QAAiB;IACtC,QAAQ,CAAC,UAAU,SAAU;IAC7B,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO;IAKP;;;;;OAKG;IACH,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,iBAAiB,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO;IAKtE;;;;OAIG;WACU,IAAI,CAAC,IAAI,EAAE;QACvB,GAAG,EAAE,iBAAiB,CAAC;QACvB,GAAG,EAAE,2BAA2B,GAAG,CAAC,MAAM,2BAA2B,CAAC,CAAC;QACvE,QAAQ,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAqCxB,UAAU,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAkBtD,KAAK,IAAI,IAAI;IASb,KAAK,IAAI,IAAI;CAKb;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,kBAAkB,GAAG,IAAI,CAW5B;AAoCD,4EAA4E;AAC5E,MAAM,WAAW,uBAAuB;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,8BAA8B,CAAC,IAAI,EAAE;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,uBAAuB,GAAG,IAAI,CAwDjC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,wBAAwB,CAAC,IAAI,EAAE;IACpD,GAAG,EAAE,iBAAiB,CAAC;IACvB,GAAG,EAAE,2BAA2B,GAAG,CAAC,MAAM,2BAA2B,CAAC,CAAC;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAmDhC;AAED;;;;;;;;;GASG;AACH,qBAAa,oBAAoB;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IACtC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA2B;IAC/C,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;gBAExB,IAAI,EAAE;QACjB,KAAK,EAAE,aAAa,CAAC;QACrB,MAAM,CAAC,EAAE,cAAc,CAAC;QACxB,MAAM,EAAE,MAAM,IAAI,CAAC;KACnB;IAMD;;;OAGG;IACG,SAAS,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC;IAoBtD,KAAK,IAAI,IAAI;CAIb"}
|