@livekit/agents 0.7.9 → 1.0.0-next.0

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 (627) hide show
  1. package/dist/_exceptions.cjs +109 -0
  2. package/dist/_exceptions.cjs.map +1 -0
  3. package/dist/_exceptions.d.cts +64 -0
  4. package/dist/_exceptions.d.ts +64 -0
  5. package/dist/_exceptions.d.ts.map +1 -0
  6. package/dist/_exceptions.js +80 -0
  7. package/dist/_exceptions.js.map +1 -0
  8. package/dist/audio.cjs +10 -3
  9. package/dist/audio.cjs.map +1 -1
  10. package/dist/audio.d.cts +2 -0
  11. package/dist/audio.d.ts +2 -0
  12. package/dist/audio.d.ts.map +1 -1
  13. package/dist/audio.js +8 -2
  14. package/dist/audio.js.map +1 -1
  15. package/dist/cli.cjs +25 -0
  16. package/dist/cli.cjs.map +1 -1
  17. package/dist/cli.d.ts.map +1 -1
  18. package/dist/cli.js +25 -0
  19. package/dist/cli.js.map +1 -1
  20. package/dist/constants.cjs +6 -3
  21. package/dist/constants.cjs.map +1 -1
  22. package/dist/constants.d.cts +2 -1
  23. package/dist/constants.d.ts +2 -1
  24. package/dist/constants.d.ts.map +1 -1
  25. package/dist/constants.js +4 -2
  26. package/dist/constants.js.map +1 -1
  27. package/dist/http_server.cjs.map +1 -1
  28. package/dist/http_server.d.cts +1 -0
  29. package/dist/http_server.d.ts +1 -0
  30. package/dist/http_server.d.ts.map +1 -1
  31. package/dist/http_server.js.map +1 -1
  32. package/dist/index.cjs +27 -20
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.d.cts +13 -10
  35. package/dist/index.d.ts +13 -10
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +15 -11
  38. package/dist/index.js.map +1 -1
  39. package/dist/inference_runner.cjs +0 -1
  40. package/dist/inference_runner.cjs.map +1 -1
  41. package/dist/inference_runner.d.cts +2 -3
  42. package/dist/inference_runner.d.ts +2 -3
  43. package/dist/inference_runner.d.ts.map +1 -1
  44. package/dist/inference_runner.js +0 -1
  45. package/dist/inference_runner.js.map +1 -1
  46. package/dist/ipc/inference_proc_executor.cjs +2 -2
  47. package/dist/ipc/inference_proc_executor.cjs.map +1 -1
  48. package/dist/ipc/inference_proc_executor.js +2 -2
  49. package/dist/ipc/inference_proc_executor.js.map +1 -1
  50. package/dist/ipc/job_executor.cjs.map +1 -1
  51. package/dist/ipc/job_executor.js.map +1 -1
  52. package/dist/ipc/job_proc_executor.cjs +1 -0
  53. package/dist/ipc/job_proc_executor.cjs.map +1 -1
  54. package/dist/ipc/job_proc_executor.js +1 -0
  55. package/dist/ipc/job_proc_executor.js.map +1 -1
  56. package/dist/ipc/job_proc_lazy_main.cjs +1 -1
  57. package/dist/ipc/job_proc_lazy_main.cjs.map +1 -1
  58. package/dist/ipc/job_proc_lazy_main.js +1 -1
  59. package/dist/ipc/job_proc_lazy_main.js.map +1 -1
  60. package/dist/ipc/supervised_proc.d.cts +1 -1
  61. package/dist/ipc/supervised_proc.d.ts +1 -1
  62. package/dist/ipc/supervised_proc.d.ts.map +1 -1
  63. package/dist/job.cjs +14 -2
  64. package/dist/job.cjs.map +1 -1
  65. package/dist/job.d.cts +8 -0
  66. package/dist/job.d.ts +8 -0
  67. package/dist/job.d.ts.map +1 -1
  68. package/dist/job.js +12 -1
  69. package/dist/job.js.map +1 -1
  70. package/dist/llm/chat_context.cjs +332 -82
  71. package/dist/llm/chat_context.cjs.map +1 -1
  72. package/dist/llm/chat_context.d.cts +152 -48
  73. package/dist/llm/chat_context.d.ts +152 -48
  74. package/dist/llm/chat_context.d.ts.map +1 -1
  75. package/dist/llm/chat_context.js +327 -81
  76. package/dist/llm/chat_context.js.map +1 -1
  77. package/dist/llm/chat_context.test.cjs +380 -0
  78. package/dist/llm/chat_context.test.cjs.map +1 -0
  79. package/dist/llm/chat_context.test.js +385 -0
  80. package/dist/llm/chat_context.test.js.map +1 -0
  81. package/dist/llm/index.cjs +37 -8
  82. package/dist/llm/index.cjs.map +1 -1
  83. package/dist/llm/index.d.cts +7 -3
  84. package/dist/llm/index.d.ts +7 -3
  85. package/dist/llm/index.d.ts.map +1 -1
  86. package/dist/llm/index.js +39 -9
  87. package/dist/llm/index.js.map +1 -1
  88. package/dist/llm/llm.cjs +98 -33
  89. package/dist/llm/llm.cjs.map +1 -1
  90. package/dist/llm/llm.d.cts +50 -24
  91. package/dist/llm/llm.d.ts +50 -24
  92. package/dist/llm/llm.d.ts.map +1 -1
  93. package/dist/llm/llm.js +99 -33
  94. package/dist/llm/llm.js.map +1 -1
  95. package/dist/llm/provider_format/google.cjs +128 -0
  96. package/dist/llm/provider_format/google.cjs.map +1 -0
  97. package/dist/llm/provider_format/google.d.cts +6 -0
  98. package/dist/llm/provider_format/google.d.ts +6 -0
  99. package/dist/llm/provider_format/google.d.ts.map +1 -0
  100. package/dist/llm/provider_format/google.js +104 -0
  101. package/dist/llm/provider_format/google.js.map +1 -0
  102. package/dist/llm/provider_format/google.test.cjs +676 -0
  103. package/dist/llm/provider_format/google.test.cjs.map +1 -0
  104. package/dist/llm/provider_format/google.test.js +675 -0
  105. package/dist/llm/provider_format/google.test.js.map +1 -0
  106. package/dist/llm/provider_format/index.cjs +40 -0
  107. package/dist/llm/provider_format/index.cjs.map +1 -0
  108. package/dist/llm/provider_format/index.d.cts +4 -0
  109. package/dist/llm/provider_format/index.d.ts +4 -0
  110. package/dist/llm/provider_format/index.d.ts.map +1 -0
  111. package/dist/llm/provider_format/index.js +16 -0
  112. package/dist/llm/provider_format/index.js.map +1 -0
  113. package/dist/llm/provider_format/openai.cjs +116 -0
  114. package/dist/llm/provider_format/openai.cjs.map +1 -0
  115. package/dist/llm/provider_format/openai.d.cts +3 -0
  116. package/dist/llm/provider_format/openai.d.ts +3 -0
  117. package/dist/llm/provider_format/openai.d.ts.map +1 -0
  118. package/dist/llm/provider_format/openai.js +92 -0
  119. package/dist/llm/provider_format/openai.js.map +1 -0
  120. package/dist/llm/provider_format/openai.test.cjs +490 -0
  121. package/dist/llm/provider_format/openai.test.cjs.map +1 -0
  122. package/dist/llm/provider_format/openai.test.js +489 -0
  123. package/dist/llm/provider_format/openai.test.js.map +1 -0
  124. package/dist/llm/provider_format/utils.cjs +146 -0
  125. package/dist/llm/provider_format/utils.cjs.map +1 -0
  126. package/dist/llm/provider_format/utils.d.cts +38 -0
  127. package/dist/llm/provider_format/utils.d.ts +38 -0
  128. package/dist/llm/provider_format/utils.d.ts.map +1 -0
  129. package/dist/llm/provider_format/utils.js +122 -0
  130. package/dist/llm/provider_format/utils.js.map +1 -0
  131. package/dist/llm/realtime.cjs +77 -0
  132. package/dist/llm/realtime.cjs.map +1 -0
  133. package/dist/llm/realtime.d.cts +98 -0
  134. package/dist/llm/realtime.d.ts +98 -0
  135. package/dist/llm/realtime.d.ts.map +1 -0
  136. package/dist/llm/realtime.js +52 -0
  137. package/dist/llm/realtime.js.map +1 -0
  138. package/dist/llm/remote_chat_context.cjs +112 -0
  139. package/dist/llm/remote_chat_context.cjs.map +1 -0
  140. package/dist/llm/remote_chat_context.d.cts +23 -0
  141. package/dist/llm/remote_chat_context.d.ts +23 -0
  142. package/dist/llm/remote_chat_context.d.ts.map +1 -0
  143. package/dist/llm/remote_chat_context.js +88 -0
  144. package/dist/llm/remote_chat_context.js.map +1 -0
  145. package/dist/llm/remote_chat_context.test.cjs +225 -0
  146. package/dist/llm/remote_chat_context.test.cjs.map +1 -0
  147. package/dist/llm/remote_chat_context.test.js +224 -0
  148. package/dist/llm/remote_chat_context.test.js.map +1 -0
  149. package/dist/llm/tool_context.cjs +111 -0
  150. package/dist/llm/tool_context.cjs.map +1 -0
  151. package/dist/llm/tool_context.d.cts +125 -0
  152. package/dist/llm/tool_context.d.ts +125 -0
  153. package/dist/llm/tool_context.d.ts.map +1 -0
  154. package/dist/llm/tool_context.js +80 -0
  155. package/dist/llm/tool_context.js.map +1 -0
  156. package/dist/llm/tool_context.test.cjs +162 -0
  157. package/dist/llm/tool_context.test.cjs.map +1 -0
  158. package/dist/llm/tool_context.test.js +161 -0
  159. package/dist/llm/tool_context.test.js.map +1 -0
  160. package/dist/llm/tool_context.type.test.cjs +92 -0
  161. package/dist/llm/tool_context.type.test.cjs.map +1 -0
  162. package/dist/llm/tool_context.type.test.js +91 -0
  163. package/dist/llm/tool_context.type.test.js.map +1 -0
  164. package/dist/llm/utils.cjs +260 -0
  165. package/dist/llm/utils.cjs.map +1 -0
  166. package/dist/llm/utils.d.cts +42 -0
  167. package/dist/llm/utils.d.ts +42 -0
  168. package/dist/llm/utils.d.ts.map +1 -0
  169. package/dist/llm/utils.js +223 -0
  170. package/dist/llm/utils.js.map +1 -0
  171. package/dist/llm/utils.test.cjs +513 -0
  172. package/dist/llm/utils.test.cjs.map +1 -0
  173. package/dist/llm/utils.test.js +490 -0
  174. package/dist/llm/utils.test.js.map +1 -0
  175. package/dist/metrics/base.cjs +0 -27
  176. package/dist/metrics/base.cjs.map +1 -1
  177. package/dist/metrics/base.d.cts +105 -63
  178. package/dist/metrics/base.d.ts +105 -63
  179. package/dist/metrics/base.d.ts.map +1 -1
  180. package/dist/metrics/base.js +0 -19
  181. package/dist/metrics/base.js.map +1 -1
  182. package/dist/metrics/index.cjs +0 -3
  183. package/dist/metrics/index.cjs.map +1 -1
  184. package/dist/metrics/index.d.cts +2 -3
  185. package/dist/metrics/index.d.ts +2 -3
  186. package/dist/metrics/index.d.ts.map +1 -1
  187. package/dist/metrics/index.js +0 -2
  188. package/dist/metrics/index.js.map +1 -1
  189. package/dist/metrics/usage_collector.cjs +17 -12
  190. package/dist/metrics/usage_collector.cjs.map +1 -1
  191. package/dist/metrics/usage_collector.d.cts +3 -2
  192. package/dist/metrics/usage_collector.d.ts +3 -2
  193. package/dist/metrics/usage_collector.d.ts.map +1 -1
  194. package/dist/metrics/usage_collector.js +17 -12
  195. package/dist/metrics/usage_collector.js.map +1 -1
  196. package/dist/metrics/utils.cjs +22 -59
  197. package/dist/metrics/utils.cjs.map +1 -1
  198. package/dist/metrics/utils.d.cts +1 -8
  199. package/dist/metrics/utils.d.ts +1 -8
  200. package/dist/metrics/utils.d.ts.map +1 -1
  201. package/dist/metrics/utils.js +22 -52
  202. package/dist/metrics/utils.js.map +1 -1
  203. package/dist/multimodal/index.cjs +0 -2
  204. package/dist/multimodal/index.cjs.map +1 -1
  205. package/dist/multimodal/index.d.cts +0 -1
  206. package/dist/multimodal/index.d.ts +0 -1
  207. package/dist/multimodal/index.d.ts.map +1 -1
  208. package/dist/multimodal/index.js +0 -1
  209. package/dist/multimodal/index.js.map +1 -1
  210. package/dist/plugin.cjs +24 -8
  211. package/dist/plugin.cjs.map +1 -1
  212. package/dist/plugin.d.cts +18 -4
  213. package/dist/plugin.d.ts +18 -4
  214. package/dist/plugin.d.ts.map +1 -1
  215. package/dist/plugin.js +22 -7
  216. package/dist/plugin.js.map +1 -1
  217. package/dist/stream/deferred_stream.cjs +98 -0
  218. package/dist/stream/deferred_stream.cjs.map +1 -0
  219. package/dist/stream/deferred_stream.d.cts +27 -0
  220. package/dist/stream/deferred_stream.d.ts +27 -0
  221. package/dist/stream/deferred_stream.d.ts.map +1 -0
  222. package/dist/stream/deferred_stream.js +73 -0
  223. package/dist/stream/deferred_stream.js.map +1 -0
  224. package/dist/stream/deferred_stream.test.cjs +527 -0
  225. package/dist/stream/deferred_stream.test.cjs.map +1 -0
  226. package/dist/stream/deferred_stream.test.js +526 -0
  227. package/dist/stream/deferred_stream.test.js.map +1 -0
  228. package/dist/stream/identity_transform.cjs +42 -0
  229. package/dist/stream/identity_transform.cjs.map +1 -0
  230. package/dist/stream/identity_transform.d.cts +6 -0
  231. package/dist/stream/identity_transform.d.ts +6 -0
  232. package/dist/stream/identity_transform.d.ts.map +1 -0
  233. package/dist/stream/identity_transform.js +18 -0
  234. package/dist/stream/identity_transform.js.map +1 -0
  235. package/dist/stream/identity_transform.test.cjs +125 -0
  236. package/dist/stream/identity_transform.test.cjs.map +1 -0
  237. package/dist/stream/identity_transform.test.js +124 -0
  238. package/dist/stream/identity_transform.test.js.map +1 -0
  239. package/dist/stream/index.cjs +38 -0
  240. package/dist/stream/index.cjs.map +1 -0
  241. package/dist/stream/index.d.cts +5 -0
  242. package/dist/stream/index.d.ts +5 -0
  243. package/dist/stream/index.d.ts.map +1 -0
  244. package/dist/stream/index.js +11 -0
  245. package/dist/stream/index.js.map +1 -0
  246. package/dist/stream/merge_readable_streams.cjs +59 -0
  247. package/dist/stream/merge_readable_streams.cjs.map +1 -0
  248. package/dist/stream/merge_readable_streams.d.cts +4 -0
  249. package/dist/stream/merge_readable_streams.d.ts +4 -0
  250. package/dist/stream/merge_readable_streams.d.ts.map +1 -0
  251. package/dist/stream/merge_readable_streams.js +35 -0
  252. package/dist/stream/merge_readable_streams.js.map +1 -0
  253. package/dist/stream/stream_channel.cjs +47 -0
  254. package/dist/stream/stream_channel.cjs.map +1 -0
  255. package/dist/stream/stream_channel.d.cts +9 -0
  256. package/dist/stream/stream_channel.d.ts +9 -0
  257. package/dist/stream/stream_channel.d.ts.map +1 -0
  258. package/dist/stream/stream_channel.js +23 -0
  259. package/dist/stream/stream_channel.js.map +1 -0
  260. package/dist/stream/stream_channel.test.cjs +97 -0
  261. package/dist/stream/stream_channel.test.cjs.map +1 -0
  262. package/dist/stream/stream_channel.test.js +96 -0
  263. package/dist/stream/stream_channel.test.js.map +1 -0
  264. package/dist/stt/stream_adapter.cjs +3 -4
  265. package/dist/stt/stream_adapter.cjs.map +1 -1
  266. package/dist/stt/stream_adapter.d.cts +1 -0
  267. package/dist/stt/stream_adapter.d.ts +1 -0
  268. package/dist/stt/stream_adapter.d.ts.map +1 -1
  269. package/dist/stt/stream_adapter.js +3 -4
  270. package/dist/stt/stream_adapter.js.map +1 -1
  271. package/dist/stt/stt.cjs +101 -10
  272. package/dist/stt/stt.cjs.map +1 -1
  273. package/dist/stt/stt.d.cts +26 -5
  274. package/dist/stt/stt.d.ts +26 -5
  275. package/dist/stt/stt.d.ts.map +1 -1
  276. package/dist/stt/stt.js +102 -11
  277. package/dist/stt/stt.js.map +1 -1
  278. package/dist/tokenize/basic/basic.cjs +10 -5
  279. package/dist/tokenize/basic/basic.cjs.map +1 -1
  280. package/dist/tokenize/basic/basic.d.cts +7 -1
  281. package/dist/tokenize/basic/basic.d.ts +7 -1
  282. package/dist/tokenize/basic/basic.d.ts.map +1 -1
  283. package/dist/tokenize/basic/basic.js +10 -5
  284. package/dist/tokenize/basic/basic.js.map +1 -1
  285. package/dist/tokenize/basic/sentence.cjs +14 -6
  286. package/dist/tokenize/basic/sentence.cjs.map +1 -1
  287. package/dist/tokenize/basic/sentence.d.cts +1 -1
  288. package/dist/tokenize/basic/sentence.d.ts +1 -1
  289. package/dist/tokenize/basic/sentence.d.ts.map +1 -1
  290. package/dist/tokenize/basic/sentence.js +14 -6
  291. package/dist/tokenize/basic/sentence.js.map +1 -1
  292. package/dist/tokenize/token_stream.cjs +5 -3
  293. package/dist/tokenize/token_stream.cjs.map +1 -1
  294. package/dist/tokenize/token_stream.d.cts +1 -0
  295. package/dist/tokenize/token_stream.d.ts +1 -0
  296. package/dist/tokenize/token_stream.d.ts.map +1 -1
  297. package/dist/tokenize/token_stream.js +6 -4
  298. package/dist/tokenize/token_stream.js.map +1 -1
  299. package/dist/transcription.cjs +1 -2
  300. package/dist/transcription.cjs.map +1 -1
  301. package/dist/transcription.d.ts.map +1 -1
  302. package/dist/transcription.js +2 -3
  303. package/dist/transcription.js.map +1 -1
  304. package/dist/tts/index.cjs +2 -4
  305. package/dist/tts/index.cjs.map +1 -1
  306. package/dist/tts/index.d.cts +1 -1
  307. package/dist/tts/index.d.ts +1 -1
  308. package/dist/tts/index.d.ts.map +1 -1
  309. package/dist/tts/index.js +1 -3
  310. package/dist/tts/index.js.map +1 -1
  311. package/dist/tts/stream_adapter.cjs +26 -13
  312. package/dist/tts/stream_adapter.cjs.map +1 -1
  313. package/dist/tts/stream_adapter.d.cts +1 -1
  314. package/dist/tts/stream_adapter.d.ts +1 -1
  315. package/dist/tts/stream_adapter.d.ts.map +1 -1
  316. package/dist/tts/stream_adapter.js +27 -14
  317. package/dist/tts/stream_adapter.js.map +1 -1
  318. package/dist/tts/tts.cjs +157 -25
  319. package/dist/tts/tts.cjs.map +1 -1
  320. package/dist/tts/tts.d.cts +29 -5
  321. package/dist/tts/tts.d.ts +29 -5
  322. package/dist/tts/tts.d.ts.map +1 -1
  323. package/dist/tts/tts.js +157 -24
  324. package/dist/tts/tts.js.map +1 -1
  325. package/dist/types.cjs +60 -0
  326. package/dist/types.cjs.map +1 -0
  327. package/dist/types.d.cts +13 -0
  328. package/dist/types.d.ts +13 -0
  329. package/dist/types.d.ts.map +1 -0
  330. package/dist/types.js +35 -0
  331. package/dist/types.js.map +1 -0
  332. package/dist/utils.cjs +281 -27
  333. package/dist/utils.cjs.map +1 -1
  334. package/dist/utils.d.cts +134 -9
  335. package/dist/utils.d.ts +134 -9
  336. package/dist/utils.d.ts.map +1 -1
  337. package/dist/utils.js +265 -26
  338. package/dist/utils.js.map +1 -1
  339. package/dist/utils.test.cjs +492 -0
  340. package/dist/utils.test.cjs.map +1 -0
  341. package/dist/utils.test.js +498 -0
  342. package/dist/utils.test.js.map +1 -0
  343. package/dist/vad.cjs +76 -20
  344. package/dist/vad.cjs.map +1 -1
  345. package/dist/vad.d.cts +25 -5
  346. package/dist/vad.d.ts +25 -5
  347. package/dist/vad.d.ts.map +1 -1
  348. package/dist/vad.js +76 -20
  349. package/dist/vad.js.map +1 -1
  350. package/dist/voice/agent.cjs +245 -0
  351. package/dist/voice/agent.cjs.map +1 -0
  352. package/dist/voice/agent.d.cts +78 -0
  353. package/dist/voice/agent.d.ts +78 -0
  354. package/dist/voice/agent.d.ts.map +1 -0
  355. package/dist/voice/agent.js +220 -0
  356. package/dist/voice/agent.js.map +1 -0
  357. package/dist/voice/agent.test.cjs +61 -0
  358. package/dist/voice/agent.test.cjs.map +1 -0
  359. package/dist/voice/agent.test.js +60 -0
  360. package/dist/voice/agent.test.js.map +1 -0
  361. package/dist/voice/agent_activity.cjs +1453 -0
  362. package/dist/voice/agent_activity.cjs.map +1 -0
  363. package/dist/voice/agent_activity.d.cts +94 -0
  364. package/dist/voice/agent_activity.d.ts +94 -0
  365. package/dist/voice/agent_activity.d.ts.map +1 -0
  366. package/dist/voice/agent_activity.js +1449 -0
  367. package/dist/voice/agent_activity.js.map +1 -0
  368. package/dist/voice/agent_session.cjs +312 -0
  369. package/dist/voice/agent_session.cjs.map +1 -0
  370. package/dist/voice/agent_session.d.cts +121 -0
  371. package/dist/voice/agent_session.d.ts +121 -0
  372. package/dist/voice/agent_session.d.ts.map +1 -0
  373. package/dist/voice/agent_session.js +295 -0
  374. package/dist/voice/agent_session.js.map +1 -0
  375. package/dist/voice/audio_recognition.cjs +375 -0
  376. package/dist/voice/audio_recognition.cjs.map +1 -0
  377. package/dist/voice/audio_recognition.d.cts +80 -0
  378. package/dist/voice/audio_recognition.d.ts +80 -0
  379. package/dist/voice/audio_recognition.d.ts.map +1 -0
  380. package/dist/voice/audio_recognition.js +351 -0
  381. package/dist/voice/audio_recognition.js.map +1 -0
  382. package/dist/voice/events.cjs +145 -0
  383. package/dist/voice/events.cjs.map +1 -0
  384. package/dist/voice/events.d.cts +124 -0
  385. package/dist/voice/events.d.ts +124 -0
  386. package/dist/voice/events.d.ts.map +1 -0
  387. package/dist/voice/events.js +110 -0
  388. package/dist/voice/events.js.map +1 -0
  389. package/dist/voice/generation.cjs +700 -0
  390. package/dist/voice/generation.cjs.map +1 -0
  391. package/dist/voice/generation.d.cts +115 -0
  392. package/dist/voice/generation.d.ts +115 -0
  393. package/dist/voice/generation.d.ts.map +1 -0
  394. package/dist/voice/generation.js +672 -0
  395. package/dist/voice/generation.js.map +1 -0
  396. package/dist/voice/index.cjs +40 -0
  397. package/dist/voice/index.cjs.map +1 -0
  398. package/dist/voice/index.d.cts +5 -0
  399. package/dist/voice/index.d.ts +5 -0
  400. package/dist/voice/index.d.ts.map +1 -0
  401. package/dist/voice/index.js +11 -0
  402. package/dist/voice/index.js.map +1 -0
  403. package/dist/voice/io.cjs +245 -0
  404. package/dist/voice/io.cjs.map +1 -0
  405. package/dist/voice/io.d.cts +101 -0
  406. package/dist/voice/io.d.ts +101 -0
  407. package/dist/voice/io.d.ts.map +1 -0
  408. package/dist/voice/io.js +217 -0
  409. package/dist/voice/io.js.map +1 -0
  410. package/dist/voice/room_io/_input.cjs +121 -0
  411. package/dist/voice/room_io/_input.cjs.map +1 -0
  412. package/dist/voice/room_io/_input.d.cts +24 -0
  413. package/dist/voice/room_io/_input.d.ts +24 -0
  414. package/dist/voice/room_io/_input.d.ts.map +1 -0
  415. package/dist/voice/room_io/_input.js +102 -0
  416. package/dist/voice/room_io/_input.js.map +1 -0
  417. package/dist/voice/room_io/_output.cjs +358 -0
  418. package/dist/voice/room_io/_output.cjs.map +1 -0
  419. package/dist/voice/room_io/_output.d.cts +75 -0
  420. package/dist/voice/room_io/_output.d.ts +75 -0
  421. package/dist/voice/room_io/_output.d.ts.map +1 -0
  422. package/dist/voice/room_io/_output.js +342 -0
  423. package/dist/voice/room_io/_output.js.map +1 -0
  424. package/dist/voice/room_io/index.cjs +25 -0
  425. package/dist/voice/room_io/index.cjs.map +1 -0
  426. package/dist/voice/room_io/index.d.cts +3 -0
  427. package/dist/voice/room_io/index.d.ts +3 -0
  428. package/dist/voice/room_io/index.d.ts.map +1 -0
  429. package/dist/voice/room_io/index.js +3 -0
  430. package/dist/voice/room_io/index.js.map +1 -0
  431. package/dist/voice/room_io/room_io.cjs +370 -0
  432. package/dist/voice/room_io/room_io.cjs.map +1 -0
  433. package/dist/voice/room_io/room_io.d.cts +73 -0
  434. package/dist/voice/room_io/room_io.d.ts +73 -0
  435. package/dist/voice/room_io/room_io.d.ts.map +1 -0
  436. package/dist/voice/room_io/room_io.js +361 -0
  437. package/dist/voice/room_io/room_io.js.map +1 -0
  438. package/dist/{pipeline/index.cjs → voice/run_context.cjs} +16 -11
  439. package/dist/voice/run_context.cjs.map +1 -0
  440. package/dist/voice/run_context.d.cts +12 -0
  441. package/dist/voice/run_context.d.ts +12 -0
  442. package/dist/voice/run_context.d.ts.map +1 -0
  443. package/dist/voice/run_context.js +14 -0
  444. package/dist/voice/run_context.js.map +1 -0
  445. package/dist/voice/speech_handle.cjs +105 -0
  446. package/dist/voice/speech_handle.cjs.map +1 -0
  447. package/dist/voice/speech_handle.d.cts +46 -0
  448. package/dist/voice/speech_handle.d.ts +46 -0
  449. package/dist/voice/speech_handle.d.ts.map +1 -0
  450. package/dist/voice/speech_handle.js +81 -0
  451. package/dist/voice/speech_handle.js.map +1 -0
  452. package/dist/voice/transcription/_utils.cjs +45 -0
  453. package/dist/voice/transcription/_utils.cjs.map +1 -0
  454. package/dist/voice/transcription/_utils.d.cts +3 -0
  455. package/dist/voice/transcription/_utils.d.ts +3 -0
  456. package/dist/voice/transcription/_utils.d.ts.map +1 -0
  457. package/dist/voice/transcription/_utils.js +21 -0
  458. package/dist/voice/transcription/_utils.js.map +1 -0
  459. package/dist/voice/transcription/index.cjs +23 -0
  460. package/dist/voice/transcription/index.cjs.map +1 -0
  461. package/dist/voice/transcription/index.d.cts +2 -0
  462. package/dist/voice/transcription/index.d.ts +2 -0
  463. package/dist/voice/transcription/index.d.ts.map +1 -0
  464. package/dist/voice/transcription/index.js +2 -0
  465. package/dist/voice/transcription/index.js.map +1 -0
  466. package/dist/voice/transcription/synchronizer.cjs +380 -0
  467. package/dist/voice/transcription/synchronizer.cjs.map +1 -0
  468. package/dist/voice/transcription/synchronizer.d.cts +86 -0
  469. package/dist/voice/transcription/synchronizer.d.ts +86 -0
  470. package/dist/voice/transcription/synchronizer.d.ts.map +1 -0
  471. package/dist/voice/transcription/synchronizer.js +355 -0
  472. package/dist/voice/transcription/synchronizer.js.map +1 -0
  473. package/dist/worker.cjs +22 -4
  474. package/dist/worker.cjs.map +1 -1
  475. package/dist/worker.d.cts +1 -1
  476. package/dist/worker.d.ts +1 -1
  477. package/dist/worker.d.ts.map +1 -1
  478. package/dist/worker.js +22 -4
  479. package/dist/worker.js.map +1 -1
  480. package/package.json +9 -2
  481. package/src/_exceptions.ts +137 -0
  482. package/src/audio.ts +12 -1
  483. package/src/cli.ts +37 -0
  484. package/src/constants.ts +2 -1
  485. package/src/http_server.ts +1 -0
  486. package/src/index.ts +13 -10
  487. package/src/inference_runner.ts +2 -3
  488. package/src/ipc/inference_proc_executor.ts +2 -2
  489. package/src/ipc/job_executor.ts +1 -1
  490. package/src/ipc/job_proc_executor.ts +1 -1
  491. package/src/ipc/job_proc_lazy_main.ts +1 -1
  492. package/src/job.ts +18 -0
  493. package/src/llm/__snapshots__/chat_context.test.ts.snap +527 -0
  494. package/src/llm/__snapshots__/tool_context.test.ts.snap +177 -0
  495. package/src/llm/__snapshots__/utils.test.ts.snap +65 -0
  496. package/src/llm/chat_context.test.ts +450 -0
  497. package/src/llm/chat_context.ts +501 -103
  498. package/src/llm/index.ts +53 -18
  499. package/src/llm/llm.ts +149 -50
  500. package/src/llm/provider_format/google.test.ts +772 -0
  501. package/src/llm/provider_format/google.ts +130 -0
  502. package/src/llm/provider_format/index.ts +23 -0
  503. package/src/llm/provider_format/openai.test.ts +581 -0
  504. package/src/llm/provider_format/openai.ts +118 -0
  505. package/src/llm/provider_format/utils.ts +183 -0
  506. package/src/llm/realtime.ts +151 -0
  507. package/src/llm/remote_chat_context.test.ts +290 -0
  508. package/src/llm/remote_chat_context.ts +114 -0
  509. package/src/llm/tool_context.test.ts +198 -0
  510. package/src/llm/tool_context.ts +259 -0
  511. package/src/llm/tool_context.type.test.ts +115 -0
  512. package/src/llm/utils.test.ts +670 -0
  513. package/src/llm/utils.ts +324 -0
  514. package/src/metrics/base.ts +110 -78
  515. package/src/metrics/index.ts +3 -9
  516. package/src/metrics/usage_collector.ts +19 -13
  517. package/src/metrics/utils.ts +24 -69
  518. package/src/multimodal/index.ts +0 -1
  519. package/src/plugin.ts +26 -8
  520. package/src/stream/deferred_stream.test.ts +755 -0
  521. package/src/stream/deferred_stream.ts +110 -0
  522. package/src/stream/identity_transform.test.ts +179 -0
  523. package/src/stream/identity_transform.ts +18 -0
  524. package/src/stream/index.ts +7 -0
  525. package/src/stream/merge_readable_streams.ts +40 -0
  526. package/src/stream/stream_channel.test.ts +129 -0
  527. package/src/stream/stream_channel.ts +32 -0
  528. package/src/stt/stream_adapter.ts +3 -5
  529. package/src/stt/stt.ts +135 -17
  530. package/src/tokenize/basic/basic.ts +13 -5
  531. package/src/tokenize/basic/sentence.ts +20 -6
  532. package/src/tokenize/token_stream.ts +7 -4
  533. package/src/transcription.ts +2 -3
  534. package/src/tts/index.ts +0 -1
  535. package/src/tts/stream_adapter.ts +42 -16
  536. package/src/tts/tts.ts +203 -21
  537. package/src/types.ts +42 -0
  538. package/src/utils.test.ts +658 -0
  539. package/src/utils.ts +375 -44
  540. package/src/vad.ts +90 -22
  541. package/src/voice/agent.test.ts +80 -0
  542. package/src/voice/agent.ts +332 -0
  543. package/src/voice/agent_activity.ts +1913 -0
  544. package/src/voice/agent_session.ts +460 -0
  545. package/src/voice/audio_recognition.ts +474 -0
  546. package/src/voice/events.ts +252 -0
  547. package/src/voice/generation.ts +881 -0
  548. package/src/voice/index.ts +7 -0
  549. package/src/voice/io.ts +304 -0
  550. package/src/voice/room_io/_input.ts +144 -0
  551. package/src/voice/room_io/_output.ts +436 -0
  552. package/src/voice/room_io/index.ts +5 -0
  553. package/src/voice/room_io/room_io.ts +495 -0
  554. package/src/voice/run_context.ts +20 -0
  555. package/src/voice/speech_handle.ts +104 -0
  556. package/src/voice/transcription/_utils.ts +25 -0
  557. package/src/voice/transcription/index.ts +4 -0
  558. package/src/voice/transcription/synchronizer.ts +478 -0
  559. package/src/worker.ts +22 -2
  560. package/dist/llm/function_context.cjs +0 -103
  561. package/dist/llm/function_context.cjs.map +0 -1
  562. package/dist/llm/function_context.d.cts +0 -47
  563. package/dist/llm/function_context.d.ts +0 -47
  564. package/dist/llm/function_context.d.ts.map +0 -1
  565. package/dist/llm/function_context.js +0 -78
  566. package/dist/llm/function_context.js.map +0 -1
  567. package/dist/llm/function_context.test.cjs +0 -218
  568. package/dist/llm/function_context.test.cjs.map +0 -1
  569. package/dist/llm/function_context.test.js +0 -217
  570. package/dist/llm/function_context.test.js.map +0 -1
  571. package/dist/multimodal/multimodal_agent.cjs +0 -486
  572. package/dist/multimodal/multimodal_agent.cjs.map +0 -1
  573. package/dist/multimodal/multimodal_agent.d.cts +0 -48
  574. package/dist/multimodal/multimodal_agent.d.ts +0 -48
  575. package/dist/multimodal/multimodal_agent.d.ts.map +0 -1
  576. package/dist/multimodal/multimodal_agent.js +0 -461
  577. package/dist/multimodal/multimodal_agent.js.map +0 -1
  578. package/dist/pipeline/agent_output.cjs +0 -197
  579. package/dist/pipeline/agent_output.cjs.map +0 -1
  580. package/dist/pipeline/agent_output.d.cts +0 -33
  581. package/dist/pipeline/agent_output.d.ts +0 -33
  582. package/dist/pipeline/agent_output.d.ts.map +0 -1
  583. package/dist/pipeline/agent_output.js +0 -172
  584. package/dist/pipeline/agent_output.js.map +0 -1
  585. package/dist/pipeline/agent_playout.cjs +0 -175
  586. package/dist/pipeline/agent_playout.cjs.map +0 -1
  587. package/dist/pipeline/agent_playout.d.cts +0 -40
  588. package/dist/pipeline/agent_playout.d.ts +0 -40
  589. package/dist/pipeline/agent_playout.d.ts.map +0 -1
  590. package/dist/pipeline/agent_playout.js +0 -139
  591. package/dist/pipeline/agent_playout.js.map +0 -1
  592. package/dist/pipeline/human_input.cjs +0 -171
  593. package/dist/pipeline/human_input.cjs.map +0 -1
  594. package/dist/pipeline/human_input.d.cts +0 -30
  595. package/dist/pipeline/human_input.d.ts +0 -30
  596. package/dist/pipeline/human_input.d.ts.map +0 -1
  597. package/dist/pipeline/human_input.js +0 -146
  598. package/dist/pipeline/human_input.js.map +0 -1
  599. package/dist/pipeline/index.cjs.map +0 -1
  600. package/dist/pipeline/index.d.cts +0 -2
  601. package/dist/pipeline/index.d.ts +0 -2
  602. package/dist/pipeline/index.d.ts.map +0 -1
  603. package/dist/pipeline/index.js +0 -11
  604. package/dist/pipeline/index.js.map +0 -1
  605. package/dist/pipeline/pipeline_agent.cjs +0 -859
  606. package/dist/pipeline/pipeline_agent.cjs.map +0 -1
  607. package/dist/pipeline/pipeline_agent.d.cts +0 -150
  608. package/dist/pipeline/pipeline_agent.d.ts +0 -150
  609. package/dist/pipeline/pipeline_agent.d.ts.map +0 -1
  610. package/dist/pipeline/pipeline_agent.js +0 -837
  611. package/dist/pipeline/pipeline_agent.js.map +0 -1
  612. package/dist/pipeline/speech_handle.cjs +0 -176
  613. package/dist/pipeline/speech_handle.cjs.map +0 -1
  614. package/dist/pipeline/speech_handle.d.cts +0 -37
  615. package/dist/pipeline/speech_handle.d.ts +0 -37
  616. package/dist/pipeline/speech_handle.d.ts.map +0 -1
  617. package/dist/pipeline/speech_handle.js +0 -152
  618. package/dist/pipeline/speech_handle.js.map +0 -1
  619. package/src/llm/function_context.test.ts +0 -248
  620. package/src/llm/function_context.ts +0 -142
  621. package/src/multimodal/multimodal_agent.ts +0 -592
  622. package/src/pipeline/agent_output.ts +0 -219
  623. package/src/pipeline/agent_playout.ts +0 -192
  624. package/src/pipeline/human_input.ts +0 -188
  625. package/src/pipeline/index.ts +0 -15
  626. package/src/pipeline/pipeline_agent.ts +0 -1197
  627. package/src/pipeline/speech_handle.ts +0 -201
