@elizaos/plugin-local-inference 2.0.0-beta.1 → 2.0.3-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +83 -0
- package/package.json +82 -15
- package/src/actions/generate-media.d.ts +59 -0
- package/src/actions/generate-media.d.ts.map +1 -0
- package/src/actions/generate-media.ts +647 -0
- package/src/actions/identify-speaker.d.ts +23 -0
- package/src/actions/identify-speaker.d.ts.map +1 -0
- package/src/actions/identify-speaker.ts +171 -0
- package/src/actions/transcription-control.d.ts +29 -0
- package/src/actions/transcription-control.d.ts.map +1 -0
- package/src/actions/transcription-control.test.ts +100 -0
- package/src/actions/transcription-control.ts +127 -0
- package/src/adapters/capacitor-llama/__tests__/compat-behavior.test.ts +218 -0
- package/src/adapters/capacitor-llama/__tests__/index.test.ts +68 -0
- package/src/adapters/capacitor-llama/__tests__/structured-output.test.ts +215 -0
- package/src/adapters/capacitor-llama/__tests__/text-streaming.test.ts +174 -0
- package/src/adapters/capacitor-llama/environment.ts +71 -0
- package/src/adapters/capacitor-llama/index.browser.ts +83 -0
- package/src/adapters/capacitor-llama/index.ts +807 -0
- package/src/adapters/capacitor-llama/loader.ts +109 -0
- package/src/adapters/capacitor-llama/structured-output.ts +165 -0
- package/src/adapters/capacitor-llama/text-streaming.ts +227 -0
- package/src/adapters/capacitor-llama/types.ts +374 -0
- package/src/backends/apple-foundation.ts +127 -0
- package/src/index.d.ts +8 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.ts +62 -0
- package/src/local-inference-routes.d.ts +38 -0
- package/src/local-inference-routes.d.ts.map +1 -0
- package/src/local-inference-routes.test.ts +344 -0
- package/src/local-inference-routes.ts +1543 -0
- package/src/provider.d.ts +21 -0
- package/src/provider.d.ts.map +1 -0
- package/src/provider.ts +1082 -0
- package/src/routes/compat-helpers.d.ts +18 -0
- package/src/routes/compat-helpers.d.ts.map +1 -0
- package/src/routes/compat-helpers.ts +274 -0
- package/src/routes/family-member-route.d.ts +62 -0
- package/src/routes/family-member-route.d.ts.map +1 -0
- package/src/routes/family-member-route.ts +353 -0
- package/src/routes/index.d.ts +19 -0
- package/src/routes/index.d.ts.map +1 -0
- package/src/routes/index.ts +60 -0
- package/src/routes/live-diarization-route.d.ts +26 -0
- package/src/routes/live-diarization-route.d.ts.map +1 -0
- package/src/routes/live-diarization-route.test.ts +213 -0
- package/src/routes/live-diarization-route.ts +122 -0
- package/src/routes/local-inference-asr-route.d.ts +4 -0
- package/src/routes/local-inference-asr-route.d.ts.map +1 -0
- package/src/routes/local-inference-asr-route.test.ts +205 -0
- package/src/routes/local-inference-asr-route.ts +163 -0
- package/src/routes/local-inference-asr-transcribe.d.ts +20 -0
- package/src/routes/local-inference-asr-transcribe.d.ts.map +1 -0
- package/src/routes/local-inference-asr-transcribe.test.ts +118 -0
- package/src/routes/local-inference-asr-transcribe.ts +97 -0
- package/src/routes/local-inference-compat-routes.d.ts +16 -0
- package/src/routes/local-inference-compat-routes.d.ts.map +1 -0
- package/src/routes/local-inference-compat-routes.test.ts +485 -0
- package/src/routes/local-inference-compat-routes.ts +808 -0
- package/src/routes/local-inference-tts-route.d.ts +7 -0
- package/src/routes/local-inference-tts-route.d.ts.map +1 -0
- package/src/routes/local-inference-tts-route.test.ts +179 -0
- package/src/routes/local-inference-tts-route.ts +230 -0
- package/src/routes/transcript-audio-store.d.ts +15 -0
- package/src/routes/transcript-audio-store.d.ts.map +1 -0
- package/src/routes/transcript-audio-store.ts +27 -0
- package/src/routes/transcripts-routes.d.ts +36 -0
- package/src/routes/transcripts-routes.d.ts.map +1 -0
- package/src/routes/transcripts-routes.test.ts +144 -0
- package/src/routes/transcripts-routes.ts +159 -0
- package/src/routes/voice-first-run-routes.d.ts +62 -0
- package/src/routes/voice-first-run-routes.d.ts.map +1 -0
- package/src/routes/voice-first-run-routes.ts +524 -0
- package/src/routes/voice-models-routes.d.ts +62 -0
- package/src/routes/voice-models-routes.d.ts.map +1 -0
- package/src/routes/voice-models-routes.ts +554 -0
- package/src/routes/voice-profile-plugin-routes.d.ts +19 -0
- package/src/routes/voice-profile-plugin-routes.d.ts.map +1 -0
- package/src/routes/voice-profile-plugin-routes.ts +138 -0
- package/src/routes/voice-profiles-management-routes.d.ts +52 -0
- package/src/routes/voice-profiles-management-routes.d.ts.map +1 -0
- package/src/routes/voice-profiles-management-routes.ts +476 -0
- package/src/routes/voice-speaker-profile-routes.d.ts +57 -0
- package/src/routes/voice-speaker-profile-routes.d.ts.map +1 -0
- package/src/routes/voice-speaker-profile-routes.ts +199 -0
- package/src/runtime/aosp-llama-loader-selection.test.ts +80 -0
- package/src/runtime/capacitor-llama.d.ts +25 -0
- package/src/runtime/embedding-manager-support.d.ts +77 -0
- package/src/runtime/embedding-manager-support.d.ts.map +1 -0
- package/src/runtime/embedding-manager-support.ts +497 -0
- package/src/runtime/embedding-presets.d.ts +16 -0
- package/src/runtime/embedding-presets.d.ts.map +1 -0
- package/src/runtime/embedding-presets.ts +81 -0
- package/src/runtime/embedding-warmup-policy.d.ts +14 -0
- package/src/runtime/embedding-warmup-policy.d.ts.map +1 -0
- package/src/runtime/embedding-warmup-policy.test.ts +53 -0
- package/src/runtime/embedding-warmup-policy.ts +48 -0
- package/src/runtime/ensure-local-inference-handler.d.ts +62 -0
- package/src/runtime/ensure-local-inference-handler.d.ts.map +1 -0
- package/src/runtime/ensure-local-inference-handler.test.ts +528 -0
- package/src/runtime/ensure-local-inference-handler.ts +1448 -0
- package/src/runtime/index.d.ts +15 -0
- package/src/runtime/index.d.ts.map +1 -0
- package/src/runtime/index.ts +33 -0
- package/src/runtime/mobile-local-inference-gate.d.ts +31 -0
- package/src/runtime/mobile-local-inference-gate.d.ts.map +1 -0
- package/src/runtime/mobile-local-inference-gate.test.ts +69 -0
- package/src/runtime/mobile-local-inference-gate.ts +44 -0
- package/src/runtime/voice-entity-binding.d.ts +103 -0
- package/src/runtime/voice-entity-binding.d.ts.map +1 -0
- package/src/runtime/voice-entity-binding.transcript.test.ts +69 -0
- package/src/runtime/voice-entity-binding.ts +328 -0
- package/src/services/README.md +71 -0
- package/src/services/__tests__/backend-selector.test.ts +101 -0
- package/src/services/__tests__/checkpoint-manager.test.ts +376 -0
- package/src/services/__tests__/gpu-autotune.test.ts +400 -0
- package/src/services/__tests__/llm-streaming-binding.test.ts +85 -0
- package/src/services/__tests__/planner-grammar.test.ts +372 -0
- package/src/services/__tests__/runtime-target.test.ts +176 -0
- package/src/services/active-model-switch-rollback.test.ts +183 -0
- package/src/services/active-model.d.ts +282 -0
- package/src/services/active-model.d.ts.map +1 -0
- package/src/services/active-model.ts +1213 -0
- package/src/services/assignments.d.ts +71 -0
- package/src/services/assignments.d.ts.map +1 -0
- package/src/services/assignments.test.ts +80 -0
- package/src/services/assignments.ts +230 -0
- package/src/services/backend-selector.ts +95 -0
- package/src/services/backend.d.ts +346 -0
- package/src/services/backend.d.ts.map +1 -0
- package/src/services/backend.ts +612 -0
- package/src/services/bionic-host-loader.d.ts +46 -0
- package/src/services/bionic-host-loader.d.ts.map +1 -0
- package/src/services/bionic-host-loader.test.ts +133 -0
- package/src/services/bionic-host-loader.ts +180 -0
- package/src/services/bundled-models.d.ts +34 -0
- package/src/services/bundled-models.d.ts.map +1 -0
- package/src/services/bundled-models.ts +129 -0
- package/src/services/cache-bridge.d.ts +206 -0
- package/src/services/cache-bridge.d.ts.map +1 -0
- package/src/services/cache-bridge.test.ts +516 -0
- package/src/services/cache-bridge.ts +423 -0
- package/src/services/catalog.d.ts +10 -0
- package/src/services/catalog.d.ts.map +1 -0
- package/src/services/catalog.test.ts +238 -0
- package/src/services/catalog.ts +27 -0
- package/src/services/checkpoint-client.d.ts +109 -0
- package/src/services/checkpoint-client.d.ts.map +1 -0
- package/src/services/checkpoint-client.ts +258 -0
- package/src/services/checkpoint-manager.ts +474 -0
- package/src/services/cloud-fallback.d.ts +102 -0
- package/src/services/cloud-fallback.d.ts.map +1 -0
- package/src/services/cloud-fallback.ts +230 -0
- package/src/services/conversation-registry.d.ts +142 -0
- package/src/services/conversation-registry.d.ts.map +1 -0
- package/src/services/conversation-registry.test.ts +235 -0
- package/src/services/conversation-registry.ts +264 -0
- package/src/services/desktop-fused-ffi-backend-runtime.d.ts +95 -0
- package/src/services/desktop-fused-ffi-backend-runtime.d.ts.map +1 -0
- package/src/services/desktop-fused-ffi-backend-runtime.ts +339 -0
- package/src/services/device-bridge.d.ts +188 -0
- package/src/services/device-bridge.d.ts.map +1 -0
- package/src/services/device-bridge.ts +1237 -0
- package/src/services/device-resource-metrics.d.ts +149 -0
- package/src/services/device-resource-metrics.d.ts.map +1 -0
- package/src/services/device-resource-metrics.test.ts +98 -0
- package/src/services/device-resource-metrics.ts +346 -0
- package/src/services/device-tier.d.ts +115 -0
- package/src/services/device-tier.d.ts.map +1 -0
- package/src/services/device-tier.test.ts +371 -0
- package/src/services/device-tier.ts +410 -0
- package/src/services/downloader.d.ts +82 -0
- package/src/services/downloader.d.ts.map +1 -0
- package/src/services/downloader.test.ts +747 -0
- package/src/services/downloader.ts +925 -0
- package/src/services/engine-direct-bundle.test.ts +58 -0
- package/src/services/engine-streaming.test.ts +80 -0
- package/src/services/engine.d.ts +540 -0
- package/src/services/engine.d.ts.map +1 -0
- package/src/services/engine.ts +1909 -0
- package/src/services/ensure-local-artifacts.integration.test.ts +273 -0
- package/src/services/ensure-local-artifacts.test.ts +368 -0
- package/src/services/ensure-local-artifacts.ts +351 -0
- package/src/services/external-scanner.d.ts +17 -0
- package/src/services/external-scanner.d.ts.map +1 -0
- package/src/services/external-scanner.ts +312 -0
- package/src/services/ffi-llm-mock.ts +354 -0
- package/src/services/ffi-llm-streaming-abi.ts +442 -0
- package/src/services/ffi-streaming-backend.d.ts +180 -0
- package/src/services/ffi-streaming-backend.d.ts.map +1 -0
- package/src/services/ffi-streaming-backend.ts +382 -0
- package/src/services/ffi-streaming-runner.d.ts +122 -0
- package/src/services/ffi-streaming-runner.d.ts.map +1 -0
- package/src/services/ffi-streaming-runner.test.ts +60 -0
- package/src/services/ffi-streaming-runner.ts +354 -0
- package/src/services/ffi-unload-ordering.test.ts +162 -0
- package/src/services/gpu-autotune.ts +534 -0
- package/src/services/gpu-detect.d.ts +56 -0
- package/src/services/gpu-detect.d.ts.map +1 -0
- package/src/services/gpu-detect.ts +139 -0
- package/src/services/handler-registry.d.ts +72 -0
- package/src/services/handler-registry.d.ts.map +1 -0
- package/src/services/handler-registry.ts +240 -0
- package/src/services/hardware.d.ts +63 -0
- package/src/services/hardware.d.ts.map +1 -0
- package/src/services/hardware.test.ts +231 -0
- package/src/services/hardware.ts +410 -0
- package/src/services/hf-search.d.ts +26 -0
- package/src/services/hf-search.d.ts.map +1 -0
- package/src/services/hf-search.test.ts +69 -0
- package/src/services/hf-search.ts +420 -0
- package/src/services/image-description-runtime.d.ts +14 -0
- package/src/services/image-description-runtime.d.ts.map +1 -0
- package/src/services/image-description-runtime.test.ts +61 -0
- package/src/services/image-description-runtime.ts +118 -0
- package/src/services/imagegen/aosp-unavailable.d.ts +134 -0
- package/src/services/imagegen/aosp-unavailable.d.ts.map +1 -0
- package/src/services/imagegen/aosp-unavailable.ts +229 -0
- package/src/services/imagegen/backend-selector.d.ts +118 -0
- package/src/services/imagegen/backend-selector.d.ts.map +1 -0
- package/src/services/imagegen/backend-selector.ts +277 -0
- package/src/services/imagegen/coreml-unavailable.d.ts +105 -0
- package/src/services/imagegen/coreml-unavailable.d.ts.map +1 -0
- package/src/services/imagegen/coreml-unavailable.ts +237 -0
- package/src/services/imagegen/errors.d.ts +16 -0
- package/src/services/imagegen/errors.d.ts.map +1 -0
- package/src/services/imagegen/errors.ts +40 -0
- package/src/services/imagegen/index.d.ts +58 -0
- package/src/services/imagegen/index.d.ts.map +1 -0
- package/src/services/imagegen/index.ts +144 -0
- package/src/services/imagegen/mflux.d.ts +74 -0
- package/src/services/imagegen/mflux.d.ts.map +1 -0
- package/src/services/imagegen/mflux.ts +313 -0
- package/src/services/imagegen/sd-cpp.d.ts +180 -0
- package/src/services/imagegen/sd-cpp.d.ts.map +1 -0
- package/src/services/imagegen/sd-cpp.ts +718 -0
- package/src/services/imagegen/tensorrt-unavailable.d.ts +83 -0
- package/src/services/imagegen/tensorrt-unavailable.d.ts.map +1 -0
- package/src/services/imagegen/tensorrt-unavailable.ts +295 -0
- package/src/services/imagegen/types.d.ts +181 -0
- package/src/services/imagegen/types.d.ts.map +1 -0
- package/src/services/imagegen/types.ts +193 -0
- package/src/services/index.d.ts +29 -0
- package/src/services/index.d.ts.map +1 -0
- package/src/services/index.ts +211 -0
- package/src/services/inference-capabilities.d.ts +132 -0
- package/src/services/inference-capabilities.d.ts.map +1 -0
- package/src/services/inference-capabilities.test.ts +75 -0
- package/src/services/inference-capabilities.ts +204 -0
- package/src/services/inference-telemetry.d.ts +59 -0
- package/src/services/inference-telemetry.d.ts.map +1 -0
- package/src/services/inference-telemetry.ts +143 -0
- package/src/services/ios-llama-streaming.ts +248 -0
- package/src/services/kv-spill.d.ts +189 -0
- package/src/services/kv-spill.d.ts.map +1 -0
- package/src/services/kv-spill.test.ts +222 -0
- package/src/services/kv-spill.ts +356 -0
- package/src/services/latency-trace.d.ts +346 -0
- package/src/services/latency-trace.d.ts.map +1 -0
- package/src/services/latency-trace.test.ts +266 -0
- package/src/services/latency-trace.ts +844 -0
- package/src/services/llama-server-metrics.ts +304 -0
- package/src/services/llm-streaming-binding.d.ts +96 -0
- package/src/services/llm-streaming-binding.d.ts.map +1 -0
- package/src/services/llm-streaming-binding.ts +136 -0
- package/src/services/load-args.d.ts +82 -0
- package/src/services/load-args.d.ts.map +1 -0
- package/src/services/load-args.ts +81 -0
- package/src/services/manifest/eliza-1.manifest.v1.json +708 -0
- package/src/services/manifest/index.d.ts +4 -0
- package/src/services/manifest/index.d.ts.map +1 -0
- package/src/services/manifest/index.ts +66 -0
- package/src/services/manifest/manifest.test.ts +689 -0
- package/src/services/manifest/schema.d.ts +713 -0
- package/src/services/manifest/schema.d.ts.map +1 -0
- package/src/services/manifest/schema.ts +653 -0
- package/src/services/manifest/types.d.ts +30 -0
- package/src/services/manifest/types.d.ts.map +1 -0
- package/src/services/manifest/types.ts +55 -0
- package/src/services/manifest/validator.d.ts +66 -0
- package/src/services/manifest/validator.d.ts.map +1 -0
- package/src/services/manifest/validator.ts +567 -0
- package/src/services/memory-arbiter.d.ts +318 -0
- package/src/services/memory-arbiter.d.ts.map +1 -0
- package/src/services/memory-arbiter.test.ts +419 -0
- package/src/services/memory-arbiter.ts +925 -0
- package/src/services/memory-monitor.d.ts +122 -0
- package/src/services/memory-monitor.d.ts.map +1 -0
- package/src/services/memory-monitor.test.ts +208 -0
- package/src/services/memory-monitor.ts +297 -0
- package/src/services/memory-pressure.d.ts +130 -0
- package/src/services/memory-pressure.d.ts.map +1 -0
- package/src/services/memory-pressure.ts +414 -0
- package/src/services/mtp-doctor.d.ts +13 -0
- package/src/services/mtp-doctor.d.ts.map +1 -0
- package/src/services/mtp-doctor.ts +78 -0
- package/src/services/network-policy.d.ts +127 -0
- package/src/services/network-policy.d.ts.map +1 -0
- package/src/services/network-policy.ts +346 -0
- package/src/services/paths.d.ts +6 -0
- package/src/services/paths.d.ts.map +1 -0
- package/src/services/paths.ts +25 -0
- package/src/services/planner-skeleton.d.ts +124 -0
- package/src/services/planner-skeleton.d.ts.map +1 -0
- package/src/services/planner-skeleton.ts +175 -0
- package/src/services/providers.d.ts +38 -0
- package/src/services/providers.d.ts.map +1 -0
- package/src/services/providers.ts +507 -0
- package/src/services/ram-budget-cache.test.ts +163 -0
- package/src/services/ram-budget.d.ts +110 -0
- package/src/services/ram-budget.d.ts.map +1 -0
- package/src/services/ram-budget.ts +0 -0
- package/src/services/readiness.d.ts +9 -0
- package/src/services/readiness.d.ts.map +1 -0
- package/src/services/readiness.test.ts +87 -0
- package/src/services/readiness.ts +238 -0
- package/src/services/recommendation.d.ts +111 -0
- package/src/services/recommendation.d.ts.map +1 -0
- package/src/services/recommendation.ts +671 -0
- package/src/services/registry.d.ts +35 -0
- package/src/services/registry.d.ts.map +1 -0
- package/src/services/registry.ts +151 -0
- package/src/services/router-handler.d.ts +92 -0
- package/src/services/router-handler.d.ts.map +1 -0
- package/src/services/router-handler.test.ts +45 -0
- package/src/services/router-handler.ts +407 -0
- package/src/services/routing-policy.d.ts +69 -0
- package/src/services/routing-policy.d.ts.map +1 -0
- package/src/services/routing-policy.test.ts +164 -0
- package/src/services/routing-policy.ts +297 -0
- package/src/services/routing-preferences.d.ts +8 -0
- package/src/services/routing-preferences.d.ts.map +1 -0
- package/src/services/routing-preferences.ts +17 -0
- package/src/services/runtime-target.d.ts +98 -0
- package/src/services/runtime-target.d.ts.map +1 -0
- package/src/services/runtime-target.ts +154 -0
- package/src/services/service.d.ts +128 -0
- package/src/services/service.d.ts.map +1 -0
- package/src/services/service.test.ts +223 -0
- package/src/services/service.ts +735 -0
- package/src/services/session-pool.d.ts +72 -0
- package/src/services/session-pool.d.ts.map +1 -0
- package/src/services/session-pool.ts +153 -0
- package/src/services/structured-output/deterministic-repair.d.ts +23 -0
- package/src/services/structured-output/deterministic-repair.d.ts.map +1 -0
- package/src/services/structured-output/deterministic-repair.test.ts +169 -0
- package/src/services/structured-output/deterministic-repair.ts +443 -0
- package/src/services/structured-output/index.ts +4 -0
- package/src/services/structured-output.d.ts +311 -0
- package/src/services/structured-output.d.ts.map +1 -0
- package/src/services/structured-output.test.ts +483 -0
- package/src/services/structured-output.ts +712 -0
- package/src/services/system-memory.d.ts +33 -0
- package/src/services/system-memory.d.ts.map +1 -0
- package/src/services/system-memory.test.ts +47 -0
- package/src/services/system-memory.ts +67 -0
- package/src/services/transcription-priority.test.ts +211 -0
- package/src/services/types.d.ts +19 -0
- package/src/services/types.d.ts.map +1 -0
- package/src/services/types.ts +55 -0
- package/src/services/verify-on-device.d.ts +34 -0
- package/src/services/verify-on-device.d.ts.map +1 -0
- package/src/services/verify-on-device.test.ts +87 -0
- package/src/services/verify-on-device.ts +127 -0
- package/src/services/verify.d.ts +8 -0
- package/src/services/verify.d.ts.map +1 -0
- package/src/services/verify.ts +13 -0
- package/src/services/vision/aosp-unavailable.d.ts +115 -0
- package/src/services/vision/aosp-unavailable.d.ts.map +1 -0
- package/src/services/vision/aosp-unavailable.ts +163 -0
- package/src/services/vision/capacitor-llama.d.ts +99 -0
- package/src/services/vision/capacitor-llama.d.ts.map +1 -0
- package/src/services/vision/capacitor-llama.ts +255 -0
- package/src/services/vision/cloud-fallback.d.ts +47 -0
- package/src/services/vision/cloud-fallback.d.ts.map +1 -0
- package/src/services/vision/cloud-fallback.test.ts +243 -0
- package/src/services/vision/cloud-fallback.ts +268 -0
- package/src/services/vision/fallback-chain.test.ts +86 -0
- package/src/services/vision/hash.d.ts +71 -0
- package/src/services/vision/hash.d.ts.map +1 -0
- package/src/services/vision/hash.ts +157 -0
- package/src/services/vision/index.d.ts +95 -0
- package/src/services/vision/index.d.ts.map +1 -0
- package/src/services/vision/index.ts +251 -0
- package/src/services/vision/llama-server.d.ts +73 -0
- package/src/services/vision/llama-server.d.ts.map +1 -0
- package/src/services/vision/llama-server.ts +177 -0
- package/src/services/vision/types.d.ts +153 -0
- package/src/services/vision/types.d.ts.map +1 -0
- package/src/services/vision/types.ts +154 -0
- package/src/services/vision/vast-fallback.d.ts +18 -0
- package/src/services/vision/vast-fallback.d.ts.map +1 -0
- package/src/services/vision/vast-fallback.ts +127 -0
- package/src/services/vision-embedding-cache.d.ts +98 -0
- package/src/services/vision-embedding-cache.d.ts.map +1 -0
- package/src/services/vision-embedding-cache.ts +189 -0
- package/src/services/voice/VOICE_WORKBENCH.md +88 -0
- package/src/services/voice/__test-helpers__/fake-ffi.ts +94 -0
- package/src/services/voice/__test-helpers__/synthetic-speech.ts +124 -0
- package/src/services/voice/__tests__/checkpoint-manager.test.ts +241 -0
- package/src/services/voice/__tests__/checkpoint-policy.test.ts +270 -0
- package/src/services/voice/__tests__/eager-context-builder.test.ts +257 -0
- package/src/services/voice/__tests__/eliza1-eot-scorer.test.ts +288 -0
- package/src/services/voice/__tests__/eot-classifier.test.ts +431 -0
- package/src/services/voice/__tests__/optimistic-rollback.test.ts +312 -0
- package/src/services/voice/__tests__/prefill-client.test.ts +266 -0
- package/src/services/voice/__tests__/prefix-preserving-queue.test.ts +208 -0
- package/src/services/voice/__tests__/streaming-asr.test.ts +450 -0
- package/src/services/voice/__tests__/streaming-transcriber.test.ts +339 -0
- package/src/services/voice/__tests__/turn-detector-resolver.test.ts +195 -0
- package/src/services/voice/__tests__/voice-state-machine-prefill.test.ts +275 -0
- package/src/services/voice/__tests__/voice-state-machine.test.ts +354 -0
- package/src/services/voice/asr-timed.real.test.ts +141 -0
- package/src/services/voice/audio-frame-consumer.d.ts +212 -0
- package/src/services/voice/audio-frame-consumer.d.ts.map +1 -0
- package/src/services/voice/audio-frame-consumer.test.ts +343 -0
- package/src/services/voice/audio-frame-consumer.ts +491 -0
- package/src/services/voice/barge-in.d.ts +112 -0
- package/src/services/voice/barge-in.d.ts.map +1 -0
- package/src/services/voice/barge-in.test.ts +244 -0
- package/src/services/voice/barge-in.ts +336 -0
- package/src/services/voice/cancellation-coordinator.d.ts +127 -0
- package/src/services/voice/cancellation-coordinator.d.ts.map +1 -0
- package/src/services/voice/cancellation-coordinator.test.ts +196 -0
- package/src/services/voice/cancellation-coordinator.ts +269 -0
- package/src/services/voice/checkpoint-manager.d.ts +199 -0
- package/src/services/voice/checkpoint-manager.d.ts.map +1 -0
- package/src/services/voice/checkpoint-manager.ts +401 -0
- package/src/services/voice/checkpoint-policy.ts +336 -0
- package/src/services/voice/composite-eot-classifier.test.ts +59 -0
- package/src/services/voice/e2e-harness.test.ts +182 -0
- package/src/services/voice/e2e-harness.ts +743 -0
- package/src/services/voice/eager-context-builder.d.ts +170 -0
- package/src/services/voice/eager-context-builder.d.ts.map +1 -0
- package/src/services/voice/eager-context-builder.ts +262 -0
- package/src/services/voice/eliza1-eot-scorer.d.ts +124 -0
- package/src/services/voice/eliza1-eot-scorer.d.ts.map +1 -0
- package/src/services/voice/eliza1-eot-scorer.ts +242 -0
- package/src/services/voice/embedding-server.ts +200 -0
- package/src/services/voice/embedding.d.ts +133 -0
- package/src/services/voice/embedding.d.ts.map +1 -0
- package/src/services/voice/embedding.test.ts +131 -0
- package/src/services/voice/embedding.ts +243 -0
- package/src/services/voice/emotion-attribution.d.ts +68 -0
- package/src/services/voice/emotion-attribution.d.ts.map +1 -0
- package/src/services/voice/emotion-attribution.test.ts +129 -0
- package/src/services/voice/emotion-attribution.ts +361 -0
- package/src/services/voice/engine-bridge-cancellation.test.ts +422 -0
- package/src/services/voice/engine-bridge.d.ts +759 -0
- package/src/services/voice/engine-bridge.d.ts.map +1 -0
- package/src/services/voice/engine-bridge.test.ts +384 -0
- package/src/services/voice/engine-bridge.ts +2302 -0
- package/src/services/voice/eot-classifier-ggml.d.ts +179 -0
- package/src/services/voice/eot-classifier-ggml.d.ts.map +1 -0
- package/src/services/voice/eot-classifier-ggml.ts +566 -0
- package/src/services/voice/eot-classifier.d.ts +214 -0
- package/src/services/voice/eot-classifier.d.ts.map +1 -0
- package/src/services/voice/eot-classifier.ts +533 -0
- package/src/services/voice/errors.d.ts +20 -0
- package/src/services/voice/errors.d.ts.map +1 -0
- package/src/services/voice/errors.ts +32 -0
- package/src/services/voice/expressive-tags.d.ts +158 -0
- package/src/services/voice/expressive-tags.d.ts.map +1 -0
- package/src/services/voice/expressive-tags.ts +405 -0
- package/src/services/voice/ffi-bindings.d.ts +674 -0
- package/src/services/voice/ffi-bindings.d.ts.map +1 -0
- package/src/services/voice/ffi-bindings.test.ts +728 -0
- package/src/services/voice/ffi-bindings.ts +3225 -0
- package/src/services/voice/first-line-cache.d.ts +181 -0
- package/src/services/voice/first-line-cache.d.ts.map +1 -0
- package/src/services/voice/first-line-cache.ts +725 -0
- package/src/services/voice/fused-eot-scorer.d.ts +51 -0
- package/src/services/voice/fused-eot-scorer.d.ts.map +1 -0
- package/src/services/voice/fused-eot-scorer.ts +135 -0
- package/src/services/voice/index.d.ts +91 -0
- package/src/services/voice/index.d.ts.map +1 -0
- package/src/services/voice/index.ts +481 -0
- package/src/services/voice/kokoro/__tests__/kokoro-backend.test.ts +151 -0
- package/src/services/voice/kokoro/__tests__/kokoro-engine-bridge.real.test.ts +151 -0
- package/src/services/voice/kokoro/__tests__/kokoro-engine-bridge.test.ts +60 -0
- package/src/services/voice/kokoro/__tests__/kokoro-engine-discovery.test.ts +277 -0
- package/src/services/voice/kokoro/__tests__/kokoro-ffi-runtime.test.ts +235 -0
- package/src/services/voice/kokoro/__tests__/kokoro-runtime.test.ts +95 -0
- package/src/services/voice/kokoro/__tests__/phonemizer.test.ts +53 -0
- package/src/services/voice/kokoro/__tests__/runtime-selection.test.ts +231 -0
- package/src/services/voice/kokoro/__tests__/voices.test.ts +57 -0
- package/src/services/voice/kokoro/index.ts +79 -0
- package/src/services/voice/kokoro/kokoro-backend.d.ts +72 -0
- package/src/services/voice/kokoro/kokoro-backend.d.ts.map +1 -0
- package/src/services/voice/kokoro/kokoro-backend.ts +207 -0
- package/src/services/voice/kokoro/kokoro-engine-discovery.d.ts +58 -0
- package/src/services/voice/kokoro/kokoro-engine-discovery.d.ts.map +1 -0
- package/src/services/voice/kokoro/kokoro-engine-discovery.ts +177 -0
- package/src/services/voice/kokoro/kokoro-ffi-runtime.d.ts +75 -0
- package/src/services/voice/kokoro/kokoro-ffi-runtime.d.ts.map +1 -0
- package/src/services/voice/kokoro/kokoro-ffi-runtime.ts +233 -0
- package/src/services/voice/kokoro/kokoro-runtime.d.ts +100 -0
- package/src/services/voice/kokoro/kokoro-runtime.d.ts.map +1 -0
- package/src/services/voice/kokoro/kokoro-runtime.ts +170 -0
- package/src/services/voice/kokoro/phoneme-stream.ts +123 -0
- package/src/services/voice/kokoro/phonemizer.d.ts +50 -0
- package/src/services/voice/kokoro/phonemizer.d.ts.map +1 -0
- package/src/services/voice/kokoro/phonemizer.ts +344 -0
- package/src/services/voice/kokoro/pick-runtime.d.ts +61 -0
- package/src/services/voice/kokoro/pick-runtime.d.ts.map +1 -0
- package/src/services/voice/kokoro/pick-runtime.test.ts +91 -0
- package/src/services/voice/kokoro/pick-runtime.ts +130 -0
- package/src/services/voice/kokoro/runtime-selection.d.ts +92 -0
- package/src/services/voice/kokoro/runtime-selection.d.ts.map +1 -0
- package/src/services/voice/kokoro/runtime-selection.ts +237 -0
- package/src/services/voice/kokoro/types.d.ts +82 -0
- package/src/services/voice/kokoro/types.d.ts.map +1 -0
- package/src/services/voice/kokoro/types.ts +95 -0
- package/src/services/voice/kokoro/voice-presets.d.ts +23 -0
- package/src/services/voice/kokoro/voice-presets.d.ts.map +1 -0
- package/src/services/voice/kokoro/voice-presets.ts +129 -0
- package/src/services/voice/kokoro/voices.d.ts +30 -0
- package/src/services/voice/kokoro/voices.d.ts.map +1 -0
- package/src/services/voice/kokoro/voices.ts +64 -0
- package/src/services/voice/lifecycle.d.ts +135 -0
- package/src/services/voice/lifecycle.d.ts.map +1 -0
- package/src/services/voice/lifecycle.test.ts +315 -0
- package/src/services/voice/lifecycle.ts +301 -0
- package/src/services/voice/live-diarization-session.d.ts +96 -0
- package/src/services/voice/live-diarization-session.d.ts.map +1 -0
- package/src/services/voice/live-diarization-session.ts +289 -0
- package/src/services/voice/mic-source.d.ts +136 -0
- package/src/services/voice/mic-source.d.ts.map +1 -0
- package/src/services/voice/mic-source.test.ts +210 -0
- package/src/services/voice/mic-source.ts +503 -0
- package/src/services/voice/optimistic-policy.d.ts +109 -0
- package/src/services/voice/optimistic-policy.d.ts.map +1 -0
- package/src/services/voice/optimistic-policy.test.ts +101 -0
- package/src/services/voice/optimistic-policy.ts +192 -0
- package/src/services/voice/optimistic-rollback.ts +343 -0
- package/src/services/voice/partial-stabilizer.d.ts +73 -0
- package/src/services/voice/partial-stabilizer.d.ts.map +1 -0
- package/src/services/voice/partial-stabilizer.test.ts +68 -0
- package/src/services/voice/partial-stabilizer.ts +140 -0
- package/src/services/voice/phoneme-tokenizer.d.ts +49 -0
- package/src/services/voice/phoneme-tokenizer.d.ts.map +1 -0
- package/src/services/voice/phoneme-tokenizer.ts +158 -0
- package/src/services/voice/phrase-cache.d.ts +76 -0
- package/src/services/voice/phrase-cache.d.ts.map +1 -0
- package/src/services/voice/phrase-cache.test.ts +242 -0
- package/src/services/voice/phrase-cache.ts +186 -0
- package/src/services/voice/phrase-chunker.d.ts +62 -0
- package/src/services/voice/phrase-chunker.d.ts.map +1 -0
- package/src/services/voice/phrase-chunker.test.ts +239 -0
- package/src/services/voice/phrase-chunker.ts +281 -0
- package/src/services/voice/pipeline-impls.d.ts +151 -0
- package/src/services/voice/pipeline-impls.d.ts.map +1 -0
- package/src/services/voice/pipeline-impls.l6.test.ts +110 -0
- package/src/services/voice/pipeline-impls.test.ts +292 -0
- package/src/services/voice/pipeline-impls.ts +315 -0
- package/src/services/voice/pipeline.d.ts +216 -0
- package/src/services/voice/pipeline.d.ts.map +1 -0
- package/src/services/voice/pipeline.ts +505 -0
- package/src/services/voice/prefill-client.d.ts +123 -0
- package/src/services/voice/prefill-client.d.ts.map +1 -0
- package/src/services/voice/prefill-client.ts +316 -0
- package/src/services/voice/prefix-preserving-queue.d.ts +113 -0
- package/src/services/voice/prefix-preserving-queue.d.ts.map +1 -0
- package/src/services/voice/prefix-preserving-queue.ts +162 -0
- package/src/services/voice/profile-store.d.ts +248 -0
- package/src/services/voice/profile-store.d.ts.map +1 -0
- package/src/services/voice/profile-store.ts +887 -0
- package/src/services/voice/real-audio-decode.test.ts +148 -0
- package/src/services/voice/ring-buffer.d.ts +40 -0
- package/src/services/voice/ring-buffer.d.ts.map +1 -0
- package/src/services/voice/ring-buffer.test.ts +129 -0
- package/src/services/voice/ring-buffer.ts +123 -0
- package/src/services/voice/rollback-queue.d.ts +24 -0
- package/src/services/voice/rollback-queue.d.ts.map +1 -0
- package/src/services/voice/rollback-queue.ts +74 -0
- package/src/services/voice/samantha-preset-placeholder.d.ts +67 -0
- package/src/services/voice/samantha-preset-placeholder.d.ts.map +1 -0
- package/src/services/voice/samantha-preset-placeholder.test.ts +97 -0
- package/src/services/voice/samantha-preset-placeholder.ts +148 -0
- package/src/services/voice/samantha-preset-regenerator.d.ts +87 -0
- package/src/services/voice/samantha-preset-regenerator.d.ts.map +1 -0
- package/src/services/voice/samantha-preset-regenerator.ts +393 -0
- package/src/services/voice/scheduler.d.ts +146 -0
- package/src/services/voice/scheduler.d.ts.map +1 -0
- package/src/services/voice/scheduler.t2.test.ts +141 -0
- package/src/services/voice/scheduler.ts +927 -0
- package/src/services/voice/shared-resources.d.ts +190 -0
- package/src/services/voice/shared-resources.d.ts.map +1 -0
- package/src/services/voice/shared-resources.ts +320 -0
- package/src/services/voice/speaker/attribution-pipeline.d.ts +74 -0
- package/src/services/voice/speaker/attribution-pipeline.d.ts.map +1 -0
- package/src/services/voice/speaker/attribution-pipeline.ts +386 -0
- package/src/services/voice/speaker/diarizer-fused.d.ts +59 -0
- package/src/services/voice/speaker/diarizer-fused.d.ts.map +1 -0
- package/src/services/voice/speaker/diarizer-fused.real.test.ts +100 -0
- package/src/services/voice/speaker/diarizer-fused.ts +154 -0
- package/src/services/voice/speaker/diarizer.d.ts +75 -0
- package/src/services/voice/speaker/diarizer.d.ts.map +1 -0
- package/src/services/voice/speaker/diarizer.ts +218 -0
- package/src/services/voice/speaker/encoder-fused.d.ts +60 -0
- package/src/services/voice/speaker/encoder-fused.d.ts.map +1 -0
- package/src/services/voice/speaker/encoder-fused.real.test.ts +113 -0
- package/src/services/voice/speaker/encoder-fused.ts +138 -0
- package/src/services/voice/speaker/encoder-ggml.d.ts +33 -0
- package/src/services/voice/speaker/encoder-ggml.d.ts.map +1 -0
- package/src/services/voice/speaker/encoder-ggml.ts +79 -0
- package/src/services/voice/speaker/encoder.d.ts +37 -0
- package/src/services/voice/speaker/encoder.d.ts.map +1 -0
- package/src/services/voice/speaker/encoder.ts +105 -0
- package/src/services/voice/speaker-imprint.d.ts +83 -0
- package/src/services/voice/speaker-imprint.d.ts.map +1 -0
- package/src/services/voice/speaker-imprint.test.ts +185 -0
- package/src/services/voice/speaker-imprint.ts +312 -0
- package/src/services/voice/speaker-preset-cache.d.ts +77 -0
- package/src/services/voice/speaker-preset-cache.d.ts.map +1 -0
- package/src/services/voice/speaker-preset-cache.test.ts +154 -0
- package/src/services/voice/speaker-preset-cache.ts +195 -0
- package/src/services/voice/streaming-asr/streaming-pipeline-adapter.ts +292 -0
- package/src/services/voice/system-audio-sink.d.ts +73 -0
- package/src/services/voice/system-audio-sink.d.ts.map +1 -0
- package/src/services/voice/system-audio-sink.test.ts +29 -0
- package/src/services/voice/system-audio-sink.ts +366 -0
- package/src/services/voice/transcriber.d.ts +244 -0
- package/src/services/voice/transcriber.d.ts.map +1 -0
- package/src/services/voice/transcriber.test.ts +392 -0
- package/src/services/voice/transcriber.ts +704 -0
- package/src/services/voice/transcript-knowledge.d.ts +37 -0
- package/src/services/voice/transcript-knowledge.d.ts.map +1 -0
- package/src/services/voice/transcript-knowledge.test.ts +68 -0
- package/src/services/voice/transcript-knowledge.ts +75 -0
- package/src/services/voice/transcript-service.d.ts +41 -0
- package/src/services/voice/transcript-service.d.ts.map +1 -0
- package/src/services/voice/transcript-service.test.ts +137 -0
- package/src/services/voice/transcript-service.ts +141 -0
- package/src/services/voice/transcript-store.d.ts +53 -0
- package/src/services/voice/transcript-store.d.ts.map +1 -0
- package/src/services/voice/transcript-store.test.ts +153 -0
- package/src/services/voice/transcript-store.ts +132 -0
- package/src/services/voice/turn-controller.d.ts +183 -0
- package/src/services/voice/turn-controller.d.ts.map +1 -0
- package/src/services/voice/turn-controller.test.ts +575 -0
- package/src/services/voice/turn-controller.ts +596 -0
- package/src/services/voice/types.d.ts +643 -0
- package/src/services/voice/types.d.ts.map +1 -0
- package/src/services/voice/types.ts +699 -0
- package/src/services/voice/vad.d.ts +282 -0
- package/src/services/voice/vad.d.ts.map +1 -0
- package/src/services/voice/vad.test.ts +480 -0
- package/src/services/voice/vad.ts +827 -0
- package/src/services/voice/vad.v1-v4.test.ts +222 -0
- package/src/services/voice/voice-budget.d.ts +241 -0
- package/src/services/voice/voice-budget.d.ts.map +1 -0
- package/src/services/voice/voice-budget.test.ts +418 -0
- package/src/services/voice/voice-budget.ts +635 -0
- package/src/services/voice/voice-duet.test.ts +375 -0
- package/src/services/voice/voice-emotion-classifier.d.ts +95 -0
- package/src/services/voice/voice-emotion-classifier.d.ts.map +1 -0
- package/src/services/voice/voice-emotion-classifier.test.ts +210 -0
- package/src/services/voice/voice-emotion-classifier.ts +273 -0
- package/src/services/voice/voice-preset-format.d.ts +158 -0
- package/src/services/voice/voice-preset-format.d.ts.map +1 -0
- package/src/services/voice/voice-preset-format.ts +700 -0
- package/src/services/voice/voice-preset-generator.test.ts +89 -0
- package/src/services/voice/voice-profile-artifact.d.ts +116 -0
- package/src/services/voice/voice-profile-artifact.d.ts.map +1 -0
- package/src/services/voice/voice-profile-artifact.test.ts +138 -0
- package/src/services/voice/voice-profile-artifact.ts +518 -0
- package/src/services/voice/voice-profile-routes.d.ts +83 -0
- package/src/services/voice/voice-profile-routes.d.ts.map +1 -0
- package/src/services/voice/voice-profile-routes.test.ts +429 -0
- package/src/services/voice/voice-profile-routes.ts +425 -0
- package/src/services/voice/voice-scenario.ts +154 -0
- package/src/services/voice/voice-settings.d.ts +82 -0
- package/src/services/voice/voice-settings.d.ts.map +1 -0
- package/src/services/voice/voice-settings.ts +172 -0
- package/src/services/voice/voice-state-machine.d.ts +364 -0
- package/src/services/voice/voice-state-machine.d.ts.map +1 -0
- package/src/services/voice/voice-state-machine.ts +727 -0
- package/src/services/voice/voice-workbench-report.test.ts +168 -0
- package/src/services/voice/voice-workbench-report.ts +326 -0
- package/src/services/voice/voice-workbench.test.ts +158 -0
- package/src/services/voice/voice.test.ts +1070 -0
- package/src/services/voice/wake-word-ggml.d.ts +101 -0
- package/src/services/voice/wake-word-ggml.d.ts.map +1 -0
- package/src/services/voice/wake-word-ggml.ts +320 -0
- package/src/services/voice/wake-word.d.ts +255 -0
- package/src/services/voice/wake-word.d.ts.map +1 -0
- package/src/services/voice/wake-word.test.ts +298 -0
- package/src/services/voice/wake-word.ts +554 -0
- package/src/services/voice/wrap-with-first-line-cache.d.ts +70 -0
- package/src/services/voice/wrap-with-first-line-cache.d.ts.map +1 -0
- package/src/services/voice/wrap-with-first-line-cache.ts +267 -0
- package/src/services/voice-model-updater.d.ts +240 -0
- package/src/services/voice-model-updater.d.ts.map +1 -0
- package/src/services/voice-model-updater.ts +724 -0
- package/src/services/voice-prewarm.d.ts +3 -0
- package/src/services/voice-prewarm.d.ts.map +1 -0
- package/src/services/voice-prewarm.ts +51 -0
- package/dist/index.d.ts +0 -37
- package/dist/index.js +0 -1098
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side voice-profile management routes.
|
|
3
|
+
*
|
|
4
|
+
* Surfaces the available OmniVoice profiles from:
|
|
5
|
+
* 1. The active Eliza-1 bundle's `cache/voice-preset-*.bin` files.
|
|
6
|
+
* 2. The `models/voice/profiles/` catalog directory (build-time profiles).
|
|
7
|
+
*
|
|
8
|
+
* Routes:
|
|
9
|
+
* GET /v1/voice/profiles — list available profiles
|
|
10
|
+
* POST /v1/voice/profiles/:id/activate — set the active default profile
|
|
11
|
+
* DELETE /v1/voice/profiles/:id — soft-delete (mark inactive in catalog)
|
|
12
|
+
*
|
|
13
|
+
* The active default profile is persisted in the voice profile catalog JSON
|
|
14
|
+
* (`models/voice/profiles/catalog.json`). On model boot, the engine bridge
|
|
15
|
+
* reads this to pick which preset to load as the default.
|
|
16
|
+
*
|
|
17
|
+
* No runtime recording interface is exposed. Profile creation happens at
|
|
18
|
+
* build time via `bun run voice:create-profile`.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import fs from "node:fs";
|
|
22
|
+
import fsp from "node:fs/promises";
|
|
23
|
+
import type http from "node:http";
|
|
24
|
+
import path from "node:path";
|
|
25
|
+
import { resolveStateDir } from "@elizaos/core";
|
|
26
|
+
import {
|
|
27
|
+
readVoicePresetFile,
|
|
28
|
+
type VoicePresetFile,
|
|
29
|
+
} from "./voice-preset-format";
|
|
30
|
+
|
|
31
|
+
/** Catalog JSON schema version. */
|
|
32
|
+
const CATALOG_SCHEMA_VERSION = 1 as const;
|
|
33
|
+
|
|
34
|
+
/** One entry in `catalog.json`. */
|
|
35
|
+
export interface VoiceProfileCatalogEntry {
|
|
36
|
+
/** Profile identifier — matches the `voice-preset-<id>.bin` filename suffix. */
|
|
37
|
+
id: string;
|
|
38
|
+
/** Human-readable display name. */
|
|
39
|
+
displayName: string;
|
|
40
|
+
/** Build-time instruct string (VoiceDesign vocabulary). */
|
|
41
|
+
instruct: string;
|
|
42
|
+
/** Whether this profile is currently active (visible + usable). */
|
|
43
|
+
active: boolean;
|
|
44
|
+
/** ISO timestamp when this entry was created. */
|
|
45
|
+
createdAt: string;
|
|
46
|
+
/** Optional source bundle. */
|
|
47
|
+
sourceBundleId?: string;
|
|
48
|
+
/** Optional sha256 of the source corpus. */
|
|
49
|
+
corpusSha256?: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface VoiceProfileCatalog {
|
|
53
|
+
version: typeof CATALOG_SCHEMA_VERSION;
|
|
54
|
+
/** ID of the profile to load as the default on model boot. */
|
|
55
|
+
defaultProfileId: string;
|
|
56
|
+
profiles: VoiceProfileCatalogEntry[];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface VoiceProfileRouteOptions {
|
|
60
|
+
/**
|
|
61
|
+
* Directory that holds `profiles/catalog.json` and the built-in
|
|
62
|
+
* `manifest.json`. Defaults to `<repo>/models/voice/`.
|
|
63
|
+
*/
|
|
64
|
+
voiceModelsDir?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Root of the active Eliza-1 bundle. When set, the routes also scan
|
|
67
|
+
* `<bundleRoot>/cache/voice-preset-*.bin` for bundle-shipped profiles.
|
|
68
|
+
*/
|
|
69
|
+
bundleRoot?: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const DEFAULT_PROFILE_ID = "same";
|
|
73
|
+
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// Catalog helpers
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
|
|
78
|
+
function resolveCatalogPath(voiceModelsDir: string): string {
|
|
79
|
+
return path.join(voiceModelsDir, "profiles", "catalog.json");
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function readCatalog(
|
|
83
|
+
voiceModelsDir: string,
|
|
84
|
+
): Promise<VoiceProfileCatalog> {
|
|
85
|
+
const catalogPath = resolveCatalogPath(voiceModelsDir);
|
|
86
|
+
if (!fs.existsSync(catalogPath)) {
|
|
87
|
+
return {
|
|
88
|
+
version: CATALOG_SCHEMA_VERSION,
|
|
89
|
+
defaultProfileId: DEFAULT_PROFILE_ID,
|
|
90
|
+
profiles: [],
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
const raw = await fsp.readFile(catalogPath, "utf8");
|
|
95
|
+
const parsed = JSON.parse(raw) as VoiceProfileCatalog;
|
|
96
|
+
if (!parsed.profiles) parsed.profiles = [];
|
|
97
|
+
if (!parsed.defaultProfileId) parsed.defaultProfileId = DEFAULT_PROFILE_ID;
|
|
98
|
+
parsed.version = CATALOG_SCHEMA_VERSION;
|
|
99
|
+
return parsed;
|
|
100
|
+
} catch {
|
|
101
|
+
return {
|
|
102
|
+
version: CATALOG_SCHEMA_VERSION,
|
|
103
|
+
defaultProfileId: DEFAULT_PROFILE_ID,
|
|
104
|
+
profiles: [],
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async function writeCatalog(
|
|
110
|
+
voiceModelsDir: string,
|
|
111
|
+
catalog: VoiceProfileCatalog,
|
|
112
|
+
): Promise<void> {
|
|
113
|
+
const catalogPath = resolveCatalogPath(voiceModelsDir);
|
|
114
|
+
await fsp.mkdir(path.dirname(catalogPath), { recursive: true });
|
|
115
|
+
const tmp = `${catalogPath}.tmp`;
|
|
116
|
+
await fsp.writeFile(tmp, JSON.stringify(catalog, null, 2), "utf8");
|
|
117
|
+
await fsp.rename(tmp, catalogPath);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
// Profile discovery
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
|
|
124
|
+
/** Parse a preset bin and extract the profile metadata we care about. */
|
|
125
|
+
function parsePresetMeta(
|
|
126
|
+
presetPath: string,
|
|
127
|
+
): Pick<VoicePresetFile, "instruct" | "refText" | "metadata"> | null {
|
|
128
|
+
if (!fs.existsSync(presetPath)) return null;
|
|
129
|
+
try {
|
|
130
|
+
const bytes = fs.readFileSync(presetPath);
|
|
131
|
+
const preset = readVoicePresetFile(new Uint8Array(bytes));
|
|
132
|
+
return {
|
|
133
|
+
instruct: preset.instruct,
|
|
134
|
+
refText: preset.refText,
|
|
135
|
+
metadata: preset.metadata,
|
|
136
|
+
};
|
|
137
|
+
} catch {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** Scan `<bundleRoot>/cache/` for `voice-preset-*.bin` files. */
|
|
143
|
+
function scanBundleProfiles(
|
|
144
|
+
bundleRoot: string,
|
|
145
|
+
): Array<{ id: string; presetPath: string }> {
|
|
146
|
+
const cacheDir = path.join(bundleRoot, "cache");
|
|
147
|
+
if (!fs.existsSync(cacheDir)) return [];
|
|
148
|
+
const PREFIX = "voice-preset-";
|
|
149
|
+
const SUFFIX = ".bin";
|
|
150
|
+
return fs
|
|
151
|
+
.readdirSync(cacheDir)
|
|
152
|
+
.filter((f) => f.startsWith(PREFIX) && f.endsWith(SUFFIX))
|
|
153
|
+
.map((f) => {
|
|
154
|
+
const id = f.slice(PREFIX.length, f.length - SUFFIX.length);
|
|
155
|
+
return { id, presetPath: path.join(cacheDir, f) };
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** Merge bundle-scanned profiles with catalog entries. */
|
|
160
|
+
async function listProfiles(
|
|
161
|
+
_voiceModelsDir: string,
|
|
162
|
+
bundleRoot: string | undefined,
|
|
163
|
+
catalog: VoiceProfileCatalog,
|
|
164
|
+
): Promise<
|
|
165
|
+
Array<{
|
|
166
|
+
id: string;
|
|
167
|
+
displayName: string;
|
|
168
|
+
instruct: string;
|
|
169
|
+
active: boolean;
|
|
170
|
+
isDefault: boolean;
|
|
171
|
+
source: "bundle" | "catalog";
|
|
172
|
+
createdAt: string;
|
|
173
|
+
}>
|
|
174
|
+
> {
|
|
175
|
+
const seenIds = new Set<string>();
|
|
176
|
+
const out: Array<{
|
|
177
|
+
id: string;
|
|
178
|
+
displayName: string;
|
|
179
|
+
instruct: string;
|
|
180
|
+
active: boolean;
|
|
181
|
+
isDefault: boolean;
|
|
182
|
+
source: "bundle" | "catalog";
|
|
183
|
+
createdAt: string;
|
|
184
|
+
}> = [];
|
|
185
|
+
|
|
186
|
+
// Bundle-shipped presets take priority.
|
|
187
|
+
if (bundleRoot) {
|
|
188
|
+
for (const { id, presetPath } of scanBundleProfiles(bundleRoot)) {
|
|
189
|
+
seenIds.add(id);
|
|
190
|
+
const meta = parsePresetMeta(presetPath);
|
|
191
|
+
const catalogEntry = catalog.profiles.find((e) => e.id === id);
|
|
192
|
+
const active = catalogEntry ? catalogEntry.active : true;
|
|
193
|
+
out.push({
|
|
194
|
+
id,
|
|
195
|
+
displayName: catalogEntry?.displayName ?? id,
|
|
196
|
+
instruct: catalogEntry?.instruct ?? meta?.instruct ?? "",
|
|
197
|
+
active,
|
|
198
|
+
isDefault: catalog.defaultProfileId === id,
|
|
199
|
+
source: "bundle",
|
|
200
|
+
createdAt: catalogEntry?.createdAt ?? new Date().toISOString(),
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Catalog-only profiles (not in bundle).
|
|
206
|
+
for (const entry of catalog.profiles) {
|
|
207
|
+
if (seenIds.has(entry.id)) continue;
|
|
208
|
+
out.push({
|
|
209
|
+
id: entry.id,
|
|
210
|
+
displayName: entry.displayName,
|
|
211
|
+
instruct: entry.instruct,
|
|
212
|
+
active: entry.active,
|
|
213
|
+
isDefault: catalog.defaultProfileId === entry.id,
|
|
214
|
+
source: "catalog",
|
|
215
|
+
createdAt: entry.createdAt,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return out;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// ---------------------------------------------------------------------------
|
|
223
|
+
// Route handler
|
|
224
|
+
// ---------------------------------------------------------------------------
|
|
225
|
+
|
|
226
|
+
function sendJson(
|
|
227
|
+
res: http.ServerResponse,
|
|
228
|
+
status: number,
|
|
229
|
+
body: unknown,
|
|
230
|
+
): void {
|
|
231
|
+
if (res.headersSent) return;
|
|
232
|
+
res.writeHead(status, { "content-type": "application/json; charset=utf-8" });
|
|
233
|
+
res.end(JSON.stringify(body));
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function sendError(
|
|
237
|
+
res: http.ServerResponse,
|
|
238
|
+
status: number,
|
|
239
|
+
message: string,
|
|
240
|
+
): void {
|
|
241
|
+
sendJson(res, status, { error: message });
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Route handler for all `/v1/voice/profiles*` endpoints.
|
|
246
|
+
*
|
|
247
|
+
* Returns `true` if the request was handled, `false` to pass through.
|
|
248
|
+
*/
|
|
249
|
+
export async function handleVoiceProfileRoutes(
|
|
250
|
+
req: http.IncomingMessage,
|
|
251
|
+
res: http.ServerResponse,
|
|
252
|
+
opts: VoiceProfileRouteOptions,
|
|
253
|
+
): Promise<boolean> {
|
|
254
|
+
const method = req.method?.toUpperCase() ?? "GET";
|
|
255
|
+
const rawUrl = req.url ?? "/";
|
|
256
|
+
// Strip query string for routing.
|
|
257
|
+
const pathname = rawUrl.split("?")[0] ?? rawUrl;
|
|
258
|
+
|
|
259
|
+
if (!pathname.startsWith("/v1/voice/profiles")) {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const voiceModelsDir =
|
|
264
|
+
opts.voiceModelsDir ??
|
|
265
|
+
path.join(resolveStateDir(process.env), "models", "voice");
|
|
266
|
+
const bundleRoot = opts.bundleRoot;
|
|
267
|
+
|
|
268
|
+
// -------------------------------------------------------------------
|
|
269
|
+
// GET /v1/voice/profiles
|
|
270
|
+
// -------------------------------------------------------------------
|
|
271
|
+
if (method === "GET" && pathname === "/v1/voice/profiles") {
|
|
272
|
+
const catalog = await readCatalog(voiceModelsDir);
|
|
273
|
+
const profiles = await listProfiles(voiceModelsDir, bundleRoot, catalog);
|
|
274
|
+
sendJson(res, 200, {
|
|
275
|
+
defaultProfileId: catalog.defaultProfileId,
|
|
276
|
+
profiles,
|
|
277
|
+
});
|
|
278
|
+
return true;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// -------------------------------------------------------------------
|
|
282
|
+
// POST /v1/voice/profiles/:id/activate
|
|
283
|
+
// -------------------------------------------------------------------
|
|
284
|
+
const activateMatch = /^\/v1\/voice\/profiles\/([^/]+)\/activate$/.exec(
|
|
285
|
+
pathname,
|
|
286
|
+
);
|
|
287
|
+
if (method === "POST" && activateMatch) {
|
|
288
|
+
const profileId = decodeURIComponent(activateMatch[1] ?? "");
|
|
289
|
+
if (!profileId || !/^[A-Za-z0-9._-]+$/.test(profileId)) {
|
|
290
|
+
sendError(res, 400, `Invalid profile id: ${profileId}`);
|
|
291
|
+
return true;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const catalog = await readCatalog(voiceModelsDir);
|
|
295
|
+
|
|
296
|
+
// Accept any profile that exists in the bundle or catalog.
|
|
297
|
+
const profiles = await listProfiles(voiceModelsDir, bundleRoot, catalog);
|
|
298
|
+
const target = profiles.find((p) => p.id === profileId);
|
|
299
|
+
if (!target) {
|
|
300
|
+
sendError(res, 404, `Profile '${profileId}' not found`);
|
|
301
|
+
return true;
|
|
302
|
+
}
|
|
303
|
+
if (!target.active) {
|
|
304
|
+
sendError(res, 409, `Profile '${profileId}' is inactive (soft-deleted)`);
|
|
305
|
+
return true;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Update the catalog default.
|
|
309
|
+
const prevDefault = catalog.defaultProfileId;
|
|
310
|
+
catalog.defaultProfileId = profileId;
|
|
311
|
+
|
|
312
|
+
// Ensure the profile has a catalog entry (for bundle-only profiles, create one).
|
|
313
|
+
const existingEntry = catalog.profiles.find((e) => e.id === profileId);
|
|
314
|
+
if (!existingEntry) {
|
|
315
|
+
catalog.profiles.push({
|
|
316
|
+
id: profileId,
|
|
317
|
+
displayName: target.displayName,
|
|
318
|
+
instruct: target.instruct,
|
|
319
|
+
active: true,
|
|
320
|
+
createdAt: new Date().toISOString(),
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
await writeCatalog(voiceModelsDir, catalog);
|
|
325
|
+
|
|
326
|
+
sendJson(res, 200, {
|
|
327
|
+
defaultProfileId: profileId,
|
|
328
|
+
previousDefaultProfileId: prevDefault,
|
|
329
|
+
});
|
|
330
|
+
return true;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// -------------------------------------------------------------------
|
|
334
|
+
// DELETE /v1/voice/profiles/:id
|
|
335
|
+
// -------------------------------------------------------------------
|
|
336
|
+
const deleteMatch = /^\/v1\/voice\/profiles\/([^/]+)$/.exec(pathname);
|
|
337
|
+
if (method === "DELETE" && deleteMatch) {
|
|
338
|
+
const profileId = decodeURIComponent(deleteMatch[1] ?? "");
|
|
339
|
+
if (!profileId || !/^[A-Za-z0-9._-]+$/.test(profileId)) {
|
|
340
|
+
sendError(res, 400, `Invalid profile id: ${profileId}`);
|
|
341
|
+
return true;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const catalog = await readCatalog(voiceModelsDir);
|
|
345
|
+
|
|
346
|
+
if (catalog.defaultProfileId === profileId) {
|
|
347
|
+
sendError(
|
|
348
|
+
res,
|
|
349
|
+
409,
|
|
350
|
+
`Cannot delete the active default profile '${profileId}'. Activate a different profile first.`,
|
|
351
|
+
);
|
|
352
|
+
return true;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// Soft-delete: mark inactive in catalog. Never unlinks shipped bundle files.
|
|
356
|
+
const existingEntry = catalog.profiles.find((e) => e.id === profileId);
|
|
357
|
+
if (existingEntry) {
|
|
358
|
+
existingEntry.active = false;
|
|
359
|
+
} else {
|
|
360
|
+
// Profile exists in bundle but is absent from catalog — add as inactive.
|
|
361
|
+
const profiles = await listProfiles(voiceModelsDir, bundleRoot, catalog);
|
|
362
|
+
const target = profiles.find((p) => p.id === profileId);
|
|
363
|
+
if (!target) {
|
|
364
|
+
sendError(res, 404, `Profile '${profileId}' not found`);
|
|
365
|
+
return true;
|
|
366
|
+
}
|
|
367
|
+
catalog.profiles.push({
|
|
368
|
+
id: profileId,
|
|
369
|
+
displayName: target.displayName,
|
|
370
|
+
instruct: target.instruct,
|
|
371
|
+
active: false,
|
|
372
|
+
createdAt: new Date().toISOString(),
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
await writeCatalog(voiceModelsDir, catalog);
|
|
377
|
+
sendJson(res, 200, { deleted: profileId, active: false });
|
|
378
|
+
return true;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
return false;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// ---------------------------------------------------------------------------
|
|
385
|
+
// Server-side default profile loading
|
|
386
|
+
// ---------------------------------------------------------------------------
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Resolve the active default profile id from the voice catalog.
|
|
390
|
+
*
|
|
391
|
+
* Called at model boot (before `EngineVoiceBridge.start()`) to determine
|
|
392
|
+
* which `voice-preset-<id>.bin` to load as the default voice. Returns
|
|
393
|
+
* `"default"` when the catalog has no explicit default set.
|
|
394
|
+
*/
|
|
395
|
+
export async function resolveDefaultProfileId(
|
|
396
|
+
voiceModelsDir: string,
|
|
397
|
+
): Promise<string> {
|
|
398
|
+
const catalog = await readCatalog(voiceModelsDir);
|
|
399
|
+
return catalog.defaultProfileId || DEFAULT_PROFILE_ID;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Persist a newly created profile into the voice catalog.
|
|
404
|
+
*
|
|
405
|
+
* Called by `bun run voice:create-profile` after the freeze pipeline
|
|
406
|
+
* writes the preset binary. Appends an entry to `catalog.json` if the
|
|
407
|
+
* profile id is not already there; updates instruct + displayName if it is.
|
|
408
|
+
*/
|
|
409
|
+
export async function registerProfileInCatalog(
|
|
410
|
+
voiceModelsDir: string,
|
|
411
|
+
entry: Omit<VoiceProfileCatalogEntry, "active"> & { active?: boolean },
|
|
412
|
+
): Promise<void> {
|
|
413
|
+
const catalog = await readCatalog(voiceModelsDir);
|
|
414
|
+
const existing = catalog.profiles.findIndex((e) => e.id === entry.id);
|
|
415
|
+
const full: VoiceProfileCatalogEntry = {
|
|
416
|
+
...entry,
|
|
417
|
+
active: entry.active ?? true,
|
|
418
|
+
};
|
|
419
|
+
if (existing >= 0) {
|
|
420
|
+
catalog.profiles[existing] = full;
|
|
421
|
+
} else {
|
|
422
|
+
catalog.profiles.push(full);
|
|
423
|
+
}
|
|
424
|
+
await writeCatalog(voiceModelsDir, catalog);
|
|
425
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Voice Workbench scenario schema (#8785).
|
|
3
|
+
*
|
|
4
|
+
* One declarative format for a voice conversation that BOTH the headless runner
|
|
5
|
+
* (real services: ASR / diarization / EOT / respond / TTS over a corpus) and
|
|
6
|
+
* the headful scenario player (the real frontend client pipeline) execute, and
|
|
7
|
+
* that the benchmark layer scores. A scenario is an ordered list of turns plus
|
|
8
|
+
* named participants and scenario-level assertions; each turn declares the
|
|
9
|
+
* expected behavior (respond / don't, transcript, speaker label, entity) so the
|
|
10
|
+
* runner can score against ground truth.
|
|
11
|
+
*
|
|
12
|
+
* Pure types + a pure validator — no model loading, no I/O — so it is safe to
|
|
13
|
+
* import from the runner, the player, and tests alike.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/** A named voice/entity participating in the scenario. */
|
|
17
|
+
export interface VoiceScenarioParticipant {
|
|
18
|
+
/** Stable label used in turns + diarization ground truth (e.g. "alice"). */
|
|
19
|
+
label: string;
|
|
20
|
+
/** TTS voice id used to synthesize this participant's turns in the corpus. */
|
|
21
|
+
ttsVoiceId?: string;
|
|
22
|
+
/** The elizaOS entity id this voice should resolve to (voice→entity match). */
|
|
23
|
+
entityId?: string;
|
|
24
|
+
/** True when this participant is the device owner / primary enrolled speaker. */
|
|
25
|
+
isOwner?: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** One spoken turn in the scenario. */
|
|
29
|
+
export interface VoiceScenarioTurn {
|
|
30
|
+
/** Participant label (must exist in `participants`). */
|
|
31
|
+
speaker: string;
|
|
32
|
+
/** Spoken text — synthesized to audio by the corpus generator. */
|
|
33
|
+
text?: string;
|
|
34
|
+
/** OR a reference to a pre-recorded/-generated audio file under the corpus. */
|
|
35
|
+
audioRef?: string;
|
|
36
|
+
/** Override the participant's default TTS voice for this turn. */
|
|
37
|
+
ttsVoiceId?: string;
|
|
38
|
+
/** Silent gaps (ms) spliced AFTER this turn's audio (pauses / barge-in gaps). */
|
|
39
|
+
pausesMs?: number[];
|
|
40
|
+
/** Ground truth: SHOULD the agent respond to this turn? */
|
|
41
|
+
expectRespond: boolean;
|
|
42
|
+
/** Expected ASR transcript (for WER scoring); defaults to `text`. */
|
|
43
|
+
expectedTranscript?: string;
|
|
44
|
+
/** Expected diarization label (defaults to `speaker`). */
|
|
45
|
+
expectedSpeakerLabel?: string;
|
|
46
|
+
/** Expected entity inferred/recognized from this turn (name extraction). */
|
|
47
|
+
expectedEntity?: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Scenario-level pass/fail thresholds the benchmark layer enforces. */
|
|
51
|
+
export interface VoiceScenarioAssertions {
|
|
52
|
+
/** Max word-error-rate across the scenario's transcripts. */
|
|
53
|
+
maxWer?: number;
|
|
54
|
+
/** Max diarization error rate. */
|
|
55
|
+
maxDer?: number;
|
|
56
|
+
/** Min respond-decision accuracy. */
|
|
57
|
+
minRespondAccuracy?: number;
|
|
58
|
+
/** Max EOT false-trigger rate. */
|
|
59
|
+
maxEotFalseTriggerRate?: number;
|
|
60
|
+
/** Min voice→entity match rate. */
|
|
61
|
+
minVoiceEntityMatchRate?: number;
|
|
62
|
+
/** Latency budgets (ms) — first-audio / time-to-first-token, etc. */
|
|
63
|
+
maxFirstAudioMs?: number;
|
|
64
|
+
maxTtftMs?: number;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export type VoiceScenarioClass =
|
|
68
|
+
| "multi-voice"
|
|
69
|
+
| "pauses"
|
|
70
|
+
| "respond-no-respond"
|
|
71
|
+
| "multi-speaker"
|
|
72
|
+
| "diarization"
|
|
73
|
+
| "entity-extraction"
|
|
74
|
+
| "voice-recognition"
|
|
75
|
+
| "eot"
|
|
76
|
+
| "transcription-mode"
|
|
77
|
+
| "multi-agent-room"
|
|
78
|
+
| "long-form-monologue";
|
|
79
|
+
|
|
80
|
+
export interface VoiceScenario {
|
|
81
|
+
/** Stable id (also the corpus subdirectory name). */
|
|
82
|
+
id: string;
|
|
83
|
+
/** Human description of what the scenario exercises. */
|
|
84
|
+
description?: string;
|
|
85
|
+
/** Which scenario class(es) this belongs to (drives the headful spec matrix). */
|
|
86
|
+
classes: VoiceScenarioClass[];
|
|
87
|
+
participants: VoiceScenarioParticipant[];
|
|
88
|
+
turns: VoiceScenarioTurn[];
|
|
89
|
+
assertions?: VoiceScenarioAssertions;
|
|
90
|
+
/** Agent labels present in a multi-agent room (subset of participants). */
|
|
91
|
+
agents?: string[];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface VoiceScenarioValidation {
|
|
95
|
+
valid: boolean;
|
|
96
|
+
errors: string[];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Validate a scenario's internal consistency (pure; no I/O). Checks ids,
|
|
101
|
+
* participant references, turn audio/text presence, and that any agents named
|
|
102
|
+
* exist as participants. Returns all errors (does not throw) so a corpus build
|
|
103
|
+
* can report every problem at once.
|
|
104
|
+
*/
|
|
105
|
+
export function validateVoiceScenario(
|
|
106
|
+
scenario: VoiceScenario,
|
|
107
|
+
): VoiceScenarioValidation {
|
|
108
|
+
const errors: string[] = [];
|
|
109
|
+
if (!scenario.id?.trim()) errors.push("scenario.id is required");
|
|
110
|
+
if (!Array.isArray(scenario.classes) || scenario.classes.length === 0) {
|
|
111
|
+
errors.push("scenario.classes must be a non-empty array");
|
|
112
|
+
}
|
|
113
|
+
const labels = new Set<string>();
|
|
114
|
+
for (const p of scenario.participants ?? []) {
|
|
115
|
+
if (!p.label?.trim()) {
|
|
116
|
+
errors.push("participant.label is required");
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (labels.has(p.label))
|
|
120
|
+
errors.push(`duplicate participant label: ${p.label}`);
|
|
121
|
+
labels.add(p.label);
|
|
122
|
+
}
|
|
123
|
+
if (labels.size === 0) errors.push("scenario.participants must be non-empty");
|
|
124
|
+
if (!Array.isArray(scenario.turns) || scenario.turns.length === 0) {
|
|
125
|
+
errors.push("scenario.turns must be a non-empty array");
|
|
126
|
+
}
|
|
127
|
+
scenario.turns?.forEach((t, i) => {
|
|
128
|
+
if (!labels.has(t.speaker)) {
|
|
129
|
+
errors.push(`turn[${i}].speaker "${t.speaker}" is not a participant`);
|
|
130
|
+
}
|
|
131
|
+
if (!t.text?.trim() && !t.audioRef?.trim()) {
|
|
132
|
+
errors.push(`turn[${i}] must have either text or audioRef`);
|
|
133
|
+
}
|
|
134
|
+
if (typeof t.expectRespond !== "boolean") {
|
|
135
|
+
errors.push(`turn[${i}].expectRespond must be a boolean`);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
for (const agent of scenario.agents ?? []) {
|
|
139
|
+
if (!labels.has(agent)) {
|
|
140
|
+
errors.push(`agent "${agent}" is not a participant`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return { valid: errors.length === 0, errors };
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** The expected ASR reference for a turn (explicit override or its text). */
|
|
147
|
+
export function turnReferenceTranscript(turn: VoiceScenarioTurn): string {
|
|
148
|
+
return (turn.expectedTranscript ?? turn.text ?? "").trim();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** The expected diarization label for a turn (explicit override or speaker). */
|
|
152
|
+
export function turnSpeakerLabel(turn: VoiceScenarioTurn): string {
|
|
153
|
+
return turn.expectedSpeakerLabel ?? turn.speaker;
|
|
154
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Voice settings — the user-facing knobs the runtime + UI consume to
|
|
3
|
+
* decide local vs cloud, model quality, RAM cap, and quant downgrade.
|
|
4
|
+
*
|
|
5
|
+
* R9 §5 spells out the five knobs:
|
|
6
|
+
*
|
|
7
|
+
* 1. `voice.forceLocal` / `voice.forceCloud` / `voice.autoSwap` — backend
|
|
8
|
+
* mode (auto by default).
|
|
9
|
+
* 2. `voice.modelQualityPreset` — `"max" | "balanced" | "minimal"`.
|
|
10
|
+
* 3. `voice.maxRamMB` — hard cap on the allocator's total budget.
|
|
11
|
+
* 4. `voice.allowQuantDowngrade` — auto-pick smaller quants if RAM tight.
|
|
12
|
+
*
|
|
13
|
+
* This module is the env-var resolver + the canonical default table. The
|
|
14
|
+
* dashboard's Settings panel writes the same fields to `messages.voice.*`
|
|
15
|
+
* config; I10 wires the persistent store. For now (I9 scope), the resolver
|
|
16
|
+
* reads env + an optional `Partial<VoiceSettings>` overlay so tests can
|
|
17
|
+
* lock in deterministic behaviour.
|
|
18
|
+
*
|
|
19
|
+
* There is no central `settings.ts` to extend in `plugins/plugin-local-
|
|
20
|
+
* inference/src/services/` today (R9 §1 path inventory confirms it).
|
|
21
|
+
* Keeping this file in `voice/` makes its surface area obvious.
|
|
22
|
+
*/
|
|
23
|
+
import type { DeviceTier } from "../device-tier";
|
|
24
|
+
export type VoiceBackendMode = "auto" | "force-local" | "force-cloud";
|
|
25
|
+
export type VoiceModelQualityPreset = "max" | "balanced" | "minimal";
|
|
26
|
+
export interface VoiceSettings {
|
|
27
|
+
/** Backend selection mode. `auto` consults the device tier. */
|
|
28
|
+
backendMode: VoiceBackendMode;
|
|
29
|
+
/** When `backendMode === "auto"`, allow the runtime to swap between
|
|
30
|
+
* cloud and local in mid-session to keep latency bounded. */
|
|
31
|
+
autoSwap: boolean;
|
|
32
|
+
/** Quality vs RAM tradeoff. Maps to a quant ladder for the LM + voice
|
|
33
|
+
* stack — see `qualityPresetQuantizationRanking()`. */
|
|
34
|
+
modelQualityPreset: VoiceModelQualityPreset;
|
|
35
|
+
/** Hard cap on the allocator's total budget, in MB. 0 / null = use the
|
|
36
|
+
* tier's natural total. */
|
|
37
|
+
maxRamMb: number | null;
|
|
38
|
+
/** When true (default), an OOM-pending reservation may pick a smaller
|
|
39
|
+
* quant variant instead of refusing. When false, `reserve()` throws. */
|
|
40
|
+
allowQuantDowngrade: boolean;
|
|
41
|
+
/** Continuous local recording on mobile when on battery. Off by default. */
|
|
42
|
+
continuousLocalRecordingOnBattery: boolean;
|
|
43
|
+
}
|
|
44
|
+
declare const DEFAULT_VOICE_SETTINGS: VoiceSettings;
|
|
45
|
+
/**
|
|
46
|
+
* Resolve voice settings from environment + an optional overlay.
|
|
47
|
+
* Env wins over defaults; overlay wins over env (so tests / UI can lock
|
|
48
|
+
* specific fields). All fields are required in the returned settings.
|
|
49
|
+
*
|
|
50
|
+
* Env knobs (canonical ELIZA_* prefix; ELIZA_* aliases honored upstream):
|
|
51
|
+
*
|
|
52
|
+
* - `ELIZA_VOICE_BACKEND_MODE` → backendMode
|
|
53
|
+
* - `ELIZA_VOICE_AUTO_SWAP` → autoSwap
|
|
54
|
+
* - `ELIZA_VOICE_QUALITY_PRESET` → modelQualityPreset
|
|
55
|
+
* - `ELIZA_VOICE_MAX_RAM_MB` → maxRamMb
|
|
56
|
+
* - `ELIZA_VOICE_ALLOW_QUANT_DOWNGRADE` → allowQuantDowngrade
|
|
57
|
+
* - `ELIZA_VOICE_CONTINUOUS_ON_BATTERY` → continuousLocalRecordingOnBattery
|
|
58
|
+
*/
|
|
59
|
+
export declare function resolveVoiceSettings(overlay?: Partial<VoiceSettings>, env?: NodeJS.ProcessEnv): VoiceSettings;
|
|
60
|
+
/**
|
|
61
|
+
* Default backend mode given the user's settings + the device tier. R9 §5:
|
|
62
|
+
*
|
|
63
|
+
* - `force-local` overrides the mobile-cloud-default;
|
|
64
|
+
* - `force-cloud` overrides the desktop-local-default;
|
|
65
|
+
* - `auto` consults the tier (MAX/GOOD → local; OKAY/POOR → cloud).
|
|
66
|
+
*
|
|
67
|
+
* Returns the resolved mode the runtime should *act on*, taking the tier
|
|
68
|
+
* into account.
|
|
69
|
+
*/
|
|
70
|
+
export declare function effectiveBackendMode(settings: VoiceSettings, tier: DeviceTier): "local" | "cloud";
|
|
71
|
+
/**
|
|
72
|
+
* Ordered quant ladder per quality preset. Most-preferred first. Loaders
|
|
73
|
+
* pick the most-preferred variant that fits the budget; `allowQuantDowngrade`
|
|
74
|
+
* controls whether they slide down the ladder when the top choice doesn't
|
|
75
|
+
* fit.
|
|
76
|
+
*
|
|
77
|
+
* Names match the catalog ids in `recommendation.ts:textQuantizationMatrix`
|
|
78
|
+
* + the voice stack's documented variants.
|
|
79
|
+
*/
|
|
80
|
+
export declare function qualityPresetQuantizationRanking(preset: VoiceModelQualityPreset): ReadonlyArray<string>;
|
|
81
|
+
export { DEFAULT_VOICE_SETTINGS };
|
|
82
|
+
//# sourceMappingURL=voice-settings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voice-settings.d.ts","sourceRoot":"","sources":["voice-settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,aAAa,GAAG,aAAa,CAAC;AACtE,MAAM,MAAM,uBAAuB,GAAG,KAAK,GAAG,UAAU,GAAG,SAAS,CAAC;AAErE,MAAM,WAAW,aAAa;IAC7B,+DAA+D;IAC/D,WAAW,EAAE,gBAAgB,CAAC;IAC9B;kEAC8D;IAC9D,QAAQ,EAAE,OAAO,CAAC;IAClB;4DACwD;IACxD,kBAAkB,EAAE,uBAAuB,CAAC;IAC5C;gCAC4B;IAC5B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;6EACyE;IACzE,mBAAmB,EAAE,OAAO,CAAC;IAC7B,4EAA4E;IAC5E,iCAAiC,EAAE,OAAO,CAAC;CAC3C;AAED,QAAA,MAAM,sBAAsB,EAAE,aAO7B,CAAC;AAqCF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CACnC,OAAO,GAAE,OAAO,CAAC,aAAa,CAAM,EACpC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAClC,aAAa,CAkBf;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CACnC,QAAQ,EAAE,aAAa,EACvB,IAAI,EAAE,UAAU,GACd,OAAO,GAAG,OAAO,CAMnB;AAED;;;;;;;;GAQG;AACH,wBAAgB,gCAAgC,CAC/C,MAAM,EAAE,uBAAuB,GAC7B,aAAa,CAAC,MAAM,CAAC,CASvB;AAED,OAAO,EAAE,sBAAsB,EAAE,CAAC"}
|