@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.
Files changed (701) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +83 -0
  3. package/package.json +82 -15
  4. package/src/actions/generate-media.d.ts +59 -0
  5. package/src/actions/generate-media.d.ts.map +1 -0
  6. package/src/actions/generate-media.ts +647 -0
  7. package/src/actions/identify-speaker.d.ts +23 -0
  8. package/src/actions/identify-speaker.d.ts.map +1 -0
  9. package/src/actions/identify-speaker.ts +171 -0
  10. package/src/actions/transcription-control.d.ts +29 -0
  11. package/src/actions/transcription-control.d.ts.map +1 -0
  12. package/src/actions/transcription-control.test.ts +100 -0
  13. package/src/actions/transcription-control.ts +127 -0
  14. package/src/adapters/capacitor-llama/__tests__/compat-behavior.test.ts +218 -0
  15. package/src/adapters/capacitor-llama/__tests__/index.test.ts +68 -0
  16. package/src/adapters/capacitor-llama/__tests__/structured-output.test.ts +215 -0
  17. package/src/adapters/capacitor-llama/__tests__/text-streaming.test.ts +174 -0
  18. package/src/adapters/capacitor-llama/environment.ts +71 -0
  19. package/src/adapters/capacitor-llama/index.browser.ts +83 -0
  20. package/src/adapters/capacitor-llama/index.ts +807 -0
  21. package/src/adapters/capacitor-llama/loader.ts +109 -0
  22. package/src/adapters/capacitor-llama/structured-output.ts +165 -0
  23. package/src/adapters/capacitor-llama/text-streaming.ts +227 -0
  24. package/src/adapters/capacitor-llama/types.ts +374 -0
  25. package/src/backends/apple-foundation.ts +127 -0
  26. package/src/index.d.ts +8 -0
  27. package/src/index.d.ts.map +1 -0
  28. package/src/index.ts +62 -0
  29. package/src/local-inference-routes.d.ts +38 -0
  30. package/src/local-inference-routes.d.ts.map +1 -0
  31. package/src/local-inference-routes.test.ts +344 -0
  32. package/src/local-inference-routes.ts +1543 -0
  33. package/src/provider.d.ts +21 -0
  34. package/src/provider.d.ts.map +1 -0
  35. package/src/provider.ts +1082 -0
  36. package/src/routes/compat-helpers.d.ts +18 -0
  37. package/src/routes/compat-helpers.d.ts.map +1 -0
  38. package/src/routes/compat-helpers.ts +274 -0
  39. package/src/routes/family-member-route.d.ts +62 -0
  40. package/src/routes/family-member-route.d.ts.map +1 -0
  41. package/src/routes/family-member-route.ts +353 -0
  42. package/src/routes/index.d.ts +19 -0
  43. package/src/routes/index.d.ts.map +1 -0
  44. package/src/routes/index.ts +60 -0
  45. package/src/routes/live-diarization-route.d.ts +26 -0
  46. package/src/routes/live-diarization-route.d.ts.map +1 -0
  47. package/src/routes/live-diarization-route.test.ts +213 -0
  48. package/src/routes/live-diarization-route.ts +122 -0
  49. package/src/routes/local-inference-asr-route.d.ts +4 -0
  50. package/src/routes/local-inference-asr-route.d.ts.map +1 -0
  51. package/src/routes/local-inference-asr-route.test.ts +205 -0
  52. package/src/routes/local-inference-asr-route.ts +163 -0
  53. package/src/routes/local-inference-asr-transcribe.d.ts +20 -0
  54. package/src/routes/local-inference-asr-transcribe.d.ts.map +1 -0
  55. package/src/routes/local-inference-asr-transcribe.test.ts +118 -0
  56. package/src/routes/local-inference-asr-transcribe.ts +97 -0
  57. package/src/routes/local-inference-compat-routes.d.ts +16 -0
  58. package/src/routes/local-inference-compat-routes.d.ts.map +1 -0
  59. package/src/routes/local-inference-compat-routes.test.ts +485 -0
  60. package/src/routes/local-inference-compat-routes.ts +808 -0
  61. package/src/routes/local-inference-tts-route.d.ts +7 -0
  62. package/src/routes/local-inference-tts-route.d.ts.map +1 -0
  63. package/src/routes/local-inference-tts-route.test.ts +179 -0
  64. package/src/routes/local-inference-tts-route.ts +230 -0
  65. package/src/routes/transcript-audio-store.d.ts +15 -0
  66. package/src/routes/transcript-audio-store.d.ts.map +1 -0
  67. package/src/routes/transcript-audio-store.ts +27 -0
  68. package/src/routes/transcripts-routes.d.ts +36 -0
  69. package/src/routes/transcripts-routes.d.ts.map +1 -0
  70. package/src/routes/transcripts-routes.test.ts +144 -0
  71. package/src/routes/transcripts-routes.ts +159 -0
  72. package/src/routes/voice-first-run-routes.d.ts +62 -0
  73. package/src/routes/voice-first-run-routes.d.ts.map +1 -0
  74. package/src/routes/voice-first-run-routes.ts +524 -0
  75. package/src/routes/voice-models-routes.d.ts +62 -0
  76. package/src/routes/voice-models-routes.d.ts.map +1 -0
  77. package/src/routes/voice-models-routes.ts +554 -0
  78. package/src/routes/voice-profile-plugin-routes.d.ts +19 -0
  79. package/src/routes/voice-profile-plugin-routes.d.ts.map +1 -0
  80. package/src/routes/voice-profile-plugin-routes.ts +138 -0
  81. package/src/routes/voice-profiles-management-routes.d.ts +52 -0
  82. package/src/routes/voice-profiles-management-routes.d.ts.map +1 -0
  83. package/src/routes/voice-profiles-management-routes.ts +476 -0
  84. package/src/routes/voice-speaker-profile-routes.d.ts +57 -0
  85. package/src/routes/voice-speaker-profile-routes.d.ts.map +1 -0
  86. package/src/routes/voice-speaker-profile-routes.ts +199 -0
  87. package/src/runtime/aosp-llama-loader-selection.test.ts +80 -0
  88. package/src/runtime/capacitor-llama.d.ts +25 -0
  89. package/src/runtime/embedding-manager-support.d.ts +77 -0
  90. package/src/runtime/embedding-manager-support.d.ts.map +1 -0
  91. package/src/runtime/embedding-manager-support.ts +497 -0
  92. package/src/runtime/embedding-presets.d.ts +16 -0
  93. package/src/runtime/embedding-presets.d.ts.map +1 -0
  94. package/src/runtime/embedding-presets.ts +81 -0
  95. package/src/runtime/embedding-warmup-policy.d.ts +14 -0
  96. package/src/runtime/embedding-warmup-policy.d.ts.map +1 -0
  97. package/src/runtime/embedding-warmup-policy.test.ts +53 -0
  98. package/src/runtime/embedding-warmup-policy.ts +48 -0
  99. package/src/runtime/ensure-local-inference-handler.d.ts +62 -0
  100. package/src/runtime/ensure-local-inference-handler.d.ts.map +1 -0
  101. package/src/runtime/ensure-local-inference-handler.test.ts +528 -0
  102. package/src/runtime/ensure-local-inference-handler.ts +1448 -0
  103. package/src/runtime/index.d.ts +15 -0
  104. package/src/runtime/index.d.ts.map +1 -0
  105. package/src/runtime/index.ts +33 -0
  106. package/src/runtime/mobile-local-inference-gate.d.ts +31 -0
  107. package/src/runtime/mobile-local-inference-gate.d.ts.map +1 -0
  108. package/src/runtime/mobile-local-inference-gate.test.ts +69 -0
  109. package/src/runtime/mobile-local-inference-gate.ts +44 -0
  110. package/src/runtime/voice-entity-binding.d.ts +103 -0
  111. package/src/runtime/voice-entity-binding.d.ts.map +1 -0
  112. package/src/runtime/voice-entity-binding.transcript.test.ts +69 -0
  113. package/src/runtime/voice-entity-binding.ts +328 -0
  114. package/src/services/README.md +71 -0
  115. package/src/services/__tests__/backend-selector.test.ts +101 -0
  116. package/src/services/__tests__/checkpoint-manager.test.ts +376 -0
  117. package/src/services/__tests__/gpu-autotune.test.ts +400 -0
  118. package/src/services/__tests__/llm-streaming-binding.test.ts +85 -0
  119. package/src/services/__tests__/planner-grammar.test.ts +372 -0
  120. package/src/services/__tests__/runtime-target.test.ts +176 -0
  121. package/src/services/active-model-switch-rollback.test.ts +183 -0
  122. package/src/services/active-model.d.ts +282 -0
  123. package/src/services/active-model.d.ts.map +1 -0
  124. package/src/services/active-model.ts +1213 -0
  125. package/src/services/assignments.d.ts +71 -0
  126. package/src/services/assignments.d.ts.map +1 -0
  127. package/src/services/assignments.test.ts +80 -0
  128. package/src/services/assignments.ts +230 -0
  129. package/src/services/backend-selector.ts +95 -0
  130. package/src/services/backend.d.ts +346 -0
  131. package/src/services/backend.d.ts.map +1 -0
  132. package/src/services/backend.ts +612 -0
  133. package/src/services/bionic-host-loader.d.ts +46 -0
  134. package/src/services/bionic-host-loader.d.ts.map +1 -0
  135. package/src/services/bionic-host-loader.test.ts +133 -0
  136. package/src/services/bionic-host-loader.ts +180 -0
  137. package/src/services/bundled-models.d.ts +34 -0
  138. package/src/services/bundled-models.d.ts.map +1 -0
  139. package/src/services/bundled-models.ts +129 -0
  140. package/src/services/cache-bridge.d.ts +206 -0
  141. package/src/services/cache-bridge.d.ts.map +1 -0
  142. package/src/services/cache-bridge.test.ts +516 -0
  143. package/src/services/cache-bridge.ts +423 -0
  144. package/src/services/catalog.d.ts +10 -0
  145. package/src/services/catalog.d.ts.map +1 -0
  146. package/src/services/catalog.test.ts +238 -0
  147. package/src/services/catalog.ts +27 -0
  148. package/src/services/checkpoint-client.d.ts +109 -0
  149. package/src/services/checkpoint-client.d.ts.map +1 -0
  150. package/src/services/checkpoint-client.ts +258 -0
  151. package/src/services/checkpoint-manager.ts +474 -0
  152. package/src/services/cloud-fallback.d.ts +102 -0
  153. package/src/services/cloud-fallback.d.ts.map +1 -0
  154. package/src/services/cloud-fallback.ts +230 -0
  155. package/src/services/conversation-registry.d.ts +142 -0
  156. package/src/services/conversation-registry.d.ts.map +1 -0
  157. package/src/services/conversation-registry.test.ts +235 -0
  158. package/src/services/conversation-registry.ts +264 -0
  159. package/src/services/desktop-fused-ffi-backend-runtime.d.ts +95 -0
  160. package/src/services/desktop-fused-ffi-backend-runtime.d.ts.map +1 -0
  161. package/src/services/desktop-fused-ffi-backend-runtime.ts +339 -0
  162. package/src/services/device-bridge.d.ts +188 -0
  163. package/src/services/device-bridge.d.ts.map +1 -0
  164. package/src/services/device-bridge.ts +1237 -0
  165. package/src/services/device-resource-metrics.d.ts +149 -0
  166. package/src/services/device-resource-metrics.d.ts.map +1 -0
  167. package/src/services/device-resource-metrics.test.ts +98 -0
  168. package/src/services/device-resource-metrics.ts +346 -0
  169. package/src/services/device-tier.d.ts +115 -0
  170. package/src/services/device-tier.d.ts.map +1 -0
  171. package/src/services/device-tier.test.ts +371 -0
  172. package/src/services/device-tier.ts +410 -0
  173. package/src/services/downloader.d.ts +82 -0
  174. package/src/services/downloader.d.ts.map +1 -0
  175. package/src/services/downloader.test.ts +747 -0
  176. package/src/services/downloader.ts +925 -0
  177. package/src/services/engine-direct-bundle.test.ts +58 -0
  178. package/src/services/engine-streaming.test.ts +80 -0
  179. package/src/services/engine.d.ts +540 -0
  180. package/src/services/engine.d.ts.map +1 -0
  181. package/src/services/engine.ts +1909 -0
  182. package/src/services/ensure-local-artifacts.integration.test.ts +273 -0
  183. package/src/services/ensure-local-artifacts.test.ts +368 -0
  184. package/src/services/ensure-local-artifacts.ts +351 -0
  185. package/src/services/external-scanner.d.ts +17 -0
  186. package/src/services/external-scanner.d.ts.map +1 -0
  187. package/src/services/external-scanner.ts +312 -0
  188. package/src/services/ffi-llm-mock.ts +354 -0
  189. package/src/services/ffi-llm-streaming-abi.ts +442 -0
  190. package/src/services/ffi-streaming-backend.d.ts +180 -0
  191. package/src/services/ffi-streaming-backend.d.ts.map +1 -0
  192. package/src/services/ffi-streaming-backend.ts +382 -0
  193. package/src/services/ffi-streaming-runner.d.ts +122 -0
  194. package/src/services/ffi-streaming-runner.d.ts.map +1 -0
  195. package/src/services/ffi-streaming-runner.test.ts +60 -0
  196. package/src/services/ffi-streaming-runner.ts +354 -0
  197. package/src/services/ffi-unload-ordering.test.ts +162 -0
  198. package/src/services/gpu-autotune.ts +534 -0
  199. package/src/services/gpu-detect.d.ts +56 -0
  200. package/src/services/gpu-detect.d.ts.map +1 -0
  201. package/src/services/gpu-detect.ts +139 -0
  202. package/src/services/handler-registry.d.ts +72 -0
  203. package/src/services/handler-registry.d.ts.map +1 -0
  204. package/src/services/handler-registry.ts +240 -0
  205. package/src/services/hardware.d.ts +63 -0
  206. package/src/services/hardware.d.ts.map +1 -0
  207. package/src/services/hardware.test.ts +231 -0
  208. package/src/services/hardware.ts +410 -0
  209. package/src/services/hf-search.d.ts +26 -0
  210. package/src/services/hf-search.d.ts.map +1 -0
  211. package/src/services/hf-search.test.ts +69 -0
  212. package/src/services/hf-search.ts +420 -0
  213. package/src/services/image-description-runtime.d.ts +14 -0
  214. package/src/services/image-description-runtime.d.ts.map +1 -0
  215. package/src/services/image-description-runtime.test.ts +61 -0
  216. package/src/services/image-description-runtime.ts +118 -0
  217. package/src/services/imagegen/aosp-unavailable.d.ts +134 -0
  218. package/src/services/imagegen/aosp-unavailable.d.ts.map +1 -0
  219. package/src/services/imagegen/aosp-unavailable.ts +229 -0
  220. package/src/services/imagegen/backend-selector.d.ts +118 -0
  221. package/src/services/imagegen/backend-selector.d.ts.map +1 -0
  222. package/src/services/imagegen/backend-selector.ts +277 -0
  223. package/src/services/imagegen/coreml-unavailable.d.ts +105 -0
  224. package/src/services/imagegen/coreml-unavailable.d.ts.map +1 -0
  225. package/src/services/imagegen/coreml-unavailable.ts +237 -0
  226. package/src/services/imagegen/errors.d.ts +16 -0
  227. package/src/services/imagegen/errors.d.ts.map +1 -0
  228. package/src/services/imagegen/errors.ts +40 -0
  229. package/src/services/imagegen/index.d.ts +58 -0
  230. package/src/services/imagegen/index.d.ts.map +1 -0
  231. package/src/services/imagegen/index.ts +144 -0
  232. package/src/services/imagegen/mflux.d.ts +74 -0
  233. package/src/services/imagegen/mflux.d.ts.map +1 -0
  234. package/src/services/imagegen/mflux.ts +313 -0
  235. package/src/services/imagegen/sd-cpp.d.ts +180 -0
  236. package/src/services/imagegen/sd-cpp.d.ts.map +1 -0
  237. package/src/services/imagegen/sd-cpp.ts +718 -0
  238. package/src/services/imagegen/tensorrt-unavailable.d.ts +83 -0
  239. package/src/services/imagegen/tensorrt-unavailable.d.ts.map +1 -0
  240. package/src/services/imagegen/tensorrt-unavailable.ts +295 -0
  241. package/src/services/imagegen/types.d.ts +181 -0
  242. package/src/services/imagegen/types.d.ts.map +1 -0
  243. package/src/services/imagegen/types.ts +193 -0
  244. package/src/services/index.d.ts +29 -0
  245. package/src/services/index.d.ts.map +1 -0
  246. package/src/services/index.ts +211 -0
  247. package/src/services/inference-capabilities.d.ts +132 -0
  248. package/src/services/inference-capabilities.d.ts.map +1 -0
  249. package/src/services/inference-capabilities.test.ts +75 -0
  250. package/src/services/inference-capabilities.ts +204 -0
  251. package/src/services/inference-telemetry.d.ts +59 -0
  252. package/src/services/inference-telemetry.d.ts.map +1 -0
  253. package/src/services/inference-telemetry.ts +143 -0
  254. package/src/services/ios-llama-streaming.ts +248 -0
  255. package/src/services/kv-spill.d.ts +189 -0
  256. package/src/services/kv-spill.d.ts.map +1 -0
  257. package/src/services/kv-spill.test.ts +222 -0
  258. package/src/services/kv-spill.ts +356 -0
  259. package/src/services/latency-trace.d.ts +346 -0
  260. package/src/services/latency-trace.d.ts.map +1 -0
  261. package/src/services/latency-trace.test.ts +266 -0
  262. package/src/services/latency-trace.ts +844 -0
  263. package/src/services/llama-server-metrics.ts +304 -0
  264. package/src/services/llm-streaming-binding.d.ts +96 -0
  265. package/src/services/llm-streaming-binding.d.ts.map +1 -0
  266. package/src/services/llm-streaming-binding.ts +136 -0
  267. package/src/services/load-args.d.ts +82 -0
  268. package/src/services/load-args.d.ts.map +1 -0
  269. package/src/services/load-args.ts +81 -0
  270. package/src/services/manifest/eliza-1.manifest.v1.json +708 -0
  271. package/src/services/manifest/index.d.ts +4 -0
  272. package/src/services/manifest/index.d.ts.map +1 -0
  273. package/src/services/manifest/index.ts +66 -0
  274. package/src/services/manifest/manifest.test.ts +689 -0
  275. package/src/services/manifest/schema.d.ts +713 -0
  276. package/src/services/manifest/schema.d.ts.map +1 -0
  277. package/src/services/manifest/schema.ts +653 -0
  278. package/src/services/manifest/types.d.ts +30 -0
  279. package/src/services/manifest/types.d.ts.map +1 -0
  280. package/src/services/manifest/types.ts +55 -0
  281. package/src/services/manifest/validator.d.ts +66 -0
  282. package/src/services/manifest/validator.d.ts.map +1 -0
  283. package/src/services/manifest/validator.ts +567 -0
  284. package/src/services/memory-arbiter.d.ts +318 -0
  285. package/src/services/memory-arbiter.d.ts.map +1 -0
  286. package/src/services/memory-arbiter.test.ts +419 -0
  287. package/src/services/memory-arbiter.ts +925 -0
  288. package/src/services/memory-monitor.d.ts +122 -0
  289. package/src/services/memory-monitor.d.ts.map +1 -0
  290. package/src/services/memory-monitor.test.ts +208 -0
  291. package/src/services/memory-monitor.ts +297 -0
  292. package/src/services/memory-pressure.d.ts +130 -0
  293. package/src/services/memory-pressure.d.ts.map +1 -0
  294. package/src/services/memory-pressure.ts +414 -0
  295. package/src/services/mtp-doctor.d.ts +13 -0
  296. package/src/services/mtp-doctor.d.ts.map +1 -0
  297. package/src/services/mtp-doctor.ts +78 -0
  298. package/src/services/network-policy.d.ts +127 -0
  299. package/src/services/network-policy.d.ts.map +1 -0
  300. package/src/services/network-policy.ts +346 -0
  301. package/src/services/paths.d.ts +6 -0
  302. package/src/services/paths.d.ts.map +1 -0
  303. package/src/services/paths.ts +25 -0
  304. package/src/services/planner-skeleton.d.ts +124 -0
  305. package/src/services/planner-skeleton.d.ts.map +1 -0
  306. package/src/services/planner-skeleton.ts +175 -0
  307. package/src/services/providers.d.ts +38 -0
  308. package/src/services/providers.d.ts.map +1 -0
  309. package/src/services/providers.ts +507 -0
  310. package/src/services/ram-budget-cache.test.ts +163 -0
  311. package/src/services/ram-budget.d.ts +110 -0
  312. package/src/services/ram-budget.d.ts.map +1 -0
  313. package/src/services/ram-budget.ts +0 -0
  314. package/src/services/readiness.d.ts +9 -0
  315. package/src/services/readiness.d.ts.map +1 -0
  316. package/src/services/readiness.test.ts +87 -0
  317. package/src/services/readiness.ts +238 -0
  318. package/src/services/recommendation.d.ts +111 -0
  319. package/src/services/recommendation.d.ts.map +1 -0
  320. package/src/services/recommendation.ts +671 -0
  321. package/src/services/registry.d.ts +35 -0
  322. package/src/services/registry.d.ts.map +1 -0
  323. package/src/services/registry.ts +151 -0
  324. package/src/services/router-handler.d.ts +92 -0
  325. package/src/services/router-handler.d.ts.map +1 -0
  326. package/src/services/router-handler.test.ts +45 -0
  327. package/src/services/router-handler.ts +407 -0
  328. package/src/services/routing-policy.d.ts +69 -0
  329. package/src/services/routing-policy.d.ts.map +1 -0
  330. package/src/services/routing-policy.test.ts +164 -0
  331. package/src/services/routing-policy.ts +297 -0
  332. package/src/services/routing-preferences.d.ts +8 -0
  333. package/src/services/routing-preferences.d.ts.map +1 -0
  334. package/src/services/routing-preferences.ts +17 -0
  335. package/src/services/runtime-target.d.ts +98 -0
  336. package/src/services/runtime-target.d.ts.map +1 -0
  337. package/src/services/runtime-target.ts +154 -0
  338. package/src/services/service.d.ts +128 -0
  339. package/src/services/service.d.ts.map +1 -0
  340. package/src/services/service.test.ts +223 -0
  341. package/src/services/service.ts +735 -0
  342. package/src/services/session-pool.d.ts +72 -0
  343. package/src/services/session-pool.d.ts.map +1 -0
  344. package/src/services/session-pool.ts +153 -0
  345. package/src/services/structured-output/deterministic-repair.d.ts +23 -0
  346. package/src/services/structured-output/deterministic-repair.d.ts.map +1 -0
  347. package/src/services/structured-output/deterministic-repair.test.ts +169 -0
  348. package/src/services/structured-output/deterministic-repair.ts +443 -0
  349. package/src/services/structured-output/index.ts +4 -0
  350. package/src/services/structured-output.d.ts +311 -0
  351. package/src/services/structured-output.d.ts.map +1 -0
  352. package/src/services/structured-output.test.ts +483 -0
  353. package/src/services/structured-output.ts +712 -0
  354. package/src/services/system-memory.d.ts +33 -0
  355. package/src/services/system-memory.d.ts.map +1 -0
  356. package/src/services/system-memory.test.ts +47 -0
  357. package/src/services/system-memory.ts +67 -0
  358. package/src/services/transcription-priority.test.ts +211 -0
  359. package/src/services/types.d.ts +19 -0
  360. package/src/services/types.d.ts.map +1 -0
  361. package/src/services/types.ts +55 -0
  362. package/src/services/verify-on-device.d.ts +34 -0
  363. package/src/services/verify-on-device.d.ts.map +1 -0
  364. package/src/services/verify-on-device.test.ts +87 -0
  365. package/src/services/verify-on-device.ts +127 -0
  366. package/src/services/verify.d.ts +8 -0
  367. package/src/services/verify.d.ts.map +1 -0
  368. package/src/services/verify.ts +13 -0
  369. package/src/services/vision/aosp-unavailable.d.ts +115 -0
  370. package/src/services/vision/aosp-unavailable.d.ts.map +1 -0
  371. package/src/services/vision/aosp-unavailable.ts +163 -0
  372. package/src/services/vision/capacitor-llama.d.ts +99 -0
  373. package/src/services/vision/capacitor-llama.d.ts.map +1 -0
  374. package/src/services/vision/capacitor-llama.ts +255 -0
  375. package/src/services/vision/cloud-fallback.d.ts +47 -0
  376. package/src/services/vision/cloud-fallback.d.ts.map +1 -0
  377. package/src/services/vision/cloud-fallback.test.ts +243 -0
  378. package/src/services/vision/cloud-fallback.ts +268 -0
  379. package/src/services/vision/fallback-chain.test.ts +86 -0
  380. package/src/services/vision/hash.d.ts +71 -0
  381. package/src/services/vision/hash.d.ts.map +1 -0
  382. package/src/services/vision/hash.ts +157 -0
  383. package/src/services/vision/index.d.ts +95 -0
  384. package/src/services/vision/index.d.ts.map +1 -0
  385. package/src/services/vision/index.ts +251 -0
  386. package/src/services/vision/llama-server.d.ts +73 -0
  387. package/src/services/vision/llama-server.d.ts.map +1 -0
  388. package/src/services/vision/llama-server.ts +177 -0
  389. package/src/services/vision/types.d.ts +153 -0
  390. package/src/services/vision/types.d.ts.map +1 -0
  391. package/src/services/vision/types.ts +154 -0
  392. package/src/services/vision/vast-fallback.d.ts +18 -0
  393. package/src/services/vision/vast-fallback.d.ts.map +1 -0
  394. package/src/services/vision/vast-fallback.ts +127 -0
  395. package/src/services/vision-embedding-cache.d.ts +98 -0
  396. package/src/services/vision-embedding-cache.d.ts.map +1 -0
  397. package/src/services/vision-embedding-cache.ts +189 -0
  398. package/src/services/voice/VOICE_WORKBENCH.md +88 -0
  399. package/src/services/voice/__test-helpers__/fake-ffi.ts +94 -0
  400. package/src/services/voice/__test-helpers__/synthetic-speech.ts +124 -0
  401. package/src/services/voice/__tests__/checkpoint-manager.test.ts +241 -0
  402. package/src/services/voice/__tests__/checkpoint-policy.test.ts +270 -0
  403. package/src/services/voice/__tests__/eager-context-builder.test.ts +257 -0
  404. package/src/services/voice/__tests__/eliza1-eot-scorer.test.ts +288 -0
  405. package/src/services/voice/__tests__/eot-classifier.test.ts +431 -0
  406. package/src/services/voice/__tests__/optimistic-rollback.test.ts +312 -0
  407. package/src/services/voice/__tests__/prefill-client.test.ts +266 -0
  408. package/src/services/voice/__tests__/prefix-preserving-queue.test.ts +208 -0
  409. package/src/services/voice/__tests__/streaming-asr.test.ts +450 -0
  410. package/src/services/voice/__tests__/streaming-transcriber.test.ts +339 -0
  411. package/src/services/voice/__tests__/turn-detector-resolver.test.ts +195 -0
  412. package/src/services/voice/__tests__/voice-state-machine-prefill.test.ts +275 -0
  413. package/src/services/voice/__tests__/voice-state-machine.test.ts +354 -0
  414. package/src/services/voice/asr-timed.real.test.ts +141 -0
  415. package/src/services/voice/audio-frame-consumer.d.ts +212 -0
  416. package/src/services/voice/audio-frame-consumer.d.ts.map +1 -0
  417. package/src/services/voice/audio-frame-consumer.test.ts +343 -0
  418. package/src/services/voice/audio-frame-consumer.ts +491 -0
  419. package/src/services/voice/barge-in.d.ts +112 -0
  420. package/src/services/voice/barge-in.d.ts.map +1 -0
  421. package/src/services/voice/barge-in.test.ts +244 -0
  422. package/src/services/voice/barge-in.ts +336 -0
  423. package/src/services/voice/cancellation-coordinator.d.ts +127 -0
  424. package/src/services/voice/cancellation-coordinator.d.ts.map +1 -0
  425. package/src/services/voice/cancellation-coordinator.test.ts +196 -0
  426. package/src/services/voice/cancellation-coordinator.ts +269 -0
  427. package/src/services/voice/checkpoint-manager.d.ts +199 -0
  428. package/src/services/voice/checkpoint-manager.d.ts.map +1 -0
  429. package/src/services/voice/checkpoint-manager.ts +401 -0
  430. package/src/services/voice/checkpoint-policy.ts +336 -0
  431. package/src/services/voice/composite-eot-classifier.test.ts +59 -0
  432. package/src/services/voice/e2e-harness.test.ts +182 -0
  433. package/src/services/voice/e2e-harness.ts +743 -0
  434. package/src/services/voice/eager-context-builder.d.ts +170 -0
  435. package/src/services/voice/eager-context-builder.d.ts.map +1 -0
  436. package/src/services/voice/eager-context-builder.ts +262 -0
  437. package/src/services/voice/eliza1-eot-scorer.d.ts +124 -0
  438. package/src/services/voice/eliza1-eot-scorer.d.ts.map +1 -0
  439. package/src/services/voice/eliza1-eot-scorer.ts +242 -0
  440. package/src/services/voice/embedding-server.ts +200 -0
  441. package/src/services/voice/embedding.d.ts +133 -0
  442. package/src/services/voice/embedding.d.ts.map +1 -0
  443. package/src/services/voice/embedding.test.ts +131 -0
  444. package/src/services/voice/embedding.ts +243 -0
  445. package/src/services/voice/emotion-attribution.d.ts +68 -0
  446. package/src/services/voice/emotion-attribution.d.ts.map +1 -0
  447. package/src/services/voice/emotion-attribution.test.ts +129 -0
  448. package/src/services/voice/emotion-attribution.ts +361 -0
  449. package/src/services/voice/engine-bridge-cancellation.test.ts +422 -0
  450. package/src/services/voice/engine-bridge.d.ts +759 -0
  451. package/src/services/voice/engine-bridge.d.ts.map +1 -0
  452. package/src/services/voice/engine-bridge.test.ts +384 -0
  453. package/src/services/voice/engine-bridge.ts +2302 -0
  454. package/src/services/voice/eot-classifier-ggml.d.ts +179 -0
  455. package/src/services/voice/eot-classifier-ggml.d.ts.map +1 -0
  456. package/src/services/voice/eot-classifier-ggml.ts +566 -0
  457. package/src/services/voice/eot-classifier.d.ts +214 -0
  458. package/src/services/voice/eot-classifier.d.ts.map +1 -0
  459. package/src/services/voice/eot-classifier.ts +533 -0
  460. package/src/services/voice/errors.d.ts +20 -0
  461. package/src/services/voice/errors.d.ts.map +1 -0
  462. package/src/services/voice/errors.ts +32 -0
  463. package/src/services/voice/expressive-tags.d.ts +158 -0
  464. package/src/services/voice/expressive-tags.d.ts.map +1 -0
  465. package/src/services/voice/expressive-tags.ts +405 -0
  466. package/src/services/voice/ffi-bindings.d.ts +674 -0
  467. package/src/services/voice/ffi-bindings.d.ts.map +1 -0
  468. package/src/services/voice/ffi-bindings.test.ts +728 -0
  469. package/src/services/voice/ffi-bindings.ts +3225 -0
  470. package/src/services/voice/first-line-cache.d.ts +181 -0
  471. package/src/services/voice/first-line-cache.d.ts.map +1 -0
  472. package/src/services/voice/first-line-cache.ts +725 -0
  473. package/src/services/voice/fused-eot-scorer.d.ts +51 -0
  474. package/src/services/voice/fused-eot-scorer.d.ts.map +1 -0
  475. package/src/services/voice/fused-eot-scorer.ts +135 -0
  476. package/src/services/voice/index.d.ts +91 -0
  477. package/src/services/voice/index.d.ts.map +1 -0
  478. package/src/services/voice/index.ts +481 -0
  479. package/src/services/voice/kokoro/__tests__/kokoro-backend.test.ts +151 -0
  480. package/src/services/voice/kokoro/__tests__/kokoro-engine-bridge.real.test.ts +151 -0
  481. package/src/services/voice/kokoro/__tests__/kokoro-engine-bridge.test.ts +60 -0
  482. package/src/services/voice/kokoro/__tests__/kokoro-engine-discovery.test.ts +277 -0
  483. package/src/services/voice/kokoro/__tests__/kokoro-ffi-runtime.test.ts +235 -0
  484. package/src/services/voice/kokoro/__tests__/kokoro-runtime.test.ts +95 -0
  485. package/src/services/voice/kokoro/__tests__/phonemizer.test.ts +53 -0
  486. package/src/services/voice/kokoro/__tests__/runtime-selection.test.ts +231 -0
  487. package/src/services/voice/kokoro/__tests__/voices.test.ts +57 -0
  488. package/src/services/voice/kokoro/index.ts +79 -0
  489. package/src/services/voice/kokoro/kokoro-backend.d.ts +72 -0
  490. package/src/services/voice/kokoro/kokoro-backend.d.ts.map +1 -0
  491. package/src/services/voice/kokoro/kokoro-backend.ts +207 -0
  492. package/src/services/voice/kokoro/kokoro-engine-discovery.d.ts +58 -0
  493. package/src/services/voice/kokoro/kokoro-engine-discovery.d.ts.map +1 -0
  494. package/src/services/voice/kokoro/kokoro-engine-discovery.ts +177 -0
  495. package/src/services/voice/kokoro/kokoro-ffi-runtime.d.ts +75 -0
  496. package/src/services/voice/kokoro/kokoro-ffi-runtime.d.ts.map +1 -0
  497. package/src/services/voice/kokoro/kokoro-ffi-runtime.ts +233 -0
  498. package/src/services/voice/kokoro/kokoro-runtime.d.ts +100 -0
  499. package/src/services/voice/kokoro/kokoro-runtime.d.ts.map +1 -0
  500. package/src/services/voice/kokoro/kokoro-runtime.ts +170 -0
  501. package/src/services/voice/kokoro/phoneme-stream.ts +123 -0
  502. package/src/services/voice/kokoro/phonemizer.d.ts +50 -0
  503. package/src/services/voice/kokoro/phonemizer.d.ts.map +1 -0
  504. package/src/services/voice/kokoro/phonemizer.ts +344 -0
  505. package/src/services/voice/kokoro/pick-runtime.d.ts +61 -0
  506. package/src/services/voice/kokoro/pick-runtime.d.ts.map +1 -0
  507. package/src/services/voice/kokoro/pick-runtime.test.ts +91 -0
  508. package/src/services/voice/kokoro/pick-runtime.ts +130 -0
  509. package/src/services/voice/kokoro/runtime-selection.d.ts +92 -0
  510. package/src/services/voice/kokoro/runtime-selection.d.ts.map +1 -0
  511. package/src/services/voice/kokoro/runtime-selection.ts +237 -0
  512. package/src/services/voice/kokoro/types.d.ts +82 -0
  513. package/src/services/voice/kokoro/types.d.ts.map +1 -0
  514. package/src/services/voice/kokoro/types.ts +95 -0
  515. package/src/services/voice/kokoro/voice-presets.d.ts +23 -0
  516. package/src/services/voice/kokoro/voice-presets.d.ts.map +1 -0
  517. package/src/services/voice/kokoro/voice-presets.ts +129 -0
  518. package/src/services/voice/kokoro/voices.d.ts +30 -0
  519. package/src/services/voice/kokoro/voices.d.ts.map +1 -0
  520. package/src/services/voice/kokoro/voices.ts +64 -0
  521. package/src/services/voice/lifecycle.d.ts +135 -0
  522. package/src/services/voice/lifecycle.d.ts.map +1 -0
  523. package/src/services/voice/lifecycle.test.ts +315 -0
  524. package/src/services/voice/lifecycle.ts +301 -0
  525. package/src/services/voice/live-diarization-session.d.ts +96 -0
  526. package/src/services/voice/live-diarization-session.d.ts.map +1 -0
  527. package/src/services/voice/live-diarization-session.ts +289 -0
  528. package/src/services/voice/mic-source.d.ts +136 -0
  529. package/src/services/voice/mic-source.d.ts.map +1 -0
  530. package/src/services/voice/mic-source.test.ts +210 -0
  531. package/src/services/voice/mic-source.ts +503 -0
  532. package/src/services/voice/optimistic-policy.d.ts +109 -0
  533. package/src/services/voice/optimistic-policy.d.ts.map +1 -0
  534. package/src/services/voice/optimistic-policy.test.ts +101 -0
  535. package/src/services/voice/optimistic-policy.ts +192 -0
  536. package/src/services/voice/optimistic-rollback.ts +343 -0
  537. package/src/services/voice/partial-stabilizer.d.ts +73 -0
  538. package/src/services/voice/partial-stabilizer.d.ts.map +1 -0
  539. package/src/services/voice/partial-stabilizer.test.ts +68 -0
  540. package/src/services/voice/partial-stabilizer.ts +140 -0
  541. package/src/services/voice/phoneme-tokenizer.d.ts +49 -0
  542. package/src/services/voice/phoneme-tokenizer.d.ts.map +1 -0
  543. package/src/services/voice/phoneme-tokenizer.ts +158 -0
  544. package/src/services/voice/phrase-cache.d.ts +76 -0
  545. package/src/services/voice/phrase-cache.d.ts.map +1 -0
  546. package/src/services/voice/phrase-cache.test.ts +242 -0
  547. package/src/services/voice/phrase-cache.ts +186 -0
  548. package/src/services/voice/phrase-chunker.d.ts +62 -0
  549. package/src/services/voice/phrase-chunker.d.ts.map +1 -0
  550. package/src/services/voice/phrase-chunker.test.ts +239 -0
  551. package/src/services/voice/phrase-chunker.ts +281 -0
  552. package/src/services/voice/pipeline-impls.d.ts +151 -0
  553. package/src/services/voice/pipeline-impls.d.ts.map +1 -0
  554. package/src/services/voice/pipeline-impls.l6.test.ts +110 -0
  555. package/src/services/voice/pipeline-impls.test.ts +292 -0
  556. package/src/services/voice/pipeline-impls.ts +315 -0
  557. package/src/services/voice/pipeline.d.ts +216 -0
  558. package/src/services/voice/pipeline.d.ts.map +1 -0
  559. package/src/services/voice/pipeline.ts +505 -0
  560. package/src/services/voice/prefill-client.d.ts +123 -0
  561. package/src/services/voice/prefill-client.d.ts.map +1 -0
  562. package/src/services/voice/prefill-client.ts +316 -0
  563. package/src/services/voice/prefix-preserving-queue.d.ts +113 -0
  564. package/src/services/voice/prefix-preserving-queue.d.ts.map +1 -0
  565. package/src/services/voice/prefix-preserving-queue.ts +162 -0
  566. package/src/services/voice/profile-store.d.ts +248 -0
  567. package/src/services/voice/profile-store.d.ts.map +1 -0
  568. package/src/services/voice/profile-store.ts +887 -0
  569. package/src/services/voice/real-audio-decode.test.ts +148 -0
  570. package/src/services/voice/ring-buffer.d.ts +40 -0
  571. package/src/services/voice/ring-buffer.d.ts.map +1 -0
  572. package/src/services/voice/ring-buffer.test.ts +129 -0
  573. package/src/services/voice/ring-buffer.ts +123 -0
  574. package/src/services/voice/rollback-queue.d.ts +24 -0
  575. package/src/services/voice/rollback-queue.d.ts.map +1 -0
  576. package/src/services/voice/rollback-queue.ts +74 -0
  577. package/src/services/voice/samantha-preset-placeholder.d.ts +67 -0
  578. package/src/services/voice/samantha-preset-placeholder.d.ts.map +1 -0
  579. package/src/services/voice/samantha-preset-placeholder.test.ts +97 -0
  580. package/src/services/voice/samantha-preset-placeholder.ts +148 -0
  581. package/src/services/voice/samantha-preset-regenerator.d.ts +87 -0
  582. package/src/services/voice/samantha-preset-regenerator.d.ts.map +1 -0
  583. package/src/services/voice/samantha-preset-regenerator.ts +393 -0
  584. package/src/services/voice/scheduler.d.ts +146 -0
  585. package/src/services/voice/scheduler.d.ts.map +1 -0
  586. package/src/services/voice/scheduler.t2.test.ts +141 -0
  587. package/src/services/voice/scheduler.ts +927 -0
  588. package/src/services/voice/shared-resources.d.ts +190 -0
  589. package/src/services/voice/shared-resources.d.ts.map +1 -0
  590. package/src/services/voice/shared-resources.ts +320 -0
  591. package/src/services/voice/speaker/attribution-pipeline.d.ts +74 -0
  592. package/src/services/voice/speaker/attribution-pipeline.d.ts.map +1 -0
  593. package/src/services/voice/speaker/attribution-pipeline.ts +386 -0
  594. package/src/services/voice/speaker/diarizer-fused.d.ts +59 -0
  595. package/src/services/voice/speaker/diarizer-fused.d.ts.map +1 -0
  596. package/src/services/voice/speaker/diarizer-fused.real.test.ts +100 -0
  597. package/src/services/voice/speaker/diarizer-fused.ts +154 -0
  598. package/src/services/voice/speaker/diarizer.d.ts +75 -0
  599. package/src/services/voice/speaker/diarizer.d.ts.map +1 -0
  600. package/src/services/voice/speaker/diarizer.ts +218 -0
  601. package/src/services/voice/speaker/encoder-fused.d.ts +60 -0
  602. package/src/services/voice/speaker/encoder-fused.d.ts.map +1 -0
  603. package/src/services/voice/speaker/encoder-fused.real.test.ts +113 -0
  604. package/src/services/voice/speaker/encoder-fused.ts +138 -0
  605. package/src/services/voice/speaker/encoder-ggml.d.ts +33 -0
  606. package/src/services/voice/speaker/encoder-ggml.d.ts.map +1 -0
  607. package/src/services/voice/speaker/encoder-ggml.ts +79 -0
  608. package/src/services/voice/speaker/encoder.d.ts +37 -0
  609. package/src/services/voice/speaker/encoder.d.ts.map +1 -0
  610. package/src/services/voice/speaker/encoder.ts +105 -0
  611. package/src/services/voice/speaker-imprint.d.ts +83 -0
  612. package/src/services/voice/speaker-imprint.d.ts.map +1 -0
  613. package/src/services/voice/speaker-imprint.test.ts +185 -0
  614. package/src/services/voice/speaker-imprint.ts +312 -0
  615. package/src/services/voice/speaker-preset-cache.d.ts +77 -0
  616. package/src/services/voice/speaker-preset-cache.d.ts.map +1 -0
  617. package/src/services/voice/speaker-preset-cache.test.ts +154 -0
  618. package/src/services/voice/speaker-preset-cache.ts +195 -0
  619. package/src/services/voice/streaming-asr/streaming-pipeline-adapter.ts +292 -0
  620. package/src/services/voice/system-audio-sink.d.ts +73 -0
  621. package/src/services/voice/system-audio-sink.d.ts.map +1 -0
  622. package/src/services/voice/system-audio-sink.test.ts +29 -0
  623. package/src/services/voice/system-audio-sink.ts +366 -0
  624. package/src/services/voice/transcriber.d.ts +244 -0
  625. package/src/services/voice/transcriber.d.ts.map +1 -0
  626. package/src/services/voice/transcriber.test.ts +392 -0
  627. package/src/services/voice/transcriber.ts +704 -0
  628. package/src/services/voice/transcript-knowledge.d.ts +37 -0
  629. package/src/services/voice/transcript-knowledge.d.ts.map +1 -0
  630. package/src/services/voice/transcript-knowledge.test.ts +68 -0
  631. package/src/services/voice/transcript-knowledge.ts +75 -0
  632. package/src/services/voice/transcript-service.d.ts +41 -0
  633. package/src/services/voice/transcript-service.d.ts.map +1 -0
  634. package/src/services/voice/transcript-service.test.ts +137 -0
  635. package/src/services/voice/transcript-service.ts +141 -0
  636. package/src/services/voice/transcript-store.d.ts +53 -0
  637. package/src/services/voice/transcript-store.d.ts.map +1 -0
  638. package/src/services/voice/transcript-store.test.ts +153 -0
  639. package/src/services/voice/transcript-store.ts +132 -0
  640. package/src/services/voice/turn-controller.d.ts +183 -0
  641. package/src/services/voice/turn-controller.d.ts.map +1 -0
  642. package/src/services/voice/turn-controller.test.ts +575 -0
  643. package/src/services/voice/turn-controller.ts +596 -0
  644. package/src/services/voice/types.d.ts +643 -0
  645. package/src/services/voice/types.d.ts.map +1 -0
  646. package/src/services/voice/types.ts +699 -0
  647. package/src/services/voice/vad.d.ts +282 -0
  648. package/src/services/voice/vad.d.ts.map +1 -0
  649. package/src/services/voice/vad.test.ts +480 -0
  650. package/src/services/voice/vad.ts +827 -0
  651. package/src/services/voice/vad.v1-v4.test.ts +222 -0
  652. package/src/services/voice/voice-budget.d.ts +241 -0
  653. package/src/services/voice/voice-budget.d.ts.map +1 -0
  654. package/src/services/voice/voice-budget.test.ts +418 -0
  655. package/src/services/voice/voice-budget.ts +635 -0
  656. package/src/services/voice/voice-duet.test.ts +375 -0
  657. package/src/services/voice/voice-emotion-classifier.d.ts +95 -0
  658. package/src/services/voice/voice-emotion-classifier.d.ts.map +1 -0
  659. package/src/services/voice/voice-emotion-classifier.test.ts +210 -0
  660. package/src/services/voice/voice-emotion-classifier.ts +273 -0
  661. package/src/services/voice/voice-preset-format.d.ts +158 -0
  662. package/src/services/voice/voice-preset-format.d.ts.map +1 -0
  663. package/src/services/voice/voice-preset-format.ts +700 -0
  664. package/src/services/voice/voice-preset-generator.test.ts +89 -0
  665. package/src/services/voice/voice-profile-artifact.d.ts +116 -0
  666. package/src/services/voice/voice-profile-artifact.d.ts.map +1 -0
  667. package/src/services/voice/voice-profile-artifact.test.ts +138 -0
  668. package/src/services/voice/voice-profile-artifact.ts +518 -0
  669. package/src/services/voice/voice-profile-routes.d.ts +83 -0
  670. package/src/services/voice/voice-profile-routes.d.ts.map +1 -0
  671. package/src/services/voice/voice-profile-routes.test.ts +429 -0
  672. package/src/services/voice/voice-profile-routes.ts +425 -0
  673. package/src/services/voice/voice-scenario.ts +154 -0
  674. package/src/services/voice/voice-settings.d.ts +82 -0
  675. package/src/services/voice/voice-settings.d.ts.map +1 -0
  676. package/src/services/voice/voice-settings.ts +172 -0
  677. package/src/services/voice/voice-state-machine.d.ts +364 -0
  678. package/src/services/voice/voice-state-machine.d.ts.map +1 -0
  679. package/src/services/voice/voice-state-machine.ts +727 -0
  680. package/src/services/voice/voice-workbench-report.test.ts +168 -0
  681. package/src/services/voice/voice-workbench-report.ts +326 -0
  682. package/src/services/voice/voice-workbench.test.ts +158 -0
  683. package/src/services/voice/voice.test.ts +1070 -0
  684. package/src/services/voice/wake-word-ggml.d.ts +101 -0
  685. package/src/services/voice/wake-word-ggml.d.ts.map +1 -0
  686. package/src/services/voice/wake-word-ggml.ts +320 -0
  687. package/src/services/voice/wake-word.d.ts +255 -0
  688. package/src/services/voice/wake-word.d.ts.map +1 -0
  689. package/src/services/voice/wake-word.test.ts +298 -0
  690. package/src/services/voice/wake-word.ts +554 -0
  691. package/src/services/voice/wrap-with-first-line-cache.d.ts +70 -0
  692. package/src/services/voice/wrap-with-first-line-cache.d.ts.map +1 -0
  693. package/src/services/voice/wrap-with-first-line-cache.ts +267 -0
  694. package/src/services/voice-model-updater.d.ts +240 -0
  695. package/src/services/voice-model-updater.d.ts.map +1 -0
  696. package/src/services/voice-model-updater.ts +724 -0
  697. package/src/services/voice-prewarm.d.ts +3 -0
  698. package/src/services/voice-prewarm.d.ts.map +1 -0
  699. package/src/services/voice-prewarm.ts +51 -0
  700. package/dist/index.d.ts +0 -37
  701. package/dist/index.js +0 -1098