package/src/utils.ts CHANGED
@@ -1,22 +1,29 @@
1
1
  // SPDX-FileCopyrightText: 2024 LiveKit, Inc.
2
2
  //
3
3
  // SPDX-License-Identifier: Apache-2.0
4
- import type {
5
- LocalParticipant,
6
- RemoteParticipant,
7
- Room,
8
- TrackPublication,
9
- } from '@livekit/rtc-node';
10
- import { AudioFrame, TrackSource } from '@livekit/rtc-node';
4
+ import { AudioFrame, AudioResampler } from '@livekit/rtc-node';
5
+ import { delay } from '@std/async';
11
6
  import { EventEmitter, once } from 'node:events';
7
+ import type { ReadableStream } from 'node:stream/web';
8
+ import { TransformStream, type TransformStreamDefaultController } from 'node:stream/web';
9
+ import { v4 as uuidv4 } from 'uuid';
10
+ import { log } from './log.js';
12
11
 
13
12
  /** Union of a single and a list of {@link AudioFrame}s */
14
13
  export type AudioBuffer = AudioFrame[] | AudioFrame;
15
14
 
15
+ export const noop = () => {};
16
+
17
+ export const isPending = async (promise: Promise<unknown>): Promise<boolean> => {
18
+ const sentinel = Symbol('sentinel');
19
+ const result = await Promise.race([promise, Promise.resolve(sentinel)]);
20
+ return result === sentinel;
21
+ };
22
+
16
23
  /**
17
24
  * Merge one or more {@link AudioFrame}s into a single one.
18
25
  *
19
- * @param buffer Either an {@link AudioFrame} or a list thereof
26
+ * @param buffer - Either an {@link AudioFrame} or a list thereof
20
27
  * @throws
21
28
  * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError
22
29
  * | TypeError} if sample rate or channel count are mismatched
@@ -52,33 +59,6 @@ export const mergeFrames = (buffer: AudioBuffer): AudioFrame => {
52
59
  return buffer;
53
60
  };
54
61
 
55
- export const findMicroTrackId = (room: Room, identity: string): string => {
56
- let p: RemoteParticipant | LocalParticipant | undefined = room.remoteParticipants.get(identity);
57
-
58
- if (identity === room.localParticipant?.identity) {
59
- p = room.localParticipant;
60
- }
61
-
62
- if (!p) {
63
- throw new Error(`participant ${identity} not found`);
64
- }
65
-
66
- // find first micro track
67
- let trackId: string | undefined;
68
- p.trackPublications.forEach((track: TrackPublication) => {
69
- if (track.source === TrackSource.SOURCE_MICROPHONE) {
70
- trackId = track.sid;
71
- return;
72
- }
73
- });
74
-
75
- if (!trackId) {
76
- throw new Error(`participant ${identity} does not have a microphone track`);
77
- }
78
-
79
- return trackId;
80
- };
81
-
82
62
  /** @internal */
