@livekit/agents 1.0.47 → 1.1.0-dev.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 (444) hide show
  1. package/dist/beta/index.cjs +29 -0
  2. package/dist/beta/index.cjs.map +1 -0
  3. package/dist/beta/index.d.cts +2 -0
  4. package/dist/beta/index.d.ts +2 -0
  5. package/dist/beta/index.d.ts.map +1 -0
  6. package/dist/beta/index.js +7 -0
  7. package/dist/beta/index.js.map +1 -0
  8. package/dist/beta/workflows/index.cjs +29 -0
  9. package/dist/beta/workflows/index.cjs.map +1 -0
  10. package/dist/beta/workflows/index.d.cts +2 -0
  11. package/dist/beta/workflows/index.d.ts +2 -0
  12. package/dist/beta/workflows/index.d.ts.map +1 -0
  13. package/dist/beta/workflows/index.js +7 -0
  14. package/dist/beta/workflows/index.js.map +1 -0
  15. package/dist/beta/workflows/task_group.cjs +162 -0
  16. package/dist/beta/workflows/task_group.cjs.map +1 -0
  17. package/dist/beta/workflows/task_group.d.cts +32 -0
  18. package/dist/beta/workflows/task_group.d.ts +32 -0
  19. package/dist/beta/workflows/task_group.d.ts.map +1 -0
  20. package/dist/beta/workflows/task_group.js +138 -0
  21. package/dist/beta/workflows/task_group.js.map +1 -0
  22. package/dist/constants.cjs +27 -0
  23. package/dist/constants.cjs.map +1 -1
  24. package/dist/constants.d.cts +9 -0
  25. package/dist/constants.d.ts +9 -0
  26. package/dist/constants.d.ts.map +1 -1
  27. package/dist/constants.js +18 -0
  28. package/dist/constants.js.map +1 -1
  29. package/dist/index.cjs +3 -0
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.cts +2 -1
  32. package/dist/index.d.ts +2 -1
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +2 -0
  35. package/dist/index.js.map +1 -1
  36. package/dist/inference/api_protos.d.cts +12 -12
  37. package/dist/inference/api_protos.d.ts +12 -12
  38. package/dist/inference/interruption/defaults.cjs +81 -0
  39. package/dist/inference/interruption/defaults.cjs.map +1 -0
  40. package/dist/inference/interruption/defaults.d.cts +19 -0
  41. package/dist/inference/interruption/defaults.d.ts +19 -0
  42. package/dist/inference/interruption/defaults.d.ts.map +1 -0
  43. package/dist/inference/interruption/defaults.js +46 -0
  44. package/dist/inference/interruption/defaults.js.map +1 -0
  45. package/dist/inference/interruption/errors.cjs +44 -0
  46. package/dist/inference/interruption/errors.cjs.map +1 -0
  47. package/dist/inference/interruption/errors.d.cts +12 -0
  48. package/dist/inference/interruption/errors.d.ts +12 -0
  49. package/dist/inference/interruption/errors.d.ts.map +1 -0
  50. package/dist/inference/interruption/errors.js +20 -0
  51. package/dist/inference/interruption/errors.js.map +1 -0
  52. package/dist/inference/interruption/http_transport.cjs +147 -0
  53. package/dist/inference/interruption/http_transport.cjs.map +1 -0
  54. package/dist/inference/interruption/http_transport.d.cts +63 -0
  55. package/dist/inference/interruption/http_transport.d.ts +63 -0
  56. package/dist/inference/interruption/http_transport.d.ts.map +1 -0
  57. package/dist/inference/interruption/http_transport.js +121 -0
  58. package/dist/inference/interruption/http_transport.js.map +1 -0
  59. package/dist/inference/interruption/interruption_cache_entry.cjs +58 -0
  60. package/dist/inference/interruption/interruption_cache_entry.cjs.map +1 -0
  61. package/dist/inference/interruption/interruption_cache_entry.d.cts +30 -0
  62. package/dist/inference/interruption/interruption_cache_entry.d.ts +30 -0
  63. package/dist/inference/interruption/interruption_cache_entry.d.ts.map +1 -0
  64. package/dist/inference/interruption/interruption_cache_entry.js +34 -0
  65. package/dist/inference/interruption/interruption_cache_entry.js.map +1 -0
  66. package/dist/inference/interruption/interruption_detector.cjs +181 -0
  67. package/dist/inference/interruption/interruption_detector.cjs.map +1 -0
  68. package/dist/inference/interruption/interruption_detector.d.cts +59 -0
  69. package/dist/inference/interruption/interruption_detector.d.ts +59 -0
  70. package/dist/inference/interruption/interruption_detector.d.ts.map +1 -0
  71. package/dist/inference/interruption/interruption_detector.js +147 -0
  72. package/dist/inference/interruption/interruption_detector.js.map +1 -0
  73. package/dist/inference/interruption/interruption_stream.cjs +368 -0
  74. package/dist/inference/interruption/interruption_stream.cjs.map +1 -0
  75. package/dist/inference/interruption/interruption_stream.d.cts +46 -0
  76. package/dist/inference/interruption/interruption_stream.d.ts +46 -0
  77. package/dist/inference/interruption/interruption_stream.d.ts.map +1 -0
  78. package/dist/inference/interruption/interruption_stream.js +344 -0
  79. package/dist/inference/interruption/interruption_stream.js.map +1 -0
  80. package/dist/inference/interruption/types.cjs +17 -0
  81. package/dist/inference/interruption/types.cjs.map +1 -0
  82. package/dist/inference/interruption/types.d.cts +66 -0
  83. package/dist/inference/interruption/types.d.ts +66 -0
  84. package/dist/inference/interruption/types.d.ts.map +1 -0
  85. package/dist/inference/interruption/types.js +1 -0
  86. package/dist/inference/interruption/types.js.map +1 -0
  87. package/dist/inference/interruption/utils.cjs +130 -0
  88. package/dist/inference/interruption/utils.cjs.map +1 -0
  89. package/dist/inference/interruption/utils.d.cts +41 -0
  90. package/dist/inference/interruption/utils.d.ts +41 -0
  91. package/dist/inference/interruption/utils.d.ts.map +1 -0
  92. package/dist/inference/interruption/utils.js +105 -0
  93. package/dist/inference/interruption/utils.js.map +1 -0
  94. package/dist/inference/interruption/utils.test.cjs +105 -0
  95. package/dist/inference/interruption/utils.test.cjs.map +1 -0
  96. package/dist/inference/interruption/utils.test.js +104 -0
  97. package/dist/inference/interruption/utils.test.js.map +1 -0
  98. package/dist/inference/interruption/ws_transport.cjs +329 -0
  99. package/dist/inference/interruption/ws_transport.cjs.map +1 -0
  100. package/dist/inference/interruption/ws_transport.d.cts +33 -0
  101. package/dist/inference/interruption/ws_transport.d.ts +33 -0
  102. package/dist/inference/interruption/ws_transport.d.ts.map +1 -0
  103. package/dist/inference/interruption/ws_transport.js +295 -0
  104. package/dist/inference/interruption/ws_transport.js.map +1 -0
  105. package/dist/inference/llm.cjs +14 -10
  106. package/dist/inference/llm.cjs.map +1 -1
  107. package/dist/inference/llm.d.cts +2 -1
  108. package/dist/inference/llm.d.ts +2 -1
  109. package/dist/inference/llm.d.ts.map +1 -1
  110. package/dist/inference/llm.js +8 -10
  111. package/dist/inference/llm.js.map +1 -1
  112. package/dist/inference/stt.cjs +7 -2
  113. package/dist/inference/stt.cjs.map +1 -1
  114. package/dist/inference/stt.d.cts +2 -0
  115. package/dist/inference/stt.d.ts +2 -0
  116. package/dist/inference/stt.d.ts.map +1 -1
  117. package/dist/inference/stt.js +8 -3
  118. package/dist/inference/stt.js.map +1 -1
  119. package/dist/inference/tts.cjs +7 -2
  120. package/dist/inference/tts.cjs.map +1 -1
  121. package/dist/inference/tts.d.cts +2 -0
  122. package/dist/inference/tts.d.ts +2 -0
  123. package/dist/inference/tts.d.ts.map +1 -1
  124. package/dist/inference/tts.js +8 -3
  125. package/dist/inference/tts.js.map +1 -1
  126. package/dist/inference/utils.cjs +26 -7
  127. package/dist/inference/utils.cjs.map +1 -1
  128. package/dist/inference/utils.d.cts +13 -0
  129. package/dist/inference/utils.d.ts +13 -0
  130. package/dist/inference/utils.d.ts.map +1 -1
  131. package/dist/inference/utils.js +18 -2
  132. package/dist/inference/utils.js.map +1 -1
  133. package/dist/llm/chat_context.cjs +108 -2
  134. package/dist/llm/chat_context.cjs.map +1 -1
  135. package/dist/llm/chat_context.d.cts +28 -1
  136. package/dist/llm/chat_context.d.ts +28 -1
  137. package/dist/llm/chat_context.d.ts.map +1 -1
  138. package/dist/llm/chat_context.js +108 -2
  139. package/dist/llm/chat_context.js.map +1 -1
  140. package/dist/llm/chat_context.test.cjs +43 -0
  141. package/dist/llm/chat_context.test.cjs.map +1 -1
  142. package/dist/llm/chat_context.test.js +43 -0
  143. package/dist/llm/chat_context.test.js.map +1 -1
  144. package/dist/llm/index.cjs +2 -0
  145. package/dist/llm/index.cjs.map +1 -1
  146. package/dist/llm/index.d.cts +2 -2
  147. package/dist/llm/index.d.ts +2 -2
  148. package/dist/llm/index.d.ts.map +1 -1
  149. package/dist/llm/index.js +3 -1
  150. package/dist/llm/index.js.map +1 -1
  151. package/dist/llm/llm.cjs +16 -1
  152. package/dist/llm/llm.cjs.map +1 -1
  153. package/dist/llm/llm.d.cts +9 -0
  154. package/dist/llm/llm.d.ts +9 -0
  155. package/dist/llm/llm.d.ts.map +1 -1
  156. package/dist/llm/llm.js +16 -1
  157. package/dist/llm/llm.js.map +1 -1
  158. package/dist/llm/provider_format/index.d.cts +1 -1
  159. package/dist/llm/provider_format/index.d.ts +1 -1
  160. package/dist/llm/realtime.cjs +3 -0
  161. package/dist/llm/realtime.cjs.map +1 -1
  162. package/dist/llm/realtime.d.cts +1 -0
  163. package/dist/llm/realtime.d.ts +1 -0
  164. package/dist/llm/realtime.d.ts.map +1 -1
  165. package/dist/llm/realtime.js +3 -0
  166. package/dist/llm/realtime.js.map +1 -1
  167. package/dist/llm/tool_context.cjs +7 -0
  168. package/dist/llm/tool_context.cjs.map +1 -1
  169. package/dist/llm/tool_context.d.cts +10 -2
  170. package/dist/llm/tool_context.d.ts +10 -2
  171. package/dist/llm/tool_context.d.ts.map +1 -1
  172. package/dist/llm/tool_context.js +6 -0
  173. package/dist/llm/tool_context.js.map +1 -1
  174. package/dist/metrics/base.cjs.map +1 -1
  175. package/dist/metrics/base.d.cts +45 -1
  176. package/dist/metrics/base.d.ts +45 -1
  177. package/dist/metrics/base.d.ts.map +1 -1
  178. package/dist/metrics/index.cjs +5 -0
  179. package/dist/metrics/index.cjs.map +1 -1
  180. package/dist/metrics/index.d.cts +2 -1
  181. package/dist/metrics/index.d.ts +2 -1
  182. package/dist/metrics/index.d.ts.map +1 -1
  183. package/dist/metrics/index.js +6 -0
  184. package/dist/metrics/index.js.map +1 -1
  185. package/dist/metrics/model_usage.cjs +189 -0
  186. package/dist/metrics/model_usage.cjs.map +1 -0
  187. package/dist/metrics/model_usage.d.cts +92 -0
  188. package/dist/metrics/model_usage.d.ts +92 -0
  189. package/dist/metrics/model_usage.d.ts.map +1 -0
  190. package/dist/metrics/model_usage.js +164 -0
  191. package/dist/metrics/model_usage.js.map +1 -0
  192. package/dist/metrics/model_usage.test.cjs +474 -0
  193. package/dist/metrics/model_usage.test.cjs.map +1 -0
  194. package/dist/metrics/model_usage.test.js +476 -0
  195. package/dist/metrics/model_usage.test.js.map +1 -0
  196. package/dist/metrics/usage_collector.cjs +3 -0
  197. package/dist/metrics/usage_collector.cjs.map +1 -1
  198. package/dist/metrics/usage_collector.d.cts +9 -0
  199. package/dist/metrics/usage_collector.d.ts +9 -0
  200. package/dist/metrics/usage_collector.d.ts.map +1 -1
  201. package/dist/metrics/usage_collector.js +3 -0
  202. package/dist/metrics/usage_collector.js.map +1 -1
  203. package/dist/metrics/utils.cjs +9 -0
  204. package/dist/metrics/utils.cjs.map +1 -1
  205. package/dist/metrics/utils.d.ts.map +1 -1
  206. package/dist/metrics/utils.js +9 -0
  207. package/dist/metrics/utils.js.map +1 -1
  208. package/dist/stream/multi_input_stream.test.cjs +4 -0
  209. package/dist/stream/multi_input_stream.test.cjs.map +1 -1
  210. package/dist/stream/multi_input_stream.test.js +5 -1
  211. package/dist/stream/multi_input_stream.test.js.map +1 -1
  212. package/dist/stream/stream_channel.cjs +31 -0
  213. package/dist/stream/stream_channel.cjs.map +1 -1
  214. package/dist/stream/stream_channel.d.cts +4 -2
  215. package/dist/stream/stream_channel.d.ts +4 -2
  216. package/dist/stream/stream_channel.d.ts.map +1 -1
  217. package/dist/stream/stream_channel.js +31 -0
  218. package/dist/stream/stream_channel.js.map +1 -1
  219. package/dist/stt/stt.cjs +34 -2
  220. package/dist/stt/stt.cjs.map +1 -1
  221. package/dist/stt/stt.d.cts +22 -0
  222. package/dist/stt/stt.d.ts +22 -0
  223. package/dist/stt/stt.d.ts.map +1 -1
  224. package/dist/stt/stt.js +34 -2
  225. package/dist/stt/stt.js.map +1 -1
  226. package/dist/telemetry/otel_http_exporter.cjs +24 -5
  227. package/dist/telemetry/otel_http_exporter.cjs.map +1 -1
  228. package/dist/telemetry/otel_http_exporter.d.cts +1 -0
  229. package/dist/telemetry/otel_http_exporter.d.ts +1 -0
  230. package/dist/telemetry/otel_http_exporter.d.ts.map +1 -1
  231. package/dist/telemetry/otel_http_exporter.js +24 -5
  232. package/dist/telemetry/otel_http_exporter.js.map +1 -1
  233. package/dist/telemetry/trace_types.cjs +5 -5
  234. package/dist/telemetry/trace_types.cjs.map +1 -1
  235. package/dist/telemetry/trace_types.d.cts +9 -5
  236. package/dist/telemetry/trace_types.d.ts +9 -5
  237. package/dist/telemetry/trace_types.d.ts.map +1 -1
  238. package/dist/telemetry/trace_types.js +5 -5
  239. package/dist/telemetry/trace_types.js.map +1 -1
  240. package/dist/telemetry/traces.cjs +47 -8
  241. package/dist/telemetry/traces.cjs.map +1 -1
  242. package/dist/telemetry/traces.d.ts.map +1 -1
  243. package/dist/telemetry/traces.js +47 -8
  244. package/dist/telemetry/traces.js.map +1 -1
  245. package/dist/tts/tts.cjs +64 -2
  246. package/dist/tts/tts.cjs.map +1 -1
  247. package/dist/tts/tts.d.cts +34 -0
  248. package/dist/tts/tts.d.ts +34 -0
  249. package/dist/tts/tts.d.ts.map +1 -1
  250. package/dist/tts/tts.js +64 -2
  251. package/dist/tts/tts.js.map +1 -1
  252. package/dist/utils.cjs +1 -0
  253. package/dist/utils.cjs.map +1 -1
  254. package/dist/utils.d.ts.map +1 -1
  255. package/dist/utils.js +1 -0
  256. package/dist/utils.js.map +1 -1
  257. package/dist/version.cjs +1 -1
  258. package/dist/version.js +1 -1
  259. package/dist/voice/agent.cjs +34 -4
  260. package/dist/voice/agent.cjs.map +1 -1
  261. package/dist/voice/agent.d.cts +11 -2
  262. package/dist/voice/agent.d.ts +11 -2
  263. package/dist/voice/agent.d.ts.map +1 -1
  264. package/dist/voice/agent.js +34 -4
  265. package/dist/voice/agent.js.map +1 -1
  266. package/dist/voice/agent_activity.cjs +292 -44
  267. package/dist/voice/agent_activity.cjs.map +1 -1
  268. package/dist/voice/agent_activity.d.cts +27 -6
  269. package/dist/voice/agent_activity.d.ts +27 -6
  270. package/dist/voice/agent_activity.d.ts.map +1 -1
  271. package/dist/voice/agent_activity.js +293 -45
  272. package/dist/voice/agent_activity.js.map +1 -1
  273. package/dist/voice/agent_session.cjs +105 -48
  274. package/dist/voice/agent_session.cjs.map +1 -1
  275. package/dist/voice/agent_session.d.cts +90 -20
  276. package/dist/voice/agent_session.d.ts +90 -20
  277. package/dist/voice/agent_session.d.ts.map +1 -1
  278. package/dist/voice/agent_session.js +105 -46
  279. package/dist/voice/agent_session.js.map +1 -1
  280. package/dist/voice/audio_recognition.cjs +287 -6
  281. package/dist/voice/audio_recognition.cjs.map +1 -1
  282. package/dist/voice/audio_recognition.d.cts +42 -3
  283. package/dist/voice/audio_recognition.d.ts +42 -3
  284. package/dist/voice/audio_recognition.d.ts.map +1 -1
  285. package/dist/voice/audio_recognition.js +289 -7
  286. package/dist/voice/audio_recognition.js.map +1 -1
  287. package/dist/voice/client_events.cjs +554 -0
  288. package/dist/voice/client_events.cjs.map +1 -0
  289. package/dist/voice/client_events.d.cts +195 -0
  290. package/dist/voice/client_events.d.ts +195 -0
  291. package/dist/voice/client_events.d.ts.map +1 -0
  292. package/dist/voice/client_events.js +548 -0
  293. package/dist/voice/client_events.js.map +1 -0
  294. package/dist/voice/events.cjs +1 -0
  295. package/dist/voice/events.cjs.map +1 -1
  296. package/dist/voice/events.d.cts +8 -5
  297. package/dist/voice/events.d.ts +8 -5
  298. package/dist/voice/events.d.ts.map +1 -1
  299. package/dist/voice/events.js +1 -0
  300. package/dist/voice/events.js.map +1 -1
  301. package/dist/voice/generation.cjs +43 -8
  302. package/dist/voice/generation.cjs.map +1 -1
  303. package/dist/voice/generation.d.cts +3 -3
  304. package/dist/voice/generation.d.ts +3 -3
  305. package/dist/voice/generation.d.ts.map +1 -1
  306. package/dist/voice/generation.js +43 -8
  307. package/dist/voice/generation.js.map +1 -1
  308. package/dist/voice/index.cjs +1 -0
  309. package/dist/voice/index.cjs.map +1 -1
  310. package/dist/voice/index.d.cts +1 -0
  311. package/dist/voice/index.d.ts +1 -0
  312. package/dist/voice/index.d.ts.map +1 -1
  313. package/dist/voice/index.js +1 -0
  314. package/dist/voice/index.js.map +1 -1
  315. package/dist/voice/report.cjs +20 -8
  316. package/dist/voice/report.cjs.map +1 -1
  317. package/dist/voice/report.d.cts +5 -0
  318. package/dist/voice/report.d.ts +5 -0
  319. package/dist/voice/report.d.ts.map +1 -1
  320. package/dist/voice/report.js +20 -8
  321. package/dist/voice/report.js.map +1 -1
  322. package/dist/voice/report.test.cjs +106 -0
  323. package/dist/voice/report.test.cjs.map +1 -0
  324. package/dist/voice/report.test.js +105 -0
  325. package/dist/voice/report.test.js.map +1 -0
  326. package/dist/voice/room_io/room_io.cjs +16 -41
  327. package/dist/voice/room_io/room_io.cjs.map +1 -1
  328. package/dist/voice/room_io/room_io.d.cts +4 -9
  329. package/dist/voice/room_io/room_io.d.ts +4 -9
  330. package/dist/voice/room_io/room_io.d.ts.map +1 -1
  331. package/dist/voice/room_io/room_io.js +17 -43
  332. package/dist/voice/room_io/room_io.js.map +1 -1
  333. package/dist/voice/testing/fake_llm.cjs +127 -0
  334. package/dist/voice/testing/fake_llm.cjs.map +1 -0
  335. package/dist/voice/testing/fake_llm.d.cts +30 -0
  336. package/dist/voice/testing/fake_llm.d.ts +30 -0
  337. package/dist/voice/testing/fake_llm.d.ts.map +1 -0
  338. package/dist/voice/testing/fake_llm.js +103 -0
  339. package/dist/voice/testing/fake_llm.js.map +1 -0
  340. package/dist/voice/testing/index.cjs +3 -0
  341. package/dist/voice/testing/index.cjs.map +1 -1
  342. package/dist/voice/testing/index.d.cts +1 -0
  343. package/dist/voice/testing/index.d.ts +1 -0
  344. package/dist/voice/testing/index.d.ts.map +1 -1
  345. package/dist/voice/testing/index.js +2 -0
  346. package/dist/voice/testing/index.js.map +1 -1
  347. package/dist/voice/turn_config/endpointing.cjs +33 -0
  348. package/dist/voice/turn_config/endpointing.cjs.map +1 -0
  349. package/dist/voice/turn_config/endpointing.d.cts +30 -0
  350. package/dist/voice/turn_config/endpointing.d.ts +30 -0
  351. package/dist/voice/turn_config/endpointing.d.ts.map +1 -0
  352. package/dist/voice/turn_config/endpointing.js +9 -0
  353. package/dist/voice/turn_config/endpointing.js.map +1 -0
  354. package/dist/voice/turn_config/interruption.cjs +37 -0
  355. package/dist/voice/turn_config/interruption.cjs.map +1 -0
  356. package/dist/voice/turn_config/interruption.d.cts +53 -0
  357. package/dist/voice/turn_config/interruption.d.ts +53 -0
  358. package/dist/voice/turn_config/interruption.d.ts.map +1 -0
  359. package/dist/voice/turn_config/interruption.js +13 -0
  360. package/dist/voice/turn_config/interruption.js.map +1 -0
  361. package/dist/voice/turn_config/turn_handling.cjs +35 -0
  362. package/dist/voice/turn_config/turn_handling.cjs.map +1 -0
  363. package/dist/voice/turn_config/turn_handling.d.cts +36 -0
  364. package/dist/voice/turn_config/turn_handling.d.ts +36 -0
  365. package/dist/voice/turn_config/turn_handling.d.ts.map +1 -0
  366. package/dist/voice/turn_config/turn_handling.js +11 -0
  367. package/dist/voice/turn_config/turn_handling.js.map +1 -0
  368. package/dist/voice/turn_config/utils.cjs +97 -0
  369. package/dist/voice/turn_config/utils.cjs.map +1 -0
  370. package/dist/voice/turn_config/utils.d.cts +25 -0
  371. package/dist/voice/turn_config/utils.d.ts +25 -0
  372. package/dist/voice/turn_config/utils.d.ts.map +1 -0
  373. package/dist/voice/turn_config/utils.js +73 -0
  374. package/dist/voice/turn_config/utils.js.map +1 -0
  375. package/dist/voice/turn_config/utils.test.cjs +86 -0
  376. package/dist/voice/turn_config/utils.test.cjs.map +1 -0
  377. package/dist/voice/turn_config/utils.test.js +85 -0
  378. package/dist/voice/turn_config/utils.test.js.map +1 -0
  379. package/dist/voice/wire_format.cjs +798 -0
  380. package/dist/voice/wire_format.cjs.map +1 -0
  381. package/dist/voice/wire_format.d.cts +5503 -0
  382. package/dist/voice/wire_format.d.ts +5503 -0
  383. package/dist/voice/wire_format.d.ts.map +1 -0
  384. package/dist/voice/wire_format.js +728 -0
  385. package/dist/voice/wire_format.js.map +1 -0
  386. package/package.json +2 -1
  387. package/src/beta/index.ts +9 -0
  388. package/src/beta/workflows/index.ts +9 -0
  389. package/src/beta/workflows/task_group.ts +194 -0
  390. package/src/constants.ts +13 -0
  391. package/src/index.ts +2 -1
  392. package/src/inference/interruption/defaults.ts +51 -0
  393. package/src/inference/interruption/errors.ts +25 -0
  394. package/src/inference/interruption/http_transport.ts +187 -0
  395. package/src/inference/interruption/interruption_cache_entry.ts +50 -0
  396. package/src/inference/interruption/interruption_detector.ts +188 -0
  397. package/src/inference/interruption/interruption_stream.ts +467 -0
  398. package/src/inference/interruption/types.ts +84 -0
  399. package/src/inference/interruption/utils.test.ts +132 -0
  400. package/src/inference/interruption/utils.ts +137 -0
  401. package/src/inference/interruption/ws_transport.ts +402 -0
  402. package/src/inference/llm.ts +9 -12
  403. package/src/inference/stt.ts +10 -3
  404. package/src/inference/tts.ts +10 -3
  405. package/src/inference/utils.ts +29 -1
  406. package/src/llm/chat_context.test.ts +48 -0
  407. package/src/llm/chat_context.ts +161 -0
  408. package/src/llm/index.ts +2 -0
  409. package/src/llm/llm.ts +16 -0
  410. package/src/llm/realtime.ts +4 -0
  411. package/src/llm/tool_context.ts +14 -0
  412. package/src/metrics/base.ts +48 -1
  413. package/src/metrics/index.ts +11 -0
  414. package/src/metrics/model_usage.test.ts +545 -0
  415. package/src/metrics/model_usage.ts +262 -0
  416. package/src/metrics/usage_collector.ts +11 -0
  417. package/src/metrics/utils.ts +11 -0
  418. package/src/stream/multi_input_stream.test.ts +6 -1
  419. package/src/stream/stream_channel.ts +34 -2
  420. package/src/stt/stt.ts +38 -0
  421. package/src/telemetry/otel_http_exporter.ts +28 -5
  422. package/src/telemetry/trace_types.ts +11 -8
  423. package/src/telemetry/traces.ts +111 -54
  424. package/src/tts/tts.ts +69 -1
  425. package/src/utils.ts +5 -0
  426. package/src/voice/agent.ts +41 -3
  427. package/src/voice/agent_activity.ts +371 -34
  428. package/src/voice/agent_session.ts +207 -59
  429. package/src/voice/audio_recognition.ts +385 -9
  430. package/src/voice/client_events.ts +838 -0
  431. package/src/voice/events.ts +14 -4
  432. package/src/voice/generation.ts +52 -9
  433. package/src/voice/index.ts +1 -0
  434. package/src/voice/report.test.ts +117 -0
  435. package/src/voice/report.ts +29 -6
  436. package/src/voice/room_io/room_io.ts +21 -64
  437. package/src/voice/testing/fake_llm.ts +138 -0
  438. package/src/voice/testing/index.ts +2 -0
  439. package/src/voice/turn_config/endpointing.ts +33 -0
  440. package/src/voice/turn_config/interruption.ts +56 -0
  441. package/src/voice/turn_config/turn_handling.ts +45 -0
  442. package/src/voice/turn_config/utils.test.ts +100 -0
  443. package/src/voice/turn_config/utils.ts +103 -0
  444. package/src/voice/wire_format.ts +827 -0
