@livekit/agents 0.7.8 → 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 -0
  21. package/dist/constants.cjs.map +1 -1
  22. package/dist/constants.d.cts +2 -0
  23. package/dist/constants.d.ts +2 -0
  24. package/dist/constants.d.ts.map +1 -1
  25. package/dist/constants.js +4 -0
  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 -0
  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 -451
  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 -425
  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 -849
  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 -826
  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 -555
  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 -1185
  627. package/src/pipeline/speech_handle.ts +0 -201
@@ -0,0 +1,183 @@
1
+ // SPDX-FileCopyrightText: 2025 LiveKit, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import { log } from '../../log.js';
5
+ import type {
6
+ ChatContext,
7
+ ChatItem,
8
+ ChatMessage,
9
+ FunctionCall,
10
+ FunctionCallOutput,
11
+ } from '../chat_context.js';
12
+
13
+ class ChatItemGroup {
14
+ message?: ChatMessage;
15
+ toolCalls: FunctionCall[];
16
+ toolOutputs: FunctionCallOutput[];
17
+ logger = log();
18
+
19
+ constructor(params: {
20
+ message?: ChatMessage;
21
+ toolCalls: FunctionCall[];
22
+ toolOutputs: FunctionCallOutput[];
23
+ }) {
24
+ this.message = params.message;
25
+ this.toolCalls = params.toolCalls;
26
+ this.toolOutputs = params.toolOutputs;
27
+ }
28
+
29
+ static create(params?: {
30
+ message?: ChatMessage;
31
+ toolCalls?: FunctionCall[];
32
+ toolOutputs?: FunctionCallOutput[];
33
+ }) {
34
+ const { message, toolCalls = [], toolOutputs = [] } = params ?? {};
35
+ return new ChatItemGroup({ message, toolCalls, toolOutputs });
36
+ }
37
+
38
+ get isEmpty() {
39
+ return (
40
+ this.message === undefined && this.toolCalls.length === 0 && this.toolOutputs.length === 0
41
+ );
42
+ }
43
+
44
+ add(item: ChatItem) {
45
+ if (item.type === 'message') {
46
+ if (this.message) {
47
+ throw new Error('only one message is allowed in a group');
48
+ }
49
+ this.message = item;
50
+ } else if (item.type === 'function_call') {
51
+ this.toolCalls.push(item);
52
+ } else if (item.type === 'function_call_output') {
53
+ this.toolOutputs.push(item);
54
+ }
55
+ return this;
56
+ }
57
+
58
+ removeInvalidToolCalls() {
59
+ if (this.toolCalls.length === this.toolOutputs.length) {
60
+ return;
61
+ }
62
+
63
+ const toolCallIds = new Set(this.toolCalls.map((call) => call.callId));
64
+ const toolOutputIds = new Set(this.toolOutputs.map((output) => output.callId));
65
+
66
+ // intersection of tool call ids and tool output ids
67
+ const validCallIds = intersection(toolCallIds, toolOutputIds);
68
+
69
+ // filter out tool calls that don't have a corresponding tool output
70
+ this.toolCalls = this.toolCalls.filter((call) => {
71
+ if (validCallIds.has(call.callId)) return true;
72
+ this.logger.warn(
73
+ {
74
+ callId: call.callId,
75
+ toolName: call.name,
76
+ },
77
+ 'function call missing the corresponding function output, ignoring',
78
+ );
79
+ return false;
80
+ });
81
+
82
+ // filter out tool outputs that don't have a corresponding tool call
83
+ this.toolOutputs = this.toolOutputs.filter((output) => {
84
+ if (validCallIds.has(output.callId)) return true;
85
+ this.logger.warn(
86
+ {
87
+ callId: output.callId,
88
+ toolName: output.name,
89
+ },
90
+ 'function output missing the corresponding function call, ignoring',
91
+ );
92
+ return false;
93
+ });
94
+ }
95
+
96
+ flatten() {
97
+ const items: ChatItem[] = [];
98
+ if (this.message) items.push(this.message);
99
+ items.push(...this.toolCalls, ...this.toolOutputs);
100
+ return items;
101
+ }
102
+ }
103
+
104
+ function intersection<T>(set1: Set<T>, set2: Set<T>): Set<T> {
105
+ return new Set([...set1].filter((item) => set2.has(item)));
106
+ }
107
+
108
+ /**
109
+ * Group chat items (messages, function calls, and function outputs)
110
+ * into coherent groups based on their item IDs and call IDs.
111
+ *
112
+ * Each group will contain:
113
+ * - Zero or one assistant message
114
+ * - Zero or more function/tool calls
115
+ * - The corresponding function/tool outputs matched by call_id
116
+ *
117
+ * User and system messages are placed in their own individual groups.
118
+ *
119
+ * @param chatCtx - The chat context containing all conversation items
120
+ * @returns A list of ChatItemGroup objects representing the grouped conversation
121
+ */
122
+ export function groupToolCalls(chatCtx: ChatContext) {
123
+ const itemGroups: Record<string, ChatItemGroup> = {};
124
+ const insertionOrder: Record<string, number> = {};
125
+ const toolOutputs: FunctionCallOutput[] = [];
126
+ const logger = log();
127
+
128
+ let insertionIndex = 0;
129
+ for (const item of chatCtx.items) {
130
+ const isAssistantMessage = item.type === 'message' && item.role === 'assistant';
131
+ const isFunctionCall = item.type === 'function_call';
132
+ const isFunctionCallOutput = item.type === 'function_call_output';
133
+
134
+ if (isAssistantMessage || isFunctionCall) {
135
+ // only assistant messages and function calls can be grouped
136
+ const groupId = item.id.split('/')[0]!;
137
+ if (itemGroups[groupId] === undefined) {
138
+ itemGroups[groupId] = ChatItemGroup.create();
139
+
140
+ // we use insertion order to sort the groups as they are added to the context
141
+ // simulating the OrderedDict in python
142
+ insertionOrder[groupId] = insertionIndex;
143
+ insertionIndex++;
144
+ }
145
+ itemGroups[groupId]!.add(item);
146
+ } else if (isFunctionCallOutput) {
147
+ toolOutputs.push(item);
148
+ } else {
149
+ itemGroups[item.id] = ChatItemGroup.create().add(item);
150
+ }
151
+ }
152
+
153
+ // add tool outputs to their corresponding groups
154
+ const callIdToGroup: Record<string, ChatItemGroup> = {};
155
+ for (const group of Object.values(itemGroups)) {
156
+ for (const toolCall of group.toolCalls) {
157
+ callIdToGroup[toolCall.callId] = group;
158
+ }
159
+ }
160
+
161
+ for (const toolOutput of toolOutputs) {
162
+ const group = callIdToGroup[toolOutput.callId];
163
+ if (group === undefined) {
164
+ logger.warn(
165
+ { callId: toolOutput.callId, toolName: toolOutput.name },
166
+ 'function output missing the corresponding function call, ignoring',
167
+ );
168
+ continue;
169
+ }
170
+ group.add(toolOutput);
171
+ }
172
+
173
+ // validate that each group and remove invalid tool calls and tool outputs
174
+ for (const group of Object.values(itemGroups)) {
175
+ group.removeInvalidToolCalls();
176
+ }
177
+
178
+ // sort groups by their item id
179
+ const orderedGroups = Object.entries(itemGroups)
180
+ .sort((a, b) => insertionOrder[a[0]]! - insertionOrder[b[0]]!)
181
+ .map(([, group]) => group);
182
+ return orderedGroups;
183
+ }
@@ -0,0 +1,151 @@
1
+ // SPDX-FileCopyrightText: 2025 LiveKit, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import type { AudioFrame } from '@livekit/rtc-node';
5
+ import { EventEmitter } from 'events';
6
+ import type { ReadableStream } from 'node:stream/web';
7
+ import { DeferredReadableStream } from '../stream/deferred_stream.js';
8
+ import { Task } from '../utils.js';
9
+ import type { ChatContext, FunctionCall } from './chat_context.js';
10
+ import type { ToolChoice, ToolContext } from './tool_context.js';
11
+
12
+ export type InputSpeechStartedEvent = object;
13
+
14
+ export interface InputSpeechStoppedEvent {
15
+ userTranscriptionEnabled: boolean;
16
+ }
17
+
18
+ export interface MessageGeneration {
19
+ messageId: string;
20
+ textStream: ReadableStream<string>;
21
+ audioStream: ReadableStream<AudioFrame>;
22
+ }
23
+
24
+ export interface GenerationCreatedEvent {
25
+ messageStream: ReadableStream<MessageGeneration>;
26
+ functionStream: ReadableStream<FunctionCall>;
27
+ userInitiated: boolean;
28
+ }
29
+
30
+ export interface RealtimeModelError {
31
+ type: 'realtime_model_error';
32
+ timestamp: number;
33
+ label: string;
34
+ error: Error;
35
+ recoverable: boolean;
36
+ }
37
+
38
+ export interface RealtimeCapabilities {
39
+ messageTruncation: boolean;
40
+ turnDetection: boolean;
41
+ userTranscription: boolean;
42
+ autoToolReplyGeneration: boolean;
43
+ }
44
+
45
+ export interface InputTranscriptionCompleted {
46
+ itemId: string;
47
+ transcript: string;
48
+ isFinal: boolean;
49
+ }
50
+
51
+ export interface RealtimeSessionReconnectedEvent {}
52
+
53
+ export abstract class RealtimeModel {
54
+ private _capabilities: RealtimeCapabilities;
55
+
56
+ constructor(capabilities: RealtimeCapabilities) {
57
+ this._capabilities = capabilities;
58
+ }
59
+
60
+ get capabilities() {
61
+ return this._capabilities;
62
+ }
63
+
64
+ abstract session(): RealtimeSession;
65
+
66
+ abstract close(): Promise<void>;
67
+ }
68
+
69
+ export abstract class RealtimeSession extends EventEmitter {
70
+ protected _realtimeModel: RealtimeModel;
71
+ private deferredInputStream = new DeferredReadableStream<AudioFrame>();
72
+ private _mainTask: Task<void>;
73
+
74
+ constructor(realtimeModel: RealtimeModel) {
75
+ super();
76
+ this._realtimeModel = realtimeModel;
77
+ this._mainTask = Task.from((controller) => this._mainTaskImpl(controller.signal));
78
+ }
79
+
80
+ get realtimeModel() {
81
+ return this._realtimeModel;
82
+ }
83
+
84
+ abstract get chatCtx(): ChatContext;
85
+
86
+ abstract get tools(): ToolContext;
87
+
88
+ abstract updateInstructions(instructions: string): Promise<void>;
89
+
90
+ /**
91
+ * @throws RealtimeError on Timeout
92
+ */
93
+ abstract updateChatCtx(chatCtx: ChatContext): Promise<void>;
94
+
95
+ abstract updateTools(tools: ToolContext): Promise<void>;
96
+
97
+ abstract updateOptions(options: { toolChoice?: ToolChoice | null }): void;
98
+
99
+ abstract pushAudio(frame: AudioFrame): void;
100
+
101
+ /**
102
+ * @throws RealtimeError on Timeout
103
+ */
104
+ abstract generateReply(instructions?: string): Promise<GenerationCreatedEvent>;
105
+
106
+ /**
107
+ * Commit the input audio buffer to the server
108
+ */
109
+ abstract commitAudio(): Promise<void>;
110
+
111
+ /**
112
+ * Clear the input audio buffer to the server
113
+ */
114
+ abstract clearAudio(): Promise<void>;
115
+
116
+ /**
117
+ * Cancel the current generation (do nothing if no generation is in progress)
118
+ */
119
+ abstract interrupt(): Promise<void>;
120
+
121
+ /**
122
+ * Truncate the message at the given audio end time
123
+ */
124
+ abstract truncate(options: { messageId: string; audioEndMs: number }): Promise<void>;
125
+
126
+ async close(): Promise<void> {
127
+ this._mainTask.cancel();
128
+ }
129
+
130
+ /**
131
+ * Notifies the model that user activity has started
132
+ */
133
+ startUserActivity(): void {
134
+ return;
135
+ }
136
+
137
+ private async _mainTaskImpl(signal: AbortSignal): Promise<void> {
138
+ const reader = this.deferredInputStream.stream.getReader();
139
+ while (true) {
140
+ const { done, value } = await reader.read();
141
+ if (done || signal.aborted) {
142
+ break;
143
+ }
144
+ this.pushAudio(value);
145
+ }
146
+ }
147
+
148
+ setInputAudioStream(audioStream: ReadableStream<AudioFrame>): void {
149
+ this.deferredInputStream.setSource(audioStream);
150
+ }
151
+ }
@@ -0,0 +1,290 @@
1
+ // SPDX-FileCopyrightText: 2025 LiveKit, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import { beforeEach, describe, expect, it } from 'vitest';
5
+ import { ChatMessage } from './chat_context.js';
6
+ import { RemoteChatContext } from './remote_chat_context.js';
7
+
8
+ function createMessage(id: string, content: string): ChatMessage {
9
+ return new ChatMessage({ id, role: 'user', content });
10
+ }
11
+
12
+ describe('RemoteChatContext', () => {
13
+ let context: RemoteChatContext;
14
+
15
+ beforeEach(() => {
16
+ context = new RemoteChatContext();
17
+ });
18
+
19
+ describe('empty context', () => {
20
+ it('should return empty ChatContext', () => {
21
+ const chatCtx = context.toChatCtx();
22
+ expect(chatCtx.items).toHaveLength(0);
23
+ });
24
+
25
+ it('should return null for non-existent item', () => {
26
+ expect(context.get('nonexistent')).toBeNull();
27
+ });
28
+
29
+ it('should throw error when deleting non-existent item', () => {
30
+ expect(() => context.delete('nonexistent')).toThrow('Item with ID nonexistent not found');
31
+ });
32
+ });
33
+
34
+ describe('single item operations', () => {
35
+ it('should insert single item at head', () => {
36
+ const msg = createMessage('msg1', 'Hello');
37
+ context.insert(undefined, msg);
38
+
39
+ expect(context.get('msg1')).toBeDefined();
40
+ expect(context.get('msg1')!.item).toBe(msg);
41
+ expect(context.toChatCtx().items).toEqual([msg]);
42
+ });
43
+
44
+ it('should delete single item', () => {
45
+ const msg = createMessage('msg1', 'Hello');
46
+ context.insert(undefined, msg);
47
+ context.delete('msg1');
48
+
49
+ expect(context.get('msg1')).toBeNull();
50
+ expect(context.toChatCtx().items).toHaveLength(0);
51
+ });
52
+ });
53
+
54
+ describe('multiple item operations', () => {
55
+ it('should insert multiple items at head', () => {
56
+ const msg1 = createMessage('msg1', 'First');
57
+ const msg2 = createMessage('msg2', 'Second');
58
+ const msg3 = createMessage('msg3', 'Third');
59
+
60
+ context.insert(undefined, msg1);
61
+ context.insert(undefined, msg2);
62
+ context.insert(undefined, msg3);
63
+
64
+ expect(context.toChatCtx().items).toEqual([msg3, msg2, msg1]);
65
+ });
66
+
67
+ it('should insert items after specific nodes', () => {
68
+ const msg1 = createMessage('msg1', 'First');
69
+ const msg2 = createMessage('msg2', 'Second');
70
+ const msg3 = createMessage('msg3', 'Third');
71
+
72
+ context.insert(undefined, msg1);
73
+ context.insert('msg1', msg2);
74
+ context.insert('msg1', msg3);
75
+
76
+ expect(context.toChatCtx().items).toEqual([msg1, msg3, msg2]);
77
+ });
78
+
79
+ it('should insert at tail', () => {
80
+ const msg1 = createMessage('msg1', 'First');
81
+ const msg2 = createMessage('msg2', 'Second');
82
+ const msg3 = createMessage('msg3', 'Third');
83
+
84
+ context.insert(undefined, msg1);
85
+ context.insert('msg1', msg2);
86
+ context.insert('msg2', msg3);
87
+
88
+ expect(context.toChatCtx().items).toEqual([msg1, msg2, msg3]);
89
+ });
90
+ });
91
+
92
+ describe('deletion edge cases', () => {
93
+ it('should delete head node from multi-item list', () => {
94
+ const msg1 = createMessage('msg1', 'First');
95
+ const msg2 = createMessage('msg2', 'Second');
96
+ const msg3 = createMessage('msg3', 'Third');
97
+
98
+ context.insert(undefined, msg1);
99
+ context.insert('msg1', msg2);
100
+ context.insert('msg2', msg3);
101
+
102
+ context.delete('msg1');
103
+ expect(context.toChatCtx().items).toEqual([msg2, msg3]);
104
+ });
105
+
106
+ it('should delete tail node from multi-item list', () => {
107
+ const msg1 = createMessage('msg1', 'First');
108
+ const msg2 = createMessage('msg2', 'Second');
109
+ const msg3 = createMessage('msg3', 'Third');
110
+
111
+ context.insert(undefined, msg1);
112
+ context.insert('msg1', msg2);
113
+ context.insert('msg2', msg3);
114
+
115
+ context.delete('msg3');
116
+ expect(context.toChatCtx().items).toEqual([msg1, msg2]);
117
+ });
118
+
119
+ it('should delete middle node from multi-item list', () => {
120
+ const msg1 = createMessage('msg1', 'First');
121
+ const msg2 = createMessage('msg2', 'Second');
122
+ const msg3 = createMessage('msg3', 'Third');
123
+
124
+ context.insert(undefined, msg1);
125
+ context.insert('msg1', msg2);
126
+ context.insert('msg2', msg3);
127
+
128
+ context.delete('msg2');
129
+ expect(context.toChatCtx().items).toEqual([msg1, msg3]);
130
+ });
131
+
132
+ it('should handle multiple deletions', () => {
133
+ const msg1 = createMessage('msg1', 'First');
134
+ const msg2 = createMessage('msg2', 'Second');
135
+ const msg3 = createMessage('msg3', 'Third');
136
+ const msg4 = createMessage('msg4', 'Fourth');
137
+
138
+ context.insert(undefined, msg1);
139
+ context.insert('msg1', msg2);
140
+ context.insert('msg2', msg3);
141
+ context.insert('msg3', msg4);
142
+
143
+ context.delete('msg2');
144
+ context.delete('msg4');
145
+ expect(context.toChatCtx().items).toEqual([msg1, msg3]);
146
+
147
+ context.delete('msg1');
148
+ expect(context.toChatCtx().items).toEqual([msg3]);
149
+
150
+ context.delete('msg3');
151
+ expect(context.toChatCtx().items).toHaveLength(0);
152
+ });
153
+ });
154
+
155
+ describe('error conditions', () => {
156
+ it('should throw error when inserting duplicate ID', () => {
157
+ const msg1 = createMessage('msg1', 'First');
158
+ const msg2 = createMessage('msg1', 'Duplicate');
159
+
160
+ context.insert(undefined, msg1);
161
+ expect(() => context.insert(undefined, msg2)).toThrow('Item with ID msg1 already exists.');
162
+ });
163
+
164
+ it('should throw error when inserting after non-existent ID', () => {
165
+ const msg = createMessage('msg1', 'Hello');
166
+ expect(() => context.insert('nonexistent', msg)).toThrow(
167
+ 'previousItemId nonexistent not found',
168
+ );
169
+ });
170
+
171
+ it('should throw error when deleting non-existent ID', () => {
172
+ expect(() => context.delete('nonexistent')).toThrow('Item with ID nonexistent not found');
173
+ });
174
+ });
175
+
176
+ describe('complex scenarios', () => {
177
+ it('should handle interleaved inserts and deletes', () => {
178
+ const msg1 = createMessage('msg1', 'A');
179
+ const msg2 = createMessage('msg2', 'B');
180
+ const msg3 = createMessage('msg3', 'C');
181
+ const msg4 = createMessage('msg4', 'D');
182
+
183
+ context.insert(undefined, msg1);
184
+ context.insert('msg1', msg2);
185
+ context.delete('msg1');
186
+ context.insert('msg2', msg3);
187
+ context.insert(undefined, msg4);
188
+
189
+ expect(context.toChatCtx().items).toEqual([msg4, msg2, msg3]);
190
+ });
191
+
192
+ it('should maintain correct pointers after complex operations', () => {
193
+ const msg1 = createMessage('msg1', 'A');
194
+ const msg2 = createMessage('msg2', 'B');
195
+ const msg3 = createMessage('msg3', 'C');
196
+ const msg4 = createMessage('msg4', 'D');
197
+ const msg5 = createMessage('msg5', 'E');
198
+
199
+ context.insert(undefined, msg1);
200
+ context.insert('msg1', msg2);
201
+ context.insert('msg2', msg3);
202
+ context.insert('msg1', msg4);
203
+ context.insert('msg4', msg5);
204
+
205
+ expect(context.toChatCtx().items).toEqual([msg1, msg4, msg5, msg2, msg3]);
206
+
207
+ context.delete('msg4');
208
+ expect(context.toChatCtx().items).toEqual([msg1, msg5, msg2, msg3]);
209
+
210
+ context.delete('msg1');
211
+ expect(context.toChatCtx().items).toEqual([msg5, msg2, msg3]);
212
+
213
+ context.delete('msg2');
214
+ expect(context.toChatCtx().items).toEqual([msg5, msg3]);
215
+ });
216
+
217
+ it('should handle rebuilding from scratch', () => {
218
+ const messages = Array.from({ length: 10 }, (_, i) =>
219
+ createMessage(`msg${i}`, `Content ${i}`),
220
+ );
221
+
222
+ for (const msg of messages) {
223
+ context.insert(undefined, msg);
224
+ }
225
+
226
+ expect(context.toChatCtx().items).toEqual([...messages].reverse());
227
+
228
+ for (let i = 0; i < 5; i++) {
229
+ context.delete(`msg${i}`);
230
+ }
231
+
232
+ const remaining = [...messages]
233
+ .reverse()
234
+ .filter((msg) => !['msg0', 'msg1', 'msg2', 'msg3', 'msg4'].includes(msg.id));
235
+ expect(context.toChatCtx().items).toEqual(remaining);
236
+ });
237
+ });
238
+
239
+ describe('get method', () => {
240
+ it('should return correct item for existing ID', () => {
241
+ const msg1 = createMessage('msg1', 'Hello');
242
+ const msg2 = createMessage('msg2', 'World');
243
+
244
+ context.insert(undefined, msg1);
245
+ context.insert('msg1', msg2);
246
+
247
+ const retrieved = context.get('msg2');
248
+ expect(retrieved).toBeDefined();
249
+ expect(retrieved!.item).toBe(msg2);
250
+ });
251
+
252
+ it('should return null for non-existent ID', () => {
253
+ const msg = createMessage('msg1', 'Hello');
254
+ context.insert(undefined, msg);
255
+
256
+ expect(context.get('nonexistent')).toBeNull();
257
+ });
258
+ });
259
+
260
+ describe('toChatCtx method', () => {
261
+ it('should preserve order in ChatContext', () => {
262
+ const msg1 = createMessage('msg1', 'First');
263
+ const msg2 = createMessage('msg2', 'Second');
264
+ const msg3 = createMessage('msg3', 'Third');
265
+
266
+ context.insert(undefined, msg1);
267
+ context.insert('msg1', msg2);
268
+ context.insert('msg2', msg3);
269
+
270
+ const chatCtx = context.toChatCtx();
271
+ expect(chatCtx.items).toEqual([msg1, msg2, msg3]);
272
+ });
273
+
274
+ it('should work with empty context', () => {
275
+ const chatCtx = context.toChatCtx();
276
+ expect(chatCtx.items).toHaveLength(0);
277
+ });
278
+
279
+ it('should create new ChatContext instance', () => {
280
+ const msg = createMessage('msg1', 'Hello');
281
+ context.insert(undefined, msg);
282
+
283
+ const chatCtx1 = context.toChatCtx();
284
+ const chatCtx2 = context.toChatCtx();
285
+
286
+ expect(chatCtx1).not.toBe(chatCtx2);
287
+ expect(chatCtx1.items).toEqual(chatCtx2.items);
288
+ });
289
+ });
290
+ });