@elizaos/plugin-local-inference 2.0.0-beta.1 → 2.0.11-beta.7

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 (676) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +83 -0
  3. package/package.json +81 -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/adapters/capacitor-llama/__tests__/compat-behavior.test.ts +218 -0
  11. package/src/adapters/capacitor-llama/__tests__/index.test.ts +68 -0
  12. package/src/adapters/capacitor-llama/__tests__/structured-output.test.ts +215 -0
  13. package/src/adapters/capacitor-llama/__tests__/text-streaming.test.ts +174 -0
  14. package/src/adapters/capacitor-llama/environment.ts +71 -0
  15. package/src/adapters/capacitor-llama/index.browser.ts +83 -0
  16. package/src/adapters/capacitor-llama/index.ts +807 -0
  17. package/src/adapters/capacitor-llama/loader.ts +109 -0
  18. package/src/adapters/capacitor-llama/structured-output.ts +165 -0
  19. package/src/adapters/capacitor-llama/text-streaming.ts +227 -0
  20. package/src/adapters/capacitor-llama/types.ts +374 -0
  21. package/src/backends/apple-foundation.ts +127 -0
  22. package/src/index.d.ts +7 -0
  23. package/src/index.d.ts.map +1 -0
  24. package/src/index.ts +54 -0
  25. package/src/local-inference-routes.d.ts +38 -0
  26. package/src/local-inference-routes.d.ts.map +1 -0
  27. package/src/local-inference-routes.test.ts +344 -0
  28. package/src/local-inference-routes.ts +1543 -0
  29. package/src/provider.d.ts +21 -0
  30. package/src/provider.d.ts.map +1 -0
  31. package/src/provider.ts +1171 -0
  32. package/src/routes/compat-helpers.d.ts +18 -0
  33. package/src/routes/compat-helpers.d.ts.map +1 -0
  34. package/src/routes/compat-helpers.ts +274 -0
  35. package/src/routes/family-member-route.d.ts +62 -0
  36. package/src/routes/family-member-route.d.ts.map +1 -0
  37. package/src/routes/family-member-route.ts +353 -0
  38. package/src/routes/index.d.ts +19 -0
  39. package/src/routes/index.d.ts.map +1 -0
  40. package/src/routes/index.ts +60 -0
  41. package/src/routes/live-diarization-route.d.ts +26 -0
  42. package/src/routes/live-diarization-route.d.ts.map +1 -0
  43. package/src/routes/live-diarization-route.test.ts +213 -0
  44. package/src/routes/live-diarization-route.ts +122 -0
  45. package/src/routes/local-inference-asr-route.d.ts +4 -0
  46. package/src/routes/local-inference-asr-route.d.ts.map +1 -0
  47. package/src/routes/local-inference-asr-route.test.ts +190 -0
  48. package/src/routes/local-inference-asr-route.ts +213 -0
  49. package/src/routes/local-inference-compat-routes.d.ts +16 -0
  50. package/src/routes/local-inference-compat-routes.d.ts.map +1 -0
  51. package/src/routes/local-inference-compat-routes.test.ts +423 -0
  52. package/src/routes/local-inference-compat-routes.ts +782 -0
  53. package/src/routes/local-inference-tts-route.d.ts +7 -0
  54. package/src/routes/local-inference-tts-route.d.ts.map +1 -0
  55. package/src/routes/local-inference-tts-route.test.ts +179 -0
  56. package/src/routes/local-inference-tts-route.ts +230 -0
  57. package/src/routes/voice-first-run-routes.d.ts +62 -0
  58. package/src/routes/voice-first-run-routes.d.ts.map +1 -0
  59. package/src/routes/voice-first-run-routes.ts +524 -0
  60. package/src/routes/voice-models-routes.d.ts +62 -0
  61. package/src/routes/voice-models-routes.d.ts.map +1 -0
  62. package/src/routes/voice-models-routes.ts +554 -0
  63. package/src/routes/voice-profile-plugin-routes.d.ts +19 -0
  64. package/src/routes/voice-profile-plugin-routes.d.ts.map +1 -0
  65. package/src/routes/voice-profile-plugin-routes.ts +138 -0
  66. package/src/routes/voice-profiles-management-routes.d.ts +52 -0
  67. package/src/routes/voice-profiles-management-routes.d.ts.map +1 -0
  68. package/src/routes/voice-profiles-management-routes.ts +476 -0
  69. package/src/routes/voice-speaker-profile-routes.d.ts +57 -0
  70. package/src/routes/voice-speaker-profile-routes.d.ts.map +1 -0
  71. package/src/routes/voice-speaker-profile-routes.ts +199 -0
  72. package/src/runtime/aosp-llama-loader-selection.test.ts +80 -0
  73. package/src/runtime/capacitor-llama.d.ts +25 -0
  74. package/src/runtime/embedding-manager-support.d.ts +77 -0
  75. package/src/runtime/embedding-manager-support.d.ts.map +1 -0
  76. package/src/runtime/embedding-manager-support.ts +497 -0
  77. package/src/runtime/embedding-presets.d.ts +16 -0
  78. package/src/runtime/embedding-presets.d.ts.map +1 -0
  79. package/src/runtime/embedding-presets.ts +81 -0
  80. package/src/runtime/embedding-warmup-policy.d.ts +14 -0
  81. package/src/runtime/embedding-warmup-policy.d.ts.map +1 -0
  82. package/src/runtime/embedding-warmup-policy.test.ts +53 -0
  83. package/src/runtime/embedding-warmup-policy.ts +48 -0
  84. package/src/runtime/ensure-local-inference-handler.d.ts +53 -0
  85. package/src/runtime/ensure-local-inference-handler.d.ts.map +1 -0
  86. package/src/runtime/ensure-local-inference-handler.test.ts +528 -0
  87. package/src/runtime/ensure-local-inference-handler.ts +1398 -0
  88. package/src/runtime/index.d.ts +14 -0
  89. package/src/runtime/index.d.ts.map +1 -0
  90. package/src/runtime/index.ts +27 -0
  91. package/src/runtime/mobile-local-inference-gate.d.ts +31 -0
  92. package/src/runtime/mobile-local-inference-gate.d.ts.map +1 -0
  93. package/src/runtime/mobile-local-inference-gate.test.ts +69 -0
  94. package/src/runtime/mobile-local-inference-gate.ts +44 -0
  95. package/src/runtime/voice-entity-binding.d.ts +103 -0
  96. package/src/runtime/voice-entity-binding.d.ts.map +1 -0
  97. package/src/runtime/voice-entity-binding.transcript.test.ts +69 -0
  98. package/src/runtime/voice-entity-binding.ts +328 -0
  99. package/src/services/README.md +71 -0
  100. package/src/services/__tests__/backend-selector.test.ts +101 -0
  101. package/src/services/__tests__/checkpoint-manager.test.ts +376 -0
  102. package/src/services/__tests__/gpu-autotune.test.ts +400 -0
  103. package/src/services/__tests__/llm-streaming-binding.test.ts +85 -0
  104. package/src/services/__tests__/planner-grammar.test.ts +372 -0
  105. package/src/services/__tests__/runtime-target.test.ts +176 -0
  106. package/src/services/active-model-switch-rollback.test.ts +183 -0
  107. package/src/services/active-model.d.ts +282 -0
  108. package/src/services/active-model.d.ts.map +1 -0
  109. package/src/services/active-model.ts +1213 -0
  110. package/src/services/asr/errors.d.ts +21 -0
  111. package/src/services/asr/errors.d.ts.map +1 -0
  112. package/src/services/asr/errors.ts +50 -0
  113. package/src/services/asr/hash.d.ts +28 -0
  114. package/src/services/asr/hash.d.ts.map +1 -0
  115. package/src/services/asr/hash.ts +49 -0
  116. package/src/services/asr/index.d.ts +76 -0
  117. package/src/services/asr/index.d.ts.map +1 -0
  118. package/src/services/asr/index.ts +178 -0
  119. package/src/services/asr/types.d.ts +91 -0
  120. package/src/services/asr/types.d.ts.map +1 -0
  121. package/src/services/asr/types.ts +95 -0
  122. package/src/services/assignments.d.ts +71 -0
  123. package/src/services/assignments.d.ts.map +1 -0
  124. package/src/services/assignments.test.ts +80 -0
  125. package/src/services/assignments.ts +230 -0
  126. package/src/services/backend-selector.ts +95 -0
  127. package/src/services/backend.d.ts +346 -0
  128. package/src/services/backend.d.ts.map +1 -0
  129. package/src/services/backend.ts +612 -0
  130. package/src/services/bundled-models.d.ts +34 -0
  131. package/src/services/bundled-models.d.ts.map +1 -0
  132. package/src/services/bundled-models.ts +129 -0
  133. package/src/services/cache-bridge.d.ts +206 -0
  134. package/src/services/cache-bridge.d.ts.map +1 -0
  135. package/src/services/cache-bridge.test.ts +516 -0
  136. package/src/services/cache-bridge.ts +423 -0
  137. package/src/services/catalog.d.ts +10 -0
  138. package/src/services/catalog.d.ts.map +1 -0
  139. package/src/services/catalog.test.ts +240 -0
  140. package/src/services/catalog.ts +27 -0
  141. package/src/services/checkpoint-client.d.ts +109 -0
  142. package/src/services/checkpoint-client.d.ts.map +1 -0
  143. package/src/services/checkpoint-client.ts +258 -0
  144. package/src/services/checkpoint-manager.ts +474 -0
  145. package/src/services/cloud-fallback.d.ts +102 -0
  146. package/src/services/cloud-fallback.d.ts.map +1 -0
  147. package/src/services/cloud-fallback.ts +230 -0
  148. package/src/services/conversation-registry.d.ts +142 -0
  149. package/src/services/conversation-registry.d.ts.map +1 -0
  150. package/src/services/conversation-registry.test.ts +235 -0
  151. package/src/services/conversation-registry.ts +264 -0
  152. package/src/services/desktop-fused-ffi-backend-runtime.d.ts +92 -0
  153. package/src/services/desktop-fused-ffi-backend-runtime.d.ts.map +1 -0
  154. package/src/services/desktop-fused-ffi-backend-runtime.ts +333 -0
  155. package/src/services/device-bridge.d.ts +188 -0
  156. package/src/services/device-bridge.d.ts.map +1 -0
  157. package/src/services/device-bridge.ts +1237 -0
  158. package/src/services/device-resource-metrics.d.ts +149 -0
  159. package/src/services/device-resource-metrics.d.ts.map +1 -0
  160. package/src/services/device-resource-metrics.test.ts +98 -0
  161. package/src/services/device-resource-metrics.ts +346 -0
  162. package/src/services/device-tier.d.ts +115 -0
  163. package/src/services/device-tier.d.ts.map +1 -0
  164. package/src/services/device-tier.test.ts +371 -0
  165. package/src/services/device-tier.ts +410 -0
  166. package/src/services/downloader.d.ts +82 -0
  167. package/src/services/downloader.d.ts.map +1 -0
  168. package/src/services/downloader.test.ts +724 -0
  169. package/src/services/downloader.ts +899 -0
  170. package/src/services/engine-direct-bundle.test.ts +58 -0
  171. package/src/services/engine-streaming.test.ts +80 -0
  172. package/src/services/engine.d.ts +534 -0
  173. package/src/services/engine.d.ts.map +1 -0
  174. package/src/services/engine.ts +1891 -0
  175. package/src/services/ensure-local-artifacts.integration.test.ts +273 -0
  176. package/src/services/ensure-local-artifacts.test.ts +368 -0
  177. package/src/services/ensure-local-artifacts.ts +351 -0
  178. package/src/services/external-scanner.d.ts +17 -0
  179. package/src/services/external-scanner.d.ts.map +1 -0
  180. package/src/services/external-scanner.ts +312 -0
  181. package/src/services/ffi-llm-mock.ts +354 -0
  182. package/src/services/ffi-llm-streaming-abi.ts +442 -0
  183. package/src/services/ffi-streaming-backend.d.ts +180 -0
  184. package/src/services/ffi-streaming-backend.d.ts.map +1 -0
  185. package/src/services/ffi-streaming-backend.ts +382 -0
  186. package/src/services/ffi-streaming-runner.d.ts +122 -0
  187. package/src/services/ffi-streaming-runner.d.ts.map +1 -0
  188. package/src/services/ffi-streaming-runner.test.ts +60 -0
  189. package/src/services/ffi-streaming-runner.ts +354 -0
  190. package/src/services/ffi-unload-ordering.test.ts +162 -0
  191. package/src/services/gpu-autotune.ts +534 -0
  192. package/src/services/gpu-detect.ts +139 -0
  193. package/src/services/handler-registry.d.ts +72 -0
  194. package/src/services/handler-registry.d.ts.map +1 -0
  195. package/src/services/handler-registry.ts +240 -0
  196. package/src/services/hardware.d.ts +63 -0
  197. package/src/services/hardware.d.ts.map +1 -0
  198. package/src/services/hardware.test.ts +183 -0
  199. package/src/services/hardware.ts +404 -0
  200. package/src/services/hf-search.d.ts +26 -0
  201. package/src/services/hf-search.d.ts.map +1 -0
  202. package/src/services/hf-search.test.ts +69 -0
  203. package/src/services/hf-search.ts +420 -0
  204. package/src/services/image-description-runtime.d.ts +14 -0
  205. package/src/services/image-description-runtime.d.ts.map +1 -0
  206. package/src/services/image-description-runtime.test.ts +61 -0
  207. package/src/services/image-description-runtime.ts +118 -0
  208. package/src/services/imagegen/aosp-unavailable.d.ts +134 -0
  209. package/src/services/imagegen/aosp-unavailable.d.ts.map +1 -0
  210. package/src/services/imagegen/aosp-unavailable.ts +229 -0
  211. package/src/services/imagegen/backend-selector.d.ts +118 -0
  212. package/src/services/imagegen/backend-selector.d.ts.map +1 -0
  213. package/src/services/imagegen/backend-selector.ts +281 -0
  214. package/src/services/imagegen/coreml-unavailable.d.ts +105 -0
  215. package/src/services/imagegen/coreml-unavailable.d.ts.map +1 -0
  216. package/src/services/imagegen/coreml-unavailable.ts +237 -0
  217. package/src/services/imagegen/errors.d.ts +16 -0
  218. package/src/services/imagegen/errors.d.ts.map +1 -0
  219. package/src/services/imagegen/errors.ts +40 -0
  220. package/src/services/imagegen/index.d.ts +58 -0
  221. package/src/services/imagegen/index.d.ts.map +1 -0
  222. package/src/services/imagegen/index.ts +144 -0
  223. package/src/services/imagegen/mflux.d.ts +74 -0
  224. package/src/services/imagegen/mflux.d.ts.map +1 -0
  225. package/src/services/imagegen/mflux.ts +313 -0
  226. package/src/services/imagegen/sd-cpp.d.ts +180 -0
  227. package/src/services/imagegen/sd-cpp.d.ts.map +1 -0
  228. package/src/services/imagegen/sd-cpp.ts +718 -0
  229. package/src/services/imagegen/tensorrt-unavailable.d.ts +83 -0
  230. package/src/services/imagegen/tensorrt-unavailable.d.ts.map +1 -0
  231. package/src/services/imagegen/tensorrt-unavailable.ts +295 -0
  232. package/src/services/imagegen/types.d.ts +181 -0
  233. package/src/services/imagegen/types.d.ts.map +1 -0
  234. package/src/services/imagegen/types.ts +193 -0
  235. package/src/services/index.d.ts +30 -0
  236. package/src/services/index.d.ts.map +1 -0
  237. package/src/services/index.ts +225 -0
  238. package/src/services/inference-capabilities.d.ts +132 -0
  239. package/src/services/inference-capabilities.d.ts.map +1 -0
  240. package/src/services/inference-capabilities.test.ts +75 -0
  241. package/src/services/inference-capabilities.ts +204 -0
  242. package/src/services/inference-telemetry.d.ts +59 -0
  243. package/src/services/inference-telemetry.d.ts.map +1 -0
  244. package/src/services/inference-telemetry.ts +143 -0
  245. package/src/services/ios-llama-streaming.ts +248 -0
  246. package/src/services/kv-spill.d.ts +189 -0
  247. package/src/services/kv-spill.d.ts.map +1 -0
  248. package/src/services/kv-spill.test.ts +222 -0
  249. package/src/services/kv-spill.ts +356 -0
  250. package/src/services/latency-trace.d.ts +346 -0
  251. package/src/services/latency-trace.d.ts.map +1 -0
  252. package/src/services/latency-trace.test.ts +266 -0
  253. package/src/services/latency-trace.ts +844 -0
  254. package/src/services/llama-server-metrics.ts +304 -0
  255. package/src/services/llm-streaming-binding.d.ts +96 -0
  256. package/src/services/llm-streaming-binding.d.ts.map +1 -0
  257. package/src/services/llm-streaming-binding.ts +136 -0
  258. package/src/services/load-args.d.ts +82 -0
  259. package/src/services/load-args.d.ts.map +1 -0
  260. package/src/services/load-args.ts +81 -0
  261. package/src/services/manifest/eliza-1.manifest.v1.json +708 -0
  262. package/src/services/manifest/index.d.ts +4 -0
  263. package/src/services/manifest/index.d.ts.map +1 -0
  264. package/src/services/manifest/index.ts +66 -0
  265. package/src/services/manifest/manifest.test.ts +693 -0
  266. package/src/services/manifest/schema.d.ts +715 -0
  267. package/src/services/manifest/schema.d.ts.map +1 -0
  268. package/src/services/manifest/schema.ts +655 -0
  269. package/src/services/manifest/types.d.ts +30 -0
  270. package/src/services/manifest/types.d.ts.map +1 -0
  271. package/src/services/manifest/types.ts +55 -0
  272. package/src/services/manifest/validator.d.ts +66 -0
  273. package/src/services/manifest/validator.d.ts.map +1 -0
  274. package/src/services/manifest/validator.ts +569 -0
  275. package/src/services/memory-arbiter.d.ts +343 -0
  276. package/src/services/memory-arbiter.d.ts.map +1 -0
  277. package/src/services/memory-arbiter.test.ts +419 -0
  278. package/src/services/memory-arbiter.ts +1000 -0
  279. package/src/services/memory-monitor.d.ts +119 -0
  280. package/src/services/memory-monitor.d.ts.map +1 -0
  281. package/src/services/memory-monitor.test.ts +208 -0
  282. package/src/services/memory-monitor.ts +296 -0
  283. package/src/services/memory-pressure.d.ts +127 -0
  284. package/src/services/memory-pressure.d.ts.map +1 -0
  285. package/src/services/memory-pressure.ts +413 -0
  286. package/src/services/mtp-doctor.d.ts +13 -0
  287. package/src/services/mtp-doctor.d.ts.map +1 -0
  288. package/src/services/mtp-doctor.ts +78 -0
  289. package/src/services/network-policy.d.ts +127 -0
  290. package/src/services/network-policy.d.ts.map +1 -0
  291. package/src/services/network-policy.ts +346 -0
  292. package/src/services/paths.d.ts +6 -0
  293. package/src/services/paths.d.ts.map +1 -0
  294. package/src/services/paths.ts +25 -0
  295. package/src/services/planner-skeleton.d.ts +124 -0
  296. package/src/services/planner-skeleton.d.ts.map +1 -0
  297. package/src/services/planner-skeleton.ts +175 -0
  298. package/src/services/providers.d.ts +38 -0
  299. package/src/services/providers.d.ts.map +1 -0
  300. package/src/services/providers.ts +507 -0
  301. package/src/services/ram-budget-cache.test.ts +163 -0
  302. package/src/services/ram-budget.d.ts +110 -0
  303. package/src/services/ram-budget.d.ts.map +1 -0
  304. package/src/services/ram-budget.ts +0 -0
  305. package/src/services/readiness.d.ts +9 -0
  306. package/src/services/readiness.d.ts.map +1 -0
  307. package/src/services/readiness.test.ts +87 -0
  308. package/src/services/readiness.ts +238 -0
  309. package/src/services/recommendation.d.ts +111 -0
  310. package/src/services/recommendation.d.ts.map +1 -0
  311. package/src/services/recommendation.ts +672 -0
  312. package/src/services/registry.d.ts +35 -0
  313. package/src/services/registry.d.ts.map +1 -0
  314. package/src/services/registry.ts +151 -0
  315. package/src/services/router-handler.d.ts +92 -0
  316. package/src/services/router-handler.d.ts.map +1 -0
  317. package/src/services/router-handler.test.ts +45 -0
  318. package/src/services/router-handler.ts +376 -0
  319. package/src/services/routing-policy.d.ts +55 -0
  320. package/src/services/routing-policy.d.ts.map +1 -0
  321. package/src/services/routing-policy.ts +228 -0
  322. package/src/services/routing-preferences.d.ts +8 -0
  323. package/src/services/routing-preferences.d.ts.map +1 -0
  324. package/src/services/routing-preferences.ts +15 -0
  325. package/src/services/runtime-target.d.ts +98 -0
  326. package/src/services/runtime-target.d.ts.map +1 -0
  327. package/src/services/runtime-target.ts +154 -0
  328. package/src/services/service.d.ts +128 -0
  329. package/src/services/service.d.ts.map +1 -0
  330. package/src/services/service.test.ts +223 -0
  331. package/src/services/service.ts +735 -0
  332. package/src/services/session-pool.d.ts +72 -0
  333. package/src/services/session-pool.d.ts.map +1 -0
  334. package/src/services/session-pool.ts +153 -0
  335. package/src/services/structured-output/deterministic-repair.d.ts +23 -0
  336. package/src/services/structured-output/deterministic-repair.d.ts.map +1 -0
  337. package/src/services/structured-output/deterministic-repair.test.ts +169 -0
  338. package/src/services/structured-output/deterministic-repair.ts +443 -0
  339. package/src/services/structured-output/index.ts +4 -0
  340. package/src/services/structured-output.d.ts +311 -0
  341. package/src/services/structured-output.d.ts.map +1 -0
  342. package/src/services/structured-output.test.ts +483 -0
  343. package/src/services/structured-output.ts +712 -0
  344. package/src/services/transcription-priority.test.ts +211 -0
  345. package/src/services/tts/errors.ts +46 -0
  346. package/src/services/tts/index.ts +214 -0
  347. package/src/services/tts/tts-audio-cache.ts +235 -0
  348. package/src/services/tts/types.ts +157 -0
  349. package/src/services/types.d.ts +19 -0
  350. package/src/services/types.d.ts.map +1 -0
  351. package/src/services/types.ts +55 -0
  352. package/src/services/verify-on-device.d.ts +34 -0
  353. package/src/services/verify-on-device.d.ts.map +1 -0
  354. package/src/services/verify-on-device.test.ts +87 -0
  355. package/src/services/verify-on-device.ts +127 -0
  356. package/src/services/verify.d.ts +8 -0
  357. package/src/services/verify.d.ts.map +1 -0
  358. package/src/services/verify.ts +13 -0
  359. package/src/services/vision/aosp-unavailable.d.ts +115 -0
  360. package/src/services/vision/aosp-unavailable.d.ts.map +1 -0
  361. package/src/services/vision/aosp-unavailable.ts +163 -0
  362. package/src/services/vision/capacitor-llama.d.ts +99 -0
  363. package/src/services/vision/capacitor-llama.d.ts.map +1 -0
  364. package/src/services/vision/capacitor-llama.ts +255 -0
  365. package/src/services/vision/cloud-fallback.d.ts +47 -0
  366. package/src/services/vision/cloud-fallback.d.ts.map +1 -0
  367. package/src/services/vision/cloud-fallback.test.ts +243 -0
  368. package/src/services/vision/cloud-fallback.ts +268 -0
  369. package/src/services/vision/fallback-chain.test.ts +86 -0
  370. package/src/services/vision/hash.d.ts +71 -0
  371. package/src/services/vision/hash.d.ts.map +1 -0
  372. package/src/services/vision/hash.ts +157 -0
  373. package/src/services/vision/index.d.ts +95 -0
  374. package/src/services/vision/index.d.ts.map +1 -0
  375. package/src/services/vision/index.ts +251 -0
  376. package/src/services/vision/llama-server.d.ts +73 -0
  377. package/src/services/vision/llama-server.d.ts.map +1 -0
  378. package/src/services/vision/llama-server.ts +177 -0
  379. package/src/services/vision/types.d.ts +153 -0
  380. package/src/services/vision/types.d.ts.map +1 -0
  381. package/src/services/vision/types.ts +154 -0
  382. package/src/services/vision/vast-fallback.d.ts +18 -0
  383. package/src/services/vision/vast-fallback.d.ts.map +1 -0
  384. package/src/services/vision/vast-fallback.ts +127 -0
  385. package/src/services/vision-embedding-cache.d.ts +98 -0
  386. package/src/services/vision-embedding-cache.d.ts.map +1 -0
  387. package/src/services/vision-embedding-cache.ts +189 -0
  388. package/src/services/voice/VOICE_WORKBENCH.md +88 -0
  389. package/src/services/voice/__test-helpers__/fake-ffi.ts +92 -0
  390. package/src/services/voice/__test-helpers__/synthetic-speech.ts +124 -0
  391. package/src/services/voice/__tests__/checkpoint-manager.test.ts +241 -0
  392. package/src/services/voice/__tests__/checkpoint-policy.test.ts +270 -0
  393. package/src/services/voice/__tests__/eager-context-builder.test.ts +257 -0
  394. package/src/services/voice/__tests__/eliza1-eot-scorer.test.ts +288 -0
  395. package/src/services/voice/__tests__/eot-classifier.test.ts +431 -0
  396. package/src/services/voice/__tests__/optimistic-rollback.test.ts +312 -0
  397. package/src/services/voice/__tests__/prefill-client.test.ts +266 -0
  398. package/src/services/voice/__tests__/prefix-preserving-queue.test.ts +208 -0
  399. package/src/services/voice/__tests__/streaming-asr.test.ts +450 -0
  400. package/src/services/voice/__tests__/streaming-transcriber.test.ts +339 -0
  401. package/src/services/voice/__tests__/turn-detector-resolver.test.ts +197 -0
  402. package/src/services/voice/__tests__/voice-state-machine-prefill.test.ts +275 -0
  403. package/src/services/voice/__tests__/voice-state-machine.test.ts +354 -0
  404. package/src/services/voice/audio-frame-consumer.d.ts +212 -0
  405. package/src/services/voice/audio-frame-consumer.d.ts.map +1 -0
  406. package/src/services/voice/audio-frame-consumer.test.ts +343 -0
  407. package/src/services/voice/audio-frame-consumer.ts +491 -0
  408. package/src/services/voice/barge-in.d.ts +112 -0
  409. package/src/services/voice/barge-in.d.ts.map +1 -0
  410. package/src/services/voice/barge-in.test.ts +244 -0
  411. package/src/services/voice/barge-in.ts +336 -0
  412. package/src/services/voice/cancellation-coordinator.d.ts +127 -0
  413. package/src/services/voice/cancellation-coordinator.d.ts.map +1 -0
  414. package/src/services/voice/cancellation-coordinator.test.ts +196 -0
  415. package/src/services/voice/cancellation-coordinator.ts +269 -0
  416. package/src/services/voice/checkpoint-manager.d.ts +199 -0
  417. package/src/services/voice/checkpoint-manager.d.ts.map +1 -0
  418. package/src/services/voice/checkpoint-manager.ts +401 -0
  419. package/src/services/voice/checkpoint-policy.ts +336 -0
  420. package/src/services/voice/composite-eot-classifier.test.ts +59 -0
  421. package/src/services/voice/e2e-harness.test.ts +182 -0
  422. package/src/services/voice/e2e-harness.ts +743 -0
  423. package/src/services/voice/eager-context-builder.d.ts +170 -0
  424. package/src/services/voice/eager-context-builder.d.ts.map +1 -0
  425. package/src/services/voice/eager-context-builder.ts +262 -0
  426. package/src/services/voice/eliza1-eot-scorer.d.ts +124 -0
  427. package/src/services/voice/eliza1-eot-scorer.d.ts.map +1 -0
  428. package/src/services/voice/eliza1-eot-scorer.ts +242 -0
  429. package/src/services/voice/embedding-server.ts +200 -0
  430. package/src/services/voice/embedding.d.ts +133 -0
  431. package/src/services/voice/embedding.d.ts.map +1 -0
  432. package/src/services/voice/embedding.test.ts +148 -0
  433. package/src/services/voice/embedding.ts +244 -0
  434. package/src/services/voice/emotion-attribution.d.ts +68 -0
  435. package/src/services/voice/emotion-attribution.d.ts.map +1 -0
  436. package/src/services/voice/emotion-attribution.test.ts +129 -0
  437. package/src/services/voice/emotion-attribution.ts +361 -0
  438. package/src/services/voice/engine-bridge-cancellation.test.ts +422 -0
  439. package/src/services/voice/engine-bridge.d.ts +746 -0
  440. package/src/services/voice/engine-bridge.d.ts.map +1 -0
  441. package/src/services/voice/engine-bridge.test.ts +384 -0
  442. package/src/services/voice/engine-bridge.ts +2226 -0
  443. package/src/services/voice/eot-classifier-ggml.d.ts +179 -0
  444. package/src/services/voice/eot-classifier-ggml.d.ts.map +1 -0
  445. package/src/services/voice/eot-classifier-ggml.ts +566 -0
  446. package/src/services/voice/eot-classifier.d.ts +214 -0
  447. package/src/services/voice/eot-classifier.d.ts.map +1 -0
  448. package/src/services/voice/eot-classifier.ts +533 -0
  449. package/src/services/voice/errors.d.ts +20 -0
  450. package/src/services/voice/errors.d.ts.map +1 -0
  451. package/src/services/voice/errors.ts +32 -0
  452. package/src/services/voice/expressive-tags.d.ts +158 -0
  453. package/src/services/voice/expressive-tags.d.ts.map +1 -0
  454. package/src/services/voice/expressive-tags.ts +405 -0
  455. package/src/services/voice/ffi-bindings.d.ts +636 -0
  456. package/src/services/voice/ffi-bindings.d.ts.map +1 -0
  457. package/src/services/voice/ffi-bindings.test.ts +671 -0
  458. package/src/services/voice/ffi-bindings.ts +3050 -0
  459. package/src/services/voice/first-line-cache.d.ts +181 -0
  460. package/src/services/voice/first-line-cache.d.ts.map +1 -0
  461. package/src/services/voice/first-line-cache.ts +725 -0
  462. package/src/services/voice/fused-eot-scorer.d.ts +51 -0
  463. package/src/services/voice/fused-eot-scorer.d.ts.map +1 -0
  464. package/src/services/voice/fused-eot-scorer.ts +135 -0
  465. package/src/services/voice/index.d.ts +91 -0
  466. package/src/services/voice/index.d.ts.map +1 -0
  467. package/src/services/voice/index.ts +481 -0
  468. package/src/services/voice/kokoro/__tests__/kokoro-backend.test.ts +151 -0
  469. package/src/services/voice/kokoro/__tests__/kokoro-engine-bridge.real.test.ts +151 -0
  470. package/src/services/voice/kokoro/__tests__/kokoro-engine-bridge.test.ts +60 -0
  471. package/src/services/voice/kokoro/__tests__/kokoro-engine-discovery.test.ts +277 -0
  472. package/src/services/voice/kokoro/__tests__/kokoro-ffi-runtime.test.ts +235 -0
  473. package/src/services/voice/kokoro/__tests__/kokoro-runtime.test.ts +95 -0
  474. package/src/services/voice/kokoro/__tests__/phonemizer.test.ts +53 -0
  475. package/src/services/voice/kokoro/__tests__/runtime-selection.test.ts +231 -0
  476. package/src/services/voice/kokoro/__tests__/voices.test.ts +57 -0
  477. package/src/services/voice/kokoro/index.ts +79 -0
  478. package/src/services/voice/kokoro/kokoro-backend.d.ts +72 -0
  479. package/src/services/voice/kokoro/kokoro-backend.d.ts.map +1 -0
  480. package/src/services/voice/kokoro/kokoro-backend.ts +207 -0
  481. package/src/services/voice/kokoro/kokoro-engine-discovery.d.ts +58 -0
  482. package/src/services/voice/kokoro/kokoro-engine-discovery.d.ts.map +1 -0
  483. package/src/services/voice/kokoro/kokoro-engine-discovery.ts +177 -0
  484. package/src/services/voice/kokoro/kokoro-ffi-runtime.d.ts +75 -0
  485. package/src/services/voice/kokoro/kokoro-ffi-runtime.d.ts.map +1 -0
  486. package/src/services/voice/kokoro/kokoro-ffi-runtime.ts +233 -0
  487. package/src/services/voice/kokoro/kokoro-runtime.d.ts +100 -0
  488. package/src/services/voice/kokoro/kokoro-runtime.d.ts.map +1 -0
  489. package/src/services/voice/kokoro/kokoro-runtime.ts +170 -0
  490. package/src/services/voice/kokoro/phoneme-stream.ts +123 -0
  491. package/src/services/voice/kokoro/phonemizer.d.ts +50 -0
  492. package/src/services/voice/kokoro/phonemizer.d.ts.map +1 -0
  493. package/src/services/voice/kokoro/phonemizer.ts +344 -0
  494. package/src/services/voice/kokoro/pick-runtime.d.ts +61 -0
  495. package/src/services/voice/kokoro/pick-runtime.d.ts.map +1 -0
  496. package/src/services/voice/kokoro/pick-runtime.test.ts +91 -0
  497. package/src/services/voice/kokoro/pick-runtime.ts +130 -0
  498. package/src/services/voice/kokoro/runtime-selection.d.ts +92 -0
  499. package/src/services/voice/kokoro/runtime-selection.d.ts.map +1 -0
  500. package/src/services/voice/kokoro/runtime-selection.ts +237 -0
  501. package/src/services/voice/kokoro/types.d.ts +82 -0
  502. package/src/services/voice/kokoro/types.d.ts.map +1 -0
  503. package/src/services/voice/kokoro/types.ts +95 -0
  504. package/src/services/voice/kokoro/voice-presets.d.ts +23 -0
  505. package/src/services/voice/kokoro/voice-presets.d.ts.map +1 -0
  506. package/src/services/voice/kokoro/voice-presets.ts +129 -0
  507. package/src/services/voice/kokoro/voices.d.ts +30 -0
  508. package/src/services/voice/kokoro/voices.d.ts.map +1 -0
  509. package/src/services/voice/kokoro/voices.ts +64 -0
  510. package/src/services/voice/lifecycle.d.ts +135 -0
  511. package/src/services/voice/lifecycle.d.ts.map +1 -0
  512. package/src/services/voice/lifecycle.test.ts +315 -0
  513. package/src/services/voice/lifecycle.ts +301 -0
  514. package/src/services/voice/live-diarization-session.d.ts +96 -0
  515. package/src/services/voice/live-diarization-session.d.ts.map +1 -0
  516. package/src/services/voice/live-diarization-session.ts +289 -0
  517. package/src/services/voice/mic-source.d.ts +136 -0
  518. package/src/services/voice/mic-source.d.ts.map +1 -0
  519. package/src/services/voice/mic-source.test.ts +210 -0
  520. package/src/services/voice/mic-source.ts +503 -0
  521. package/src/services/voice/optimistic-policy.d.ts +109 -0
  522. package/src/services/voice/optimistic-policy.d.ts.map +1 -0
  523. package/src/services/voice/optimistic-policy.test.ts +101 -0
  524. package/src/services/voice/optimistic-policy.ts +192 -0
  525. package/src/services/voice/optimistic-rollback.ts +343 -0
  526. package/src/services/voice/partial-stabilizer.d.ts +73 -0
  527. package/src/services/voice/partial-stabilizer.d.ts.map +1 -0
  528. package/src/services/voice/partial-stabilizer.test.ts +68 -0
  529. package/src/services/voice/partial-stabilizer.ts +140 -0
  530. package/src/services/voice/phoneme-tokenizer.d.ts +49 -0
  531. package/src/services/voice/phoneme-tokenizer.d.ts.map +1 -0
  532. package/src/services/voice/phoneme-tokenizer.ts +158 -0
  533. package/src/services/voice/phrase-cache.d.ts +76 -0
  534. package/src/services/voice/phrase-cache.d.ts.map +1 -0
  535. package/src/services/voice/phrase-cache.test.ts +242 -0
  536. package/src/services/voice/phrase-cache.ts +186 -0
  537. package/src/services/voice/phrase-chunker.d.ts +62 -0
  538. package/src/services/voice/phrase-chunker.d.ts.map +1 -0
  539. package/src/services/voice/phrase-chunker.test.ts +239 -0
  540. package/src/services/voice/phrase-chunker.ts +281 -0
  541. package/src/services/voice/pipeline-impls.d.ts +151 -0
  542. package/src/services/voice/pipeline-impls.d.ts.map +1 -0
  543. package/src/services/voice/pipeline-impls.l6.test.ts +110 -0
  544. package/src/services/voice/pipeline-impls.test.ts +292 -0
  545. package/src/services/voice/pipeline-impls.ts +315 -0
  546. package/src/services/voice/pipeline.d.ts +216 -0
  547. package/src/services/voice/pipeline.d.ts.map +1 -0
  548. package/src/services/voice/pipeline.ts +505 -0
  549. package/src/services/voice/prefill-client.d.ts +123 -0
  550. package/src/services/voice/prefill-client.d.ts.map +1 -0
  551. package/src/services/voice/prefill-client.ts +316 -0
  552. package/src/services/voice/prefix-preserving-queue.d.ts +113 -0
  553. package/src/services/voice/prefix-preserving-queue.d.ts.map +1 -0
  554. package/src/services/voice/prefix-preserving-queue.ts +162 -0
  555. package/src/services/voice/profile-store.d.ts +248 -0
  556. package/src/services/voice/profile-store.d.ts.map +1 -0
  557. package/src/services/voice/profile-store.ts +887 -0
  558. package/src/services/voice/ring-buffer.d.ts +40 -0
  559. package/src/services/voice/ring-buffer.d.ts.map +1 -0
  560. package/src/services/voice/ring-buffer.ts +105 -0
  561. package/src/services/voice/rollback-queue.d.ts +24 -0
  562. package/src/services/voice/rollback-queue.d.ts.map +1 -0
  563. package/src/services/voice/rollback-queue.ts +74 -0
  564. package/src/services/voice/samantha-preset-placeholder.d.ts +67 -0
  565. package/src/services/voice/samantha-preset-placeholder.d.ts.map +1 -0
  566. package/src/services/voice/samantha-preset-placeholder.test.ts +97 -0
  567. package/src/services/voice/samantha-preset-placeholder.ts +148 -0
  568. package/src/services/voice/samantha-preset-regenerator.d.ts +87 -0
  569. package/src/services/voice/samantha-preset-regenerator.d.ts.map +1 -0
  570. package/src/services/voice/samantha-preset-regenerator.ts +393 -0
  571. package/src/services/voice/scheduler.d.ts +146 -0
  572. package/src/services/voice/scheduler.d.ts.map +1 -0
  573. package/src/services/voice/scheduler.t2.test.ts +141 -0
  574. package/src/services/voice/scheduler.ts +927 -0
  575. package/src/services/voice/shared-resources.d.ts +190 -0
  576. package/src/services/voice/shared-resources.d.ts.map +1 -0
  577. package/src/services/voice/shared-resources.ts +320 -0
  578. package/src/services/voice/speaker/attribution-pipeline.d.ts +74 -0
  579. package/src/services/voice/speaker/attribution-pipeline.d.ts.map +1 -0
  580. package/src/services/voice/speaker/attribution-pipeline.ts +386 -0
  581. package/src/services/voice/speaker/diarizer-fused.d.ts +59 -0
  582. package/src/services/voice/speaker/diarizer-fused.d.ts.map +1 -0
  583. package/src/services/voice/speaker/diarizer-fused.real.test.ts +100 -0
  584. package/src/services/voice/speaker/diarizer-fused.ts +154 -0
  585. package/src/services/voice/speaker/diarizer.d.ts +75 -0
  586. package/src/services/voice/speaker/diarizer.d.ts.map +1 -0
  587. package/src/services/voice/speaker/diarizer.ts +218 -0
  588. package/src/services/voice/speaker/encoder-fused.d.ts +60 -0
  589. package/src/services/voice/speaker/encoder-fused.d.ts.map +1 -0
  590. package/src/services/voice/speaker/encoder-fused.real.test.ts +113 -0
  591. package/src/services/voice/speaker/encoder-fused.ts +138 -0
  592. package/src/services/voice/speaker/encoder-ggml.d.ts +33 -0
  593. package/src/services/voice/speaker/encoder-ggml.d.ts.map +1 -0
  594. package/src/services/voice/speaker/encoder-ggml.ts +79 -0
  595. package/src/services/voice/speaker/encoder.d.ts +37 -0
  596. package/src/services/voice/speaker/encoder.d.ts.map +1 -0
  597. package/src/services/voice/speaker/encoder.ts +105 -0
  598. package/src/services/voice/speaker-imprint.d.ts +83 -0
  599. package/src/services/voice/speaker-imprint.d.ts.map +1 -0
  600. package/src/services/voice/speaker-imprint.test.ts +185 -0
  601. package/src/services/voice/speaker-imprint.ts +312 -0
  602. package/src/services/voice/speaker-preset-cache.d.ts +77 -0
  603. package/src/services/voice/speaker-preset-cache.d.ts.map +1 -0
  604. package/src/services/voice/speaker-preset-cache.test.ts +154 -0
  605. package/src/services/voice/speaker-preset-cache.ts +195 -0
  606. package/src/services/voice/streaming-asr/streaming-pipeline-adapter.ts +292 -0
  607. package/src/services/voice/system-audio-sink.d.ts +73 -0
  608. package/src/services/voice/system-audio-sink.d.ts.map +1 -0
  609. package/src/services/voice/system-audio-sink.test.ts +29 -0
  610. package/src/services/voice/system-audio-sink.ts +366 -0
  611. package/src/services/voice/transcriber.d.ts +244 -0
  612. package/src/services/voice/transcriber.d.ts.map +1 -0
  613. package/src/services/voice/transcriber.test.ts +392 -0
  614. package/src/services/voice/transcriber.ts +704 -0
  615. package/src/services/voice/turn-controller.d.ts +183 -0
  616. package/src/services/voice/turn-controller.d.ts.map +1 -0
  617. package/src/services/voice/turn-controller.test.ts +575 -0
  618. package/src/services/voice/turn-controller.ts +596 -0
  619. package/src/services/voice/types.d.ts +643 -0
  620. package/src/services/voice/types.d.ts.map +1 -0
  621. package/src/services/voice/types.ts +699 -0
  622. package/src/services/voice/vad.d.ts +282 -0
  623. package/src/services/voice/vad.d.ts.map +1 -0
  624. package/src/services/voice/vad.test.ts +480 -0
  625. package/src/services/voice/vad.ts +827 -0
  626. package/src/services/voice/vad.v1-v4.test.ts +222 -0
  627. package/src/services/voice/voice-budget.d.ts +241 -0
  628. package/src/services/voice/voice-budget.d.ts.map +1 -0
  629. package/src/services/voice/voice-budget.test.ts +420 -0
  630. package/src/services/voice/voice-budget.ts +656 -0
  631. package/src/services/voice/voice-duet.test.ts +375 -0
  632. package/src/services/voice/voice-emotion-classifier.d.ts +95 -0
  633. package/src/services/voice/voice-emotion-classifier.d.ts.map +1 -0
  634. package/src/services/voice/voice-emotion-classifier.test.ts +210 -0
  635. package/src/services/voice/voice-emotion-classifier.ts +273 -0
  636. package/src/services/voice/voice-preset-format.d.ts +158 -0
  637. package/src/services/voice/voice-preset-format.d.ts.map +1 -0
  638. package/src/services/voice/voice-preset-format.ts +700 -0
  639. package/src/services/voice/voice-preset-generator.test.ts +89 -0
  640. package/src/services/voice/voice-profile-artifact.d.ts +116 -0
  641. package/src/services/voice/voice-profile-artifact.d.ts.map +1 -0
  642. package/src/services/voice/voice-profile-artifact.test.ts +138 -0
  643. package/src/services/voice/voice-profile-artifact.ts +518 -0
  644. package/src/services/voice/voice-profile-routes.d.ts +83 -0
  645. package/src/services/voice/voice-profile-routes.d.ts.map +1 -0
  646. package/src/services/voice/voice-profile-routes.test.ts +429 -0
  647. package/src/services/voice/voice-profile-routes.ts +425 -0
  648. package/src/services/voice/voice-scenario.ts +154 -0
  649. package/src/services/voice/voice-settings.d.ts +82 -0
  650. package/src/services/voice/voice-settings.d.ts.map +1 -0
  651. package/src/services/voice/voice-settings.ts +172 -0
  652. package/src/services/voice/voice-state-machine.d.ts +364 -0
  653. package/src/services/voice/voice-state-machine.d.ts.map +1 -0
  654. package/src/services/voice/voice-state-machine.ts +727 -0
  655. package/src/services/voice/voice-workbench-report.test.ts +168 -0
  656. package/src/services/voice/voice-workbench-report.ts +326 -0
  657. package/src/services/voice/voice-workbench.test.ts +158 -0
  658. package/src/services/voice/voice.test.ts +1070 -0
  659. package/src/services/voice/wake-word-ggml.d.ts +101 -0
  660. package/src/services/voice/wake-word-ggml.d.ts.map +1 -0
  661. package/src/services/voice/wake-word-ggml.ts +320 -0
  662. package/src/services/voice/wake-word.d.ts +255 -0
  663. package/src/services/voice/wake-word.d.ts.map +1 -0
  664. package/src/services/voice/wake-word.test.ts +298 -0
  665. package/src/services/voice/wake-word.ts +554 -0
  666. package/src/services/voice/wrap-with-first-line-cache.d.ts +70 -0
  667. package/src/services/voice/wrap-with-first-line-cache.d.ts.map +1 -0
  668. package/src/services/voice/wrap-with-first-line-cache.ts +267 -0
  669. package/src/services/voice-model-updater.d.ts +240 -0
  670. package/src/services/voice-model-updater.d.ts.map +1 -0
  671. package/src/services/voice-model-updater.ts +724 -0
  672. package/src/services/voice-prewarm.d.ts +3 -0
  673. package/src/services/voice-prewarm.d.ts.map +1 -0
  674. package/src/services/voice-prewarm.ts +51 -0
  675. package/dist/index.d.ts +0 -37
  676. package/dist/index.js +0 -1098
