@elizaos/plugin-local-inference 2.0.3-beta.2 → 2.0.3-beta.3
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/README.md +84 -10
- package/dist/actions/generate-media.d.ts.map +1 -0
- package/dist/actions/identify-speaker.d.ts.map +1 -0
- package/dist/actions/transcription-control.d.ts.map +1 -0
- package/dist/adapters/capacitor-llama/environment.d.ts +12 -0
- package/dist/adapters/capacitor-llama/environment.d.ts.map +1 -0
- package/dist/adapters/capacitor-llama/index.browser.d.ts +9 -0
- package/dist/adapters/capacitor-llama/index.browser.d.ts.map +1 -0
- package/dist/adapters/capacitor-llama/index.d.ts +18 -0
- package/dist/adapters/capacitor-llama/index.d.ts.map +1 -0
- package/dist/adapters/capacitor-llama/loader.d.ts +35 -0
- package/dist/adapters/capacitor-llama/loader.d.ts.map +1 -0
- package/dist/adapters/capacitor-llama/native-voice-capture.d.ts +70 -0
- package/dist/adapters/capacitor-llama/native-voice-capture.d.ts.map +1 -0
- package/dist/adapters/capacitor-llama/structured-output.d.ts +62 -0
- package/dist/adapters/capacitor-llama/structured-output.d.ts.map +1 -0
- package/dist/adapters/capacitor-llama/text-streaming.d.ts +24 -0
- package/dist/adapters/capacitor-llama/text-streaming.d.ts.map +1 -0
- package/dist/adapters/capacitor-llama/types.d.ts +338 -0
- package/dist/adapters/capacitor-llama/types.d.ts.map +1 -0
- package/dist/adapters/capacitor-llama/voice-turn.d.ts +86 -0
- package/dist/adapters/capacitor-llama/voice-turn.d.ts.map +1 -0
- package/dist/backends/apple-foundation.d.ts +56 -0
- package/dist/backends/apple-foundation.d.ts.map +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39647 -0
- package/dist/index.js.map +217 -0
- package/{src → dist}/local-inference-routes.d.ts +9 -0
- package/dist/local-inference-routes.d.ts.map +1 -0
- package/dist/provider.d.ts.map +1 -0
- package/{src → dist}/routes/compat-helpers.d.ts +1 -1
- package/dist/routes/compat-helpers.d.ts.map +1 -0
- package/dist/routes/family-member-route.d.ts.map +1 -0
- package/{src → dist}/routes/index.d.ts +1 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +42040 -0
- package/dist/routes/index.js.map +236 -0
- package/{src → dist}/routes/live-diarization-route.d.ts +7 -0
- package/dist/routes/live-diarization-route.d.ts.map +1 -0
- package/dist/routes/local-inference-asr-route.d.ts.map +1 -0
- package/dist/routes/local-inference-asr-transcribe.d.ts.map +1 -0
- package/dist/routes/local-inference-compat-routes.d.ts.map +1 -0
- package/dist/routes/local-inference-tts-route.d.ts.map +1 -0
- package/dist/routes/native-pcm-turn-route.d.ts +3 -0
- package/dist/routes/native-pcm-turn-route.d.ts.map +1 -0
- package/dist/routes/transcript-audio-store.d.ts.map +1 -0
- package/{src → dist}/routes/transcripts-routes.d.ts +8 -0
- package/dist/routes/transcripts-routes.d.ts.map +1 -0
- package/dist/routes/voice-first-run-routes.d.ts.map +1 -0
- package/dist/routes/voice-models-routes.d.ts.map +1 -0
- package/dist/routes/voice-profile-plugin-routes.d.ts.map +1 -0
- package/dist/routes/voice-profiles-management-routes.d.ts.map +1 -0
- package/dist/routes/voice-speaker-profile-routes.d.ts.map +1 -0
- package/dist/runtime/embedding-manager-support.d.ts.map +1 -0
- package/dist/runtime/embedding-presets.d.ts.map +1 -0
- package/dist/runtime/embedding-warmup-policy.d.ts.map +1 -0
- package/{src → dist}/runtime/ensure-local-inference-handler.d.ts +8 -0
- package/dist/runtime/ensure-local-inference-handler.d.ts.map +1 -0
- package/{src → dist}/runtime/index.d.ts +1 -1
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +38768 -0
- package/dist/runtime/index.js.map +217 -0
- package/dist/runtime/mobile-local-inference-gate.d.ts +63 -0
- package/dist/runtime/mobile-local-inference-gate.d.ts.map +1 -0
- package/{src → dist}/runtime/voice-entity-binding.d.ts +10 -0
- package/dist/runtime/voice-entity-binding.d.ts.map +1 -0
- package/{src → dist}/services/active-model.d.ts +28 -0
- package/dist/services/active-model.d.ts.map +1 -0
- package/dist/services/asr-provenance.d.ts +5 -0
- package/dist/services/asr-provenance.d.ts.map +1 -0
- package/{src → dist}/services/assignments.d.ts +16 -3
- package/dist/services/assignments.d.ts.map +1 -0
- package/dist/services/backend-selector.d.ts +55 -0
- package/dist/services/backend-selector.d.ts.map +1 -0
- package/{src → dist}/services/backend.d.ts +110 -16
- package/dist/services/backend.d.ts.map +1 -0
- package/{src → dist}/services/bionic-host-loader.d.ts +21 -0
- package/dist/services/bionic-host-loader.d.ts.map +1 -0
- package/dist/services/bundled-models.d.ts.map +1 -0
- package/dist/services/cache-bridge.d.ts.map +1 -0
- package/dist/services/catalog.d.ts +10 -0
- package/dist/services/catalog.d.ts.map +1 -0
- package/dist/services/checkpoint-client.d.ts.map +1 -0
- package/dist/services/checkpoint-manager.d.ts +217 -0
- package/dist/services/checkpoint-manager.d.ts.map +1 -0
- package/dist/services/cloud-fallback.d.ts.map +1 -0
- package/dist/services/context-fit.d.ts +36 -0
- package/dist/services/context-fit.d.ts.map +1 -0
- package/dist/services/conversation-registry.d.ts.map +1 -0
- package/{src → dist}/services/desktop-fused-ffi-backend-runtime.d.ts +22 -6
- package/dist/services/desktop-fused-ffi-backend-runtime.d.ts.map +1 -0
- package/dist/services/device-bridge.d.ts.map +1 -0
- package/dist/services/device-resource-metrics.d.ts.map +1 -0
- package/{src → dist}/services/device-tier.d.ts +19 -1
- package/dist/services/device-tier.d.ts.map +1 -0
- package/{src → dist}/services/downloader.d.ts +16 -4
- package/dist/services/downloader.d.ts.map +1 -0
- package/{src → dist}/services/engine.d.ts +43 -4
- package/dist/services/engine.d.ts.map +1 -0
- package/dist/services/ensure-local-artifacts.d.ts +82 -0
- package/dist/services/ensure-local-artifacts.d.ts.map +1 -0
- package/dist/services/external-scanner.d.ts.map +1 -0
- package/dist/services/ffi-llm-mock.d.ts +90 -0
- package/dist/services/ffi-llm-mock.d.ts.map +1 -0
- package/dist/services/ffi-llm-streaming-abi.d.ts +318 -0
- package/dist/services/ffi-llm-streaming-abi.d.ts.map +1 -0
- package/{src → dist}/services/ffi-streaming-backend.d.ts +28 -7
- package/dist/services/ffi-streaming-backend.d.ts.map +1 -0
- package/{src → dist}/services/ffi-streaming-runner.d.ts +24 -0
- package/dist/services/ffi-streaming-runner.d.ts.map +1 -0
- package/dist/services/gpu-autotune.d.ts +150 -0
- package/dist/services/gpu-autotune.d.ts.map +1 -0
- package/dist/services/gpu-detect.d.ts.map +1 -0
- package/dist/services/handler-registry.d.ts.map +1 -0
- package/dist/services/hardware.d.ts.map +1 -0
- package/dist/services/image-description-runtime.d.ts.map +1 -0
- package/dist/services/imagegen/aosp-unavailable.d.ts.map +1 -0
- package/dist/services/imagegen/backend-selector.d.ts.map +1 -0
- package/dist/services/imagegen/coreml-unavailable.d.ts.map +1 -0
- package/dist/services/imagegen/errors.d.ts.map +1 -0
- package/dist/services/imagegen/index.d.ts.map +1 -0
- package/dist/services/imagegen/mflux.d.ts.map +1 -0
- package/{src → dist}/services/imagegen/sd-cpp.d.ts +1 -0
- package/dist/services/imagegen/sd-cpp.d.ts.map +1 -0
- package/dist/services/imagegen/tensorrt-unavailable.d.ts.map +1 -0
- package/dist/services/imagegen/types.d.ts.map +1 -0
- package/{src → dist}/services/index.d.ts +3 -1
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +39453 -0
- package/dist/services/index.js.map +227 -0
- package/dist/services/inference-capabilities.d.ts.map +1 -0
- package/dist/services/inference-telemetry.d.ts.map +1 -0
- package/dist/services/ios-llama-streaming.d.ts +119 -0
- package/dist/services/ios-llama-streaming.d.ts.map +1 -0
- package/dist/services/kv-spill.d.ts.map +1 -0
- package/dist/services/latency-trace.d.ts.map +1 -0
- package/dist/services/lib-target.d.ts +55 -0
- package/dist/services/lib-target.d.ts.map +1 -0
- package/dist/services/live-signals.d.ts +86 -0
- package/dist/services/live-signals.d.ts.map +1 -0
- package/dist/services/llama-server-metrics.d.ts +114 -0
- package/dist/services/llama-server-metrics.d.ts.map +1 -0
- package/dist/services/llm-streaming-binding.d.ts.map +1 -0
- package/dist/services/load-args.d.ts.map +1 -0
- package/dist/services/manifest/index.d.ts +4 -0
- package/dist/services/manifest/index.d.ts.map +1 -0
- package/{src → dist}/services/manifest/schema.d.ts +196 -6
- package/dist/services/manifest/schema.d.ts.map +1 -0
- package/{src → dist}/services/manifest/types.d.ts +3 -1
- package/dist/services/manifest/types.d.ts.map +1 -0
- package/dist/services/manifest/validator.d.ts.map +1 -0
- package/{src → dist}/services/memory-arbiter.d.ts +33 -3
- package/dist/services/memory-arbiter.d.ts.map +1 -0
- package/dist/services/memory-benchmark.d.ts +76 -0
- package/dist/services/memory-benchmark.d.ts.map +1 -0
- package/{src → dist}/services/memory-monitor.d.ts +6 -0
- package/dist/services/memory-monitor.d.ts.map +1 -0
- package/dist/services/memory-pressure.d.ts.map +1 -0
- package/dist/services/mtp-doctor.d.ts.map +1 -0
- package/dist/services/network-policy.d.ts.map +1 -0
- package/dist/services/paths.d.ts.map +1 -0
- package/dist/services/planner-skeleton.d.ts.map +1 -0
- package/dist/services/providers.d.ts.map +1 -0
- package/dist/services/ram-budget.d.ts.map +1 -0
- package/dist/services/readiness.d.ts.map +1 -0
- package/dist/services/recommendation.d.ts.map +1 -0
- package/{src → dist}/services/registry.d.ts +11 -13
- package/dist/services/registry.d.ts.map +1 -0
- package/{src → dist}/services/router-handler.d.ts +2 -2
- package/dist/services/router-handler.d.ts.map +1 -0
- package/{src → dist}/services/routing-policy.d.ts +32 -9
- package/dist/services/routing-policy.d.ts.map +1 -0
- package/dist/services/routing-preferences.d.ts.map +1 -0
- package/dist/services/runtime-target.d.ts.map +1 -0
- package/{src → dist}/services/service.d.ts +1 -1
- package/dist/services/service.d.ts.map +1 -0
- package/dist/services/session-pool.d.ts.map +1 -0
- package/dist/services/structured-output/deterministic-repair.d.ts.map +1 -0
- package/dist/services/structured-output/index.d.ts +2 -0
- package/dist/services/structured-output/index.d.ts.map +1 -0
- package/dist/services/structured-output.d.ts.map +1 -0
- package/dist/services/system-memory.d.ts.map +1 -0
- package/{src → dist}/services/types.d.ts +1 -1
- package/dist/services/types.d.ts.map +1 -0
- package/dist/services/verify-on-device.d.ts.map +1 -0
- package/dist/services/verify.d.ts.map +1 -0
- package/dist/services/vision/aosp-unavailable.d.ts.map +1 -0
- package/dist/services/vision/capacitor-llama.d.ts.map +1 -0
- package/dist/services/vision/cloud-fallback.d.ts.map +1 -0
- package/dist/services/vision/hash.d.ts.map +1 -0
- package/{src → dist}/services/vision/index.d.ts +1 -1
- package/dist/services/vision/index.d.ts.map +1 -0
- package/dist/services/vision/llama-server.d.ts.map +1 -0
- package/{src → dist}/services/vision/types.d.ts +13 -4
- package/dist/services/vision/types.d.ts.map +1 -0
- package/dist/services/vision/vast-fallback.d.ts.map +1 -0
- package/{src → dist}/services/vision-embedding-cache.d.ts +1 -1
- package/dist/services/vision-embedding-cache.d.ts.map +1 -0
- package/dist/services/voice/__test-helpers__/fake-ffi.d.ts +27 -0
- package/dist/services/voice/__test-helpers__/fake-ffi.d.ts.map +1 -0
- package/dist/services/voice/__test-helpers__/synthetic-speech.d.ts +66 -0
- package/dist/services/voice/__test-helpers__/synthetic-speech.d.ts.map +1 -0
- package/dist/services/voice/acoustic-speaker-attribution.d.ts +61 -0
- package/dist/services/voice/acoustic-speaker-attribution.d.ts.map +1 -0
- package/{src → dist}/services/voice/audio-frame-consumer.d.ts +82 -0
- package/dist/services/voice/audio-frame-consumer.d.ts.map +1 -0
- package/dist/services/voice/barge-in.d.ts.map +1 -0
- package/dist/services/voice/cancellation-coordinator.d.ts.map +1 -0
- package/dist/services/voice/checkpoint-manager.d.ts.map +1 -0
- package/dist/services/voice/checkpoint-policy.d.ts +178 -0
- package/dist/services/voice/checkpoint-policy.d.ts.map +1 -0
- package/dist/services/voice/corpus-augment.d.ts +111 -0
- package/dist/services/voice/corpus-augment.d.ts.map +1 -0
- package/dist/services/voice/corpus-generator.d.ts +134 -0
- package/dist/services/voice/corpus-generator.d.ts.map +1 -0
- package/dist/services/voice/diarization-error-rate.d.ts +40 -0
- package/dist/services/voice/diarization-error-rate.d.ts.map +1 -0
- package/dist/services/voice/e2e-harness.d.ts +297 -0
- package/dist/services/voice/e2e-harness.d.ts.map +1 -0
- package/dist/services/voice/eager-context-builder.d.ts.map +1 -0
- package/dist/services/voice/echo-delay.d.ts +67 -0
- package/dist/services/voice/echo-delay.d.ts.map +1 -0
- package/dist/services/voice/echo-metrics.d.ts +7 -0
- package/dist/services/voice/echo-metrics.d.ts.map +1 -0
- package/dist/services/voice/echo-reference-buffer.d.ts +65 -0
- package/dist/services/voice/echo-reference-buffer.d.ts.map +1 -0
- package/{src → dist}/services/voice/eliza1-eot-scorer.d.ts +8 -8
- package/dist/services/voice/eliza1-eot-scorer.d.ts.map +1 -0
- package/dist/services/voice/embedding-server.d.ts +37 -0
- package/dist/services/voice/embedding-server.d.ts.map +1 -0
- package/{src → dist}/services/voice/embedding.d.ts +2 -3
- package/dist/services/voice/embedding.d.ts.map +1 -0
- package/dist/services/voice/emotion-attribution.d.ts.map +1 -0
- package/{src → dist}/services/voice/engine-bridge.d.ts +8 -5
- package/dist/services/voice/engine-bridge.d.ts.map +1 -0
- package/{src → dist}/services/voice/eot-classifier-ggml.d.ts +22 -22
- package/dist/services/voice/eot-classifier-ggml.d.ts.map +1 -0
- package/{src → dist}/services/voice/eot-classifier.d.ts +9 -12
- package/dist/services/voice/eot-classifier.d.ts.map +1 -0
- package/{src → dist}/services/voice/errors.d.ts +1 -1
- package/dist/services/voice/errors.d.ts.map +1 -0
- package/{src → dist}/services/voice/expressive-tags.d.ts +5 -5
- package/dist/services/voice/expressive-tags.d.ts.map +1 -0
- package/{src → dist}/services/voice/ffi-bindings.d.ts +26 -4
- package/dist/services/voice/ffi-bindings.d.ts.map +1 -0
- package/dist/services/voice/first-line-cache.d.ts.map +1 -0
- package/{src → dist}/services/voice/fused-eot-scorer.d.ts +6 -6
- package/dist/services/voice/fused-eot-scorer.d.ts.map +1 -0
- package/{src → dist}/services/voice/index.d.ts +8 -3
- package/dist/services/voice/index.d.ts.map +1 -0
- package/dist/services/voice/kokoro/index.d.ts +24 -0
- package/dist/services/voice/kokoro/index.d.ts.map +1 -0
- package/{src → dist}/services/voice/kokoro/kokoro-backend.d.ts +15 -0
- package/dist/services/voice/kokoro/kokoro-backend.d.ts.map +1 -0
- package/{src → dist}/services/voice/kokoro/kokoro-engine-discovery.d.ts +1 -1
- package/dist/services/voice/kokoro/kokoro-engine-discovery.d.ts.map +1 -0
- package/{src → dist}/services/voice/kokoro/kokoro-ffi-runtime.d.ts +3 -3
- package/dist/services/voice/kokoro/kokoro-ffi-runtime.d.ts.map +1 -0
- package/dist/services/voice/kokoro/kokoro-runtime.d.ts.map +1 -0
- package/dist/services/voice/kokoro/phoneme-stream.d.ts +51 -0
- package/dist/services/voice/kokoro/phoneme-stream.d.ts.map +1 -0
- package/dist/services/voice/kokoro/phonemizer.d.ts.map +1 -0
- package/{src → dist}/services/voice/kokoro/pick-runtime.d.ts +1 -1
- package/dist/services/voice/kokoro/pick-runtime.d.ts.map +1 -0
- package/dist/services/voice/kokoro/runtime-selection.d.ts +31 -0
- package/dist/services/voice/kokoro/runtime-selection.d.ts.map +1 -0
- package/dist/services/voice/kokoro/types.d.ts.map +1 -0
- package/dist/services/voice/kokoro/voice-presets.d.ts.map +1 -0
- package/dist/services/voice/kokoro/voices.d.ts.map +1 -0
- package/dist/services/voice/lifecycle.d.ts.map +1 -0
- package/dist/services/voice/live-diarization-session.d.ts +196 -0
- package/dist/services/voice/live-diarization-session.d.ts.map +1 -0
- package/dist/services/voice/metric-math.d.ts +10 -0
- package/dist/services/voice/metric-math.d.ts.map +1 -0
- package/{src → dist}/services/voice/mic-source.d.ts +1 -1
- package/dist/services/voice/mic-source.d.ts.map +1 -0
- package/dist/services/voice/nlms-echo-canceller.d.ts +137 -0
- package/dist/services/voice/nlms-echo-canceller.d.ts.map +1 -0
- package/dist/services/voice/optimistic-policy.d.ts.map +1 -0
- package/dist/services/voice/optimistic-rollback.d.ts +151 -0
- package/dist/services/voice/optimistic-rollback.d.ts.map +1 -0
- package/{src → dist}/services/voice/partial-stabilizer.d.ts +1 -1
- package/dist/services/voice/partial-stabilizer.d.ts.map +1 -0
- package/dist/services/voice/phoneme-tokenizer.d.ts.map +1 -0
- package/dist/services/voice/phrase-cache.d.ts.map +1 -0
- package/dist/services/voice/phrase-chunker.d.ts.map +1 -0
- package/dist/services/voice/pipeline-impls.d.ts.map +1 -0
- package/dist/services/voice/pipeline.d.ts.map +1 -0
- package/dist/services/voice/prefill-client.d.ts.map +1 -0
- package/dist/services/voice/prefix-preserving-queue.d.ts.map +1 -0
- package/dist/services/voice/profile-store.d.ts.map +1 -0
- package/dist/services/voice/ring-buffer.d.ts.map +1 -0
- package/dist/services/voice/rollback-queue.d.ts.map +1 -0
- package/dist/services/voice/samantha-preset-placeholder.d.ts.map +1 -0
- package/dist/services/voice/samantha-preset-regenerator.d.ts.map +1 -0
- package/dist/services/voice/scheduler.d.ts.map +1 -0
- package/dist/services/voice/self-voice-imprint.d.ts +33 -0
- package/dist/services/voice/self-voice-imprint.d.ts.map +1 -0
- package/{src → dist}/services/voice/shared-resources.d.ts +14 -0
- package/dist/services/voice/shared-resources.d.ts.map +1 -0
- package/dist/services/voice/speaker/attribution-pipeline.d.ts.map +1 -0
- package/dist/services/voice/speaker/diarizer-fused.d.ts.map +1 -0
- package/dist/services/voice/speaker/diarizer.d.ts.map +1 -0
- package/dist/services/voice/speaker/encoder-fused.d.ts.map +1 -0
- package/dist/services/voice/speaker/encoder-ggml.d.ts.map +1 -0
- package/dist/services/voice/speaker/encoder.d.ts.map +1 -0
- package/dist/services/voice/speaker-imprint.d.ts.map +1 -0
- package/dist/services/voice/speaker-preset-cache.d.ts.map +1 -0
- package/dist/services/voice/streaming-asr/streaming-pipeline-adapter.d.ts +160 -0
- package/dist/services/voice/streaming-asr/streaming-pipeline-adapter.d.ts.map +1 -0
- package/dist/services/voice/system-audio-sink.d.ts.map +1 -0
- package/{src → dist}/services/voice/transcriber.d.ts +4 -4
- package/dist/services/voice/transcriber.d.ts.map +1 -0
- package/dist/services/voice/transcript-knowledge.d.ts.map +1 -0
- package/{src → dist}/services/voice/transcript-service.d.ts +20 -1
- package/dist/services/voice/transcript-service.d.ts.map +1 -0
- package/{src → dist}/services/voice/transcript-store.d.ts +12 -1
- package/dist/services/voice/transcript-store.d.ts.map +1 -0
- package/dist/services/voice/turn-controller.d.ts.map +1 -0
- package/{src → dist}/services/voice/types.d.ts +6 -6
- package/dist/services/voice/types.d.ts.map +1 -0
- package/{src → dist}/services/voice/vad.d.ts +6 -5
- package/dist/services/voice/vad.d.ts.map +1 -0
- package/dist/services/voice/voice-budget.d.ts.map +1 -0
- package/dist/services/voice/voice-emotion-classifier.d.ts.map +1 -0
- package/dist/services/voice/voice-preload-predictor.d.ts +76 -0
- package/dist/services/voice/voice-preload-predictor.d.ts.map +1 -0
- package/{src → dist}/services/voice/voice-preset-format.d.ts +2 -2
- package/dist/services/voice/voice-preset-format.d.ts.map +1 -0
- package/dist/services/voice/voice-profile-artifact.d.ts.map +1 -0
- package/dist/services/voice/voice-profile-routes.d.ts.map +1 -0
- package/dist/services/voice/voice-scenario.d.ts +131 -0
- package/dist/services/voice/voice-scenario.d.ts.map +1 -0
- package/dist/services/voice/voice-state-machine.d.ts.map +1 -0
- package/dist/services/voice/voice-workbench-report.d.ts +117 -0
- package/dist/services/voice/voice-workbench-report.d.ts.map +1 -0
- package/{src → dist}/services/voice/wake-word-ggml.d.ts +8 -9
- package/dist/services/voice/wake-word-ggml.d.ts.map +1 -0
- package/dist/services/voice/wake-word.d.ts.map +1 -0
- package/dist/services/voice/wav-codec.d.ts +11 -0
- package/dist/services/voice/wav-codec.d.ts.map +1 -0
- package/dist/services/voice/workbench-entrypoint.d.ts +42 -0
- package/dist/services/voice/workbench-entrypoint.d.ts.map +1 -0
- package/dist/services/voice/workbench-headless-runner.d.ts +102 -0
- package/dist/services/voice/workbench-headless-runner.d.ts.map +1 -0
- package/dist/services/voice/workbench-logic-services.d.ts +36 -0
- package/dist/services/voice/workbench-logic-services.d.ts.map +1 -0
- package/dist/services/voice/workbench-real-services.d.ts +17 -0
- package/dist/services/voice/workbench-real-services.d.ts.map +1 -0
- package/dist/services/voice/workbench-scenarios.d.ts +24 -0
- package/dist/services/voice/workbench-scenarios.d.ts.map +1 -0
- package/dist/services/voice/wrap-with-first-line-cache.d.ts.map +1 -0
- package/dist/services/voice-model-updater.d.ts.map +1 -0
- package/dist/services/voice-prewarm.d.ts.map +1 -0
- package/dist/voice-workbench.d.ts +18 -0
- package/dist/voice-workbench.d.ts.map +1 -0
- package/dist/voice-workbench.js +5259 -0
- package/dist/voice-workbench.js.map +34 -0
- package/package.json +28 -9
- package/registry-entry.json +137 -0
- package/src/adapters/capacitor-llama/__tests__/voice-turn.test.ts +293 -0
- package/src/adapters/capacitor-llama/environment.ts +1 -1
- package/src/adapters/capacitor-llama/index.ts +28 -4
- package/src/adapters/capacitor-llama/native-voice-capture.ts +140 -0
- package/src/adapters/capacitor-llama/text-streaming.ts +2 -2
- package/src/adapters/capacitor-llama/voice-turn.ts +178 -0
- package/src/backends/apple-foundation.ts +1 -1
- package/src/local-inference-routes.test.ts +57 -11
- package/src/local-inference-routes.ts +90 -8
- package/src/provider.ts +32 -3
- package/src/routes/compat-helpers.ts +2 -1
- package/src/routes/index.ts +1 -0
- package/src/routes/live-diarization-route.test.ts +134 -0
- package/src/routes/live-diarization-route.ts +79 -3
- package/src/routes/local-inference-asr-route.test.ts +43 -2
- package/src/routes/local-inference-asr-route.ts +7 -4
- package/src/routes/local-inference-asr-transcribe.test.ts +4 -4
- package/src/routes/local-inference-asr-transcribe.ts +1 -1
- package/src/routes/local-inference-compat-routes.test.ts +3 -3
- package/src/routes/local-inference-compat-routes.ts +23 -56
- package/src/routes/native-pcm-turn-route.test.ts +136 -0
- package/src/routes/native-pcm-turn-route.ts +121 -0
- package/src/routes/transcripts-routes.test.ts +51 -0
- package/src/routes/transcripts-routes.ts +35 -3
- package/src/runtime/bionic-wire-encoding.test.ts +147 -0
- package/src/runtime/ensure-local-inference-handler.test.ts +203 -5
- package/src/runtime/ensure-local-inference-handler.ts +203 -11
- package/src/runtime/index.ts +4 -1
- package/src/runtime/mobile-local-inference-gate.test.ts +85 -2
- package/src/runtime/mobile-local-inference-gate.ts +60 -5
- package/src/runtime/voice-entity-binding.transcript.test.ts +29 -0
- package/src/runtime/voice-entity-binding.ts +46 -6
- package/src/runtime/voice-speaker-entity-contract.test.ts +149 -0
- package/src/services/README.md +2 -2
- package/src/services/__tests__/backend-selector.precedence.test.ts +333 -0
- package/src/services/active-model-context-fit.test.ts +125 -0
- package/src/services/active-model.ts +211 -8
- package/src/services/asr-provenance.ts +68 -0
- package/src/services/assignment-validation.test.ts +118 -0
- package/src/services/assignments.test.ts +26 -0
- package/src/services/assignments.ts +52 -4
- package/src/services/backend.test.ts +84 -0
- package/src/services/backend.ts +198 -19
- package/src/services/bionic-host-loader.test.ts +94 -1
- package/src/services/bionic-host-loader.ts +72 -0
- package/src/services/cache-bridge.test.ts +7 -7
- package/src/services/catalog.test.ts +32 -11
- package/src/services/catalog.ts +6 -0
- package/src/services/cloud-fallback.ts +1 -1
- package/src/services/context-fit.test.ts +121 -0
- package/src/services/context-fit.ts +113 -0
- package/src/services/desktop-fused-ffi-backend-runtime.ts +99 -7
- package/src/services/device-tier.test.ts +89 -2
- package/src/services/device-tier.ts +103 -11
- package/src/services/downloader.test.ts +199 -58
- package/src/services/downloader.ts +141 -27
- package/src/services/engine-direct-bundle.test.ts +38 -6
- package/src/services/engine.ts +291 -104
- package/src/services/ensure-local-artifacts.ts +1 -1
- package/src/services/ffi-llm-streaming-abi.ts +6 -3
- package/src/services/ffi-streaming-backend.ts +44 -8
- package/src/services/ffi-streaming-runner.test.ts +163 -3
- package/src/services/ffi-streaming-runner.ts +54 -1
- package/src/services/ffi-unload-ordering.test.ts +5 -1
- package/src/services/fused-eliza1-no-regression.test.ts +144 -0
- package/src/services/hardware.test.ts +7 -2
- package/src/services/hardware.ts +28 -0
- package/src/services/imagegen/backend-selector.test.ts +190 -0
- package/src/services/imagegen/sd-cpp.ts +6 -9
- package/src/services/index.ts +18 -0
- package/src/services/ios-llama-streaming.ts +1 -1
- package/src/services/kv-spill.ts +6 -5
- package/src/services/lib-target.test.ts +145 -0
- package/src/services/lib-target.ts +102 -0
- package/src/services/live-signals.test.ts +132 -0
- package/src/services/live-signals.ts +177 -0
- package/src/services/llama-server-metrics.test.ts +168 -0
- package/src/services/manifest/eliza-1.manifest.v1.json +84 -2
- package/src/services/manifest/index.ts +6 -0
- package/src/services/manifest/manifest.test.ts +156 -54
- package/src/services/manifest/schema.ts +160 -52
- package/src/services/manifest/types.ts +6 -0
- package/src/services/manifest/validator.ts +91 -25
- package/src/services/memory-arbiter.test.ts +139 -0
- package/src/services/memory-arbiter.ts +81 -15
- package/src/services/memory-benchmark.test.ts +91 -0
- package/src/services/memory-benchmark.ts +354 -0
- package/src/services/memory-monitor.test.ts +24 -0
- package/src/services/memory-monitor.ts +12 -0
- package/src/services/mtp-doctor.ts +10 -2
- package/src/services/network-policy.ts +5 -5
- package/src/services/ram-budget-cache.test.ts +2 -1
- package/src/services/ram-budget.ts +0 -0
- package/src/services/recommendation.test.ts +216 -0
- package/src/services/registry.ts +25 -19
- package/src/services/required-kernels-gate.test.ts +64 -0
- package/src/services/router-handler.ts +43 -24
- package/src/services/routing-policy.test.ts +211 -23
- package/src/services/routing-policy.ts +92 -22
- package/src/services/service.test.ts +3 -3
- package/src/services/service.ts +22 -7
- package/src/services/transcription-priority.test.ts +2 -2
- package/src/services/types.ts +4 -0
- package/src/services/verify-on-device.test.ts +2 -2
- package/src/services/vision/hash.ts +1 -1
- package/src/services/vision/index.ts +2 -2
- package/src/services/vision/llama-server.ts +1 -1
- package/src/services/vision/types.ts +13 -4
- package/src/services/vision-embedding-cache.ts +1 -1
- package/src/services/voice/VOICE_WORKBENCH.md +71 -26
- package/src/services/voice/__fixtures__/voice-workbench-logic-baseline.json +180 -0
- package/src/services/voice/__test-helpers__/synthetic-speech.ts +72 -2
- package/src/services/voice/__tests__/eliza1-eot-scorer.test.ts +29 -29
- package/src/services/voice/__tests__/streaming-asr.test.ts +1 -1
- package/src/services/voice/acoustic-speaker-attribution.test.ts +165 -0
- package/src/services/voice/acoustic-speaker-attribution.ts +336 -0
- package/src/services/voice/asr-timed.real.test.ts +6 -8
- package/src/services/voice/audio-frame-consumer.test.ts +327 -1
- package/src/services/voice/audio-frame-consumer.ts +165 -5
- package/src/services/voice/barge-in.ts +2 -3
- package/src/services/voice/corpus-augment.test.ts +276 -0
- package/src/services/voice/corpus-augment.ts +451 -0
- package/src/services/voice/corpus-generator.test.ts +201 -0
- package/src/services/voice/corpus-generator.ts +413 -0
- package/src/services/voice/diarization-error-rate.greedy.test.ts +140 -0
- package/src/services/voice/diarization-error-rate.test.ts +100 -0
- package/src/services/voice/diarization-error-rate.ts +249 -0
- package/src/services/voice/e2e-harness.der.test.ts +94 -0
- package/src/services/voice/e2e-harness.respond-eot-entity.test.ts +277 -0
- package/src/services/voice/e2e-harness.security-echo.test.ts +103 -0
- package/src/services/voice/e2e-harness.test.ts +2 -2
- package/src/services/voice/e2e-harness.ts +175 -16
- package/src/services/voice/echo-delay.test.ts +118 -0
- package/src/services/voice/echo-delay.ts +135 -0
- package/src/services/voice/echo-metrics.test.ts +17 -0
- package/src/services/voice/echo-metrics.ts +20 -0
- package/src/services/voice/echo-reference-buffer.test.ts +86 -0
- package/src/services/voice/echo-reference-buffer.ts +165 -0
- package/src/services/voice/eliza1-eot-scorer.ts +22 -22
- package/src/services/voice/embedding.ts +2 -3
- package/src/services/voice/engine-bridge-transcript-join.test.ts +278 -0
- package/src/services/voice/engine-bridge.ts +151 -110
- package/src/services/voice/eot-classifier-ggml.ts +42 -39
- package/src/services/voice/eot-classifier.test.ts +98 -0
- package/src/services/voice/eot-classifier.ts +11 -122
- package/src/services/voice/errors.ts +2 -0
- package/src/services/voice/expressive-tags.asr.test.ts +77 -0
- package/src/services/voice/expressive-tags.test.ts +102 -0
- package/src/services/voice/expressive-tags.ts +8 -8
- package/src/services/voice/ffi-bindings.test.ts +10 -3
- package/src/services/voice/ffi-bindings.ts +177 -15
- package/src/services/voice/fused-eot-scorer.ts +17 -13
- package/src/services/voice/index.ts +33 -12
- package/src/services/voice/kokoro/__tests__/kokoro-backend.test.ts +112 -1
- package/src/services/voice/kokoro/__tests__/kokoro-engine-bridge.real.test.ts +88 -3
- package/src/services/voice/kokoro/__tests__/runtime-selection.test.ts +37 -201
- package/src/services/voice/kokoro/kokoro-backend.ts +16 -0
- package/src/services/voice/kokoro/kokoro-engine-discovery.ts +1 -1
- package/src/services/voice/kokoro/kokoro-ffi-runtime.ts +3 -3
- package/src/services/voice/kokoro/pick-runtime.ts +1 -1
- package/src/services/voice/kokoro/runtime-selection.ts +28 -201
- package/src/services/voice/live-diarization-session.echo.test.ts +232 -0
- package/src/services/voice/live-diarization-session.ts +335 -2
- package/src/services/voice/metric-math.test.ts +61 -0
- package/src/services/voice/metric-math.ts +25 -0
- package/src/services/voice/mic-source.ts +1 -1
- package/src/services/voice/nlms-echo-canceller.test.ts +244 -0
- package/src/services/voice/nlms-echo-canceller.ts +317 -0
- package/src/services/voice/optimistic-policy.power-source.test.ts +36 -0
- package/src/services/voice/partial-stabilizer.ts +1 -1
- package/src/services/voice/pipeline.ts +3 -4
- package/src/services/voice/research/VOICE_8785_ASSESSMENT.md +141 -0
- package/src/services/voice/research/VOICE_PIPELINE_RESEARCH_2026.md +117 -0
- package/src/services/voice/research/VOICE_VALIDATION_RUNBOOK.md +135 -0
- package/src/services/voice/samantha-preset-regenerator.wav.test.ts +90 -0
- package/src/services/voice/self-voice-imprint.test.ts +59 -0
- package/src/services/voice/self-voice-imprint.ts +102 -0
- package/src/services/voice/shared-resources.ts +23 -0
- package/src/services/voice/speaker/attribution-pipeline.test.ts +221 -0
- package/src/services/voice/speaker/attribution-pipeline.ts +85 -22
- package/src/services/voice/speaker/encoder-ggml.test.ts +59 -0
- package/src/services/voice/transcriber.asr-backend.test.ts +76 -0
- package/src/services/voice/transcriber.ts +4 -4
- package/src/services/voice/transcript-service.test.ts +58 -0
- package/src/services/voice/transcript-service.ts +64 -0
- package/src/services/voice/transcript-store.test.ts +36 -0
- package/src/services/voice/transcript-store.ts +32 -0
- package/src/services/voice/types.ts +7 -7
- package/src/services/voice/vad.test.ts +33 -15
- package/src/services/voice/vad.ts +25 -20
- package/src/services/voice/voice-budget.test.ts +0 -3
- package/src/services/voice/voice-budget.ts +6 -6
- package/src/services/voice/voice-duet.test.ts +1 -1
- package/src/services/voice/voice-hardening.fuzz.test.ts +116 -0
- package/src/services/voice/voice-preload-predictor.test.ts +130 -0
- package/src/services/voice/voice-preload-predictor.ts +113 -0
- package/src/services/voice/voice-preset-format.fuzz.test.ts +89 -0
- package/src/services/voice/voice-preset-format.test.ts +75 -0
- package/src/services/voice/voice-preset-format.ts +17 -4
- package/src/services/voice/voice-scenario.test.ts +159 -0
- package/src/services/voice/voice-scenario.ts +133 -7
- package/src/services/voice/voice-scenario.turn-helpers.test.ts +77 -0
- package/src/services/voice/voice-workbench-report.ts +58 -17
- package/src/services/voice/wake-word-ggml.ts +12 -13
- package/src/services/voice/wav-codec.fuzz.test.ts +59 -0
- package/src/services/voice/wav-codec.test.ts +32 -0
- package/src/services/voice/wav-codec.ts +101 -0
- package/src/services/voice/workbench-entrypoint.test.ts +55 -0
- package/src/services/voice/workbench-entrypoint.ts +88 -0
- package/src/services/voice/workbench-headless-runner.test.ts +162 -0
- package/src/services/voice/workbench-headless-runner.ts +396 -0
- package/src/services/voice/workbench-logic-services.test.ts +225 -0
- package/src/services/voice/workbench-logic-services.ts +184 -0
- package/src/services/voice/workbench-real-services.ts +629 -0
- package/src/services/voice/workbench-scenarios.ts +407 -0
- package/src/services/voice-prewarm.ts +1 -1
- package/src/voice-workbench.ts +71 -0
- package/src/actions/generate-media.d.ts.map +0 -1
- package/src/actions/identify-speaker.d.ts.map +0 -1
- package/src/actions/transcription-control.d.ts.map +0 -1
- package/src/index.d.ts.map +0 -1
- package/src/local-inference-routes.d.ts.map +0 -1
- package/src/provider.d.ts.map +0 -1
- package/src/routes/compat-helpers.d.ts.map +0 -1
- package/src/routes/family-member-route.d.ts.map +0 -1
- package/src/routes/index.d.ts.map +0 -1
- package/src/routes/live-diarization-route.d.ts.map +0 -1
- package/src/routes/local-inference-asr-route.d.ts.map +0 -1
- package/src/routes/local-inference-asr-transcribe.d.ts.map +0 -1
- package/src/routes/local-inference-compat-routes.d.ts.map +0 -1
- package/src/routes/local-inference-tts-route.d.ts.map +0 -1
- package/src/routes/transcript-audio-store.d.ts.map +0 -1
- package/src/routes/transcripts-routes.d.ts.map +0 -1
- package/src/routes/voice-first-run-routes.d.ts.map +0 -1
- package/src/routes/voice-models-routes.d.ts.map +0 -1
- package/src/routes/voice-profile-plugin-routes.d.ts.map +0 -1
- package/src/routes/voice-profiles-management-routes.d.ts.map +0 -1
- package/src/routes/voice-speaker-profile-routes.d.ts.map +0 -1
- package/src/runtime/embedding-manager-support.d.ts.map +0 -1
- package/src/runtime/embedding-presets.d.ts.map +0 -1
- package/src/runtime/embedding-warmup-policy.d.ts.map +0 -1
- package/src/runtime/ensure-local-inference-handler.d.ts.map +0 -1
- package/src/runtime/index.d.ts.map +0 -1
- package/src/runtime/mobile-local-inference-gate.d.ts +0 -31
- package/src/runtime/mobile-local-inference-gate.d.ts.map +0 -1
- package/src/runtime/voice-entity-binding.d.ts.map +0 -1
- package/src/services/active-model.d.ts.map +0 -1
- package/src/services/assignments.d.ts.map +0 -1
- package/src/services/backend.d.ts.map +0 -1
- package/src/services/bionic-host-loader.d.ts.map +0 -1
- package/src/services/bundled-models.d.ts.map +0 -1
- package/src/services/cache-bridge.d.ts.map +0 -1
- package/src/services/catalog.d.ts +0 -10
- package/src/services/catalog.d.ts.map +0 -1
- package/src/services/checkpoint-client.d.ts.map +0 -1
- package/src/services/cloud-fallback.d.ts.map +0 -1
- package/src/services/conversation-registry.d.ts.map +0 -1
- package/src/services/desktop-fused-ffi-backend-runtime.d.ts.map +0 -1
- package/src/services/device-bridge.d.ts.map +0 -1
- package/src/services/device-resource-metrics.d.ts.map +0 -1
- package/src/services/device-tier.d.ts.map +0 -1
- package/src/services/downloader.d.ts.map +0 -1
- package/src/services/engine.d.ts.map +0 -1
- package/src/services/external-scanner.d.ts.map +0 -1
- package/src/services/ffi-streaming-backend.d.ts.map +0 -1
- package/src/services/ffi-streaming-runner.d.ts.map +0 -1
- package/src/services/gpu-detect.d.ts.map +0 -1
- package/src/services/handler-registry.d.ts.map +0 -1
- package/src/services/hardware.d.ts.map +0 -1
- package/src/services/hf-search.d.ts +0 -26
- package/src/services/hf-search.d.ts.map +0 -1
- package/src/services/hf-search.test.ts +0 -69
- package/src/services/hf-search.ts +0 -420
- package/src/services/image-description-runtime.d.ts.map +0 -1
- package/src/services/imagegen/aosp-unavailable.d.ts.map +0 -1
- package/src/services/imagegen/backend-selector.d.ts.map +0 -1
- package/src/services/imagegen/coreml-unavailable.d.ts.map +0 -1
- package/src/services/imagegen/errors.d.ts.map +0 -1
- package/src/services/imagegen/index.d.ts.map +0 -1
- package/src/services/imagegen/mflux.d.ts.map +0 -1
- package/src/services/imagegen/sd-cpp.d.ts.map +0 -1
- package/src/services/imagegen/tensorrt-unavailable.d.ts.map +0 -1
- package/src/services/imagegen/types.d.ts.map +0 -1
- package/src/services/index.d.ts.map +0 -1
- package/src/services/inference-capabilities.d.ts.map +0 -1
- package/src/services/inference-telemetry.d.ts.map +0 -1
- package/src/services/kv-spill.d.ts.map +0 -1
- package/src/services/latency-trace.d.ts.map +0 -1
- package/src/services/llm-streaming-binding.d.ts.map +0 -1
- package/src/services/load-args.d.ts.map +0 -1
- package/src/services/manifest/index.d.ts +0 -4
- package/src/services/manifest/index.d.ts.map +0 -1
- package/src/services/manifest/schema.d.ts.map +0 -1
- package/src/services/manifest/types.d.ts.map +0 -1
- package/src/services/manifest/validator.d.ts.map +0 -1
- package/src/services/memory-arbiter.d.ts.map +0 -1
- package/src/services/memory-monitor.d.ts.map +0 -1
- package/src/services/memory-pressure.d.ts.map +0 -1
- package/src/services/mtp-doctor.d.ts.map +0 -1
- package/src/services/network-policy.d.ts.map +0 -1
- package/src/services/paths.d.ts.map +0 -1
- package/src/services/planner-skeleton.d.ts.map +0 -1
- package/src/services/providers.d.ts.map +0 -1
- package/src/services/ram-budget.d.ts.map +0 -1
- package/src/services/readiness.d.ts.map +0 -1
- package/src/services/recommendation.d.ts.map +0 -1
- package/src/services/registry.d.ts.map +0 -1
- package/src/services/router-handler.d.ts.map +0 -1
- package/src/services/routing-policy.d.ts.map +0 -1
- package/src/services/routing-preferences.d.ts.map +0 -1
- package/src/services/runtime-target.d.ts.map +0 -1
- package/src/services/service.d.ts.map +0 -1
- package/src/services/session-pool.d.ts.map +0 -1
- package/src/services/structured-output/deterministic-repair.d.ts.map +0 -1
- package/src/services/structured-output.d.ts.map +0 -1
- package/src/services/system-memory.d.ts.map +0 -1
- package/src/services/types.d.ts.map +0 -1
- package/src/services/verify-on-device.d.ts.map +0 -1
- package/src/services/verify.d.ts.map +0 -1
- package/src/services/vision/aosp-unavailable.d.ts.map +0 -1
- package/src/services/vision/capacitor-llama.d.ts.map +0 -1
- package/src/services/vision/cloud-fallback.d.ts.map +0 -1
- package/src/services/vision/hash.d.ts.map +0 -1
- package/src/services/vision/index.d.ts.map +0 -1
- package/src/services/vision/llama-server.d.ts.map +0 -1
- package/src/services/vision/types.d.ts.map +0 -1
- package/src/services/vision/vast-fallback.d.ts.map +0 -1
- package/src/services/vision-embedding-cache.d.ts.map +0 -1
- package/src/services/voice/audio-frame-consumer.d.ts.map +0 -1
- package/src/services/voice/barge-in.d.ts.map +0 -1
- package/src/services/voice/cancellation-coordinator.d.ts.map +0 -1
- package/src/services/voice/checkpoint-manager.d.ts.map +0 -1
- package/src/services/voice/eager-context-builder.d.ts.map +0 -1
- package/src/services/voice/eliza1-eot-scorer.d.ts.map +0 -1
- package/src/services/voice/embedding.d.ts.map +0 -1
- package/src/services/voice/emotion-attribution.d.ts.map +0 -1
- package/src/services/voice/engine-bridge.d.ts.map +0 -1
- package/src/services/voice/eot-classifier-ggml.d.ts.map +0 -1
- package/src/services/voice/eot-classifier.d.ts.map +0 -1
- package/src/services/voice/errors.d.ts.map +0 -1
- package/src/services/voice/expressive-tags.d.ts.map +0 -1
- package/src/services/voice/ffi-bindings.d.ts.map +0 -1
- package/src/services/voice/first-line-cache.d.ts.map +0 -1
- package/src/services/voice/fused-eot-scorer.d.ts.map +0 -1
- package/src/services/voice/index.d.ts.map +0 -1
- package/src/services/voice/kokoro/kokoro-backend.d.ts.map +0 -1
- package/src/services/voice/kokoro/kokoro-engine-discovery.d.ts.map +0 -1
- package/src/services/voice/kokoro/kokoro-ffi-runtime.d.ts.map +0 -1
- package/src/services/voice/kokoro/kokoro-runtime.d.ts.map +0 -1
- package/src/services/voice/kokoro/phonemizer.d.ts.map +0 -1
- package/src/services/voice/kokoro/pick-runtime.d.ts.map +0 -1
- package/src/services/voice/kokoro/runtime-selection.d.ts +0 -92
- package/src/services/voice/kokoro/runtime-selection.d.ts.map +0 -1
- package/src/services/voice/kokoro/types.d.ts.map +0 -1
- package/src/services/voice/kokoro/voice-presets.d.ts.map +0 -1
- package/src/services/voice/kokoro/voices.d.ts.map +0 -1
- package/src/services/voice/lifecycle.d.ts.map +0 -1
- package/src/services/voice/live-diarization-session.d.ts +0 -96
- package/src/services/voice/live-diarization-session.d.ts.map +0 -1
- package/src/services/voice/mic-source.d.ts.map +0 -1
- package/src/services/voice/optimistic-policy.d.ts.map +0 -1
- package/src/services/voice/partial-stabilizer.d.ts.map +0 -1
- package/src/services/voice/phoneme-tokenizer.d.ts.map +0 -1
- package/src/services/voice/phrase-cache.d.ts.map +0 -1
- package/src/services/voice/phrase-chunker.d.ts.map +0 -1
- package/src/services/voice/pipeline-impls.d.ts.map +0 -1
- package/src/services/voice/pipeline.d.ts.map +0 -1
- package/src/services/voice/prefill-client.d.ts.map +0 -1
- package/src/services/voice/prefix-preserving-queue.d.ts.map +0 -1
- package/src/services/voice/profile-store.d.ts.map +0 -1
- package/src/services/voice/ring-buffer.d.ts.map +0 -1
- package/src/services/voice/rollback-queue.d.ts.map +0 -1
- package/src/services/voice/samantha-preset-placeholder.d.ts.map +0 -1
- package/src/services/voice/samantha-preset-regenerator.d.ts.map +0 -1
- package/src/services/voice/scheduler.d.ts.map +0 -1
- package/src/services/voice/shared-resources.d.ts.map +0 -1
- package/src/services/voice/speaker/attribution-pipeline.d.ts.map +0 -1
- package/src/services/voice/speaker/diarizer-fused.d.ts.map +0 -1
- package/src/services/voice/speaker/diarizer.d.ts.map +0 -1
- package/src/services/voice/speaker/encoder-fused.d.ts.map +0 -1
- package/src/services/voice/speaker/encoder-ggml.d.ts.map +0 -1
- package/src/services/voice/speaker/encoder.d.ts.map +0 -1
- package/src/services/voice/speaker-imprint.d.ts.map +0 -1
- package/src/services/voice/speaker-preset-cache.d.ts.map +0 -1
- package/src/services/voice/system-audio-sink.d.ts.map +0 -1
- package/src/services/voice/transcriber.d.ts.map +0 -1
- package/src/services/voice/transcript-knowledge.d.ts.map +0 -1
- package/src/services/voice/transcript-service.d.ts.map +0 -1
- package/src/services/voice/transcript-store.d.ts.map +0 -1
- package/src/services/voice/turn-controller.d.ts.map +0 -1
- package/src/services/voice/types.d.ts.map +0 -1
- package/src/services/voice/vad.d.ts.map +0 -1
- package/src/services/voice/voice-budget.d.ts.map +0 -1
- package/src/services/voice/voice-emotion-classifier.d.ts.map +0 -1
- package/src/services/voice/voice-preset-format.d.ts.map +0 -1
- package/src/services/voice/voice-profile-artifact.d.ts.map +0 -1
- package/src/services/voice/voice-profile-routes.d.ts.map +0 -1
- package/src/services/voice/voice-settings.d.ts +0 -82
- package/src/services/voice/voice-settings.d.ts.map +0 -1
- package/src/services/voice/voice-settings.ts +0 -172
- package/src/services/voice/voice-state-machine.d.ts.map +0 -1
- package/src/services/voice/wake-word-ggml.d.ts.map +0 -1
- package/src/services/voice/wake-word.d.ts.map +0 -1
- package/src/services/voice/wrap-with-first-line-cache.d.ts.map +0 -1
- package/src/services/voice-model-updater.d.ts.map +0 -1
- package/src/services/voice-prewarm.d.ts.map +0 -1
- /package/{src → dist}/actions/generate-media.d.ts +0 -0
- /package/{src → dist}/actions/identify-speaker.d.ts +0 -0
- /package/{src → dist}/actions/transcription-control.d.ts +0 -0
- /package/{src → dist}/index.d.ts +0 -0
- /package/{src → dist}/provider.d.ts +0 -0
- /package/{src → dist}/routes/family-member-route.d.ts +0 -0
- /package/{src → dist}/routes/local-inference-asr-route.d.ts +0 -0
- /package/{src → dist}/routes/local-inference-asr-transcribe.d.ts +0 -0
- /package/{src → dist}/routes/local-inference-compat-routes.d.ts +0 -0
- /package/{src → dist}/routes/local-inference-tts-route.d.ts +0 -0
- /package/{src → dist}/routes/transcript-audio-store.d.ts +0 -0
- /package/{src → dist}/routes/voice-first-run-routes.d.ts +0 -0
- /package/{src → dist}/routes/voice-models-routes.d.ts +0 -0
- /package/{src → dist}/routes/voice-profile-plugin-routes.d.ts +0 -0
- /package/{src → dist}/routes/voice-profiles-management-routes.d.ts +0 -0
- /package/{src → dist}/routes/voice-speaker-profile-routes.d.ts +0 -0
- /package/{src → dist}/runtime/embedding-manager-support.d.ts +0 -0
- /package/{src → dist}/runtime/embedding-presets.d.ts +0 -0
- /package/{src → dist}/runtime/embedding-warmup-policy.d.ts +0 -0
- /package/{src → dist}/services/bundled-models.d.ts +0 -0
- /package/{src → dist}/services/cache-bridge.d.ts +0 -0
- /package/{src → dist}/services/checkpoint-client.d.ts +0 -0
- /package/{src → dist}/services/cloud-fallback.d.ts +0 -0
- /package/{src → dist}/services/conversation-registry.d.ts +0 -0
- /package/{src → dist}/services/device-bridge.d.ts +0 -0
- /package/{src → dist}/services/device-resource-metrics.d.ts +0 -0
- /package/{src → dist}/services/external-scanner.d.ts +0 -0
- /package/{src → dist}/services/gpu-detect.d.ts +0 -0
- /package/{src → dist}/services/handler-registry.d.ts +0 -0
- /package/{src → dist}/services/hardware.d.ts +0 -0
- /package/{src → dist}/services/image-description-runtime.d.ts +0 -0
- /package/{src → dist}/services/imagegen/aosp-unavailable.d.ts +0 -0
- /package/{src → dist}/services/imagegen/backend-selector.d.ts +0 -0
- /package/{src → dist}/services/imagegen/coreml-unavailable.d.ts +0 -0
- /package/{src → dist}/services/imagegen/errors.d.ts +0 -0
- /package/{src → dist}/services/imagegen/index.d.ts +0 -0
- /package/{src → dist}/services/imagegen/mflux.d.ts +0 -0
- /package/{src → dist}/services/imagegen/tensorrt-unavailable.d.ts +0 -0
- /package/{src → dist}/services/imagegen/types.d.ts +0 -0
- /package/{src → dist}/services/inference-capabilities.d.ts +0 -0
- /package/{src → dist}/services/inference-telemetry.d.ts +0 -0
- /package/{src → dist}/services/kv-spill.d.ts +0 -0
- /package/{src → dist}/services/latency-trace.d.ts +0 -0
- /package/{src → dist}/services/llm-streaming-binding.d.ts +0 -0
- /package/{src → dist}/services/load-args.d.ts +0 -0
- /package/{src → dist}/services/manifest/validator.d.ts +0 -0
- /package/{src → dist}/services/memory-pressure.d.ts +0 -0
- /package/{src → dist}/services/mtp-doctor.d.ts +0 -0
- /package/{src → dist}/services/network-policy.d.ts +0 -0
- /package/{src → dist}/services/paths.d.ts +0 -0
- /package/{src → dist}/services/planner-skeleton.d.ts +0 -0
- /package/{src → dist}/services/providers.d.ts +0 -0
- /package/{src → dist}/services/ram-budget.d.ts +0 -0
- /package/{src → dist}/services/readiness.d.ts +0 -0
- /package/{src → dist}/services/recommendation.d.ts +0 -0
- /package/{src → dist}/services/routing-preferences.d.ts +0 -0
- /package/{src → dist}/services/runtime-target.d.ts +0 -0
- /package/{src → dist}/services/session-pool.d.ts +0 -0
- /package/{src → dist}/services/structured-output/deterministic-repair.d.ts +0 -0
- /package/{src → dist}/services/structured-output.d.ts +0 -0
- /package/{src → dist}/services/system-memory.d.ts +0 -0
- /package/{src → dist}/services/verify-on-device.d.ts +0 -0
- /package/{src → dist}/services/verify.d.ts +0 -0
- /package/{src → dist}/services/vision/aosp-unavailable.d.ts +0 -0
- /package/{src → dist}/services/vision/capacitor-llama.d.ts +0 -0
- /package/{src → dist}/services/vision/cloud-fallback.d.ts +0 -0
- /package/{src → dist}/services/vision/hash.d.ts +0 -0
- /package/{src → dist}/services/vision/llama-server.d.ts +0 -0
- /package/{src → dist}/services/vision/vast-fallback.d.ts +0 -0
- /package/{src → dist}/services/voice/barge-in.d.ts +0 -0
- /package/{src → dist}/services/voice/cancellation-coordinator.d.ts +0 -0
- /package/{src → dist}/services/voice/checkpoint-manager.d.ts +0 -0
- /package/{src → dist}/services/voice/eager-context-builder.d.ts +0 -0
- /package/{src → dist}/services/voice/emotion-attribution.d.ts +0 -0
- /package/{src → dist}/services/voice/first-line-cache.d.ts +0 -0
- /package/{src → dist}/services/voice/kokoro/kokoro-runtime.d.ts +0 -0
- /package/{src → dist}/services/voice/kokoro/phonemizer.d.ts +0 -0
- /package/{src → dist}/services/voice/kokoro/types.d.ts +0 -0
- /package/{src → dist}/services/voice/kokoro/voice-presets.d.ts +0 -0
- /package/{src → dist}/services/voice/kokoro/voices.d.ts +0 -0
- /package/{src → dist}/services/voice/lifecycle.d.ts +0 -0
- /package/{src → dist}/services/voice/optimistic-policy.d.ts +0 -0
- /package/{src → dist}/services/voice/phoneme-tokenizer.d.ts +0 -0
- /package/{src → dist}/services/voice/phrase-cache.d.ts +0 -0
- /package/{src → dist}/services/voice/phrase-chunker.d.ts +0 -0
- /package/{src → dist}/services/voice/pipeline-impls.d.ts +0 -0
- /package/{src → dist}/services/voice/pipeline.d.ts +0 -0
- /package/{src → dist}/services/voice/prefill-client.d.ts +0 -0
- /package/{src → dist}/services/voice/prefix-preserving-queue.d.ts +0 -0
- /package/{src → dist}/services/voice/profile-store.d.ts +0 -0
- /package/{src → dist}/services/voice/ring-buffer.d.ts +0 -0
- /package/{src → dist}/services/voice/rollback-queue.d.ts +0 -0
- /package/{src → dist}/services/voice/samantha-preset-placeholder.d.ts +0 -0
- /package/{src → dist}/services/voice/samantha-preset-regenerator.d.ts +0 -0
- /package/{src → dist}/services/voice/scheduler.d.ts +0 -0
- /package/{src → dist}/services/voice/speaker/attribution-pipeline.d.ts +0 -0
- /package/{src → dist}/services/voice/speaker/diarizer-fused.d.ts +0 -0
- /package/{src → dist}/services/voice/speaker/diarizer.d.ts +0 -0
- /package/{src → dist}/services/voice/speaker/encoder-fused.d.ts +0 -0
- /package/{src → dist}/services/voice/speaker/encoder-ggml.d.ts +0 -0
- /package/{src → dist}/services/voice/speaker/encoder.d.ts +0 -0
- /package/{src → dist}/services/voice/speaker-imprint.d.ts +0 -0
- /package/{src → dist}/services/voice/speaker-preset-cache.d.ts +0 -0
- /package/{src → dist}/services/voice/system-audio-sink.d.ts +0 -0
- /package/{src → dist}/services/voice/transcript-knowledge.d.ts +0 -0
- /package/{src → dist}/services/voice/turn-controller.d.ts +0 -0
- /package/{src → dist}/services/voice/voice-budget.d.ts +0 -0
- /package/{src → dist}/services/voice/voice-emotion-classifier.d.ts +0 -0
- /package/{src → dist}/services/voice/voice-profile-artifact.d.ts +0 -0
- /package/{src → dist}/services/voice/voice-profile-routes.d.ts +0 -0
- /package/{src → dist}/services/voice/voice-state-machine.d.ts +0 -0
- /package/{src → dist}/services/voice/wake-word.d.ts +0 -0
- /package/{src → dist}/services/voice/wrap-with-first-line-cache.d.ts +0 -0
- /package/{src → dist}/services/voice-model-updater.d.ts +0 -0
- /package/{src → dist}/services/voice-prewarm.d.ts +0 -0
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { NlmsEchoCanceller } from "./nlms-echo-canceller";
|
|
3
|
+
|
|
4
|
+
const SR = 16000;
|
|
5
|
+
const BLOCK = 320; // 20 ms @ 16 kHz — the pipeline's frame size
|
|
6
|
+
|
|
7
|
+
/** Speech-like signal: two-pole low-passed pseudo-random noise (deterministic). */
|
|
8
|
+
function signal(n: number, seed: number): Float32Array {
|
|
9
|
+
const x = new Float32Array(n);
|
|
10
|
+
let s = seed >>> 0;
|
|
11
|
+
let p1 = 0;
|
|
12
|
+
let p2 = 0;
|
|
13
|
+
for (let i = 0; i < n; i++) {
|
|
14
|
+
s = (s * 1103515245 + 12345) & 0x7fffffff;
|
|
15
|
+
const w = s / 0x3fffffff - 1;
|
|
16
|
+
p1 = 0.92 * p1 + 0.08 * w;
|
|
17
|
+
p2 = 0.85 * p2 + 0.15 * p1;
|
|
18
|
+
x[i] = p2 * 3;
|
|
19
|
+
}
|
|
20
|
+
return x;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Realistic (attenuated) playback→mic path: bulk delay + decaying reverb. */
|
|
24
|
+
function echoOf(x: Float32Array, gain = 0.22): Float32Array {
|
|
25
|
+
const delay = 35;
|
|
26
|
+
const tail = 90;
|
|
27
|
+
const h = new Float32Array(delay + tail);
|
|
28
|
+
for (let k = 0; k < tail; k++) {
|
|
29
|
+
h[delay + k] = Math.exp(-k / 25) * (k % 2 ? -0.6 : 0.8) * gain;
|
|
30
|
+
}
|
|
31
|
+
const y = new Float32Array(x.length);
|
|
32
|
+
for (let n = 0; n < x.length; n++) {
|
|
33
|
+
let acc = 0;
|
|
34
|
+
for (let k = 0; k < h.length; k++) if (n - k >= 0) acc += h[k] * x[n - k];
|
|
35
|
+
y[n] = acc;
|
|
36
|
+
}
|
|
37
|
+
return y;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function power(a: Float32Array, from = 0, to = a.length): number {
|
|
41
|
+
let p = 0;
|
|
42
|
+
for (let i = from; i < to; i++) p += a[i] * a[i];
|
|
43
|
+
return p / Math.max(1, to - from);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function runBlocks(
|
|
47
|
+
aec: NlmsEchoCanceller,
|
|
48
|
+
near: Float32Array,
|
|
49
|
+
far: Float32Array,
|
|
50
|
+
): Float32Array {
|
|
51
|
+
const out = new Float32Array(near.length);
|
|
52
|
+
for (let off = 0; off + BLOCK <= near.length; off += BLOCK) {
|
|
53
|
+
out.set(
|
|
54
|
+
aec.process(
|
|
55
|
+
near.subarray(off, off + BLOCK),
|
|
56
|
+
far.subarray(off, off + BLOCK),
|
|
57
|
+
),
|
|
58
|
+
off,
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
describe("NlmsEchoCanceller", () => {
|
|
65
|
+
it("cancels the agent's echo by >=10 dB ERLE after convergence (echo-only)", () => {
|
|
66
|
+
const N = SR * 4;
|
|
67
|
+
const far = signal(N, 1);
|
|
68
|
+
const echo = echoOf(far);
|
|
69
|
+
const out = runBlocks(
|
|
70
|
+
new NlmsEchoCanceller({ filterTaps: 256, mu: 0.5 }),
|
|
71
|
+
echo,
|
|
72
|
+
far,
|
|
73
|
+
);
|
|
74
|
+
const from = SR * 2; // ignore the first 2 s of adaptation
|
|
75
|
+
const to = N - (N % BLOCK);
|
|
76
|
+
const erleDb =
|
|
77
|
+
10 * Math.log10(power(echo, from, to) / power(out, from, to));
|
|
78
|
+
expect(erleDb).toBeGreaterThan(10);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("passes the mic through unchanged while the agent is silent", () => {
|
|
82
|
+
const aec = new NlmsEchoCanceller({ filterTaps: 256 });
|
|
83
|
+
const micOnly = signal(BLOCK, 777);
|
|
84
|
+
const out = aec.process(micOnly, new Float32Array(BLOCK)); // far-end = silence
|
|
85
|
+
let maxDiff = 0;
|
|
86
|
+
for (let i = 0; i < BLOCK; i++) {
|
|
87
|
+
maxDiff = Math.max(maxDiff, Math.abs(out[i] - micOnly[i]));
|
|
88
|
+
}
|
|
89
|
+
expect(maxDiff).toBeLessThan(1e-6);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("never touches the user's voice when only the user is speaking (no playback)", () => {
|
|
93
|
+
// Pure near-end speech, agent silent for the whole run → exact passthrough,
|
|
94
|
+
// so the canceller can never suppress a barge-in while no echo exists.
|
|
95
|
+
const N = SR * 2;
|
|
96
|
+
const speech = signal(N, 99);
|
|
97
|
+
const out = runBlocks(
|
|
98
|
+
new NlmsEchoCanceller({ filterTaps: 256 }),
|
|
99
|
+
speech,
|
|
100
|
+
new Float32Array(N),
|
|
101
|
+
);
|
|
102
|
+
let maxDiff = 0;
|
|
103
|
+
for (let i = 0; i < out.length; i++) {
|
|
104
|
+
maxDiff = Math.max(maxDiff, Math.abs(out[i] - speech[i]));
|
|
105
|
+
}
|
|
106
|
+
expect(maxDiff).toBeLessThan(1e-6);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("stays stable (does not diverge) under sustained double-talk", () => {
|
|
110
|
+
// Agent speaks the whole time; the user also speaks from 2 s. The filter
|
|
111
|
+
// must not blow up — the output power stays bounded near the input power.
|
|
112
|
+
const N = SR * 4;
|
|
113
|
+
const far = signal(N, 1);
|
|
114
|
+
const echo = echoOf(far);
|
|
115
|
+
const speech = signal(N, 99);
|
|
116
|
+
const near = new Float32Array(N);
|
|
117
|
+
for (let i = 0; i < N; i++)
|
|
118
|
+
near[i] = echo[i] + (i >= SR * 2 ? speech[i] : 0);
|
|
119
|
+
const out = runBlocks(
|
|
120
|
+
new NlmsEchoCanceller({ filterTaps: 256, mu: 0.5, dtdRatio: 1.5 }),
|
|
121
|
+
near,
|
|
122
|
+
far,
|
|
123
|
+
);
|
|
124
|
+
const from = SR * 2;
|
|
125
|
+
const to = N - (N % BLOCK);
|
|
126
|
+
// No divergence: output energy is the same order as the input, not exploding.
|
|
127
|
+
expect(power(out, from, to)).toBeLessThan(power(near, from, to) * 4);
|
|
128
|
+
for (let i = from; i < to; i++) expect(Number.isFinite(out[i])).toBe(true);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("does not diverge when the far-end has quiet passages (real-TTS pauses)", () => {
|
|
132
|
+
// Regression for the divergence found measuring real Kokoro/`say` TTS echo
|
|
133
|
+
// on-device (#9455): real TTS has inter-word/sentence pauses where the
|
|
134
|
+
// far-end energy collapses toward — but never reaches — zero (DAC dither,
|
|
135
|
+
// room floor). Meanwhile the mic always carries a small noise floor. Before
|
|
136
|
+
// the far-end-activity gate, ‖x‖²→ε during those pauses inflated the NLMS
|
|
137
|
+
// step so the filter learned the MIC NOISE and blew up (‖w‖→100s, residual
|
|
138
|
+
// RMS ≫ input). A purely-zero gap does NOT reproduce it (x[k]=0 → no update),
|
|
139
|
+
// which is why the synthetic echo test missed it — the floor is essential.
|
|
140
|
+
const N = SR * 6;
|
|
141
|
+
const speech = signal(N, 1);
|
|
142
|
+
const far = new Float32Array(N);
|
|
143
|
+
for (let i = 0; i < N; i++) {
|
|
144
|
+
const t = i / SR;
|
|
145
|
+
const active = t % 0.6 < 0.4 ? 1 : 0; // 0.4 s on / 0.2 s pause, TTS-like
|
|
146
|
+
// Quiet passage keeps a tiny non-zero floor (≈ −60 dBFS), as real audio does.
|
|
147
|
+
far[i] = active ? speech[i] : speech[i] * 3e-4;
|
|
148
|
+
}
|
|
149
|
+
const echo = echoOf(far);
|
|
150
|
+
const near = new Float32Array(N);
|
|
151
|
+
let s = 4242 >>> 0;
|
|
152
|
+
for (let i = 0; i < N; i++) {
|
|
153
|
+
s = (s * 1103515245 + 12345) & 0x7fffffff;
|
|
154
|
+
near[i] = echo[i] + (s / 0x3fffffff - 1) * 6e-3; // continuous mic noise floor
|
|
155
|
+
}
|
|
156
|
+
const out = runBlocks(new NlmsEchoCanceller(), near, far); // shipped defaults
|
|
157
|
+
const from = SR * 2;
|
|
158
|
+
const to = N - (N % BLOCK);
|
|
159
|
+
for (let i = from; i < to; i++) expect(Number.isFinite(out[i])).toBe(true);
|
|
160
|
+
// Stable: the cleaned signal stays at/below the mic level — it must never
|
|
161
|
+
// amplify the input (divergence injected ~200× energy before the fix).
|
|
162
|
+
expect(power(out, from, to)).toBeLessThan(power(near, from, to) * 1.5);
|
|
163
|
+
let peak = 0;
|
|
164
|
+
for (let i = from; i < to; i++) peak = Math.max(peak, Math.abs(out[i]));
|
|
165
|
+
expect(peak).toBeLessThan(1); // pre-fix peaks reached >20
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it("reset() clears adaptation (first post-reset sample is exact passthrough)", () => {
|
|
169
|
+
const far = signal(SR, 1);
|
|
170
|
+
const echo = echoOf(far);
|
|
171
|
+
const aec = new NlmsEchoCanceller({ filterTaps: 128 });
|
|
172
|
+
runBlocks(aec, echo, far);
|
|
173
|
+
aec.reset();
|
|
174
|
+
const out = aec.process(echo.subarray(0, BLOCK), far.subarray(0, BLOCK));
|
|
175
|
+
// weights + reference history are zero → ŷ[0]=0 → out[0]==in[0] exactly.
|
|
176
|
+
expect(out[0]).toBe(echo[0]);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
describe("opt-in residual suppressor (#9583/#9649)", () => {
|
|
180
|
+
it("further attenuates the residual on echo-only frames when enabled", () => {
|
|
181
|
+
const far = signal(SR, 7);
|
|
182
|
+
const near = echoOf(far); // user silent — echo only
|
|
183
|
+
const base = runBlocks(
|
|
184
|
+
new NlmsEchoCanceller({ filterTaps: 256, mu: 0.5 }),
|
|
185
|
+
near,
|
|
186
|
+
far,
|
|
187
|
+
);
|
|
188
|
+
const sup = runBlocks(
|
|
189
|
+
new NlmsEchoCanceller({
|
|
190
|
+
filterTaps: 256,
|
|
191
|
+
mu: 0.5,
|
|
192
|
+
residualSuppression: true,
|
|
193
|
+
}),
|
|
194
|
+
near,
|
|
195
|
+
far,
|
|
196
|
+
);
|
|
197
|
+
const half = near.length >> 1; // measure after convergence
|
|
198
|
+
// The suppressor only ever scales the residual down, so on echo-only
|
|
199
|
+
// frames its output power must be strictly below the linear filter's.
|
|
200
|
+
expect(power(sup, half)).toBeLessThan(power(base, half));
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it("preserves the user's voice during double-talk (only touches echo-only sub-frames)", () => {
|
|
204
|
+
const far = signal(SR, 3);
|
|
205
|
+
const user = signal(SR, 99); // continuous local talker
|
|
206
|
+
const echo = echoOf(far);
|
|
207
|
+
const near = new Float32Array(far.length);
|
|
208
|
+
for (let i = 0; i < near.length; i++) near[i] = user[i] + echo[i];
|
|
209
|
+
const cfg = { filterTaps: 256, mu: 0.5, dtdRatio: 1.5 } as const;
|
|
210
|
+
const base = runBlocks(new NlmsEchoCanceller(cfg), near, far);
|
|
211
|
+
const sup = runBlocks(
|
|
212
|
+
new NlmsEchoCanceller({ ...cfg, residualSuppression: { gain: 0.1 } }),
|
|
213
|
+
near,
|
|
214
|
+
far,
|
|
215
|
+
);
|
|
216
|
+
// With the user active, near-end power dominates far-end power, so the
|
|
217
|
+
// gate (pFar > pNear) stays shut and the user's voice is left intact.
|
|
218
|
+
// The suppressor only ever engages on the rare echo-only sub-frame (a
|
|
219
|
+
// momentary user pause while the agent plays), so total output power is
|
|
220
|
+
// preserved to well within 0.1% — never the aggressive `gain: 0.1` crush.
|
|
221
|
+
const half = near.length >> 1;
|
|
222
|
+
const pBase = power(base, half);
|
|
223
|
+
const pSup = power(sup, half);
|
|
224
|
+
expect(Math.abs(pSup - pBase) / pBase).toBeLessThan(0.001);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it("is off by default (no residualSuppression option ⇒ no extra attenuation)", () => {
|
|
228
|
+
const far = signal(SR, 5);
|
|
229
|
+
const near = echoOf(far);
|
|
230
|
+
const a = runBlocks(
|
|
231
|
+
new NlmsEchoCanceller({ filterTaps: 128 }),
|
|
232
|
+
near,
|
|
233
|
+
far,
|
|
234
|
+
);
|
|
235
|
+
const b = runBlocks(
|
|
236
|
+
new NlmsEchoCanceller({ filterTaps: 128, residualSuppression: false }),
|
|
237
|
+
near,
|
|
238
|
+
far,
|
|
239
|
+
);
|
|
240
|
+
const half = near.length >> 1;
|
|
241
|
+
expect(power(a, half)).toBeCloseTo(power(b, half), 12);
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
});
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* nlms-echo-canceller.ts — PCM acoustic echo cancellation for the live
|
|
3
|
+
* half-duplex voice pipeline (#9455).
|
|
4
|
+
*
|
|
5
|
+
* When the agent speaks, its TTS playback leaks back into the microphone and
|
|
6
|
+
* corrupts ASR / VAD / diarization (the agent hears itself). This is a
|
|
7
|
+
* single-channel adaptive echo canceller: a normalized least-mean-squares
|
|
8
|
+
* (NLMS) FIR filter models the playback→mic acoustic path and subtracts the
|
|
9
|
+
* estimated echo from the near-end (mic) signal sample-by-sample.
|
|
10
|
+
*
|
|
11
|
+
* near-end d[n] = local_speech[n] + echo[n] (the raw mic)
|
|
12
|
+
* far-end x[n] = agent TTS playback (the reference)
|
|
13
|
+
* estimate ŷ[n] = Σ_k w[k]·x[n−k] (modeled echo)
|
|
14
|
+
* output e[n] = d[n] − ŷ[n] (echo-cancelled mic → ASR)
|
|
15
|
+
* update w[k] += μ·e[n]·x[n−k] / (‖x‖² + ε) (NLMS adaptation)
|
|
16
|
+
*
|
|
17
|
+
* All audio is 16 kHz mono Float32 [-1, 1] — the pipeline's internal format
|
|
18
|
+
* (see audio-frame-consumer.ts). The filter length must cover the
|
|
19
|
+
* playback→mic delay plus the room's reverberation tail; for tails longer than
|
|
20
|
+
* the filter, calibrate `delaySamples` (the bulk transport delay) so the
|
|
21
|
+
* adaptive taps only have to model the short residual impulse.
|
|
22
|
+
*
|
|
23
|
+
* Scope: this targets the dominant failure mode — the agent transcribing its
|
|
24
|
+
* own TTS while the *user is silent* (echo-only), where it achieves ~29 dB of
|
|
25
|
+
* echo-return-loss-enhancement. A far-end-vs-near-end double-talk detector
|
|
26
|
+
* freezes adaptation when a local talker is active so the filter cannot learn
|
|
27
|
+
* (and cancel) the user's voice; barge-in itself is handled upstream by the
|
|
28
|
+
* barge-in detector (which stops playback). Full double-talk residual-echo
|
|
29
|
+
* suppression is AEC3-class work and intentionally out of scope here.
|
|
30
|
+
*
|
|
31
|
+
* Pure DSP, zero dependencies — verified by nlms-echo-canceller.test.ts
|
|
32
|
+
* (ERLE on synthetic echo, passthrough, stability, reset).
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
export interface NlmsEchoCancellerOptions {
|
|
36
|
+
/** Adaptive FIR length in samples. 256 ≈ 16 ms of impulse response @16 kHz. */
|
|
37
|
+
filterTaps?: number;
|
|
38
|
+
/** NLMS step size in (0, 2). Larger = faster adaptation, less stable. */
|
|
39
|
+
mu?: number;
|
|
40
|
+
/** Regularization added to the reference energy to avoid divide-by-zero. */
|
|
41
|
+
epsilon?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Bulk playback→mic transport delay in samples. The reference is consumed
|
|
44
|
+
* `delaySamples` ahead of the near-end so the adaptive taps only model the
|
|
45
|
+
* residual room impulse, not the (potentially large) transport latency.
|
|
46
|
+
*/
|
|
47
|
+
delaySamples?: number;
|
|
48
|
+
/**
|
|
49
|
+
* Double-talk detector ratio. When the smoothed near-end power exceeds
|
|
50
|
+
* `dtdRatio`× the smoothed far-end reference power (a passive echo path
|
|
51
|
+
* attenuates, so echo power stays below the reference), a local talker is
|
|
52
|
+
* assumed active and adaptation is frozen so the filter cannot learn (and
|
|
53
|
+
* cancel) the user's voice. Set 0 to disable.
|
|
54
|
+
*/
|
|
55
|
+
dtdRatio?: number;
|
|
56
|
+
/**
|
|
57
|
+
* Opt-in nonlinear residual-echo suppressor (#9583/#9649). After the linear
|
|
58
|
+
* NLMS subtracts the modeled echo, an echo-only frame (the agent is speaking,
|
|
59
|
+
* the user is NOT — far-end power exceeds near-end power and no double-talk)
|
|
60
|
+
* still carries the residual echo the finite-length filter could not remove.
|
|
61
|
+
* When enabled, the residual on those frames is scaled toward zero. It is
|
|
62
|
+
* **default-off** and never engages during double-talk or near-end-dominant
|
|
63
|
+
* frames, so it can never attenuate the user's voice. Pass `true` for the
|
|
64
|
+
* default gain or `{ gain }` to tune.
|
|
65
|
+
*/
|
|
66
|
+
residualSuppression?: boolean | ResidualSuppressionOptions;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface ResidualSuppressionOptions {
|
|
70
|
+
/**
|
|
71
|
+
* Gain (0,1] applied to the residual on echo-only frames. Lower = stronger
|
|
72
|
+
* suppression. Default 0.15 (~−16 dB) — aggressive enough to flatten residual
|
|
73
|
+
* echo while leaving headroom for the gate's hysteresis.
|
|
74
|
+
*/
|
|
75
|
+
gain?: number;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const DEFAULTS = {
|
|
79
|
+
filterTaps: 256,
|
|
80
|
+
mu: 0.3,
|
|
81
|
+
epsilon: 1e-6,
|
|
82
|
+
delaySamples: 0,
|
|
83
|
+
dtdRatio: 2,
|
|
84
|
+
residualSuppressionGain: 0.15,
|
|
85
|
+
} as const;
|
|
86
|
+
|
|
87
|
+
export class NlmsEchoCanceller {
|
|
88
|
+
private readonly w: Float32Array; // adaptive filter weights
|
|
89
|
+
private readonly x: Float32Array; // far-end ring buffer (most-recent-first)
|
|
90
|
+
private readonly taps: number;
|
|
91
|
+
private readonly mu: number;
|
|
92
|
+
private readonly eps: number;
|
|
93
|
+
private readonly delay: number;
|
|
94
|
+
private readonly dtdRatio: number;
|
|
95
|
+
/** Residual-suppressor gain, or null when the suppressor is disabled (default). */
|
|
96
|
+
private readonly resGain: number | null;
|
|
97
|
+
/** Pending far-end samples not yet aligned to a near-end sample (delay line). */
|
|
98
|
+
private readonly delayLine: number[] = [];
|
|
99
|
+
private xEnergy = 0; // running ‖x‖² over the active window (incremental)
|
|
100
|
+
private peakXEnergy = 0; // slowly-decaying envelope of ‖x‖² (far-end scale)
|
|
101
|
+
private pNear = 0; // smoothed near-end power (DTD)
|
|
102
|
+
private pFar = 0; // smoothed far-end reference power (DTD)
|
|
103
|
+
private hangover = 0; // samples to stay frozen after a double-talk trigger
|
|
104
|
+
private lastEchoPow = 0;
|
|
105
|
+
|
|
106
|
+
/** Stay frozen ~30 ms after the last double-talk trigger so the filter is not
|
|
107
|
+
* corrupted by the bursty onset/offset of the near-end talker. */
|
|
108
|
+
private static readonly HANGOVER_SAMPLES = 480;
|
|
109
|
+
/** Per-sample decay of the far-end energy envelope (~1 s time constant) so a
|
|
110
|
+
* short TTS pause keeps the far-end-active gate closed through the gap. */
|
|
111
|
+
private static readonly PEAK_DECAY = 0.99994;
|
|
112
|
+
/** Far-end is "active" only when the instantaneous ‖x‖² is within this
|
|
113
|
+
* fraction (−20 dB) of the recent envelope. Below it there is no echo to
|
|
114
|
+
* learn, so adaptation freezes (see process()). */
|
|
115
|
+
private static readonly FAR_ACTIVITY_FRAC = 0.01;
|
|
116
|
+
/** NLMS regularization as a fraction of the far-end envelope. Keeps the step
|
|
117
|
+
* bounded when ‖x‖² momentarily underflows, so a quiet far-end passage can't
|
|
118
|
+
* make the normaliser collapse to the absolute `eps` and blow the filter up. */
|
|
119
|
+
private static readonly REG_FRAC = 0.01;
|
|
120
|
+
private lastResidualPow = 0;
|
|
121
|
+
|
|
122
|
+
constructor(opts: NlmsEchoCancellerOptions = {}) {
|
|
123
|
+
this.taps = Math.max(1, Math.floor(opts.filterTaps ?? DEFAULTS.filterTaps));
|
|
124
|
+
this.mu = opts.mu ?? DEFAULTS.mu;
|
|
125
|
+
this.eps = opts.epsilon ?? DEFAULTS.epsilon;
|
|
126
|
+
this.delay = Math.max(
|
|
127
|
+
0,
|
|
128
|
+
Math.floor(opts.delaySamples ?? DEFAULTS.delaySamples),
|
|
129
|
+
);
|
|
130
|
+
this.dtdRatio = opts.dtdRatio ?? DEFAULTS.dtdRatio;
|
|
131
|
+
this.resGain = resolveResidualSuppressionGain(opts.residualSuppression);
|
|
132
|
+
this.w = new Float32Array(this.taps);
|
|
133
|
+
this.x = new Float32Array(this.taps);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Cancel echo from one block of mic audio.
|
|
138
|
+
*
|
|
139
|
+
* @param nearEnd raw mic block (local speech + echo), Float32 [-1, 1]
|
|
140
|
+
* @param farEnd agent playback reference for the same time window. Pass an
|
|
141
|
+
* empty/zero array when the agent is NOT speaking — the filter
|
|
142
|
+
* then passes the mic through unchanged (output ≈ input).
|
|
143
|
+
* @returns echo-cancelled near-end block (same length as `nearEnd`).
|
|
144
|
+
*/
|
|
145
|
+
process(nearEnd: Float32Array, farEnd: Float32Array): Float32Array {
|
|
146
|
+
const n = nearEnd.length;
|
|
147
|
+
const out = new Float32Array(n);
|
|
148
|
+
let echoPow = 0;
|
|
149
|
+
let residualPow = 0;
|
|
150
|
+
|
|
151
|
+
for (let i = 0; i < n; i++) {
|
|
152
|
+
// Feed the (delay-aligned) far-end sample into the ring buffer.
|
|
153
|
+
const incoming = i < farEnd.length ? farEnd[i] : 0;
|
|
154
|
+
this.delayLine.push(incoming);
|
|
155
|
+
const ref =
|
|
156
|
+
this.delayLine.length > this.delay
|
|
157
|
+
? (this.delayLine.shift() as number)
|
|
158
|
+
: 0;
|
|
159
|
+
this.pushRef(ref);
|
|
160
|
+
// Track the far-end energy envelope (instant rise, slow decay) so the
|
|
161
|
+
// activity gate and the regulariser scale with the playback level.
|
|
162
|
+
this.peakXEnergy = Math.max(
|
|
163
|
+
this.peakXEnergy * NlmsEchoCanceller.PEAK_DECAY,
|
|
164
|
+
this.xEnergy,
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
// Estimate echo ŷ = wᵀ·x and the error e = d − ŷ (the cleaned sample).
|
|
168
|
+
let yhat = 0;
|
|
169
|
+
for (let k = 0; k < this.taps; k++) yhat += this.w[k] * this.x[k];
|
|
170
|
+
const d = nearEnd[i];
|
|
171
|
+
const e = d - yhat;
|
|
172
|
+
|
|
173
|
+
// Double-talk detection by near-end vs far-end power. A passive
|
|
174
|
+
// playback→mic path attenuates, so the echo power stays below the
|
|
175
|
+
// far-end reference power; when the smoothed near-end power instead
|
|
176
|
+
// exceeds `dtdRatio`× the far-end power, a local talker is active. This is
|
|
177
|
+
// independent of the filter's convergence state, so it never blocks
|
|
178
|
+
// initial adaptation (unlike comparing against the echo estimate).
|
|
179
|
+
// Fast smoothing (~6 ms) so the detector reacts at the onset of the
|
|
180
|
+
// near-end burst, plus a hangover so it stays frozen through it.
|
|
181
|
+
this.pNear = 0.99 * this.pNear + 0.01 * d * d;
|
|
182
|
+
this.pFar = 0.99 * this.pFar + 0.01 * ref * ref;
|
|
183
|
+
if (
|
|
184
|
+
this.dtdRatio > 0 &&
|
|
185
|
+
this.pFar > this.eps &&
|
|
186
|
+
this.pNear > this.dtdRatio * this.pFar
|
|
187
|
+
) {
|
|
188
|
+
this.hangover = NlmsEchoCanceller.HANGOVER_SAMPLES;
|
|
189
|
+
}
|
|
190
|
+
const doubleTalk = this.hangover > 0;
|
|
191
|
+
if (this.hangover > 0) this.hangover--;
|
|
192
|
+
|
|
193
|
+
// Far-end activity gate: only adapt while the far-end is actually
|
|
194
|
+
// driving an echo. During a quiet TTS passage ‖x‖² collapses toward
|
|
195
|
+
// zero but is not exactly zero (DAC dither / room floor), so without
|
|
196
|
+
// this gate the NLMS step μ·e/(‖x‖²+ε) explodes and the filter learns
|
|
197
|
+
// the near-end MIC NOISE instead of an echo — diverging and corrupting
|
|
198
|
+
// the signal handed to ASR/VAD. There is no echo to learn when the
|
|
199
|
+
// far-end is silent, so freezing is both correct and stabilising.
|
|
200
|
+
const farActive =
|
|
201
|
+
this.xEnergy > NlmsEchoCanceller.FAR_ACTIVITY_FRAC * this.peakXEnergy;
|
|
202
|
+
|
|
203
|
+
// NLMS weight update: w += μ·e·x / (‖x‖² + δ), frozen during
|
|
204
|
+
// double-talk or far-end silence. δ scales with the far-end envelope so
|
|
205
|
+
// the normaliser can never collapse to the tiny absolute `eps`.
|
|
206
|
+
if (!doubleTalk && farActive) {
|
|
207
|
+
const reg = Math.max(
|
|
208
|
+
this.eps,
|
|
209
|
+
NlmsEchoCanceller.REG_FRAC * this.peakXEnergy,
|
|
210
|
+
);
|
|
211
|
+
const norm = this.xEnergy + reg;
|
|
212
|
+
const step = (this.mu * e) / norm;
|
|
213
|
+
if (Number.isFinite(step)) {
|
|
214
|
+
for (let k = 0; k < this.taps; k++) this.w[k] += step * this.x[k];
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Opt-in residual-echo suppressor (#9583/#9649): on echo-only frames
|
|
219
|
+
// (far-end dominant, no double-talk, far actually active) the residual
|
|
220
|
+
// `e` is mostly the echo the finite filter could not remove, so scale it
|
|
221
|
+
// toward zero. Gated so it never engages while the user might be talking
|
|
222
|
+
// (double-talk or near-end-dominant) — it cannot attenuate the user's
|
|
223
|
+
// voice. Default-off: `cleaned === e` unless explicitly enabled.
|
|
224
|
+
const cleaned =
|
|
225
|
+
this.resGain !== null &&
|
|
226
|
+
!doubleTalk &&
|
|
227
|
+
farActive &&
|
|
228
|
+
this.pFar > this.pNear
|
|
229
|
+
? e * this.resGain
|
|
230
|
+
: e;
|
|
231
|
+
out[i] = cleaned;
|
|
232
|
+
|
|
233
|
+
echoPow += yhat * yhat;
|
|
234
|
+
residualPow += cleaned * cleaned;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
this.lastEchoPow = echoPow / Math.max(1, n);
|
|
238
|
+
this.lastResidualPow = residualPow / Math.max(1, n);
|
|
239
|
+
return out;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Advance cheap detector/reference state while the far-end is silent without
|
|
244
|
+
* running the FIR echo-estimation loop. Learned filter weights are preserved,
|
|
245
|
+
* but stale playback samples are removed from the delay line/ring so the next
|
|
246
|
+
* non-empty reference frame cannot subtract an echo estimate from a previous
|
|
247
|
+
* utterance.
|
|
248
|
+
*/
|
|
249
|
+
observeFarEndSilence(nearEnd: Float32Array): void {
|
|
250
|
+
const n = nearEnd.length;
|
|
251
|
+
this.delayLine.length = 0;
|
|
252
|
+
this.x.fill(0);
|
|
253
|
+
this.xEnergy = 0;
|
|
254
|
+
this.peakXEnergy *= NlmsEchoCanceller.PEAK_DECAY ** n;
|
|
255
|
+
this.pFar *= 0.99 ** n;
|
|
256
|
+
this.hangover = Math.max(0, this.hangover - n);
|
|
257
|
+
|
|
258
|
+
let residualPow = 0;
|
|
259
|
+
for (let i = 0; i < n; i++) {
|
|
260
|
+
const d = nearEnd[i];
|
|
261
|
+
this.pNear = 0.99 * this.pNear + 0.01 * d * d;
|
|
262
|
+
residualPow += d * d;
|
|
263
|
+
}
|
|
264
|
+
if (this.peakXEnergy < this.eps) this.peakXEnergy = 0;
|
|
265
|
+
if (this.pFar < this.eps) this.pFar = 0;
|
|
266
|
+
this.lastEchoPow = 0;
|
|
267
|
+
this.lastResidualPow = residualPow / Math.max(1, n);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/** Echo-return-loss-enhancement (dB) over the last processed block. Higher is
|
|
271
|
+
* better; >10 dB is a meaningful cancellation. Returns 0 when there is no
|
|
272
|
+
* modeled echo (agent silent) so a passthrough block reads as "no gain". */
|
|
273
|
+
get lastErleDb(): number {
|
|
274
|
+
if (this.lastResidualPow <= 0 || this.lastEchoPow <= 0) return 0;
|
|
275
|
+
return 10 * Math.log10(this.lastEchoPow / this.lastResidualPow);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/** Reset adaptation (e.g. when the playback path changes). */
|
|
279
|
+
reset(): void {
|
|
280
|
+
this.w.fill(0);
|
|
281
|
+
this.x.fill(0);
|
|
282
|
+
this.delayLine.length = 0;
|
|
283
|
+
this.xEnergy = 0;
|
|
284
|
+
this.peakXEnergy = 0;
|
|
285
|
+
this.pNear = 0;
|
|
286
|
+
this.pFar = 0;
|
|
287
|
+
this.hangover = 0;
|
|
288
|
+
this.lastEchoPow = 0;
|
|
289
|
+
this.lastResidualPow = 0;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/** Shift a new far-end sample into the ring buffer, maintaining ‖x‖²
|
|
293
|
+
* incrementally (drop the oldest sample's energy, add the newest). */
|
|
294
|
+
private pushRef(sample: number): void {
|
|
295
|
+
const dropped = this.x[this.taps - 1];
|
|
296
|
+
this.xEnergy += sample * sample - dropped * dropped;
|
|
297
|
+
if (this.xEnergy < 0) this.xEnergy = 0; // guard fp drift
|
|
298
|
+
for (let k = this.taps - 1; k > 0; k--) this.x[k] = this.x[k - 1];
|
|
299
|
+
this.x[0] = sample;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/** Resolve the residual-suppressor option to a clamped gain in (0,1], or null
|
|
304
|
+
* (disabled). `false`/`undefined` → null; `true` → default gain; `{ gain }` →
|
|
305
|
+
* that gain clamped to (0,1] (an out-of-range/non-finite gain falls back to the
|
|
306
|
+
* default rather than silently disabling the suppressor). */
|
|
307
|
+
function resolveResidualSuppressionGain(
|
|
308
|
+
option: boolean | ResidualSuppressionOptions | undefined,
|
|
309
|
+
): number | null {
|
|
310
|
+
if (!option) return null;
|
|
311
|
+
if (option === true) return DEFAULTS.residualSuppressionGain;
|
|
312
|
+
const g = option.gain;
|
|
313
|
+
if (typeof g !== "number" || !Number.isFinite(g) || g <= 0 || g > 1) {
|
|
314
|
+
return DEFAULTS.residualSuppressionGain;
|
|
315
|
+
}
|
|
316
|
+
return g;
|
|
317
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit coverage for resolvePowerSourceState's env-override contract (#9147 voice).
|
|
3
|
+
*
|
|
4
|
+
* resolvePowerSourceState gates the optimistic-decode power policy. Its
|
|
5
|
+
* `ELIZA_VOICE_POWER_SOURCE` override is the deterministic, cross-platform path
|
|
6
|
+
* (the `/sys/class/power_supply` probe is Linux-only and environment-dependent,
|
|
7
|
+
* so it is not asserted here). Was untested. No GGUF / audio.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
11
|
+
import { resolvePowerSourceState } from "./optimistic-policy";
|
|
12
|
+
|
|
13
|
+
const STATES = ["plugged-in", "battery", "unknown"] as const;
|
|
14
|
+
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
vi.unstubAllEnvs();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe("resolvePowerSourceState — ELIZA_VOICE_POWER_SOURCE override", () => {
|
|
20
|
+
it("honors each valid override value verbatim", () => {
|
|
21
|
+
for (const state of STATES) {
|
|
22
|
+
vi.stubEnv("ELIZA_VOICE_POWER_SOURCE", state);
|
|
23
|
+
expect(resolvePowerSourceState()).toBe(state);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("trims and lowercases the override", () => {
|
|
28
|
+
vi.stubEnv("ELIZA_VOICE_POWER_SOURCE", " BATTERY ");
|
|
29
|
+
expect(resolvePowerSourceState()).toBe("battery");
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("ignores an invalid override and still returns a valid state", () => {
|
|
33
|
+
vi.stubEnv("ELIZA_VOICE_POWER_SOURCE", "nonsense");
|
|
34
|
+
expect(STATES).toContain(resolvePowerSourceState());
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A2 — LocalAgreement-n streaming-ASR partial stabilizer.
|
|
3
3
|
*
|
|
4
|
-
* Streaming ASR (the
|
|
4
|
+
* Streaming ASR (the fused Gemma ASR build running on partial windows)
|
|
5
5
|
* emits a fresh partial transcript on every
|
|
6
6
|
* audio frame. Each partial can revise tokens the previous partial
|
|
7
7
|
* already showed — "the cat sa" → "the cat sat" → "the cat sat on" is
|
|
@@ -310,10 +310,9 @@ export class VoicePipeline {
|
|
|
310
310
|
// Drive the live `StreamingTranscriber` as a batch: feed the whole
|
|
311
311
|
// (already VAD-gated) utterance buffer as one frame, `flush()` to
|
|
312
312
|
// force-finalize, and split the final transcript into contiguous text
|
|
313
|
-
// tokens. The fused
|
|
314
|
-
//
|
|
315
|
-
//
|
|
316
|
-
// is used.
|
|
313
|
+
// tokens. The fused Gemma ASR decoder shares the text-model tokenizer, so
|
|
314
|
+
// when it reports token ids alongside the transcript they ride along as
|
|
315
|
+
// `TextToken.id`; when it omits them the word-chunk fallback is used.
|
|
317
316
|
const asrTokens = await this.transcribeAll(audio, cancel);
|
|
318
317
|
if (cancel.cancelled) return this.finish("cancelled");
|
|
319
318
|
// The instant ASR's last token has been emitted: drafter + verifier
|