@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":"room_io.d.ts","sourceRoot":"","sources":["../../../src/voice/room_io/room_io.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"room_io.d.ts","sourceRoot":"","sources":["../../../src/voice/room_io/room_io.ts"],"names":[],"mappings":"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"}
@@ -6,10 +6,10 @@ import {
6
6
  TrackPublishOptions,
7
7
  TrackSource
8
8
  } from "@livekit/rtc-node";
9
- import { ATTRIBUTE_PUBLISH_ON_BEHALF, TOPIC_CHAT } from "../../constants.js";
9
+ import { ATTRIBUTE_PUBLISH_ON_BEHALF } from "../../constants.js";
10
10
  import { log } from "../../log.js";
11
11
  import { IdentityTransform } from "../../stream/identity_transform.js";
12
- import { Future, Task } from "../../utils.js";
12
+ import { Future, Task, waitForAbort } from "../../utils.js";
13
13
  import {} from "../agent_session.js";
14
14
  import {
15
15
  AgentSessionEventTypes,
@@ -72,7 +72,6 @@ class RoomIO {
72
72
  userTranscriptWriter;
73
73
  forwardUserTranscriptTask;
74
74
  initTask;
75
- textStreamHandlerRegistered = false;
76
75
  logger = log();
77
76
  constructor({
78
77
  agentSession,
@@ -90,14 +89,23 @@ class RoomIO {
90
89
  }
91
90
  async init(signal) {
92
91
  var _a, _b;
93
- await this.roomConnectedFuture.await;
92
+ await Promise.race([this.roomConnectedFuture.await, waitForAbort(signal)]);
93
+ if (signal.aborted) {
94
+ return;
95
+ }
94
96
  for (const participant2 of this.room.remoteParticipants.values()) {
95
97
  this.onParticipantConnected(participant2);
96
98
  }
97
99
  if (signal.aborted) {
98
100
  return;
99
101
  }
100
- const participant = await this.participantAvailableFuture.await;
102
+ const participant = await Promise.race([
103
+ this.participantAvailableFuture.await,
104
+ waitForAbort(signal)
105
+ ]);
106
+ if (!participant) {
107
+ return;
108
+ }
101
109
  this.setParticipant(participant.identity);
102
110
  this.updateTranscriptionOutput({
103
111
  output: this.agentTranscriptOutput,
@@ -162,30 +170,6 @@ class RoomIO {
162
170
  });
163
171
  }
164
172
  };
165
- onUserTextInput = (reader, participantInfo) => {
166
- if (participantInfo.identity !== this.participantIdentity) {
167
- return;
168
- }
169
- const participant = this.room.remoteParticipants.get(participantInfo.identity);
170
- if (!participant) {
171
- this.logger.warn("participant not found, ignoring text input");
172
- return;
173
- }
174
- const readText = async () => {
175
- const text = await reader.readAll();
176
- const textInputResult = this.inputOptions.textInputCallback(this.agentSession, {
177
- text,
178
- info: reader.info,
179
- participant
180
- });
181
- if (textInputResult instanceof Promise) {
182
- await textInputResult;
183
- }
184
- };
185
- readText().catch((error) => {
186
- this.logger.error({ error }, "Error reading text input");
187
- });
188
- };
189
173
  async forwardUserTranscript(signal) {
190
174
  var _a, _b;
191
175
  const reader = this.userTranscriptStream.readable.getReader();
@@ -241,6 +225,9 @@ class RoomIO {
241
225
  get isParticipantAvailable() {
242
226
  return this.participantAvailableFuture.done;
243
227
  }
228
+ get rtcRoom() {
229
+ return this.room;
230
+ }
244
231
  get linkedParticipant() {
245
232
  if (!this.isParticipantAvailable) {
246
233
  return void 0;
@@ -285,16 +272,6 @@ class RoomIO {
285
272
  });
286
273
  }
287
274
  start() {
288
- if (this.inputOptions.textEnabled) {
289
- try {
290
- this.room.registerTextStreamHandler(TOPIC_CHAT, this.onUserTextInput);
291
- this.textStreamHandlerRegistered = true;
292
- } catch (error) {
293
- if (this.inputOptions.textEnabled) {
294
- this.logger.warn(`text stream handler for topic "${TOPIC_CHAT}" already set, ignoring`);
295
- }
296
- }
297
- }
298
275
  if (this.inputOptions.audioEnabled) {
299
276
  this.audioInput = new ParticipantAudioInputStream({
300
277
  room: this.room,
@@ -356,10 +333,6 @@ class RoomIO {
356
333
  this.room.off(RoomEvent.ParticipantDisconnected, this.onParticipantDisconnected);
357
334
  this.agentSession.off(AgentSessionEventTypes.UserInputTranscribed, this.onUserInputTranscribed);
358
335
  this.agentSession.off(AgentSessionEventTypes.AgentStateChanged, this.onAgentStateChanged);
359
- if (this.textStreamHandlerRegistered) {
360
- this.room.unregisterTextStreamHandler(TOPIC_CHAT);
361
- this.textStreamHandlerRegistered = false;
362
- }
363
336
  await ((_a = this.initTask) == null ? void 0 : _a.cancelAndWait());
364
337
  this.userTranscriptWriter.close();
365
338
  await ((_b = this.forwardUserTranscriptTask) == null ? void 0 : _b.cancelAndWait());
@@ -369,6 +342,7 @@ class RoomIO {
369
342
  }
370
343
  }
371
344
  export {
345
+ DEFAULT_TEXT_INPUT_CALLBACK,
372
346
  RoomIO
373
347
  };
374
348
  //# sourceMappingURL=room_io.js.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"]}
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var fake_llm_exports = {};
20
+ __export(fake_llm_exports, {
21
+ FakeLLM: () => FakeLLM
22
+ });
23
+ module.exports = __toCommonJS(fake_llm_exports);
24
+ var import_chat_context = require("../../llm/chat_context.cjs");
25
+ var import_llm = require("../../llm/llm.cjs");
26
+ var import_types = require("../../types.cjs");
27
+ var import_utils = require("../../utils.cjs");
28
+ class FakeLLM extends import_llm.LLM {
29
+ responseMap = /* @__PURE__ */ new Map();
30
+ constructor(responses = []) {
31
+ super();
32
+ for (const response of responses) {
33
+ this.responseMap.set(response.input, {
34
+ type: "llm",
35
+ ttft: 0,
36
+ duration: 0,
37
+ ...response
38
+ });
39
+ }
40
+ }
41
+ label() {
42
+ return "fake-llm";
43
+ }
44
+ chat({
45
+ chatCtx,
46
+ toolCtx,
47
+ connOptions = import_types.DEFAULT_API_CONNECT_OPTIONS
48
+ }) {
49
+ return new FakeLLMStream(this, {
50
+ chatCtx,
51
+ toolCtx,
52
+ connOptions
53
+ });
54
+ }
55
+ lookup(input) {
56
+ return this.responseMap.get(input);
57
+ }
58
+ }
59
+ class FakeLLMStream extends import_llm.LLMStream {
60
+ fake;
61
+ constructor(fake, params) {
62
+ super(fake, params);
63
+ this.fake = fake;
64
+ }
65
+ async run() {
66
+ const input = this.getInputText();
67
+ const decision = this.fake.lookup(input);
68
+ if (!decision) {
69
+ return;
70
+ }
71
+ const startedAt = Date.now();
72
+ if ((decision.ttft ?? 0) > 0) {
73
+ await (0, import_utils.delay)(decision.ttft);
74
+ }
75
+ const content = decision.content ?? "";
76
+ const chunkSize = 3;
77
+ for (let i = 0; i < content.length; i += chunkSize) {
78
+ this.queue.put({
79
+ id: "fake",
80
+ delta: { role: "assistant", content: content.slice(i, i + chunkSize) }
81
+ });
82
+ }
83
+ if (decision.toolCalls && decision.toolCalls.length > 0) {
84
+ const calls = decision.toolCalls.map(
85
+ (tc, index) => import_chat_context.FunctionCall.create({
86
+ callId: `fake_call_${index}`,
87
+ name: tc.name,
88
+ args: JSON.stringify(tc.args)
89
+ })
90
+ );
91
+ this.queue.put({
92
+ id: "fake",
93
+ delta: { role: "assistant", toolCalls: calls }
94
+ });
95
+ }
96
+ const elapsed = Date.now() - startedAt;
97
+ const waitMs = Math.max(0, (decision.duration ?? 0) - elapsed);
98
+ if (waitMs > 0) {
99
+ await (0, import_utils.delay)(waitMs);
100
+ }
101
+ }
102
+ getInputText() {
103
+ const items = this.chatCtx.items;
104
+ if (items.length === 0) {
105
+ throw new Error("No input text found");
106
+ }
107
+ for (const item of items) {
108
+ if (item.type === "message" && item.role === "system") {
109
+ const text = item.textContent ?? "";
110
+ const lines = text.split("\n");
111
+ const tail = lines[lines.length - 1] ?? "";
112
+ if (lines.length > 1 && tail.startsWith("instructions:")) {
113
+ return tail;
114
+ }
115
+ }
116
+ }
117
+ const last = items[items.length - 1];
118
+ if (last.type === "message" && last.role === "user") return last.textContent ?? "";
119
+ if (last.type === "function_call_output") return last.output;
120
+ throw new Error("No input text found");
121
+ }
122
+ }
123
+ // Annotate the CommonJS export names for ESM import in node:
124
+ 0 && (module.exports = {
125
+ FakeLLM
126
+ });
127
+ //# sourceMappingURL=fake_llm.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/voice/testing/fake_llm.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2026 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { ChatContext } from '../../llm/chat_context.js';\nimport { FunctionCall } from '../../llm/chat_context.js';\nimport { LLMStream as BaseLLMStream, LLM, type LLMStream } from '../../llm/llm.js';\nimport type { ToolChoice, ToolContext } from '../../llm/tool_context.js';\nimport { type APIConnectOptions, DEFAULT_API_CONNECT_OPTIONS } from '../../types.js';\nimport { delay } from '../../utils.js';\n\nexport interface FakeLLMResponse {\n input: string;\n type?: 'llm';\n content?: string;\n ttft?: number;\n duration?: number;\n toolCalls?: Array<{ name: string; args: Record<string, unknown> }>;\n}\n\nexport class FakeLLM extends LLM {\n private readonly responseMap = new Map<string, FakeLLMResponse>();\n\n constructor(responses: FakeLLMResponse[] = []) {\n super();\n for (const response of responses) {\n this.responseMap.set(response.input, {\n type: 'llm',\n ttft: 0,\n duration: 0,\n ...response,\n });\n }\n }\n\n label(): string {\n return 'fake-llm';\n }\n\n chat({\n chatCtx,\n toolCtx,\n connOptions = DEFAULT_API_CONNECT_OPTIONS,\n }: {\n chatCtx: ChatContext;\n toolCtx?: ToolContext;\n connOptions?: APIConnectOptions;\n parallelToolCalls?: boolean;\n toolChoice?: ToolChoice;\n extraKwargs?: Record<string, unknown>;\n }): LLMStream {\n return new FakeLLMStream(this, {\n chatCtx,\n toolCtx,\n connOptions,\n });\n }\n\n lookup(input: string): FakeLLMResponse | undefined {\n return this.responseMap.get(input);\n }\n}\n\nclass FakeLLMStream extends BaseLLMStream {\n private readonly fake: FakeLLM;\n\n constructor(\n fake: FakeLLM,\n params: { chatCtx: ChatContext; toolCtx?: ToolContext; connOptions: APIConnectOptions },\n ) {\n super(fake, params);\n this.fake = fake;\n }\n\n protected async run(): Promise<void> {\n const input = this.getInputText();\n const decision = this.fake.lookup(input);\n if (!decision) {\n return;\n }\n\n const startedAt = Date.now();\n if ((decision.ttft ?? 0) > 0) {\n await delay(decision.ttft!);\n }\n\n const content = decision.content ?? '';\n const chunkSize = 3;\n for (let i = 0; i < content.length; i += chunkSize) {\n this.queue.put({\n id: 'fake',\n delta: { role: 'assistant', content: content.slice(i, i + chunkSize) },\n });\n }\n\n if (decision.toolCalls && decision.toolCalls.length > 0) {\n const calls = decision.toolCalls.map((tc, index) =>\n FunctionCall.create({\n callId: `fake_call_${index}`,\n name: tc.name,\n args: JSON.stringify(tc.args),\n }),\n );\n this.queue.put({\n id: 'fake',\n delta: { role: 'assistant', toolCalls: calls },\n });\n }\n\n const elapsed = Date.now() - startedAt;\n const waitMs = Math.max(0, (decision.duration ?? 0) - elapsed);\n if (waitMs > 0) {\n await delay(waitMs);\n }\n }\n\n private getInputText(): string {\n const items = this.chatCtx.items;\n if (items.length === 0) {\n throw new Error('No input text found');\n }\n\n for (const item of items) {\n if (item.type === 'message' && item.role === 'system') {\n const text = item.textContent ?? '';\n const lines = text.split('\\n');\n const tail = lines[lines.length - 1] ?? '';\n if (lines.length > 1 && tail.startsWith('instructions:')) {\n return tail;\n }\n }\n }\n\n const last = items[items.length - 1]!;\n if (last.type === 'message' && last.role === 'user') return last.textContent ?? '';\n if (last.type === 'function_call_output') return last.output;\n throw new Error('No input text found');\n }\n}\n"],"mappings":"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","names":["BaseLLMStream"]}
@@ -0,0 +1,30 @@
1
+ import type { ChatContext } from '../../llm/chat_context.js';
2
+ import { LLM, type LLMStream } from '../../llm/llm.js';
3
+ import type { ToolChoice, ToolContext } from '../../llm/tool_context.js';
4
+ import { type APIConnectOptions } from '../../types.js';
5
+ export interface FakeLLMResponse {
6
+ input: string;
7
+ type?: 'llm';
8
+ content?: string;
9
+ ttft?: number;
10
+ duration?: number;
11
+ toolCalls?: Array<{
12
+ name: string;
13
+ args: Record<string, unknown>;
14
+ }>;
15
+ }
16
+ export declare class FakeLLM extends LLM {
17
+ private readonly responseMap;
18
+ constructor(responses?: FakeLLMResponse[]);
19
+ label(): string;
20
+ chat({ chatCtx, toolCtx, connOptions, }: {
21
+ chatCtx: ChatContext;
22
+ toolCtx?: ToolContext;
23
+ connOptions?: APIConnectOptions;
24
+ parallelToolCalls?: boolean;
25
+ toolChoice?: ToolChoice;
26
+ extraKwargs?: Record<string, unknown>;
27
+ }): LLMStream;
28
+ lookup(input: string): FakeLLMResponse | undefined;
29
+ }
30
+ //# sourceMappingURL=fake_llm.d.ts.map
@@ -0,0 +1,30 @@
1
+ import type { ChatContext } from '../../llm/chat_context.js';
2
+ import { LLM, type LLMStream } from '../../llm/llm.js';
3
+ import type { ToolChoice, ToolContext } from '../../llm/tool_context.js';
4
+ import { type APIConnectOptions } from '../../types.js';
5
+ export interface FakeLLMResponse {
6
+ input: string;
7
+ type?: 'llm';
8
+ content?: string;
9
+ ttft?: number;
10
+ duration?: number;
11
+ toolCalls?: Array<{
12
+ name: string;
13
+ args: Record<string, unknown>;
14
+ }>;
15
+ }
16
+ export declare class FakeLLM extends LLM {
17
+ private readonly responseMap;
18
+ constructor(responses?: FakeLLMResponse[]);
19
+ label(): string;
20
+ chat({ chatCtx, toolCtx, connOptions, }: {
21
+ chatCtx: ChatContext;
22
+ toolCtx?: ToolContext;
23
+ connOptions?: APIConnectOptions;
24
+ parallelToolCalls?: boolean;
25
+ toolChoice?: ToolChoice;
26
+ extraKwargs?: Record<string, unknown>;
27
+ }): LLMStream;
28
+ lookup(input: string): FakeLLMResponse | undefined;
29
+ }
30
+ //# sourceMappingURL=fake_llm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fake_llm.d.ts","sourceRoot":"","sources":["../../../src/voice/testing/fake_llm.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAE7D,OAAO,EAA8B,GAAG,EAAE,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACnF,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACzE,OAAO,EAAE,KAAK,iBAAiB,EAA+B,MAAM,gBAAgB,CAAC;AAGrF,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;CACpE;AAED,qBAAa,OAAQ,SAAQ,GAAG;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAsC;gBAEtD,SAAS,GAAE,eAAe,EAAO;IAY7C,KAAK,IAAI,MAAM;IAIf,IAAI,CAAC,EACH,OAAO,EACP,OAAO,EACP,WAAyC,GAC1C,EAAE;QACD,OAAO,EAAE,WAAW,CAAC;QACrB,OAAO,CAAC,EAAE,WAAW,CAAC;QACtB,WAAW,CAAC,EAAE,iBAAiB,CAAC;QAChC,iBAAiB,CAAC,EAAE,OAAO,CAAC;QAC5B,UAAU,CAAC,EAAE,UAAU,CAAC;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACvC,GAAG,SAAS;IAQb,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;CAGnD"}
@@ -0,0 +1,103 @@
1
+ import { FunctionCall } from "../../llm/chat_context.js";
2
+ import { LLMStream as BaseLLMStream, LLM } from "../../llm/llm.js";
3
+ import { DEFAULT_API_CONNECT_OPTIONS } from "../../types.js";
4
+ import { delay } from "../../utils.js";
5
+ class FakeLLM extends LLM {
6
+ responseMap = /* @__PURE__ */ new Map();
7
+ constructor(responses = []) {
8
+ super();
9
+ for (const response of responses) {
10
+ this.responseMap.set(response.input, {
11
+ type: "llm",
12
+ ttft: 0,
13
+ duration: 0,
14
+ ...response
15
+ });
16
+ }
17
+ }
18
+ label() {
19
+ return "fake-llm";
20
+ }
21
+ chat({
22
+ chatCtx,
23
+ toolCtx,
24
+ connOptions = DEFAULT_API_CONNECT_OPTIONS
25
+ }) {
26
+ return new FakeLLMStream(this, {
27
+ chatCtx,
28
+ toolCtx,
29
+ connOptions
30
+ });
31
+ }
32
+ lookup(input) {
33
+ return this.responseMap.get(input);
34
+ }
35
+ }
36
+ class FakeLLMStream extends BaseLLMStream {
37
+ fake;
38
+ constructor(fake, params) {
39
+ super(fake, params);
40
+ this.fake = fake;
41
+ }
42
+ async run() {
43
+ const input = this.getInputText();
44
+ const decision = this.fake.lookup(input);
45
+ if (!decision) {
46
+ return;
47
+ }
48
+ const startedAt = Date.now();
49
+ if ((decision.ttft ?? 0) > 0) {
50
+ await delay(decision.ttft);
51
+ }
52
+ const content = decision.content ?? "";
53
+ const chunkSize = 3;
54
+ for (let i = 0; i < content.length; i += chunkSize) {
55
+ this.queue.put({
56
+ id: "fake",
57
+ delta: { role: "assistant", content: content.slice(i, i + chunkSize) }
58
+ });
59
+ }
60
+ if (decision.toolCalls && decision.toolCalls.length > 0) {
61
+ const calls = decision.toolCalls.map(
62
+ (tc, index) => FunctionCall.create({
63
+ callId: `fake_call_${index}`,
64
+ name: tc.name,
65
+ args: JSON.stringify(tc.args)
66
+ })
67
+ );
68
+ this.queue.put({
69
+ id: "fake",
70
+ delta: { role: "assistant", toolCalls: calls }
71
+ });
72
+ }
73
+ const elapsed = Date.now() - startedAt;
74
+ const waitMs = Math.max(0, (decision.duration ?? 0) - elapsed);
75
+ if (waitMs > 0) {
76
+ await delay(waitMs);
77
+ }
78
+ }
79
+ getInputText() {
80
+ const items = this.chatCtx.items;
81
+ if (items.length === 0) {
82
+ throw new Error("No input text found");
83
+ }
84
+ for (const item of items) {
85
+ if (item.type === "message" && item.role === "system") {
86
+ const text = item.textContent ?? "";
87
+ const lines = text.split("\n");
88
+ const tail = lines[lines.length - 1] ?? "";
89
+ if (lines.length > 1 && tail.startsWith("instructions:")) {
90
+ return tail;
91
+ }
92
+ }
93
+ }
94
+ const last = items[items.length - 1];
95
+ if (last.type === "message" && last.role === "user") return last.textContent ?? "";
96
+ if (last.type === "function_call_output") return last.output;
97
+ throw new Error("No input text found");
98
+ }
99
+ }
100
+ export {
101
+ FakeLLM
102
+ };
103
+ //# sourceMappingURL=fake_llm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/voice/testing/fake_llm.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2026 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { ChatContext } from '../../llm/chat_context.js';\nimport { FunctionCall } from '../../llm/chat_context.js';\nimport { LLMStream as BaseLLMStream, LLM, type LLMStream } from '../../llm/llm.js';\nimport type { ToolChoice, ToolContext } from '../../llm/tool_context.js';\nimport { type APIConnectOptions, DEFAULT_API_CONNECT_OPTIONS } from '../../types.js';\nimport { delay } from '../../utils.js';\n\nexport interface FakeLLMResponse {\n input: string;\n type?: 'llm';\n content?: string;\n ttft?: number;\n duration?: number;\n toolCalls?: Array<{ name: string; args: Record<string, unknown> }>;\n}\n\nexport class FakeLLM extends LLM {\n private readonly responseMap = new Map<string, FakeLLMResponse>();\n\n constructor(responses: FakeLLMResponse[] = []) {\n super();\n for (const response of responses) {\n this.responseMap.set(response.input, {\n type: 'llm',\n ttft: 0,\n duration: 0,\n ...response,\n });\n }\n }\n\n label(): string {\n return 'fake-llm';\n }\n\n chat({\n chatCtx,\n toolCtx,\n connOptions = DEFAULT_API_CONNECT_OPTIONS,\n }: {\n chatCtx: ChatContext;\n toolCtx?: ToolContext;\n connOptions?: APIConnectOptions;\n parallelToolCalls?: boolean;\n toolChoice?: ToolChoice;\n extraKwargs?: Record<string, unknown>;\n }): LLMStream {\n return new FakeLLMStream(this, {\n chatCtx,\n toolCtx,\n connOptions,\n });\n }\n\n lookup(input: string): FakeLLMResponse | undefined {\n return this.responseMap.get(input);\n }\n}\n\nclass FakeLLMStream extends BaseLLMStream {\n private readonly fake: FakeLLM;\n\n constructor(\n fake: FakeLLM,\n params: { chatCtx: ChatContext; toolCtx?: ToolContext; connOptions: APIConnectOptions },\n ) {\n super(fake, params);\n this.fake = fake;\n }\n\n protected async run(): Promise<void> {\n const input = this.getInputText();\n const decision = this.fake.lookup(input);\n if (!decision) {\n return;\n }\n\n const startedAt = Date.now();\n if ((decision.ttft ?? 0) > 0) {\n await delay(decision.ttft!);\n }\n\n const content = decision.content ?? '';\n const chunkSize = 3;\n for (let i = 0; i < content.length; i += chunkSize) {\n this.queue.put({\n id: 'fake',\n delta: { role: 'assistant', content: content.slice(i, i + chunkSize) },\n });\n }\n\n if (decision.toolCalls && decision.toolCalls.length > 0) {\n const calls = decision.toolCalls.map((tc, index) =>\n FunctionCall.create({\n callId: `fake_call_${index}`,\n name: tc.name,\n args: JSON.stringify(tc.args),\n }),\n );\n this.queue.put({\n id: 'fake',\n delta: { role: 'assistant', toolCalls: calls },\n });\n }\n\n const elapsed = Date.now() - startedAt;\n const waitMs = Math.max(0, (decision.duration ?? 0) - elapsed);\n if (waitMs > 0) {\n await delay(waitMs);\n }\n }\n\n private getInputText(): string {\n const items = this.chatCtx.items;\n if (items.length === 0) {\n throw new Error('No input text found');\n }\n\n for (const item of items) {\n if (item.type === 'message' && item.role === 'system') {\n const text = item.textContent ?? '';\n const lines = text.split('\\n');\n const tail = lines[lines.length - 1] ?? '';\n if (lines.length > 1 && tail.startsWith('instructions:')) {\n return tail;\n }\n }\n }\n\n const last = items[items.length - 1]!;\n if (last.type === 'message' && last.role === 'user') return last.textContent ?? '';\n if (last.type === 'function_call_output') return last.output;\n throw new Error('No input text found');\n }\n}\n"],"mappings":"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","names":[]}
@@ -22,6 +22,7 @@ __export(testing_exports, {
22
22
  AssertionError: () => import_run_result.AssertionError,
23
23
  EventAssert: () => import_run_result.EventAssert,
24
24
  EventRangeAssert: () => import_run_result.EventRangeAssert,
25
+ FakeLLM: () => import_fake_llm.FakeLLM,
25
26
  FunctionCallAssert: () => import_run_result.FunctionCallAssert,
26
27
  FunctionCallOutputAssert: () => import_run_result.FunctionCallOutputAssert,
27
28
  MessageAssert: () => import_run_result.MessageAssert,
@@ -35,12 +36,14 @@ __export(testing_exports, {
35
36
  module.exports = __toCommonJS(testing_exports);
36
37
  var import_run_result = require("./run_result.cjs");
37
38
  var import_types = require("./types.cjs");
39
+ var import_fake_llm = require("./fake_llm.cjs");
38
40
  // Annotate the CommonJS export names for ESM import in node:
39
41
  0 && (module.exports = {
40
42
  AgentHandoffAssert,
41
43
  AssertionError,
42
44
  EventAssert,
43
45
  EventRangeAssert,
46
+ FakeLLM,
44
47
  FunctionCallAssert,
45
48
  FunctionCallOutputAssert,
46
49
  MessageAssert,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/voice/testing/index.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Testing utilities for agent evaluation.\n *\n * @example\n * ```typescript\n * import { AgentSession, Agent, voice } from '@livekit/agents';\n *\n * const session = new AgentSession({ llm });\n * await session.start(agent);\n *\n * const result = await session.run({ userInput: 'Hello' });\n * result.expect.nextEvent().isMessage({ role: 'assistant' });\n * result.expect.noMoreEvents();\n * ```\n *\n * @packageDocumentation\n */\n\nexport {\n AgentHandoffAssert,\n AssertionError,\n EventAssert,\n EventRangeAssert,\n FunctionCallAssert,\n FunctionCallOutputAssert,\n MessageAssert,\n RunAssert,\n RunResult,\n} from './run_result.js';\n\nexport {\n isAgentHandoffEvent,\n isChatMessageEvent,\n isFunctionCallEvent,\n isFunctionCallOutputEvent,\n type AgentHandoffAssertOptions,\n type AgentHandoffEvent,\n type ChatMessageEvent,\n type EventType,\n type FunctionCallAssertOptions,\n type FunctionCallEvent,\n type FunctionCallOutputAssertOptions,\n type FunctionCallOutputEvent,\n type MessageAssertOptions,\n type RunEvent,\n} from './types.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBA,wBAUO;AAEP,mBAeO;","names":[]}
1
+ {"version":3,"sources":["../../../src/voice/testing/index.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Testing utilities for agent evaluation.\n *\n * @example\n * ```typescript\n * import { AgentSession, Agent, voice } from '@livekit/agents';\n *\n * const session = new AgentSession({ llm });\n * await session.start(agent);\n *\n * const result = await session.run({ userInput: 'Hello' });\n * result.expect.nextEvent().isMessage({ role: 'assistant' });\n * result.expect.noMoreEvents();\n * ```\n *\n * @packageDocumentation\n */\n\nexport {\n AgentHandoffAssert,\n AssertionError,\n EventAssert,\n EventRangeAssert,\n FunctionCallAssert,\n FunctionCallOutputAssert,\n MessageAssert,\n RunAssert,\n RunResult,\n} from './run_result.js';\n\nexport {\n isAgentHandoffEvent,\n isChatMessageEvent,\n isFunctionCallEvent,\n isFunctionCallOutputEvent,\n type AgentHandoffAssertOptions,\n type AgentHandoffEvent,\n type ChatMessageEvent,\n type EventType,\n type FunctionCallAssertOptions,\n type FunctionCallEvent,\n type FunctionCallOutputAssertOptions,\n type FunctionCallOutputEvent,\n type MessageAssertOptions,\n type RunEvent,\n} from './types.js';\n\nexport { FakeLLM, type FakeLLMResponse } from './fake_llm.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBA,wBAUO;AAEP,mBAeO;AAEP,sBAA8C;","names":[]}
@@ -17,4 +17,5 @@
17
17
  */
18
18
  export { AgentHandoffAssert, AssertionError, EventAssert, EventRangeAssert, FunctionCallAssert, FunctionCallOutputAssert, MessageAssert, RunAssert, RunResult, } from './run_result.js';
19
19
  export { isAgentHandoffEvent, isChatMessageEvent, isFunctionCallEvent, isFunctionCallOutputEvent, type AgentHandoffAssertOptions, type AgentHandoffEvent, type ChatMessageEvent, type EventType, type FunctionCallAssertOptions, type FunctionCallEvent, type FunctionCallOutputAssertOptions, type FunctionCallOutputEvent, type MessageAssertOptions, type RunEvent, } from './types.js';
20
+ export { FakeLLM, type FakeLLMResponse } from './fake_llm.js';
20
21
  //# sourceMappingURL=index.d.ts.map
@@ -17,4 +17,5 @@
17
17
  */
18
18
  export { AgentHandoffAssert, AssertionError, EventAssert, EventRangeAssert, FunctionCallAssert, FunctionCallOutputAssert, MessageAssert, RunAssert, RunResult, } from './run_result.js';
19
19
  export { isAgentHandoffEvent, isChatMessageEvent, isFunctionCallEvent, isFunctionCallOutputEvent, type AgentHandoffAssertOptions, type AgentHandoffEvent, type ChatMessageEvent, type EventType, type FunctionCallAssertOptions, type FunctionCallEvent, type FunctionCallOutputAssertOptions, type FunctionCallOutputEvent, type MessageAssertOptions, type RunEvent, } from './types.js';
20
+ export { FakeLLM, type FakeLLMResponse } from './fake_llm.js';
20
21
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/voice/testing/index.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EAClB,wBAAwB,EACxB,aAAa,EACb,SAAS,EACT,SAAS,GACV,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,yBAAyB,EACzB,KAAK,yBAAyB,EAC9B,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,KAAK,yBAAyB,EAC9B,KAAK,iBAAiB,EACtB,KAAK,+BAA+B,EACpC,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EACzB,KAAK,QAAQ,GACd,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/voice/testing/index.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EAClB,wBAAwB,EACxB,aAAa,EACb,SAAS,EACT,SAAS,GACV,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,yBAAyB,EACzB,KAAK,yBAAyB,EAC9B,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,KAAK,yBAAyB,EAC9B,KAAK,iBAAiB,EACtB,KAAK,+BAA+B,EACpC,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EACzB,KAAK,QAAQ,GACd,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC"}