@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.
Files changed (893) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +157 -0
  3. package/dist/actions/generate-media.d.ts +59 -0
  4. package/dist/actions/generate-media.d.ts.map +1 -0
  5. package/dist/actions/identify-speaker.d.ts +23 -0
  6. package/dist/actions/identify-speaker.d.ts.map +1 -0
  7. package/dist/actions/transcription-control.d.ts +29 -0
  8. package/dist/actions/transcription-control.d.ts.map +1 -0
  9. package/dist/adapters/capacitor-llama/environment.d.ts +12 -0
  10. package/dist/adapters/capacitor-llama/environment.d.ts.map +1 -0
  11. package/dist/adapters/capacitor-llama/index.browser.d.ts +9 -0
  12. package/dist/adapters/capacitor-llama/index.browser.d.ts.map +1 -0
  13. package/dist/adapters/capacitor-llama/index.d.ts +18 -0
  14. package/dist/adapters/capacitor-llama/index.d.ts.map +1 -0
  15. package/dist/adapters/capacitor-llama/loader.d.ts +35 -0
  16. package/dist/adapters/capacitor-llama/loader.d.ts.map +1 -0
  17. package/dist/adapters/capacitor-llama/native-voice-capture.d.ts +70 -0
  18. package/dist/adapters/capacitor-llama/native-voice-capture.d.ts.map +1 -0
  19. package/dist/adapters/capacitor-llama/structured-output.d.ts +62 -0
  20. package/dist/adapters/capacitor-llama/structured-output.d.ts.map +1 -0
  21. package/dist/adapters/capacitor-llama/text-streaming.d.ts +24 -0
  22. package/dist/adapters/capacitor-llama/text-streaming.d.ts.map +1 -0
  23. package/dist/adapters/capacitor-llama/types.d.ts +338 -0
  24. package/dist/adapters/capacitor-llama/types.d.ts.map +1 -0
  25. package/dist/adapters/capacitor-llama/voice-turn.d.ts +86 -0
  26. package/dist/adapters/capacitor-llama/voice-turn.d.ts.map +1 -0
  27. package/dist/backends/apple-foundation.d.ts +56 -0
  28. package/dist/backends/apple-foundation.d.ts.map +1 -0
  29. package/dist/index.d.ts +8 -37
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +38979 -430
  32. package/dist/index.js.map +217 -0
  33. package/dist/local-inference-routes.d.ts +47 -0
  34. package/dist/local-inference-routes.d.ts.map +1 -0
  35. package/dist/provider.d.ts +21 -0
  36. package/dist/provider.d.ts.map +1 -0
  37. package/dist/routes/compat-helpers.d.ts +18 -0
  38. package/dist/routes/compat-helpers.d.ts.map +1 -0
  39. package/dist/routes/family-member-route.d.ts +62 -0
  40. package/dist/routes/family-member-route.d.ts.map +1 -0
  41. package/dist/routes/index.d.ts +20 -0
  42. package/dist/routes/index.d.ts.map +1 -0
  43. package/dist/routes/index.js +42040 -0
  44. package/dist/routes/index.js.map +236 -0
  45. package/dist/routes/live-diarization-route.d.ts +33 -0
  46. package/dist/routes/live-diarization-route.d.ts.map +1 -0
  47. package/dist/routes/local-inference-asr-route.d.ts +4 -0
  48. package/dist/routes/local-inference-asr-route.d.ts.map +1 -0
  49. package/dist/routes/local-inference-asr-transcribe.d.ts +20 -0
  50. package/dist/routes/local-inference-asr-transcribe.d.ts.map +1 -0
  51. package/dist/routes/local-inference-compat-routes.d.ts +16 -0
  52. package/dist/routes/local-inference-compat-routes.d.ts.map +1 -0
  53. package/dist/routes/local-inference-tts-route.d.ts +7 -0
  54. package/dist/routes/local-inference-tts-route.d.ts.map +1 -0
  55. package/dist/routes/native-pcm-turn-route.d.ts +3 -0
  56. package/dist/routes/native-pcm-turn-route.d.ts.map +1 -0
  57. package/dist/routes/transcript-audio-store.d.ts +15 -0
  58. package/dist/routes/transcript-audio-store.d.ts.map +1 -0
  59. package/dist/routes/transcripts-routes.d.ts +44 -0
  60. package/dist/routes/transcripts-routes.d.ts.map +1 -0
  61. package/dist/routes/voice-first-run-routes.d.ts +62 -0
  62. package/dist/routes/voice-first-run-routes.d.ts.map +1 -0
  63. package/dist/routes/voice-models-routes.d.ts +62 -0
  64. package/dist/routes/voice-models-routes.d.ts.map +1 -0
  65. package/dist/routes/voice-profile-plugin-routes.d.ts +19 -0
  66. package/dist/routes/voice-profile-plugin-routes.d.ts.map +1 -0
  67. package/dist/routes/voice-profiles-management-routes.d.ts +52 -0
  68. package/dist/routes/voice-profiles-management-routes.d.ts.map +1 -0
  69. package/dist/routes/voice-speaker-profile-routes.d.ts +57 -0
  70. package/dist/routes/voice-speaker-profile-routes.d.ts.map +1 -0
  71. package/dist/runtime/embedding-manager-support.d.ts +77 -0
  72. package/dist/runtime/embedding-manager-support.d.ts.map +1 -0
  73. package/dist/runtime/embedding-presets.d.ts +16 -0
  74. package/dist/runtime/embedding-presets.d.ts.map +1 -0
  75. package/dist/runtime/embedding-warmup-policy.d.ts +14 -0
  76. package/dist/runtime/embedding-warmup-policy.d.ts.map +1 -0
  77. package/dist/runtime/ensure-local-inference-handler.d.ts +70 -0
  78. package/dist/runtime/ensure-local-inference-handler.d.ts.map +1 -0
  79. package/dist/runtime/index.d.ts +15 -0
  80. package/dist/runtime/index.d.ts.map +1 -0
  81. package/dist/runtime/index.js +38768 -0
  82. package/dist/runtime/index.js.map +217 -0
  83. package/dist/runtime/mobile-local-inference-gate.d.ts +63 -0
  84. package/dist/runtime/mobile-local-inference-gate.d.ts.map +1 -0
  85. package/dist/runtime/voice-entity-binding.d.ts +113 -0
  86. package/dist/runtime/voice-entity-binding.d.ts.map +1 -0
  87. package/dist/services/active-model.d.ts +310 -0
  88. package/dist/services/active-model.d.ts.map +1 -0
  89. package/dist/services/asr-provenance.d.ts +5 -0
  90. package/dist/services/asr-provenance.d.ts.map +1 -0
  91. package/dist/services/assignments.d.ts +84 -0
  92. package/dist/services/assignments.d.ts.map +1 -0
  93. package/dist/services/backend-selector.d.ts +55 -0
  94. package/dist/services/backend-selector.d.ts.map +1 -0
  95. package/dist/services/backend.d.ts +440 -0
  96. package/dist/services/backend.d.ts.map +1 -0
  97. package/dist/services/bionic-host-loader.d.ts +67 -0
  98. package/dist/services/bionic-host-loader.d.ts.map +1 -0
  99. package/dist/services/bundled-models.d.ts +34 -0
  100. package/dist/services/bundled-models.d.ts.map +1 -0
  101. package/dist/services/cache-bridge.d.ts +206 -0
  102. package/dist/services/cache-bridge.d.ts.map +1 -0
  103. package/dist/services/catalog.d.ts +10 -0
  104. package/dist/services/catalog.d.ts.map +1 -0
  105. package/dist/services/checkpoint-client.d.ts +109 -0
  106. package/dist/services/checkpoint-client.d.ts.map +1 -0
  107. package/dist/services/checkpoint-manager.d.ts +217 -0
  108. package/dist/services/checkpoint-manager.d.ts.map +1 -0
  109. package/dist/services/cloud-fallback.d.ts +102 -0
  110. package/dist/services/cloud-fallback.d.ts.map +1 -0
  111. package/dist/services/context-fit.d.ts +36 -0
  112. package/dist/services/context-fit.d.ts.map +1 -0
  113. package/dist/services/conversation-registry.d.ts +142 -0
  114. package/dist/services/conversation-registry.d.ts.map +1 -0
  115. package/dist/services/desktop-fused-ffi-backend-runtime.d.ts +111 -0
  116. package/dist/services/desktop-fused-ffi-backend-runtime.d.ts.map +1 -0
  117. package/dist/services/device-bridge.d.ts +188 -0
  118. package/dist/services/device-bridge.d.ts.map +1 -0
  119. package/dist/services/device-resource-metrics.d.ts +149 -0
  120. package/dist/services/device-resource-metrics.d.ts.map +1 -0
  121. package/dist/services/device-tier.d.ts +133 -0
  122. package/dist/services/device-tier.d.ts.map +1 -0
  123. package/dist/services/downloader.d.ts +94 -0
  124. package/dist/services/downloader.d.ts.map +1 -0
  125. package/dist/services/engine.d.ts +579 -0
  126. package/dist/services/engine.d.ts.map +1 -0
  127. package/dist/services/ensure-local-artifacts.d.ts +82 -0
  128. package/dist/services/ensure-local-artifacts.d.ts.map +1 -0
  129. package/dist/services/external-scanner.d.ts +17 -0
  130. package/dist/services/external-scanner.d.ts.map +1 -0
  131. package/dist/services/ffi-llm-mock.d.ts +90 -0
  132. package/dist/services/ffi-llm-mock.d.ts.map +1 -0
  133. package/dist/services/ffi-llm-streaming-abi.d.ts +318 -0
  134. package/dist/services/ffi-llm-streaming-abi.d.ts.map +1 -0
  135. package/dist/services/ffi-streaming-backend.d.ts +201 -0
  136. package/dist/services/ffi-streaming-backend.d.ts.map +1 -0
  137. package/dist/services/ffi-streaming-runner.d.ts +146 -0
  138. package/dist/services/ffi-streaming-runner.d.ts.map +1 -0
  139. package/dist/services/gpu-autotune.d.ts +150 -0
  140. package/dist/services/gpu-autotune.d.ts.map +1 -0
  141. package/dist/services/gpu-detect.d.ts +56 -0
  142. package/dist/services/gpu-detect.d.ts.map +1 -0
  143. package/dist/services/handler-registry.d.ts +72 -0
  144. package/dist/services/handler-registry.d.ts.map +1 -0
  145. package/dist/services/hardware.d.ts +63 -0
  146. package/dist/services/hardware.d.ts.map +1 -0
  147. package/dist/services/image-description-runtime.d.ts +14 -0
  148. package/dist/services/image-description-runtime.d.ts.map +1 -0
  149. package/dist/services/imagegen/aosp-unavailable.d.ts +134 -0
  150. package/dist/services/imagegen/aosp-unavailable.d.ts.map +1 -0
  151. package/dist/services/imagegen/backend-selector.d.ts +118 -0
  152. package/dist/services/imagegen/backend-selector.d.ts.map +1 -0
  153. package/dist/services/imagegen/coreml-unavailable.d.ts +105 -0
  154. package/dist/services/imagegen/coreml-unavailable.d.ts.map +1 -0
  155. package/dist/services/imagegen/errors.d.ts +16 -0
  156. package/dist/services/imagegen/errors.d.ts.map +1 -0
  157. package/dist/services/imagegen/index.d.ts +58 -0
  158. package/dist/services/imagegen/index.d.ts.map +1 -0
  159. package/dist/services/imagegen/mflux.d.ts +74 -0
  160. package/dist/services/imagegen/mflux.d.ts.map +1 -0
  161. package/dist/services/imagegen/sd-cpp.d.ts +181 -0
  162. package/dist/services/imagegen/sd-cpp.d.ts.map +1 -0
  163. package/dist/services/imagegen/tensorrt-unavailable.d.ts +83 -0
  164. package/dist/services/imagegen/tensorrt-unavailable.d.ts.map +1 -0
  165. package/dist/services/imagegen/types.d.ts +181 -0
  166. package/dist/services/imagegen/types.d.ts.map +1 -0
  167. package/dist/services/index.d.ts +31 -0
  168. package/dist/services/index.d.ts.map +1 -0
  169. package/dist/services/index.js +39453 -0
  170. package/dist/services/index.js.map +227 -0
  171. package/dist/services/inference-capabilities.d.ts +132 -0
  172. package/dist/services/inference-capabilities.d.ts.map +1 -0
  173. package/dist/services/inference-telemetry.d.ts +59 -0
  174. package/dist/services/inference-telemetry.d.ts.map +1 -0
  175. package/dist/services/ios-llama-streaming.d.ts +119 -0
  176. package/dist/services/ios-llama-streaming.d.ts.map +1 -0
  177. package/dist/services/kv-spill.d.ts +189 -0
  178. package/dist/services/kv-spill.d.ts.map +1 -0
  179. package/dist/services/latency-trace.d.ts +346 -0
  180. package/dist/services/latency-trace.d.ts.map +1 -0
  181. package/dist/services/lib-target.d.ts +55 -0
  182. package/dist/services/lib-target.d.ts.map +1 -0
  183. package/dist/services/live-signals.d.ts +86 -0
  184. package/dist/services/live-signals.d.ts.map +1 -0
  185. package/dist/services/llama-server-metrics.d.ts +114 -0
  186. package/dist/services/llama-server-metrics.d.ts.map +1 -0
  187. package/dist/services/llm-streaming-binding.d.ts +96 -0
  188. package/dist/services/llm-streaming-binding.d.ts.map +1 -0
  189. package/dist/services/load-args.d.ts +82 -0
  190. package/dist/services/load-args.d.ts.map +1 -0
  191. package/dist/services/manifest/index.d.ts +4 -0
  192. package/dist/services/manifest/index.d.ts.map +1 -0
  193. package/dist/services/manifest/schema.d.ts +903 -0
  194. package/dist/services/manifest/schema.d.ts.map +1 -0
  195. package/dist/services/manifest/types.d.ts +32 -0
  196. package/dist/services/manifest/types.d.ts.map +1 -0
  197. package/dist/services/manifest/validator.d.ts +66 -0
  198. package/dist/services/manifest/validator.d.ts.map +1 -0
  199. package/dist/services/memory-arbiter.d.ts +348 -0
  200. package/dist/services/memory-arbiter.d.ts.map +1 -0
  201. package/dist/services/memory-benchmark.d.ts +76 -0
  202. package/dist/services/memory-benchmark.d.ts.map +1 -0
  203. package/dist/services/memory-monitor.d.ts +128 -0
  204. package/dist/services/memory-monitor.d.ts.map +1 -0
  205. package/dist/services/memory-pressure.d.ts +130 -0
  206. package/dist/services/memory-pressure.d.ts.map +1 -0
  207. package/dist/services/mtp-doctor.d.ts +13 -0
  208. package/dist/services/mtp-doctor.d.ts.map +1 -0
  209. package/dist/services/network-policy.d.ts +127 -0
  210. package/dist/services/network-policy.d.ts.map +1 -0
  211. package/dist/services/paths.d.ts +6 -0
  212. package/dist/services/paths.d.ts.map +1 -0
  213. package/dist/services/planner-skeleton.d.ts +124 -0
  214. package/dist/services/planner-skeleton.d.ts.map +1 -0
  215. package/dist/services/providers.d.ts +38 -0
  216. package/dist/services/providers.d.ts.map +1 -0
  217. package/dist/services/ram-budget.d.ts +110 -0
  218. package/dist/services/ram-budget.d.ts.map +1 -0
  219. package/dist/services/readiness.d.ts +9 -0
  220. package/dist/services/readiness.d.ts.map +1 -0
  221. package/dist/services/recommendation.d.ts +111 -0
  222. package/dist/services/recommendation.d.ts.map +1 -0
  223. package/dist/services/registry.d.ts +33 -0
  224. package/dist/services/registry.d.ts.map +1 -0
  225. package/dist/services/router-handler.d.ts +92 -0
  226. package/dist/services/router-handler.d.ts.map +1 -0
  227. package/dist/services/routing-policy.d.ts +92 -0
  228. package/dist/services/routing-policy.d.ts.map +1 -0
  229. package/dist/services/routing-preferences.d.ts +8 -0
  230. package/dist/services/routing-preferences.d.ts.map +1 -0
  231. package/dist/services/runtime-target.d.ts +98 -0
  232. package/dist/services/runtime-target.d.ts.map +1 -0
  233. package/dist/services/service.d.ts +128 -0
  234. package/dist/services/service.d.ts.map +1 -0
  235. package/dist/services/session-pool.d.ts +72 -0
  236. package/dist/services/session-pool.d.ts.map +1 -0
  237. package/dist/services/structured-output/deterministic-repair.d.ts +23 -0
  238. package/dist/services/structured-output/deterministic-repair.d.ts.map +1 -0
  239. package/dist/services/structured-output/index.d.ts +2 -0
  240. package/dist/services/structured-output/index.d.ts.map +1 -0
  241. package/dist/services/structured-output.d.ts +311 -0
  242. package/dist/services/structured-output.d.ts.map +1 -0
  243. package/dist/services/system-memory.d.ts +33 -0
  244. package/dist/services/system-memory.d.ts.map +1 -0
  245. package/dist/services/types.d.ts +19 -0
  246. package/dist/services/types.d.ts.map +1 -0
  247. package/dist/services/verify-on-device.d.ts +34 -0
  248. package/dist/services/verify-on-device.d.ts.map +1 -0
  249. package/dist/services/verify.d.ts +8 -0
  250. package/dist/services/verify.d.ts.map +1 -0
  251. package/dist/services/vision/aosp-unavailable.d.ts +115 -0
  252. package/dist/services/vision/aosp-unavailable.d.ts.map +1 -0
  253. package/dist/services/vision/capacitor-llama.d.ts +99 -0
  254. package/dist/services/vision/capacitor-llama.d.ts.map +1 -0
  255. package/dist/services/vision/cloud-fallback.d.ts +47 -0
  256. package/dist/services/vision/cloud-fallback.d.ts.map +1 -0
  257. package/dist/services/vision/hash.d.ts +71 -0
  258. package/dist/services/vision/hash.d.ts.map +1 -0
  259. package/dist/services/vision/index.d.ts +95 -0
  260. package/dist/services/vision/index.d.ts.map +1 -0
  261. package/dist/services/vision/llama-server.d.ts +73 -0
  262. package/dist/services/vision/llama-server.d.ts.map +1 -0
  263. package/dist/services/vision/types.d.ts +162 -0
  264. package/dist/services/vision/types.d.ts.map +1 -0
  265. package/dist/services/vision/vast-fallback.d.ts +18 -0
  266. package/dist/services/vision/vast-fallback.d.ts.map +1 -0
  267. package/dist/services/vision-embedding-cache.d.ts +98 -0
  268. package/dist/services/vision-embedding-cache.d.ts.map +1 -0
  269. package/dist/services/voice/__test-helpers__/fake-ffi.d.ts +27 -0
  270. package/dist/services/voice/__test-helpers__/fake-ffi.d.ts.map +1 -0
  271. package/dist/services/voice/__test-helpers__/synthetic-speech.d.ts +66 -0
  272. package/dist/services/voice/__test-helpers__/synthetic-speech.d.ts.map +1 -0
  273. package/dist/services/voice/acoustic-speaker-attribution.d.ts +61 -0
  274. package/dist/services/voice/acoustic-speaker-attribution.d.ts.map +1 -0
  275. package/dist/services/voice/audio-frame-consumer.d.ts +294 -0
  276. package/dist/services/voice/audio-frame-consumer.d.ts.map +1 -0
  277. package/dist/services/voice/barge-in.d.ts +112 -0
  278. package/dist/services/voice/barge-in.d.ts.map +1 -0
  279. package/dist/services/voice/cancellation-coordinator.d.ts +127 -0
  280. package/dist/services/voice/cancellation-coordinator.d.ts.map +1 -0
  281. package/dist/services/voice/checkpoint-manager.d.ts +199 -0
  282. package/dist/services/voice/checkpoint-manager.d.ts.map +1 -0
  283. package/dist/services/voice/checkpoint-policy.d.ts +178 -0
  284. package/dist/services/voice/checkpoint-policy.d.ts.map +1 -0
  285. package/dist/services/voice/corpus-augment.d.ts +111 -0
  286. package/dist/services/voice/corpus-augment.d.ts.map +1 -0
  287. package/dist/services/voice/corpus-generator.d.ts +134 -0
  288. package/dist/services/voice/corpus-generator.d.ts.map +1 -0
  289. package/dist/services/voice/diarization-error-rate.d.ts +40 -0
  290. package/dist/services/voice/diarization-error-rate.d.ts.map +1 -0
  291. package/dist/services/voice/e2e-harness.d.ts +297 -0
  292. package/dist/services/voice/e2e-harness.d.ts.map +1 -0
  293. package/dist/services/voice/eager-context-builder.d.ts +170 -0
  294. package/dist/services/voice/eager-context-builder.d.ts.map +1 -0
  295. package/dist/services/voice/echo-delay.d.ts +67 -0
  296. package/dist/services/voice/echo-delay.d.ts.map +1 -0
  297. package/dist/services/voice/echo-metrics.d.ts +7 -0
  298. package/dist/services/voice/echo-metrics.d.ts.map +1 -0
  299. package/dist/services/voice/echo-reference-buffer.d.ts +65 -0
  300. package/dist/services/voice/echo-reference-buffer.d.ts.map +1 -0
  301. package/dist/services/voice/eliza1-eot-scorer.d.ts +124 -0
  302. package/dist/services/voice/eliza1-eot-scorer.d.ts.map +1 -0
  303. package/dist/services/voice/embedding-server.d.ts +37 -0
  304. package/dist/services/voice/embedding-server.d.ts.map +1 -0
  305. package/dist/services/voice/embedding.d.ts +132 -0
  306. package/dist/services/voice/embedding.d.ts.map +1 -0
  307. package/dist/services/voice/emotion-attribution.d.ts +68 -0
  308. package/dist/services/voice/emotion-attribution.d.ts.map +1 -0
  309. package/dist/services/voice/engine-bridge.d.ts +762 -0
  310. package/dist/services/voice/engine-bridge.d.ts.map +1 -0
  311. package/dist/services/voice/eot-classifier-ggml.d.ts +179 -0
  312. package/dist/services/voice/eot-classifier-ggml.d.ts.map +1 -0
  313. package/dist/services/voice/eot-classifier.d.ts +211 -0
  314. package/dist/services/voice/eot-classifier.d.ts.map +1 -0
  315. package/dist/services/voice/errors.d.ts +20 -0
  316. package/dist/services/voice/errors.d.ts.map +1 -0
  317. package/dist/services/voice/expressive-tags.d.ts +158 -0
  318. package/dist/services/voice/expressive-tags.d.ts.map +1 -0
  319. package/dist/services/voice/ffi-bindings.d.ts +696 -0
  320. package/dist/services/voice/ffi-bindings.d.ts.map +1 -0
  321. package/dist/services/voice/first-line-cache.d.ts +181 -0
  322. package/dist/services/voice/first-line-cache.d.ts.map +1 -0
  323. package/dist/services/voice/fused-eot-scorer.d.ts +51 -0
  324. package/dist/services/voice/fused-eot-scorer.d.ts.map +1 -0
  325. package/dist/services/voice/index.d.ts +96 -0
  326. package/dist/services/voice/index.d.ts.map +1 -0
  327. package/dist/services/voice/kokoro/index.d.ts +24 -0
  328. package/dist/services/voice/kokoro/index.d.ts.map +1 -0
  329. package/dist/services/voice/kokoro/kokoro-backend.d.ts +87 -0
  330. package/dist/services/voice/kokoro/kokoro-backend.d.ts.map +1 -0
  331. package/dist/services/voice/kokoro/kokoro-engine-discovery.d.ts +58 -0
  332. package/dist/services/voice/kokoro/kokoro-engine-discovery.d.ts.map +1 -0
  333. package/dist/services/voice/kokoro/kokoro-ffi-runtime.d.ts +75 -0
  334. package/dist/services/voice/kokoro/kokoro-ffi-runtime.d.ts.map +1 -0
  335. package/dist/services/voice/kokoro/kokoro-runtime.d.ts +100 -0
  336. package/dist/services/voice/kokoro/kokoro-runtime.d.ts.map +1 -0
  337. package/dist/services/voice/kokoro/phoneme-stream.d.ts +51 -0
  338. package/dist/services/voice/kokoro/phoneme-stream.d.ts.map +1 -0
  339. package/dist/services/voice/kokoro/phonemizer.d.ts +50 -0
  340. package/dist/services/voice/kokoro/phonemizer.d.ts.map +1 -0
  341. package/dist/services/voice/kokoro/pick-runtime.d.ts +61 -0
  342. package/dist/services/voice/kokoro/pick-runtime.d.ts.map +1 -0
  343. package/dist/services/voice/kokoro/runtime-selection.d.ts +31 -0
  344. package/dist/services/voice/kokoro/runtime-selection.d.ts.map +1 -0
  345. package/dist/services/voice/kokoro/types.d.ts +82 -0
  346. package/dist/services/voice/kokoro/types.d.ts.map +1 -0
  347. package/dist/services/voice/kokoro/voice-presets.d.ts +23 -0
  348. package/dist/services/voice/kokoro/voice-presets.d.ts.map +1 -0
  349. package/dist/services/voice/kokoro/voices.d.ts +30 -0
  350. package/dist/services/voice/kokoro/voices.d.ts.map +1 -0
  351. package/dist/services/voice/lifecycle.d.ts +135 -0
  352. package/dist/services/voice/lifecycle.d.ts.map +1 -0
  353. package/dist/services/voice/live-diarization-session.d.ts +196 -0
  354. package/dist/services/voice/live-diarization-session.d.ts.map +1 -0
  355. package/dist/services/voice/metric-math.d.ts +10 -0
  356. package/dist/services/voice/metric-math.d.ts.map +1 -0
  357. package/dist/services/voice/mic-source.d.ts +136 -0
  358. package/dist/services/voice/mic-source.d.ts.map +1 -0
  359. package/dist/services/voice/nlms-echo-canceller.d.ts +137 -0
  360. package/dist/services/voice/nlms-echo-canceller.d.ts.map +1 -0
  361. package/dist/services/voice/optimistic-policy.d.ts +109 -0
  362. package/dist/services/voice/optimistic-policy.d.ts.map +1 -0
  363. package/dist/services/voice/optimistic-rollback.d.ts +151 -0
  364. package/dist/services/voice/optimistic-rollback.d.ts.map +1 -0
  365. package/dist/services/voice/partial-stabilizer.d.ts +73 -0
  366. package/dist/services/voice/partial-stabilizer.d.ts.map +1 -0
  367. package/dist/services/voice/phoneme-tokenizer.d.ts +49 -0
  368. package/dist/services/voice/phoneme-tokenizer.d.ts.map +1 -0
  369. package/dist/services/voice/phrase-cache.d.ts +76 -0
  370. package/dist/services/voice/phrase-cache.d.ts.map +1 -0
  371. package/dist/services/voice/phrase-chunker.d.ts +62 -0
  372. package/dist/services/voice/phrase-chunker.d.ts.map +1 -0
  373. package/dist/services/voice/pipeline-impls.d.ts +151 -0
  374. package/dist/services/voice/pipeline-impls.d.ts.map +1 -0
  375. package/dist/services/voice/pipeline.d.ts +216 -0
  376. package/dist/services/voice/pipeline.d.ts.map +1 -0
  377. package/dist/services/voice/prefill-client.d.ts +123 -0
  378. package/dist/services/voice/prefill-client.d.ts.map +1 -0
  379. package/dist/services/voice/prefix-preserving-queue.d.ts +113 -0
  380. package/dist/services/voice/prefix-preserving-queue.d.ts.map +1 -0
  381. package/dist/services/voice/profile-store.d.ts +248 -0
  382. package/dist/services/voice/profile-store.d.ts.map +1 -0
  383. package/dist/services/voice/ring-buffer.d.ts +40 -0
  384. package/dist/services/voice/ring-buffer.d.ts.map +1 -0
  385. package/dist/services/voice/rollback-queue.d.ts +24 -0
  386. package/dist/services/voice/rollback-queue.d.ts.map +1 -0
  387. package/dist/services/voice/samantha-preset-placeholder.d.ts +67 -0
  388. package/dist/services/voice/samantha-preset-placeholder.d.ts.map +1 -0
  389. package/dist/services/voice/samantha-preset-regenerator.d.ts +87 -0
  390. package/dist/services/voice/samantha-preset-regenerator.d.ts.map +1 -0
  391. package/dist/services/voice/scheduler.d.ts +146 -0
  392. package/dist/services/voice/scheduler.d.ts.map +1 -0
  393. package/dist/services/voice/self-voice-imprint.d.ts +33 -0
  394. package/dist/services/voice/self-voice-imprint.d.ts.map +1 -0
  395. package/dist/services/voice/shared-resources.d.ts +204 -0
  396. package/dist/services/voice/shared-resources.d.ts.map +1 -0
  397. package/dist/services/voice/speaker/attribution-pipeline.d.ts +74 -0
  398. package/dist/services/voice/speaker/attribution-pipeline.d.ts.map +1 -0
  399. package/dist/services/voice/speaker/diarizer-fused.d.ts +59 -0
  400. package/dist/services/voice/speaker/diarizer-fused.d.ts.map +1 -0
  401. package/dist/services/voice/speaker/diarizer.d.ts +75 -0
  402. package/dist/services/voice/speaker/diarizer.d.ts.map +1 -0
  403. package/dist/services/voice/speaker/encoder-fused.d.ts +60 -0
  404. package/dist/services/voice/speaker/encoder-fused.d.ts.map +1 -0
  405. package/dist/services/voice/speaker/encoder-ggml.d.ts +33 -0
  406. package/dist/services/voice/speaker/encoder-ggml.d.ts.map +1 -0
  407. package/dist/services/voice/speaker/encoder.d.ts +37 -0
  408. package/dist/services/voice/speaker/encoder.d.ts.map +1 -0
  409. package/dist/services/voice/speaker-imprint.d.ts +83 -0
  410. package/dist/services/voice/speaker-imprint.d.ts.map +1 -0
  411. package/dist/services/voice/speaker-preset-cache.d.ts +77 -0
  412. package/dist/services/voice/speaker-preset-cache.d.ts.map +1 -0
  413. package/dist/services/voice/streaming-asr/streaming-pipeline-adapter.d.ts +160 -0
  414. package/dist/services/voice/streaming-asr/streaming-pipeline-adapter.d.ts.map +1 -0
  415. package/dist/services/voice/system-audio-sink.d.ts +73 -0
  416. package/dist/services/voice/system-audio-sink.d.ts.map +1 -0
  417. package/dist/services/voice/transcriber.d.ts +244 -0
  418. package/dist/services/voice/transcriber.d.ts.map +1 -0
  419. package/dist/services/voice/transcript-knowledge.d.ts +37 -0
  420. package/dist/services/voice/transcript-knowledge.d.ts.map +1 -0
  421. package/dist/services/voice/transcript-service.d.ts +60 -0
  422. package/dist/services/voice/transcript-service.d.ts.map +1 -0
  423. package/dist/services/voice/transcript-store.d.ts +64 -0
  424. package/dist/services/voice/transcript-store.d.ts.map +1 -0
  425. package/dist/services/voice/turn-controller.d.ts +183 -0
  426. package/dist/services/voice/turn-controller.d.ts.map +1 -0
  427. package/dist/services/voice/types.d.ts +643 -0
  428. package/dist/services/voice/types.d.ts.map +1 -0
  429. package/dist/services/voice/vad.d.ts +283 -0
  430. package/dist/services/voice/vad.d.ts.map +1 -0
  431. package/dist/services/voice/voice-budget.d.ts +241 -0
  432. package/dist/services/voice/voice-budget.d.ts.map +1 -0
  433. package/dist/services/voice/voice-emotion-classifier.d.ts +95 -0
  434. package/dist/services/voice/voice-emotion-classifier.d.ts.map +1 -0
  435. package/dist/services/voice/voice-preload-predictor.d.ts +76 -0
  436. package/dist/services/voice/voice-preload-predictor.d.ts.map +1 -0
  437. package/dist/services/voice/voice-preset-format.d.ts +158 -0
  438. package/dist/services/voice/voice-preset-format.d.ts.map +1 -0
  439. package/dist/services/voice/voice-profile-artifact.d.ts +116 -0
  440. package/dist/services/voice/voice-profile-artifact.d.ts.map +1 -0
  441. package/dist/services/voice/voice-profile-routes.d.ts +83 -0
  442. package/dist/services/voice/voice-profile-routes.d.ts.map +1 -0
  443. package/dist/services/voice/voice-scenario.d.ts +131 -0
  444. package/dist/services/voice/voice-scenario.d.ts.map +1 -0
  445. package/dist/services/voice/voice-state-machine.d.ts +364 -0
  446. package/dist/services/voice/voice-state-machine.d.ts.map +1 -0
  447. package/dist/services/voice/voice-workbench-report.d.ts +117 -0
  448. package/dist/services/voice/voice-workbench-report.d.ts.map +1 -0
  449. package/dist/services/voice/wake-word-ggml.d.ts +100 -0
  450. package/dist/services/voice/wake-word-ggml.d.ts.map +1 -0
  451. package/dist/services/voice/wake-word.d.ts +255 -0
  452. package/dist/services/voice/wake-word.d.ts.map +1 -0
  453. package/dist/services/voice/wav-codec.d.ts +11 -0
  454. package/dist/services/voice/wav-codec.d.ts.map +1 -0
  455. package/dist/services/voice/workbench-entrypoint.d.ts +42 -0
  456. package/dist/services/voice/workbench-entrypoint.d.ts.map +1 -0
  457. package/dist/services/voice/workbench-headless-runner.d.ts +102 -0
  458. package/dist/services/voice/workbench-headless-runner.d.ts.map +1 -0
  459. package/dist/services/voice/workbench-logic-services.d.ts +36 -0
  460. package/dist/services/voice/workbench-logic-services.d.ts.map +1 -0
  461. package/dist/services/voice/workbench-real-services.d.ts +17 -0
  462. package/dist/services/voice/workbench-real-services.d.ts.map +1 -0
  463. package/dist/services/voice/workbench-scenarios.d.ts +24 -0
  464. package/dist/services/voice/workbench-scenarios.d.ts.map +1 -0
  465. package/dist/services/voice/wrap-with-first-line-cache.d.ts +70 -0
  466. package/dist/services/voice/wrap-with-first-line-cache.d.ts.map +1 -0
  467. package/dist/services/voice-model-updater.d.ts +240 -0
  468. package/dist/services/voice-model-updater.d.ts.map +1 -0
  469. package/dist/services/voice-prewarm.d.ts +3 -0
  470. package/dist/services/voice-prewarm.d.ts.map +1 -0
  471. package/dist/voice-workbench.d.ts +18 -0
  472. package/dist/voice-workbench.d.ts.map +1 -0
  473. package/dist/voice-workbench.js +5259 -0
  474. package/dist/voice-workbench.js.map +34 -0
  475. package/package.json +101 -15
  476. package/registry-entry.json +137 -0
  477. package/src/actions/generate-media.ts +647 -0
  478. package/src/actions/identify-speaker.ts +171 -0
  479. package/src/actions/transcription-control.test.ts +100 -0
  480. package/src/actions/transcription-control.ts +127 -0
  481. package/src/adapters/capacitor-llama/__tests__/compat-behavior.test.ts +218 -0
  482. package/src/adapters/capacitor-llama/__tests__/index.test.ts +68 -0
  483. package/src/adapters/capacitor-llama/__tests__/structured-output.test.ts +215 -0
  484. package/src/adapters/capacitor-llama/__tests__/text-streaming.test.ts +174 -0
  485. package/src/adapters/capacitor-llama/__tests__/voice-turn.test.ts +293 -0
  486. package/src/adapters/capacitor-llama/environment.ts +71 -0
  487. package/src/adapters/capacitor-llama/index.browser.ts +83 -0
  488. package/src/adapters/capacitor-llama/index.ts +831 -0
  489. package/src/adapters/capacitor-llama/loader.ts +109 -0
  490. package/src/adapters/capacitor-llama/native-voice-capture.ts +140 -0
  491. package/src/adapters/capacitor-llama/structured-output.ts +165 -0
  492. package/src/adapters/capacitor-llama/text-streaming.ts +227 -0
  493. package/src/adapters/capacitor-llama/types.ts +374 -0
  494. package/src/adapters/capacitor-llama/voice-turn.ts +178 -0
  495. package/src/backends/apple-foundation.ts +127 -0
  496. package/src/index.ts +62 -0
  497. package/src/local-inference-routes.test.ts +390 -0
  498. package/src/local-inference-routes.ts +1625 -0
  499. package/src/provider.ts +1111 -0
  500. package/src/routes/compat-helpers.ts +275 -0
  501. package/src/routes/family-member-route.ts +353 -0
  502. package/src/routes/index.ts +61 -0
  503. package/src/routes/live-diarization-route.test.ts +347 -0
  504. package/src/routes/live-diarization-route.ts +198 -0
  505. package/src/routes/local-inference-asr-route.test.ts +246 -0
  506. package/src/routes/local-inference-asr-route.ts +166 -0
  507. package/src/routes/local-inference-asr-transcribe.test.ts +118 -0
  508. package/src/routes/local-inference-asr-transcribe.ts +97 -0
  509. package/src/routes/local-inference-compat-routes.test.ts +485 -0
  510. package/src/routes/local-inference-compat-routes.ts +775 -0
  511. package/src/routes/local-inference-tts-route.test.ts +179 -0
  512. package/src/routes/local-inference-tts-route.ts +230 -0
  513. package/src/routes/native-pcm-turn-route.test.ts +136 -0
  514. package/src/routes/native-pcm-turn-route.ts +121 -0
  515. package/src/routes/transcript-audio-store.ts +27 -0
  516. package/src/routes/transcripts-routes.test.ts +195 -0
  517. package/src/routes/transcripts-routes.ts +191 -0
  518. package/src/routes/voice-first-run-routes.ts +524 -0
  519. package/src/routes/voice-models-routes.ts +554 -0
  520. package/src/routes/voice-profile-plugin-routes.ts +138 -0
  521. package/src/routes/voice-profiles-management-routes.ts +476 -0
  522. package/src/routes/voice-speaker-profile-routes.ts +199 -0
  523. package/src/runtime/aosp-llama-loader-selection.test.ts +80 -0
  524. package/src/runtime/bionic-wire-encoding.test.ts +147 -0
  525. package/src/runtime/capacitor-llama.d.ts +25 -0
  526. package/src/runtime/embedding-manager-support.ts +497 -0
  527. package/src/runtime/embedding-presets.ts +81 -0
  528. package/src/runtime/embedding-warmup-policy.test.ts +53 -0
  529. package/src/runtime/embedding-warmup-policy.ts +48 -0
  530. package/src/runtime/ensure-local-inference-handler.test.ts +726 -0
  531. package/src/runtime/ensure-local-inference-handler.ts +1640 -0
  532. package/src/runtime/index.ts +36 -0
  533. package/src/runtime/mobile-local-inference-gate.test.ts +152 -0
  534. package/src/runtime/mobile-local-inference-gate.ts +99 -0
  535. package/src/runtime/voice-entity-binding.transcript.test.ts +98 -0
  536. package/src/runtime/voice-entity-binding.ts +368 -0
  537. package/src/runtime/voice-speaker-entity-contract.test.ts +149 -0
  538. package/src/services/README.md +71 -0
  539. package/src/services/__tests__/backend-selector.precedence.test.ts +333 -0
  540. package/src/services/__tests__/backend-selector.test.ts +101 -0
  541. package/src/services/__tests__/checkpoint-manager.test.ts +376 -0
  542. package/src/services/__tests__/gpu-autotune.test.ts +400 -0
  543. package/src/services/__tests__/llm-streaming-binding.test.ts +85 -0
  544. package/src/services/__tests__/planner-grammar.test.ts +372 -0
  545. package/src/services/__tests__/runtime-target.test.ts +176 -0
  546. package/src/services/active-model-context-fit.test.ts +125 -0
  547. package/src/services/active-model-switch-rollback.test.ts +183 -0
  548. package/src/services/active-model.ts +1416 -0
  549. package/src/services/asr-provenance.ts +68 -0
  550. package/src/services/assignment-validation.test.ts +118 -0
  551. package/src/services/assignments.test.ts +106 -0
  552. package/src/services/assignments.ts +278 -0
  553. package/src/services/backend-selector.ts +95 -0
  554. package/src/services/backend.test.ts +84 -0
  555. package/src/services/backend.ts +791 -0
  556. package/src/services/bionic-host-loader.test.ts +226 -0
  557. package/src/services/bionic-host-loader.ts +252 -0
  558. package/src/services/bundled-models.ts +129 -0
  559. package/src/services/cache-bridge.test.ts +516 -0
  560. package/src/services/cache-bridge.ts +423 -0
  561. package/src/services/catalog.test.ts +259 -0
  562. package/src/services/catalog.ts +33 -0
  563. package/src/services/checkpoint-client.ts +258 -0
  564. package/src/services/checkpoint-manager.ts +474 -0
  565. package/src/services/cloud-fallback.ts +230 -0
  566. package/src/services/context-fit.test.ts +121 -0
  567. package/src/services/context-fit.ts +113 -0
  568. package/src/services/conversation-registry.test.ts +235 -0
  569. package/src/services/conversation-registry.ts +264 -0
  570. package/src/services/desktop-fused-ffi-backend-runtime.ts +431 -0
  571. package/src/services/device-bridge.ts +1237 -0
  572. package/src/services/device-resource-metrics.test.ts +98 -0
  573. package/src/services/device-resource-metrics.ts +346 -0
  574. package/src/services/device-tier.test.ts +458 -0
  575. package/src/services/device-tier.ts +502 -0
  576. package/src/services/downloader.test.ts +888 -0
  577. package/src/services/downloader.ts +1039 -0
  578. package/src/services/engine-direct-bundle.test.ts +90 -0
  579. package/src/services/engine-streaming.test.ts +80 -0
  580. package/src/services/engine.ts +2096 -0
  581. package/src/services/ensure-local-artifacts.integration.test.ts +273 -0
  582. package/src/services/ensure-local-artifacts.test.ts +368 -0
  583. package/src/services/ensure-local-artifacts.ts +351 -0
  584. package/src/services/external-scanner.ts +312 -0
  585. package/src/services/ffi-llm-mock.ts +354 -0
  586. package/src/services/ffi-llm-streaming-abi.ts +445 -0
  587. package/src/services/ffi-streaming-backend.ts +418 -0
  588. package/src/services/ffi-streaming-runner.test.ts +220 -0
  589. package/src/services/ffi-streaming-runner.ts +407 -0
  590. package/src/services/ffi-unload-ordering.test.ts +166 -0
  591. package/src/services/fused-eliza1-no-regression.test.ts +144 -0
  592. package/src/services/gpu-autotune.ts +534 -0
  593. package/src/services/gpu-detect.ts +139 -0
  594. package/src/services/handler-registry.ts +240 -0
  595. package/src/services/hardware.test.ts +236 -0
  596. package/src/services/hardware.ts +438 -0
  597. package/src/services/image-description-runtime.test.ts +61 -0
  598. package/src/services/image-description-runtime.ts +118 -0
  599. package/src/services/imagegen/aosp-unavailable.ts +229 -0
  600. package/src/services/imagegen/backend-selector.test.ts +190 -0
  601. package/src/services/imagegen/backend-selector.ts +277 -0
  602. package/src/services/imagegen/coreml-unavailable.ts +237 -0
  603. package/src/services/imagegen/errors.ts +40 -0
  604. package/src/services/imagegen/index.ts +144 -0
  605. package/src/services/imagegen/mflux.ts +313 -0
  606. package/src/services/imagegen/sd-cpp.ts +715 -0
  607. package/src/services/imagegen/tensorrt-unavailable.ts +295 -0
  608. package/src/services/imagegen/types.ts +193 -0
  609. package/src/services/index.ts +229 -0
  610. package/src/services/inference-capabilities.test.ts +75 -0
  611. package/src/services/inference-capabilities.ts +204 -0
  612. package/src/services/inference-telemetry.ts +143 -0
  613. package/src/services/ios-llama-streaming.ts +248 -0
  614. package/src/services/kv-spill.test.ts +222 -0
  615. package/src/services/kv-spill.ts +357 -0
  616. package/src/services/latency-trace.test.ts +266 -0
  617. package/src/services/latency-trace.ts +844 -0
  618. package/src/services/lib-target.test.ts +145 -0
  619. package/src/services/lib-target.ts +102 -0
  620. package/src/services/live-signals.test.ts +132 -0
  621. package/src/services/live-signals.ts +177 -0
  622. package/src/services/llama-server-metrics.test.ts +168 -0
  623. package/src/services/llama-server-metrics.ts +304 -0
  624. package/src/services/llm-streaming-binding.ts +136 -0
  625. package/src/services/load-args.ts +81 -0
  626. package/src/services/manifest/eliza-1.manifest.v1.json +790 -0
  627. package/src/services/manifest/index.ts +72 -0
  628. package/src/services/manifest/manifest.test.ts +791 -0
  629. package/src/services/manifest/schema.ts +761 -0
  630. package/src/services/manifest/types.ts +61 -0
  631. package/src/services/manifest/validator.ts +633 -0
  632. package/src/services/memory-arbiter.test.ts +558 -0
  633. package/src/services/memory-arbiter.ts +991 -0
  634. package/src/services/memory-benchmark.test.ts +91 -0
  635. package/src/services/memory-benchmark.ts +354 -0
  636. package/src/services/memory-monitor.test.ts +232 -0
  637. package/src/services/memory-monitor.ts +309 -0
  638. package/src/services/memory-pressure.ts +414 -0
  639. package/src/services/mtp-doctor.ts +86 -0
  640. package/src/services/network-policy.ts +346 -0
  641. package/src/services/paths.ts +25 -0
  642. package/src/services/planner-skeleton.ts +175 -0
  643. package/src/services/providers.ts +507 -0
  644. package/src/services/ram-budget-cache.test.ts +164 -0
  645. package/src/services/ram-budget.ts +309 -0
  646. package/src/services/readiness.test.ts +87 -0
  647. package/src/services/readiness.ts +238 -0
  648. package/src/services/recommendation.test.ts +216 -0
  649. package/src/services/recommendation.ts +671 -0
  650. package/src/services/registry.ts +157 -0
  651. package/src/services/required-kernels-gate.test.ts +64 -0
  652. package/src/services/router-handler.test.ts +45 -0
  653. package/src/services/router-handler.ts +426 -0
  654. package/src/services/routing-policy.test.ts +352 -0
  655. package/src/services/routing-policy.ts +367 -0
  656. package/src/services/routing-preferences.ts +17 -0
  657. package/src/services/runtime-target.ts +154 -0
  658. package/src/services/service.test.ts +223 -0
  659. package/src/services/service.ts +750 -0
  660. package/src/services/session-pool.ts +153 -0
  661. package/src/services/structured-output/deterministic-repair.test.ts +169 -0
  662. package/src/services/structured-output/deterministic-repair.ts +443 -0
  663. package/src/services/structured-output/index.ts +4 -0
  664. package/src/services/structured-output.test.ts +483 -0
  665. package/src/services/structured-output.ts +712 -0
  666. package/src/services/system-memory.test.ts +47 -0
  667. package/src/services/system-memory.ts +67 -0
  668. package/src/services/transcription-priority.test.ts +211 -0
  669. package/src/services/types.ts +59 -0
  670. package/src/services/verify-on-device.test.ts +87 -0
  671. package/src/services/verify-on-device.ts +127 -0
  672. package/src/services/verify.ts +13 -0
  673. package/src/services/vision/aosp-unavailable.ts +163 -0
  674. package/src/services/vision/capacitor-llama.ts +255 -0
  675. package/src/services/vision/cloud-fallback.test.ts +243 -0
  676. package/src/services/vision/cloud-fallback.ts +268 -0
  677. package/src/services/vision/fallback-chain.test.ts +86 -0
  678. package/src/services/vision/hash.ts +157 -0
  679. package/src/services/vision/index.ts +251 -0
  680. package/src/services/vision/llama-server.ts +177 -0
  681. package/src/services/vision/types.ts +163 -0
  682. package/src/services/vision/vast-fallback.ts +127 -0
  683. package/src/services/vision-embedding-cache.ts +189 -0
  684. package/src/services/voice/VOICE_WORKBENCH.md +133 -0
  685. package/src/services/voice/__fixtures__/voice-workbench-logic-baseline.json +180 -0
  686. package/src/services/voice/__test-helpers__/fake-ffi.ts +94 -0
  687. package/src/services/voice/__test-helpers__/synthetic-speech.ts +194 -0
  688. package/src/services/voice/__tests__/checkpoint-manager.test.ts +241 -0
  689. package/src/services/voice/__tests__/checkpoint-policy.test.ts +270 -0
  690. package/src/services/voice/__tests__/eager-context-builder.test.ts +257 -0
  691. package/src/services/voice/__tests__/eliza1-eot-scorer.test.ts +288 -0
  692. package/src/services/voice/__tests__/eot-classifier.test.ts +431 -0
  693. package/src/services/voice/__tests__/optimistic-rollback.test.ts +312 -0
  694. package/src/services/voice/__tests__/prefill-client.test.ts +266 -0
  695. package/src/services/voice/__tests__/prefix-preserving-queue.test.ts +208 -0
  696. package/src/services/voice/__tests__/streaming-asr.test.ts +450 -0
  697. package/src/services/voice/__tests__/streaming-transcriber.test.ts +339 -0
  698. package/src/services/voice/__tests__/turn-detector-resolver.test.ts +195 -0
  699. package/src/services/voice/__tests__/voice-state-machine-prefill.test.ts +275 -0
  700. package/src/services/voice/__tests__/voice-state-machine.test.ts +354 -0
  701. package/src/services/voice/acoustic-speaker-attribution.test.ts +165 -0
  702. package/src/services/voice/acoustic-speaker-attribution.ts +336 -0
  703. package/src/services/voice/asr-timed.real.test.ts +139 -0
  704. package/src/services/voice/audio-frame-consumer.test.ts +669 -0
  705. package/src/services/voice/audio-frame-consumer.ts +651 -0
  706. package/src/services/voice/barge-in.test.ts +244 -0
  707. package/src/services/voice/barge-in.ts +335 -0
  708. package/src/services/voice/cancellation-coordinator.test.ts +196 -0
  709. package/src/services/voice/cancellation-coordinator.ts +269 -0
  710. package/src/services/voice/checkpoint-manager.ts +401 -0
  711. package/src/services/voice/checkpoint-policy.ts +336 -0
  712. package/src/services/voice/composite-eot-classifier.test.ts +59 -0
  713. package/src/services/voice/corpus-augment.test.ts +276 -0
  714. package/src/services/voice/corpus-augment.ts +451 -0
  715. package/src/services/voice/corpus-generator.test.ts +201 -0
  716. package/src/services/voice/corpus-generator.ts +413 -0
  717. package/src/services/voice/diarization-error-rate.greedy.test.ts +140 -0
  718. package/src/services/voice/diarization-error-rate.test.ts +100 -0
  719. package/src/services/voice/diarization-error-rate.ts +249 -0
  720. package/src/services/voice/e2e-harness.der.test.ts +94 -0
  721. package/src/services/voice/e2e-harness.respond-eot-entity.test.ts +277 -0
  722. package/src/services/voice/e2e-harness.security-echo.test.ts +103 -0
  723. package/src/services/voice/e2e-harness.test.ts +182 -0
  724. package/src/services/voice/e2e-harness.ts +902 -0
  725. package/src/services/voice/eager-context-builder.ts +262 -0
  726. package/src/services/voice/echo-delay.test.ts +118 -0
  727. package/src/services/voice/echo-delay.ts +135 -0
  728. package/src/services/voice/echo-metrics.test.ts +17 -0
  729. package/src/services/voice/echo-metrics.ts +20 -0
  730. package/src/services/voice/echo-reference-buffer.test.ts +86 -0
  731. package/src/services/voice/echo-reference-buffer.ts +165 -0
  732. package/src/services/voice/eliza1-eot-scorer.ts +242 -0
  733. package/src/services/voice/embedding-server.ts +200 -0
  734. package/src/services/voice/embedding.test.ts +131 -0
  735. package/src/services/voice/embedding.ts +242 -0
  736. package/src/services/voice/emotion-attribution.test.ts +129 -0
  737. package/src/services/voice/emotion-attribution.ts +361 -0
  738. package/src/services/voice/engine-bridge-cancellation.test.ts +422 -0
  739. package/src/services/voice/engine-bridge-transcript-join.test.ts +278 -0
  740. package/src/services/voice/engine-bridge.test.ts +384 -0
  741. package/src/services/voice/engine-bridge.ts +2343 -0
  742. package/src/services/voice/eot-classifier-ggml.ts +569 -0
  743. package/src/services/voice/eot-classifier.test.ts +98 -0
  744. package/src/services/voice/eot-classifier.ts +422 -0
  745. package/src/services/voice/errors.ts +34 -0
  746. package/src/services/voice/expressive-tags.asr.test.ts +77 -0
  747. package/src/services/voice/expressive-tags.test.ts +102 -0
  748. package/src/services/voice/expressive-tags.ts +405 -0
  749. package/src/services/voice/ffi-bindings.test.ts +735 -0
  750. package/src/services/voice/ffi-bindings.ts +3387 -0
  751. package/src/services/voice/first-line-cache.ts +725 -0
  752. package/src/services/voice/fused-eot-scorer.ts +139 -0
  753. package/src/services/voice/index.ts +502 -0
  754. package/src/services/voice/kokoro/__tests__/kokoro-backend.test.ts +262 -0
  755. package/src/services/voice/kokoro/__tests__/kokoro-engine-bridge.real.test.ts +236 -0
  756. package/src/services/voice/kokoro/__tests__/kokoro-engine-bridge.test.ts +60 -0
  757. package/src/services/voice/kokoro/__tests__/kokoro-engine-discovery.test.ts +277 -0
  758. package/src/services/voice/kokoro/__tests__/kokoro-ffi-runtime.test.ts +235 -0
  759. package/src/services/voice/kokoro/__tests__/kokoro-runtime.test.ts +95 -0
  760. package/src/services/voice/kokoro/__tests__/phonemizer.test.ts +53 -0
  761. package/src/services/voice/kokoro/__tests__/runtime-selection.test.ts +67 -0
  762. package/src/services/voice/kokoro/__tests__/voices.test.ts +57 -0
  763. package/src/services/voice/kokoro/index.ts +79 -0
  764. package/src/services/voice/kokoro/kokoro-backend.ts +223 -0
  765. package/src/services/voice/kokoro/kokoro-engine-discovery.ts +177 -0
  766. package/src/services/voice/kokoro/kokoro-ffi-runtime.ts +233 -0
  767. package/src/services/voice/kokoro/kokoro-runtime.ts +170 -0
  768. package/src/services/voice/kokoro/phoneme-stream.ts +123 -0
  769. package/src/services/voice/kokoro/phonemizer.ts +344 -0
  770. package/src/services/voice/kokoro/pick-runtime.test.ts +91 -0
  771. package/src/services/voice/kokoro/pick-runtime.ts +130 -0
  772. package/src/services/voice/kokoro/runtime-selection.ts +64 -0
  773. package/src/services/voice/kokoro/types.ts +95 -0
  774. package/src/services/voice/kokoro/voice-presets.ts +129 -0
  775. package/src/services/voice/kokoro/voices.ts +64 -0
  776. package/src/services/voice/lifecycle.test.ts +315 -0
  777. package/src/services/voice/lifecycle.ts +301 -0
  778. package/src/services/voice/live-diarization-session.echo.test.ts +232 -0
  779. package/src/services/voice/live-diarization-session.ts +622 -0
  780. package/src/services/voice/metric-math.test.ts +61 -0
  781. package/src/services/voice/metric-math.ts +25 -0
  782. package/src/services/voice/mic-source.test.ts +210 -0
  783. package/src/services/voice/mic-source.ts +503 -0
  784. package/src/services/voice/nlms-echo-canceller.test.ts +244 -0
  785. package/src/services/voice/nlms-echo-canceller.ts +317 -0
  786. package/src/services/voice/optimistic-policy.power-source.test.ts +36 -0
  787. package/src/services/voice/optimistic-policy.test.ts +101 -0
  788. package/src/services/voice/optimistic-policy.ts +192 -0
  789. package/src/services/voice/optimistic-rollback.ts +343 -0
  790. package/src/services/voice/partial-stabilizer.test.ts +68 -0
  791. package/src/services/voice/partial-stabilizer.ts +140 -0
  792. package/src/services/voice/phoneme-tokenizer.ts +158 -0
  793. package/src/services/voice/phrase-cache.test.ts +242 -0
  794. package/src/services/voice/phrase-cache.ts +186 -0
  795. package/src/services/voice/phrase-chunker.test.ts +239 -0
  796. package/src/services/voice/phrase-chunker.ts +281 -0
  797. package/src/services/voice/pipeline-impls.l6.test.ts +110 -0
  798. package/src/services/voice/pipeline-impls.test.ts +292 -0
  799. package/src/services/voice/pipeline-impls.ts +315 -0
  800. package/src/services/voice/pipeline.ts +504 -0
  801. package/src/services/voice/prefill-client.ts +316 -0
  802. package/src/services/voice/prefix-preserving-queue.ts +162 -0
  803. package/src/services/voice/profile-store.ts +887 -0
  804. package/src/services/voice/real-audio-decode.test.ts +148 -0
  805. package/src/services/voice/research/VOICE_8785_ASSESSMENT.md +141 -0
  806. package/src/services/voice/research/VOICE_PIPELINE_RESEARCH_2026.md +117 -0
  807. package/src/services/voice/research/VOICE_VALIDATION_RUNBOOK.md +135 -0
  808. package/src/services/voice/ring-buffer.test.ts +129 -0
  809. package/src/services/voice/ring-buffer.ts +123 -0
  810. package/src/services/voice/rollback-queue.ts +74 -0
  811. package/src/services/voice/samantha-preset-placeholder.test.ts +97 -0
  812. package/src/services/voice/samantha-preset-placeholder.ts +148 -0
  813. package/src/services/voice/samantha-preset-regenerator.ts +393 -0
  814. package/src/services/voice/samantha-preset-regenerator.wav.test.ts +90 -0
  815. package/src/services/voice/scheduler.t2.test.ts +141 -0
  816. package/src/services/voice/scheduler.ts +927 -0
  817. package/src/services/voice/self-voice-imprint.test.ts +59 -0
  818. package/src/services/voice/self-voice-imprint.ts +102 -0
  819. package/src/services/voice/shared-resources.ts +343 -0
  820. package/src/services/voice/speaker/attribution-pipeline.test.ts +221 -0
  821. package/src/services/voice/speaker/attribution-pipeline.ts +449 -0
  822. package/src/services/voice/speaker/diarizer-fused.real.test.ts +100 -0
  823. package/src/services/voice/speaker/diarizer-fused.ts +154 -0
  824. package/src/services/voice/speaker/diarizer.ts +218 -0
  825. package/src/services/voice/speaker/encoder-fused.real.test.ts +113 -0
  826. package/src/services/voice/speaker/encoder-fused.ts +138 -0
  827. package/src/services/voice/speaker/encoder-ggml.test.ts +59 -0
  828. package/src/services/voice/speaker/encoder-ggml.ts +79 -0
  829. package/src/services/voice/speaker/encoder.ts +105 -0
  830. package/src/services/voice/speaker-imprint.test.ts +185 -0
  831. package/src/services/voice/speaker-imprint.ts +312 -0
  832. package/src/services/voice/speaker-preset-cache.test.ts +154 -0
  833. package/src/services/voice/speaker-preset-cache.ts +195 -0
  834. package/src/services/voice/streaming-asr/streaming-pipeline-adapter.ts +292 -0
  835. package/src/services/voice/system-audio-sink.test.ts +29 -0
  836. package/src/services/voice/system-audio-sink.ts +366 -0
  837. package/src/services/voice/transcriber.asr-backend.test.ts +76 -0
  838. package/src/services/voice/transcriber.test.ts +392 -0
  839. package/src/services/voice/transcriber.ts +704 -0
  840. package/src/services/voice/transcript-knowledge.test.ts +68 -0
  841. package/src/services/voice/transcript-knowledge.ts +75 -0
  842. package/src/services/voice/transcript-service.test.ts +195 -0
  843. package/src/services/voice/transcript-service.ts +205 -0
  844. package/src/services/voice/transcript-store.test.ts +189 -0
  845. package/src/services/voice/transcript-store.ts +164 -0
  846. package/src/services/voice/turn-controller.test.ts +575 -0
  847. package/src/services/voice/turn-controller.ts +596 -0
  848. package/src/services/voice/types.ts +699 -0
  849. package/src/services/voice/vad.test.ts +498 -0
  850. package/src/services/voice/vad.ts +832 -0
  851. package/src/services/voice/vad.v1-v4.test.ts +222 -0
  852. package/src/services/voice/voice-budget.test.ts +415 -0
  853. package/src/services/voice/voice-budget.ts +635 -0
  854. package/src/services/voice/voice-duet.test.ts +375 -0
  855. package/src/services/voice/voice-emotion-classifier.test.ts +210 -0
  856. package/src/services/voice/voice-emotion-classifier.ts +273 -0
  857. package/src/services/voice/voice-hardening.fuzz.test.ts +116 -0
  858. package/src/services/voice/voice-preload-predictor.test.ts +130 -0
  859. package/src/services/voice/voice-preload-predictor.ts +113 -0
  860. package/src/services/voice/voice-preset-format.fuzz.test.ts +89 -0
  861. package/src/services/voice/voice-preset-format.test.ts +75 -0
  862. package/src/services/voice/voice-preset-format.ts +713 -0
  863. package/src/services/voice/voice-preset-generator.test.ts +89 -0
  864. package/src/services/voice/voice-profile-artifact.test.ts +138 -0
  865. package/src/services/voice/voice-profile-artifact.ts +518 -0
  866. package/src/services/voice/voice-profile-routes.test.ts +429 -0
  867. package/src/services/voice/voice-profile-routes.ts +425 -0
  868. package/src/services/voice/voice-scenario.test.ts +159 -0
  869. package/src/services/voice/voice-scenario.ts +280 -0
  870. package/src/services/voice/voice-scenario.turn-helpers.test.ts +77 -0
  871. package/src/services/voice/voice-state-machine.ts +727 -0
  872. package/src/services/voice/voice-workbench-report.test.ts +168 -0
  873. package/src/services/voice/voice-workbench-report.ts +367 -0
  874. package/src/services/voice/voice-workbench.test.ts +158 -0
  875. package/src/services/voice/voice.test.ts +1070 -0
  876. package/src/services/voice/wake-word-ggml.ts +319 -0
  877. package/src/services/voice/wake-word.test.ts +298 -0
  878. package/src/services/voice/wake-word.ts +554 -0
  879. package/src/services/voice/wav-codec.fuzz.test.ts +59 -0
  880. package/src/services/voice/wav-codec.test.ts +32 -0
  881. package/src/services/voice/wav-codec.ts +101 -0
  882. package/src/services/voice/workbench-entrypoint.test.ts +55 -0
  883. package/src/services/voice/workbench-entrypoint.ts +88 -0
  884. package/src/services/voice/workbench-headless-runner.test.ts +162 -0
  885. package/src/services/voice/workbench-headless-runner.ts +396 -0
  886. package/src/services/voice/workbench-logic-services.test.ts +225 -0
  887. package/src/services/voice/workbench-logic-services.ts +184 -0
  888. package/src/services/voice/workbench-real-services.ts +629 -0
  889. package/src/services/voice/workbench-scenarios.ts +407 -0
  890. package/src/services/voice/wrap-with-first-line-cache.ts +267 -0
  891. package/src/services/voice-model-updater.ts +724 -0
  892. package/src/services/voice-prewarm.ts +51 -0
  893. package/src/voice-workbench.ts +71 -0