83
63
  export class Queue<T> {
84
64
  /** @internal */
@@ -117,14 +97,14 @@ export class Queue<T> {
117
97
  }
118
98
 
119
99
  /** @internal */
120
- export class Future {
121
- #await: Promise<void>;
122
- #resolvePromise!: () => void;
100
+ export class Future<T = void> {
101
+ #await: Promise<T>;
102
+ #resolvePromise!: (value: T) => void;
123
103
  #rejectPromise!: (error: Error) => void;
124
104
  #done: boolean = false;
125
105
 
126
106
  constructor() {
127
- this.#await = new Promise<void>((resolve, reject) => {
107
+ this.#await = new Promise<T>((resolve, reject) => {
128
108
  this.#resolvePromise = resolve;
129
109
  this.#rejectPromise = reject;
130
110
  });
@@ -138,9 +118,9 @@ export class Future {
138
118
  return this.#done;
139
119
  }
140
120
 
141
- resolve() {
121
+ resolve(value: T) {
142
122
  this.#done = true;
143
- this.#resolvePromise();
123
+ this.#resolvePromise(value);
144
124
  }
145
125
 
146
126
  reject(error: Error) {
@@ -149,6 +129,48 @@ export class Future {
149
129
  }
150
130
  }
151
131
 
132
+ /** @internal */
133
+ export class Event {
134
+ #isSet = false;
135
+ #waiters: Array<() => void> = [];
136
+
137
+ async wait() {
138
+ if (this.#isSet) return true;
139
+
140
+ let resolve: () => void = noop;
141
+ const waiter = new Promise<void>((r) => {
142
+ resolve = r;
143
+ this.#waiters.push(resolve);
144
+ });
145
+
146
+ try {
147
+ await waiter;
148
+ return true;
149
+ } finally {
150
+ const index = this.#waiters.indexOf(resolve);
151
+ if (index !== -1) {
152
+ this.#waiters.splice(index, 1);
153
+ }
154
+ }
155
+ }
156
+
157
+ get isSet(): boolean {
158
+ return this.#isSet;
159
+ }
160
+
161
+ set(): void {
162
+ if (this.#isSet) return;
163
+
164
+ this.#isSet = true;
165
+ this.#waiters.forEach((resolve) => resolve());
166
+ this.#waiters = [];
167
+ }
168
+
169
+ clear(): void {
170
+ this.#isSet = false;
171
+ }
172
+ }
173
+
152
174
  /** @internal */
153
175
  export class CancellablePromise<T> {
154
176
  #promise: Promise<T>;
@@ -159,7 +181,7 @@ export class CancellablePromise<T> {
159
181
  constructor(
160
182
  executor: (
161
183
  resolve: (value: T | PromiseLike<T>) => void,
162
- reject: (reason?: any) => void,
184
+ reject: (reason?: unknown) => void,
163
185
  onCancel: (cancelFn: () => void) => void,
164
186
  ) => void,
165
187
  ) {
@@ -194,13 +216,13 @@ export class CancellablePromise<T> {
194
216
 
195
217
  then<TResult1 = T, TResult2 = never>(
196
218
  onfulfilled?: ((value: T) => TResult1 | Promise<TResult1>) | null,
197
- onrejected?: ((reason: any) => TResult2 | Promise<TResult2>) | null,
219
+ onrejected?: ((reason: unknown) => TResult2 | Promise<TResult2>) | null,
198
220
  ): Promise<TResult1 | TResult2> {
199
221
  return this.#promise.then(onfulfilled, onrejected);
200
222
  }
201
223
 
202
224
  catch<TResult = never>(
203
- onrejected?: ((reason: any) => TResult | Promise<TResult>) | null,
225
+ onrejected?: ((reason: unknown) => TResult | Promise<TResult>) | null,
204
226
  ): Promise<T | TResult> {
205
227
  return this.#promise.catch(onrejected);
206
228
  }
@@ -339,3 +361,312 @@ export class AudioEnergyFilter {
339
361
  return false;
340
362
  }
341
363
  }
364
+
365
+ export const TASK_TIMEOUT_ERROR = new Error('Task cancellation timed out');
366
+
367
+ export enum TaskResult {
368
+ Timeout = 'timeout',
369
+ Completed = 'completed',
370
+ Aborted = 'aborted',
371
+ }
372
+
373
+ /** @internal */
374
+ /**
375
+ * A task that can be cancelled.
376
+ *
377
+ * We recommend using the `Task.from` method to create a task. When creating subtasks, pass the same controller to all subtasks.
378
+ *
379
+ * @example
380
+ * ```ts
381
+ * const parent = Task.from((controller) => {
382
+ * const child1 = Task.from(() => { ... }, controller);
383
+ * const child2 = Task.from(() => { ... }, controller);
384
+ * });
385
+ * parent.cancel();
386
+ * ```
387
+ *
388
+ * This will cancel all subtasks when the parent is cancelled.
389
+ *
390
+ * @param T - The type of the task result
391
+ */
392
+ export class Task<T> {
393
+ private resultFuture: Future<T>;
394
+
395
+ #logger = log();
396
+
397
+ constructor(
398
+ private readonly fn: (controller: AbortController) => Promise<T>,
399
+ private readonly controller: AbortController,
400
+ readonly name?: string,
401
+ ) {
402
+ this.resultFuture = new Future();
403
+ this.runTask();
404
+ }
405
+
406
+ /**
407
+ * Creates a new task from a function.
408
+ *
409
+ * @param fn - The function to run
410
+ * @param controller - The abort controller to use
411
+ * @returns A new task
412
+ */
413
+ static from<T>(
414
+ fn: (controller: AbortController) => Promise<T>,
415
+ controller?: AbortController,
416
+ name?: string,
417
+ ) {
418
+ const abortController = controller ?? new AbortController();
419
+ return new Task(fn, abortController, name);
420
+ }
421
+
422
+ private async runTask() {
423
+ const run = async () => {
424
+ if (this.name) {
425
+ this.#logger.debug(`Task.runTask: task ${this.name} started`);
426
+ }
427
+ return await this.fn(this.controller);
428
+ };
429
+
430
+ return run()
431
+ .then((value) => {
432
+ this.resultFuture.resolve(value);
433
+ return value;
434
+ })
435
+ .catch((error) => {
436
+ this.resultFuture.reject(error);
437
+ })
438
+ .finally(() => {
439
+ if (this.name) {
440
+ this.#logger.debug(`Task.runTask: task ${this.name} done`);
441
+ }
442
+ });
443
+ }
444
+
445
+ /**
446
+ * Cancels the task.
447
+ */
448
+ cancel() {
449
+ this.controller.abort();
450
+ }
451
+
452
+ /**
453
+ * Cancels the task and waits for it to complete.
454
+ *
455
+ * @param timeout - The timeout in milliseconds
456
+ * @returns The result status of the task (timeout, completed, aborted)
457
+ */
458
+ async cancelAndWait(timeout?: number) {
459
+ this.cancel();
460
+
461
+ try {
462
+ // Race between task completion and timeout
463
+ const promises = [
464
+ this.result
465
+ .then(() => TaskResult.Completed)
466
+ .catch((error) => {
467
+ if (error.name === 'AbortError') {
468
+ return TaskResult.Aborted;
469
+ }
470
+ throw error;
471
+ }),
472
+ ];
473
+
474
+ if (timeout) {
475
+ promises.push(delay(timeout).then(() => TaskResult.Timeout));
476
+ }
477
+
478
+ const result = await Promise.race(promises);
479
+
480
+ // Check what happened
481
+ if (result === TaskResult.Timeout) {
482
+ throw TASK_TIMEOUT_ERROR;
483
+ }
484
+
485
+ return result;
486
+ } catch (error) {
487
+ throw error;
488
+ }
489
+ }
490
+
491
+ /**
492
+ * The result of the task.
493
+ */
494
+ get result(): Promise<T> {
495
+ return this.resultFuture.await;
496
+ }
497
+
498
+ /**
499
+ * Whether the task has completed.
500
+ */
501
+ get done(): boolean {
502
+ return this.resultFuture.done;
503
+ }
504
+ }
505
+
506
+ export async function waitFor(tasks: Task<void>[]): Promise<void> {
507
+ await Promise.allSettled(tasks.map((task) => task.result));
508
+ }
509
+
510
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
511
+ export async function cancelAndWait(tasks: Task<any>[], timeout?: number): Promise<void> {
512
+ await Promise.allSettled(tasks.map((task) => task.cancelAndWait(timeout)));
513
+ }
514
+
515
+ export function withResolvers<T = unknown>() {
516
+ let resolve!: (value: T | PromiseLike<T>) => void;
517
+ let reject!: (reason?: unknown) => void;
518
+
519
+ const promise = new Promise<T>((res, rej) => {
520
+ resolve = res;
521
+ reject = rej;
522
+ });
523
+
524
+ return { promise, resolve, reject };
525
+ }
526
+
527
+ /**
528
+ * Generates a short UUID with a prefix. Mirrors the python agents implementation.
529
+ *
530
+ * @param prefix - The prefix to add to the UUID.
531
+ * @returns A short UUID with the prefix.
532
+ */
533
+ export function shortuuid(prefix: string = ''): string {
534
+ return `${prefix}${uuidv4().slice(0, 12)}`;
535
+ }
536
+
537
+ const READONLY_SYMBOL = Symbol('Readonly');
538
+
539
+ const MUTATION_METHODS = [
540
+ 'push',
541
+ 'pop',
542
+ 'shift',
543
+ 'unshift',
544
+ 'splice',
545
+ 'sort',
546
+ 'reverse',
547
+ 'fill',
548
+ 'copyWithin',
549
+ ] as const;
550
+
551
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
552
+ /**
553
+ * Creates a read-only proxy for an array.
554
+ * @param array - The array to make read-only.
555
+ * @param additionalErrorMessage - An additional error message to include in the error thrown when a mutation method is called.
556
+ * @returns A read-only proxy for the array.
557
+ */
558
+ export function createImmutableArray<T>(array: T[], additionalErrorMessage: string = ''): T[] {
559
+ return new Proxy(array, {
560
+ get(target, key) {
561
+ if (key === READONLY_SYMBOL) {
562
+ return true;
563
+ }
564
+
565
+ // Intercept mutation methods
566
+ if (
567
+ typeof key === 'string' &&
568
+ MUTATION_METHODS.includes(key as (typeof MUTATION_METHODS)[number])
569
+ ) {
570
+ return function () {
571
+ throw new TypeError(
572
+ `Cannot call ${key}() on a read-only array. ${additionalErrorMessage}`.trim(),
573
+ );
574
+ };
575
+ }
576
+
577
+ return Reflect.get(target, key);
578
+ },
579
+ set(_, prop) {
580
+ throw new TypeError(
581
+ `Cannot assign to read-only array index "${String(prop)}". ${additionalErrorMessage}`.trim(),
582
+ );
583
+ },
584
+ deleteProperty(_, prop) {
585
+ throw new TypeError(
586
+ `Cannot delete read-only array index "${String(prop)}". ${additionalErrorMessage}`.trim(),
587
+ );
588
+ },
589
+ defineProperty(_, prop) {
590
+ throw new TypeError(
591
+ `Cannot define property "${String(prop)}" on a read-only array. ${additionalErrorMessage}`.trim(),
592
+ );
593
+ },
594
+ setPrototypeOf() {
595
+ throw new TypeError(
596
+ `Cannot change prototype of a read-only array. ${additionalErrorMessage}`.trim(),
597
+ );
598
+ },
599
+ });
600
+ }
601
+
602
+ export function isImmutableArray(array: unknown): boolean {
603
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
604
+ return typeof array === 'object' && !!(array as any)[READONLY_SYMBOL];
605
+ }
606
+
607
+ /**
608
+ * Resamples an audio stream to a target sample rate.
609
+ *
610
+ * WARINING: The input stream will be locked until the resampled stream is closed.
611
+ *
612
+ * @param stream - The input stream to resample.
613
+ * @param outputRate - The target sample rate.
614
+ * @returns A new stream with the resampled audio.
615
+ */
616
+ export function resampleStream({
617
+ stream,
618
+ outputRate,
619
+ }: {
620
+ stream: ReadableStream<AudioFrame>;
621
+ outputRate: number;
622
+ }): ReadableStream<AudioFrame> {
623
+ let resampler: AudioResampler | null = null;
624
+ const transformStream = new TransformStream<AudioFrame, AudioFrame>({
625
+ transform(chunk: AudioFrame, controller: TransformStreamDefaultController<AudioFrame>) {
626
+ if (!resampler) {
627
+ resampler = new AudioResampler(chunk.sampleRate, outputRate);
628
+ }
629
+ for (const frame of resampler.push(chunk)) {
630
+ controller.enqueue(frame);
631
+ }
632
+ for (const frame of resampler.flush()) {
633
+ controller.enqueue(frame);
634
+ }
635
+ },
636
+ });
637
+ return stream.pipeThrough(transformStream);
638
+ }
639
+
640
+ export class InvalidErrorType extends Error {
641
+ readonly error: unknown;
642
+
643
+ constructor(error: unknown) {
644
+ super(`Expected error, got ${error} (${typeof error})`);
645
+ this.error = error;
646
+ Error.captureStackTrace(this, InvalidErrorType);
647
+ }
648
+ }
649
+
650
+ /**
651
+ * In JS an error can be any arbitrary value.
652
+ * This function converts an unknown error to an Error and stores the original value in the error object.
653
+ *
654
+ * @param error - The error to convert.
655
+ * @returns An Error.
656
+ */
657
+ export function toError(error: unknown): Error {
658
+ if (error instanceof Error) {
659
+ return error;
660
+ }
661
+ throw new InvalidErrorType(error);
662
+ }
663
+
664
+ /**
665
+ * This is a hack to immitate asyncio.create_task so that
666
+ * func will be run after the current event loop iteration.
667
+ *
668
+ * @param func - The function to run.
669
+ */
670
+ export function startSoon(func: () => void) {
671
+ setTimeout(func, 0);
672
+ }
package/src/vad.ts CHANGED
@@ -4,8 +4,15 @@
4
4
  import type { AudioFrame } from '@livekit/rtc-node';
5
5
  import type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';
6
6
  import { EventEmitter } from 'node:events';
7
+ import type {
8
+ ReadableStream,
9
+ ReadableStreamDefaultReader,
10
+ WritableStreamDefaultWriter,
11
+ } from 'node:stream/web';
12
+ import { log } from './log.js';
7
13
  import type { VADMetrics } from './metrics/base.js';
8
- import { AsyncIterableQueue } from './utils.js';
14
+ import { DeferredReadableStream } from './stream/deferred_stream.js';
15
+ import { IdentityTransform } from './stream/identity_transform.js';
9
16
 
10
17
  export enum VADEventType {
11
18
  START_OF_SPEECH,
@@ -53,7 +60,7 @@ export interface VADCapabilities {
53
60
  }
54
61
 
55
62
  export type VADCallbacks = {
56
- [VADEventType.METRICS_COLLECTED]: (metrics: VADMetrics) => void;
63
+ ['metrics_collected']: (metrics: VADMetrics) => void;
57
64
  };
58
65
 
59
66
  export abstract class VAD extends (EventEmitter as new () => TypedEmitter<VADCallbacks>) {
@@ -77,29 +84,75 @@ export abstract class VAD extends (EventEmitter as new () => TypedEmitter<VADCal
77
84
 
78
85
  export abstract class VADStream implements AsyncIterableIterator<VADEvent> {
79
86
  protected static readonly FLUSH_SENTINEL = Symbol('FLUSH_SENTINEL');
80
- protected input = new AsyncIterableQueue<AudioFrame | typeof VADStream.FLUSH_SENTINEL>();
81
- protected queue = new AsyncIterableQueue<VADEvent>();
82
- protected output = new AsyncIterableQueue<VADEvent>();
87
+ protected input = new IdentityTransform<AudioFrame | typeof VADStream.FLUSH_SENTINEL>();
88
+ protected output = new IdentityTransform<VADEvent>();
89
+ protected inputWriter: WritableStreamDefaultWriter<AudioFrame | typeof VADStream.FLUSH_SENTINEL>;
90
+ protected inputReader: ReadableStreamDefaultReader<AudioFrame | typeof VADStream.FLUSH_SENTINEL>;
91
+ protected outputWriter: WritableStreamDefaultWriter<VADEvent>;
92
+ protected outputReader: ReadableStreamDefaultReader<VADEvent>;
83
93
  protected closed = false;
94
+ protected inputClosed = false;
95
+
84
96
  #vad: VAD;
85
97
  #lastActivityTime = BigInt(0);
98
+ private logger = log();
99
+ private deferredInputStream: DeferredReadableStream<AudioFrame>;
86
100
 
101
+ private metricsStream: ReadableStream<VADEvent>;
87
102
  constructor(vad: VAD) {
88
103
  this.#vad = vad;
104
+ this.deferredInputStream = new DeferredReadableStream<AudioFrame>();
105
+
106
+ this.inputWriter = this.input.writable.getWriter();
107
+ this.inputReader = this.input.readable.getReader();
108
+ this.outputWriter = this.output.writable.getWriter();
109
+
110
+ const [outputStream, metricsStream] = this.output.readable.tee();
111
+ this.metricsStream = metricsStream;
112
+ this.outputReader = outputStream.getReader();
113
+
114
+ this.pumpDeferredStream();
89
115
  this.monitorMetrics();
90
116
  }
91
117
 
118
+ /**
119
+ * Reads from the deferred input stream and forwards chunks to the input writer.
120
+ *
121
+ * Note: we can't just do this.deferredInputStream.stream.pipeTo(this.input.writable)
122
+ * because the inputWriter locks the this.input.writable stream. All writes must go through
123
+ * the inputWriter.
124
+ */
125
+ private async pumpDeferredStream() {
126
+ const reader = this.deferredInputStream.stream.getReader();
127
+ try {
128
+ while (true) {
129
+ const { done, value } = await reader.read();
130
+ if (done) break;
131
+ await this.inputWriter.write(value);
132
+ }
133
+ } catch (e) {
134
+ this.logger.error(`Error pumping deferred stream: ${e}`);
135
+ throw e;
136
+ } finally {
137
+ reader.releaseLock();
138
+ }
139
+ }
140
+
92
141
  protected async monitorMetrics() {
93
142
  let inferenceDurationTotal = 0;
94
143
  let inferenceCount = 0;
95
-
96
- for await (const event of this.queue) {
97
- this.output.put(event);
98
- switch (event.type) {
144
+ const metricsReader = this.metricsStream.getReader();
145
+ while (true) {
146
+ const { done, value } = await metricsReader.read();
147
+ if (done) {
148
+ break;
149
+ }
150
+ switch (value.type) {
99
151
  case VADEventType.START_OF_SPEECH:
100
152
  inferenceCount++;
101
153
  if (inferenceCount >= 1 / this.#vad.capabilities.updateInterval) {
102
- this.#vad.emit(VADEventType.METRICS_COLLECTED, {
154
+ this.#vad.emit('metrics_collected', {
155
+ type: 'vad_metrics',
103
156
  timestamp: Date.now(),
104
157
  idleTime: Math.trunc(
105
158
  Number((process.hrtime.bigint() - this.#lastActivityTime) / BigInt(1000000)),
@@ -119,47 +172,62 @@ export abstract class VADStream implements AsyncIterableIterator<VADEvent> {
119
172
  break;
120
173
  }
121
174
  }
122
- this.output.close();
123
175
  }
124
176
 
177
+ updateInputStream(audioStream: ReadableStream<AudioFrame>) {
178
+ this.deferredInputStream.setSource(audioStream);
179
+ }
180
+
181
+ detachInputStream() {
182
+ this.deferredInputStream.detachSource();
183
+ }
184
+
185
+ /** @deprecated Use `updateInputStream` instead */
125
186
  pushFrame(frame: AudioFrame) {
126
- if (this.input.closed) {
187
+ // TODO(AJS-395): remove this method
188
+ if (this.inputClosed) {
127
189
  throw new Error('Input is closed');
128
190
  }
129
191
  if (this.closed) {
130
192
  throw new Error('Stream is closed');
131
193
  }
132
- this.input.put(frame);
194
+ this.inputWriter.write(frame);
133
195
  }
134
196
 
135
197
  flush() {
136
- if (this.input.closed) {
198
+ if (this.inputClosed) {
137
199
  throw new Error('Input is closed');
138
200
  }
139
201
  if (this.closed) {
140
202
  throw new Error('Stream is closed');
141
203
  }
142
- this.input.put(VADStream.FLUSH_SENTINEL);
204
+ this.inputWriter.write(VADStream.FLUSH_SENTINEL);
143
205
  }
144
206
 
145
207
  endInput() {
146
- if (this.input.closed) {
208
+ if (this.inputClosed) {
147
209
  throw new Error('Input is closed');
148
210
  }
149
211
  if (this.closed) {
150
212
  throw new Error('Stream is closed');
151
213
  }
152
- this.input.close();
214
+ this.inputClosed = true;
215
+ this.input.writable.close();
153
216
  }
154
217
 
155
- next(): Promise<IteratorResult<VADEvent>> {
156
- return this.output.next();
218
+ async next(): Promise<IteratorResult<VADEvent>> {
219
+ return this.outputReader.read().then(({ done, value }) => {
220
+ if (done) {
221
+ return { done: true, value: undefined };
222
+ }
223
+ return { done: false, value };
224
+ });
157
225
  }
158
226
 
159
227
  close() {
160
- this.input.close();
161
- this.queue.close();
162
- this.output.close();
228
+ this.outputWriter.releaseLock();
229
+ this.outputReader.cancel();
230
+ this.output.writable.close();
163
231
  this.closed = true;
164
232
  }
165
233