@@ -1 +1 @@
1
- {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/voice/report.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,WAAW,EAAE,WAAW,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;IACzB,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,wGAAwG;IACxG,SAAS,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gEAAgE;IAChE,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,WAAW,EAAE,WAAW,CAAC;IACzB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gEAAgE;IAChE,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,oBAAoB,GAAG,aAAa,CAmB7E;AAMD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA6BlF"}
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/voice/report.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,KAAK,UAAU,EAAoB,MAAM,2BAA2B,CAAC;AAC9E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,WAAW,EAAE,WAAW,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;IACzB,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,wGAAwG;IACxG,SAAS,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gEAAgE;IAChE,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,WAAW,EAAE,WAAW,CAAC;IACzB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gEAAgE;IAChE,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,0EAA0E;IAC1E,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,oBAAoB,GAAG,aAAa,CAoB7E;AAMD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA8ClF"}
@@ -1,3 +1,4 @@
1
+ import { filterZeroValues } from "../metrics/model_usage.js";
1
2
  function createSessionReport(opts) {
2
3
  const timestamp = opts.timestamp ?? Date.now();
3
4
  const audioRecordingStartedAt = opts.audioRecordingStartedAt;
@@ -13,11 +14,21 @@ function createSessionReport(opts) {
13
14
  timestamp,
14
15
  audioRecordingPath: opts.audioRecordingPath,
15
16
  audioRecordingStartedAt,
16
- duration: audioRecordingStartedAt !== void 0 ? timestamp - audioRecordingStartedAt : void 0
17
+ duration: audioRecordingStartedAt !== void 0 ? timestamp - audioRecordingStartedAt : void 0,
18
+ modelUsage: opts.modelUsage
17
19
  };
18
20
  }
19
21
  function sessionReportToJSON(report) {
22
+ var _a, _b;
20
23
  const events = [];
24
+ const interruptionConfig = (_a = report.options.turnHandling) == null ? void 0 : _a.interruption;
25
+ const endpointingConfig = (_b = report.options.turnHandling) == null ? void 0 : _b.endpointing;
26
+ const allowInterruptions = (interruptionConfig == null ? void 0 : interruptionConfig.mode) !== void 0 ? interruptionConfig.mode !== false : report.options.allowInterruptions;
27
+ const discardAudioIfUninterruptible = (interruptionConfig == null ? void 0 : interruptionConfig.discardAudioIfUninterruptible) ?? report.options.discardAudioIfUninterruptible;
28
+ const minInterruptionDuration = (interruptionConfig == null ? void 0 : interruptionConfig.minDuration) ?? report.options.minInterruptionDuration;
29
+ const minInterruptionWords = (interruptionConfig == null ? void 0 : interruptionConfig.minWords) ?? report.options.minInterruptionWords;
30
+ const minEndpointingDelay = (endpointingConfig == null ? void 0 : endpointingConfig.minDelay) ?? report.options.minEndpointingDelay;
31
+ const maxEndpointingDelay = (endpointingConfig == null ? void 0 : endpointingConfig.maxDelay) ?? report.options.maxEndpointingDelay;
21
32
  for (const event of report.events) {
22
33
  if (event.type === "metrics_collected") {
23
34
  continue;
@@ -30,17 +41,18 @@ function sessionReportToJSON(report) {
30
41
  room: report.room,
31
42
  events,
32
43
  options: {
33
- allow_interruptions: report.options.allowInterruptions,
34
- discard_audio_if_uninterruptible: report.options.discardAudioIfUninterruptible,
35
- min_interruption_duration: report.options.minInterruptionDuration,
36
- min_interruption_words: report.options.minInterruptionWords,
37
- min_endpointing_delay: report.options.minEndpointingDelay,
38
- max_endpointing_delay: report.options.maxEndpointingDelay,
44
+ allow_interruptions: allowInterruptions,
45
+ discard_audio_if_uninterruptible: discardAudioIfUninterruptible,
46
+ min_interruption_duration: minInterruptionDuration,
47
+ min_interruption_words: minInterruptionWords,
48
+ min_endpointing_delay: minEndpointingDelay,
49
+ max_endpointing_delay: maxEndpointingDelay,
39
50
  max_tool_steps: report.options.maxToolSteps
40
51
  },
41
52
  chat_history: report.chatHistory.toJSON({ excludeTimestamp: false }),
42
53
  enable_user_data_training: report.enableRecording,
43
- timestamp: report.timestamp
54
+ timestamp: report.timestamp,
55
+ usage: report.modelUsage ? report.modelUsage.map(filterZeroValues) : null
44
56
  };
45
57
  }
46
58
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/voice/report.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { ChatContext } from '../llm/chat_context.js';\nimport type { VoiceOptions } from './agent_session.js';\nimport type { AgentEvent } from './events.js';\n\nexport interface SessionReport {\n jobId: string;\n roomId: string;\n room: string;\n options: VoiceOptions;\n events: AgentEvent[];\n chatHistory: ChatContext;\n enableRecording: boolean;\n /** Timestamp when the session started (milliseconds) */\n startedAt: number;\n /** Timestamp when the session report was created (milliseconds), typically at the end of the session */\n timestamp: number;\n /** Path to the audio recording file (if recording was enabled) */\n audioRecordingPath?: string;\n /** Timestamp when the audio recording started (milliseconds) */\n audioRecordingStartedAt?: number;\n /** Duration of the session in milliseconds */\n duration?: number;\n}\n\nexport interface SessionReportOptions {\n jobId: string;\n roomId: string;\n room: string;\n options: VoiceOptions;\n events: AgentEvent[];\n chatHistory: ChatContext;\n enableRecording?: boolean;\n /** Timestamp when the session started (milliseconds) */\n startedAt?: number;\n /** Timestamp when the session report was created (milliseconds) */\n timestamp?: number;\n /** Path to the audio recording file (if recording was enabled) */\n audioRecordingPath?: string;\n /** Timestamp when the audio recording started (milliseconds) */\n audioRecordingStartedAt?: number;\n}\n\nexport function createSessionReport(opts: SessionReportOptions): SessionReport {\n const timestamp = opts.timestamp ?? Date.now();\n const audioRecordingStartedAt = opts.audioRecordingStartedAt;\n\n return {\n jobId: opts.jobId,\n roomId: opts.roomId,\n room: opts.room,\n options: opts.options,\n events: opts.events,\n chatHistory: opts.chatHistory,\n enableRecording: opts.enableRecording ?? false,\n startedAt: opts.startedAt ?? Date.now(),\n timestamp,\n audioRecordingPath: opts.audioRecordingPath,\n audioRecordingStartedAt,\n duration:\n audioRecordingStartedAt !== undefined ? timestamp - audioRecordingStartedAt : undefined,\n };\n}\n\n// - header: protobuf MetricsRecordingHeader (room_id, duration, start_time)\n// - chat_history: JSON serialized chat history (use sessionReportToJSON)\n// - audio: audio recording file if available (ogg format)\n// - Uploads to LiveKit Cloud observability endpoint with JWT auth\nexport function sessionReportToJSON(report: SessionReport): Record<string, unknown> {\n const events: Record<string, unknown>[] = [];\n\n for (const event of report.events) {\n if (event.type === 'metrics_collected') {\n continue; // metrics are too noisy, Cloud is using the chat_history as the source of truth\n }\n\n events.push({ ...event });\n }\n\n return {\n job_id: report.jobId,\n room_id: report.roomId,\n room: report.room,\n events,\n options: {\n allow_interruptions: report.options.allowInterruptions,\n discard_audio_if_uninterruptible: report.options.discardAudioIfUninterruptible,\n min_interruption_duration: report.options.minInterruptionDuration,\n min_interruption_words: report.options.minInterruptionWords,\n min_endpointing_delay: report.options.minEndpointingDelay,\n max_endpointing_delay: report.options.maxEndpointingDelay,\n max_tool_steps: report.options.maxToolSteps,\n },\n chat_history: report.chatHistory.toJSON({ excludeTimestamp: false }),\n enable_user_data_training: report.enableRecording,\n timestamp: report.timestamp,\n };\n}\n"],"mappings":"AA6CO,SAAS,oBAAoB,MAA2C;AAC7E,QAAM,YAAY,KAAK,aAAa,KAAK,IAAI;AAC7C,QAAM,0BAA0B,KAAK;AAErC,SAAO;AAAA,IACL,OAAO,KAAK;AAAA,IACZ,QAAQ,KAAK;AAAA,IACb,MAAM,KAAK;AAAA,IACX,SAAS,KAAK;AAAA,IACd,QAAQ,KAAK;AAAA,IACb,aAAa,KAAK;AAAA,IAClB,iBAAiB,KAAK,mBAAmB;AAAA,IACzC,WAAW,KAAK,aAAa,KAAK,IAAI;AAAA,IACtC;AAAA,IACA,oBAAoB,KAAK;AAAA,IACzB;AAAA,IACA,UACE,4BAA4B,SAAY,YAAY,0BAA0B;AAAA,EAClF;AACF;AAMO,SAAS,oBAAoB,QAAgD;AAClF,QAAM,SAAoC,CAAC;AAE3C,aAAW,SAAS,OAAO,QAAQ;AACjC,QAAI,MAAM,SAAS,qBAAqB;AACtC;AAAA,IACF;AAEA,WAAO,KAAK,EAAE,GAAG,MAAM,CAAC;AAAA,EAC1B;AAEA,SAAO;AAAA,IACL,QAAQ,OAAO;AAAA,IACf,SAAS,OAAO;AAAA,IAChB,MAAM,OAAO;AAAA,IACb;AAAA,IACA,SAAS;AAAA,MACP,qBAAqB,OAAO,QAAQ;AAAA,MACpC,kCAAkC,OAAO,QAAQ;AAAA,MACjD,2BAA2B,OAAO,QAAQ;AAAA,MAC1C,wBAAwB,OAAO,QAAQ;AAAA,MACvC,uBAAuB,OAAO,QAAQ;AAAA,MACtC,uBAAuB,OAAO,QAAQ;AAAA,MACtC,gBAAgB,OAAO,QAAQ;AAAA,IACjC;AAAA,IACA,cAAc,OAAO,YAAY,OAAO,EAAE,kBAAkB,MAAM,CAAC;AAAA,IACnE,2BAA2B,OAAO;AAAA,IAClC,WAAW,OAAO;AAAA,EACpB;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/voice/report.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { ChatContext } from '../llm/chat_context.js';\nimport { type ModelUsage, filterZeroValues } from '../metrics/model_usage.js';\nimport type { VoiceOptions } from './agent_session.js';\nimport type { AgentEvent } from './events.js';\n\nexport interface SessionReport {\n jobId: string;\n roomId: string;\n room: string;\n options: VoiceOptions;\n events: AgentEvent[];\n chatHistory: ChatContext;\n enableRecording: boolean;\n /** Timestamp when the session started (milliseconds) */\n startedAt: number;\n /** Timestamp when the session report was created (milliseconds), typically at the end of the session */\n timestamp: number;\n /** Path to the audio recording file (if recording was enabled) */\n audioRecordingPath?: string;\n /** Timestamp when the audio recording started (milliseconds) */\n audioRecordingStartedAt?: number;\n /** Duration of the session in milliseconds */\n duration?: number;\n /** Usage summaries for the session, one per model/provider combination */\n modelUsage?: ModelUsage[];\n}\n\nexport interface SessionReportOptions {\n jobId: string;\n roomId: string;\n room: string;\n options: VoiceOptions;\n events: AgentEvent[];\n chatHistory: ChatContext;\n enableRecording?: boolean;\n /** Timestamp when the session started (milliseconds) */\n startedAt?: number;\n /** Timestamp when the session report was created (milliseconds) */\n timestamp?: number;\n /** Path to the audio recording file (if recording was enabled) */\n audioRecordingPath?: string;\n /** Timestamp when the audio recording started (milliseconds) */\n audioRecordingStartedAt?: number;\n /** Usage summaries for the session, one per model/provider combination */\n modelUsage?: ModelUsage[];\n}\n\nexport function createSessionReport(opts: SessionReportOptions): SessionReport {\n const timestamp = opts.timestamp ?? Date.now();\n const audioRecordingStartedAt = opts.audioRecordingStartedAt;\n\n return {\n jobId: opts.jobId,\n roomId: opts.roomId,\n room: opts.room,\n options: opts.options,\n events: opts.events,\n chatHistory: opts.chatHistory,\n enableRecording: opts.enableRecording ?? false,\n startedAt: opts.startedAt ?? Date.now(),\n timestamp,\n audioRecordingPath: opts.audioRecordingPath,\n audioRecordingStartedAt,\n duration:\n audioRecordingStartedAt !== undefined ? timestamp - audioRecordingStartedAt : undefined,\n modelUsage: opts.modelUsage,\n };\n}\n\n// - header: protobuf MetricsRecordingHeader (room_id, duration, start_time)\n// - chat_history: JSON serialized chat history (use sessionReportToJSON)\n// - audio: audio recording file if available (ogg format)\n// - Uploads to LiveKit Cloud observability endpoint with JWT auth\nexport function sessionReportToJSON(report: SessionReport): Record<string, unknown> {\n const events: Record<string, unknown>[] = [];\n const interruptionConfig = report.options.turnHandling?.interruption;\n const endpointingConfig = report.options.turnHandling?.endpointing;\n\n // Keep backwards compatibility with deprecated fields\n const allowInterruptions =\n interruptionConfig?.mode !== undefined\n ? interruptionConfig.mode !== false\n : report.options.allowInterruptions;\n const discardAudioIfUninterruptible =\n interruptionConfig?.discardAudioIfUninterruptible ??\n report.options.discardAudioIfUninterruptible;\n const minInterruptionDuration =\n interruptionConfig?.minDuration ?? report.options.minInterruptionDuration;\n const minInterruptionWords = interruptionConfig?.minWords ?? report.options.minInterruptionWords;\n const minEndpointingDelay = endpointingConfig?.minDelay ?? report.options.minEndpointingDelay;\n const maxEndpointingDelay = endpointingConfig?.maxDelay ?? report.options.maxEndpointingDelay;\n\n for (const event of report.events) {\n if (event.type === 'metrics_collected') {\n continue; // metrics are too noisy, Cloud is using the chat_history as the source of truth\n }\n\n events.push({ ...event });\n }\n\n return {\n job_id: report.jobId,\n room_id: report.roomId,\n room: report.room,\n events,\n options: {\n allow_interruptions: allowInterruptions,\n discard_audio_if_uninterruptible: discardAudioIfUninterruptible,\n min_interruption_duration: minInterruptionDuration,\n min_interruption_words: minInterruptionWords,\n min_endpointing_delay: minEndpointingDelay,\n max_endpointing_delay: maxEndpointingDelay,\n max_tool_steps: report.options.maxToolSteps,\n },\n chat_history: report.chatHistory.toJSON({ excludeTimestamp: false }),\n enable_user_data_training: report.enableRecording,\n timestamp: report.timestamp,\n usage: report.modelUsage ? report.modelUsage.map(filterZeroValues) : null,\n };\n}\n"],"mappings":"AAIA,SAA0B,wBAAwB;AA8C3C,SAAS,oBAAoB,MAA2C;AAC7E,QAAM,YAAY,KAAK,aAAa,KAAK,IAAI;AAC7C,QAAM,0BAA0B,KAAK;AAErC,SAAO;AAAA,IACL,OAAO,KAAK;AAAA,IACZ,QAAQ,KAAK;AAAA,IACb,MAAM,KAAK;AAAA,IACX,SAAS,KAAK;AAAA,IACd,QAAQ,KAAK;AAAA,IACb,aAAa,KAAK;AAAA,IAClB,iBAAiB,KAAK,mBAAmB;AAAA,IACzC,WAAW,KAAK,aAAa,KAAK,IAAI;AAAA,IACtC;AAAA,IACA,oBAAoB,KAAK;AAAA,IACzB;AAAA,IACA,UACE,4BAA4B,SAAY,YAAY,0BAA0B;AAAA,IAChF,YAAY,KAAK;AAAA,EACnB;AACF;AAMO,SAAS,oBAAoB,QAAgD;AA5EpF;AA6EE,QAAM,SAAoC,CAAC;AAC3C,QAAM,sBAAqB,YAAO,QAAQ,iBAAf,mBAA6B;AACxD,QAAM,qBAAoB,YAAO,QAAQ,iBAAf,mBAA6B;AAGvD,QAAM,sBACJ,yDAAoB,UAAS,SACzB,mBAAmB,SAAS,QAC5B,OAAO,QAAQ;AACrB,QAAM,iCACJ,yDAAoB,kCACpB,OAAO,QAAQ;AACjB,QAAM,2BACJ,yDAAoB,gBAAe,OAAO,QAAQ;AACpD,QAAM,wBAAuB,yDAAoB,aAAY,OAAO,QAAQ;AAC5E,QAAM,uBAAsB,uDAAmB,aAAY,OAAO,QAAQ;AAC1E,QAAM,uBAAsB,uDAAmB,aAAY,OAAO,QAAQ;AAE1E,aAAW,SAAS,OAAO,QAAQ;AACjC,QAAI,MAAM,SAAS,qBAAqB;AACtC;AAAA,IACF;AAEA,WAAO,KAAK,EAAE,GAAG,MAAM,CAAC;AAAA,EAC1B;AAEA,SAAO;AAAA,IACL,QAAQ,OAAO;AAAA,IACf,SAAS,OAAO;AAAA,IAChB,MAAM,OAAO;AAAA,IACb;AAAA,IACA,SAAS;AAAA,MACP,qBAAqB;AAAA,MACrB,kCAAkC;AAAA,MAClC,2BAA2B;AAAA,MAC3B,wBAAwB;AAAA,MACxB,uBAAuB;AAAA,MACvB,uBAAuB;AAAA,MACvB,gBAAgB,OAAO,QAAQ;AAAA,IACjC;AAAA,IACA,cAAc,OAAO,YAAY,OAAO,EAAE,kBAAkB,MAAM,CAAC;AAAA,IACnE,2BAA2B,OAAO;AAAA,IAClC,WAAW,OAAO;AAAA,IAClB,OAAO,OAAO,aAAa,OAAO,WAAW,IAAI,gBAAgB,IAAI;AAAA,EACvE;AACF;","names":[]}
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ var import_vitest = require("vitest");
3
+ var import_chat_context = require("../llm/chat_context.cjs");
4
+ var import_report = require("./report.cjs");
5
+ function baseOptions() {
6
+ return {
7
+ maxToolSteps: 3,
8
+ preemptiveGeneration: false,
9
+ userAwayTimeout: 15,
10
+ useTtsAlignedTranscript: true,
11
+ turnHandling: {}
12
+ };
13
+ }
14
+ function serializeOptions(options) {
15
+ const report = (0, import_report.createSessionReport)({
16
+ jobId: "job",
17
+ roomId: "room-id",
18
+ room: "room",
19
+ options,
20
+ events: [],
21
+ chatHistory: import_chat_context.ChatContext.empty(),
22
+ enableRecording: false,
23
+ timestamp: 0,
24
+ startedAt: 0
25
+ });
26
+ const payload = (0, import_report.sessionReportToJSON)(report);
27
+ return payload.options;
28
+ }
29
+ (0, import_vitest.describe)("sessionReportToJSON", () => {
30
+ (0, import_vitest.it)("serializes interruption and endpointing values from turnHandling", () => {
31
+ const options = baseOptions();
32
+ options.turnHandling = {
33
+ interruption: {
34
+ mode: "adaptive",
35
+ discardAudioIfUninterruptible: false,
36
+ minDuration: 1200,
37
+ minWords: 2
38
+ },
39
+ endpointing: {
40
+ minDelay: 900,
41
+ maxDelay: 4500
42
+ }
43
+ };
44
+ const serialized = serializeOptions(options);
45
+ (0, import_vitest.expect)(serialized).toMatchObject({
46
+ allow_interruptions: true,
47
+ discard_audio_if_uninterruptible: false,
48
+ min_interruption_duration: 1200,
49
+ min_interruption_words: 2,
50
+ min_endpointing_delay: 900,
51
+ max_endpointing_delay: 4500,
52
+ max_tool_steps: 3
53
+ });
54
+ });
55
+ (0, import_vitest.it)("prefers turnHandling values over deprecated flat fields", () => {
56
+ const options = baseOptions();
57
+ options.allowInterruptions = false;
58
+ options.discardAudioIfUninterruptible = true;
59
+ options.minInterruptionDuration = 400;
60
+ options.minInterruptionWords = 1;
61
+ options.minEndpointingDelay = 500;
62
+ options.maxEndpointingDelay = 2500;
63
+ options.turnHandling = {
64
+ interruption: {
65
+ mode: "vad",
66
+ discardAudioIfUninterruptible: false,
67
+ minDuration: 1400,
68
+ minWords: 4
69
+ },
70
+ endpointing: {
71
+ minDelay: 700,
72
+ maxDelay: 3900
73
+ }
74
+ };
75
+ const serialized = serializeOptions(options);
76
+ (0, import_vitest.expect)(serialized).toMatchObject({
77
+ allow_interruptions: true,
78
+ discard_audio_if_uninterruptible: false,
79
+ min_interruption_duration: 1400,
80
+ min_interruption_words: 4,
81
+ min_endpointing_delay: 700,
82
+ max_endpointing_delay: 3900,
83
+ max_tool_steps: 3
84
+ });
85
+ });
86
+ (0, import_vitest.it)("falls back to deprecated flat fields when turnHandling values are absent", () => {
87
+ const options = baseOptions();
88
+ options.allowInterruptions = false;
89
+ options.discardAudioIfUninterruptible = false;
90
+ options.minInterruptionDuration = 600;
91
+ options.minInterruptionWords = 3;
92
+ options.minEndpointingDelay = 1e3;
93
+ options.maxEndpointingDelay = 5e3;
94
+ const serialized = serializeOptions(options);
95
+ (0, import_vitest.expect)(serialized).toMatchObject({
96
+ allow_interruptions: false,
97
+ discard_audio_if_uninterruptible: false,
98
+ min_interruption_duration: 600,
99
+ min_interruption_words: 3,
100
+ min_endpointing_delay: 1e3,
101
+ max_endpointing_delay: 5e3,
102
+ max_tool_steps: 3
103
+ });
104
+ });
105
+ });
106
+ //# sourceMappingURL=report.test.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/voice/report.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2026 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { describe, expect, it } from 'vitest';\nimport { ChatContext } from '../llm/chat_context.js';\nimport type { VoiceOptions } from './agent_session.js';\nimport { createSessionReport, sessionReportToJSON } from './report.js';\n\nfunction baseOptions(): VoiceOptions {\n return {\n maxToolSteps: 3,\n preemptiveGeneration: false,\n userAwayTimeout: 15,\n useTtsAlignedTranscript: true,\n turnHandling: {},\n };\n}\n\nfunction serializeOptions(options: VoiceOptions) {\n const report = createSessionReport({\n jobId: 'job',\n roomId: 'room-id',\n room: 'room',\n options,\n events: [],\n chatHistory: ChatContext.empty(),\n enableRecording: false,\n timestamp: 0,\n startedAt: 0,\n });\n\n const payload = sessionReportToJSON(report);\n return payload.options as Record<string, unknown>;\n}\n\ndescribe('sessionReportToJSON', () => {\n it('serializes interruption and endpointing values from turnHandling', () => {\n const options = baseOptions();\n options.turnHandling = {\n interruption: {\n mode: 'adaptive',\n discardAudioIfUninterruptible: false,\n minDuration: 1200,\n minWords: 2,\n },\n endpointing: {\n minDelay: 900,\n maxDelay: 4500,\n },\n };\n\n const serialized = serializeOptions(options);\n expect(serialized).toMatchObject({\n allow_interruptions: true,\n discard_audio_if_uninterruptible: false,\n min_interruption_duration: 1200,\n min_interruption_words: 2,\n min_endpointing_delay: 900,\n max_endpointing_delay: 4500,\n max_tool_steps: 3,\n });\n });\n\n it('prefers turnHandling values over deprecated flat fields', () => {\n const options = baseOptions();\n options.allowInterruptions = false;\n options.discardAudioIfUninterruptible = true;\n options.minInterruptionDuration = 400;\n options.minInterruptionWords = 1;\n options.minEndpointingDelay = 500;\n options.maxEndpointingDelay = 2500;\n options.turnHandling = {\n interruption: {\n mode: 'vad',\n discardAudioIfUninterruptible: false,\n minDuration: 1400,\n minWords: 4,\n },\n endpointing: {\n minDelay: 700,\n maxDelay: 3900,\n },\n };\n\n const serialized = serializeOptions(options);\n expect(serialized).toMatchObject({\n allow_interruptions: true,\n discard_audio_if_uninterruptible: false,\n min_interruption_duration: 1400,\n min_interruption_words: 4,\n min_endpointing_delay: 700,\n max_endpointing_delay: 3900,\n max_tool_steps: 3,\n });\n });\n\n it('falls back to deprecated flat fields when turnHandling values are absent', () => {\n const options = baseOptions();\n options.allowInterruptions = false;\n options.discardAudioIfUninterruptible = false;\n options.minInterruptionDuration = 600;\n options.minInterruptionWords = 3;\n options.minEndpointingDelay = 1000;\n options.maxEndpointingDelay = 5000;\n\n const serialized = serializeOptions(options);\n expect(serialized).toMatchObject({\n allow_interruptions: false,\n discard_audio_if_uninterruptible: false,\n min_interruption_duration: 600,\n min_interruption_words: 3,\n min_endpointing_delay: 1000,\n max_endpointing_delay: 5000,\n max_tool_steps: 3,\n });\n });\n});\n"],"mappings":";AAGA,oBAAqC;AACrC,0BAA4B;AAE5B,oBAAyD;AAEzD,SAAS,cAA4B;AACnC,SAAO;AAAA,IACL,cAAc;AAAA,IACd,sBAAsB;AAAA,IACtB,iBAAiB;AAAA,IACjB,yBAAyB;AAAA,IACzB,cAAc,CAAC;AAAA,EACjB;AACF;AAEA,SAAS,iBAAiB,SAAuB;AAC/C,QAAM,aAAS,mCAAoB;AAAA,IACjC,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,MAAM;AAAA,IACN;AAAA,IACA,QAAQ,CAAC;AAAA,IACT,aAAa,gCAAY,MAAM;AAAA,IAC/B,iBAAiB;AAAA,IACjB,WAAW;AAAA,IACX,WAAW;AAAA,EACb,CAAC;AAED,QAAM,cAAU,mCAAoB,MAAM;AAC1C,SAAO,QAAQ;AACjB;AAAA,IAEA,wBAAS,uBAAuB,MAAM;AACpC,wBAAG,oEAAoE,MAAM;AAC3E,UAAM,UAAU,YAAY;AAC5B,YAAQ,eAAe;AAAA,MACrB,cAAc;AAAA,QACZ,MAAM;AAAA,QACN,+BAA+B;AAAA,QAC/B,aAAa;AAAA,QACb,UAAU;AAAA,MACZ;AAAA,MACA,aAAa;AAAA,QACX,UAAU;AAAA,QACV,UAAU;AAAA,MACZ;AAAA,IACF;AAEA,UAAM,aAAa,iBAAiB,OAAO;AAC3C,8BAAO,UAAU,EAAE,cAAc;AAAA,MAC/B,qBAAqB;AAAA,MACrB,kCAAkC;AAAA,MAClC,2BAA2B;AAAA,MAC3B,wBAAwB;AAAA,MACxB,uBAAuB;AAAA,MACvB,uBAAuB;AAAA,MACvB,gBAAgB;AAAA,IAClB,CAAC;AAAA,EACH,CAAC;AAED,wBAAG,2DAA2D,MAAM;AAClE,UAAM,UAAU,YAAY;AAC5B,YAAQ,qBAAqB;AAC7B,YAAQ,gCAAgC;AACxC,YAAQ,0BAA0B;AAClC,YAAQ,uBAAuB;AAC/B,YAAQ,sBAAsB;AAC9B,YAAQ,sBAAsB;AAC9B,YAAQ,eAAe;AAAA,MACrB,cAAc;AAAA,QACZ,MAAM;AAAA,QACN,+BAA+B;AAAA,QAC/B,aAAa;AAAA,QACb,UAAU;AAAA,MACZ;AAAA,MACA,aAAa;AAAA,QACX,UAAU;AAAA,QACV,UAAU;AAAA,MACZ;AAAA,IACF;AAEA,UAAM,aAAa,iBAAiB,OAAO;AAC3C,8BAAO,UAAU,EAAE,cAAc;AAAA,MAC/B,qBAAqB;AAAA,MACrB,kCAAkC;AAAA,MAClC,2BAA2B;AAAA,MAC3B,wBAAwB;AAAA,MACxB,uBAAuB;AAAA,MACvB,uBAAuB;AAAA,MACvB,gBAAgB;AAAA,IAClB,CAAC;AAAA,EACH,CAAC;AAED,wBAAG,4EAA4E,MAAM;AACnF,UAAM,UAAU,YAAY;AAC5B,YAAQ,qBAAqB;AAC7B,YAAQ,gCAAgC;AACxC,YAAQ,0BAA0B;AAClC,YAAQ,uBAAuB;AAC/B,YAAQ,sBAAsB;AAC9B,YAAQ,sBAAsB;AAE9B,UAAM,aAAa,iBAAiB,OAAO;AAC3C,8BAAO,UAAU,EAAE,cAAc;AAAA,MAC/B,qBAAqB;AAAA,MACrB,kCAAkC;AAAA,MAClC,2BAA2B;AAAA,MAC3B,wBAAwB;AAAA,MACxB,uBAAuB;AAAA,MACvB,uBAAuB;AAAA,MACvB,gBAAgB;AAAA,IAClB,CAAC;AAAA,EACH,CAAC;AACH,CAAC;","names":[]}
@@ -0,0 +1,105 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { ChatContext } from "../llm/chat_context.js";
3
+ import { createSessionReport, sessionReportToJSON } from "./report.js";
4
+ function baseOptions() {
5
+ return {
6
+ maxToolSteps: 3,
7
+ preemptiveGeneration: false,
8
+ userAwayTimeout: 15,
9
+ useTtsAlignedTranscript: true,
10
+ turnHandling: {}
11
+ };
12
+ }
13
+ function serializeOptions(options) {
14
+ const report = createSessionReport({
15
+ jobId: "job",
16
+ roomId: "room-id",
17
+ room: "room",
18
+ options,
19
+ events: [],
20
+ chatHistory: ChatContext.empty(),
21
+ enableRecording: false,
22
+ timestamp: 0,
23
+ startedAt: 0
24
+ });
25
+ const payload = sessionReportToJSON(report);
26
+ return payload.options;
27
+ }
28
+ describe("sessionReportToJSON", () => {
29
+ it("serializes interruption and endpointing values from turnHandling", () => {
30
+ const options = baseOptions();
31
+ options.turnHandling = {
32
+ interruption: {
33
+ mode: "adaptive",
34
+ discardAudioIfUninterruptible: false,
35
+ minDuration: 1200,
36
+ minWords: 2
37
+ },
38
+ endpointing: {
39
+ minDelay: 900,
40
+ maxDelay: 4500
41
+ }
42
+ };
43
+ const serialized = serializeOptions(options);
44
+ expect(serialized).toMatchObject({
45
+ allow_interruptions: true,
46
+ discard_audio_if_uninterruptible: false,
47
+ min_interruption_duration: 1200,
48
+ min_interruption_words: 2,
49
+ min_endpointing_delay: 900,
50
+ max_endpointing_delay: 4500,
51
+ max_tool_steps: 3
52
+ });
53
+ });
54
+ it("prefers turnHandling values over deprecated flat fields", () => {
55
+ const options = baseOptions();
56
+ options.allowInterruptions = false;
57
+ options.discardAudioIfUninterruptible = true;
58
+ options.minInterruptionDuration = 400;
59
+ options.minInterruptionWords = 1;
60
+ options.minEndpointingDelay = 500;
61
+ options.maxEndpointingDelay = 2500;
62
+ options.turnHandling = {
63
+ interruption: {
64
+ mode: "vad",
65
+ discardAudioIfUninterruptible: false,
66
+ minDuration: 1400,
67
+ minWords: 4
68
+ },
69
+ endpointing: {
70
+ minDelay: 700,
71
+ maxDelay: 3900
72
+ }
73
+ };
74
+ const serialized = serializeOptions(options);
75
+ expect(serialized).toMatchObject({
76
+ allow_interruptions: true,
77
+ discard_audio_if_uninterruptible: false,
78
+ min_interruption_duration: 1400,
79
+ min_interruption_words: 4,
80
+ min_endpointing_delay: 700,
81
+ max_endpointing_delay: 3900,
82
+ max_tool_steps: 3
83
+ });
84
+ });
85
+ it("falls back to deprecated flat fields when turnHandling values are absent", () => {
86
+ const options = baseOptions();
87
+ options.allowInterruptions = false;
88
+ options.discardAudioIfUninterruptible = false;
89
+ options.minInterruptionDuration = 600;
90
+ options.minInterruptionWords = 3;
91
+ options.minEndpointingDelay = 1e3;
92
+ options.maxEndpointingDelay = 5e3;
93
+ const serialized = serializeOptions(options);
94
+ expect(serialized).toMatchObject({
95
+ allow_interruptions: false,
96
+ discard_audio_if_uninterruptible: false,
97
+ min_interruption_duration: 600,
98
+ min_interruption_words: 3,
99
+ min_endpointing_delay: 1e3,
100
+ max_endpointing_delay: 5e3,
101
+ max_tool_steps: 3
102
+ });
103
+ });
104
+ });
105
+ //# sourceMappingURL=report.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/voice/report.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2026 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { describe, expect, it } from 'vitest';\nimport { ChatContext } from '../llm/chat_context.js';\nimport type { VoiceOptions } from './agent_session.js';\nimport { createSessionReport, sessionReportToJSON } from './report.js';\n\nfunction baseOptions(): VoiceOptions {\n return {\n maxToolSteps: 3,\n preemptiveGeneration: false,\n userAwayTimeout: 15,\n useTtsAlignedTranscript: true,\n turnHandling: {},\n };\n}\n\nfunction serializeOptions(options: VoiceOptions) {\n const report = createSessionReport({\n jobId: 'job',\n roomId: 'room-id',\n room: 'room',\n options,\n events: [],\n chatHistory: ChatContext.empty(),\n enableRecording: false,\n timestamp: 0,\n startedAt: 0,\n });\n\n const payload = sessionReportToJSON(report);\n return payload.options as Record<string, unknown>;\n}\n\ndescribe('sessionReportToJSON', () => {\n it('serializes interruption and endpointing values from turnHandling', () => {\n const options = baseOptions();\n options.turnHandling = {\n interruption: {\n mode: 'adaptive',\n discardAudioIfUninterruptible: false,\n minDuration: 1200,\n minWords: 2,\n },\n endpointing: {\n minDelay: 900,\n maxDelay: 4500,\n },\n };\n\n const serialized = serializeOptions(options);\n expect(serialized).toMatchObject({\n allow_interruptions: true,\n discard_audio_if_uninterruptible: false,\n min_interruption_duration: 1200,\n min_interruption_words: 2,\n min_endpointing_delay: 900,\n max_endpointing_delay: 4500,\n max_tool_steps: 3,\n });\n });\n\n it('prefers turnHandling values over deprecated flat fields', () => {\n const options = baseOptions();\n options.allowInterruptions = false;\n options.discardAudioIfUninterruptible = true;\n options.minInterruptionDuration = 400;\n options.minInterruptionWords = 1;\n options.minEndpointingDelay = 500;\n options.maxEndpointingDelay = 2500;\n options.turnHandling = {\n interruption: {\n mode: 'vad',\n discardAudioIfUninterruptible: false,\n minDuration: 1400,\n minWords: 4,\n },\n endpointing: {\n minDelay: 700,\n maxDelay: 3900,\n },\n };\n\n const serialized = serializeOptions(options);\n expect(serialized).toMatchObject({\n allow_interruptions: true,\n discard_audio_if_uninterruptible: false,\n min_interruption_duration: 1400,\n min_interruption_words: 4,\n min_endpointing_delay: 700,\n max_endpointing_delay: 3900,\n max_tool_steps: 3,\n });\n });\n\n it('falls back to deprecated flat fields when turnHandling values are absent', () => {\n const options = baseOptions();\n options.allowInterruptions = false;\n options.discardAudioIfUninterruptible = false;\n options.minInterruptionDuration = 600;\n options.minInterruptionWords = 3;\n options.minEndpointingDelay = 1000;\n options.maxEndpointingDelay = 5000;\n\n const serialized = serializeOptions(options);\n expect(serialized).toMatchObject({\n allow_interruptions: false,\n discard_audio_if_uninterruptible: false,\n min_interruption_duration: 600,\n min_interruption_words: 3,\n min_endpointing_delay: 1000,\n max_endpointing_delay: 5000,\n max_tool_steps: 3,\n });\n });\n});\n"],"mappings":"AAGA,SAAS,UAAU,QAAQ,UAAU;AACrC,SAAS,mBAAmB;AAE5B,SAAS,qBAAqB,2BAA2B;AAEzD,SAAS,cAA4B;AACnC,SAAO;AAAA,IACL,cAAc;AAAA,IACd,sBAAsB;AAAA,IACtB,iBAAiB;AAAA,IACjB,yBAAyB;AAAA,IACzB,cAAc,CAAC;AAAA,EACjB;AACF;AAEA,SAAS,iBAAiB,SAAuB;AAC/C,QAAM,SAAS,oBAAoB;AAAA,IACjC,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,MAAM;AAAA,IACN;AAAA,IACA,QAAQ,CAAC;AAAA,IACT,aAAa,YAAY,MAAM;AAAA,IAC/B,iBAAiB;AAAA,IACjB,WAAW;AAAA,IACX,WAAW;AAAA,EACb,CAAC;AAED,QAAM,UAAU,oBAAoB,MAAM;AAC1C,SAAO,QAAQ;AACjB;AAEA,SAAS,uBAAuB,MAAM;AACpC,KAAG,oEAAoE,MAAM;AAC3E,UAAM,UAAU,YAAY;AAC5B,YAAQ,eAAe;AAAA,MACrB,cAAc;AAAA,QACZ,MAAM;AAAA,QACN,+BAA+B;AAAA,QAC/B,aAAa;AAAA,QACb,UAAU;AAAA,MACZ;AAAA,MACA,aAAa;AAAA,QACX,UAAU;AAAA,QACV,UAAU;AAAA,MACZ;AAAA,IACF;AAEA,UAAM,aAAa,iBAAiB,OAAO;AAC3C,WAAO,UAAU,EAAE,cAAc;AAAA,MAC/B,qBAAqB;AAAA,MACrB,kCAAkC;AAAA,MAClC,2BAA2B;AAAA,MAC3B,wBAAwB;AAAA,MACxB,uBAAuB;AAAA,MACvB,uBAAuB;AAAA,MACvB,gBAAgB;AAAA,IAClB,CAAC;AAAA,EACH,CAAC;AAED,KAAG,2DAA2D,MAAM;AAClE,UAAM,UAAU,YAAY;AAC5B,YAAQ,qBAAqB;AAC7B,YAAQ,gCAAgC;AACxC,YAAQ,0BAA0B;AAClC,YAAQ,uBAAuB;AAC/B,YAAQ,sBAAsB;AAC9B,YAAQ,sBAAsB;AAC9B,YAAQ,eAAe;AAAA,MACrB,cAAc;AAAA,QACZ,MAAM;AAAA,QACN,+BAA+B;AAAA,QAC/B,aAAa;AAAA,QACb,UAAU;AAAA,MACZ;AAAA,MACA,aAAa;AAAA,QACX,UAAU;AAAA,QACV,UAAU;AAAA,MACZ;AAAA,IACF;AAEA,UAAM,aAAa,iBAAiB,OAAO;AAC3C,WAAO,UAAU,EAAE,cAAc;AAAA,MAC/B,qBAAqB;AAAA,MACrB,kCAAkC;AAAA,MAClC,2BAA2B;AAAA,MAC3B,wBAAwB;AAAA,MACxB,uBAAuB;AAAA,MACvB,uBAAuB;AAAA,MACvB,gBAAgB;AAAA,IAClB,CAAC;AAAA,EACH,CAAC;AAED,KAAG,4EAA4E,MAAM;AACnF,UAAM,UAAU,YAAY;AAC5B,YAAQ,qBAAqB;AAC7B,YAAQ,gCAAgC;AACxC,YAAQ,0BAA0B;AAClC,YAAQ,uBAAuB;AAC/B,YAAQ,sBAAsB;AAC9B,YAAQ,sBAAsB;AAE9B,UAAM,aAAa,iBAAiB,OAAO;AAC3C,WAAO,UAAU,EAAE,cAAc;AAAA,MAC/B,qBAAqB;AAAA,MACrB,kCAAkC;AAAA,MAClC,2BAA2B;AAAA,MAC3B,wBAAwB;AAAA,MACxB,uBAAuB;AAAA,MACvB,uBAAuB;AAAA,MACvB,gBAAgB;AAAA,IAClB,CAAC;AAAA,EACH,CAAC;AACH,CAAC;","names":[]}
@@ -18,6 +18,7 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var room_io_exports = {};
20
20
  __export(room_io_exports, {
21
+ DEFAULT_TEXT_INPUT_CALLBACK: () => DEFAULT_TEXT_INPUT_CALLBACK,
21
22
  RoomIO: () => RoomIO
22
23
  });
23
24
  module.exports = __toCommonJS(room_io_exports);
@@ -80,7 +81,6 @@ class RoomIO {
80
81
  userTranscriptWriter;
81
82
  forwardUserTranscriptTask;
82
83
  initTask;
83
- textStreamHandlerRegistered = false;
84
84
  logger = (0, import_log.log)();
85
85
  constructor({
86
86
  agentSession,
@@ -98,14 +98,23 @@ class RoomIO {
98
98
  }
99
99
  async init(signal) {
100
100
  var _a, _b;
101
- await this.roomConnectedFuture.await;
101
+ await Promise.race([this.roomConnectedFuture.await, (0, import_utils.waitForAbort)(signal)]);
102
+ if (signal.aborted) {
103
+ return;
104
+ }
102
105
  for (const participant2 of this.room.remoteParticipants.values()) {
103
106
  this.onParticipantConnected(participant2);
104
107
  }
105
108
  if (signal.aborted) {
106
109
  return;
107
110
  }
108
- const participant = await this.participantAvailableFuture.await;
111
+ const participant = await Promise.race([
112
+ this.participantAvailableFuture.await,
113
+ (0, import_utils.waitForAbort)(signal)
114
+ ]);
115
+ if (!participant) {
116
+ return;
117
+ }
109
118
  this.setParticipant(participant.identity);
110
119
  this.updateTranscriptionOutput({
111
120
  output: this.agentTranscriptOutput,
@@ -170,30 +179,6 @@ class RoomIO {
170
179
  });
171
180
  }
172
181
  };
173
- onUserTextInput = (reader, participantInfo) => {
174
- if (participantInfo.identity !== this.participantIdentity) {
175
- return;
176
- }
177
- const participant = this.room.remoteParticipants.get(participantInfo.identity);
178
- if (!participant) {
179
- this.logger.warn("participant not found, ignoring text input");
180
- return;
181
- }
182
- const readText = async () => {
183
- const text = await reader.readAll();
184
- const textInputResult = this.inputOptions.textInputCallback(this.agentSession, {
185
- text,
186
- info: reader.info,
187
- participant
188
- });
189
- if (textInputResult instanceof Promise) {
190
- await textInputResult;
191
- }
192
- };
193
- readText().catch((error) => {
194
- this.logger.error({ error }, "Error reading text input");
195
- });
196
- };
197
182
  async forwardUserTranscript(signal) {
198
183
  var _a, _b;
199
184
  const reader = this.userTranscriptStream.readable.getReader();
@@ -249,6 +234,9 @@ class RoomIO {
249
234
  get isParticipantAvailable() {
250
235
  return this.participantAvailableFuture.done;
251
236
  }
237
+ get rtcRoom() {
238
+ return this.room;
239
+ }
252
240
  get linkedParticipant() {
253
241
  if (!this.isParticipantAvailable) {
254
242
  return void 0;
@@ -293,16 +281,6 @@ class RoomIO {
293
281
  });
294
282
  }
295
283
  start() {
296
- if (this.inputOptions.textEnabled) {
297
- try {
298
- this.room.registerTextStreamHandler(import_constants.TOPIC_CHAT, this.onUserTextInput);
299
- this.textStreamHandlerRegistered = true;
300
- } catch (error) {
301
- if (this.inputOptions.textEnabled) {
302
- this.logger.warn(`text stream handler for topic "${import_constants.TOPIC_CHAT}" already set, ignoring`);
303
- }
304
- }
305
- }
306
284
  if (this.inputOptions.audioEnabled) {
307
285
  this.audioInput = new import_input.ParticipantAudioInputStream({
308
286
  room: this.room,
@@ -364,10 +342,6 @@ class RoomIO {
364
342
  this.room.off(import_rtc_node.RoomEvent.ParticipantDisconnected, this.onParticipantDisconnected);
365
343
  this.agentSession.off(import_events.AgentSessionEventTypes.UserInputTranscribed, this.onUserInputTranscribed);
366
344
  this.agentSession.off(import_events.AgentSessionEventTypes.AgentStateChanged, this.onAgentStateChanged);
367
- if (this.textStreamHandlerRegistered) {
368
- this.room.unregisterTextStreamHandler(import_constants.TOPIC_CHAT);
369
- this.textStreamHandlerRegistered = false;
370
- }
371
345
  await ((_a = this.initTask) == null ? void 0 : _a.cancelAndWait());
372
346
  this.userTranscriptWriter.close();
373
347
  await ((_b = this.forwardUserTranscriptTask) == null ? void 0 : _b.cancelAndWait());
@@ -378,6 +352,7 @@ class RoomIO {
378
352
  }
379
353
  // Annotate the CommonJS export names for ESM import in node:
380
354
  0 && (module.exports = {
355
+ DEFAULT_TEXT_INPUT_CALLBACK,
381
356
  RoomIO
382
357
  });
383
358
  //# sourceMappingURL=room_io.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/voice/room_io/room_io.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport {\n type AudioFrame,\n ConnectionState,\n DisconnectReason,\n type FrameProcessor,\n type NoiseCancellationOptions,\n type Participant,\n ParticipantKind,\n type RemoteParticipant,\n type Room,\n RoomEvent,\n type TextStreamInfo,\n type TextStreamReader,\n TrackPublishOptions,\n TrackSource,\n} from '@livekit/rtc-node';\nimport type { WritableStreamDefaultWriter } from 'node:stream/web';\nimport { ATTRIBUTE_PUBLISH_ON_BEHALF, TOPIC_CHAT } from '../../constants.js';\nimport { log } from '../../log.js';\nimport { IdentityTransform } from '../../stream/identity_transform.js';\nimport { Future, Task } from '../../utils.js';\nimport { type AgentSession } from '../agent_session.js';\nimport {\n AgentSessionEventTypes,\n type AgentStateChangedEvent,\n CloseReason,\n type UserInputTranscribedEvent,\n} from '../events.js';\nimport type { AudioOutput, TextOutput } from '../io.js';\nimport { TranscriptionSynchronizer } from '../transcription/synchronizer.js';\nimport { ParticipantAudioInputStream } from './_input.js';\nimport {\n ParalellTextOutput,\n ParticipantAudioOutput,\n ParticipantLegacyTranscriptionOutput,\n ParticipantTranscriptionOutput,\n} from './_output.js';\n\nexport interface TextInputEvent {\n text: string;\n info: TextStreamInfo;\n participant: RemoteParticipant;\n}\n\nexport type TextInputCallback = (sess: AgentSession, ev: TextInputEvent) => void | Promise<void>;\n\nconst DEFAULT_TEXT_INPUT_CALLBACK: TextInputCallback = (sess: AgentSession, ev: TextInputEvent) => {\n sess.interrupt();\n sess.generateReply({ userInput: ev.text });\n};\n\nconst DEFAULT_PARTICIPANT_KINDS: ParticipantKind[] = [\n ParticipantKind.CONNECTOR,\n ParticipantKind.SIP,\n ParticipantKind.STANDARD,\n];\n\nconst CLOSE_ON_DISCONNECT_REASONS: DisconnectReason[] = [\n DisconnectReason.CLIENT_INITIATED,\n DisconnectReason.ROOM_DELETED,\n DisconnectReason.USER_REJECTED,\n];\n\nexport interface RoomInputOptions {\n audioSampleRate: number;\n audioNumChannels: number;\n /** If not given, default to True. */\n textEnabled: boolean;\n /** If not given, default to True. */\n audioEnabled: boolean;\n /** If not given, default to False. */\n videoEnabled: boolean;\n /** The participant to link to. If not provided, link to the first participant.\n Can be overridden by the `participant` argument of RoomIO constructor or `set_participant`.\n */\n participantIdentity?: string;\n noiseCancellation?: NoiseCancellationOptions | FrameProcessor<AudioFrame>;\n textInputCallback?: TextInputCallback;\n /** Participant kinds accepted for auto subscription. If not provided,\n accept `DEFAULT_PARTICIPANT_KINDS`\n */\n participantKinds?: ParticipantKind[];\n /** Close the AgentSession if the linked participant disconnects with reasons in\n CLIENT_INITIATED, ROOM_DELETED, or USER_REJECTED.\n */\n closeOnDisconnect: boolean;\n}\n\nexport interface RoomOutputOptions {\n /** If not given, default to True. */\n transcriptionEnabled: boolean;\n /** If not given, default to True. */\n audioEnabled: boolean;\n audioSampleRate: number;\n audioNumChannels: number;\n /** False to disable transcription synchronization with audio output.\n Otherwise, transcription is emitted as quickly as available.\n */\n syncTranscription: boolean;\n /** The name of the audio track to publish. If not provided, default to \"roomio_audio\".\n */\n audioPublishOptions: TrackPublishOptions;\n}\n\nconst DEFAULT_ROOM_INPUT_OPTIONS: RoomInputOptions = {\n audioSampleRate: 24000,\n audioNumChannels: 1,\n textEnabled: true,\n audioEnabled: true,\n videoEnabled: false,\n textInputCallback: DEFAULT_TEXT_INPUT_CALLBACK,\n closeOnDisconnect: true,\n};\n\nconst DEFAULT_ROOM_OUTPUT_OPTIONS: RoomOutputOptions = {\n audioSampleRate: 24000,\n audioNumChannels: 1,\n transcriptionEnabled: true,\n audioEnabled: true,\n syncTranscription: true,\n audioPublishOptions: new TrackPublishOptions({ source: TrackSource.SOURCE_MICROPHONE }),\n};\n\nexport class RoomIO {\n private agentSession: AgentSession;\n private room: Room;\n private inputOptions: RoomInputOptions;\n private outputOptions: RoomOutputOptions;\n\n private audioInput?: ParticipantAudioInputStream;\n private participantAudioOutput?: ParticipantAudioOutput;\n private userTranscriptOutput?: ParalellTextOutput;\n private agentTranscriptOutput?: ParalellTextOutput;\n private transcriptionSynchronizer?: TranscriptionSynchronizer;\n private participantIdentity: string | null = null;\n\n private participantAvailableFuture: Future<RemoteParticipant> = new Future();\n private roomConnectedFuture: Future<void> = new Future();\n\n // Use stream API for transcript queue\n private userTranscriptStream = new IdentityTransform<UserInputTranscribedEvent>();\n private userTranscriptWriter: WritableStreamDefaultWriter<UserInputTranscribedEvent>;\n private forwardUserTranscriptTask?: Task<void>;\n private initTask?: Task<void>;\n\n private textStreamHandlerRegistered = false;\n\n private logger = log();\n\n constructor({\n agentSession,\n room,\n participant = null,\n inputOptions,\n outputOptions,\n }: {\n agentSession: AgentSession;\n room: Room;\n participant?: RemoteParticipant | string | null;\n inputOptions?: Partial<RoomInputOptions>;\n outputOptions?: Partial<RoomOutputOptions>;\n }) {\n this.agentSession = agentSession;\n this.room = room;\n this.inputOptions = { ...DEFAULT_ROOM_INPUT_OPTIONS, ...inputOptions };\n this.outputOptions = { ...DEFAULT_ROOM_OUTPUT_OPTIONS, ...outputOptions };\n\n this.userTranscriptWriter = this.userTranscriptStream.writable.getWriter();\n\n this.participantIdentity = participant\n ? typeof participant === 'string'\n ? participant\n : participant.identity\n : this.inputOptions.participantIdentity ?? null;\n }\n private async init(signal: AbortSignal): Promise<void> {\n await this.roomConnectedFuture.await;\n\n for (const participant of this.room.remoteParticipants.values()) {\n this.onParticipantConnected(participant);\n }\n if (signal.aborted) {\n return;\n }\n\n const participant = await this.participantAvailableFuture.await;\n this.setParticipant(participant.identity);\n\n // init agent outputs\n this.updateTranscriptionOutput({\n output: this.agentTranscriptOutput,\n participant: this.room.localParticipant?.identity ?? null,\n });\n\n await this.participantAudioOutput?.start(signal);\n }\n\n private onConnectionStateChanged = (state: ConnectionState) => {\n this.logger.debug({ state }, 'connection state changed');\n if (\n state === ConnectionState.CONN_CONNECTED &&\n this.room.isConnected &&\n !this.roomConnectedFuture.done\n ) {\n this.roomConnectedFuture.resolve();\n }\n };\n\n private onParticipantConnected = (participant: RemoteParticipant) => {\n if (this.participantAvailableFuture.done) {\n return;\n }\n\n if (this.participantIdentity) {\n if (participant.identity !== this.participantIdentity) {\n return;\n }\n } else if (\n // otherwise, skip participants that are marked as publishing for this agent\n participant.attributes?.[ATTRIBUTE_PUBLISH_ON_BEHALF] === this.room.localParticipant?.identity\n ) {\n return;\n }\n\n const acceptedKinds = this.inputOptions.participantKinds ?? DEFAULT_PARTICIPANT_KINDS;\n if (participant.info.kind !== undefined && !acceptedKinds.includes(participant.info.kind)) {\n return;\n }\n\n this.participantAvailableFuture.resolve(participant);\n };\n\n private onParticipantDisconnected = (participant: RemoteParticipant) => {\n if (participant.identity !== this.participantIdentity) {\n return;\n }\n this.participantAvailableFuture = new Future<RemoteParticipant>();\n if (\n this.inputOptions.closeOnDisconnect &&\n participant.disconnectReason &&\n CLOSE_ON_DISCONNECT_REASONS.includes(participant.disconnectReason)\n ) {\n this.logger.info(\n {\n participant: participant.identity,\n reason: DisconnectReason[participant.disconnectReason],\n },\n 'closing agent session due to participant disconnect ' +\n '(disable via `RoomInputOptions.closeOnDisconnect=False`)',\n );\n this.agentSession._closeSoon({\n reason: CloseReason.PARTICIPANT_DISCONNECTED,\n });\n }\n };\n\n private onUserInputTranscribed = (ev: UserInputTranscribedEvent) => {\n this.userTranscriptWriter.write(ev).catch((error) => {\n this.logger.error({ error }, 'Failed to write transcript event to stream');\n });\n };\n\n private onAgentStateChanged = async (ev: AgentStateChangedEvent) => {\n if (this.room.isConnected && this.room.localParticipant) {\n await this.room.localParticipant.setAttributes({\n [`lk.agent.state`]: ev.newState,\n });\n }\n };\n\n private onUserTextInput = (reader: TextStreamReader, participantInfo: { identity: string }) => {\n if (participantInfo.identity !== this.participantIdentity) {\n return;\n }\n\n const participant = this.room.remoteParticipants.get(participantInfo.identity);\n if (!participant) {\n this.logger.warn('participant not found, ignoring text input');\n return;\n }\n\n const readText = async () => {\n const text = await reader.readAll();\n\n const textInputResult = this.inputOptions.textInputCallback!(this.agentSession, {\n text,\n info: reader.info,\n participant,\n });\n\n // check if callback is a Promise\n if (textInputResult instanceof Promise) {\n await textInputResult;\n }\n };\n\n readText().catch((error) => {\n this.logger.error({ error }, 'Error reading text input');\n });\n };\n\n private async forwardUserTranscript(signal: AbortSignal): Promise<void> {\n const reader = this.userTranscriptStream.readable.getReader();\n try {\n while (!signal.aborted) {\n const { done, value } = await reader.read();\n if (done) break;\n\n const event = value;\n // IMPORTANT: need to await here to avoid race condition\n await this.userTranscriptOutput?.captureText(event.transcript);\n if (event.isFinal) {\n this.userTranscriptOutput?.flush();\n }\n }\n } catch (error) {\n this.logger.error({ error }, 'Error processing transcript stream');\n }\n }\n\n private createTranscriptionOutput(options: {\n isDeltaStream: boolean;\n participant: Participant | string | null;\n }) {\n return new ParalellTextOutput([\n new ParticipantLegacyTranscriptionOutput(\n this.room,\n options.isDeltaStream,\n options.participant,\n ),\n new ParticipantTranscriptionOutput(this.room, options.isDeltaStream, options.participant),\n ]);\n }\n\n private updateTranscriptionOutput({\n output,\n participant,\n }: {\n output?: ParalellTextOutput;\n participant: string | null;\n }) {\n if (!output) {\n return;\n }\n\n for (const sink of output._sinks) {\n if (\n sink instanceof ParticipantLegacyTranscriptionOutput ||\n sink instanceof ParticipantTranscriptionOutput\n ) {\n sink.setParticipant(participant);\n }\n }\n }\n\n get audioOutput(): AudioOutput | undefined {\n if (!this.transcriptionSynchronizer) {\n return this.participantAudioOutput;\n }\n\n return this.transcriptionSynchronizer.audioOutput;\n }\n\n get transcriptionOutput(): TextOutput | undefined {\n if (!this.transcriptionSynchronizer) {\n return this.agentTranscriptOutput;\n }\n\n return this.transcriptionSynchronizer.textOutput;\n }\n\n get isParticipantAvailable(): boolean {\n return this.participantAvailableFuture.done;\n }\n\n get linkedParticipant(): RemoteParticipant | undefined {\n if (!this.isParticipantAvailable) {\n return undefined;\n }\n\n return this.participantAvailableFuture.result;\n }\n\n get localParticipant(): Participant | undefined {\n return this.room.localParticipant ?? undefined;\n }\n\n /** Switch to a different participant */\n setParticipant(participantIdentity: string | null) {\n this.logger.debug({ participantIdentity }, 'setting participant');\n if (participantIdentity === null) {\n this.unsetParticipant();\n return;\n }\n\n if (this.participantIdentity !== participantIdentity) {\n this.participantAvailableFuture = new Future<RemoteParticipant>();\n\n // check if new participant is already connected\n for (const participant of this.room.remoteParticipants.values()) {\n if (participant.identity === participantIdentity) {\n this.participantAvailableFuture.resolve(participant);\n break;\n }\n }\n }\n\n // update participant identity and handlers\n this.participantIdentity = participantIdentity;\n this.audioInput?.setParticipant(participantIdentity);\n this.updateTranscriptionOutput({\n output: this.userTranscriptOutput,\n participant: participantIdentity,\n });\n }\n\n unsetParticipant() {\n this.participantIdentity = null;\n this.participantAvailableFuture = new Future<RemoteParticipant>();\n this.audioInput?.setParticipant(null);\n this.updateTranscriptionOutput({\n output: this.userTranscriptOutput,\n participant: null,\n });\n }\n\n start() {\n if (this.inputOptions.textEnabled) {\n try {\n this.room.registerTextStreamHandler(TOPIC_CHAT, this.onUserTextInput);\n this.textStreamHandlerRegistered = true;\n } catch (error) {\n if (this.inputOptions.textEnabled) {\n this.logger.warn(`text stream handler for topic \"${TOPIC_CHAT}\" already set, ignoring`);\n }\n }\n }\n\n // -- create inputs --\n if (this.inputOptions.audioEnabled) {\n this.audioInput = new ParticipantAudioInputStream({\n room: this.room,\n sampleRate: this.inputOptions.audioSampleRate,\n numChannels: this.inputOptions.audioNumChannels,\n noiseCancellation: this.inputOptions.noiseCancellation,\n });\n }\n\n // -- create outputs --\n if (this.outputOptions.audioEnabled) {\n this.participantAudioOutput = new ParticipantAudioOutput(this.room, {\n sampleRate: this.outputOptions.audioSampleRate,\n numChannels: this.outputOptions.audioNumChannels,\n trackPublishOptions: this.outputOptions.audioPublishOptions,\n });\n }\n if (this.outputOptions.transcriptionEnabled) {\n this.userTranscriptOutput = this.createTranscriptionOutput({\n isDeltaStream: false,\n participant: this.participantIdentity,\n });\n // Start the transcript forwarding\n this.forwardUserTranscriptTask = Task.from((controller) =>\n this.forwardUserTranscript(controller.signal),\n );\n this.agentTranscriptOutput = this.createTranscriptionOutput({\n isDeltaStream: true,\n participant: null,\n });\n\n // use the RoomIO's audio output if available, otherwise use the agent's audio output\n // TODO(AJS-176): check for agent output\n const audioOutput = this.participantAudioOutput;\n if (this.outputOptions.syncTranscription && audioOutput) {\n this.transcriptionSynchronizer = new TranscriptionSynchronizer(\n audioOutput,\n this.agentTranscriptOutput,\n );\n }\n }\n\n // -- set the room event handlers --\n this.room.on(RoomEvent.ParticipantConnected, this.onParticipantConnected);\n this.room.on(RoomEvent.ConnectionStateChanged, this.onConnectionStateChanged);\n this.room.on(RoomEvent.ParticipantDisconnected, this.onParticipantDisconnected);\n if (this.room.isConnected) {\n this.onConnectionStateChanged(ConnectionState.CONN_CONNECTED);\n }\n\n this.initTask = Task.from((controller) => this.init(controller.signal));\n\n // attach the agent to the session\n if (this.audioInput) {\n this.agentSession.input.audio = this.audioInput;\n }\n if (this.audioOutput) {\n this.agentSession.output.audio = this.audioOutput;\n }\n if (this.transcriptionOutput) {\n this.agentSession.output.transcription = this.transcriptionOutput;\n }\n\n this.agentSession.on(AgentSessionEventTypes.AgentStateChanged, this.onAgentStateChanged);\n this.agentSession.on(AgentSessionEventTypes.UserInputTranscribed, this.onUserInputTranscribed);\n }\n\n async close() {\n this.room.off(RoomEvent.ParticipantConnected, this.onParticipantConnected);\n this.room.off(RoomEvent.ConnectionStateChanged, this.onConnectionStateChanged);\n this.room.off(RoomEvent.ParticipantDisconnected, this.onParticipantDisconnected);\n this.agentSession.off(AgentSessionEventTypes.UserInputTranscribed, this.onUserInputTranscribed);\n this.agentSession.off(AgentSessionEventTypes.AgentStateChanged, this.onAgentStateChanged);\n\n if (this.textStreamHandlerRegistered) {\n this.room.unregisterTextStreamHandler(TOPIC_CHAT);\n this.textStreamHandlerRegistered = false;\n }\n\n await this.initTask?.cancelAndWait();\n\n // Close stream FIRST so reader.read() in forwardUserTranscript can exit.\n // This is a workaround for a race condition in the stream API.\n this.userTranscriptWriter.close();\n await this.forwardUserTranscriptTask?.cancelAndWait();\n\n await this.audioInput?.close();\n await this.participantAudioOutput?.close();\n await this.transcriptionSynchronizer?.close();\n }\n}\n"],"mappings":"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","names":["participant"]}
1
+ {"version":3,"sources":["../../../src/voice/room_io/room_io.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport {\n type AudioFrame,\n ConnectionState,\n DisconnectReason,\n type FrameProcessor,\n type NoiseCancellationOptions,\n type Participant,\n ParticipantKind,\n type RemoteParticipant,\n type Room,\n RoomEvent,\n TrackPublishOptions,\n TrackSource,\n} from '@livekit/rtc-node';\nimport type { WritableStreamDefaultWriter } from 'node:stream/web';\nimport { ATTRIBUTE_PUBLISH_ON_BEHALF } from '../../constants.js';\nimport { log } from '../../log.js';\nimport { IdentityTransform } from '../../stream/identity_transform.js';\nimport { Future, Task, waitForAbort } from '../../utils.js';\nimport { type AgentSession } from '../agent_session.js';\nimport type { TextInputCallback } from '../client_events.js';\nimport {\n AgentSessionEventTypes,\n type AgentStateChangedEvent,\n CloseReason,\n type UserInputTranscribedEvent,\n} from '../events.js';\nimport type { AudioOutput, TextOutput } from '../io.js';\nimport { TranscriptionSynchronizer } from '../transcription/synchronizer.js';\nimport { ParticipantAudioInputStream } from './_input.js';\nimport {\n ParalellTextOutput,\n ParticipantAudioOutput,\n ParticipantLegacyTranscriptionOutput,\n ParticipantTranscriptionOutput,\n} from './_output.js';\n\nexport const DEFAULT_TEXT_INPUT_CALLBACK: TextInputCallback = (sess, ev) => {\n sess.interrupt();\n sess.generateReply({ userInput: ev.text });\n};\n\nconst DEFAULT_PARTICIPANT_KINDS: ParticipantKind[] = [\n ParticipantKind.CONNECTOR,\n ParticipantKind.SIP,\n ParticipantKind.STANDARD,\n];\n\nconst CLOSE_ON_DISCONNECT_REASONS: DisconnectReason[] = [\n DisconnectReason.CLIENT_INITIATED,\n DisconnectReason.ROOM_DELETED,\n DisconnectReason.USER_REJECTED,\n];\n\nexport interface RoomInputOptions {\n audioSampleRate: number;\n audioNumChannels: number;\n /** If not given, default to True. */\n textEnabled: boolean;\n /** If not given, default to True. */\n audioEnabled: boolean;\n /** If not given, default to False. */\n videoEnabled: boolean;\n /** The participant to link to. If not provided, link to the first participant.\n Can be overridden by the `participant` argument of RoomIO constructor or `set_participant`.\n */\n participantIdentity?: string;\n noiseCancellation?: NoiseCancellationOptions | FrameProcessor<AudioFrame>;\n textInputCallback?: TextInputCallback;\n /** Participant kinds accepted for auto subscription. If not provided,\n accept `DEFAULT_PARTICIPANT_KINDS`\n */\n participantKinds?: ParticipantKind[];\n /** Close the AgentSession if the linked participant disconnects with reasons in\n CLIENT_INITIATED, ROOM_DELETED, or USER_REJECTED.\n */\n closeOnDisconnect: boolean;\n}\n\nexport interface RoomOutputOptions {\n /** If not given, default to True. */\n transcriptionEnabled: boolean;\n /** If not given, default to True. */\n audioEnabled: boolean;\n audioSampleRate: number;\n audioNumChannels: number;\n /** False to disable transcription synchronization with audio output.\n Otherwise, transcription is emitted as quickly as available.\n */\n syncTranscription: boolean;\n /** The name of the audio track to publish. If not provided, default to \"roomio_audio\".\n */\n audioPublishOptions: TrackPublishOptions;\n}\n\nconst DEFAULT_ROOM_INPUT_OPTIONS: RoomInputOptions = {\n audioSampleRate: 24000,\n audioNumChannels: 1,\n textEnabled: true,\n audioEnabled: true,\n videoEnabled: false,\n textInputCallback: DEFAULT_TEXT_INPUT_CALLBACK,\n closeOnDisconnect: true,\n};\n\nconst DEFAULT_ROOM_OUTPUT_OPTIONS: RoomOutputOptions = {\n audioSampleRate: 24000,\n audioNumChannels: 1,\n transcriptionEnabled: true,\n audioEnabled: true,\n syncTranscription: true,\n audioPublishOptions: new TrackPublishOptions({ source: TrackSource.SOURCE_MICROPHONE }),\n};\n\nexport class RoomIO {\n private agentSession: AgentSession;\n private room: Room;\n private inputOptions: RoomInputOptions;\n private outputOptions: RoomOutputOptions;\n\n private audioInput?: ParticipantAudioInputStream;\n private participantAudioOutput?: ParticipantAudioOutput;\n private userTranscriptOutput?: ParalellTextOutput;\n private agentTranscriptOutput?: ParalellTextOutput;\n private transcriptionSynchronizer?: TranscriptionSynchronizer;\n private participantIdentity: string | null = null;\n\n private participantAvailableFuture: Future<RemoteParticipant> = new Future();\n private roomConnectedFuture: Future<void> = new Future();\n\n // Use stream API for transcript queue\n private userTranscriptStream = new IdentityTransform<UserInputTranscribedEvent>();\n private userTranscriptWriter: WritableStreamDefaultWriter<UserInputTranscribedEvent>;\n private forwardUserTranscriptTask?: Task<void>;\n private initTask?: Task<void>;\n\n private logger = log();\n\n constructor({\n agentSession,\n room,\n participant = null,\n inputOptions,\n outputOptions,\n }: {\n agentSession: AgentSession;\n room: Room;\n participant?: RemoteParticipant | string | null;\n inputOptions?: Partial<RoomInputOptions>;\n outputOptions?: Partial<RoomOutputOptions>;\n }) {\n this.agentSession = agentSession;\n this.room = room;\n this.inputOptions = { ...DEFAULT_ROOM_INPUT_OPTIONS, ...inputOptions };\n this.outputOptions = { ...DEFAULT_ROOM_OUTPUT_OPTIONS, ...outputOptions };\n\n this.userTranscriptWriter = this.userTranscriptStream.writable.getWriter();\n\n this.participantIdentity = participant\n ? typeof participant === 'string'\n ? participant\n : participant.identity\n : this.inputOptions.participantIdentity ?? null;\n }\n private async init(signal: AbortSignal): Promise<void> {\n await Promise.race([this.roomConnectedFuture.await, waitForAbort(signal)]);\n if (signal.aborted) {\n return;\n }\n\n for (const participant of this.room.remoteParticipants.values()) {\n this.onParticipantConnected(participant);\n }\n if (signal.aborted) {\n return;\n }\n\n const participant = await Promise.race([\n this.participantAvailableFuture.await,\n waitForAbort(signal),\n ]);\n\n if (!participant) {\n return;\n }\n\n this.setParticipant(participant.identity);\n\n // init agent outputs\n this.updateTranscriptionOutput({\n output: this.agentTranscriptOutput,\n participant: this.room.localParticipant?.identity ?? null,\n });\n\n await this.participantAudioOutput?.start(signal);\n }\n\n private onConnectionStateChanged = (state: ConnectionState) => {\n this.logger.debug({ state }, 'connection state changed');\n if (\n state === ConnectionState.CONN_CONNECTED &&\n this.room.isConnected &&\n !this.roomConnectedFuture.done\n ) {\n this.roomConnectedFuture.resolve();\n }\n };\n\n private onParticipantConnected = (participant: RemoteParticipant) => {\n if (this.participantAvailableFuture.done) {\n return;\n }\n\n if (this.participantIdentity) {\n if (participant.identity !== this.participantIdentity) {\n return;\n }\n } else if (\n // otherwise, skip participants that are marked as publishing for this agent\n participant.attributes?.[ATTRIBUTE_PUBLISH_ON_BEHALF] === this.room.localParticipant?.identity\n ) {\n return;\n }\n\n const acceptedKinds = this.inputOptions.participantKinds ?? DEFAULT_PARTICIPANT_KINDS;\n if (participant.info.kind !== undefined && !acceptedKinds.includes(participant.info.kind)) {\n return;\n }\n\n this.participantAvailableFuture.resolve(participant);\n };\n\n private onParticipantDisconnected = (participant: RemoteParticipant) => {\n if (participant.identity !== this.participantIdentity) {\n return;\n }\n this.participantAvailableFuture = new Future<RemoteParticipant>();\n if (\n this.inputOptions.closeOnDisconnect &&\n participant.disconnectReason &&\n CLOSE_ON_DISCONNECT_REASONS.includes(participant.disconnectReason)\n ) {\n this.logger.info(\n {\n participant: participant.identity,\n reason: DisconnectReason[participant.disconnectReason],\n },\n 'closing agent session due to participant disconnect ' +\n '(disable via `RoomInputOptions.closeOnDisconnect=False`)',\n );\n this.agentSession._closeSoon({\n reason: CloseReason.PARTICIPANT_DISCONNECTED,\n });\n }\n };\n\n private onUserInputTranscribed = (ev: UserInputTranscribedEvent) => {\n this.userTranscriptWriter.write(ev).catch((error) => {\n this.logger.error({ error }, 'Failed to write transcript event to stream');\n });\n };\n\n private onAgentStateChanged = async (ev: AgentStateChangedEvent) => {\n if (this.room.isConnected && this.room.localParticipant) {\n await this.room.localParticipant.setAttributes({\n [`lk.agent.state`]: ev.newState,\n });\n }\n };\n\n private async forwardUserTranscript(signal: AbortSignal): Promise<void> {\n const reader = this.userTranscriptStream.readable.getReader();\n try {\n while (!signal.aborted) {\n const { done, value } = await reader.read();\n if (done) break;\n\n const event = value;\n // IMPORTANT: need to await here to avoid race condition\n await this.userTranscriptOutput?.captureText(event.transcript);\n if (event.isFinal) {\n this.userTranscriptOutput?.flush();\n }\n }\n } catch (error) {\n this.logger.error({ error }, 'Error processing transcript stream');\n }\n }\n\n private createTranscriptionOutput(options: {\n isDeltaStream: boolean;\n participant: Participant | string | null;\n }) {\n return new ParalellTextOutput([\n new ParticipantLegacyTranscriptionOutput(\n this.room,\n options.isDeltaStream,\n options.participant,\n ),\n new ParticipantTranscriptionOutput(this.room, options.isDeltaStream, options.participant),\n ]);\n }\n\n private updateTranscriptionOutput({\n output,\n participant,\n }: {\n output?: ParalellTextOutput;\n participant: string | null;\n }) {\n if (!output) {\n return;\n }\n\n for (const sink of output._sinks) {\n if (\n sink instanceof ParticipantLegacyTranscriptionOutput ||\n sink instanceof ParticipantTranscriptionOutput\n ) {\n sink.setParticipant(participant);\n }\n }\n }\n\n get audioOutput(): AudioOutput | undefined {\n if (!this.transcriptionSynchronizer) {\n return this.participantAudioOutput;\n }\n\n return this.transcriptionSynchronizer.audioOutput;\n }\n\n get transcriptionOutput(): TextOutput | undefined {\n if (!this.transcriptionSynchronizer) {\n return this.agentTranscriptOutput;\n }\n\n return this.transcriptionSynchronizer.textOutput;\n }\n\n get isParticipantAvailable(): boolean {\n return this.participantAvailableFuture.done;\n }\n\n get rtcRoom(): Room {\n return this.room;\n }\n\n get linkedParticipant(): RemoteParticipant | undefined {\n if (!this.isParticipantAvailable) {\n return undefined;\n }\n\n return this.participantAvailableFuture.result;\n }\n\n get localParticipant(): Participant | undefined {\n return this.room.localParticipant ?? undefined;\n }\n\n /** Switch to a different participant */\n setParticipant(participantIdentity: string | null) {\n this.logger.debug({ participantIdentity }, 'setting participant');\n if (participantIdentity === null) {\n this.unsetParticipant();\n return;\n }\n\n if (this.participantIdentity !== participantIdentity) {\n this.participantAvailableFuture = new Future<RemoteParticipant>();\n\n // check if new participant is already connected\n for (const participant of this.room.remoteParticipants.values()) {\n if (participant.identity === participantIdentity) {\n this.participantAvailableFuture.resolve(participant);\n break;\n }\n }\n }\n\n // update participant identity and handlers\n this.participantIdentity = participantIdentity;\n this.audioInput?.setParticipant(participantIdentity);\n this.updateTranscriptionOutput({\n output: this.userTranscriptOutput,\n participant: participantIdentity,\n });\n }\n\n unsetParticipant() {\n this.participantIdentity = null;\n this.participantAvailableFuture = new Future<RemoteParticipant>();\n this.audioInput?.setParticipant(null);\n this.updateTranscriptionOutput({\n output: this.userTranscriptOutput,\n participant: null,\n });\n }\n\n start() {\n // -- create inputs --\n if (this.inputOptions.audioEnabled) {\n this.audioInput = new ParticipantAudioInputStream({\n room: this.room,\n sampleRate: this.inputOptions.audioSampleRate,\n numChannels: this.inputOptions.audioNumChannels,\n noiseCancellation: this.inputOptions.noiseCancellation,\n });\n }\n\n // -- create outputs --\n if (this.outputOptions.audioEnabled) {\n this.participantAudioOutput = new ParticipantAudioOutput(this.room, {\n sampleRate: this.outputOptions.audioSampleRate,\n numChannels: this.outputOptions.audioNumChannels,\n trackPublishOptions: this.outputOptions.audioPublishOptions,\n });\n }\n if (this.outputOptions.transcriptionEnabled) {\n this.userTranscriptOutput = this.createTranscriptionOutput({\n isDeltaStream: false,\n participant: this.participantIdentity,\n });\n // Start the transcript forwarding\n this.forwardUserTranscriptTask = Task.from((controller) =>\n this.forwardUserTranscript(controller.signal),\n );\n this.agentTranscriptOutput = this.createTranscriptionOutput({\n isDeltaStream: true,\n participant: null,\n });\n\n // use the RoomIO's audio output if available, otherwise use the agent's audio output\n // TODO(AJS-176): check for agent output\n const audioOutput = this.participantAudioOutput;\n if (this.outputOptions.syncTranscription && audioOutput) {\n this.transcriptionSynchronizer = new TranscriptionSynchronizer(\n audioOutput,\n this.agentTranscriptOutput,\n );\n }\n }\n\n // -- set the room event handlers --\n this.room.on(RoomEvent.ParticipantConnected, this.onParticipantConnected);\n this.room.on(RoomEvent.ConnectionStateChanged, this.onConnectionStateChanged);\n this.room.on(RoomEvent.ParticipantDisconnected, this.onParticipantDisconnected);\n if (this.room.isConnected) {\n this.onConnectionStateChanged(ConnectionState.CONN_CONNECTED);\n }\n\n this.initTask = Task.from((controller) => this.init(controller.signal));\n\n // attach the agent to the session\n if (this.audioInput) {\n this.agentSession.input.audio = this.audioInput;\n }\n if (this.audioOutput) {\n this.agentSession.output.audio = this.audioOutput;\n }\n if (this.transcriptionOutput) {\n this.agentSession.output.transcription = this.transcriptionOutput;\n }\n\n this.agentSession.on(AgentSessionEventTypes.AgentStateChanged, this.onAgentStateChanged);\n this.agentSession.on(AgentSessionEventTypes.UserInputTranscribed, this.onUserInputTranscribed);\n }\n\n async close() {\n this.room.off(RoomEvent.ParticipantConnected, this.onParticipantConnected);\n this.room.off(RoomEvent.ConnectionStateChanged, this.onConnectionStateChanged);\n this.room.off(RoomEvent.ParticipantDisconnected, this.onParticipantDisconnected);\n this.agentSession.off(AgentSessionEventTypes.UserInputTranscribed, this.onUserInputTranscribed);\n this.agentSession.off(AgentSessionEventTypes.AgentStateChanged, this.onAgentStateChanged);\n\n await this.initTask?.cancelAndWait();\n\n // Close stream FIRST so reader.read() in forwardUserTranscript can exit.\n // This is a workaround for a race condition in the stream API.\n this.userTranscriptWriter.close();\n await this.forwardUserTranscriptTask?.cancelAndWait();\n\n await this.audioInput?.close();\n await this.participantAudioOutput?.close();\n await this.transcriptionSynchronizer?.close();\n }\n}\n"],"mappings":"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","names":["participant"]}
@@ -1,12 +1,8 @@
1
- import { type AudioFrame, type FrameProcessor, type NoiseCancellationOptions, type Participant, ParticipantKind, type RemoteParticipant, type Room, type TextStreamInfo, TrackPublishOptions } from '@livekit/rtc-node';
1
+ import { type AudioFrame, type FrameProcessor, type NoiseCancellationOptions, type Participant, ParticipantKind, type RemoteParticipant, type Room, TrackPublishOptions } from '@livekit/rtc-node';
2
2
  import { type AgentSession } from '../agent_session.js';
3
+ import type { TextInputCallback } from '../client_events.js';
3
4
  import type { AudioOutput, TextOutput } from '../io.js';
4
- export interface TextInputEvent {
5
- text: string;
6
- info: TextStreamInfo;
7
- participant: RemoteParticipant;
8
- }
9
- export type TextInputCallback = (sess: AgentSession, ev: TextInputEvent) => void | Promise<void>;
5
+ export declare const DEFAULT_TEXT_INPUT_CALLBACK: TextInputCallback;
10
6
  export interface RoomInputOptions {
11
7
  audioSampleRate: number;
12
8
  audioNumChannels: number;
@@ -63,7 +59,6 @@ export declare class RoomIO {
63
59
  private userTranscriptWriter;
64
60
  private forwardUserTranscriptTask?;
65
61
  private initTask?;
66
- private textStreamHandlerRegistered;
67
62
  private logger;
68
63
  constructor({ agentSession, room, participant, inputOptions, outputOptions, }: {
69
64
  agentSession: AgentSession;
@@ -78,13 +73,13 @@ export declare class RoomIO {
78
73
  private onParticipantDisconnected;
79
74
  private onUserInputTranscribed;
80
75
  private onAgentStateChanged;
81
- private onUserTextInput;
82
76
  private forwardUserTranscript;
83
77
  private createTranscriptionOutput;
84
78
  private updateTranscriptionOutput;
85
79
  get audioOutput(): AudioOutput | undefined;
86
80
  get transcriptionOutput(): TextOutput | undefined;
87
81
  get isParticipantAvailable(): boolean;
82
+ get rtcRoom(): Room;
88
83
  get linkedParticipant(): RemoteParticipant | undefined;
89
84
  get localParticipant(): Participant | undefined;
90
85
  /** Switch to a different participant */
@@ -1,12 +1,8 @@
1
- import { type AudioFrame, type FrameProcessor, type NoiseCancellationOptions, type Participant, ParticipantKind, type RemoteParticipant, type Room, type TextStreamInfo, TrackPublishOptions } from '@livekit/rtc-node';
1
+ import { type AudioFrame, type FrameProcessor, type NoiseCancellationOptions, type Participant, ParticipantKind, type RemoteParticipant, type Room, TrackPublishOptions } from '@livekit/rtc-node';
2
2
  import { type AgentSession } from '../agent_session.js';
3
+ import type { TextInputCallback } from '../client_events.js';
3
4
  import type { AudioOutput, TextOutput } from '../io.js';
4
- export interface TextInputEvent {
5
- text: string;
6
- info: TextStreamInfo;
7
- participant: RemoteParticipant;
8
- }
9
- export type TextInputCallback = (sess: AgentSession, ev: TextInputEvent) => void | Promise<void>;
5
+ export declare const DEFAULT_TEXT_INPUT_CALLBACK: TextInputCallback;
10
6
  export interface RoomInputOptions {
11
7
  audioSampleRate: number;
12
8
  audioNumChannels: number;
@@ -63,7 +59,6 @@ export declare class RoomIO {
63
59
  private userTranscriptWriter;
64
60
  private forwardUserTranscriptTask?;
65
61
  private initTask?;
66
- private textStreamHandlerRegistered;
67
62
  private logger;
68
63
  constructor({ agentSession, room, participant, inputOptions, outputOptions, }: {
69
64
  agentSession: AgentSession;
@@ -78,13 +73,13 @@ export declare class RoomIO {
78
73
  private onParticipantDisconnected;
79
74
  private onUserInputTranscribed;
80
75
  private onAgentStateChanged;
81
- private onUserTextInput;
82
76
  private forwardUserTranscript;
83
77
  private createTranscriptionOutput;
84
78
  private updateTranscriptionOutput;
85
79
  get audioOutput(): AudioOutput | undefined;
86
80
  get transcriptionOutput(): TextOutput | undefined;
87
81
  get isParticipantAvailable(): boolean;
82
+ get rtcRoom(): Room;
88
83
  get linkedParticipant(): RemoteParticipant | undefined;
89
84
  get localParticipant(): Participant | undefined;
90
85
  /** Switch to a different participant */