@@ -0,0 +1,244 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { NlmsEchoCanceller } from "./nlms-echo-canceller";
3
+
4
+ const SR = 16000;
5
+ const BLOCK = 320; // 20 ms @ 16 kHz — the pipeline's frame size
6
+
7
+ /** Speech-like signal: two-pole low-passed pseudo-random noise (deterministic). */
8
+ function signal(n: number, seed: number): Float32Array {
9
+ const x = new Float32Array(n);
10
+ let s = seed >>> 0;
11
+ let p1 = 0;
12
+ let p2 = 0;
13
+ for (let i = 0; i < n; i++) {
14
+ s = (s * 1103515245 + 12345) & 0x7fffffff;
15
+ const w = s / 0x3fffffff - 1;
16
+ p1 = 0.92 * p1 + 0.08 * w;
17
+ p2 = 0.85 * p2 + 0.15 * p1;
18
+ x[i] = p2 * 3;
19
+ }
20
+ return x;
21
+ }
22
+
23
+ /** Realistic (attenuated) playback→mic path: bulk delay + decaying reverb. */
24
+ function echoOf(x: Float32Array, gain = 0.22): Float32Array {
25
+ const delay = 35;
26
+ const tail = 90;
27
+ const h = new Float32Array(delay + tail);
28
+ for (let k = 0; k < tail; k++) {
29
+ h[delay + k] = Math.exp(-k / 25) * (k % 2 ? -0.6 : 0.8) * gain;
30
+ }
31
+ const y = new Float32Array(x.length);
32
+ for (let n = 0; n < x.length; n++) {
33
+ let acc = 0;
34
+ for (let k = 0; k < h.length; k++) if (n - k >= 0) acc += h[k] * x[n - k];
35
+ y[n] = acc;
36
+ }
37
+ return y;
38
+ }
39
+
40
+ function power(a: Float32Array, from = 0, to = a.length): number {
41
+ let p = 0;
42
+ for (let i = from; i < to; i++) p += a[i] * a[i];
43
+ return p / Math.max(1, to - from);
44
+ }
45
+
46
+ function runBlocks(
47
+ aec: NlmsEchoCanceller,
48
+ near: Float32Array,
49
+ far: Float32Array,
50
+ ): Float32Array {
51
+ const out = new Float32Array(near.length);
52
+ for (let off = 0; off + BLOCK <= near.length; off += BLOCK) {
53
+ out.set(
54
+ aec.process(
55
+ near.subarray(off, off + BLOCK),
56
+ far.subarray(off, off + BLOCK),
57
+ ),
58
+ off,
59
+ );
60
+ }
61
+ return out;
62
+ }
63
+
64
+ describe("NlmsEchoCanceller", () => {
65
+ it("cancels the agent's echo by >=10 dB ERLE after convergence (echo-only)", () => {
66
+ const N = SR * 4;
67
+ const far = signal(N, 1);
68
+ const echo = echoOf(far);
69
+ const out = runBlocks(
70
+ new NlmsEchoCanceller({ filterTaps: 256, mu: 0.5 }),
71
+ echo,
72
+ far,
73
+ );
74
+ const from = SR * 2; // ignore the first 2 s of adaptation
75
+ const to = N - (N % BLOCK);
76
+ const erleDb =
77
+ 10 * Math.log10(power(echo, from, to) / power(out, from, to));
78
+ expect(erleDb).toBeGreaterThan(10);
79
+ });
80
+
81
+ it("passes the mic through unchanged while the agent is silent", () => {
82
+ const aec = new NlmsEchoCanceller({ filterTaps: 256 });
83
+ const micOnly = signal(BLOCK, 777);
84
+ const out = aec.process(micOnly, new Float32Array(BLOCK)); // far-end = silence
85
+ let maxDiff = 0;
86
+ for (let i = 0; i < BLOCK; i++) {
87
+ maxDiff = Math.max(maxDiff, Math.abs(out[i] - micOnly[i]));
88
+ }
89
+ expect(maxDiff).toBeLessThan(1e-6);
90
+ });
91
+
92
+ it("never touches the user's voice when only the user is speaking (no playback)", () => {
93
+ // Pure near-end speech, agent silent for the whole run → exact passthrough,
94
+ // so the canceller can never suppress a barge-in while no echo exists.
95
+ const N = SR * 2;
96
+ const speech = signal(N, 99);
97
+ const out = runBlocks(
98
+ new NlmsEchoCanceller({ filterTaps: 256 }),
99
+ speech,
100
+ new Float32Array(N),
101
+ );
102
+ let maxDiff = 0;
103
+ for (let i = 0; i < out.length; i++) {
104
+ maxDiff = Math.max(maxDiff, Math.abs(out[i] - speech[i]));
105
+ }
106
+ expect(maxDiff).toBeLessThan(1e-6);
107
+ });
108
+
109
+ it("stays stable (does not diverge) under sustained double-talk", () => {
110
+ // Agent speaks the whole time; the user also speaks from 2 s. The filter
111
+ // must not blow up — the output power stays bounded near the input power.
112
+ const N = SR * 4;
113
+ const far = signal(N, 1);
114
+ const echo = echoOf(far);
115
+ const speech = signal(N, 99);
116
+ const near = new Float32Array(N);
117
+ for (let i = 0; i < N; i++)
118
+ near[i] = echo[i] + (i >= SR * 2 ? speech[i] : 0);
119
+ const out = runBlocks(
120
+ new NlmsEchoCanceller({ filterTaps: 256, mu: 0.5, dtdRatio: 1.5 }),
121
+ near,
122
+ far,
123
+ );
124
+ const from = SR * 2;
125
+ const to = N - (N % BLOCK);
126
+ // No divergence: output energy is the same order as the input, not exploding.
127
+ expect(power(out, from, to)).toBeLessThan(power(near, from, to) * 4);
128
+ for (let i = from; i < to; i++) expect(Number.isFinite(out[i])).toBe(true);
129
+ });
130
+
131
+ it("does not diverge when the far-end has quiet passages (real-TTS pauses)", () => {
132
+ // Regression for the divergence found measuring real Kokoro/`say` TTS echo
133
+ // on-device (#9455): real TTS has inter-word/sentence pauses where the
134
+ // far-end energy collapses toward — but never reaches — zero (DAC dither,
135
+ // room floor). Meanwhile the mic always carries a small noise floor. Before
136
+ // the far-end-activity gate, ‖x‖²→ε during those pauses inflated the NLMS
137
+ // step so the filter learned the MIC NOISE and blew up (‖w‖→100s, residual
138
+ // RMS ≫ input). A purely-zero gap does NOT reproduce it (x[k]=0 → no update),
139
+ // which is why the synthetic echo test missed it — the floor is essential.
140
+ const N = SR * 6;
141
+ const speech = signal(N, 1);
142
+ const far = new Float32Array(N);
143
+ for (let i = 0; i < N; i++) {
144
+ const t = i / SR;
145
+ const active = t % 0.6 < 0.4 ? 1 : 0; // 0.4 s on / 0.2 s pause, TTS-like
146
+ // Quiet passage keeps a tiny non-zero floor (≈ −60 dBFS), as real audio does.
147
+ far[i] = active ? speech[i] : speech[i] * 3e-4;
148
+ }
149
+ const echo = echoOf(far);
150
+ const near = new Float32Array(N);
151
+ let s = 4242 >>> 0;
152
+ for (let i = 0; i < N; i++) {
153
+ s = (s * 1103515245 + 12345) & 0x7fffffff;
154
+ near[i] = echo[i] + (s / 0x3fffffff - 1) * 6e-3; // continuous mic noise floor
155
+ }
156
+ const out = runBlocks(new NlmsEchoCanceller(), near, far); // shipped defaults
157
+ const from = SR * 2;
158
+ const to = N - (N % BLOCK);
159
+ for (let i = from; i < to; i++) expect(Number.isFinite(out[i])).toBe(true);
160
+ // Stable: the cleaned signal stays at/below the mic level — it must never
161
+ // amplify the input (divergence injected ~200× energy before the fix).
162
+ expect(power(out, from, to)).toBeLessThan(power(near, from, to) * 1.5);
163
+ let peak = 0;
164
+ for (let i = from; i < to; i++) peak = Math.max(peak, Math.abs(out[i]));
165
+ expect(peak).toBeLessThan(1); // pre-fix peaks reached >20
166
+ });
167
+
168
+ it("reset() clears adaptation (first post-reset sample is exact passthrough)", () => {
169
+ const far = signal(SR, 1);
170
+ const echo = echoOf(far);
171
+ const aec = new NlmsEchoCanceller({ filterTaps: 128 });
172
+ runBlocks(aec, echo, far);
173
+ aec.reset();
174
+ const out = aec.process(echo.subarray(0, BLOCK), far.subarray(0, BLOCK));
175
+ // weights + reference history are zero → ŷ[0]=0 → out[0]==in[0] exactly.
176
+ expect(out[0]).toBe(echo[0]);
177
+ });
178
+
179
+ describe("opt-in residual suppressor (#9583/#9649)", () => {
180
+ it("further attenuates the residual on echo-only frames when enabled", () => {
181
+ const far = signal(SR, 7);
182
+ const near = echoOf(far); // user silent — echo only
183
+ const base = runBlocks(
184
+ new NlmsEchoCanceller({ filterTaps: 256, mu: 0.5 }),
185
+ near,
186
+ far,
187
+ );
188
+ const sup = runBlocks(
189
+ new NlmsEchoCanceller({
190
+ filterTaps: 256,
191
+ mu: 0.5,
192
+ residualSuppression: true,
193
+ }),
194
+ near,
195
+ far,
196
+ );
197
+ const half = near.length >> 1; // measure after convergence
198
+ // The suppressor only ever scales the residual down, so on echo-only
199
+ // frames its output power must be strictly below the linear filter's.
200
+ expect(power(sup, half)).toBeLessThan(power(base, half));
201
+ });
202
+
203
+ it("preserves the user's voice during double-talk (only touches echo-only sub-frames)", () => {
204
+ const far = signal(SR, 3);
205
+ const user = signal(SR, 99); // continuous local talker
206
+ const echo = echoOf(far);
207
+ const near = new Float32Array(far.length);
208
+ for (let i = 0; i < near.length; i++) near[i] = user[i] + echo[i];
209
+ const cfg = { filterTaps: 256, mu: 0.5, dtdRatio: 1.5 } as const;
210
+ const base = runBlocks(new NlmsEchoCanceller(cfg), near, far);
211
+ const sup = runBlocks(
212
+ new NlmsEchoCanceller({ ...cfg, residualSuppression: { gain: 0.1 } }),
213
+ near,
214
+ far,
215
+ );
216
+ // With the user active, near-end power dominates far-end power, so the
217
+ // gate (pFar > pNear) stays shut and the user's voice is left intact.
218
+ // The suppressor only ever engages on the rare echo-only sub-frame (a
219
+ // momentary user pause while the agent plays), so total output power is
220
+ // preserved to well within 0.1% — never the aggressive `gain: 0.1` crush.
221
+ const half = near.length >> 1;
222
+ const pBase = power(base, half);
223
+ const pSup = power(sup, half);
224
+ expect(Math.abs(pSup - pBase) / pBase).toBeLessThan(0.001);
225
+ });
226
+
227
+ it("is off by default (no residualSuppression option ⇒ no extra attenuation)", () => {
228
+ const far = signal(SR, 5);
229
+ const near = echoOf(far);
230
+ const a = runBlocks(
231
+ new NlmsEchoCanceller({ filterTaps: 128 }),
232
+ near,
233
+ far,
234
+ );
235
+ const b = runBlocks(
236
+ new NlmsEchoCanceller({ filterTaps: 128, residualSuppression: false }),
237
+ near,
238
+ far,
239
+ );
240
+ const half = near.length >> 1;
241
+ expect(power(a, half)).toBeCloseTo(power(b, half), 12);
242
+ });
243
+ });
244
+ });
@@ -0,0 +1,317 @@
1
+ /**
2
+ * nlms-echo-canceller.ts — PCM acoustic echo cancellation for the live
3
+ * half-duplex voice pipeline (#9455).
4
+ *
5
+ * When the agent speaks, its TTS playback leaks back into the microphone and
6
+ * corrupts ASR / VAD / diarization (the agent hears itself). This is a
7
+ * single-channel adaptive echo canceller: a normalized least-mean-squares
8
+ * (NLMS) FIR filter models the playback→mic acoustic path and subtracts the
9
+ * estimated echo from the near-end (mic) signal sample-by-sample.
10
+ *
11
+ * near-end d[n] = local_speech[n] + echo[n] (the raw mic)
12
+ * far-end x[n] = agent TTS playback (the reference)
13
+ * estimate ŷ[n] = Σ_k w[k]·x[n−k] (modeled echo)
14
+ * output e[n] = d[n] − ŷ[n] (echo-cancelled mic → ASR)
15
+ * update w[k] += μ·e[n]·x[n−k] / (‖x‖² + ε) (NLMS adaptation)
16
+ *
17
+ * All audio is 16 kHz mono Float32 [-1, 1] — the pipeline's internal format
18
+ * (see audio-frame-consumer.ts). The filter length must cover the
19
+ * playback→mic delay plus the room's reverberation tail; for tails longer than
20
+ * the filter, calibrate `delaySamples` (the bulk transport delay) so the
21
+ * adaptive taps only have to model the short residual impulse.
22
+ *
23
+ * Scope: this targets the dominant failure mode — the agent transcribing its
24
+ * own TTS while the *user is silent* (echo-only), where it achieves ~29 dB of
25
+ * echo-return-loss-enhancement. A far-end-vs-near-end double-talk detector
26
+ * freezes adaptation when a local talker is active so the filter cannot learn
27
+ * (and cancel) the user's voice; barge-in itself is handled upstream by the
28
+ * barge-in detector (which stops playback). Full double-talk residual-echo
29
+ * suppression is AEC3-class work and intentionally out of scope here.
30
+ *
31
+ * Pure DSP, zero dependencies — verified by nlms-echo-canceller.test.ts
32
+ * (ERLE on synthetic echo, passthrough, stability, reset).
33
+ */
34
+
35
+ export interface NlmsEchoCancellerOptions {
36
+ /** Adaptive FIR length in samples. 256 ≈ 16 ms of impulse response @16 kHz. */
37
+ filterTaps?: number;
38
+ /** NLMS step size in (0, 2). Larger = faster adaptation, less stable. */
39
+ mu?: number;
40
+ /** Regularization added to the reference energy to avoid divide-by-zero. */
41
+ epsilon?: number;
42
+ /**
43
+ * Bulk playback→mic transport delay in samples. The reference is consumed
44
+ * `delaySamples` ahead of the near-end so the adaptive taps only model the
45
+ * residual room impulse, not the (potentially large) transport latency.
46
+ */
47
+ delaySamples?: number;
48
+ /**
49
+ * Double-talk detector ratio. When the smoothed near-end power exceeds
50
+ * `dtdRatio`× the smoothed far-end reference power (a passive echo path
51
+ * attenuates, so echo power stays below the reference), a local talker is
52
+ * assumed active and adaptation is frozen so the filter cannot learn (and
53
+ * cancel) the user's voice. Set 0 to disable.
54
+ */
55
+ dtdRatio?: number;
56
+ /**
57
+ * Opt-in nonlinear residual-echo suppressor (#9583/#9649). After the linear
58
+ * NLMS subtracts the modeled echo, an echo-only frame (the agent is speaking,
59
+ * the user is NOT — far-end power exceeds near-end power and no double-talk)
60
+ * still carries the residual echo the finite-length filter could not remove.
61
+ * When enabled, the residual on those frames is scaled toward zero. It is
62
+ * **default-off** and never engages during double-talk or near-end-dominant
63
+ * frames, so it can never attenuate the user's voice. Pass `true` for the
64
+ * default gain or `{ gain }` to tune.
65
+ */
66
+ residualSuppression?: boolean | ResidualSuppressionOptions;
67
+ }
68
+
69
+ export interface ResidualSuppressionOptions {
70
+ /**
71
+ * Gain (0,1] applied to the residual on echo-only frames. Lower = stronger
72
+ * suppression. Default 0.15 (~−16 dB) — aggressive enough to flatten residual
73
+ * echo while leaving headroom for the gate's hysteresis.
74
+ */
75
+ gain?: number;
76
+ }
77
+
78
+ const DEFAULTS = {
79
+ filterTaps: 256,
80
+ mu: 0.3,
81
+ epsilon: 1e-6,
82
+ delaySamples: 0,
83
+ dtdRatio: 2,
84
+ residualSuppressionGain: 0.15,
85
+ } as const;
86
+
87
+ export class NlmsEchoCanceller {
88
+ private readonly w: Float32Array; // adaptive filter weights
89
+ private readonly x: Float32Array; // far-end ring buffer (most-recent-first)
90
+ private readonly taps: number;
91
+ private readonly mu: number;
92
+ private readonly eps: number;
93
+ private readonly delay: number;
94
+ private readonly dtdRatio: number;
95
+ /** Residual-suppressor gain, or null when the suppressor is disabled (default). */
96
+ private readonly resGain: number | null;
97
+ /** Pending far-end samples not yet aligned to a near-end sample (delay line). */
98
+ private readonly delayLine: number[] = [];
99
+ private xEnergy = 0; // running ‖x‖² over the active window (incremental)
100
+ private peakXEnergy = 0; // slowly-decaying envelope of ‖x‖² (far-end scale)
101
+ private pNear = 0; // smoothed near-end power (DTD)
102
+ private pFar = 0; // smoothed far-end reference power (DTD)
103
+ private hangover = 0; // samples to stay frozen after a double-talk trigger
104
+ private lastEchoPow = 0;
105
+
106
+ /** Stay frozen ~30 ms after the last double-talk trigger so the filter is not
107
+ * corrupted by the bursty onset/offset of the near-end talker. */
108
+ private static readonly HANGOVER_SAMPLES = 480;
109
+ /** Per-sample decay of the far-end energy envelope (~1 s time constant) so a
110
+ * short TTS pause keeps the far-end-active gate closed through the gap. */
111
+ private static readonly PEAK_DECAY = 0.99994;
112
+ /** Far-end is "active" only when the instantaneous ‖x‖² is within this
113
+ * fraction (−20 dB) of the recent envelope. Below it there is no echo to
114
+ * learn, so adaptation freezes (see process()). */
115
+ private static readonly FAR_ACTIVITY_FRAC = 0.01;
116
+ /** NLMS regularization as a fraction of the far-end envelope. Keeps the step
117
+ * bounded when ‖x‖² momentarily underflows, so a quiet far-end passage can't
118
+ * make the normaliser collapse to the absolute `eps` and blow the filter up. */
119
+ private static readonly REG_FRAC = 0.01;
120
+ private lastResidualPow = 0;
121
+
122
+ constructor(opts: NlmsEchoCancellerOptions = {}) {
123
+ this.taps = Math.max(1, Math.floor(opts.filterTaps ?? DEFAULTS.filterTaps));
124
+ this.mu = opts.mu ?? DEFAULTS.mu;
125
+ this.eps = opts.epsilon ?? DEFAULTS.epsilon;
126
+ this.delay = Math.max(
127
+ 0,
128
+ Math.floor(opts.delaySamples ?? DEFAULTS.delaySamples),
129
+ );
130
+ this.dtdRatio = opts.dtdRatio ?? DEFAULTS.dtdRatio;
131
+ this.resGain = resolveResidualSuppressionGain(opts.residualSuppression);
132
+ this.w = new Float32Array(this.taps);
133
+ this.x = new Float32Array(this.taps);
134
+ }
135
+
136
+ /**
137
+ * Cancel echo from one block of mic audio.
138
+ *
139
+ * @param nearEnd raw mic block (local speech + echo), Float32 [-1, 1]
140
+ * @param farEnd agent playback reference for the same time window. Pass an
141
+ * empty/zero array when the agent is NOT speaking — the filter
142
+ * then passes the mic through unchanged (output ≈ input).
143
+ * @returns echo-cancelled near-end block (same length as `nearEnd`).
144
+ */
145
+ process(nearEnd: Float32Array, farEnd: Float32Array): Float32Array {
146
+ const n = nearEnd.length;
147
+ const out = new Float32Array(n);
148
+ let echoPow = 0;
149
+ let residualPow = 0;
150
+
151
+ for (let i = 0; i < n; i++) {
152
+ // Feed the (delay-aligned) far-end sample into the ring buffer.
153
+ const incoming = i < farEnd.length ? farEnd[i] : 0;
154
+ this.delayLine.push(incoming);
155
+ const ref =
156
+ this.delayLine.length > this.delay
157
+ ? (this.delayLine.shift() as number)
158
+ : 0;
159
+ this.pushRef(ref);
160
+ // Track the far-end energy envelope (instant rise, slow decay) so the
161
+ // activity gate and the regulariser scale with the playback level.
162
+ this.peakXEnergy = Math.max(
163
+ this.peakXEnergy * NlmsEchoCanceller.PEAK_DECAY,
164
+ this.xEnergy,
165
+ );
166
+
167
+ // Estimate echo ŷ = wᵀ·x and the error e = d − ŷ (the cleaned sample).
168
+ let yhat = 0;
169
+ for (let k = 0; k < this.taps; k++) yhat += this.w[k] * this.x[k];
170
+ const d = nearEnd[i];
171
+ const e = d - yhat;
172
+
173
+ // Double-talk detection by near-end vs far-end power. A passive
174
+ // playback→mic path attenuates, so the echo power stays below the
175
+ // far-end reference power; when the smoothed near-end power instead
176
+ // exceeds `dtdRatio`× the far-end power, a local talker is active. This is
177
+ // independent of the filter's convergence state, so it never blocks
178
+ // initial adaptation (unlike comparing against the echo estimate).
179
+ // Fast smoothing (~6 ms) so the detector reacts at the onset of the
180
+ // near-end burst, plus a hangover so it stays frozen through it.
181
+ this.pNear = 0.99 * this.pNear + 0.01 * d * d;
182
+ this.pFar = 0.99 * this.pFar + 0.01 * ref * ref;
183
+ if (
184
+ this.dtdRatio > 0 &&
185
+ this.pFar > this.eps &&
186
+ this.pNear > this.dtdRatio * this.pFar
187
+ ) {
188
+ this.hangover = NlmsEchoCanceller.HANGOVER_SAMPLES;
189
+ }
190
+ const doubleTalk = this.hangover > 0;
191
+ if (this.hangover > 0) this.hangover--;
192
+
193
+ // Far-end activity gate: only adapt while the far-end is actually
194
+ // driving an echo. During a quiet TTS passage ‖x‖² collapses toward
195
+ // zero but is not exactly zero (DAC dither / room floor), so without
196
+ // this gate the NLMS step μ·e/(‖x‖²+ε) explodes and the filter learns
197
+ // the near-end MIC NOISE instead of an echo — diverging and corrupting
198
+ // the signal handed to ASR/VAD. There is no echo to learn when the
199
+ // far-end is silent, so freezing is both correct and stabilising.
200
+ const farActive =
201
+ this.xEnergy > NlmsEchoCanceller.FAR_ACTIVITY_FRAC * this.peakXEnergy;
202
+
203
+ // NLMS weight update: w += μ·e·x / (‖x‖² + δ), frozen during
204
+ // double-talk or far-end silence. δ scales with the far-end envelope so
205
+ // the normaliser can never collapse to the tiny absolute `eps`.
206
+ if (!doubleTalk && farActive) {
207
+ const reg = Math.max(
208
+ this.eps,
209
+ NlmsEchoCanceller.REG_FRAC * this.peakXEnergy,
210
+ );
211
+ const norm = this.xEnergy + reg;
212
+ const step = (this.mu * e) / norm;
213
+ if (Number.isFinite(step)) {
214
+ for (let k = 0; k < this.taps; k++) this.w[k] += step * this.x[k];
215
+ }
216
+ }
217
+
218
+ // Opt-in residual-echo suppressor (#9583/#9649): on echo-only frames
219
+ // (far-end dominant, no double-talk, far actually active) the residual
220
+ // `e` is mostly the echo the finite filter could not remove, so scale it
221
+ // toward zero. Gated so it never engages while the user might be talking
222
+ // (double-talk or near-end-dominant) — it cannot attenuate the user's
223
+ // voice. Default-off: `cleaned === e` unless explicitly enabled.
224
+ const cleaned =
225
+ this.resGain !== null &&
226
+ !doubleTalk &&
227
+ farActive &&
228
+ this.pFar > this.pNear
229
+ ? e * this.resGain
230
+ : e;
231
+ out[i] = cleaned;
232
+
233
+ echoPow += yhat * yhat;
234
+ residualPow += cleaned * cleaned;
235
+ }
236
+
237
+ this.lastEchoPow = echoPow / Math.max(1, n);
238
+ this.lastResidualPow = residualPow / Math.max(1, n);
239
+ return out;
240
+ }
241
+
242
+ /**
243
+ * Advance cheap detector/reference state while the far-end is silent without
244
+ * running the FIR echo-estimation loop. Learned filter weights are preserved,
245
+ * but stale playback samples are removed from the delay line/ring so the next
246
+ * non-empty reference frame cannot subtract an echo estimate from a previous
247
+ * utterance.
248
+ */
249
+ observeFarEndSilence(nearEnd: Float32Array): void {
250
+ const n = nearEnd.length;
251
+ this.delayLine.length = 0;
252
+ this.x.fill(0);
253
+ this.xEnergy = 0;
254
+ this.peakXEnergy *= NlmsEchoCanceller.PEAK_DECAY ** n;
255
+ this.pFar *= 0.99 ** n;
256
+ this.hangover = Math.max(0, this.hangover - n);
257
+
258
+ let residualPow = 0;
259
+ for (let i = 0; i < n; i++) {
260
+ const d = nearEnd[i];
261
+ this.pNear = 0.99 * this.pNear + 0.01 * d * d;
262
+ residualPow += d * d;
263
+ }
264
+ if (this.peakXEnergy < this.eps) this.peakXEnergy = 0;
265
+ if (this.pFar < this.eps) this.pFar = 0;
266
+ this.lastEchoPow = 0;
267
+ this.lastResidualPow = residualPow / Math.max(1, n);
268
+ }
269
+
270
+ /** Echo-return-loss-enhancement (dB) over the last processed block. Higher is
271
+ * better; >10 dB is a meaningful cancellation. Returns 0 when there is no
272
+ * modeled echo (agent silent) so a passthrough block reads as "no gain". */
273
+ get lastErleDb(): number {
274
+ if (this.lastResidualPow <= 0 || this.lastEchoPow <= 0) return 0;
275
+ return 10 * Math.log10(this.lastEchoPow / this.lastResidualPow);
276
+ }
277
+
278
+ /** Reset adaptation (e.g. when the playback path changes). */
279
+ reset(): void {
280
+ this.w.fill(0);
281
+ this.x.fill(0);
282
+ this.delayLine.length = 0;
283
+ this.xEnergy = 0;
284
+ this.peakXEnergy = 0;
285
+ this.pNear = 0;
286
+ this.pFar = 0;
287
+ this.hangover = 0;
288
+ this.lastEchoPow = 0;
289
+ this.lastResidualPow = 0;
290
+ }
291
+
292
+ /** Shift a new far-end sample into the ring buffer, maintaining ‖x‖²
293
+ * incrementally (drop the oldest sample's energy, add the newest). */
294
+ private pushRef(sample: number): void {
295
+ const dropped = this.x[this.taps - 1];
296
+ this.xEnergy += sample * sample - dropped * dropped;
297
+ if (this.xEnergy < 0) this.xEnergy = 0; // guard fp drift
298
+ for (let k = this.taps - 1; k > 0; k--) this.x[k] = this.x[k - 1];
299
+ this.x[0] = sample;
300
+ }
301
+ }
302
+
303
+ /** Resolve the residual-suppressor option to a clamped gain in (0,1], or null
304
+ * (disabled). `false`/`undefined` → null; `true` → default gain; `{ gain }` →
305
+ * that gain clamped to (0,1] (an out-of-range/non-finite gain falls back to the
306
+ * default rather than silently disabling the suppressor). */
307
+ function resolveResidualSuppressionGain(
308
+ option: boolean | ResidualSuppressionOptions | undefined,
309
+ ): number | null {
310
+ if (!option) return null;
311
+ if (option === true) return DEFAULTS.residualSuppressionGain;
312
+ const g = option.gain;
313
+ if (typeof g !== "number" || !Number.isFinite(g) || g <= 0 || g > 1) {
314
+ return DEFAULTS.residualSuppressionGain;
315
+ }
316
+ return g;
317
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Unit coverage for resolvePowerSourceState's env-override contract (#9147 voice).
3
+ *
4
+ * resolvePowerSourceState gates the optimistic-decode power policy. Its
5
+ * `ELIZA_VOICE_POWER_SOURCE` override is the deterministic, cross-platform path
6
+ * (the `/sys/class/power_supply` probe is Linux-only and environment-dependent,
7
+ * so it is not asserted here). Was untested. No GGUF / audio.
8
+ */
9
+
10
+ import { afterEach, describe, expect, it, vi } from "vitest";
11
+ import { resolvePowerSourceState } from "./optimistic-policy";
12
+
13
+ const STATES = ["plugged-in", "battery", "unknown"] as const;
14
+
15
+ afterEach(() => {
16
+ vi.unstubAllEnvs();
17
+ });
18
+
19
+ describe("resolvePowerSourceState — ELIZA_VOICE_POWER_SOURCE override", () => {
20
+ it("honors each valid override value verbatim", () => {
21
+ for (const state of STATES) {
22
+ vi.stubEnv("ELIZA_VOICE_POWER_SOURCE", state);
23
+ expect(resolvePowerSourceState()).toBe(state);
24
+ }
25
+ });
26
+
27
+ it("trims and lowercases the override", () => {
28
+ vi.stubEnv("ELIZA_VOICE_POWER_SOURCE", " BATTERY ");
29
+ expect(resolvePowerSourceState()).toBe("battery");
30
+ });
31
+
32
+ it("ignores an invalid override and still returns a valid state", () => {
33
+ vi.stubEnv("ELIZA_VOICE_POWER_SOURCE", "nonsense");
34
+ expect(STATES).toContain(resolvePowerSourceState());
35
+ });
36
+ });
@@ -0,0 +1,101 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import {
3
+ DEFAULT_OPTIMISTIC_EOT_THRESHOLD,
4
+ OptimisticGenerationPolicy,
5
+ resolveOptimisticPolicyEnabled,
6
+ } from "./optimistic-policy";
7
+
8
+ describe("resolveOptimisticPolicyEnabled — pure", () => {
9
+ it("override:true wins regardless of power source", () => {
10
+ expect(
11
+ resolveOptimisticPolicyEnabled({
12
+ powerSource: "battery",
13
+ override: true,
14
+ }),
15
+ ).toBe(true);
16
+ });
17
+
18
+ it("override:false wins regardless of power source", () => {
19
+ expect(
20
+ resolveOptimisticPolicyEnabled({
21
+ powerSource: "plugged-in",
22
+ override: false,
23
+ }),
24
+ ).toBe(false);
25
+ });
26
+
27
+ it("battery without override → false", () => {
28
+ expect(resolveOptimisticPolicyEnabled({ powerSource: "battery" })).toBe(
29
+ false,
30
+ );
31
+ });
32
+
33
+ it("plugged-in without override → true", () => {
34
+ expect(resolveOptimisticPolicyEnabled({ powerSource: "plugged-in" })).toBe(
35
+ true,
36
+ );
37
+ });
38
+
39
+ it("unknown power source defaults to true", () => {
40
+ expect(resolveOptimisticPolicyEnabled({ powerSource: "unknown" })).toBe(
41
+ true,
42
+ );
43
+ expect(resolveOptimisticPolicyEnabled({})).toBe(true);
44
+ });
45
+ });
46
+
47
+ describe("OptimisticGenerationPolicy", () => {
48
+ it("defaults: enabled, threshold = DEFAULT", () => {
49
+ const p = new OptimisticGenerationPolicy();
50
+ expect(p.enabled()).toBe(true);
51
+ expect(p.threshold).toBe(DEFAULT_OPTIMISTIC_EOT_THRESHOLD);
52
+ });
53
+
54
+ it("battery flips enabled() to false", () => {
55
+ const p = new OptimisticGenerationPolicy();
56
+ p.setPowerSource("battery");
57
+ expect(p.enabled()).toBe(false);
58
+ });
59
+
60
+ it("explicit override true wins on battery", () => {
61
+ const p = new OptimisticGenerationPolicy();
62
+ p.setPowerSource("battery");
63
+ p.setOverride(true);
64
+ expect(p.enabled()).toBe(true);
65
+ });
66
+
67
+ it("override:false wins on plugged-in", () => {
68
+ const p = new OptimisticGenerationPolicy();
69
+ p.setPowerSource("plugged-in");
70
+ p.setOverride(false);
71
+ expect(p.enabled()).toBe(false);
72
+ });
73
+
74
+ it("shouldStartOptimisticLm gates on EOT threshold", () => {
75
+ const p = new OptimisticGenerationPolicy({ eotThreshold: 0.7 });
76
+ expect(p.shouldStartOptimisticLm(0.5)).toBe(false);
77
+ expect(p.shouldStartOptimisticLm(0.7)).toBe(true);
78
+ expect(p.shouldStartOptimisticLm(0.95)).toBe(true);
79
+ });
80
+
81
+ it("shouldStartOptimisticLm returns false when disabled regardless of probability", () => {
82
+ const p = new OptimisticGenerationPolicy();
83
+ p.setPowerSource("battery");
84
+ expect(p.shouldStartOptimisticLm(0.99)).toBe(false);
85
+ });
86
+
87
+ it("override clears back to default with undefined", () => {
88
+ const p = new OptimisticGenerationPolicy();
89
+ p.setOverride(false);
90
+ expect(p.enabled()).toBe(false);
91
+ p.setOverride(undefined);
92
+ expect(p.enabled()).toBe(true);
93
+ });
94
+
95
+ it("constructor defaultEnabled=false flips the base policy", () => {
96
+ const p = new OptimisticGenerationPolicy({ defaultEnabled: false });
97
+ expect(p.enabled()).toBe(false);
98
+ p.setOverride(true);
99
+ expect(p.enabled()).toBe(true);
100
+ });
101
+ });