@@ -0,0 +1,346 @@
1
+ /**
2
+ * End-to-end voice-loop latency tracing.
3
+ *
4
+ * One `LatencyTrace` per voice turn — a span recorder with named
5
+ * checkpoints from "user makes a sound" to "agent's first audio plays".
6
+ * The checkpoint set is fixed (`VOICE_CHECKPOINTS`) and ordered; each
7
+ * checkpoint is recorded at most once per turn. Missing checkpoints are
8
+ * surfaced as missing-checkpoint state — never synthesized — and derived
9
+ * metrics that depend on a missing checkpoint stay `null` (AGENTS.md §3 / §7:
10
+ * a missing measurement is recorded as missing, not faked).
11
+ *
12
+ * Ownership / lifecycle:
13
+ * - The turn controller (`voice/turn-controller.ts`, W9) is the natural
14
+ * owner of the per-turn tracer: it calls `tracer.beginTurn({...})` when
15
+ * a turn opens and `tracer.endTurn(turnId)` when it finalizes/aborts.
16
+ * Until that lands, callers can use the module-level
17
+ * `voiceLatencyTracer` singleton + the `markVoiceLatency()` helper —
18
+ * the singleton lazily opens a turn keyed by `roomId` on first mark.
19
+ * - Components that produce a checkpoint either (a) hold a `tracer` and
20
+ * call `tracer.mark(turnId, checkpoint)`, or (b) call the context-free
21
+ * `markVoiceLatency(roomId, checkpoint)` helper. `bindVadDetector()`
22
+ * bridges a `VadEventSource` onto the tracer without touching `vad.ts`.
23
+ *
24
+ * Hook points (where each checkpoint is meant to be recorded):
25
+ * - `peer-utterance-end` — (DUET ONLY) the producing agent's
26
+ * scheduler drained its last PCM chunk into
27
+ * the cross ring — the headline `t0` for a
28
+ * two-agents-talking run (`voice-duet.mjs`).
29
+ * Not recorded in the single-agent path.
30
+ * - `vad-trigger` — `VadDetector` energy-rise edge / the
31
+ * turn controller's wake instant.
32
+ * - `vad-speech-start` — `VadDetector` Silero speech-start.
33
+ * - `prewarm-fired` — the turn controller (W9) when it calls
34
+ * W6's `prewarmConversation`.
35
+ * - `asr-first-partial` — `StreamingTranscriber` first `partial`.
36
+ * - `asr-final` — `StreamingTranscriber` `final`.
37
+ * - `llm-first-token` — the engine generate path's first
38
+ * `onTextChunk` (W4).
39
+ * - `llm-first-replytext-char` — `StructuredFieldStreamExtractor`'s
40
+ * `onFieldStart("replyText")`.
41
+ * - `replyText-first-emotion-tag` — the field extractor / `parseExpressiveTags`
42
+ * on the first inline expressive tag (`[happy]`
43
+ * …) in `replyText` — emotion-markup overhead,
44
+ * measured the way `envelopeToReplyTextMs`
45
+ * measures envelope overhead.
46
+ * - `phrase-1-to-tts` — the scheduler/chunker (W9) on the first
47
+ * phrase handed to the TTS backend.
48
+ * - `tts-first-audio-chunk` — the TTS backend's first PCM chunk (W7).
49
+ * - `audio-first-played` — the audio sink on the first written
50
+ * sample (W9/W13) — single-agent path.
51
+ * - `audio-first-into-peer-ring` — (DUET ONLY) the responding agent's first
52
+ * TTS PCM chunk landed in the peer's ring
53
+ * (the duet replacement for
54
+ * `audio-first-played` — no speakers).
55
+ *
56
+ * Logger only, `[LatencyTracer]` prefix (AGENTS.md §9).
57
+ */
58
+ import type { VadEventSource } from "./voice/types";
59
+ /**
60
+ * The fixed, ordered set of latency checkpoints. The recorder enforces the
61
+ * order is non-decreasing in wall-clock terms only loosely — a checkpoint
62
+ * arriving "out of order" (a later checkpoint with an earlier timestamp) is
63
+ * recorded as-is and flagged; we never reorder or clamp.
64
+ */
65
+ export declare const VOICE_CHECKPOINTS: readonly ["peer-utterance-end", "vad-trigger", "vad-speech-start", "prewarm-fired", "asr-first-partial", "asr-final", "llm-first-token", "llm-first-replytext-char", "replyText-first-emotion-tag", "phrase-1-to-tts", "tts-first-audio-chunk", "audio-first-played", "audio-first-into-peer-ring"];
66
+ export type VoiceCheckpoint = (typeof VOICE_CHECKPOINTS)[number];
67
+ /** The single-agent "core" checkpoint set — every checkpoint that is NOT
68
+ * optional. A trace is `complete` iff every core checkpoint was recorded. */
69
+ export declare const CORE_VOICE_CHECKPOINTS: ("peer-utterance-end" | "vad-trigger" | "vad-speech-start" | "prewarm-fired" | "asr-first-partial" | "asr-final" | "llm-first-token" | "llm-first-replytext-char" | "replyText-first-emotion-tag" | "phrase-1-to-tts" | "tts-first-audio-chunk" | "audio-first-played" | "audio-first-into-peer-ring")[];
70
+ /**
71
+ * Derived per-turn metrics. Every field is the duration between two
72
+ * checkpoints; `null` whenever either endpoint checkpoint is missing for
73
+ * the turn — there is no fallback estimate.
74
+ */
75
+ export interface LatencyDerived {
76
+ /** vad-trigger → llm-first-token (time-to-first-token). */
77
+ ttftMs: number | null;
78
+ /** vad-trigger → tts-first-audio-chunk (time-to-first-audio). */
79
+ ttfaMs: number | null;
80
+ /** vad-trigger → audio-first-played (time-to-audio-played; the headline). */
81
+ ttapMs: number | null;
82
+ /** vad-speech-start → asr-final (ASR finalization latency). */
83
+ asrFinalLatencyMs: number | null;
84
+ /** vad-trigger → asr-first-partial (how fast the first words appear). */
85
+ asrFirstPartialMs: number | null;
86
+ /** vad-trigger → prewarm-fired (how fast the prewarm kicks off). */
87
+ prewarmLatencyMs: number | null;
88
+ /** asr-final → llm-first-token (LLM latency once the prompt is complete). */
89
+ llmFirstTokenAfterAsrMs: number | null;
90
+ /** llm-first-token → llm-first-replytext-char (envelope-skip overhead). */
91
+ envelopeToReplyTextMs: number | null;
92
+ /** llm-first-replytext-char → phrase-1-to-tts (chunker hand-off lag). */
93
+ replyTextToPhrase1Ms: number | null;
94
+ /** phrase-1-to-tts → tts-first-audio-chunk (TTS first-chunk latency). */
95
+ ttsFirstChunkMs: number | null;
96
+ /** tts-first-audio-chunk → audio-first-played (sink/playback lag). */
97
+ audioSinkLatencyMs: number | null;
98
+ /**
99
+ * peer-utterance-end → llm-first-token — **THE headline number** for the
100
+ * two-agents-talking benchmark: how long after the peer stopped speaking
101
+ * the responding agent emits its first token (TTFT-from-last-utterance).
102
+ */
103
+ ttftFromUtteranceEndMs: number | null;
104
+ /** peer-utterance-end → llm-first-replytext-char. */
105
+ replyTextFirstCharFromUtteranceEndMs: number | null;
106
+ /** peer-utterance-end → tts-first-audio-chunk. */
107
+ firstTtsPcmFromUtteranceEndMs: number | null;
108
+ /**
109
+ * peer-utterance-end → audio-first-into-peer-ring — the **duet round-trip**:
110
+ * peer stops speaking → responding agent's first audio is back in the
111
+ * peer's ear (the `duet_round_trip_ms` gate reads `.p50` of this).
112
+ */
113
+ firstAudioIntoPeerRingFromUtteranceEndMs: number | null;
114
+ /** llm-first-token → replyText-first-emotion-tag (emotion-markup overhead);
115
+ * `null` when the model emitted no inline expressive tag. */
116
+ emotionTagOverheadMs: number | null;
117
+ }
118
+ /** The derived-metric keys, in display order. */
119
+ export declare const LATENCY_DERIVED_KEYS: readonly ["ttftFromUtteranceEndMs", "firstAudioIntoPeerRingFromUtteranceEndMs", "ttftMs", "ttfaMs", "ttapMs", "asrFinalLatencyMs", "asrFirstPartialMs", "prewarmLatencyMs", "llmFirstTokenAfterAsrMs", "envelopeToReplyTextMs", "emotionTagOverheadMs", "replyTextToPhrase1Ms", "ttsFirstChunkMs", "audioSinkLatencyMs", "ttftFromUtteranceEndMs", "replyTextFirstCharFromUtteranceEndMs", "firstTtsPcmFromUtteranceEndMs", "firstAudioIntoPeerRingFromUtteranceEndMs", "emotionTagOverheadMs"];
120
+ export type LatencyDerivedKey = (typeof LATENCY_DERIVED_KEYS)[number];
121
+ export interface LatencyCheckpoint {
122
+ name: VoiceCheckpoint;
123
+ /** Wall-clock ms since the turn's `t0` (the first checkpoint recorded). */
124
+ tMs: number;
125
+ /** Absolute epoch ms when the checkpoint was recorded. */
126
+ atEpochMs: number;
127
+ }
128
+ export interface LatencyTrace {
129
+ turnId: string;
130
+ roomId: string | null;
131
+ /** Epoch ms of the first checkpoint recorded for this turn (the t=0 ref). */
132
+ t0EpochMs: number;
133
+ /** Epoch ms when `endTurn` was called, or null while still open. */
134
+ closedAtEpochMs: number | null;
135
+ checkpoints: LatencyCheckpoint[];
136
+ derived: LatencyDerived;
137
+ /** Names of checkpoints that were never recorded for this turn. */
138
+ missing: VoiceCheckpoint[];
139
+ /** True when every checkpoint in `VOICE_CHECKPOINTS` was recorded. */
140
+ complete: boolean;
141
+ /**
142
+ * Non-empty when the recorder saw something it could not reconcile —
143
+ * a duplicate mark, an out-of-order timestamp, an unknown checkpoint.
144
+ * Diagnostic only; the trace is still emitted.
145
+ */
146
+ anomalies: string[];
147
+ }
148
+ export interface HistogramSummary {
149
+ count: number;
150
+ p50: number | null;
151
+ p90: number | null;
152
+ p99: number | null;
153
+ min: number | null;
154
+ max: number | null;
155
+ mean: number | null;
156
+ }
157
+ /**
158
+ * Bounded-sample running histogram for one derived metric. Keeps the last
159
+ * `capacity` samples (FIFO) and computes percentiles on demand. Bounded so
160
+ * a long-running process does not grow without limit.
161
+ *
162
+ * Exported so sibling accumulators (e.g. the Mobile Resource Workbench's
163
+ * `DeviceResourceMetrics`) reuse the same percentile logic instead of
164
+ * re-implementing it.
165
+ */
166
+ export declare class BoundedHistogram {
167
+ private readonly capacity;
168
+ private readonly samples;
169
+ constructor(capacity: number);
170
+ add(value: number): void;
171
+ summary(): HistogramSummary;
172
+ }
173
+ export interface TracerOptions {
174
+ /** Max number of completed traces to retain in the ring. Default 64. */
175
+ ringCapacity?: number;
176
+ /** Max samples per derived-metric histogram. Default 256. */
177
+ histogramCapacity?: number;
178
+ /**
179
+ * Max number of concurrently-open turns. A new `beginTurn` past this cap
180
+ * evicts the oldest still-open turn (it is closed and emitted with whatever
181
+ * checkpoints it had). Guards against a leaked turn never being closed.
182
+ * Default 16.
183
+ */
184
+ maxOpenTurns?: number;
185
+ }
186
+ export declare class EndToEndLatencyTracer {
187
+ private readonly ring;
188
+ private readonly open;
189
+ private readonly byRoom;
190
+ private readonly histograms;
191
+ private readonly ringCapacity;
192
+ private readonly histogramCapacity;
193
+ private readonly maxOpenTurns;
194
+ constructor(opts?: TracerOptions);
195
+ /**
196
+ * Open a new turn. Returns the `turnId`. If `roomId` is given, subsequent
197
+ * context-free marks for that room route to this turn until it is closed.
198
+ */
199
+ beginTurn(args?: {
200
+ turnId?: string;
201
+ roomId?: string | null;
202
+ }): string;
203
+ /** Resolve (or lazily open) a turn for a roomId. Used by the helper. */
204
+ turnForRoom(roomId: string): string;
205
+ /**
206
+ * Record a checkpoint on an open turn. No-op (with a warning) if the turn
207
+ * is unknown or already closed — a late mark on a finalized turn is a
208
+ * caller bug, not something to retroactively patch into history.
209
+ */
210
+ mark(turnId: string, checkpoint: VoiceCheckpoint, atEpochMs?: number): void;
211
+ /** Convenience: mark a checkpoint by roomId, opening a turn if needed. */
212
+ markByRoom(roomId: string, checkpoint: VoiceCheckpoint, atEpochMs?: number): void;
213
+ /**
214
+ * Close an open turn: snapshot it into a `LatencyTrace`, push to the ring
215
+ * (evicting the oldest), and fold its derived metrics into the histograms.
216
+ * Idempotent for an unknown turnId. Returns the emitted trace (or null if
217
+ * the turn was unknown).
218
+ */
219
+ endTurn(turnId: string): LatencyTrace | null;
220
+ /** A read-only snapshot of an open turn (does not close it). */
221
+ peekTurn(turnId: string): LatencyTrace | null;
222
+ /** The most recent `n` completed traces, newest last. */
223
+ recentTraces(n?: number): LatencyTrace[];
224
+ /** Per-derived-metric histogram summaries over the retained sample. */
225
+ histogramSummaries(): Record<LatencyDerivedKey, HistogramSummary>;
226
+ /** Drop all retained traces, histograms, and open turns. */
227
+ reset(): void;
228
+ /** Number of turns currently open (un-closed). */
229
+ get openTurnCount(): number;
230
+ /**
231
+ * Bridge a VAD event source onto this tracer: subscribes to the
232
+ * `VadEvent` stream and emits `vad-trigger` + `vad-speech-start` on the
233
+ * Silero rising edge (the earliest reliable per-turn `t0`). Returns the
234
+ * unsubscribe function. This is the documented seam that lets the tracer
235
+ * hook the VAD without editing `voice/vad.ts` — the true energy-rise
236
+ * "wake" instant is owned by the turn controller (W9), which calls
237
+ * `mark(turnId, "vad-trigger")` directly; this bridge is the fallback for
238
+ * plain VAD-only setups.
239
+ */
240
+ bindVadDetector(source: VadEventSource, args?: {
241
+ roomId?: string | null;
242
+ onTurnOpen?: (turnId: string) => void;
243
+ }): () => void;
244
+ private snapshotTurn;
245
+ private computeDerived;
246
+ }
247
+ /**
248
+ * Process-wide tracer. The turn controller (W9) owns per-turn lifecycle
249
+ * via `beginTurn` / `endTurn`; components that only know a `roomId` use
250
+ * `markVoiceLatency(roomId, checkpoint)` which routes through `markByRoom`.
251
+ * The dev endpoint (`GET /api/dev/voice-latency`) reads this singleton.
252
+ */
253
+ export declare const voiceLatencyTracer: EndToEndLatencyTracer;
254
+ /**
255
+ * Record a checkpoint on the process-wide tracer, keyed by `roomId`. Opens
256
+ * a turn for that room on first call. No-op-safe — instrumentation must
257
+ * never throw into the voice loop. This is the seam every component (VAD,
258
+ * turn controller, engine, field extractor, chunker, TTS backend, audio
259
+ * sink) can call without threading a tracer reference.
260
+ */
261
+ export declare function markVoiceLatency(roomId: string | null | undefined, checkpoint: VoiceCheckpoint, atEpochMs?: number): void;
262
+ /** Close the process-wide tracer's turn for a roomId, returning the trace. */
263
+ export declare function endVoiceLatencyTurn(roomId: string): LatencyTrace | null;
264
+ export interface VoiceLatencyDevPayload {
265
+ generatedAtEpochMs: number;
266
+ /** Checkpoint names, in canonical order — so consumers can render headers. */
267
+ checkpoints: ReadonlyArray<VoiceCheckpoint>;
268
+ derivedKeys: ReadonlyArray<LatencyDerivedKey>;
269
+ openTurnCount: number;
270
+ traces: LatencyTrace[];
271
+ histograms: Record<LatencyDerivedKey, HistogramSummary>;
272
+ }
273
+ /** Build the JSON body for `GET /api/dev/voice-latency`. */
274
+ export declare function buildVoiceLatencyDevPayload(tracer?: EndToEndLatencyTracer, limit?: number): VoiceLatencyDevPayload;
275
+ /** A per-turn observation fed to `VoiceRunMetrics.recordTurn`. Every field is
276
+ * optional — a turn that couldn't measure a quantity records it as missing,
277
+ * never as a fabricated zero (AGENTS.md §3 / §7). */
278
+ export interface VoiceTurnMetrics {
279
+ /** MTP drafter token-acceptance rate (n_drafted_accepted / n_drafted)
280
+ * for this turn's generation, from the llama-server `/metrics` deltas. */
281
+ mtpAcceptRate?: number | null;
282
+ /** Tokens accepted from the drafter this turn (for an aggregate accept-rate
283
+ * that weights by token count, not turn count). */
284
+ mtpAccepted?: number | null;
285
+ /** Tokens drafted this turn. */
286
+ mtpDrafted?: number | null;
287
+ /** Structured-decode token-savings % for this turn — tokens the grammar
288
+ * force-filled ÷ tokens that would otherwise have been generated, ×100
289
+ * (WS-4's `guided_decode_token_bench.mjs` counter; ≈28% aggregate forced
290
+ * on the synthetic action set). */
291
+ structuredDecodeTokenSavingsPct?: number | null;
292
+ /** Decode throughput (tokens / second) for this turn's generation. */
293
+ tokensPerSecond?: number | null;
294
+ /** Server resident-set high-water mark in MB at the end of this turn
295
+ * (`VmHWM` from `/proc/<pid>/status`). */
296
+ serverRssMb?: number | null;
297
+ }
298
+ export interface VoiceRunMetricsSummary {
299
+ turns: number;
300
+ /** MTP accept-rate, token-weighted across the run (Σaccepted / Σdrafted);
301
+ * `null` when nothing was drafted / no drafter present. */
302
+ mtpAcceptRate: number | null;
303
+ mtpAccepted: number;
304
+ mtpDrafted: number;
305
+ /** Per-turn accept-rate histogram (p50/p90/p99 etc. — bounded sample). */
306
+ mtpAcceptRateHistogram: HistogramSummary;
307
+ /** Mean / histogram of the structured-decode token-savings %. */
308
+ structuredDecodeTokenSavingsPct: HistogramSummary;
309
+ /** Mean / histogram of decode tok/s. */
310
+ tokensPerSecond: HistogramSummary;
311
+ /** Server RSS over the run: first / last / max in MB + the `leakSuspected`
312
+ * flag (true when RSS is monotone non-decreasing across ≥4 turns and grew
313
+ * by more than `leakGrowthMbThreshold`). */
314
+ rss: {
315
+ firstMb: number | null;
316
+ lastMb: number | null;
317
+ maxMb: number | null;
318
+ samples: number;
319
+ leakSuspected: boolean;
320
+ growthMb: number | null;
321
+ };
322
+ }
323
+ /**
324
+ * Accumulates the non-latency signals over a long voice run (the duet harness
325
+ * feeds it per-turn). Sibling to `EndToEndLatencyTracer` (which is per-turn
326
+ * spans only). The duet bench report (`voice-duet-bench-<model>.json`) writes
327
+ * `summary()` next to the latency histograms; `eliza1_gates_collect.mjs`
328
+ * ingests the gate-named fields.
329
+ */
330
+ export declare class VoiceRunMetrics {
331
+ private readonly opts;
332
+ private turns;
333
+ private mtpAccepted;
334
+ private mtpDrafted;
335
+ private readonly acceptRateHist;
336
+ private readonly savingsHist;
337
+ private readonly tokSecHist;
338
+ private readonly rssSamples;
339
+ constructor(opts?: {
340
+ leakGrowthMbThreshold?: number;
341
+ });
342
+ recordTurn(m: VoiceTurnMetrics): void;
343
+ summary(): VoiceRunMetricsSummary;
344
+ reset(): void;
345
+ }
346
+ //# sourceMappingURL=latency-trace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"latency-trace.d.ts","sourceRoot":"","sources":["latency-trace.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,266 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import {
3
+ buildVoiceLatencyDevPayload,
4
+ EndToEndLatencyTracer,
5
+ LATENCY_DERIVED_KEYS,
6
+ VOICE_CHECKPOINTS,
7
+ type VoiceCheckpoint,
8
+ } from "./latency-trace";
9
+ import type { VadEvent, VadEventListener } from "./voice/types";
10
+
11
+ /** Drive one full turn's worth of checkpoints with explicit timestamps. */
12
+ function fullTurn(
13
+ tracer: EndToEndLatencyTracer,
14
+ base: number,
15
+ offsets: Partial<Record<VoiceCheckpoint, number>>,
16
+ roomId?: string,
17
+ ): string {
18
+ const turnId = tracer.beginTurn(roomId ? { roomId } : {});
19
+ for (const cp of VOICE_CHECKPOINTS) {
20
+ const off = offsets[cp];
21
+ if (off === undefined) continue;
22
+ tracer.mark(turnId, cp, base + off);
23
+ }
24
+ return turnId;
25
+ }
26
+
27
+ const CANONICAL_OFFSETS: Record<VoiceCheckpoint, number> = {
28
+ "peer-utterance-end": -120,
29
+ "vad-trigger": 0,
30
+ "vad-speech-start": 30,
31
+ "prewarm-fired": 35,
32
+ "asr-first-partial": 220,
33
+ "asr-final": 900,
34
+ "llm-first-token": 1000,
35
+ "llm-first-replytext-char": 1040,
36
+ "replyText-first-emotion-tag": 1050,
37
+ "phrase-1-to-tts": 1090,
38
+ "tts-first-audio-chunk": 1200,
39
+ "audio-first-played": 1230,
40
+ "audio-first-into-peer-ring": 1235,
41
+ };
42
+
43
+ describe("EndToEndLatencyTracer", () => {
44
+ it("records checkpoints and derives metrics for a complete turn", () => {
45
+ const tracer = new EndToEndLatencyTracer();
46
+ const turnId = fullTurn(tracer, 1_000_000, CANONICAL_OFFSETS, "roomA");
47
+ const trace = tracer.endTurn(turnId);
48
+ expect(trace).not.toBeNull();
49
+ if (!trace) return;
50
+ expect(trace.complete).toBe(true);
51
+ // CANONICAL_OFFSETS records every checkpoint including the duet-only ones,
52
+ // so nothing is missing.
53
+ expect(trace.missing).toHaveLength(0);
54
+ expect(trace.roomId).toBe("roomA");
55
+ expect(trace.checkpoints).toHaveLength(VOICE_CHECKPOINTS.length);
56
+ // t0 == the earliest checkpoint recorded — here `peer-utterance-end`
57
+ // (offset -120), the duet headline t0; checkpoints sorted by atEpochMs.
58
+ expect(trace.t0EpochMs).toBe(1_000_000 - 120);
59
+ expect(trace.checkpoints[0]?.name).toBe("peer-utterance-end");
60
+ expect(trace.checkpoints[0]?.tMs).toBe(0);
61
+ // Derived spans (absolute deltas — independent of t0).
62
+ expect(trace.derived.ttftMs).toBe(1000); // vad-trigger → llm-first-token
63
+ expect(trace.derived.ttfaMs).toBe(1200); // vad-trigger → tts-first-audio-chunk
64
+ expect(trace.derived.ttapMs).toBe(1230); // vad-trigger → audio-first-played
65
+ expect(trace.derived.asrFinalLatencyMs).toBe(870); // vad-speech-start(30) → asr-final(900)
66
+ expect(trace.derived.prewarmLatencyMs).toBe(35);
67
+ expect(trace.derived.audioSinkLatencyMs).toBe(30); // tts-first-chunk(1200) → played(1230)
68
+ // Duet (cross-agent) spans — peer-utterance-end(-120) is the headline t0.
69
+ expect(trace.derived.ttftFromUtteranceEndMs).toBe(1120); // -120 → 1000
70
+ expect(trace.derived.firstAudioIntoPeerRingFromUtteranceEndMs).toBe(1355); // -120 → 1235
71
+ expect(trace.derived.emotionTagOverheadMs).toBe(50); // llm-first-token(1000) → tag(1050)
72
+ expect(trace.anomalies).toHaveLength(0);
73
+ });
74
+
75
+ it("leaves derived metrics null when an endpoint checkpoint is missing", () => {
76
+ const tracer = new EndToEndLatencyTracer();
77
+ // No `audio-first-played`, no `tts-first-audio-chunk`.
78
+ const offsets = { ...CANONICAL_OFFSETS };
79
+ delete (offsets as Partial<Record<VoiceCheckpoint, number>>)[
80
+ "tts-first-audio-chunk"
81
+ ];
82
+ delete (offsets as Partial<Record<VoiceCheckpoint, number>>)[
83
+ "audio-first-played"
84
+ ];
85
+ const turnId = fullTurn(tracer, 2_000_000, offsets);
86
+ const trace = tracer.endTurn(turnId);
87
+ if (!trace) throw new Error("expected trace");
88
+ expect(trace.complete).toBe(false);
89
+ expect(trace.missing).toEqual(
90
+ expect.arrayContaining(["tts-first-audio-chunk", "audio-first-played"]),
91
+ );
92
+ expect(trace.derived.ttftMs).toBe(1000); // still computable
93
+ expect(trace.derived.ttfaMs).toBeNull(); // depends on tts-first-audio-chunk
94
+ expect(trace.derived.ttapMs).toBeNull(); // depends on audio-first-played
95
+ expect(trace.derived.audioSinkLatencyMs).toBeNull();
96
+ });
97
+
98
+ it("flags a duplicate mark and keeps the first timestamp", () => {
99
+ const tracer = new EndToEndLatencyTracer();
100
+ const turnId = tracer.beginTurn({});
101
+ tracer.mark(turnId, "vad-trigger", 100);
102
+ tracer.mark(turnId, "vad-trigger", 999); // duplicate
103
+ tracer.mark(turnId, "llm-first-token", 600);
104
+ const trace = tracer.endTurn(turnId);
105
+ if (!trace) throw new Error("expected trace");
106
+ expect(trace.anomalies.some((a) => a.includes("duplicate"))).toBe(true);
107
+ expect(trace.derived.ttftMs).toBe(500); // 100 → 600, not 999 → 600
108
+ });
109
+
110
+ it("flags an out-of-order checkpoint without reordering", () => {
111
+ const tracer = new EndToEndLatencyTracer();
112
+ const turnId = tracer.beginTurn({});
113
+ tracer.mark(turnId, "vad-trigger", 100);
114
+ tracer.mark(turnId, "llm-first-token", 500);
115
+ // asr-final ordered before llm-first-token but timestamped after it.
116
+ tracer.mark(turnId, "asr-final", 700);
117
+ const trace = tracer.endTurn(turnId);
118
+ if (!trace) throw new Error("expected trace");
119
+ expect(trace.anomalies.some((a) => a.includes("clock skew"))).toBe(true);
120
+ expect(trace.derived.llmFirstTokenAfterAsrMs).toBe(-200); // 700 → 500 recorded as-is
121
+ });
122
+
123
+ it("ignores marks for unknown / closed turns", () => {
124
+ const tracer = new EndToEndLatencyTracer();
125
+ const turnId = tracer.beginTurn({});
126
+ tracer.mark(turnId, "vad-trigger", 1);
127
+ tracer.endTurn(turnId);
128
+ // Late mark — must not throw, must not resurrect the turn.
129
+ tracer.mark(turnId, "llm-first-token", 5);
130
+ tracer.mark("does-not-exist", "vad-trigger", 5);
131
+ expect(tracer.recentTraces()).toHaveLength(1);
132
+ });
133
+
134
+ it("evicts the oldest trace when the ring is full", () => {
135
+ const tracer = new EndToEndLatencyTracer({ ringCapacity: 3 });
136
+ for (let i = 0; i < 5; i += 1) {
137
+ const turnId = tracer.beginTurn({ roomId: `room-${i}` });
138
+ tracer.mark(turnId, "vad-trigger", i * 1000);
139
+ tracer.mark(turnId, "llm-first-token", i * 1000 + 100);
140
+ tracer.endTurn(turnId);
141
+ }
142
+ const traces = tracer.recentTraces();
143
+ expect(traces).toHaveLength(3);
144
+ expect(traces.map((t) => t.roomId)).toEqual(["room-2", "room-3", "room-4"]);
145
+ });
146
+
147
+ it("evicts the oldest *open* turn past maxOpenTurns", () => {
148
+ const tracer = new EndToEndLatencyTracer({ maxOpenTurns: 2 });
149
+ const a = tracer.beginTurn({ roomId: "a" });
150
+ tracer.mark(a, "vad-trigger", 10);
151
+ tracer.beginTurn({ roomId: "b" });
152
+ tracer.beginTurn({ roomId: "c" }); // forces eviction of `a`
153
+ expect(tracer.openTurnCount).toBe(2);
154
+ // `a` was emitted with whatever it had.
155
+ const traces = tracer.recentTraces();
156
+ expect(traces.some((t) => t.roomId === "a")).toBe(true);
157
+ // A mark on the evicted turn is now ignored.
158
+ tracer.mark(a, "llm-first-token", 50);
159
+ expect(
160
+ tracer.recentTraces().find((t) => t.roomId === "a")?.missing,
161
+ ).toContain("llm-first-token");
162
+ });
163
+
164
+ it("builds histograms with nearest-rank percentiles", () => {
165
+ const tracer = new EndToEndLatencyTracer();
166
+ // Five turns with ttftMs of 100, 200, 300, 400, 500.
167
+ for (const v of [100, 200, 300, 400, 500]) {
168
+ const turnId = tracer.beginTurn({});
169
+ tracer.mark(turnId, "vad-trigger", 0);
170
+ tracer.mark(turnId, "llm-first-token", v);
171
+ tracer.endTurn(turnId);
172
+ }
173
+ const h = tracer.histogramSummaries();
174
+ expect(h.ttftMs.count).toBe(5);
175
+ expect(h.ttftMs.min).toBe(100);
176
+ expect(h.ttftMs.max).toBe(500);
177
+ expect(h.ttftMs.p50).toBe(300);
178
+ expect(h.ttftMs.p90).toBe(500);
179
+ expect(h.ttftMs.p99).toBe(500);
180
+ expect(h.ttftMs.mean).toBe(300);
181
+ // A metric with no samples is all-null, not zero.
182
+ expect(h.ttfaMs.count).toBe(0);
183
+ expect(h.ttfaMs.p50).toBeNull();
184
+ });
185
+
186
+ it("only feeds non-null derived metrics into the histograms", () => {
187
+ const tracer = new EndToEndLatencyTracer();
188
+ const turnId = tracer.beginTurn({});
189
+ tracer.mark(turnId, "vad-trigger", 0);
190
+ // No llm-first-token → ttftMs is null and must not become a 0 sample.
191
+ tracer.mark(turnId, "asr-first-partial", 150);
192
+ tracer.endTurn(turnId);
193
+ const h = tracer.histogramSummaries();
194
+ expect(h.ttftMs.count).toBe(0);
195
+ expect(h.asrFirstPartialMs.count).toBe(1);
196
+ expect(h.asrFirstPartialMs.p50).toBe(150);
197
+ });
198
+
199
+ it("bridges a VadEventSource onto vad-trigger / vad-speech-start", () => {
200
+ const listeners = new Set<VadEventListener>();
201
+ const source = {
202
+ onVadEvent(l: VadEventListener) {
203
+ listeners.add(l);
204
+ return () => listeners.delete(l);
205
+ },
206
+ };
207
+ const emit = (e: VadEvent) => {
208
+ for (const l of listeners) l(e);
209
+ };
210
+ const tracer = new EndToEndLatencyTracer();
211
+ let openedTurnId: string | null = null;
212
+ const unsub = tracer.bindVadDetector(source, {
213
+ roomId: "roomVad",
214
+ onTurnOpen: (id) => {
215
+ openedTurnId = id;
216
+ },
217
+ });
218
+ emit({ type: "speech-start", timestampMs: 4_242, probability: 0.9 });
219
+ expect(openedTurnId).not.toBeNull();
220
+ if (!openedTurnId) return;
221
+ // The bridge recorded vad-trigger + vad-speech-start at the event ts.
222
+ const peek = tracer.peekTurn(openedTurnId);
223
+ expect(peek?.checkpoints.map((c) => c.name)).toEqual([
224
+ "vad-trigger",
225
+ "vad-speech-start",
226
+ ]);
227
+ expect(peek?.t0EpochMs).toBe(4_242);
228
+ // speech-active / speech-end do not open new turns.
229
+ emit({
230
+ type: "speech-active",
231
+ timestampMs: 4_500,
232
+ probability: 0.95,
233
+ speechDurationMs: 258,
234
+ });
235
+ expect(tracer.openTurnCount).toBe(1);
236
+ unsub();
237
+ emit({ type: "speech-start", timestampMs: 9_000, probability: 0.8 });
238
+ // After unsubscribe, no new turn.
239
+ expect(tracer.openTurnCount).toBe(1);
240
+ });
241
+
242
+ it("buildVoiceLatencyDevPayload exposes traces + histograms + metadata", () => {
243
+ const tracer = new EndToEndLatencyTracer();
244
+ const turnId = fullTurn(tracer, 5_000_000, CANONICAL_OFFSETS, "roomP");
245
+ tracer.endTurn(turnId);
246
+ const payload = buildVoiceLatencyDevPayload(tracer, 10);
247
+ expect(payload.checkpoints).toEqual(VOICE_CHECKPOINTS);
248
+ expect(payload.derivedKeys).toEqual(LATENCY_DERIVED_KEYS);
249
+ expect(payload.openTurnCount).toBe(0);
250
+ expect(payload.traces).toHaveLength(1);
251
+ expect(payload.traces[0]?.roomId).toBe("roomP");
252
+ expect(payload.histograms.ttftMs.count).toBe(1);
253
+ expect(typeof payload.generatedAtEpochMs).toBe("number");
254
+ });
255
+
256
+ it("reset() clears traces, histograms, and open turns", () => {
257
+ const tracer = new EndToEndLatencyTracer();
258
+ const t = fullTurn(tracer, 1, CANONICAL_OFFSETS);
259
+ tracer.endTurn(t);
260
+ tracer.beginTurn({ roomId: "still-open" });
261
+ tracer.reset();
262
+ expect(tracer.recentTraces()).toHaveLength(0);
263
+ expect(tracer.openTurnCount).toBe(0);
264
+ expect(tracer.histogramSummaries().ttftMs.count).toBe(0);
265
+ });
266
+ });