@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
@@ -0,0 +1,658 @@
1
+ // SPDX-FileCopyrightText: 2024 LiveKit, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import { AudioFrame } from '@livekit/rtc-node';
5
+ import { delay } from '@std/async';
6
+ import { ReadableStream } from 'node:stream/web';
7
+ import { describe, expect, it } from 'vitest';
8
+ import { initializeLogger } from '../src/log.js';
9
+ import {
10
+ Event,
11
+ TASK_TIMEOUT_ERROR,
12
+ Task,
13
+ TaskResult,
14
+ isPending,
15
+ resampleStream,
16
+ } from '../src/utils.js';
17
+
18
+ describe('utils', () => {
19
+ // initialize logger
20
+ initializeLogger({ pretty: true, level: 'debug' });
21
+
22
+ describe('Task', () => {
23
+ it('should execute task successfully and return result', async () => {
24
+ const expectedResult = 'task completed';
25
+ const task = Task.from(async () => {
26
+ await delay(10);
27
+ return expectedResult;
28
+ });
29
+
30
+ expect(task.done).toBe(false);
31
+ const result = await task.result;
32
+ expect(result).toBe(expectedResult);
33
+ expect(task.done).toBe(true);
34
+ });
35
+
36
+ it('should handle task errors properly', async () => {
37
+ const expectedError = new Error('Task failed');
38
+ const task = Task.from(async () => {
39
+ await delay(10);
40
+ throw expectedError;
41
+ });
42
+
43
+ expect(task.done).toBe(false);
44
+ await expect(task.result).rejects.toThrow(expectedError);
45
+ expect(task.done).toBe(true);
46
+ });
47
+
48
+ it('should cancel task when cancel is called', async () => {
49
+ let taskStarted = false;
50
+ let taskCompleted = false;
51
+
52
+ const task = Task.from(async (controller) => {
53
+ taskStarted = true;
54
+ await delay(100, { signal: controller.signal });
55
+ taskCompleted = true;
56
+ return 'should not complete';
57
+ });
58
+
59
+ // Wait a bit to ensure task starts
60
+ await delay(10);
61
+ expect(taskStarted).toBe(true);
62
+ expect(task.done).toBe(false);
63
+
64
+ // Cancel the task
65
+ task.cancel();
66
+
67
+ // The task should reject with AbortError
68
+ try {
69
+ await task.result;
70
+ } catch (error: unknown) {
71
+ expect((error as Error).name).toBe('AbortError');
72
+ }
73
+
74
+ expect(taskCompleted).toBe(false);
75
+ expect(task.done).toBe(true);
76
+ });
77
+
78
+ it('should use provided AbortController', async () => {
79
+ const controller = new AbortController();
80
+ const task = Task.from(async (ctrl) => {
81
+ expect(ctrl).toBe(controller);
82
+ await delay(100, { signal: ctrl.signal });
83
+ return 'completed';
84
+ }, controller);
85
+
86
+ await delay(10);
87
+ controller.abort();
88
+
89
+ try {
90
+ await task.result;
91
+ } catch (error: unknown) {
92
+ expect((error as Error).name).toBe('AbortError');
93
+ }
94
+
95
+ expect(task.done).toBe(true);
96
+ });
97
+
98
+ it('should handle immediate resolution', async () => {
99
+ const task = Task.from(async () => {
100
+ return 'immediate';
101
+ });
102
+
103
+ const result = await task.result;
104
+ expect(result).toBe('immediate');
105
+ expect(task.done).toBe(true);
106
+ });
107
+
108
+ it('should handle immediate rejection', async () => {
109
+ const expectedError = new Error('Immediate error');
110
+ const task = Task.from(async () => {
111
+ throw expectedError;
112
+ });
113
+
114
+ try {
115
+ await task.result;
116
+ } catch (error: unknown) {
117
+ expect(error).toBe(expectedError);
118
+ }
119
+
120
+ expect(task.done).toBe(true);
121
+ });
122
+
123
+ it('should handle multiple calls to cancel', async () => {
124
+ const task = Task.from(async (controller) => {
125
+ await delay(100, { signal: controller.signal });
126
+ return 'should not complete';
127
+ });
128
+
129
+ await delay(10);
130
+
131
+ // Multiple cancellations should not cause issues
132
+ task.cancel();
133
+ task.cancel();
134
+ task.cancel();
135
+
136
+ try {
137
+ await task.result;
138
+ } catch (error: unknown) {
139
+ expect((error as Error).name).toBe('AbortError');
140
+ }
141
+
142
+ expect(task.done).toBe(true);
143
+ });
144
+
145
+ it('should handle task that checks abort signal manually', async () => {
146
+ const arr: number[] = [];
147
+ const task = Task.from(async (controller) => {
148
+ for (let i = 0; i < 10; i++) {
149
+ if (controller.signal.aborted) {
150
+ throw new Error('Task was aborted');
151
+ }
152
+ await delay(10);
153
+ arr.push(i);
154
+ }
155
+ return 'completed';
156
+ });
157
+
158
+ await delay(39);
159
+ task.cancel();
160
+
161
+ expect(arr).toEqual([0, 1, 2]);
162
+ try {
163
+ await task.result;
164
+ } catch (error: unknown) {
165
+ expect((error as Error).message).toBe('Task was aborted');
166
+ }
167
+
168
+ expect(task.done).toBe(true);
169
+ });
170
+
171
+ it('should handle cleanup in finally block', async () => {
172
+ let cleanupExecuted = false;
173
+
174
+ const task = Task.from(async (controller) => {
175
+ try {
176
+ await delay(100, { signal: controller.signal });
177
+ return 'completed';
178
+ } finally {
179
+ cleanupExecuted = true;
180
+ }
181
+ });
182
+
183
+ await delay(10);
184
+ task.cancel();
185
+
186
+ try {
187
+ await task.result;
188
+ } catch {
189
+ // Ignore the abort error
190
+ }
191
+
192
+ // Cleanup should still execute even when cancelled
193
+ expect(cleanupExecuted).toBe(true);
194
+ });
195
+
196
+ it('should handle accessing result multiple times', async () => {
197
+ const task = Task.from(async () => {
198
+ await delay(10);
199
+ return 'result';
200
+ });
201
+
202
+ const result1 = await task.result;
203
+ const result2 = await task.result;
204
+ const result3 = await task.result;
205
+
206
+ expect(result1).toBe('result');
207
+ expect(result2).toBe('result');
208
+ expect(result3).toBe('result');
209
+ expect(task.done).toBe(true);
210
+ });
211
+
212
+ it('should handle accessing result promise before completion', async () => {
213
+ const task = Task.from(async () => {
214
+ await delay(50);
215
+ return 'delayed result';
216
+ });
217
+
218
+ // Get references to result promise before completion
219
+ const resultPromise1 = task.result;
220
+ const resultPromise2 = task.result;
221
+
222
+ expect(task.done).toBe(false);
223
+
224
+ // Both promises should resolve to the same value
225
+ const [result1, result2] = await Promise.all([resultPromise1, resultPromise2]);
226
+
227
+ expect(result1).toBe('delayed result');
228
+ expect(result2).toBe('delayed result');
229
+ expect(task.done).toBe(true);
230
+ });
231
+
232
+ it('should cancel child tasks when parent task is canceled', async () => {
233
+ let parentStarted = false;
234
+ let child1Started = false;
235
+ let child2Started = false;
236
+ let parentCompleted = false;
237
+ let child1Completed = false;
238
+ let child2Completed = false;
239
+
240
+ let child1Task: Task<string> | undefined = undefined;
241
+ let child2Task: Task<string> | undefined = undefined;
242
+
243
+ const parentTask = Task.from(async (controller) => {
244
+ parentStarted = true;
245
+
246
+ // Create two child tasks using the parent's controller
247
+ child1Task = Task.from(async (childController) => {
248
+ child1Started = true;
249
+ await delay(100, { signal: childController.signal });
250
+ child1Completed = true;
251
+ return 'child1';
252
+ }, controller);
253
+
254
+ child2Task = Task.from(async (childController) => {
255
+ child2Started = true;
256
+ await delay(100, { signal: childController.signal });
257
+ child2Completed = true;
258
+ return 'child2';
259
+ }, controller);
260
+
261
+ // Wait for both child tasks
262
+ const results = await Promise.all([child1Task.result, child2Task.result]);
263
+ parentCompleted = true;
264
+ return results;
265
+ });
266
+
267
+ // Let tasks start
268
+ await delay(20);
269
+
270
+ // Verify tasks have started
271
+ expect(parentStarted).toBe(true);
272
+ expect(child1Started).toBe(true);
273
+ expect(child2Started).toBe(true);
274
+
275
+ // Cancel parent task
276
+ parentTask.cancel();
277
+
278
+ // Use Promise.allSettled to handle all promise settlements
279
+ const [parentResult, child1Result, child2Result] = await Promise.allSettled([
280
+ parentTask.result,
281
+ child1Task!.result,
282
+ child2Task!.result,
283
+ ]);
284
+
285
+ // Verify all tasks were rejected with AbortError
286
+ expect(parentResult.status).toBe('rejected');
287
+ expect((parentResult as PromiseRejectedResult).reason.name).toBe('AbortError');
288
+
289
+ expect(child1Result.status).toBe('rejected');
290
+ expect((child1Result as PromiseRejectedResult).reason.name).toBe('AbortError');
291
+
292
+ expect(child2Result.status).toBe('rejected');
293
+ expect((child2Result as PromiseRejectedResult).reason.name).toBe('AbortError');
294
+
295
+ // Verify none of the tasks completed
296
+ expect(parentCompleted).toBe(false);
297
+ expect(child1Completed).toBe(false);
298
+ expect(child2Completed).toBe(false);
299
+ expect(parentTask.done).toBe(true);
300
+ expect(child1Task!.done).toBe(true);
301
+ expect(child2Task!.done).toBe(true);
302
+ });
303
+
304
+ it('should handle nested tasks that complete successfully', async () => {
305
+ const results: string[] = [];
306
+
307
+ const parentTask = Task.from(async (controller) => {
308
+ results.push('parent-start');
309
+
310
+ // Create first child task
311
+ const child1Task = Task.from(async () => {
312
+ results.push('child1-start');
313
+ await delay(25);
314
+ results.push('child1-end');
315
+ return 'child1-result';
316
+ }, controller);
317
+
318
+ // Create second child task that depends on first
319
+ const child2Task = Task.from(async (childController) => {
320
+ results.push('child2-start');
321
+
322
+ // Create a grandchild task
323
+ const grandchildTask = Task.from(async () => {
324
+ results.push('grandchild-start');
325
+ await delay(10);
326
+ results.push('grandchild-end');
327
+ return 'grandchild-result';
328
+ }, childController);
329
+
330
+ const grandchildResult = await grandchildTask.result;
331
+ await delay(10);
332
+ results.push('child2-end');
333
+ return `child2-result-with-${grandchildResult}`;
334
+ }, controller);
335
+
336
+ // Wait for all tasks
337
+ const [child1Result, child2Result] = await Promise.all([
338
+ child1Task.result,
339
+ child2Task.result,
340
+ ]);
341
+
342
+ results.push('parent-end');
343
+ return {
344
+ parent: 'parent-result',
345
+ child1: child1Result,
346
+ child2: child2Result,
347
+ };
348
+ });
349
+
350
+ // Wait for everything to complete
351
+ const finalResult = await parentTask.result;
352
+
353
+ // Verify results
354
+ expect(finalResult).toEqual({
355
+ parent: 'parent-result',
356
+ child1: 'child1-result',
357
+ child2: 'child2-result-with-grandchild-result',
358
+ });
359
+
360
+ // Verify execution order
361
+ // Check important ordering constraints without being strict about parallel task ordering
362
+ expect(results).toEqual([
363
+ 'parent-start',
364
+ 'child1-start',
365
+ 'child2-start',
366
+ 'grandchild-start',
367
+ 'grandchild-end',
368
+ 'child2-end',
369
+ 'child1-end',
370
+ 'parent-end',
371
+ ]);
372
+
373
+ // All tasks should be done
374
+ expect(parentTask.done).toBe(true);
375
+ });
376
+
377
+ it('should propagate errors from nested tasks', async () => {
378
+ let parentError: Error | null = null;
379
+ let child1Completed = false;
380
+ let child2Started = false;
381
+
382
+ const parentTask = Task.from(async (controller) => {
383
+ const child1Task = Task.from(async () => {
384
+ await delay(20);
385
+ throw new Error('child1 error');
386
+ }, controller);
387
+
388
+ const child2Task = Task.from(async () => {
389
+ child2Started = true;
390
+ await delay(30);
391
+ child1Completed = true;
392
+ return 'child2-result';
393
+ }, controller);
394
+
395
+ // This will throw when child1 fails
396
+ const results = await Promise.all([child1Task.result, child2Task.result]);
397
+ return results;
398
+ });
399
+
400
+ // Wait for the parent task to fail
401
+ try {
402
+ await parentTask.result;
403
+ expect.fail('Parent task should have thrown');
404
+ } catch (error: unknown) {
405
+ parentError = error as Error;
406
+ }
407
+
408
+ // Verify the error propagated correctly
409
+ expect(parentError?.message).toBe('child1 error');
410
+ expect(child1Completed).toBe(false);
411
+ expect(child2Started).toBe(true);
412
+ expect(parentTask.done).toBe(true);
413
+ });
414
+
415
+ it('should cancel and wait for task completion', async () => {
416
+ let taskCompleted = false;
417
+
418
+ const task = Task.from(async (controller) => {
419
+ await delay(5000, { signal: controller.signal });
420
+ taskCompleted = true;
421
+ return 'should not complete';
422
+ });
423
+
424
+ // Cancel and wait should complete quickly when task is aborted
425
+ const start = Date.now();
426
+ const result = await task.cancelAndWait(1000);
427
+ const duration = Date.now() - start;
428
+
429
+ expect(result).toBe(TaskResult.Aborted);
430
+ expect(duration).toBeLessThan(100); // Should not wait for full timeout
431
+ expect(taskCompleted).toBe(false);
432
+ expect(task.done).toBe(true);
433
+ });
434
+
435
+ it('should timeout if task does not respond to cancellation', async () => {
436
+ const task = Task.from(async () => {
437
+ await delay(1000);
438
+ });
439
+
440
+ // This should timeout because the task ignores cancellation
441
+ try {
442
+ await task.cancelAndWait(200);
443
+ expect.fail('Task should have timed out');
444
+ } catch (error: unknown) {
445
+ expect(error).toBe(TASK_TIMEOUT_ERROR);
446
+ }
447
+ });
448
+
449
+ it('should handle task that completes before timeout', async () => {
450
+ const task = Task.from(async () => {
451
+ await delay(50);
452
+ });
453
+
454
+ // Start the task
455
+ await delay(10);
456
+
457
+ // Cancel and wait - but task will complete normally before being canceled
458
+ const result = await task.cancelAndWait(1000);
459
+
460
+ // Task should have completed normally
461
+ expect(result).toBe(TaskResult.Completed);
462
+ expect(task.done).toBe(true);
463
+ });
464
+
465
+ it('should propagate non-abort errors from cancelAndWait', async () => {
466
+ const task = Task.from(async () => {
467
+ await delay(10);
468
+ throw new TypeError('Custom error');
469
+ });
470
+
471
+ try {
472
+ await task.cancelAndWait(1000);
473
+ expect.fail('Task should have thrown');
474
+ } catch (error: unknown) {
475
+ expect((error as Error).message).toBe('Custom error');
476
+ expect((error as Error).name).toBe('TypeError');
477
+ }
478
+ });
479
+ });
480
+
481
+ describe('Event', () => {
482
+ it('wait resolves immediately when the event is already set', async () => {
483
+ const event = new Event();
484
+ event.set();
485
+
486
+ const result = await event.wait();
487
+ expect(result).toBe(true);
488
+ });
489
+
490
+ it('wait resolves after set is called', async () => {
491
+ // check promise is pending
492
+ const event = new Event();
493
+ const waiterPromise = event.wait();
494
+
495
+ await delay(10);
496
+ expect(await isPending(waiterPromise)).toBe(true);
497
+
498
+ // check promise is resolved after set is called
499
+ event.set();
500
+ const result = await waiterPromise;
501
+ expect(result).toBe(true);
502
+ });
503
+
504
+ it('all waiters resolve once set is called', async () => {
505
+ const event = new Event();
506
+ const waiters = [event.wait(), event.wait(), event.wait()];
507
+
508
+ await delay(10);
509
+ const pendings = await Promise.all(waiters.map((w) => isPending(w)));
510
+ expect(pendings).toEqual([true, true, true]);
511
+
512
+ event.set();
513
+ const results = await Promise.all(waiters);
514
+ expect(results).toEqual([true, true, true]);
515
+ });
516
+
517
+ it('wait after 2 seconds is still pending before set', async () => {
518
+ const event = new Event();
519
+ const waiter = event.wait();
520
+
521
+ await delay(2000);
522
+ expect(await isPending(waiter)).toBe(true);
523
+
524
+ event.set();
525
+ const result = await waiter;
526
+ expect(result).toBe(true);
527
+ });
528
+
529
+ it('wait after set and clear should be pending', async () => {
530
+ const event = new Event();
531
+ const waiterBeforeSet = event.wait();
532
+ event.set();
533
+ event.clear();
534
+
535
+ const waiterAfterSet = event.wait();
536
+
537
+ const result = await Promise.race([
538
+ waiterBeforeSet.then(() => 'before'),
539
+ waiterAfterSet.then(() => 'after'),
540
+ ]);
541
+
542
+ expect(result).toBe('before');
543
+ expect(await isPending(waiterBeforeSet)).toBe(false);
544
+ expect(await isPending(waiterAfterSet)).toBe(true);
545
+
546
+ event.set();
547
+ expect(await waiterAfterSet).toBe(true);
548
+ });
549
+ });
550
+
551
+ describe('resampleStream', () => {
552
+ const createAudioFrame = (sampleRate: number, samples: number, channels = 1): AudioFrame => {
553
+ const data = new Int16Array(samples * channels);
554
+ for (let i = 0; i < data.length; i++) {
555
+ data[i] = Math.sin((i / samples) * Math.PI * 2) * 16000;
556
+ }
557
+ return new AudioFrame(data, sampleRate, channels, samples);
558
+ };
559
+
560
+ const streamToArray = async (stream: ReadableStream<AudioFrame>): Promise<AudioFrame[]> => {
561
+ const reader = stream.getReader();
562
+ const chunks: AudioFrame[] = [];
563
+ try {
564
+ while (true) {
565
+ const { done, value } = await reader.read();
566
+ if (done) break;
567
+ chunks.push(value);
568
+ }
569
+ } finally {
570
+ reader.releaseLock();
571
+ }
572
+ return chunks;
573
+ };
574
+
575
+ it('should resample audio frames to target sample rate', async () => {
576
+ const inputRate = 48000;
577
+ const outputRate = 16000;
578
+ const inputFrame = createAudioFrame(inputRate, 960); // 20ms at 48kHz
579
+
580
+ const inputStream = new ReadableStream<AudioFrame>({
581
+ start(controller) {
582
+ controller.enqueue(inputFrame);
583
+ controller.close();
584
+ },
585
+ });
586
+
587
+ const outputStream = resampleStream({ stream: inputStream, outputRate });
588
+ const outputFrames = await streamToArray(outputStream);
589
+
590
+ expect(outputFrames.length).toBeGreaterThan(0);
591
+
592
+ for (const frame of outputFrames) {
593
+ expect(frame.sampleRate).toBe(outputRate);
594
+ expect(frame.channels).toBe(inputFrame.channels);
595
+ }
596
+ });
597
+
598
+ it('should handle same input and output rate', async () => {
599
+ const sampleRate = 44100;
600
+ const inputFrame = createAudioFrame(sampleRate, 1024);
601
+
602
+ const inputStream = new ReadableStream<AudioFrame>({
603
+ start(controller) {
604
+ controller.enqueue(inputFrame);
605
+ controller.close();
606
+ },
607
+ });
608
+
609
+ const outputStream = resampleStream({ stream: inputStream, outputRate: sampleRate });
610
+ const outputFrames = await streamToArray(outputStream);
611
+
612
+ expect(outputFrames.length).toBeGreaterThan(0);
613
+
614
+ for (const frame of outputFrames) {
615
+ expect(frame.sampleRate).toBe(sampleRate);
616
+ expect(frame.channels).toBe(inputFrame.channels);
617
+ }
618
+ });
619
+
620
+ it('should handle multiple input frames', async () => {
621
+ const inputRate = 32000;
622
+ const outputRate = 48000;
623
+ const frame1 = createAudioFrame(inputRate, 640);
624
+ const frame2 = createAudioFrame(inputRate, 640);
625
+
626
+ const inputStream = new ReadableStream<AudioFrame>({
627
+ start(controller) {
628
+ controller.enqueue(frame1);
629
+ controller.enqueue(frame2);
630
+ controller.close();
631
+ },
632
+ });
633
+
634
+ const outputStream = resampleStream({ stream: inputStream, outputRate });
635
+ const outputFrames = await streamToArray(outputStream);
636
+
637
+ expect(outputFrames.length).toBeGreaterThan(0);
638
+
639
+ for (const frame of outputFrames) {
640
+ expect(frame.sampleRate).toBe(outputRate);
641
+ expect(frame.channels).toBe(frame1.channels);
642
+ }
643
+ });
644
+
645
+ it('should handle empty stream', async () => {
646
+ const inputStream = new ReadableStream<AudioFrame>({
647
+ start(controller) {
648
+ controller.close();
649
+ },
650
+ });
651
+
652
+ const outputStream = resampleStream({ stream: inputStream, outputRate: 44100 });
653
+ const outputFrames = await streamToArray(outputStream);
654
+
655
+ expect(outputFrames).toEqual([]);
656
+ });
657
+ });
658
+ });