@elizaos/plugin-local-inference 2.0.0-beta.1 → 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/LICENSE +21 -0
- package/README.md +157 -0
- package/dist/actions/generate-media.d.ts +59 -0
- package/dist/actions/generate-media.d.ts.map +1 -0
- package/dist/actions/identify-speaker.d.ts +23 -0
- package/dist/actions/identify-speaker.d.ts.map +1 -0
- package/dist/actions/transcription-control.d.ts +29 -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 +8 -37
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38979 -430
- package/dist/index.js.map +217 -0
- package/dist/local-inference-routes.d.ts +47 -0
- package/dist/local-inference-routes.d.ts.map +1 -0
- package/dist/provider.d.ts +21 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/routes/compat-helpers.d.ts +18 -0
- package/dist/routes/compat-helpers.d.ts.map +1 -0
- package/dist/routes/family-member-route.d.ts +62 -0
- package/dist/routes/family-member-route.d.ts.map +1 -0
- package/dist/routes/index.d.ts +20 -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/dist/routes/live-diarization-route.d.ts +33 -0
- package/dist/routes/live-diarization-route.d.ts.map +1 -0
- package/dist/routes/local-inference-asr-route.d.ts +4 -0
- package/dist/routes/local-inference-asr-route.d.ts.map +1 -0
- package/dist/routes/local-inference-asr-transcribe.d.ts +20 -0
- package/dist/routes/local-inference-asr-transcribe.d.ts.map +1 -0
- package/dist/routes/local-inference-compat-routes.d.ts +16 -0
- package/dist/routes/local-inference-compat-routes.d.ts.map +1 -0
- package/dist/routes/local-inference-tts-route.d.ts +7 -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 +15 -0
- package/dist/routes/transcript-audio-store.d.ts.map +1 -0
- package/dist/routes/transcripts-routes.d.ts +44 -0
- package/dist/routes/transcripts-routes.d.ts.map +1 -0
- package/dist/routes/voice-first-run-routes.d.ts +62 -0
- package/dist/routes/voice-first-run-routes.d.ts.map +1 -0
- package/dist/routes/voice-models-routes.d.ts +62 -0
- package/dist/routes/voice-models-routes.d.ts.map +1 -0
- package/dist/routes/voice-profile-plugin-routes.d.ts +19 -0
- package/dist/routes/voice-profile-plugin-routes.d.ts.map +1 -0
- package/dist/routes/voice-profiles-management-routes.d.ts +52 -0
- package/dist/routes/voice-profiles-management-routes.d.ts.map +1 -0
- package/dist/routes/voice-speaker-profile-routes.d.ts +57 -0
- package/dist/routes/voice-speaker-profile-routes.d.ts.map +1 -0
- package/dist/runtime/embedding-manager-support.d.ts +77 -0
- package/dist/runtime/embedding-manager-support.d.ts.map +1 -0
- package/dist/runtime/embedding-presets.d.ts +16 -0
- package/dist/runtime/embedding-presets.d.ts.map +1 -0
- package/dist/runtime/embedding-warmup-policy.d.ts +14 -0
- package/dist/runtime/embedding-warmup-policy.d.ts.map +1 -0
- package/dist/runtime/ensure-local-inference-handler.d.ts +70 -0
- package/dist/runtime/ensure-local-inference-handler.d.ts.map +1 -0
- package/dist/runtime/index.d.ts +15 -0
- 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/dist/runtime/voice-entity-binding.d.ts +113 -0
- package/dist/runtime/voice-entity-binding.d.ts.map +1 -0
- package/dist/services/active-model.d.ts +310 -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/dist/services/assignments.d.ts +84 -0
- 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/dist/services/backend.d.ts +440 -0
- package/dist/services/backend.d.ts.map +1 -0
- package/dist/services/bionic-host-loader.d.ts +67 -0
- package/dist/services/bionic-host-loader.d.ts.map +1 -0
- package/dist/services/bundled-models.d.ts +34 -0
- package/dist/services/bundled-models.d.ts.map +1 -0
- package/dist/services/cache-bridge.d.ts +206 -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 +109 -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 +102 -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 +142 -0
- package/dist/services/conversation-registry.d.ts.map +1 -0
- package/dist/services/desktop-fused-ffi-backend-runtime.d.ts +111 -0
- package/dist/services/desktop-fused-ffi-backend-runtime.d.ts.map +1 -0
- package/dist/services/device-bridge.d.ts +188 -0
- package/dist/services/device-bridge.d.ts.map +1 -0
- package/dist/services/device-resource-metrics.d.ts +149 -0
- package/dist/services/device-resource-metrics.d.ts.map +1 -0
- package/dist/services/device-tier.d.ts +133 -0
- package/dist/services/device-tier.d.ts.map +1 -0
- package/dist/services/downloader.d.ts +94 -0
- package/dist/services/downloader.d.ts.map +1 -0
- package/dist/services/engine.d.ts +579 -0
- 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 +17 -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/dist/services/ffi-streaming-backend.d.ts +201 -0
- package/dist/services/ffi-streaming-backend.d.ts.map +1 -0
- package/dist/services/ffi-streaming-runner.d.ts +146 -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 +56 -0
- package/dist/services/gpu-detect.d.ts.map +1 -0
- package/dist/services/handler-registry.d.ts +72 -0
- package/dist/services/handler-registry.d.ts.map +1 -0
- package/dist/services/hardware.d.ts +63 -0
- package/dist/services/hardware.d.ts.map +1 -0
- package/dist/services/image-description-runtime.d.ts +14 -0
- package/dist/services/image-description-runtime.d.ts.map +1 -0
- package/dist/services/imagegen/aosp-unavailable.d.ts +134 -0
- package/dist/services/imagegen/aosp-unavailable.d.ts.map +1 -0
- package/dist/services/imagegen/backend-selector.d.ts +118 -0
- package/dist/services/imagegen/backend-selector.d.ts.map +1 -0
- package/dist/services/imagegen/coreml-unavailable.d.ts +105 -0
- package/dist/services/imagegen/coreml-unavailable.d.ts.map +1 -0
- package/dist/services/imagegen/errors.d.ts +16 -0
- package/dist/services/imagegen/errors.d.ts.map +1 -0
- package/dist/services/imagegen/index.d.ts +58 -0
- package/dist/services/imagegen/index.d.ts.map +1 -0
- package/dist/services/imagegen/mflux.d.ts +74 -0
- package/dist/services/imagegen/mflux.d.ts.map +1 -0
- package/dist/services/imagegen/sd-cpp.d.ts +181 -0
- package/dist/services/imagegen/sd-cpp.d.ts.map +1 -0
- package/dist/services/imagegen/tensorrt-unavailable.d.ts +83 -0
- package/dist/services/imagegen/tensorrt-unavailable.d.ts.map +1 -0
- package/dist/services/imagegen/types.d.ts +181 -0
- package/dist/services/imagegen/types.d.ts.map +1 -0
- package/dist/services/index.d.ts +31 -0
- 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 +132 -0
- package/dist/services/inference-capabilities.d.ts.map +1 -0
- package/dist/services/inference-telemetry.d.ts +59 -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 +189 -0
- package/dist/services/kv-spill.d.ts.map +1 -0
- package/dist/services/latency-trace.d.ts +346 -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 +96 -0
- package/dist/services/llm-streaming-binding.d.ts.map +1 -0
- package/dist/services/load-args.d.ts +82 -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/dist/services/manifest/schema.d.ts +903 -0
- package/dist/services/manifest/schema.d.ts.map +1 -0
- package/dist/services/manifest/types.d.ts +32 -0
- package/dist/services/manifest/types.d.ts.map +1 -0
- package/dist/services/manifest/validator.d.ts +66 -0
- package/dist/services/manifest/validator.d.ts.map +1 -0
- package/dist/services/memory-arbiter.d.ts +348 -0
- 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/dist/services/memory-monitor.d.ts +128 -0
- package/dist/services/memory-monitor.d.ts.map +1 -0
- package/dist/services/memory-pressure.d.ts +130 -0
- package/dist/services/memory-pressure.d.ts.map +1 -0
- package/dist/services/mtp-doctor.d.ts +13 -0
- package/dist/services/mtp-doctor.d.ts.map +1 -0
- package/dist/services/network-policy.d.ts +127 -0
- package/dist/services/network-policy.d.ts.map +1 -0
- package/dist/services/paths.d.ts +6 -0
- package/dist/services/paths.d.ts.map +1 -0
- package/dist/services/planner-skeleton.d.ts +124 -0
- package/dist/services/planner-skeleton.d.ts.map +1 -0
- package/dist/services/providers.d.ts +38 -0
- package/dist/services/providers.d.ts.map +1 -0
- package/dist/services/ram-budget.d.ts +110 -0
- package/dist/services/ram-budget.d.ts.map +1 -0
- package/dist/services/readiness.d.ts +9 -0
- package/dist/services/readiness.d.ts.map +1 -0
- package/dist/services/recommendation.d.ts +111 -0
- package/dist/services/recommendation.d.ts.map +1 -0
- package/dist/services/registry.d.ts +33 -0
- package/dist/services/registry.d.ts.map +1 -0
- package/dist/services/router-handler.d.ts +92 -0
- package/dist/services/router-handler.d.ts.map +1 -0
- package/dist/services/routing-policy.d.ts +92 -0
- package/dist/services/routing-policy.d.ts.map +1 -0
- package/dist/services/routing-preferences.d.ts +8 -0
- package/dist/services/routing-preferences.d.ts.map +1 -0
- package/dist/services/runtime-target.d.ts +98 -0
- package/dist/services/runtime-target.d.ts.map +1 -0
- package/dist/services/service.d.ts +128 -0
- package/dist/services/service.d.ts.map +1 -0
- package/dist/services/session-pool.d.ts +72 -0
- package/dist/services/session-pool.d.ts.map +1 -0
- package/dist/services/structured-output/deterministic-repair.d.ts +23 -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 +311 -0
- package/dist/services/structured-output.d.ts.map +1 -0
- package/dist/services/system-memory.d.ts +33 -0
- package/dist/services/system-memory.d.ts.map +1 -0
- package/dist/services/types.d.ts +19 -0
- package/dist/services/types.d.ts.map +1 -0
- package/dist/services/verify-on-device.d.ts +34 -0
- package/dist/services/verify-on-device.d.ts.map +1 -0
- package/dist/services/verify.d.ts +8 -0
- package/dist/services/verify.d.ts.map +1 -0
- package/dist/services/vision/aosp-unavailable.d.ts +115 -0
- package/dist/services/vision/aosp-unavailable.d.ts.map +1 -0
- package/dist/services/vision/capacitor-llama.d.ts +99 -0
- package/dist/services/vision/capacitor-llama.d.ts.map +1 -0
- package/dist/services/vision/cloud-fallback.d.ts +47 -0
- package/dist/services/vision/cloud-fallback.d.ts.map +1 -0
- package/dist/services/vision/hash.d.ts +71 -0
- package/dist/services/vision/hash.d.ts.map +1 -0
- package/dist/services/vision/index.d.ts +95 -0
- package/dist/services/vision/index.d.ts.map +1 -0
- package/dist/services/vision/llama-server.d.ts +73 -0
- package/dist/services/vision/llama-server.d.ts.map +1 -0
- package/dist/services/vision/types.d.ts +162 -0
- package/dist/services/vision/types.d.ts.map +1 -0
- package/dist/services/vision/vast-fallback.d.ts +18 -0
- package/dist/services/vision/vast-fallback.d.ts.map +1 -0
- package/dist/services/vision-embedding-cache.d.ts +98 -0
- 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/dist/services/voice/audio-frame-consumer.d.ts +294 -0
- package/dist/services/voice/audio-frame-consumer.d.ts.map +1 -0
- package/dist/services/voice/barge-in.d.ts +112 -0
- package/dist/services/voice/barge-in.d.ts.map +1 -0
- package/dist/services/voice/cancellation-coordinator.d.ts +127 -0
- package/dist/services/voice/cancellation-coordinator.d.ts.map +1 -0
- package/dist/services/voice/checkpoint-manager.d.ts +199 -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 +170 -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/dist/services/voice/eliza1-eot-scorer.d.ts +124 -0
- 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/dist/services/voice/embedding.d.ts +132 -0
- package/dist/services/voice/embedding.d.ts.map +1 -0
- package/dist/services/voice/emotion-attribution.d.ts +68 -0
- package/dist/services/voice/emotion-attribution.d.ts.map +1 -0
- package/dist/services/voice/engine-bridge.d.ts +762 -0
- package/dist/services/voice/engine-bridge.d.ts.map +1 -0
- package/dist/services/voice/eot-classifier-ggml.d.ts +179 -0
- package/dist/services/voice/eot-classifier-ggml.d.ts.map +1 -0
- package/dist/services/voice/eot-classifier.d.ts +211 -0
- package/dist/services/voice/eot-classifier.d.ts.map +1 -0
- package/dist/services/voice/errors.d.ts +20 -0
- package/dist/services/voice/errors.d.ts.map +1 -0
- package/dist/services/voice/expressive-tags.d.ts +158 -0
- package/dist/services/voice/expressive-tags.d.ts.map +1 -0
- package/dist/services/voice/ffi-bindings.d.ts +696 -0
- package/dist/services/voice/ffi-bindings.d.ts.map +1 -0
- package/dist/services/voice/first-line-cache.d.ts +181 -0
- package/dist/services/voice/first-line-cache.d.ts.map +1 -0
- package/dist/services/voice/fused-eot-scorer.d.ts +51 -0
- package/dist/services/voice/fused-eot-scorer.d.ts.map +1 -0
- package/dist/services/voice/index.d.ts +96 -0
- 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/dist/services/voice/kokoro/kokoro-backend.d.ts +87 -0
- package/dist/services/voice/kokoro/kokoro-backend.d.ts.map +1 -0
- package/dist/services/voice/kokoro/kokoro-engine-discovery.d.ts +58 -0
- package/dist/services/voice/kokoro/kokoro-engine-discovery.d.ts.map +1 -0
- package/dist/services/voice/kokoro/kokoro-ffi-runtime.d.ts +75 -0
- package/dist/services/voice/kokoro/kokoro-ffi-runtime.d.ts.map +1 -0
- package/dist/services/voice/kokoro/kokoro-runtime.d.ts +100 -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 +50 -0
- package/dist/services/voice/kokoro/phonemizer.d.ts.map +1 -0
- package/dist/services/voice/kokoro/pick-runtime.d.ts +61 -0
- 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 +82 -0
- package/dist/services/voice/kokoro/types.d.ts.map +1 -0
- package/dist/services/voice/kokoro/voice-presets.d.ts +23 -0
- package/dist/services/voice/kokoro/voice-presets.d.ts.map +1 -0
- package/dist/services/voice/kokoro/voices.d.ts +30 -0
- package/dist/services/voice/kokoro/voices.d.ts.map +1 -0
- package/dist/services/voice/lifecycle.d.ts +135 -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/dist/services/voice/mic-source.d.ts +136 -0
- 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 +109 -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/dist/services/voice/partial-stabilizer.d.ts +73 -0
- package/dist/services/voice/partial-stabilizer.d.ts.map +1 -0
- package/dist/services/voice/phoneme-tokenizer.d.ts +49 -0
- package/dist/services/voice/phoneme-tokenizer.d.ts.map +1 -0
- package/dist/services/voice/phrase-cache.d.ts +76 -0
- package/dist/services/voice/phrase-cache.d.ts.map +1 -0
- package/dist/services/voice/phrase-chunker.d.ts +62 -0
- package/dist/services/voice/phrase-chunker.d.ts.map +1 -0
- package/dist/services/voice/pipeline-impls.d.ts +151 -0
- package/dist/services/voice/pipeline-impls.d.ts.map +1 -0
- package/dist/services/voice/pipeline.d.ts +216 -0
- package/dist/services/voice/pipeline.d.ts.map +1 -0
- package/dist/services/voice/prefill-client.d.ts +123 -0
- package/dist/services/voice/prefill-client.d.ts.map +1 -0
- package/dist/services/voice/prefix-preserving-queue.d.ts +113 -0
- package/dist/services/voice/prefix-preserving-queue.d.ts.map +1 -0
- package/dist/services/voice/profile-store.d.ts +248 -0
- package/dist/services/voice/profile-store.d.ts.map +1 -0
- package/dist/services/voice/ring-buffer.d.ts +40 -0
- package/dist/services/voice/ring-buffer.d.ts.map +1 -0
- package/dist/services/voice/rollback-queue.d.ts +24 -0
- package/dist/services/voice/rollback-queue.d.ts.map +1 -0
- package/dist/services/voice/samantha-preset-placeholder.d.ts +67 -0
- package/dist/services/voice/samantha-preset-placeholder.d.ts.map +1 -0
- package/dist/services/voice/samantha-preset-regenerator.d.ts +87 -0
- package/dist/services/voice/samantha-preset-regenerator.d.ts.map +1 -0
- package/dist/services/voice/scheduler.d.ts +146 -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/dist/services/voice/shared-resources.d.ts +204 -0
- package/dist/services/voice/shared-resources.d.ts.map +1 -0
- package/dist/services/voice/speaker/attribution-pipeline.d.ts +74 -0
- package/dist/services/voice/speaker/attribution-pipeline.d.ts.map +1 -0
- package/dist/services/voice/speaker/diarizer-fused.d.ts +59 -0
- package/dist/services/voice/speaker/diarizer-fused.d.ts.map +1 -0
- package/dist/services/voice/speaker/diarizer.d.ts +75 -0
- package/dist/services/voice/speaker/diarizer.d.ts.map +1 -0
- package/dist/services/voice/speaker/encoder-fused.d.ts +60 -0
- package/dist/services/voice/speaker/encoder-fused.d.ts.map +1 -0
- package/dist/services/voice/speaker/encoder-ggml.d.ts +33 -0
- package/dist/services/voice/speaker/encoder-ggml.d.ts.map +1 -0
- package/dist/services/voice/speaker/encoder.d.ts +37 -0
- package/dist/services/voice/speaker/encoder.d.ts.map +1 -0
- package/dist/services/voice/speaker-imprint.d.ts +83 -0
- package/dist/services/voice/speaker-imprint.d.ts.map +1 -0
- package/dist/services/voice/speaker-preset-cache.d.ts +77 -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 +73 -0
- package/dist/services/voice/system-audio-sink.d.ts.map +1 -0
- package/dist/services/voice/transcriber.d.ts +244 -0
- package/dist/services/voice/transcriber.d.ts.map +1 -0
- package/dist/services/voice/transcript-knowledge.d.ts +37 -0
- package/dist/services/voice/transcript-knowledge.d.ts.map +1 -0
- package/dist/services/voice/transcript-service.d.ts +60 -0
- package/dist/services/voice/transcript-service.d.ts.map +1 -0
- package/dist/services/voice/transcript-store.d.ts +64 -0
- package/dist/services/voice/transcript-store.d.ts.map +1 -0
- package/dist/services/voice/turn-controller.d.ts +183 -0
- package/dist/services/voice/turn-controller.d.ts.map +1 -0
- package/dist/services/voice/types.d.ts +643 -0
- package/dist/services/voice/types.d.ts.map +1 -0
- package/dist/services/voice/vad.d.ts +283 -0
- package/dist/services/voice/vad.d.ts.map +1 -0
- package/dist/services/voice/voice-budget.d.ts +241 -0
- package/dist/services/voice/voice-budget.d.ts.map +1 -0
- package/dist/services/voice/voice-emotion-classifier.d.ts +95 -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/dist/services/voice/voice-preset-format.d.ts +158 -0
- package/dist/services/voice/voice-preset-format.d.ts.map +1 -0
- package/dist/services/voice/voice-profile-artifact.d.ts +116 -0
- package/dist/services/voice/voice-profile-artifact.d.ts.map +1 -0
- package/dist/services/voice/voice-profile-routes.d.ts +83 -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 +364 -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/dist/services/voice/wake-word-ggml.d.ts +100 -0
- package/dist/services/voice/wake-word-ggml.d.ts.map +1 -0
- package/dist/services/voice/wake-word.d.ts +255 -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 +70 -0
- package/dist/services/voice/wrap-with-first-line-cache.d.ts.map +1 -0
- package/dist/services/voice-model-updater.d.ts +240 -0
- package/dist/services/voice-model-updater.d.ts.map +1 -0
- package/dist/services/voice-prewarm.d.ts +3 -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 +101 -15
- package/registry-entry.json +137 -0
- package/src/actions/generate-media.ts +647 -0
- package/src/actions/identify-speaker.ts +171 -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/__tests__/voice-turn.test.ts +293 -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 +831 -0
- package/src/adapters/capacitor-llama/loader.ts +109 -0
- package/src/adapters/capacitor-llama/native-voice-capture.ts +140 -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/adapters/capacitor-llama/voice-turn.ts +178 -0
- package/src/backends/apple-foundation.ts +127 -0
- package/src/index.ts +62 -0
- package/src/local-inference-routes.test.ts +390 -0
- package/src/local-inference-routes.ts +1625 -0
- package/src/provider.ts +1111 -0
- package/src/routes/compat-helpers.ts +275 -0
- package/src/routes/family-member-route.ts +353 -0
- package/src/routes/index.ts +61 -0
- package/src/routes/live-diarization-route.test.ts +347 -0
- package/src/routes/live-diarization-route.ts +198 -0
- package/src/routes/local-inference-asr-route.test.ts +246 -0
- package/src/routes/local-inference-asr-route.ts +166 -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.test.ts +485 -0
- package/src/routes/local-inference-compat-routes.ts +775 -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/native-pcm-turn-route.test.ts +136 -0
- package/src/routes/native-pcm-turn-route.ts +121 -0
- package/src/routes/transcript-audio-store.ts +27 -0
- package/src/routes/transcripts-routes.test.ts +195 -0
- package/src/routes/transcripts-routes.ts +191 -0
- package/src/routes/voice-first-run-routes.ts +524 -0
- package/src/routes/voice-models-routes.ts +554 -0
- package/src/routes/voice-profile-plugin-routes.ts +138 -0
- package/src/routes/voice-profiles-management-routes.ts +476 -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/bionic-wire-encoding.test.ts +147 -0
- package/src/runtime/capacitor-llama.d.ts +25 -0
- package/src/runtime/embedding-manager-support.ts +497 -0
- package/src/runtime/embedding-presets.ts +81 -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.test.ts +726 -0
- package/src/runtime/ensure-local-inference-handler.ts +1640 -0
- package/src/runtime/index.ts +36 -0
- package/src/runtime/mobile-local-inference-gate.test.ts +152 -0
- package/src/runtime/mobile-local-inference-gate.ts +99 -0
- package/src/runtime/voice-entity-binding.transcript.test.ts +98 -0
- package/src/runtime/voice-entity-binding.ts +368 -0
- package/src/runtime/voice-speaker-entity-contract.test.ts +149 -0
- package/src/services/README.md +71 -0
- package/src/services/__tests__/backend-selector.precedence.test.ts +333 -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-context-fit.test.ts +125 -0
- package/src/services/active-model-switch-rollback.test.ts +183 -0
- package/src/services/active-model.ts +1416 -0
- package/src/services/asr-provenance.ts +68 -0
- package/src/services/assignment-validation.test.ts +118 -0
- package/src/services/assignments.test.ts +106 -0
- package/src/services/assignments.ts +278 -0
- package/src/services/backend-selector.ts +95 -0
- package/src/services/backend.test.ts +84 -0
- package/src/services/backend.ts +791 -0
- package/src/services/bionic-host-loader.test.ts +226 -0
- package/src/services/bionic-host-loader.ts +252 -0
- package/src/services/bundled-models.ts +129 -0
- package/src/services/cache-bridge.test.ts +516 -0
- package/src/services/cache-bridge.ts +423 -0
- package/src/services/catalog.test.ts +259 -0
- package/src/services/catalog.ts +33 -0
- package/src/services/checkpoint-client.ts +258 -0
- package/src/services/checkpoint-manager.ts +474 -0
- package/src/services/cloud-fallback.ts +230 -0
- package/src/services/context-fit.test.ts +121 -0
- package/src/services/context-fit.ts +113 -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.ts +431 -0
- package/src/services/device-bridge.ts +1237 -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.test.ts +458 -0
- package/src/services/device-tier.ts +502 -0
- package/src/services/downloader.test.ts +888 -0
- package/src/services/downloader.ts +1039 -0
- package/src/services/engine-direct-bundle.test.ts +90 -0
- package/src/services/engine-streaming.test.ts +80 -0
- package/src/services/engine.ts +2096 -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.ts +312 -0
- package/src/services/ffi-llm-mock.ts +354 -0
- package/src/services/ffi-llm-streaming-abi.ts +445 -0
- package/src/services/ffi-streaming-backend.ts +418 -0
- package/src/services/ffi-streaming-runner.test.ts +220 -0
- package/src/services/ffi-streaming-runner.ts +407 -0
- package/src/services/ffi-unload-ordering.test.ts +166 -0
- package/src/services/fused-eliza1-no-regression.test.ts +144 -0
- package/src/services/gpu-autotune.ts +534 -0
- package/src/services/gpu-detect.ts +139 -0
- package/src/services/handler-registry.ts +240 -0
- package/src/services/hardware.test.ts +236 -0
- package/src/services/hardware.ts +438 -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.ts +229 -0
- package/src/services/imagegen/backend-selector.test.ts +190 -0
- package/src/services/imagegen/backend-selector.ts +277 -0
- package/src/services/imagegen/coreml-unavailable.ts +237 -0
- package/src/services/imagegen/errors.ts +40 -0
- package/src/services/imagegen/index.ts +144 -0
- package/src/services/imagegen/mflux.ts +313 -0
- package/src/services/imagegen/sd-cpp.ts +715 -0
- package/src/services/imagegen/tensorrt-unavailable.ts +295 -0
- package/src/services/imagegen/types.ts +193 -0
- package/src/services/index.ts +229 -0
- package/src/services/inference-capabilities.test.ts +75 -0
- package/src/services/inference-capabilities.ts +204 -0
- package/src/services/inference-telemetry.ts +143 -0
- package/src/services/ios-llama-streaming.ts +248 -0
- package/src/services/kv-spill.test.ts +222 -0
- package/src/services/kv-spill.ts +357 -0
- package/src/services/latency-trace.test.ts +266 -0
- package/src/services/latency-trace.ts +844 -0
- 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/llama-server-metrics.ts +304 -0
- package/src/services/llm-streaming-binding.ts +136 -0
- package/src/services/load-args.ts +81 -0
- package/src/services/manifest/eliza-1.manifest.v1.json +790 -0
- package/src/services/manifest/index.ts +72 -0
- package/src/services/manifest/manifest.test.ts +791 -0
- package/src/services/manifest/schema.ts +761 -0
- package/src/services/manifest/types.ts +61 -0
- package/src/services/manifest/validator.ts +633 -0
- package/src/services/memory-arbiter.test.ts +558 -0
- package/src/services/memory-arbiter.ts +991 -0
- package/src/services/memory-benchmark.test.ts +91 -0
- package/src/services/memory-benchmark.ts +354 -0
- package/src/services/memory-monitor.test.ts +232 -0
- package/src/services/memory-monitor.ts +309 -0
- package/src/services/memory-pressure.ts +414 -0
- package/src/services/mtp-doctor.ts +86 -0
- package/src/services/network-policy.ts +346 -0
- package/src/services/paths.ts +25 -0
- package/src/services/planner-skeleton.ts +175 -0
- package/src/services/providers.ts +507 -0
- package/src/services/ram-budget-cache.test.ts +164 -0
- package/src/services/ram-budget.ts +309 -0
- package/src/services/readiness.test.ts +87 -0
- package/src/services/readiness.ts +238 -0
- package/src/services/recommendation.test.ts +216 -0
- package/src/services/recommendation.ts +671 -0
- package/src/services/registry.ts +157 -0
- package/src/services/required-kernels-gate.test.ts +64 -0
- package/src/services/router-handler.test.ts +45 -0
- package/src/services/router-handler.ts +426 -0
- package/src/services/routing-policy.test.ts +352 -0
- package/src/services/routing-policy.ts +367 -0
- package/src/services/routing-preferences.ts +17 -0
- package/src/services/runtime-target.ts +154 -0
- package/src/services/service.test.ts +223 -0
- package/src/services/service.ts +750 -0
- package/src/services/session-pool.ts +153 -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.test.ts +483 -0
- package/src/services/structured-output.ts +712 -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.ts +59 -0
- package/src/services/verify-on-device.test.ts +87 -0
- package/src/services/verify-on-device.ts +127 -0
- package/src/services/verify.ts +13 -0
- package/src/services/vision/aosp-unavailable.ts +163 -0
- package/src/services/vision/capacitor-llama.ts +255 -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.ts +157 -0
- package/src/services/vision/index.ts +251 -0
- package/src/services/vision/llama-server.ts +177 -0
- package/src/services/vision/types.ts +163 -0
- package/src/services/vision/vast-fallback.ts +127 -0
- package/src/services/vision-embedding-cache.ts +189 -0
- package/src/services/voice/VOICE_WORKBENCH.md +133 -0
- package/src/services/voice/__fixtures__/voice-workbench-logic-baseline.json +180 -0
- package/src/services/voice/__test-helpers__/fake-ffi.ts +94 -0
- package/src/services/voice/__test-helpers__/synthetic-speech.ts +194 -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/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 +139 -0
- package/src/services/voice/audio-frame-consumer.test.ts +669 -0
- package/src/services/voice/audio-frame-consumer.ts +651 -0
- package/src/services/voice/barge-in.test.ts +244 -0
- package/src/services/voice/barge-in.ts +335 -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.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/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 +182 -0
- package/src/services/voice/e2e-harness.ts +902 -0
- package/src/services/voice/eager-context-builder.ts +262 -0
- 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 +242 -0
- package/src/services/voice/embedding-server.ts +200 -0
- package/src/services/voice/embedding.test.ts +131 -0
- package/src/services/voice/embedding.ts +242 -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-transcript-join.test.ts +278 -0
- package/src/services/voice/engine-bridge.test.ts +384 -0
- package/src/services/voice/engine-bridge.ts +2343 -0
- package/src/services/voice/eot-classifier-ggml.ts +569 -0
- package/src/services/voice/eot-classifier.test.ts +98 -0
- package/src/services/voice/eot-classifier.ts +422 -0
- package/src/services/voice/errors.ts +34 -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 +405 -0
- package/src/services/voice/ffi-bindings.test.ts +735 -0
- package/src/services/voice/ffi-bindings.ts +3387 -0
- package/src/services/voice/first-line-cache.ts +725 -0
- package/src/services/voice/fused-eot-scorer.ts +139 -0
- package/src/services/voice/index.ts +502 -0
- package/src/services/voice/kokoro/__tests__/kokoro-backend.test.ts +262 -0
- package/src/services/voice/kokoro/__tests__/kokoro-engine-bridge.real.test.ts +236 -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 +67 -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.ts +223 -0
- package/src/services/voice/kokoro/kokoro-engine-discovery.ts +177 -0
- package/src/services/voice/kokoro/kokoro-ffi-runtime.ts +233 -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.ts +344 -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.ts +64 -0
- package/src/services/voice/kokoro/types.ts +95 -0
- package/src/services/voice/kokoro/voice-presets.ts +129 -0
- package/src/services/voice/kokoro/voices.ts +64 -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.echo.test.ts +232 -0
- package/src/services/voice/live-diarization-session.ts +622 -0
- 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.test.ts +210 -0
- package/src/services/voice/mic-source.ts +503 -0
- 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/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.test.ts +68 -0
- package/src/services/voice/partial-stabilizer.ts +140 -0
- package/src/services/voice/phoneme-tokenizer.ts +158 -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.test.ts +239 -0
- package/src/services/voice/phrase-chunker.ts +281 -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.ts +504 -0
- package/src/services/voice/prefill-client.ts +316 -0
- package/src/services/voice/prefix-preserving-queue.ts +162 -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/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/ring-buffer.test.ts +129 -0
- package/src/services/voice/ring-buffer.ts +123 -0
- package/src/services/voice/rollback-queue.ts +74 -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.ts +393 -0
- package/src/services/voice/samantha-preset-regenerator.wav.test.ts +90 -0
- package/src/services/voice/scheduler.t2.test.ts +141 -0
- package/src/services/voice/scheduler.ts +927 -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 +343 -0
- package/src/services/voice/speaker/attribution-pipeline.test.ts +221 -0
- package/src/services/voice/speaker/attribution-pipeline.ts +449 -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.ts +218 -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.test.ts +59 -0
- package/src/services/voice/speaker/encoder-ggml.ts +79 -0
- package/src/services/voice/speaker/encoder.ts +105 -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.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.test.ts +29 -0
- package/src/services/voice/system-audio-sink.ts +366 -0
- package/src/services/voice/transcriber.asr-backend.test.ts +76 -0
- package/src/services/voice/transcriber.test.ts +392 -0
- package/src/services/voice/transcriber.ts +704 -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.test.ts +195 -0
- package/src/services/voice/transcript-service.ts +205 -0
- package/src/services/voice/transcript-store.test.ts +189 -0
- package/src/services/voice/transcript-store.ts +164 -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.ts +699 -0
- package/src/services/voice/vad.test.ts +498 -0
- package/src/services/voice/vad.ts +832 -0
- package/src/services/voice/vad.v1-v4.test.ts +222 -0
- package/src/services/voice/voice-budget.test.ts +415 -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.test.ts +210 -0
- package/src/services/voice/voice-emotion-classifier.ts +273 -0
- 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 +713 -0
- package/src/services/voice/voice-preset-generator.test.ts +89 -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.test.ts +429 -0
- package/src/services/voice/voice-profile-routes.ts +425 -0
- package/src/services/voice/voice-scenario.test.ts +159 -0
- package/src/services/voice/voice-scenario.ts +280 -0
- package/src/services/voice/voice-scenario.turn-helpers.test.ts +77 -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 +367 -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.ts +319 -0
- package/src/services/voice/wake-word.test.ts +298 -0
- package/src/services/voice/wake-word.ts +554 -0
- 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/wrap-with-first-line-cache.ts +267 -0
- package/src/services/voice-model-updater.ts +724 -0
- package/src/services/voice-prewarm.ts +51 -0
- package/src/voice-workbench.ts +71 -0
|
@@ -0,0 +1,622 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live on-device diarization session — the agent-process owner of an
|
|
3
|
+
* {@link AudioFrameConsumer} wired to the REAL fused VAD / encoder / diarizer /
|
|
4
|
+
* attribution stack.
|
|
5
|
+
*
|
|
6
|
+
* The Android `audioFrame` PCM stream is produced in the Capacitor WebView
|
|
7
|
+
* (JS renderer) but the voice FFI runs in the embedded bun agent process. The
|
|
8
|
+
* agent's `/api/voice/audio-frames` route pumps batched frames into the single
|
|
9
|
+
* session this module owns, where the consumer segments turns, runs
|
|
10
|
+
* diarization + speaker attribution, and emits VOICE_TURN_OBSERVED.
|
|
11
|
+
*
|
|
12
|
+
* This module is the agent-side mirror of the host smoke harness
|
|
13
|
+
* (`packages/app-core/scripts/voice-attribution-smoke.ts`): same real models,
|
|
14
|
+
* same consumer, fed live frames over HTTP instead of a WAV.
|
|
15
|
+
*
|
|
16
|
+
* Single fused engine: VAD, the WeSpeaker speaker encoder, and the pyannote
|
|
17
|
+
* diarizer all run through the ONE fused `libelizainference` handle via its
|
|
18
|
+
* `eliza_inference_vad_*` / `_speaker_*` / `_diariz_*` ABI (the user directive:
|
|
19
|
+
* no separate bun:ffi-musl libs). Resolution:
|
|
20
|
+
* - fused lib: `$ELIZA_INFERENCE_LIBRARY` (exact) or `$ELIZA_INFERENCE_LIB_DIR`
|
|
21
|
+
* (dir) — both exported by ElizaAgentService on Android to the app
|
|
22
|
+
* nativeLibraryDir.
|
|
23
|
+
* - context bundle root: `$ELIZA_VOICE_MODEL_DIR` (the same dir the GGUFs
|
|
24
|
+
* live under); the fused runtime resolves the per-model GGUFs from there.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import { existsSync } from "node:fs";
|
|
28
|
+
import path from "node:path";
|
|
29
|
+
import { resolveStateDir } from "@elizaos/core";
|
|
30
|
+
import {
|
|
31
|
+
type AttributedTurn,
|
|
32
|
+
type AttributionPipelineLike,
|
|
33
|
+
AudioFrameConsumer,
|
|
34
|
+
type AudioFrameConsumerConfig,
|
|
35
|
+
type AudioFrameConsumerDeps,
|
|
36
|
+
type AudioFrameEvent,
|
|
37
|
+
decodeAudioFramePcm,
|
|
38
|
+
type EchoReferenceProvider,
|
|
39
|
+
type RuntimeEventSink,
|
|
40
|
+
type TurnTranscriber,
|
|
41
|
+
type VadSegmenter,
|
|
42
|
+
} from "./audio-frame-consumer.js";
|
|
43
|
+
import {
|
|
44
|
+
estimateEchoDelaySamples,
|
|
45
|
+
platformPlaybackDelaySamples,
|
|
46
|
+
} from "./echo-delay.js";
|
|
47
|
+
import { EchoReferenceBuffer } from "./echo-reference-buffer.js";
|
|
48
|
+
import type {
|
|
49
|
+
ElizaInferenceContextHandle,
|
|
50
|
+
ElizaInferenceFfi,
|
|
51
|
+
} from "./ffi-bindings.js";
|
|
52
|
+
import { loadElizaInferenceFfi } from "./ffi-bindings.js";
|
|
53
|
+
import { VoiceProfileStore } from "./profile-store.js";
|
|
54
|
+
import { VoiceAttributionPipeline } from "./speaker/attribution-pipeline.js";
|
|
55
|
+
import { FusedDiarizer } from "./speaker/diarizer-fused.js";
|
|
56
|
+
import { FusedSpeakerEncoder } from "./speaker/encoder-fused.js";
|
|
57
|
+
import { GgmlSileroVad, VadDetector } from "./vad.js";
|
|
58
|
+
|
|
59
|
+
export type { RuntimeEventSink } from "./audio-frame-consumer.js";
|
|
60
|
+
|
|
61
|
+
/** Resolve the on-device voice-model directory (env override wins). Doubles as
|
|
62
|
+
* the fused context bundle root — the runtime resolves per-model GGUFs from it. */
|
|
63
|
+
function voiceModelDir(): string {
|
|
64
|
+
const override = process.env.ELIZA_VOICE_MODEL_DIR?.trim();
|
|
65
|
+
if (override) return override;
|
|
66
|
+
return path.join(resolveStateDir(process.env), "models", "voice");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Candidate filenames for the fused library on this platform. */
|
|
70
|
+
function fusedLibraryFilenames(): string[] {
|
|
71
|
+
if (process.platform === "darwin") return ["libelizainference.dylib"];
|
|
72
|
+
if (process.platform === "win32") {
|
|
73
|
+
return ["elizainference.dll", "libelizainference.dll"];
|
|
74
|
+
}
|
|
75
|
+
return ["libelizainference.so"];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Resolve the fused `libelizainference` path from the environment. Returns
|
|
80
|
+
* `null` when neither an exact path nor a containing dir yields a file —
|
|
81
|
+
* the session then surfaces that as a structured build error.
|
|
82
|
+
*/
|
|
83
|
+
function resolveFusedLibrary(): string | null {
|
|
84
|
+
const exact = process.env.ELIZA_INFERENCE_LIBRARY?.trim();
|
|
85
|
+
if (exact && existsSync(exact)) return exact;
|
|
86
|
+
const dir = process.env.ELIZA_INFERENCE_LIB_DIR?.trim();
|
|
87
|
+
if (dir) {
|
|
88
|
+
for (const name of fusedLibraryFilenames()) {
|
|
89
|
+
const candidate = path.join(dir, name);
|
|
90
|
+
if (existsSync(candidate)) return candidate;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface LiveDiarizationStatus {
|
|
97
|
+
/** True once the consumer + real fused deps are loaded and accepting frames. */
|
|
98
|
+
ready: boolean;
|
|
99
|
+
/** Resolved fused-library path (null when it could not be resolved). */
|
|
100
|
+
libs: {
|
|
101
|
+
fusedInference: string | null;
|
|
102
|
+
};
|
|
103
|
+
/** Resolved context-bundle dir for the fused runtime. */
|
|
104
|
+
models: {
|
|
105
|
+
dir: string;
|
|
106
|
+
};
|
|
107
|
+
/** Frames received from the WebView across this session. */
|
|
108
|
+
framesReceived: number;
|
|
109
|
+
/** Frames dropped at the decode boundary. */
|
|
110
|
+
framesDropped: number;
|
|
111
|
+
/** Turns segmented + attributed so far. */
|
|
112
|
+
turnsObserved: number;
|
|
113
|
+
/** Live AEC wiring status. Echo cancellation runs only when this is true. */
|
|
114
|
+
aec: {
|
|
115
|
+
echoReferenceWired: boolean;
|
|
116
|
+
/** Playback→mic delay (samples @16 kHz) currently applied to align the
|
|
117
|
+
* far-end reference — self-calibrated from real echo when confident,
|
|
118
|
+
* otherwise the `ELIZA_VOICE_ECHO_DELAY_MS` seed (default 0). */
|
|
119
|
+
echoDelaySamples: number;
|
|
120
|
+
/** Peak cross-correlation [0,1] of the last accepted delay calibration;
|
|
121
|
+
* 0 until a confident estimate replaces the seed. */
|
|
122
|
+
echoDelayConfidence: number;
|
|
123
|
+
};
|
|
124
|
+
/** The most recent attributed turns (capped), for device-evidence reads. */
|
|
125
|
+
recentTurns: LiveDiarizationTurnSummary[];
|
|
126
|
+
/** Populated only when readiness failed — the precise blocker. */
|
|
127
|
+
error?: string;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** A compact, JSON-safe summary of one attributed turn (no PCM/embeddings). */
|
|
131
|
+
export interface LiveDiarizationTurnSummary {
|
|
132
|
+
turnId: string;
|
|
133
|
+
startedAtMs: number;
|
|
134
|
+
endedAtMs: number;
|
|
135
|
+
samples: number;
|
|
136
|
+
durationMs: number;
|
|
137
|
+
hasSpeaker: boolean;
|
|
138
|
+
speakerEntityId: string | null;
|
|
139
|
+
speakerConfidence: number | null;
|
|
140
|
+
segments: number;
|
|
141
|
+
agentShouldSpeak: boolean | null;
|
|
142
|
+
nextSpeaker: string | null;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const MAX_RECENT_TURNS = 20;
|
|
146
|
+
|
|
147
|
+
export interface LiveDiarizationSessionOptions {
|
|
148
|
+
/**
|
|
149
|
+
* Agent-playback PCM provider for AEC. The caller owns playback capture and
|
|
150
|
+
* delay calibration when supplied. Without an external provider, the session
|
|
151
|
+
* uses its built-in playback buffer fed by /api/voice/playback-frames.
|
|
152
|
+
*/
|
|
153
|
+
echoReference?: EchoReferenceProvider | null;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export interface LiveDiarizationConsumerDepsInput {
|
|
157
|
+
vad: VadSegmenter;
|
|
158
|
+
pipeline: AttributionPipelineLike;
|
|
159
|
+
runtime: RuntimeEventSink;
|
|
160
|
+
transcribe?: TurnTranscriber | null;
|
|
161
|
+
echoReference?: EchoReferenceProvider | null;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export function buildLiveDiarizationConsumerDeps({
|
|
165
|
+
vad,
|
|
166
|
+
pipeline,
|
|
167
|
+
runtime,
|
|
168
|
+
transcribe,
|
|
169
|
+
echoReference,
|
|
170
|
+
}: LiveDiarizationConsumerDepsInput): AudioFrameConsumerDeps {
|
|
171
|
+
return {
|
|
172
|
+
vad,
|
|
173
|
+
pipeline,
|
|
174
|
+
runtime,
|
|
175
|
+
...(transcribe ? { transcribe } : {}),
|
|
176
|
+
...(echoReference ? { echoReference } : {}),
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const AUDIO_FRAME_SAMPLE_RATE = 16_000;
|
|
181
|
+
|
|
182
|
+
/** Echo-delay self-calibration (#9583/#9586). */
|
|
183
|
+
/** Accumulate this many playback-active samples before estimating the delay
|
|
184
|
+
* (~0.75 s @16 kHz — enough correlated echo for a stable cross-correlation). */
|
|
185
|
+
const ECHO_CAL_TARGET_SAMPLES = 12_000;
|
|
186
|
+
/** Bound the rolling calibration window so a long talk-over doesn't grow it. */
|
|
187
|
+
const ECHO_CAL_MAX_SAMPLES = 24_000;
|
|
188
|
+
/** Accept a calibrated delay only above this normalized cross-correlation; below
|
|
189
|
+
* it the near/far are independent (user talking, no echo) — keep the seed. */
|
|
190
|
+
const ECHO_CAL_MIN_CONFIDENCE = 0.3;
|
|
191
|
+
/** Largest playback→mic delay to search (300 ms @16 kHz). */
|
|
192
|
+
const ECHO_CAL_MAX_LAG_SAMPLES = 4_800;
|
|
193
|
+
/** Far-end mean-square floor below which a frame is "no playback" (skip). */
|
|
194
|
+
const ECHO_CAL_FAR_ENERGY_FLOOR = 1e-7;
|
|
195
|
+
|
|
196
|
+
function concatFloat32(chunks: Float32Array[]): Float32Array {
|
|
197
|
+
let total = 0;
|
|
198
|
+
for (const c of chunks) total += c.length;
|
|
199
|
+
const out = new Float32Array(total);
|
|
200
|
+
let off = 0;
|
|
201
|
+
for (const c of chunks) {
|
|
202
|
+
out.set(c, off);
|
|
203
|
+
off += c.length;
|
|
204
|
+
}
|
|
205
|
+
return out;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Playback→mic transport delay used to time-align the far-end echo reference,
|
|
210
|
+
* in samples @ 16 kHz. Device-tunable via `ELIZA_VOICE_ECHO_DELAY_MS`:
|
|
211
|
+
* - a positive number → that many milliseconds, exactly;
|
|
212
|
+
* - the literal `"auto"` → seed from a per-platform default
|
|
213
|
+
* (`platformPlaybackDelaySamples`, #9583), useful on iOS/macOS where the
|
|
214
|
+
* CoreAudio / AVAudioEngine transport delay is small but non-zero;
|
|
215
|
+
* - unset / anything else → 0 (the default — the canceller aligns to the
|
|
216
|
+
* most-recently-rendered playback and the NLMS filter adapts the residual).
|
|
217
|
+
*
|
|
218
|
+
* Either way the on-device calibration (`estimateEchoDelaySamples`, #9586)
|
|
219
|
+
* refines this seed at runtime once enough correlated echo is observed.
|
|
220
|
+
*/
|
|
221
|
+
function resolveEchoDelaySamples(): number {
|
|
222
|
+
const raw = process.env.ELIZA_VOICE_ECHO_DELAY_MS;
|
|
223
|
+
if (raw && raw.trim().toLowerCase() === "auto") {
|
|
224
|
+
// Resolve the platform id the way the rest of this plugin does
|
|
225
|
+
// (service.ts / backend-selector.ts): the mobile shells report
|
|
226
|
+
// `ELIZA_PLATFORM=ios|android`, where `process.platform` is `darwin`/
|
|
227
|
+
// `linux`. Using the resolved id makes the iOS (25 ms) / AOSP-Android
|
|
228
|
+
// (45 ms) seeds in the #9653 table reachable on device instead of
|
|
229
|
+
// collapsing to the host's darwin (20 ms) / linux (30 ms) seed.
|
|
230
|
+
const platformId =
|
|
231
|
+
process.env.ELIZA_PLATFORM === "ios"
|
|
232
|
+
? "ios"
|
|
233
|
+
: process.env.ELIZA_PLATFORM === "android"
|
|
234
|
+
? "android"
|
|
235
|
+
: process.platform;
|
|
236
|
+
return platformPlaybackDelaySamples(platformId, AUDIO_FRAME_SAMPLE_RATE);
|
|
237
|
+
}
|
|
238
|
+
const ms = Number(raw);
|
|
239
|
+
if (!Number.isFinite(ms) || ms <= 0) return 0;
|
|
240
|
+
return Math.round((ms / 1000) * AUDIO_FRAME_SAMPLE_RATE);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Opt-in residual-echo suppressor, off by default (#9583/#9649). Device-tunable
|
|
245
|
+
* via `ELIZA_VOICE_RESIDUAL_SUPPRESSION`:
|
|
246
|
+
* - `"1"` / `"true"` / `"on"` → enable with the canceller's default gain;
|
|
247
|
+
* - a number in (0,1] → enable with that residual gain (lower = stronger);
|
|
248
|
+
* - unset / anything else → disabled (the canceller does linear NLMS only).
|
|
249
|
+
* Left off until validated with real device audio, per #9649 item 2.
|
|
250
|
+
*/
|
|
251
|
+
function resolveResidualSuppression(): boolean | { gain: number } | undefined {
|
|
252
|
+
const raw =
|
|
253
|
+
process.env.ELIZA_VOICE_RESIDUAL_SUPPRESSION?.trim().toLowerCase();
|
|
254
|
+
if (!raw) return undefined;
|
|
255
|
+
if (raw === "1" || raw === "true" || raw === "on") return true;
|
|
256
|
+
const gain = Number(raw);
|
|
257
|
+
if (Number.isFinite(gain) && gain > 0 && gain <= 1) return { gain };
|
|
258
|
+
return undefined;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Owns the single live diarization consumer for the agent process. Built
|
|
263
|
+
* lazily on first frame batch so it does not load voice models at boot.
|
|
264
|
+
*/
|
|
265
|
+
export class LiveDiarizationSession {
|
|
266
|
+
private consumer: AudioFrameConsumer | null = null;
|
|
267
|
+
private ffi: ElizaInferenceFfi | null = null;
|
|
268
|
+
private ctx: ElizaInferenceContextHandle | null = null;
|
|
269
|
+
private encoder: FusedSpeakerEncoder | null = null;
|
|
270
|
+
private diarizer: FusedDiarizer | null = null;
|
|
271
|
+
private vad: GgmlSileroVad | null = null;
|
|
272
|
+
private building: Promise<void> | null = null;
|
|
273
|
+
private framesReceived = 0;
|
|
274
|
+
private turnsObserved = 0;
|
|
275
|
+
private readonly recentTurns: LiveDiarizationTurnSummary[] = [];
|
|
276
|
+
private resolvedLibPath: string | null = null;
|
|
277
|
+
private buildError: string | null = null;
|
|
278
|
+
/** True once the fused ASR region is mmap-acquired for per-turn transcribe. */
|
|
279
|
+
private asrRegionAcquired = false;
|
|
280
|
+
/**
|
|
281
|
+
* Far-end (agent TTS playback) alignment buffer for echo cancellation
|
|
282
|
+
* (#9583/#9455). Fed by {@link pushPlayback}; read per mic frame via the
|
|
283
|
+
* consumer's `echoReference` seam. Inert (zero far-end ⇒ NLMS passthrough)
|
|
284
|
+
* until the device streams playback, so wiring it never regresses the
|
|
285
|
+
* no-playback case.
|
|
286
|
+
*/
|
|
287
|
+
private readonly echoBuffer = new EchoReferenceBuffer();
|
|
288
|
+
/**
|
|
289
|
+
* Playback→mic delay applied when reading the far-end reference. Seeded from
|
|
290
|
+
* `ELIZA_VOICE_ECHO_DELAY_MS` (default 0) and then SELF-CALIBRATED on the live
|
|
291
|
+
* path: once enough playback-active echo is observed, `estimateEchoDelaySamples`
|
|
292
|
+
* (#9586) recovers the bulk transport lag by cross-correlation and replaces the
|
|
293
|
+
* seed (#9583). Mutable for that reason.
|
|
294
|
+
*/
|
|
295
|
+
private echoDelaySamples = resolveEchoDelaySamples();
|
|
296
|
+
private echoDelayConfidence = 0;
|
|
297
|
+
private echoDelayCalibrated = false;
|
|
298
|
+
/** Rolling near/far windows accumulated only while the far-end is active, used
|
|
299
|
+
* once to estimate the playback→mic delay. Cleared after a confident estimate
|
|
300
|
+
* and on {@link resetPlayback}. */
|
|
301
|
+
private calNear: Float32Array[] = [];
|
|
302
|
+
private calFar: Float32Array[] = [];
|
|
303
|
+
private calSampleCount = 0;
|
|
304
|
+
|
|
305
|
+
constructor(
|
|
306
|
+
private readonly runtime: RuntimeEventSink,
|
|
307
|
+
private readonly options: LiveDiarizationSessionOptions = {},
|
|
308
|
+
) {}
|
|
309
|
+
|
|
310
|
+
/** Ensure the real-deps consumer exists; idempotent + concurrency-safe. */
|
|
311
|
+
private ensureBuilt(): Promise<void> {
|
|
312
|
+
if (this.consumer) return Promise.resolve();
|
|
313
|
+
if (this.building) return this.building;
|
|
314
|
+
this.building = this.build().catch((err) => {
|
|
315
|
+
this.buildError = err instanceof Error ? err.message : String(err);
|
|
316
|
+
throw err;
|
|
317
|
+
});
|
|
318
|
+
return this.building;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
private async build(): Promise<void> {
|
|
322
|
+
const dir = voiceModelDir();
|
|
323
|
+
const libPath = resolveFusedLibrary();
|
|
324
|
+
if (!libPath) {
|
|
325
|
+
throw new Error(
|
|
326
|
+
`fused libelizainference not found on device. Set $ELIZA_INFERENCE_LIBRARY (exact path) or $ELIZA_INFERENCE_LIB_DIR (containing one of ${fusedLibraryFilenames().join(", ")}).`,
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
this.resolvedLibPath = libPath;
|
|
330
|
+
const ffi = loadElizaInferenceFfi(libPath);
|
|
331
|
+
this.ffi = ffi;
|
|
332
|
+
// One context anchored at the voice-model dir; the fused runtime resolves
|
|
333
|
+
// the VAD / speaker / diarizer GGUFs from it.
|
|
334
|
+
const ctx = ffi.create(dir);
|
|
335
|
+
this.ctx = ctx;
|
|
336
|
+
|
|
337
|
+
if (!GgmlSileroVad.isSupported(ffi)) {
|
|
338
|
+
throw new Error(
|
|
339
|
+
"fused libelizainference does not export the VAD ABI (eliza_inference_vad_supported() == 0). Rebuild with the fused voice runtime linked in.",
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
if (!FusedSpeakerEncoder.isSupported(ffi)) {
|
|
343
|
+
throw new Error(
|
|
344
|
+
"fused libelizainference does not export the speaker ABI (eliza_inference_speaker_supported() == 0).",
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
if (!FusedDiarizer.isSupported(ffi)) {
|
|
348
|
+
throw new Error(
|
|
349
|
+
"fused libelizainference does not export the diarizer ABI (eliza_inference_diariz_supported() == 0).",
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const vad = await GgmlSileroVad.load({ ffi, ctx });
|
|
354
|
+
this.vad = vad;
|
|
355
|
+
const detector = new VadDetector(vad, {
|
|
356
|
+
onsetThreshold: 0.5,
|
|
357
|
+
pauseHangoverMs: 120,
|
|
358
|
+
endHangoverMs: 500,
|
|
359
|
+
minSpeechMs: 250,
|
|
360
|
+
});
|
|
361
|
+
const encoder = await FusedSpeakerEncoder.load({ ffi, ctx });
|
|
362
|
+
this.encoder = encoder;
|
|
363
|
+
const diarizer = await FusedDiarizer.load({ ffi, ctx });
|
|
364
|
+
this.diarizer = diarizer;
|
|
365
|
+
const store = new VoiceProfileStore({
|
|
366
|
+
rootDir: path.join(resolveStateDir(process.env), "voice-profiles"),
|
|
367
|
+
});
|
|
368
|
+
await store.init();
|
|
369
|
+
|
|
370
|
+
const pipeline = new VoiceAttributionPipeline({
|
|
371
|
+
encoder,
|
|
372
|
+
diarizer,
|
|
373
|
+
profileStore: store,
|
|
374
|
+
});
|
|
375
|
+
const residualSuppression = resolveResidualSuppression();
|
|
376
|
+
const config: AudioFrameConsumerConfig = {
|
|
377
|
+
source: { kind: "local_mic", deviceId: "android-audioframe" },
|
|
378
|
+
preRollSeconds: 0.3,
|
|
379
|
+
maxTurnSeconds: 30,
|
|
380
|
+
...(residualSuppression ? { residualSuppression } : {}),
|
|
381
|
+
};
|
|
382
|
+
// Join the fused batch ASR so the live path carries the real transcript
|
|
383
|
+
// on VOICE_TURN_OBSERVED (#8786). Null when the fused build has no ASR
|
|
384
|
+
// decoder — the path then stays diarization-only, as before.
|
|
385
|
+
const transcribe = this.buildTurnTranscriber(ffi, ctx);
|
|
386
|
+
const consumer = new AudioFrameConsumer(
|
|
387
|
+
buildLiveDiarizationConsumerDeps({
|
|
388
|
+
vad: detector,
|
|
389
|
+
pipeline,
|
|
390
|
+
runtime: this.runtime,
|
|
391
|
+
transcribe,
|
|
392
|
+
// Cancel the agent's own TTS playback before VAD/attribution so the
|
|
393
|
+
// live path never transcribes its echo (#9455/#9583). Hosts may
|
|
394
|
+
// provide their own live reference; otherwise the session uses the
|
|
395
|
+
// built-in playback buffer fed by pushPlayback.
|
|
396
|
+
echoReference:
|
|
397
|
+
this.options.echoReference ??
|
|
398
|
+
((timestampMs, samples) =>
|
|
399
|
+
this.echoReferenceFrame(timestampMs, samples)),
|
|
400
|
+
}),
|
|
401
|
+
config,
|
|
402
|
+
);
|
|
403
|
+
consumer.onTurn((turn) => this.recordTurn(turn));
|
|
404
|
+
this.consumer = consumer;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Build a per-turn ASR transcriber over the fused batch decoder
|
|
409
|
+
* (`eliza_inference_asr_transcribe`). Returns null when the fused build
|
|
410
|
+
* exposes no ASR decoder; acquiring the ASR mmap region is best-effort (a
|
|
411
|
+
* missing bundled ASR model leaves the path diarization-only rather than
|
|
412
|
+
* failing the whole session). One batch decode per finalized turn — the turn
|
|
413
|
+
* is already fully buffered for attribution, so no streaming state is needed.
|
|
414
|
+
*/
|
|
415
|
+
private buildTurnTranscriber(
|
|
416
|
+
ffi: ElizaInferenceFfi,
|
|
417
|
+
ctx: ElizaInferenceContextHandle,
|
|
418
|
+
): TurnTranscriber | null {
|
|
419
|
+
if (typeof ffi.asrTranscribe !== "function") return null;
|
|
420
|
+
try {
|
|
421
|
+
ffi.mmapAcquire(ctx, "asr");
|
|
422
|
+
} catch {
|
|
423
|
+
return null;
|
|
424
|
+
}
|
|
425
|
+
this.asrRegionAcquired = true;
|
|
426
|
+
return (pcm) => {
|
|
427
|
+
const text = ffi.asrTranscribe({ ctx, pcm, sampleRateHz: 16_000 });
|
|
428
|
+
const trimmed = text.trim();
|
|
429
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
private recordTurn(turn: AttributedTurn): void {
|
|
434
|
+
this.turnsObserved += 1;
|
|
435
|
+
const speaker = turn.output.primarySpeaker;
|
|
436
|
+
const summary: LiveDiarizationTurnSummary = {
|
|
437
|
+
turnId: turn.turnId,
|
|
438
|
+
startedAtMs: turn.startedAtMs,
|
|
439
|
+
endedAtMs: turn.endedAtMs,
|
|
440
|
+
samples: turn.samples,
|
|
441
|
+
durationMs: Math.round((turn.samples / 16_000) * 1000),
|
|
442
|
+
hasSpeaker: speaker != null,
|
|
443
|
+
speakerEntityId: speaker?.entityId ?? null,
|
|
444
|
+
speakerConfidence: speaker?.confidence ?? null,
|
|
445
|
+
segments: turn.output.segments.length,
|
|
446
|
+
agentShouldSpeak: turn.signal.agentShouldSpeak,
|
|
447
|
+
nextSpeaker: turn.signal.nextSpeaker ?? null,
|
|
448
|
+
};
|
|
449
|
+
this.recentTurns.push(summary);
|
|
450
|
+
if (this.recentTurns.length > MAX_RECENT_TURNS) this.recentTurns.shift();
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* The far-end (agent TTS playback) reference aligned to a mic frame of
|
|
455
|
+
* `samples` samples — the consumer's `echoReference` seam (#9455/#9583).
|
|
456
|
+
* Reads the alignment buffer at the configured playback→mic delay; the slice
|
|
457
|
+
* is zero-filled (⇒ NLMS passthrough) until the device streams playback.
|
|
458
|
+
* Public so the wiring is unit-testable without the fused FFI.
|
|
459
|
+
*/
|
|
460
|
+
echoReferenceFrame(timestampMs: number, samples: number): Float32Array {
|
|
461
|
+
return this.echoBuffer.referenceAt(
|
|
462
|
+
timestampMs,
|
|
463
|
+
samples,
|
|
464
|
+
this.echoDelaySamples,
|
|
465
|
+
);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/** Current self-calibrated AEC delay state (for status + tests). */
|
|
469
|
+
aecDelayState(): {
|
|
470
|
+
delaySamples: number;
|
|
471
|
+
confidence: number;
|
|
472
|
+
calibrated: boolean;
|
|
473
|
+
} {
|
|
474
|
+
return {
|
|
475
|
+
delaySamples: this.echoDelaySamples,
|
|
476
|
+
confidence: this.echoDelayConfidence,
|
|
477
|
+
calibrated: this.echoDelayCalibrated,
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Self-calibrate the playback→mic delay (#9583/#9586) from real echo. Called
|
|
483
|
+
* per mic frame while uncalibrated: when the far-end is active (the agent is
|
|
484
|
+
* playing TTS), accumulate the time-aligned near/far windows; once ~0.75 s of
|
|
485
|
+
* playback-active audio is buffered, recover the bulk transport lag by
|
|
486
|
+
* cross-correlation and, if confident, replace the static seed. One-shot — the
|
|
487
|
+
* device's speaker→mic path is stable, so we lock the first confident estimate
|
|
488
|
+
* and stop re-measuring. Public so it can be unit-tested without the fused FFI.
|
|
489
|
+
*/
|
|
490
|
+
observeForDelayCalibration(nearPcm: Float32Array, timestampMs: number): void {
|
|
491
|
+
if (this.echoDelayCalibrated || nearPcm.length === 0) return;
|
|
492
|
+
// Read the RAW far-end at this frame (delay 0) — calibration recovers the
|
|
493
|
+
// delay, so it must not pre-apply the value it is trying to measure.
|
|
494
|
+
const far = this.echoBuffer.referenceAt(timestampMs, nearPcm.length, 0);
|
|
495
|
+
let farEnergy = 0;
|
|
496
|
+
for (let i = 0; i < far.length; i++) farEnergy += far[i] * far[i];
|
|
497
|
+
if (farEnergy / Math.max(1, far.length) < ECHO_CAL_FAR_ENERGY_FLOOR) {
|
|
498
|
+
return; // no playback → nothing to calibrate against
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
this.calNear.push(nearPcm.slice());
|
|
502
|
+
this.calFar.push(far);
|
|
503
|
+
this.calSampleCount += nearPcm.length;
|
|
504
|
+
while (
|
|
505
|
+
this.calSampleCount > ECHO_CAL_MAX_SAMPLES &&
|
|
506
|
+
this.calNear.length > 1
|
|
507
|
+
) {
|
|
508
|
+
this.calSampleCount -= (this.calNear.shift() as Float32Array).length;
|
|
509
|
+
this.calFar.shift();
|
|
510
|
+
}
|
|
511
|
+
if (this.calSampleCount < ECHO_CAL_TARGET_SAMPLES) return;
|
|
512
|
+
|
|
513
|
+
const near = concatFloat32(this.calNear);
|
|
514
|
+
const farWin = concatFloat32(this.calFar);
|
|
515
|
+
const est = estimateEchoDelaySamples(near, farWin, {
|
|
516
|
+
maxLagSamples: ECHO_CAL_MAX_LAG_SAMPLES,
|
|
517
|
+
});
|
|
518
|
+
if (est.confidence >= ECHO_CAL_MIN_CONFIDENCE) {
|
|
519
|
+
this.echoDelaySamples = est.lagSamples;
|
|
520
|
+
this.echoDelayConfidence = est.confidence;
|
|
521
|
+
this.echoDelayCalibrated = true;
|
|
522
|
+
}
|
|
523
|
+
this.calNear = [];
|
|
524
|
+
this.calFar = [];
|
|
525
|
+
this.calSampleCount = 0;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Feed a batch of agent-playback (far-end) frames for echo cancellation. The
|
|
530
|
+
* device captures the agent's TTS output in the SAME base64 LE-s16 16 kHz
|
|
531
|
+
* mono wire format as the mic and POSTs it in real time as it renders; we
|
|
532
|
+
* decode + append to the alignment buffer. The device MUST also call
|
|
533
|
+
* {@link resetPlayback} when playback stops (or on barge-in) so the canceller
|
|
534
|
+
* never aligns a later mic frame to stale, no-longer-playing audio.
|
|
535
|
+
*/
|
|
536
|
+
pushPlayback(frames: AudioFrameEvent[]): void {
|
|
537
|
+
for (const frame of frames) {
|
|
538
|
+
this.echoBuffer.pushAt(frame.timestamp, decodeAudioFramePcm(frame));
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
/** Drop buffered far-end playback (playback stopped / barge-in). Also clears
|
|
543
|
+
* the in-progress delay-calibration window (it would otherwise straddle a
|
|
544
|
+
* playback gap); the already-learned delay is kept. */
|
|
545
|
+
resetPlayback(): void {
|
|
546
|
+
this.echoBuffer.reset();
|
|
547
|
+
this.calNear = [];
|
|
548
|
+
this.calFar = [];
|
|
549
|
+
this.calSampleCount = 0;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/** Feed a batch of WebView-captured frames; resolves once VAD has processed them. */
|
|
553
|
+
async ingest(frames: AudioFrameEvent[]): Promise<void> {
|
|
554
|
+
await this.ensureBuilt();
|
|
555
|
+
if (!this.consumer) return;
|
|
556
|
+
for (const frame of frames) {
|
|
557
|
+
this.framesReceived += 1;
|
|
558
|
+
if (!this.echoDelayCalibrated) {
|
|
559
|
+
try {
|
|
560
|
+
this.observeForDelayCalibration(
|
|
561
|
+
decodeAudioFramePcm(frame),
|
|
562
|
+
frame.timestamp,
|
|
563
|
+
);
|
|
564
|
+
} catch {
|
|
565
|
+
// Let AudioFrameConsumer own decode-error accounting below.
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
await this.consumer.onAudioFrame(frame);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
/** Flush any open segment (call on stopAudioFrames) and await attribution. */
|
|
573
|
+
async flush(): Promise<void> {
|
|
574
|
+
if (this.consumer) await this.consumer.flush();
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/** Build (if needed) and report status — the device-evidence read. */
|
|
578
|
+
async status(): Promise<LiveDiarizationStatus> {
|
|
579
|
+
try {
|
|
580
|
+
await this.ensureBuilt();
|
|
581
|
+
} catch {
|
|
582
|
+
// Surface the blocker in the status payload rather than throwing.
|
|
583
|
+
}
|
|
584
|
+
return {
|
|
585
|
+
ready: this.consumer != null,
|
|
586
|
+
libs: { fusedInference: this.resolvedLibPath },
|
|
587
|
+
models: { dir: voiceModelDir() },
|
|
588
|
+
framesReceived: this.framesReceived,
|
|
589
|
+
framesDropped: this.consumer?.droppedFrames ?? 0,
|
|
590
|
+
turnsObserved: this.turnsObserved,
|
|
591
|
+
aec: {
|
|
592
|
+
echoReferenceWired:
|
|
593
|
+
this.consumer != null || this.options.echoReference != null,
|
|
594
|
+
echoDelaySamples: this.echoDelaySamples,
|
|
595
|
+
echoDelayConfidence: this.echoDelayConfidence,
|
|
596
|
+
},
|
|
597
|
+
recentTurns: [...this.recentTurns],
|
|
598
|
+
...(this.buildError ? { error: this.buildError } : {}),
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
/** Release native handles + listeners. */
|
|
603
|
+
async close(): Promise<void> {
|
|
604
|
+
await this.consumer?.close();
|
|
605
|
+
if (this.asrRegionAcquired && this.ffi && this.ctx !== null) {
|
|
606
|
+
try {
|
|
607
|
+
this.ffi.mmapEvict(this.ctx, "asr");
|
|
608
|
+
} catch {
|
|
609
|
+
// Best-effort release; the context is destroyed below regardless.
|
|
610
|
+
}
|
|
611
|
+
this.asrRegionAcquired = false;
|
|
612
|
+
}
|
|
613
|
+
await this.encoder?.dispose();
|
|
614
|
+
await this.diarizer?.dispose();
|
|
615
|
+
this.vad?.close();
|
|
616
|
+
if (this.ffi && this.ctx !== null) this.ffi.destroy(this.ctx);
|
|
617
|
+
this.ffi?.close();
|
|
618
|
+
this.consumer = null;
|
|
619
|
+
this.ffi = null;
|
|
620
|
+
this.ctx = null;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { percentile, round1, round4 } from "./metric-math";
|
|
3
|
+
|
|
4
|
+
describe("round1", () => {
|
|
5
|
+
it("rounds to one decimal place", () => {
|
|
6
|
+
expect(round1(12.34)).toBe(12.3);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("rounds half up", () => {
|
|
10
|
+
expect(round1(0.25)).toBe(0.3);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("leaves integers unchanged", () => {
|
|
14
|
+
expect(round1(42)).toBe(42);
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe("round4", () => {
|
|
19
|
+
it("rounds to four decimal places", () => {
|
|
20
|
+
expect(round4(0.123456)).toBe(0.1235);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("leaves shorter values unchanged", () => {
|
|
24
|
+
expect(round4(0.12)).toBe(0.12);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe("percentile", () => {
|
|
29
|
+
it("computes the nearest-rank percentile", () => {
|
|
30
|
+
const sample = [10, 20, 30, 40, 50];
|
|
31
|
+
// p50 over 5 elements: rank = ceil(0.5 * 5) = 3 -> index 2 -> 30
|
|
32
|
+
expect(percentile(sample, 50)).toBe(30);
|
|
33
|
+
// p95: rank = ceil(0.95 * 5) = 5 -> index 4 -> 50
|
|
34
|
+
expect(percentile(sample, 95)).toBe(50);
|
|
35
|
+
// p0: rank = ceil(0) = 0 -> clamped to index 0 -> 10
|
|
36
|
+
expect(percentile(sample, 0)).toBe(10);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("sorts before ranking", () => {
|
|
40
|
+
expect(percentile([50, 10, 30, 20, 40], 50)).toBe(30);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("filters non-finite values before ranking", () => {
|
|
44
|
+
const sample = [10, Number.NaN, 20, Number.POSITIVE_INFINITY, 30];
|
|
45
|
+
// finite = [10, 20, 30]; p50: rank = ceil(0.5 * 3) = 2 -> index 1 -> 20
|
|
46
|
+
expect(percentile(sample, 50)).toBe(20);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("rounds the result to one decimal place", () => {
|
|
50
|
+
// finite single sample -> returned via round1
|
|
51
|
+
expect(percentile([12.34], 50)).toBe(12.3);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("returns null for an empty sample", () => {
|
|
55
|
+
expect(percentile([], 50)).toBeNull();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("returns null when every value is non-finite", () => {
|
|
59
|
+
expect(percentile([Number.NaN, Number.POSITIVE_INFINITY], 50)).toBeNull();
|
|
60
|
+
});
|
|
61
|
+
});
|