@@ -0,0 +1,239 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { type ClockMs, chunkTokens, PhraseChunker } from "./phrase-chunker";
3
+ import type { TextToken } from "./types";
4
+
5
+ function tokens(parts: string[]): TextToken[] {
6
+ return parts.map((text, index) => ({ index, text }));
7
+ }
8
+
9
+ describe("PhraseChunker punctuation boundaries", () => {
10
+ it("flushes on semicolon and colon boundaries for faster first audio", () => {
11
+ const phrases = chunkTokens(tokens(["First:", " second;", " third"]), {});
12
+
13
+ expect(phrases.map((phrase) => phrase.text)).toEqual([
14
+ "First:",
15
+ " second;",
16
+ " third",
17
+ ]);
18
+ expect(phrases.map((phrase) => phrase.terminator)).toEqual([
19
+ "punctuation",
20
+ "punctuation",
21
+ "max-cap",
22
+ ]);
23
+ });
24
+ });
25
+
26
+ describe("PhraseChunker T3 time-budget flush", () => {
27
+ it("force-flushes once the time budget elapses on a slow producer", () => {
28
+ let now = 0;
29
+ const clock: ClockMs = () => now;
30
+ const chunker = new PhraseChunker(
31
+ // Pin first-phrase budget == full budget so these mechanism tests
32
+ // exercise the uniform 200ms path (first-phrase shortening is
33
+ // covered separately below).
34
+ {
35
+ maxAccumulationMs: 200,
36
+ firstPhraseMaxAccumulationMs: 200,
37
+ maxTokensPerPhrase: 100,
38
+ },
39
+ null,
40
+ clock,
41
+ );
42
+
43
+ expect(chunker.push({ index: 0, text: "hello", acceptedAt: 0 })).toBeNull();
44
+ now = 100;
45
+ expect(
46
+ chunker.push({ index: 1, text: " there", acceptedAt: 0 }),
47
+ ).toBeNull();
48
+ now = 220;
49
+ const flushed = chunker.push({ index: 2, text: " friend", acceptedAt: 0 });
50
+ expect(flushed).not.toBeNull();
51
+ expect(flushed?.text).toBe("hello there friend");
52
+ expect(flushed?.terminator).toBe("max-cap");
53
+ });
54
+
55
+ it("does not flush before the budget elapses", () => {
56
+ let now = 0;
57
+ const clock: ClockMs = () => now;
58
+ const chunker = new PhraseChunker(
59
+ // Pin first-phrase budget == full budget so these mechanism tests
60
+ // exercise the uniform 200ms path (first-phrase shortening is
61
+ // covered separately below).
62
+ {
63
+ maxAccumulationMs: 200,
64
+ firstPhraseMaxAccumulationMs: 200,
65
+ maxTokensPerPhrase: 100,
66
+ },
67
+ null,
68
+ clock,
69
+ );
70
+ expect(chunker.push({ index: 0, text: "a", acceptedAt: 0 })).toBeNull();
71
+ now = 50;
72
+ expect(chunker.push({ index: 1, text: "b", acceptedAt: 0 })).toBeNull();
73
+ now = 150;
74
+ expect(chunker.push({ index: 2, text: "c", acceptedAt: 0 })).toBeNull();
75
+ });
76
+
77
+ it("flushIfTimeBudgetExceeded triggers on caller poll without a new token", () => {
78
+ let now = 0;
79
+ const clock: ClockMs = () => now;
80
+ const chunker = new PhraseChunker(
81
+ // Pin first-phrase budget == full budget so these mechanism tests
82
+ // exercise the uniform 200ms path (first-phrase shortening is
83
+ // covered separately below).
84
+ {
85
+ maxAccumulationMs: 200,
86
+ firstPhraseMaxAccumulationMs: 200,
87
+ maxTokensPerPhrase: 100,
88
+ },
89
+ null,
90
+ clock,
91
+ );
92
+ chunker.push({ index: 0, text: "x", acceptedAt: 0 });
93
+ now = 100;
94
+ expect(chunker.flushIfTimeBudgetExceeded()).toBeNull();
95
+ now = 250;
96
+ const phrase = chunker.flushIfTimeBudgetExceeded();
97
+ expect(phrase?.text).toBe("x");
98
+ expect(phrase?.terminator).toBe("max-cap");
99
+ expect(chunker.flushIfTimeBudgetExceeded()).toBeNull();
100
+ });
101
+
102
+ it("msUntilTimeBudget reports infinity for an empty buffer or disabled budget", () => {
103
+ let now = 0;
104
+ const clock: ClockMs = () => now;
105
+ const chunker = new PhraseChunker(
106
+ // Pin first-phrase budget == full budget so these mechanism tests
107
+ // exercise the uniform 200ms path (first-phrase shortening is
108
+ // covered separately below).
109
+ {
110
+ maxAccumulationMs: 200,
111
+ firstPhraseMaxAccumulationMs: 200,
112
+ maxTokensPerPhrase: 100,
113
+ },
114
+ null,
115
+ clock,
116
+ );
117
+ expect(chunker.msUntilTimeBudget()).toBe(Number.POSITIVE_INFINITY);
118
+ chunker.push({ index: 0, text: "x", acceptedAt: 0 });
119
+ expect(chunker.msUntilTimeBudget()).toBe(200);
120
+ now = 75;
121
+ expect(chunker.msUntilTimeBudget()).toBe(125);
122
+
123
+ const disabled = new PhraseChunker(
124
+ { maxAccumulationMs: 0, maxTokensPerPhrase: 100 },
125
+ null,
126
+ clock,
127
+ );
128
+ disabled.push({ index: 0, text: "x", acceptedAt: 0 });
129
+ expect(disabled.msUntilTimeBudget()).toBe(Number.POSITIVE_INFINITY);
130
+ });
131
+
132
+ it("disabled budget never time-flushes", () => {
133
+ let now = 0;
134
+ const clock: ClockMs = () => now;
135
+ const chunker = new PhraseChunker(
136
+ { maxAccumulationMs: 0, maxTokensPerPhrase: 100 },
137
+ null,
138
+ clock,
139
+ );
140
+ chunker.push({ index: 0, text: "a", acceptedAt: 0 });
141
+ now = 10_000;
142
+ expect(chunker.push({ index: 1, text: " b", acceptedAt: 0 })).toBeNull();
143
+ expect(chunker.flushIfTimeBudgetExceeded()).toBeNull();
144
+ });
145
+ });
146
+
147
+ describe("PhraseChunker first-phrase budget (TTFA)", () => {
148
+ it("flushes the first phrase on the shorter budget, later phrases on the full one", () => {
149
+ let now = 0;
150
+ const clock: ClockMs = () => now;
151
+ const chunker = new PhraseChunker(
152
+ {
153
+ maxAccumulationMs: 700,
154
+ firstPhraseMaxAccumulationMs: 300,
155
+ maxTokensPerPhrase: 100,
156
+ },
157
+ null,
158
+ clock,
159
+ );
160
+ // First phrase: silent producer, no punctuation — flushes at 300ms.
161
+ expect(chunker.push({ index: 0, text: "hello", acceptedAt: 0 })).toBeNull();
162
+ expect(chunker.msUntilTimeBudget()).toBe(300);
163
+ now = 300;
164
+ const first = chunker.flushIfTimeBudgetExceeded();
165
+ expect(first?.text).toBe("hello");
166
+ expect(first?.terminator).toBe("max-cap");
167
+
168
+ // Second phrase now uses the FULL 700ms budget (no fragmentation).
169
+ now = 1000;
170
+ expect(
171
+ chunker.push({ index: 1, text: " there", acceptedAt: 0 }),
172
+ ).toBeNull();
173
+ expect(chunker.msUntilTimeBudget()).toBe(700);
174
+ now = 1300; // 300ms in — would have flushed the first phrase, not this one
175
+ expect(chunker.flushIfTimeBudgetExceeded()).toBeNull();
176
+ now = 1700; // full 700ms elapsed
177
+ expect(chunker.flushIfTimeBudgetExceeded()?.text).toBe(" there");
178
+ });
179
+
180
+ it("derives the first-phrase budget from maxAccumulationMs when unset (half, capped 350)", () => {
181
+ const now = 0;
182
+ const clock: ClockMs = () => now;
183
+ // 700ms full → first-phrase budget = min(350, 350) = 350.
184
+ const chunker = new PhraseChunker(
185
+ { maxAccumulationMs: 700, maxTokensPerPhrase: 100 },
186
+ null,
187
+ clock,
188
+ );
189
+ chunker.push({ index: 0, text: "x", acceptedAt: 0 });
190
+ expect(chunker.msUntilTimeBudget()).toBe(350);
191
+
192
+ // 400ms full → half = 200 (below the 350 cap).
193
+ const small = new PhraseChunker(
194
+ { maxAccumulationMs: 400, maxTokensPerPhrase: 100 },
195
+ null,
196
+ clock,
197
+ );
198
+ small.push({ index: 0, text: "x", acceptedAt: 0 });
199
+ expect(small.msUntilTimeBudget()).toBe(200);
200
+ });
201
+
202
+ it("resets the first-phrase gate on reset() so each reply gets fast first audio", () => {
203
+ let now = 0;
204
+ const clock: ClockMs = () => now;
205
+ const chunker = new PhraseChunker(
206
+ {
207
+ maxAccumulationMs: 700,
208
+ firstPhraseMaxAccumulationMs: 300,
209
+ maxTokensPerPhrase: 100,
210
+ },
211
+ null,
212
+ clock,
213
+ );
214
+ chunker.push({ index: 0, text: "first", acceptedAt: 0 });
215
+ now = 300;
216
+ expect(chunker.flushIfTimeBudgetExceeded()).not.toBeNull(); // phrase #1 flushed
217
+ chunker.reset();
218
+ now = 1000;
219
+ chunker.push({ index: 0, text: "again", acceptedAt: 0 });
220
+ // Back to the short first-phrase budget after reset.
221
+ expect(chunker.msUntilTimeBudget()).toBe(300);
222
+ });
223
+
224
+ it("clamps an explicit first-phrase budget to the full budget", () => {
225
+ const now = 0;
226
+ const clock: ClockMs = () => now;
227
+ const chunker = new PhraseChunker(
228
+ {
229
+ maxAccumulationMs: 200,
230
+ firstPhraseMaxAccumulationMs: 999,
231
+ maxTokensPerPhrase: 100,
232
+ },
233
+ null,
234
+ clock,
235
+ );
236
+ chunker.push({ index: 0, text: "x", acceptedAt: 0 });
237
+ expect(chunker.msUntilTimeBudget()).toBe(200);
238
+ });
239
+ });
@@ -0,0 +1,281 @@
1
+ import type { PhonemeTokenizer } from "./phoneme-tokenizer";
2
+ import type {
3
+ AcceptedToken,
4
+ Phrase,
5
+ PhraseChunkerConfig,
6
+ TextToken,
7
+ } from "./types";
8
+
9
+ /**
10
+ * Default phrase boundaries: end-of-clause punctuation plus the three
11
+ * sentence-final marks. Per `packages/inference/AGENTS.md` §4 / the
12
+ * voice-swarm brief item A6 — "the first segment delimited by punctuation
13
+ * OR the first 30 words, whichever comes first". Cutting a phrase at the
14
+ * first comma/semicolon/colon hands TTS something to say without waiting
15
+ * for a sentence-final mark.
16
+ */
17
+ const DEFAULT_TERMINATORS: ReadonlySet<string> = new Set([
18
+ ",",
19
+ ".",
20
+ "!",
21
+ "?",
22
+ ";",
23
+ ":",
24
+ ]);
25
+ const DEFAULT_PHONEMES_PER_CHUNK = 8;
26
+ /** Default hard word cap when a caller doesn't supply `maxTokensPerPhrase` (the brief's "first 30 words"). */
27
+ const DEFAULT_MAX_TOKENS_PER_PHRASE = 30;
28
+ /**
29
+ * T3 — default time budget in milliseconds for the time-budget phrase
30
+ * flush. When a phrase has been accumulating in the buffer for this long
31
+ * without hitting a punctuation / phoneme / cap boundary, force a flush
32
+ * so the next phrase reaches TTS instead of stalling behind a slow
33
+ * producer. Override via `ELIZA_PHRASE_FLUSH_MS` env var.
34
+ *
35
+ * The default is deliberately phrase-sized. A 200ms budget was fast on paper
36
+ * but split slow token streams into word fragments, which made OmniVoice
37
+ * produce filler-like audio and degraded the downstream ASR loop.
38
+ */
39
+ function resolveDefaultMaxAccumulationMs(): number {
40
+ const raw = process.env.ELIZA_PHRASE_FLUSH_MS?.trim();
41
+ if (raw) {
42
+ const v = Number.parseInt(raw, 10);
43
+ if (Number.isFinite(v) && v > 0) return v;
44
+ }
45
+ return 700;
46
+ }
47
+ const DEFAULT_MAX_ACCUMULATION_MS = resolveDefaultMaxAccumulationMs();
48
+
49
+ /**
50
+ * First-audio (TTFA) optimization: the FIRST phrase of a reply uses a shorter
51
+ * time budget than the rest. First-audio latency is the dominant voice-UX
52
+ * metric, and a punctuation-sparse opening otherwise waits the full
53
+ * {@link DEFAULT_MAX_ACCUMULATION_MS} before any sound plays. Once audio is
54
+ * flowing, later phrases keep the full budget so the bulk of the reply is not
55
+ * fragmented into word-sized chunks (the failure mode the 700ms default fixed).
56
+ * Override via `ELIZA_PHRASE_FLUSH_FIRST_MS`; defaults to half the full budget,
57
+ * capped at 350ms. A non-positive full budget disables both.
58
+ */
59
+ function resolveFirstPhraseMs(fullBudgetMs: number): number {
60
+ if (fullBudgetMs <= 0) return 0;
61
+ const raw = process.env.ELIZA_PHRASE_FLUSH_FIRST_MS?.trim();
62
+ if (raw) {
63
+ const v = Number.parseInt(raw, 10);
64
+ if (Number.isFinite(v) && v > 0) return Math.min(v, fullBudgetMs);
65
+ }
66
+ return Math.min(350, Math.ceil(fullBudgetMs / 2));
67
+ }
68
+
69
+ /** Wall-clock source the chunker uses. Tests inject a deterministic clock. */
70
+ export type ClockMs = () => number;
71
+
72
+ const DEFAULT_CLOCK: ClockMs = () => globalThis.performance.now();
73
+
74
+ export class PhraseChunker {
75
+ private buffer: AcceptedToken[] = [];
76
+ private nextPhraseId = 0;
77
+ private readonly terminators: ReadonlySet<string>;
78
+ private readonly chunkOn: "punctuation" | "phoneme-stream";
79
+ private readonly phonemesPerChunk: number;
80
+ private readonly maxTokensPerPhrase: number;
81
+ private readonly tokenizer: PhonemeTokenizer | null;
82
+ private phonemeCount = 0;
83
+ /**
84
+ * T3 — time-budget flush. `firstTokenAtMs` is captured on the first
85
+ * `push()` after an empty buffer; once `clock() - firstTokenAtMs >=
86
+ * maxAccumulationMs` the chunker force-flushes even without a
87
+ * punctuation / phoneme / cap boundary. `maxAccumulationMs <= 0`
88
+ * disables the time budget.
89
+ */
90
+ private readonly maxAccumulationMs: number;
91
+ /** Shorter budget applied only while no phrase has flushed yet this reply. */
92
+ private readonly firstPhraseMaxAccumulationMs: number;
93
+ private readonly clock: ClockMs;
94
+ private firstTokenAtMs = 0;
95
+ /** Phrases emitted since the last {@link reset}; gates the first-phrase budget. */
96
+ private phrasesEmitted = 0;
97
+
98
+ constructor(
99
+ config: PhraseChunkerConfig,
100
+ tokenizer: PhonemeTokenizer | null = null,
101
+ clock: ClockMs = DEFAULT_CLOCK,
102
+ ) {
103
+ this.terminators = config.sentenceTerminators ?? DEFAULT_TERMINATORS;
104
+ this.chunkOn = config.chunkOn ?? "punctuation";
105
+ this.phonemesPerChunk = Math.max(
106
+ 1,
107
+ config.phonemesPerChunk ?? DEFAULT_PHONEMES_PER_CHUNK,
108
+ );
109
+ this.maxTokensPerPhrase = Math.max(
110
+ 1,
111
+ config.maxTokensPerPhrase ?? DEFAULT_MAX_TOKENS_PER_PHRASE,
112
+ );
113
+ this.maxAccumulationMs =
114
+ config.maxAccumulationMs !== undefined
115
+ ? Math.max(0, config.maxAccumulationMs)
116
+ : DEFAULT_MAX_ACCUMULATION_MS;
117
+ this.firstPhraseMaxAccumulationMs =
118
+ config.firstPhraseMaxAccumulationMs !== undefined
119
+ ? Math.min(
120
+ this.maxAccumulationMs,
121
+ Math.max(0, config.firstPhraseMaxAccumulationMs),
122
+ )
123
+ : resolveFirstPhraseMs(this.maxAccumulationMs);
124
+ this.clock = clock;
125
+ this.tokenizer = tokenizer;
126
+ if (this.chunkOn === "phoneme-stream" && this.tokenizer === null) {
127
+ throw new Error(
128
+ "PhraseChunker: chunkOn='phoneme-stream' requires a PhonemeTokenizer",
129
+ );
130
+ }
131
+ }
132
+
133
+ push(token: AcceptedToken): Phrase | null {
134
+ if (this.buffer.length === 0) {
135
+ this.firstTokenAtMs = this.clock();
136
+ }
137
+ this.buffer.push(token);
138
+
139
+ // Punctuation always wins — a `, . ! ?` boundary forces a flush even
140
+ // in phoneme-stream mode.
141
+ if (this.endsWithTerminator(token.text)) {
142
+ return this.flushAs("punctuation");
143
+ }
144
+
145
+ if (this.chunkOn === "phoneme-stream" && this.tokenizer !== null) {
146
+ const phonemes = this.tokenizer.tokenize(token.text, token.index);
147
+ this.phonemeCount += phonemes.length;
148
+ if (this.phonemeCount >= this.phonemesPerChunk) {
149
+ return this.flushAs("phoneme-stream");
150
+ }
151
+ }
152
+
153
+ if (this.buffer.length >= this.maxTokensPerPhrase) {
154
+ return this.flushAs("max-cap");
155
+ }
156
+
157
+ // T3 — time-budget flush. Re-uses the `"max-cap"` terminator because
158
+ // adding a new terminator value would require editing the shared
159
+ // `Phrase` type in `types.ts`. Structurally "the chunker forced a
160
+ // flush" is what max-cap already means.
161
+ const budget = this.currentBudgetMs();
162
+ if (budget > 0 && this.clock() - this.firstTokenAtMs >= budget) {
163
+ return this.flushAs("max-cap");
164
+ }
165
+ return null;
166
+ }
167
+
168
+ /** Active time budget: the shorter first-phrase budget until the reply's
169
+ * first phrase has flushed, then the full budget. */
170
+ private currentBudgetMs(): number {
171
+ return this.phrasesEmitted === 0
172
+ ? this.firstPhraseMaxAccumulationMs
173
+ : this.maxAccumulationMs;
174
+ }
175
+
176
+ /**
177
+ * T3 — caller-driven check. Returns a phrase when the time budget has
178
+ * elapsed for the current buffer, otherwise null. The scheduler polls
179
+ * this from a `setTimeout` so even a producer that goes silent before
180
+ * pushing the next token still gets its in-flight phrase flushed.
181
+ */
182
+ flushIfTimeBudgetExceeded(): Phrase | null {
183
+ if (this.buffer.length === 0) return null;
184
+ const budget = this.currentBudgetMs();
185
+ if (budget <= 0) return null;
186
+ if (this.clock() - this.firstTokenAtMs < budget) {
187
+ return null;
188
+ }
189
+ return this.flushAs("max-cap");
190
+ }
191
+
192
+ /**
193
+ * T3 — milliseconds remaining until the time budget elapses for the
194
+ * current buffer. Negative when the budget has already been exceeded;
195
+ * `Number.POSITIVE_INFINITY` when the buffer is empty or the budget is
196
+ * disabled. Callers compute their flush timer off this.
197
+ */
198
+ msUntilTimeBudget(): number {
199
+ if (this.buffer.length === 0) return Number.POSITIVE_INFINITY;
200
+ const budget = this.currentBudgetMs();
201
+ if (budget <= 0) return Number.POSITIVE_INFINITY;
202
+ return this.firstTokenAtMs + budget - this.clock();
203
+ }
204
+
205
+ flushPending(): Phrase | null {
206
+ if (this.buffer.length === 0) return null;
207
+ return this.flushAs("max-cap");
208
+ }
209
+
210
+ /**
211
+ * Drop buffered tokens that have not flushed whose token index is ≥
212
+ * `fromIndex`. Used by the pipeline's rollback path: when the target
213
+ * verifier rejects a draft tail, any draft tokens still sitting in the
214
+ * chunker's buffer before phrase packing MUST be discarded so
215
+ * the verifier's correction does not get glued onto stale text.
216
+ * Phonemes are recounted from scratch over what remains.
217
+ */
218
+ dropPendingFrom(fromIndex: number): void {
219
+ const kept = this.buffer.filter((t) => t.index < fromIndex);
220
+ if (kept.length === this.buffer.length) return;
221
+ this.buffer = kept;
222
+ this.phonemeCount = 0;
223
+ if (this.buffer.length === 0) {
224
+ this.firstTokenAtMs = 0;
225
+ }
226
+ if (this.chunkOn === "phoneme-stream" && this.tokenizer !== null) {
227
+ for (const t of this.buffer) {
228
+ this.phonemeCount += this.tokenizer.tokenize(t.text, t.index).length;
229
+ }
230
+ }
231
+ }
232
+
233
+ reset(): void {
234
+ this.buffer = [];
235
+ this.phonemeCount = 0;
236
+ this.firstTokenAtMs = 0;
237
+ this.phrasesEmitted = 0;
238
+ }
239
+
240
+ private endsWithTerminator(text: string): boolean {
241
+ if (text.length === 0) return false;
242
+ const last = text[text.length - 1];
243
+ return this.terminators.has(last);
244
+ }
245
+
246
+ private flushAs(terminator: Phrase["terminator"]): Phrase {
247
+ const tokens = this.buffer;
248
+ this.buffer = [];
249
+ this.phonemeCount = 0;
250
+ this.firstTokenAtMs = 0;
251
+ this.phrasesEmitted++;
252
+ const fromIndex = tokens[0].index;
253
+ const toIndex = tokens[tokens.length - 1].index;
254
+ const text = tokens.map((t) => t.text).join("");
255
+ const phrase: Phrase = {
256
+ id: this.nextPhraseId++,
257
+ text,
258
+ fromIndex,
259
+ toIndex,
260
+ terminator,
261
+ };
262
+ return phrase;
263
+ }
264
+ }
265
+
266
+ export function chunkTokens(
267
+ tokens: TextToken[],
268
+ config: PhraseChunkerConfig,
269
+ acceptedAt = 0,
270
+ tokenizer: PhonemeTokenizer | null = null,
271
+ ): Phrase[] {
272
+ const chunker = new PhraseChunker(config, tokenizer);
273
+ const phrases: Phrase[] = [];
274
+ for (const t of tokens) {
275
+ const p = chunker.push({ ...t, acceptedAt });
276
+ if (p) phrases.push(p);
277
+ }
278
+ const tail = chunker.flushPending();
279
+ if (tail) phrases.push(tail);
280
+ return phrases;
281
+ }
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Concrete implementations of the `VoicePipeline` seams (`pipeline.ts`).
3
+ *
4
+ * `pipeline.ts` defines two interfaces — `DraftProposer`, `TargetVerifier`
5
+ * — plus the ASR contract (it consumes the live `StreamingTranscriber`
6
+ * from `voice/types.ts` directly) and an overlapped scheduler that drives
7
+ * the fused mic→speech graph from `packages/inference/AGENTS.md` §4. This
8
+ * module fills those interfaces against the live runtime:
9
+ *
10
+ * - `MissingAsrTranscriber` — a `StreamingTranscriber` that hard-fails
11
+ * when no ASR backend is available (AGENTS.md §3 — no silent cloud
12
+ * fallback). The bridge's `resolveTranscriber()` returns this instead
13
+ * of throwing eagerly so the failure surfaces at turn time.
14
+ * - `MtpDraftProposer` — proposes a small MTP draft window from the
15
+ * running in-process llama.cpp runtime; honours `cancel.cancelled`
16
+ * between kernel ticks.
17
+ * - `MtpTargetVerifier` — verifies against the text model's KV cache
18
+ * and consumes exact verifier accept/reject events when the runtime
19
+ * emits them.
20
+ *
21
+ * Hard-fail discipline (AGENTS.md §3 + §9): a missing fused ASR region in
22
+ * voice mode is a thrown `VoiceStartupError`, never a silent cloud
23
+ * fallback, never log-and-continue.
24
+ *
25
+ * Why a separate file from `pipeline.ts`: `pipeline.ts` stays
26
+ * dependency-light (it is the streaming contract, importable by text-only
27
+ * callers). The runtime wiring lives here so
28
+ * the contract module does not drag it in.
29
+ */
30
+ import type { GenerateArgs } from "../backend";
31
+ import { type DraftProposer, type TargetVerifier } from "./pipeline";
32
+ import type { PcmFrame, StreamingTranscriber, TextToken, TranscriptUpdate, VerifierStreamEvent } from "./types";
33
+ /**
34
+ * A `StreamingTranscriber` that hard-fails: used when no ASR backend is
35
+ * available (no fused streaming decoder, no fused batch decoder, no
36
+ * bundled ASR region) but a voice turn was requested. AGENTS.md §3 —
37
+ * missing required voice backend in voice mode is a thrown
38
+ * `VoiceStartupError`, never a silent fallback. The bridge returns this
39
+ * from `resolveTranscriber()` so the failure surfaces when the pipeline
40
+ * actually feeds audio rather than at bridge construction.
41
+ */
42
+ export declare class MissingAsrTranscriber implements StreamingTranscriber {
43
+ private readonly reason;
44
+ constructor(reason: string);
45
+ feed(_frame: PcmFrame): void;
46
+ flush(): Promise<TranscriptUpdate>;
47
+ on(): () => void;
48
+ dispose(): void;
49
+ }
50
+ /**
51
+ * Minimal surface of the running MTP text runtime the draft/verify
52
+ * adapters need. Kept structural so tests can pass a fake without
53
+ * standing up a real runtime.
54
+ */
55
+ export interface MtpTextRunner {
56
+ /** True when MTP speculative decoding is enabled. */
57
+ hasDrafter(): boolean;
58
+ generateWithVerifierEvents(args: GenerateArgs & {
59
+ onVerifierEvent: (event: VerifierStreamEvent) => void | Promise<void>;
60
+ }): Promise<{
61
+ text: string;
62
+ }>;
63
+ }
64
+ /** Adapt a local-inference backend onto `MtpTextRunner`. */
65
+ export declare function mtpTextRunner(runner: {
66
+ mtpEnabled(): boolean;
67
+ generateWithUsage(args: GenerateArgs & {
68
+ onVerifierEvent: (event: VerifierStreamEvent) => void | Promise<void>;
69
+ }): Promise<{
70
+ text: string;
71
+ }>;
72
+ }): MtpTextRunner;
73
+ /**
74
+ * `DraftProposer` over native MTP. The runtime draft window already bounds
75
+ * proposals; this adapter additionally
76
+ * clamps to the pipeline's `maxDraft` and stops early on
77
+ * `cancel.cancelled`. GPU dispatch is N=1 (the fork's voice profile
78
+ * disables command-buffer batching — ledger §2 "Keep voice dispatch
79
+ * unbatched") so a barge-in lands at the next kernel boundary.
80
+ *
81
+ * Until the fork exposes a "draft only, return the proposed tokens"
82
+ * endpoint, the proposer issues a short low-temperature completion
83
+ * (`maxTokens = maxDraft`) and treats the produced tokens as the draft
84
+ * window. The verifier then re-checks them against the target's KV — the
85
+ * standard speculative-decoding contract, just with the draft sourced
86
+ * from the same server.
87
+ */
88
+ export declare class MtpDraftProposer implements DraftProposer {
89
+ private readonly runner;
90
+ constructor(runner: MtpTextRunner);
91
+ propose(args: {
92
+ prefix: ReadonlyArray<TextToken>;
93
+ maxDraft: number;
94
+ cancel: {
95
+ cancelled: boolean;
96
+ };
97
+ }): Promise<TextToken[]>;
98
+ }
99
+ /**
100
+ * `TargetVerifier` over the text model via MTP. Runs one
101
+ * autoregressive verify step against the runtime KV cache: it sends the
102
+ * accepted prefix and reads back the model's own continuation. The
103
+ * leading tokens that match the supplied `draft` are "accepted from
104
+ * draft"; the first mismatch is the correction; the model's `done` /
105
+ * stop is propagated.
106
+ *
107
+ * When the native fork emits exact verifier reject ranges, the
108
+ * `onVerifierEvent` callback already carries `kind: "reject"` events with
109
+ * the rejected token positions — this adapter records both and trusts the
110
+ * server's accept/reject split rather than re-deriving it.
111
+ */
112
+ export declare class MtpTargetVerifier implements TargetVerifier {
113
+ private readonly runner;
114
+ private readonly maxStep;
115
+ constructor(runner: MtpTextRunner, opts?: {
116
+ maxStep?: number;
117
+ });
118
+ verify(args: {
119
+ prefix: ReadonlyArray<TextToken>;
120
+ draft: ReadonlyArray<TextToken>;
121
+ cancel: {
122
+ cancelled: boolean;
123
+ };
124
+ }): Promise<{
125
+ accepted: TextToken[];
126
+ done: boolean;
127
+ }>;
128
+ }
129
+ /**
130
+ * Bridge a `{cancelled: boolean}` flag (the pipeline's cancellation
131
+ * primitive — checked between kernel ticks) onto an `AbortSignal` so the
132
+ * local generation aborts when a barge-in fires.
133
+ *
134
+ * L6 — event-driven cancellation. The cancel token may expose an
135
+ * `onCancel(listener)` hook (set by the scheduler / pipeline when it
136
+ * wires the token up); when present, we fire `controller.abort()`
137
+ * synchronously from that hook and skip polling entirely. When the
138
+ * token is the plain `{cancelled: boolean}` POJO with no hook, we fall
139
+ * back to a coarse poll so a barge-in still lands in bounded time —
140
+ * but the hook-driven path is what voice barge-ins use in production.
141
+ */
142
+ export interface CancelTokenWithSignal {
143
+ cancelled: boolean;
144
+ /**
145
+ * Optional hook the token's owner fires synchronously when `cancelled`
146
+ * flips from false to true. The listener returns nothing; calling it
147
+ * after `cancelled` has already been set is a harmless no-op.
148
+ */
149
+ onCancel?: (listener: () => void) => () => void;
150
+ }
151
+ //# sourceMappingURL=pipeline-impls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-impls.d.ts","sourceRoot":"","sources":["pipeline-impls.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,OAAO,EACN,KAAK,aAAa,EAElB,KAAK,cAAc,EACnB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EACX,QAAQ,EACR,oBAAoB,EACpB,SAAS,EACT,gBAAgB,EAChB,mBAAmB,EACnB,MAAM,SAAS,CAAC;AAMjB;;;;;;;;GAQG;AACH,qBAAa,qBAAsB,YAAW,oBAAoB;IACrD,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,MAAM;IAC3C,IAAI,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI;IAGtB,KAAK,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAGxC,EAAE,IAAI,MAAM,IAAI;IAGhB,OAAO,IAAI,IAAI;CACf;AAMD;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC7B,qDAAqD;IACrD,UAAU,IAAI,OAAO,CAAC;IACtB,0BAA0B,CACzB,IAAI,EAAE,YAAY,GAAG;QACpB,eAAe,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;KACtE,GACC,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC7B;AAED,4DAA4D;AAC5D,wBAAgB,aAAa,CAAC,MAAM,EAAE;IACrC,UAAU,IAAI,OAAO,CAAC;IACtB,iBAAiB,CAChB,IAAI,EAAE,YAAY,GAAG;QACpB,eAAe,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;KACtE,GACC,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC7B,GAAG,aAAa,CAUhB;AAaD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,gBAAiB,YAAW,aAAa;IACrD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;gBAE3B,MAAM,EAAE,aAAa;IAI3B,OAAO,CAAC,IAAI,EAAE;QACnB,MAAM,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;QACjC,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE;YAAE,SAAS,EAAE,OAAO,CAAA;SAAE,CAAC;KAC/B,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;CA6BxB;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,iBAAkB,YAAW,cAAc;IACvD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,MAAM,EAAE,aAAa,EAAE,IAAI,GAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAO;IAK5D,MAAM,CAAC,IAAI,EAAE;QAClB,MAAM,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;QACjC,KAAK,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;QAChC,MAAM,EAAE;YAAE,SAAS,EAAE,OAAO,CAAA;SAAE,CAAC;KAC/B,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC;CA2CrD;AAMD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,qBAAqB;IACrC,SAAS,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAC;CAChD"}