@livekit/agents 0.7.9 → 1.0.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (627) hide show
  1. package/dist/_exceptions.cjs +109 -0
  2. package/dist/_exceptions.cjs.map +1 -0
  3. package/dist/_exceptions.d.cts +64 -0
  4. package/dist/_exceptions.d.ts +64 -0
  5. package/dist/_exceptions.d.ts.map +1 -0
  6. package/dist/_exceptions.js +80 -0
  7. package/dist/_exceptions.js.map +1 -0
  8. package/dist/audio.cjs +10 -3
  9. package/dist/audio.cjs.map +1 -1
  10. package/dist/audio.d.cts +2 -0
  11. package/dist/audio.d.ts +2 -0
  12. package/dist/audio.d.ts.map +1 -1
  13. package/dist/audio.js +8 -2
  14. package/dist/audio.js.map +1 -1
  15. package/dist/cli.cjs +25 -0
  16. package/dist/cli.cjs.map +1 -1
  17. package/dist/cli.d.ts.map +1 -1
  18. package/dist/cli.js +25 -0
  19. package/dist/cli.js.map +1 -1
  20. package/dist/constants.cjs +6 -3
  21. package/dist/constants.cjs.map +1 -1
  22. package/dist/constants.d.cts +2 -1
  23. package/dist/constants.d.ts +2 -1
  24. package/dist/constants.d.ts.map +1 -1
  25. package/dist/constants.js +4 -2
  26. package/dist/constants.js.map +1 -1
  27. package/dist/http_server.cjs.map +1 -1
  28. package/dist/http_server.d.cts +1 -0
  29. package/dist/http_server.d.ts +1 -0
  30. package/dist/http_server.d.ts.map +1 -1
  31. package/dist/http_server.js.map +1 -1
  32. package/dist/index.cjs +27 -20
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.d.cts +13 -10
  35. package/dist/index.d.ts +13 -10
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +15 -11
  38. package/dist/index.js.map +1 -1
  39. package/dist/inference_runner.cjs +0 -1
  40. package/dist/inference_runner.cjs.map +1 -1
  41. package/dist/inference_runner.d.cts +2 -3
  42. package/dist/inference_runner.d.ts +2 -3
  43. package/dist/inference_runner.d.ts.map +1 -1
  44. package/dist/inference_runner.js +0 -1
  45. package/dist/inference_runner.js.map +1 -1
  46. package/dist/ipc/inference_proc_executor.cjs +2 -2
  47. package/dist/ipc/inference_proc_executor.cjs.map +1 -1
  48. package/dist/ipc/inference_proc_executor.js +2 -2
  49. package/dist/ipc/inference_proc_executor.js.map +1 -1
  50. package/dist/ipc/job_executor.cjs.map +1 -1
  51. package/dist/ipc/job_executor.js.map +1 -1
  52. package/dist/ipc/job_proc_executor.cjs +1 -0
  53. package/dist/ipc/job_proc_executor.cjs.map +1 -1
  54. package/dist/ipc/job_proc_executor.js +1 -0
  55. package/dist/ipc/job_proc_executor.js.map +1 -1
  56. package/dist/ipc/job_proc_lazy_main.cjs +1 -1
  57. package/dist/ipc/job_proc_lazy_main.cjs.map +1 -1
  58. package/dist/ipc/job_proc_lazy_main.js +1 -1
  59. package/dist/ipc/job_proc_lazy_main.js.map +1 -1
  60. package/dist/ipc/supervised_proc.d.cts +1 -1
  61. package/dist/ipc/supervised_proc.d.ts +1 -1
  62. package/dist/ipc/supervised_proc.d.ts.map +1 -1
  63. package/dist/job.cjs +14 -2
  64. package/dist/job.cjs.map +1 -1
  65. package/dist/job.d.cts +8 -0
  66. package/dist/job.d.ts +8 -0
  67. package/dist/job.d.ts.map +1 -1
  68. package/dist/job.js +12 -1
  69. package/dist/job.js.map +1 -1
  70. package/dist/llm/chat_context.cjs +332 -82
  71. package/dist/llm/chat_context.cjs.map +1 -1
  72. package/dist/llm/chat_context.d.cts +152 -48
  73. package/dist/llm/chat_context.d.ts +152 -48
  74. package/dist/llm/chat_context.d.ts.map +1 -1
  75. package/dist/llm/chat_context.js +327 -81
  76. package/dist/llm/chat_context.js.map +1 -1
  77. package/dist/llm/chat_context.test.cjs +380 -0
  78. package/dist/llm/chat_context.test.cjs.map +1 -0
  79. package/dist/llm/chat_context.test.js +385 -0
  80. package/dist/llm/chat_context.test.js.map +1 -0
  81. package/dist/llm/index.cjs +37 -8
  82. package/dist/llm/index.cjs.map +1 -1
  83. package/dist/llm/index.d.cts +7 -3
  84. package/dist/llm/index.d.ts +7 -3
  85. package/dist/llm/index.d.ts.map +1 -1
  86. package/dist/llm/index.js +39 -9
  87. package/dist/llm/index.js.map +1 -1
  88. package/dist/llm/llm.cjs +98 -33
  89. package/dist/llm/llm.cjs.map +1 -1
  90. package/dist/llm/llm.d.cts +50 -24
  91. package/dist/llm/llm.d.ts +50 -24
  92. package/dist/llm/llm.d.ts.map +1 -1
  93. package/dist/llm/llm.js +99 -33
  94. package/dist/llm/llm.js.map +1 -1
  95. package/dist/llm/provider_format/google.cjs +128 -0
  96. package/dist/llm/provider_format/google.cjs.map +1 -0
  97. package/dist/llm/provider_format/google.d.cts +6 -0
  98. package/dist/llm/provider_format/google.d.ts +6 -0
  99. package/dist/llm/provider_format/google.d.ts.map +1 -0
  100. package/dist/llm/provider_format/google.js +104 -0
  101. package/dist/llm/provider_format/google.js.map +1 -0
  102. package/dist/llm/provider_format/google.test.cjs +676 -0
  103. package/dist/llm/provider_format/google.test.cjs.map +1 -0
  104. package/dist/llm/provider_format/google.test.js +675 -0
  105. package/dist/llm/provider_format/google.test.js.map +1 -0
  106. package/dist/llm/provider_format/index.cjs +40 -0
  107. package/dist/llm/provider_format/index.cjs.map +1 -0
  108. package/dist/llm/provider_format/index.d.cts +4 -0
  109. package/dist/llm/provider_format/index.d.ts +4 -0
  110. package/dist/llm/provider_format/index.d.ts.map +1 -0
  111. package/dist/llm/provider_format/index.js +16 -0
  112. package/dist/llm/provider_format/index.js.map +1 -0
  113. package/dist/llm/provider_format/openai.cjs +116 -0
  114. package/dist/llm/provider_format/openai.cjs.map +1 -0
  115. package/dist/llm/provider_format/openai.d.cts +3 -0
  116. package/dist/llm/provider_format/openai.d.ts +3 -0
  117. package/dist/llm/provider_format/openai.d.ts.map +1 -0
  118. package/dist/llm/provider_format/openai.js +92 -0
  119. package/dist/llm/provider_format/openai.js.map +1 -0
  120. package/dist/llm/provider_format/openai.test.cjs +490 -0
  121. package/dist/llm/provider_format/openai.test.cjs.map +1 -0
  122. package/dist/llm/provider_format/openai.test.js +489 -0
  123. package/dist/llm/provider_format/openai.test.js.map +1 -0
  124. package/dist/llm/provider_format/utils.cjs +146 -0
  125. package/dist/llm/provider_format/utils.cjs.map +1 -0
  126. package/dist/llm/provider_format/utils.d.cts +38 -0
  127. package/dist/llm/provider_format/utils.d.ts +38 -0
  128. package/dist/llm/provider_format/utils.d.ts.map +1 -0
  129. package/dist/llm/provider_format/utils.js +122 -0
  130. package/dist/llm/provider_format/utils.js.map +1 -0
  131. package/dist/llm/realtime.cjs +77 -0
  132. package/dist/llm/realtime.cjs.map +1 -0
  133. package/dist/llm/realtime.d.cts +98 -0
  134. package/dist/llm/realtime.d.ts +98 -0
  135. package/dist/llm/realtime.d.ts.map +1 -0
  136. package/dist/llm/realtime.js +52 -0
  137. package/dist/llm/realtime.js.map +1 -0
  138. package/dist/llm/remote_chat_context.cjs +112 -0
  139. package/dist/llm/remote_chat_context.cjs.map +1 -0
  140. package/dist/llm/remote_chat_context.d.cts +23 -0
  141. package/dist/llm/remote_chat_context.d.ts +23 -0
  142. package/dist/llm/remote_chat_context.d.ts.map +1 -0
  143. package/dist/llm/remote_chat_context.js +88 -0
  144. package/dist/llm/remote_chat_context.js.map +1 -0
  145. package/dist/llm/remote_chat_context.test.cjs +225 -0
  146. package/dist/llm/remote_chat_context.test.cjs.map +1 -0
  147. package/dist/llm/remote_chat_context.test.js +224 -0
  148. package/dist/llm/remote_chat_context.test.js.map +1 -0
  149. package/dist/llm/tool_context.cjs +111 -0
  150. package/dist/llm/tool_context.cjs.map +1 -0
  151. package/dist/llm/tool_context.d.cts +125 -0
  152. package/dist/llm/tool_context.d.ts +125 -0
  153. package/dist/llm/tool_context.d.ts.map +1 -0
  154. package/dist/llm/tool_context.js +80 -0
  155. package/dist/llm/tool_context.js.map +1 -0
  156. package/dist/llm/tool_context.test.cjs +162 -0
  157. package/dist/llm/tool_context.test.cjs.map +1 -0
  158. package/dist/llm/tool_context.test.js +161 -0
  159. package/dist/llm/tool_context.test.js.map +1 -0
  160. package/dist/llm/tool_context.type.test.cjs +92 -0
  161. package/dist/llm/tool_context.type.test.cjs.map +1 -0
  162. package/dist/llm/tool_context.type.test.js +91 -0
  163. package/dist/llm/tool_context.type.test.js.map +1 -0
  164. package/dist/llm/utils.cjs +260 -0
  165. package/dist/llm/utils.cjs.map +1 -0
  166. package/dist/llm/utils.d.cts +42 -0
  167. package/dist/llm/utils.d.ts +42 -0
  168. package/dist/llm/utils.d.ts.map +1 -0
  169. package/dist/llm/utils.js +223 -0
  170. package/dist/llm/utils.js.map +1 -0
  171. package/dist/llm/utils.test.cjs +513 -0
  172. package/dist/llm/utils.test.cjs.map +1 -0
  173. package/dist/llm/utils.test.js +490 -0
  174. package/dist/llm/utils.test.js.map +1 -0
  175. package/dist/metrics/base.cjs +0 -27
  176. package/dist/metrics/base.cjs.map +1 -1
  177. package/dist/metrics/base.d.cts +105 -63
  178. package/dist/metrics/base.d.ts +105 -63
  179. package/dist/metrics/base.d.ts.map +1 -1
  180. package/dist/metrics/base.js +0 -19
  181. package/dist/metrics/base.js.map +1 -1
  182. package/dist/metrics/index.cjs +0 -3
  183. package/dist/metrics/index.cjs.map +1 -1
  184. package/dist/metrics/index.d.cts +2 -3
  185. package/dist/metrics/index.d.ts +2 -3
  186. package/dist/metrics/index.d.ts.map +1 -1
  187. package/dist/metrics/index.js +0 -2
  188. package/dist/metrics/index.js.map +1 -1
  189. package/dist/metrics/usage_collector.cjs +17 -12
  190. package/dist/metrics/usage_collector.cjs.map +1 -1
  191. package/dist/metrics/usage_collector.d.cts +3 -2
  192. package/dist/metrics/usage_collector.d.ts +3 -2
  193. package/dist/metrics/usage_collector.d.ts.map +1 -1
  194. package/dist/metrics/usage_collector.js +17 -12
  195. package/dist/metrics/usage_collector.js.map +1 -1
  196. package/dist/metrics/utils.cjs +22 -59
  197. package/dist/metrics/utils.cjs.map +1 -1
  198. package/dist/metrics/utils.d.cts +1 -8
  199. package/dist/metrics/utils.d.ts +1 -8
  200. package/dist/metrics/utils.d.ts.map +1 -1
  201. package/dist/metrics/utils.js +22 -52
  202. package/dist/metrics/utils.js.map +1 -1
  203. package/dist/multimodal/index.cjs +0 -2
  204. package/dist/multimodal/index.cjs.map +1 -1
  205. package/dist/multimodal/index.d.cts +0 -1
  206. package/dist/multimodal/index.d.ts +0 -1
  207. package/dist/multimodal/index.d.ts.map +1 -1
  208. package/dist/multimodal/index.js +0 -1
  209. package/dist/multimodal/index.js.map +1 -1
  210. package/dist/plugin.cjs +24 -8
  211. package/dist/plugin.cjs.map +1 -1
  212. package/dist/plugin.d.cts +18 -4
  213. package/dist/plugin.d.ts +18 -4
  214. package/dist/plugin.d.ts.map +1 -1
  215. package/dist/plugin.js +22 -7
  216. package/dist/plugin.js.map +1 -1
  217. package/dist/stream/deferred_stream.cjs +98 -0
  218. package/dist/stream/deferred_stream.cjs.map +1 -0
  219. package/dist/stream/deferred_stream.d.cts +27 -0
  220. package/dist/stream/deferred_stream.d.ts +27 -0
  221. package/dist/stream/deferred_stream.d.ts.map +1 -0
  222. package/dist/stream/deferred_stream.js +73 -0
  223. package/dist/stream/deferred_stream.js.map +1 -0
  224. package/dist/stream/deferred_stream.test.cjs +527 -0
  225. package/dist/stream/deferred_stream.test.cjs.map +1 -0
  226. package/dist/stream/deferred_stream.test.js +526 -0
  227. package/dist/stream/deferred_stream.test.js.map +1 -0
  228. package/dist/stream/identity_transform.cjs +42 -0
  229. package/dist/stream/identity_transform.cjs.map +1 -0
  230. package/dist/stream/identity_transform.d.cts +6 -0
  231. package/dist/stream/identity_transform.d.ts +6 -0
  232. package/dist/stream/identity_transform.d.ts.map +1 -0
  233. package/dist/stream/identity_transform.js +18 -0
  234. package/dist/stream/identity_transform.js.map +1 -0
  235. package/dist/stream/identity_transform.test.cjs +125 -0
  236. package/dist/stream/identity_transform.test.cjs.map +1 -0
  237. package/dist/stream/identity_transform.test.js +124 -0
  238. package/dist/stream/identity_transform.test.js.map +1 -0
  239. package/dist/stream/index.cjs +38 -0
  240. package/dist/stream/index.cjs.map +1 -0
  241. package/dist/stream/index.d.cts +5 -0
  242. package/dist/stream/index.d.ts +5 -0
  243. package/dist/stream/index.d.ts.map +1 -0
  244. package/dist/stream/index.js +11 -0
  245. package/dist/stream/index.js.map +1 -0
  246. package/dist/stream/merge_readable_streams.cjs +59 -0
  247. package/dist/stream/merge_readable_streams.cjs.map +1 -0
  248. package/dist/stream/merge_readable_streams.d.cts +4 -0
  249. package/dist/stream/merge_readable_streams.d.ts +4 -0
  250. package/dist/stream/merge_readable_streams.d.ts.map +1 -0
  251. package/dist/stream/merge_readable_streams.js +35 -0
  252. package/dist/stream/merge_readable_streams.js.map +1 -0
  253. package/dist/stream/stream_channel.cjs +47 -0
  254. package/dist/stream/stream_channel.cjs.map +1 -0
  255. package/dist/stream/stream_channel.d.cts +9 -0
  256. package/dist/stream/stream_channel.d.ts +9 -0
  257. package/dist/stream/stream_channel.d.ts.map +1 -0
  258. package/dist/stream/stream_channel.js +23 -0
  259. package/dist/stream/stream_channel.js.map +1 -0
  260. package/dist/stream/stream_channel.test.cjs +97 -0
  261. package/dist/stream/stream_channel.test.cjs.map +1 -0
  262. package/dist/stream/stream_channel.test.js +96 -0
  263. package/dist/stream/stream_channel.test.js.map +1 -0
  264. package/dist/stt/stream_adapter.cjs +3 -4
  265. package/dist/stt/stream_adapter.cjs.map +1 -1
  266. package/dist/stt/stream_adapter.d.cts +1 -0
  267. package/dist/stt/stream_adapter.d.ts +1 -0
  268. package/dist/stt/stream_adapter.d.ts.map +1 -1
  269. package/dist/stt/stream_adapter.js +3 -4
  270. package/dist/stt/stream_adapter.js.map +1 -1
  271. package/dist/stt/stt.cjs +101 -10
  272. package/dist/stt/stt.cjs.map +1 -1
  273. package/dist/stt/stt.d.cts +26 -5
  274. package/dist/stt/stt.d.ts +26 -5
  275. package/dist/stt/stt.d.ts.map +1 -1
  276. package/dist/stt/stt.js +102 -11
  277. package/dist/stt/stt.js.map +1 -1
  278. package/dist/tokenize/basic/basic.cjs +10 -5
  279. package/dist/tokenize/basic/basic.cjs.map +1 -1
  280. package/dist/tokenize/basic/basic.d.cts +7 -1
  281. package/dist/tokenize/basic/basic.d.ts +7 -1
  282. package/dist/tokenize/basic/basic.d.ts.map +1 -1
  283. package/dist/tokenize/basic/basic.js +10 -5
  284. package/dist/tokenize/basic/basic.js.map +1 -1
  285. package/dist/tokenize/basic/sentence.cjs +14 -6
  286. package/dist/tokenize/basic/sentence.cjs.map +1 -1
  287. package/dist/tokenize/basic/sentence.d.cts +1 -1
  288. package/dist/tokenize/basic/sentence.d.ts +1 -1
  289. package/dist/tokenize/basic/sentence.d.ts.map +1 -1
  290. package/dist/tokenize/basic/sentence.js +14 -6
  291. package/dist/tokenize/basic/sentence.js.map +1 -1
  292. package/dist/tokenize/token_stream.cjs +5 -3
  293. package/dist/tokenize/token_stream.cjs.map +1 -1
  294. package/dist/tokenize/token_stream.d.cts +1 -0
  295. package/dist/tokenize/token_stream.d.ts +1 -0
  296. package/dist/tokenize/token_stream.d.ts.map +1 -1
  297. package/dist/tokenize/token_stream.js +6 -4
  298. package/dist/tokenize/token_stream.js.map +1 -1
  299. package/dist/transcription.cjs +1 -2
  300. package/dist/transcription.cjs.map +1 -1
  301. package/dist/transcription.d.ts.map +1 -1
  302. package/dist/transcription.js +2 -3
  303. package/dist/transcription.js.map +1 -1
  304. package/dist/tts/index.cjs +2 -4
  305. package/dist/tts/index.cjs.map +1 -1
  306. package/dist/tts/index.d.cts +1 -1
  307. package/dist/tts/index.d.ts +1 -1
  308. package/dist/tts/index.d.ts.map +1 -1
  309. package/dist/tts/index.js +1 -3
  310. package/dist/tts/index.js.map +1 -1
  311. package/dist/tts/stream_adapter.cjs +26 -13
  312. package/dist/tts/stream_adapter.cjs.map +1 -1
  313. package/dist/tts/stream_adapter.d.cts +1 -1
  314. package/dist/tts/stream_adapter.d.ts +1 -1
  315. package/dist/tts/stream_adapter.d.ts.map +1 -1
  316. package/dist/tts/stream_adapter.js +27 -14
  317. package/dist/tts/stream_adapter.js.map +1 -1
  318. package/dist/tts/tts.cjs +157 -25
  319. package/dist/tts/tts.cjs.map +1 -1
  320. package/dist/tts/tts.d.cts +29 -5
  321. package/dist/tts/tts.d.ts +29 -5
  322. package/dist/tts/tts.d.ts.map +1 -1
  323. package/dist/tts/tts.js +157 -24
  324. package/dist/tts/tts.js.map +1 -1
  325. package/dist/types.cjs +60 -0
  326. package/dist/types.cjs.map +1 -0
  327. package/dist/types.d.cts +13 -0
  328. package/dist/types.d.ts +13 -0
  329. package/dist/types.d.ts.map +1 -0
  330. package/dist/types.js +35 -0
  331. package/dist/types.js.map +1 -0
  332. package/dist/utils.cjs +281 -27
  333. package/dist/utils.cjs.map +1 -1
  334. package/dist/utils.d.cts +134 -9
  335. package/dist/utils.d.ts +134 -9
  336. package/dist/utils.d.ts.map +1 -1
  337. package/dist/utils.js +265 -26
  338. package/dist/utils.js.map +1 -1
  339. package/dist/utils.test.cjs +492 -0
  340. package/dist/utils.test.cjs.map +1 -0
  341. package/dist/utils.test.js +498 -0
  342. package/dist/utils.test.js.map +1 -0
  343. package/dist/vad.cjs +76 -20
  344. package/dist/vad.cjs.map +1 -1
  345. package/dist/vad.d.cts +25 -5
  346. package/dist/vad.d.ts +25 -5
  347. package/dist/vad.d.ts.map +1 -1
  348. package/dist/vad.js +76 -20
  349. package/dist/vad.js.map +1 -1
  350. package/dist/voice/agent.cjs +245 -0
  351. package/dist/voice/agent.cjs.map +1 -0
  352. package/dist/voice/agent.d.cts +78 -0
  353. package/dist/voice/agent.d.ts +78 -0
  354. package/dist/voice/agent.d.ts.map +1 -0
  355. package/dist/voice/agent.js +220 -0
  356. package/dist/voice/agent.js.map +1 -0
  357. package/dist/voice/agent.test.cjs +61 -0
  358. package/dist/voice/agent.test.cjs.map +1 -0
  359. package/dist/voice/agent.test.js +60 -0
  360. package/dist/voice/agent.test.js.map +1 -0
  361. package/dist/voice/agent_activity.cjs +1453 -0
  362. package/dist/voice/agent_activity.cjs.map +1 -0
  363. package/dist/voice/agent_activity.d.cts +94 -0
  364. package/dist/voice/agent_activity.d.ts +94 -0
  365. package/dist/voice/agent_activity.d.ts.map +1 -0
  366. package/dist/voice/agent_activity.js +1449 -0
  367. package/dist/voice/agent_activity.js.map +1 -0
  368. package/dist/voice/agent_session.cjs +312 -0
  369. package/dist/voice/agent_session.cjs.map +1 -0
  370. package/dist/voice/agent_session.d.cts +121 -0
  371. package/dist/voice/agent_session.d.ts +121 -0
  372. package/dist/voice/agent_session.d.ts.map +1 -0
  373. package/dist/voice/agent_session.js +295 -0
  374. package/dist/voice/agent_session.js.map +1 -0
  375. package/dist/voice/audio_recognition.cjs +375 -0
  376. package/dist/voice/audio_recognition.cjs.map +1 -0
  377. package/dist/voice/audio_recognition.d.cts +80 -0
  378. package/dist/voice/audio_recognition.d.ts +80 -0
  379. package/dist/voice/audio_recognition.d.ts.map +1 -0
  380. package/dist/voice/audio_recognition.js +351 -0
  381. package/dist/voice/audio_recognition.js.map +1 -0
  382. package/dist/voice/events.cjs +145 -0
  383. package/dist/voice/events.cjs.map +1 -0
  384. package/dist/voice/events.d.cts +124 -0
  385. package/dist/voice/events.d.ts +124 -0
  386. package/dist/voice/events.d.ts.map +1 -0
  387. package/dist/voice/events.js +110 -0
  388. package/dist/voice/events.js.map +1 -0
  389. package/dist/voice/generation.cjs +700 -0
  390. package/dist/voice/generation.cjs.map +1 -0
  391. package/dist/voice/generation.d.cts +115 -0
  392. package/dist/voice/generation.d.ts +115 -0
  393. package/dist/voice/generation.d.ts.map +1 -0
  394. package/dist/voice/generation.js +672 -0
  395. package/dist/voice/generation.js.map +1 -0
  396. package/dist/voice/index.cjs +40 -0
  397. package/dist/voice/index.cjs.map +1 -0
  398. package/dist/voice/index.d.cts +5 -0
  399. package/dist/voice/index.d.ts +5 -0
  400. package/dist/voice/index.d.ts.map +1 -0
  401. package/dist/voice/index.js +11 -0
  402. package/dist/voice/index.js.map +1 -0
  403. package/dist/voice/io.cjs +245 -0
  404. package/dist/voice/io.cjs.map +1 -0
  405. package/dist/voice/io.d.cts +101 -0
  406. package/dist/voice/io.d.ts +101 -0
  407. package/dist/voice/io.d.ts.map +1 -0
  408. package/dist/voice/io.js +217 -0
  409. package/dist/voice/io.js.map +1 -0
  410. package/dist/voice/room_io/_input.cjs +121 -0
  411. package/dist/voice/room_io/_input.cjs.map +1 -0
  412. package/dist/voice/room_io/_input.d.cts +24 -0
  413. package/dist/voice/room_io/_input.d.ts +24 -0
  414. package/dist/voice/room_io/_input.d.ts.map +1 -0
  415. package/dist/voice/room_io/_input.js +102 -0
  416. package/dist/voice/room_io/_input.js.map +1 -0
  417. package/dist/voice/room_io/_output.cjs +358 -0
  418. package/dist/voice/room_io/_output.cjs.map +1 -0
  419. package/dist/voice/room_io/_output.d.cts +75 -0
  420. package/dist/voice/room_io/_output.d.ts +75 -0
  421. package/dist/voice/room_io/_output.d.ts.map +1 -0
  422. package/dist/voice/room_io/_output.js +342 -0
  423. package/dist/voice/room_io/_output.js.map +1 -0
  424. package/dist/voice/room_io/index.cjs +25 -0
  425. package/dist/voice/room_io/index.cjs.map +1 -0
  426. package/dist/voice/room_io/index.d.cts +3 -0
  427. package/dist/voice/room_io/index.d.ts +3 -0
  428. package/dist/voice/room_io/index.d.ts.map +1 -0
  429. package/dist/voice/room_io/index.js +3 -0
  430. package/dist/voice/room_io/index.js.map +1 -0
  431. package/dist/voice/room_io/room_io.cjs +370 -0
  432. package/dist/voice/room_io/room_io.cjs.map +1 -0
  433. package/dist/voice/room_io/room_io.d.cts +73 -0
  434. package/dist/voice/room_io/room_io.d.ts +73 -0
  435. package/dist/voice/room_io/room_io.d.ts.map +1 -0
  436. package/dist/voice/room_io/room_io.js +361 -0
  437. package/dist/voice/room_io/room_io.js.map +1 -0
  438. package/dist/{pipeline/index.cjs → voice/run_context.cjs} +16 -11
  439. package/dist/voice/run_context.cjs.map +1 -0
  440. package/dist/voice/run_context.d.cts +12 -0
  441. package/dist/voice/run_context.d.ts +12 -0
  442. package/dist/voice/run_context.d.ts.map +1 -0
  443. package/dist/voice/run_context.js +14 -0
  444. package/dist/voice/run_context.js.map +1 -0
  445. package/dist/voice/speech_handle.cjs +105 -0
  446. package/dist/voice/speech_handle.cjs.map +1 -0
  447. package/dist/voice/speech_handle.d.cts +46 -0
  448. package/dist/voice/speech_handle.d.ts +46 -0
  449. package/dist/voice/speech_handle.d.ts.map +1 -0
  450. package/dist/voice/speech_handle.js +81 -0
  451. package/dist/voice/speech_handle.js.map +1 -0
  452. package/dist/voice/transcription/_utils.cjs +45 -0
  453. package/dist/voice/transcription/_utils.cjs.map +1 -0
  454. package/dist/voice/transcription/_utils.d.cts +3 -0
  455. package/dist/voice/transcription/_utils.d.ts +3 -0
  456. package/dist/voice/transcription/_utils.d.ts.map +1 -0
  457. package/dist/voice/transcription/_utils.js +21 -0
  458. package/dist/voice/transcription/_utils.js.map +1 -0
  459. package/dist/voice/transcription/index.cjs +23 -0
  460. package/dist/voice/transcription/index.cjs.map +1 -0
  461. package/dist/voice/transcription/index.d.cts +2 -0
  462. package/dist/voice/transcription/index.d.ts +2 -0
  463. package/dist/voice/transcription/index.d.ts.map +1 -0
  464. package/dist/voice/transcription/index.js +2 -0
  465. package/dist/voice/transcription/index.js.map +1 -0
  466. package/dist/voice/transcription/synchronizer.cjs +380 -0
  467. package/dist/voice/transcription/synchronizer.cjs.map +1 -0
  468. package/dist/voice/transcription/synchronizer.d.cts +86 -0
  469. package/dist/voice/transcription/synchronizer.d.ts +86 -0
  470. package/dist/voice/transcription/synchronizer.d.ts.map +1 -0
  471. package/dist/voice/transcription/synchronizer.js +355 -0
  472. package/dist/voice/transcription/synchronizer.js.map +1 -0
  473. package/dist/worker.cjs +22 -4
  474. package/dist/worker.cjs.map +1 -1
  475. package/dist/worker.d.cts +1 -1
  476. package/dist/worker.d.ts +1 -1
  477. package/dist/worker.d.ts.map +1 -1
  478. package/dist/worker.js +22 -4
  479. package/dist/worker.js.map +1 -1
  480. package/package.json +9 -2
  481. package/src/_exceptions.ts +137 -0
  482. package/src/audio.ts +12 -1
  483. package/src/cli.ts +37 -0
  484. package/src/constants.ts +2 -1
  485. package/src/http_server.ts +1 -0
  486. package/src/index.ts +13 -10
  487. package/src/inference_runner.ts +2 -3
  488. package/src/ipc/inference_proc_executor.ts +2 -2
  489. package/src/ipc/job_executor.ts +1 -1
  490. package/src/ipc/job_proc_executor.ts +1 -1
  491. package/src/ipc/job_proc_lazy_main.ts +1 -1
  492. package/src/job.ts +18 -0
  493. package/src/llm/__snapshots__/chat_context.test.ts.snap +527 -0
  494. package/src/llm/__snapshots__/tool_context.test.ts.snap +177 -0
  495. package/src/llm/__snapshots__/utils.test.ts.snap +65 -0
  496. package/src/llm/chat_context.test.ts +450 -0
  497. package/src/llm/chat_context.ts +501 -103
  498. package/src/llm/index.ts +53 -18
  499. package/src/llm/llm.ts +149 -50
  500. package/src/llm/provider_format/google.test.ts +772 -0
  501. package/src/llm/provider_format/google.ts +130 -0
  502. package/src/llm/provider_format/index.ts +23 -0
  503. package/src/llm/provider_format/openai.test.ts +581 -0
  504. package/src/llm/provider_format/openai.ts +118 -0
  505. package/src/llm/provider_format/utils.ts +183 -0
  506. package/src/llm/realtime.ts +151 -0
  507. package/src/llm/remote_chat_context.test.ts +290 -0
  508. package/src/llm/remote_chat_context.ts +114 -0
  509. package/src/llm/tool_context.test.ts +198 -0
  510. package/src/llm/tool_context.ts +259 -0
  511. package/src/llm/tool_context.type.test.ts +115 -0
  512. package/src/llm/utils.test.ts +670 -0
  513. package/src/llm/utils.ts +324 -0
  514. package/src/metrics/base.ts +110 -78
  515. package/src/metrics/index.ts +3 -9
  516. package/src/metrics/usage_collector.ts +19 -13
  517. package/src/metrics/utils.ts +24 -69
  518. package/src/multimodal/index.ts +0 -1
  519. package/src/plugin.ts +26 -8
  520. package/src/stream/deferred_stream.test.ts +755 -0
  521. package/src/stream/deferred_stream.ts +110 -0
  522. package/src/stream/identity_transform.test.ts +179 -0
  523. package/src/stream/identity_transform.ts +18 -0
  524. package/src/stream/index.ts +7 -0
  525. package/src/stream/merge_readable_streams.ts +40 -0
  526. package/src/stream/stream_channel.test.ts +129 -0
  527. package/src/stream/stream_channel.ts +32 -0
  528. package/src/stt/stream_adapter.ts +3 -5
  529. package/src/stt/stt.ts +135 -17
  530. package/src/tokenize/basic/basic.ts +13 -5
  531. package/src/tokenize/basic/sentence.ts +20 -6
  532. package/src/tokenize/token_stream.ts +7 -4
  533. package/src/transcription.ts +2 -3
  534. package/src/tts/index.ts +0 -1
  535. package/src/tts/stream_adapter.ts +42 -16
  536. package/src/tts/tts.ts +203 -21
  537. package/src/types.ts +42 -0
  538. package/src/utils.test.ts +658 -0
  539. package/src/utils.ts +375 -44
  540. package/src/vad.ts +90 -22
  541. package/src/voice/agent.test.ts +80 -0
  542. package/src/voice/agent.ts +332 -0
  543. package/src/voice/agent_activity.ts +1913 -0
  544. package/src/voice/agent_session.ts +460 -0
  545. package/src/voice/audio_recognition.ts +474 -0
  546. package/src/voice/events.ts +252 -0
  547. package/src/voice/generation.ts +881 -0
  548. package/src/voice/index.ts +7 -0
  549. package/src/voice/io.ts +304 -0
  550. package/src/voice/room_io/_input.ts +144 -0
  551. package/src/voice/room_io/_output.ts +436 -0
  552. package/src/voice/room_io/index.ts +5 -0
  553. package/src/voice/room_io/room_io.ts +495 -0
  554. package/src/voice/run_context.ts +20 -0
  555. package/src/voice/speech_handle.ts +104 -0
  556. package/src/voice/transcription/_utils.ts +25 -0
  557. package/src/voice/transcription/index.ts +4 -0
  558. package/src/voice/transcription/synchronizer.ts +478 -0
  559. package/src/worker.ts +22 -2
  560. package/dist/llm/function_context.cjs +0 -103
  561. package/dist/llm/function_context.cjs.map +0 -1
  562. package/dist/llm/function_context.d.cts +0 -47
  563. package/dist/llm/function_context.d.ts +0 -47
  564. package/dist/llm/function_context.d.ts.map +0 -1
  565. package/dist/llm/function_context.js +0 -78
  566. package/dist/llm/function_context.js.map +0 -1
  567. package/dist/llm/function_context.test.cjs +0 -218
  568. package/dist/llm/function_context.test.cjs.map +0 -1
  569. package/dist/llm/function_context.test.js +0 -217
  570. package/dist/llm/function_context.test.js.map +0 -1
  571. package/dist/multimodal/multimodal_agent.cjs +0 -486
  572. package/dist/multimodal/multimodal_agent.cjs.map +0 -1
  573. package/dist/multimodal/multimodal_agent.d.cts +0 -48
  574. package/dist/multimodal/multimodal_agent.d.ts +0 -48
  575. package/dist/multimodal/multimodal_agent.d.ts.map +0 -1
  576. package/dist/multimodal/multimodal_agent.js +0 -461
  577. package/dist/multimodal/multimodal_agent.js.map +0 -1
  578. package/dist/pipeline/agent_output.cjs +0 -197
  579. package/dist/pipeline/agent_output.cjs.map +0 -1
  580. package/dist/pipeline/agent_output.d.cts +0 -33
  581. package/dist/pipeline/agent_output.d.ts +0 -33
  582. package/dist/pipeline/agent_output.d.ts.map +0 -1
  583. package/dist/pipeline/agent_output.js +0 -172
  584. package/dist/pipeline/agent_output.js.map +0 -1
  585. package/dist/pipeline/agent_playout.cjs +0 -175
  586. package/dist/pipeline/agent_playout.cjs.map +0 -1
  587. package/dist/pipeline/agent_playout.d.cts +0 -40
  588. package/dist/pipeline/agent_playout.d.ts +0 -40
  589. package/dist/pipeline/agent_playout.d.ts.map +0 -1
  590. package/dist/pipeline/agent_playout.js +0 -139
  591. package/dist/pipeline/agent_playout.js.map +0 -1
  592. package/dist/pipeline/human_input.cjs +0 -171
  593. package/dist/pipeline/human_input.cjs.map +0 -1
  594. package/dist/pipeline/human_input.d.cts +0 -30
  595. package/dist/pipeline/human_input.d.ts +0 -30
  596. package/dist/pipeline/human_input.d.ts.map +0 -1
  597. package/dist/pipeline/human_input.js +0 -146
  598. package/dist/pipeline/human_input.js.map +0 -1
  599. package/dist/pipeline/index.cjs.map +0 -1
  600. package/dist/pipeline/index.d.cts +0 -2
  601. package/dist/pipeline/index.d.ts +0 -2
  602. package/dist/pipeline/index.d.ts.map +0 -1
  603. package/dist/pipeline/index.js +0 -11
  604. package/dist/pipeline/index.js.map +0 -1
  605. package/dist/pipeline/pipeline_agent.cjs +0 -859
  606. package/dist/pipeline/pipeline_agent.cjs.map +0 -1
  607. package/dist/pipeline/pipeline_agent.d.cts +0 -150
  608. package/dist/pipeline/pipeline_agent.d.ts +0 -150
  609. package/dist/pipeline/pipeline_agent.d.ts.map +0 -1
  610. package/dist/pipeline/pipeline_agent.js +0 -837
  611. package/dist/pipeline/pipeline_agent.js.map +0 -1
  612. package/dist/pipeline/speech_handle.cjs +0 -176
  613. package/dist/pipeline/speech_handle.cjs.map +0 -1
  614. package/dist/pipeline/speech_handle.d.cts +0 -37
  615. package/dist/pipeline/speech_handle.d.ts +0 -37
  616. package/dist/pipeline/speech_handle.d.ts.map +0 -1
  617. package/dist/pipeline/speech_handle.js +0 -152
  618. package/dist/pipeline/speech_handle.js.map +0 -1
  619. package/src/llm/function_context.test.ts +0 -248
  620. package/src/llm/function_context.ts +0 -142
  621. package/src/multimodal/multimodal_agent.ts +0 -592
  622. package/src/pipeline/agent_output.ts +0 -219
  623. package/src/pipeline/agent_playout.ts +0 -192
  624. package/src/pipeline/human_input.ts +0 -188
  625. package/src/pipeline/index.ts +0 -15
  626. package/src/pipeline/pipeline_agent.ts +0 -1197
  627. package/src/pipeline/speech_handle.ts +0 -201
@@ -0,0 +1,1453 @@
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 agent_activity_exports = {};
20
+ __export(agent_activity_exports, {
21
+ AgentActivity: () => AgentActivity
22
+ });
23
+ module.exports = __toCommonJS(agent_activity_exports);
24
+ var import_mutex = require("@livekit/mutex");
25
+ var import_heap_js = require("heap-js");
26
+ var import_node_async_hooks = require("node:async_hooks");
27
+ var import_web = require("node:stream/web");
28
+ var import_chat_context = require("../llm/chat_context.cjs");
29
+ var import_llm = require("../llm/index.cjs");
30
+ var import_log = require("../log.cjs");
31
+ var import_deferred_stream = require("../stream/deferred_stream.cjs");
32
+ var import_stt = require("../stt/stt.cjs");
33
+ var import_word = require("../tokenize/basic/word.cjs");
34
+ var import_tts = require("../tts/tts.cjs");
35
+ var import_utils = require("../utils.cjs");
36
+ var import_vad = require("../vad.cjs");
37
+ var import_agent = require("./agent.cjs");
38
+ var import_agent_session = require("./agent_session.cjs");
39
+ var import_audio_recognition = require("./audio_recognition.cjs");
40
+ var import_events = require("./events.cjs");
41
+ var import_generation = require("./generation.cjs");
42
+ var import_speech_handle = require("./speech_handle.cjs");
43
+ const speechHandleStorage = new import_node_async_hooks.AsyncLocalStorage();
44
+ class AgentActivity {
45
+ static REPLY_TASK_CANCEL_TIMEOUT = 5e3;
46
+ started = false;
47
+ audioRecognition;
48
+ realtimeSession;
49
+ turnDetectionMode;
50
+ logger = (0, import_log.log)();
51
+ _draining = false;
52
+ _currentSpeech;
53
+ speechQueue;
54
+ // [priority, timestamp, speechHandle]
55
+ q_updated;
56
+ speechTasks = /* @__PURE__ */ new Set();
57
+ lock = new import_mutex.Mutex();
58
+ audioStream = new import_deferred_stream.DeferredReadableStream();
59
+ // default to null as None, which maps to the default provider tool choice value
60
+ toolChoice = null;
61
+ agent;
62
+ agentSession;
63
+ /** @internal */
64
+ _mainTask;
65
+ _userTurnCompletedTask;
66
+ constructor(agent, agentSession) {
67
+ this.agent = agent;
68
+ this.agentSession = agentSession;
69
+ this.speechQueue = new import_heap_js.Heap(([p1, t1, _], [p2, t2, __]) => {
70
+ return p1 === p2 ? t1 - t2 : p2 - p1;
71
+ });
72
+ this.q_updated = new import_utils.Future();
73
+ this.turnDetectionMode = typeof this.turnDetection === "string" ? this.turnDetection : void 0;
74
+ if (this.turnDetectionMode === "vad" && this.vad === void 0) {
75
+ this.logger.warn(
76
+ 'turnDetection is set to "vad", but no VAD model is provided, ignoring the turnDdetection setting'
77
+ );
78
+ this.turnDetectionMode = void 0;
79
+ }
80
+ if (this.turnDetectionMode === "stt" && this.stt === void 0) {
81
+ this.logger.warn(
82
+ 'turnDetection is set to "stt", but no STT model is provided, ignoring the turnDetection setting'
83
+ );
84
+ this.turnDetectionMode = void 0;
85
+ }
86
+ if (this.llm instanceof import_llm.RealtimeModel) {
87
+ if (this.llm.capabilities.turnDetection && !this.allowInterruptions) {
88
+ this.logger.warn(
89
+ "the RealtimeModel uses a server-side turn detection, allowInterruptions cannot be false, disable turnDetection in the RealtimeModel and use VAD on the AgentSession instead"
90
+ );
91
+ }
92
+ if (this.turnDetectionMode === "realtime_llm" && !this.llm.capabilities.turnDetection) {
93
+ this.logger.warn(
94
+ 'turnDetection is set to "realtime_llm", but the LLM is not a RealtimeModel or the server-side turn detection is not supported/enabled, ignoring the turnDetection setting'
95
+ );
96
+ this.turnDetectionMode = void 0;
97
+ }
98
+ if (this.turnDetectionMode === "stt") {
99
+ this.logger.warn(
100
+ 'turnDetection is set to "stt", but the LLM is a RealtimeModel, ignoring the turnDetection setting'
101
+ );
102
+ this.turnDetectionMode = void 0;
103
+ }
104
+ if (this.turnDetectionMode && this.turnDetectionMode !== "realtime_llm" && this.llm.capabilities.turnDetection) {
105
+ this.logger.warn(
106
+ `turnDetection is set to "${this.turnDetectionMode}", but the LLM is a RealtimeModel and server-side turn detection enabled, ignoring the turnDetection setting`
107
+ );
108
+ this.turnDetectionMode = void 0;
109
+ }
110
+ if (!this.llm.capabilities.turnDetection && this.vad && this.turnDetectionMode === void 0) {
111
+ this.turnDetectionMode = "vad";
112
+ }
113
+ } else if (this.turnDetectionMode === "realtime_llm") {
114
+ this.logger.warn(
115
+ 'turnDetection is set to "realtime_llm", but the LLM is not a RealtimeModel'
116
+ );
117
+ this.turnDetectionMode = void 0;
118
+ }
119
+ if (!this.vad && this.stt && this.llm instanceof import_llm.LLM && this.allowInterruptions && this.turnDetectionMode === void 0) {
120
+ this.logger.warn(
121
+ "VAD is not set. Enabling VAD is recommended when using LLM and STT for more responsive interruption handling."
122
+ );
123
+ }
124
+ }
125
+ async start() {
126
+ const unlock = await this.lock.lock();
127
+ try {
128
+ this.agent._agentActivity = this;
129
+ if (this.llm instanceof import_llm.RealtimeModel) {
130
+ this.realtimeSession = this.llm.session();
131
+ this.realtimeSession.on("generation_created", (ev) => this.onGenerationCreated(ev));
132
+ this.realtimeSession.on("input_speech_started", (ev) => this.onInputSpeechStarted(ev));
133
+ this.realtimeSession.on("input_speech_stopped", (ev) => this.onInputSpeechStopped(ev));
134
+ this.realtimeSession.on(
135
+ "input_audio_transcription_completed",
136
+ (ev) => this.onInputAudioTranscriptionCompleted(ev)
137
+ );
138
+ this.realtimeSession.on("metrics_collected", (ev) => this.onMetricsCollected(ev));
139
+ this.realtimeSession.on("error", (ev) => this.onError(ev));
140
+ (0, import_generation.removeInstructions)(this.agent._chatCtx);
141
+ try {
142
+ await this.realtimeSession.updateInstructions(this.agent.instructions);
143
+ } catch (error) {
144
+ this.logger.error(error, "failed to update the instructions");
145
+ }
146
+ try {
147
+ await this.realtimeSession.updateChatCtx(this.agent.chatCtx);
148
+ } catch (error) {
149
+ this.logger.error(error, "failed to update the chat context");
150
+ }
151
+ try {
152
+ await this.realtimeSession.updateTools(this.tools);
153
+ } catch (error) {
154
+ this.logger.error(error, "failed to update the tools");
155
+ }
156
+ } else if (this.llm instanceof import_llm.LLM) {
157
+ try {
158
+ (0, import_generation.updateInstructions)({
159
+ chatCtx: this.agent._chatCtx,
160
+ instructions: this.agent.instructions,
161
+ addIfMissing: true
162
+ });
163
+ } catch (error) {
164
+ this.logger.error("failed to update the instructions", error);
165
+ }
166
+ }
167
+ if (this.llm instanceof import_llm.LLM) {
168
+ this.llm.on("metrics_collected", (ev) => this.onMetricsCollected(ev));
169
+ this.llm.on("error", (ev) => this.onError(ev));
170
+ }
171
+ if (this.stt instanceof import_stt.STT) {
172
+ this.stt.on("metrics_collected", (ev) => this.onMetricsCollected(ev));
173
+ this.stt.on("error", (ev) => this.onError(ev));
174
+ }
175
+ if (this.tts instanceof import_tts.TTS) {
176
+ this.tts.on("metrics_collected", (ev) => this.onMetricsCollected(ev));
177
+ this.tts.on("error", (ev) => this.onError(ev));
178
+ }
179
+ if (this.vad instanceof import_vad.VAD) {
180
+ this.vad.on("metrics_collected", (ev) => this.onMetricsCollected(ev));
181
+ }
182
+ this.audioRecognition = new import_audio_recognition.AudioRecognition({
183
+ recognitionHooks: this,
184
+ // Disable stt node if stt is not provided
185
+ stt: this.stt ? (...args) => this.agent.sttNode(...args) : void 0,
186
+ vad: this.vad,
187
+ turnDetector: typeof this.turnDetection === "string" ? void 0 : this.turnDetection,
188
+ turnDetectionMode: this.turnDetectionMode,
189
+ minEndpointingDelay: this.agentSession.options.minEndpointingDelay,
190
+ maxEndpointingDelay: this.agentSession.options.maxEndpointingDelay
191
+ });
192
+ this.audioRecognition.start();
193
+ this.started = true;
194
+ this._mainTask = import_utils.Task.from(({ signal }) => this.mainTask(signal));
195
+ this.createSpeechTask({
196
+ promise: this.agent.onEnter(),
197
+ name: "AgentActivity_onEnter"
198
+ });
199
+ } finally {
200
+ unlock();
201
+ }
202
+ }
203
+ get currentSpeech() {
204
+ return this._currentSpeech;
205
+ }
206
+ get vad() {
207
+ return this.agent.vad || this.agentSession.vad;
208
+ }
209
+ get stt() {
210
+ return this.agent.stt || this.agentSession.stt;
211
+ }
212
+ get llm() {
213
+ return this.agent.llm || this.agentSession.llm;
214
+ }
215
+ get tts() {
216
+ return this.agent.tts || this.agentSession.tts;
217
+ }
218
+ get tools() {
219
+ return this.agent.toolCtx;
220
+ }
221
+ get draining() {
222
+ return this._draining;
223
+ }
224
+ get realtimeLLMSession() {
225
+ return this.realtimeSession;
226
+ }
227
+ get allowInterruptions() {
228
+ return this.agentSession.options.allowInterruptions;
229
+ }
230
+ get turnDetection() {
231
+ return this.agentSession.turnDetection;
232
+ }
233
+ get toolCtx() {
234
+ return this.agent.toolCtx;
235
+ }
236
+ async updateChatCtx(chatCtx) {
237
+ chatCtx = chatCtx.copy({ toolCtx: this.toolCtx });
238
+ this.agent._chatCtx = chatCtx;
239
+ if (this.realtimeSession) {
240
+ (0, import_generation.removeInstructions)(chatCtx);
241
+ this.realtimeSession.updateChatCtx(chatCtx);
242
+ } else {
243
+ (0, import_generation.updateInstructions)({
244
+ chatCtx,
245
+ instructions: this.agent.instructions,
246
+ addIfMissing: true
247
+ });
248
+ }
249
+ }
250
+ updateOptions({ toolChoice }) {
251
+ if (toolChoice !== void 0) {
252
+ this.toolChoice = toolChoice;
253
+ }
254
+ if (this.realtimeSession) {
255
+ this.realtimeSession.updateOptions({ toolChoice: this.toolChoice });
256
+ }
257
+ }
258
+ attachAudioInput(audioStream) {
259
+ if (this.audioStream.isSourceSet) {
260
+ this.logger.debug("detaching existing audio input in agent activity");
261
+ this.audioStream.detachSource();
262
+ }
263
+ this.audioStream.setSource(audioStream);
264
+ const [realtimeAudioStream, recognitionAudioStream] = this.audioStream.stream.tee();
265
+ if (this.realtimeSession) {
266
+ this.realtimeSession.setInputAudioStream(realtimeAudioStream);
267
+ }
268
+ if (this.audioRecognition) {
269
+ this.audioRecognition.setInputAudioStream(recognitionAudioStream);
270
+ }
271
+ }
272
+ detachAudioInput() {
273
+ this.audioStream.detachSource();
274
+ }
275
+ commitUserTurn() {
276
+ if (!this.audioRecognition) {
277
+ throw new Error("AudioRecognition is not initialized");
278
+ }
279
+ const audioDetached = false;
280
+ this.audioRecognition.commitUserTurn(audioDetached);
281
+ }
282
+ clearUserTurn() {
283
+ var _a, _b;
284
+ (_a = this.audioRecognition) == null ? void 0 : _a.clearUserTurn();
285
+ (_b = this.realtimeSession) == null ? void 0 : _b.clearAudio();
286
+ }
287
+ say(text, options) {
288
+ const {
289
+ audio,
290
+ allowInterruptions: defaultAllowInterruptions,
291
+ addToChatCtx = true
292
+ } = options ?? {};
293
+ let allowInterruptions = defaultAllowInterruptions;
294
+ if (!audio && !this.tts && this.agentSession.output.audio && this.agentSession.output.audioEnabled) {
295
+ throw new Error("trying to generate speech from text without a TTS model");
296
+ }
297
+ if (this.llm instanceof import_llm.RealtimeModel && this.llm.capabilities.turnDetection && allowInterruptions === false) {
298
+ this.logger.warn(
299
+ "the RealtimeModel uses a server-side turn detection, allowInterruptions cannot be false when using VoiceAgent.say(), disable turnDetection in the RealtimeModel and use VAD on the AgentTask/VoiceAgent instead"
300
+ );
301
+ allowInterruptions = true;
302
+ }
303
+ const handle = import_speech_handle.SpeechHandle.create({
304
+ allowInterruptions: allowInterruptions ?? this.allowInterruptions
305
+ });
306
+ this.agentSession.emit(
307
+ import_events.AgentSessionEventTypes.SpeechCreated,
308
+ (0, import_events.createSpeechCreatedEvent)({
309
+ userInitiated: true,
310
+ source: "say",
311
+ speechHandle: handle
312
+ })
313
+ );
314
+ const task = this.createSpeechTask({
315
+ promise: this.ttsTask(handle, text, addToChatCtx, {}, audio),
316
+ ownedSpeechHandle: handle,
317
+ name: "AgentActivity.say_tts"
318
+ });
319
+ task.finally(() => this.onPipelineReplyDone());
320
+ this.scheduleSpeech(handle, import_speech_handle.SpeechHandle.SPEECH_PRIORITY_NORMAL);
321
+ return handle;
322
+ }
323
+ // -- Metrics and errors --
324
+ onMetricsCollected = (ev) => {
325
+ const speechHandle = speechHandleStorage.getStore();
326
+ if (speechHandle && (ev.type === "llm_metrics" || ev.type === "tts_metrics")) {
327
+ ev.speechId = speechHandle.id;
328
+ }
329
+ this.agentSession.emit(
330
+ import_events.AgentSessionEventTypes.MetricsCollected,
331
+ (0, import_events.createMetricsCollectedEvent)({ metrics: ev })
332
+ );
333
+ };
334
+ onError(ev) {
335
+ if (ev.type === "realtime_model_error") {
336
+ const errorEvent = (0, import_events.createErrorEvent)(ev.error, this.llm);
337
+ this.agentSession.emit(import_events.AgentSessionEventTypes.Error, errorEvent);
338
+ } else if (ev.type === "stt_error") {
339
+ const errorEvent = (0, import_events.createErrorEvent)(ev.error, this.stt);
340
+ this.agentSession.emit(import_events.AgentSessionEventTypes.Error, errorEvent);
341
+ } else if (ev.type === "tts_error") {
342
+ const errorEvent = (0, import_events.createErrorEvent)(ev.error, this.tts);
343
+ this.agentSession.emit(import_events.AgentSessionEventTypes.Error, errorEvent);
344
+ } else if (ev.type === "llm_error") {
345
+ const errorEvent = (0, import_events.createErrorEvent)(ev.error, this.llm);
346
+ this.agentSession.emit(import_events.AgentSessionEventTypes.Error, errorEvent);
347
+ }
348
+ this.agentSession._onError(ev);
349
+ }
350
+ // -- Realtime Session events --
351
+ onInputSpeechStarted(_ev) {
352
+ this.logger.info("onInputSpeechStarted");
353
+ if (!this.vad) {
354
+ this.agentSession._updateUserState("speaking");
355
+ }
356
+ try {
357
+ this.interrupt();
358
+ } catch (error) {
359
+ this.logger.error(
360
+ "RealtimeAPI input_speech_started, but current speech is not interruptable, this should never happen!",
361
+ error
362
+ );
363
+ }
364
+ }
365
+ onInputSpeechStopped(ev) {
366
+ this.logger.info(ev, "onInputSpeechStopped");
367
+ if (!this.vad) {
368
+ this.agentSession._updateUserState("listening");
369
+ }
370
+ if (ev.userTranscriptionEnabled) {
371
+ this.agentSession.emit(
372
+ import_events.AgentSessionEventTypes.UserInputTranscribed,
373
+ (0, import_events.createUserInputTranscribedEvent)({
374
+ isFinal: false,
375
+ transcript: ""
376
+ })
377
+ );
378
+ }
379
+ }
380
+ onInputAudioTranscriptionCompleted(ev) {
381
+ this.agentSession.emit(
382
+ import_events.AgentSessionEventTypes.UserInputTranscribed,
383
+ (0, import_events.createUserInputTranscribedEvent)({
384
+ transcript: ev.transcript,
385
+ isFinal: ev.isFinal
386
+ })
387
+ );
388
+ if (ev.isFinal) {
389
+ const message = import_chat_context.ChatMessage.create({
390
+ role: "user",
391
+ content: ev.transcript,
392
+ id: ev.itemId
393
+ });
394
+ this.agent._chatCtx.items.push(message);
395
+ this.agentSession._conversationItemAdded(message);
396
+ }
397
+ }
398
+ onGenerationCreated(ev) {
399
+ if (ev.userInitiated) {
400
+ return;
401
+ }
402
+ if (this.draining) {
403
+ this.logger.warn("skipping new realtime generation, the agent is draining");
404
+ return;
405
+ }
406
+ const handle = import_speech_handle.SpeechHandle.create({
407
+ allowInterruptions: this.allowInterruptions
408
+ });
409
+ this.agentSession.emit(
410
+ import_events.AgentSessionEventTypes.SpeechCreated,
411
+ (0, import_events.createSpeechCreatedEvent)({
412
+ userInitiated: false,
413
+ source: "generate_reply",
414
+ speechHandle: handle
415
+ })
416
+ );
417
+ this.logger.info({ speech_id: handle.id }, "Creating speech handle");
418
+ this.createSpeechTask({
419
+ promise: this.realtimeGenerationTask(handle, ev, {}),
420
+ ownedSpeechHandle: handle,
421
+ name: "AgentActivity.realtimeGeneration"
422
+ });
423
+ this.scheduleSpeech(handle, import_speech_handle.SpeechHandle.SPEECH_PRIORITY_NORMAL);
424
+ }
425
+ // recognition hooks
426
+ onStartOfSpeech(_ev) {
427
+ this.agentSession._updateUserState("speaking");
428
+ }
429
+ onEndOfSpeech(_ev) {
430
+ this.agentSession._updateUserState("listening");
431
+ }
432
+ onVADInferenceDone(ev) {
433
+ var _a, _b;
434
+ if (this.turnDetection === "manual" || this.turnDetection === "realtime_llm") {
435
+ return;
436
+ }
437
+ if (this.llm instanceof import_llm.RealtimeModel && this.llm.capabilities.turnDetection) {
438
+ return;
439
+ }
440
+ if (ev.speechDuration < this.agentSession.options.minInterruptionDuration) {
441
+ return;
442
+ }
443
+ if (this.stt && this.agentSession.options.minInterruptionWords > 0 && this.audioRecognition) {
444
+ const text = this.audioRecognition.currentTranscript;
445
+ if (text && (0, import_word.splitWords)(text, true).length < this.agentSession.options.minInterruptionWords) {
446
+ return;
447
+ }
448
+ }
449
+ (_a = this.realtimeSession) == null ? void 0 : _a.startUserActivity();
450
+ if (this._currentSpeech && !this._currentSpeech.interrupted && this._currentSpeech.allowInterruptions) {
451
+ this.logger.info({ "speech id": this._currentSpeech.id }, "speech interrupted by VAD");
452
+ (_b = this.realtimeSession) == null ? void 0 : _b.interrupt();
453
+ this._currentSpeech.interrupt();
454
+ }
455
+ }
456
+ onInterimTranscript(ev) {
457
+ if (this.llm instanceof import_llm.RealtimeModel && this.llm.capabilities.userTranscription) {
458
+ return;
459
+ }
460
+ this.agentSession.emit(
461
+ import_events.AgentSessionEventTypes.UserInputTranscribed,
462
+ (0, import_events.createUserInputTranscribedEvent)({
463
+ transcript: ev.alternatives[0].text,
464
+ isFinal: false
465
+ // TODO(AJS-106): add multi participant support
466
+ })
467
+ );
468
+ }
469
+ onFinalTranscript(ev) {
470
+ if (this.llm instanceof import_llm.RealtimeModel && this.llm.capabilities.userTranscription) {
471
+ return;
472
+ }
473
+ this.agentSession.emit(
474
+ import_events.AgentSessionEventTypes.UserInputTranscribed,
475
+ (0, import_events.createUserInputTranscribedEvent)({
476
+ transcript: ev.alternatives[0].text,
477
+ isFinal: true
478
+ // TODO(AJS-106): add multi participant support
479
+ })
480
+ );
481
+ }
482
+ createSpeechTask(options) {
483
+ const { promise, ownedSpeechHandle } = options;
484
+ this.speechTasks.add(promise);
485
+ promise.finally(() => {
486
+ this.speechTasks.delete(promise);
487
+ if (ownedSpeechHandle) {
488
+ ownedSpeechHandle._markPlayoutDone();
489
+ }
490
+ this.wakeupMainTask();
491
+ });
492
+ return promise;
493
+ }
494
+ async onEndOfTurn(info) {
495
+ if (this.draining) {
496
+ this.logger.warn({ user_input: info.newTranscript }, "skipping user input, task is draining");
497
+ return true;
498
+ }
499
+ if (this.stt && this.turnDetection !== "manual" && this._currentSpeech && this._currentSpeech.allowInterruptions && !this._currentSpeech.interrupted && this.agentSession.options.minInterruptionWords > 0 && info.newTranscript.split(" ").length < this.agentSession.options.minInterruptionWords) {
500
+ this.logger.info("skipping user input, new_transcript is too short");
501
+ return false;
502
+ }
503
+ const oldTask = this._userTurnCompletedTask;
504
+ this._userTurnCompletedTask = this.createSpeechTask({
505
+ promise: this.userTurnCompleted(info, oldTask),
506
+ name: "AgentActivity.userTurnCompleted"
507
+ });
508
+ return true;
509
+ }
510
+ retrieveChatCtx() {
511
+ return this.agentSession.chatCtx;
512
+ }
513
+ async mainTask(signal) {
514
+ const abortFuture = new import_utils.Future();
515
+ const abortHandler = () => {
516
+ abortFuture.resolve();
517
+ signal.removeEventListener("abort", abortHandler);
518
+ };
519
+ signal.addEventListener("abort", abortHandler);
520
+ while (true) {
521
+ await Promise.race([this.q_updated.await, abortFuture.await]);
522
+ if (signal.aborted) break;
523
+ while (this.speechQueue.size() > 0) {
524
+ if (signal.aborted) break;
525
+ const heapItem = this.speechQueue.pop();
526
+ if (!heapItem) {
527
+ throw new Error("Speech queue is empty");
528
+ }
529
+ const speechHandle = heapItem[2];
530
+ this._currentSpeech = speechHandle;
531
+ speechHandle._authorizePlayout();
532
+ await speechHandle.waitForPlayout();
533
+ this._currentSpeech = void 0;
534
+ }
535
+ if (this.draining && this.speechTasks.size === 0) {
536
+ this.logger.info("mainTask: draining and no more speech tasks");
537
+ break;
538
+ }
539
+ this.q_updated = new import_utils.Future();
540
+ }
541
+ this.logger.info("AgentActivity mainTask: exiting");
542
+ }
543
+ wakeupMainTask() {
544
+ this.q_updated.resolve();
545
+ }
546
+ generateReply(options) {
547
+ var _a;
548
+ const {
549
+ userMessage,
550
+ chatCtx,
551
+ instructions: defaultInstructions,
552
+ toolChoice: defaultToolChoice,
553
+ allowInterruptions: defaultAllowInterruptions
554
+ } = options;
555
+ let instructions = defaultInstructions;
556
+ let toolChoice = defaultToolChoice;
557
+ let allowInterruptions = defaultAllowInterruptions;
558
+ if (this.llm instanceof import_llm.RealtimeModel && this.llm.capabilities.turnDetection && allowInterruptions === false) {
559
+ this.logger.warn(
560
+ "the RealtimeModel uses a server-side turn detection, allowInterruptions cannot be false when using VoiceAgent.generateReply(), disable turnDetection in the RealtimeModel and use VAD on the AgentTask/VoiceAgent instead"
561
+ );
562
+ allowInterruptions = true;
563
+ }
564
+ if (this.llm === void 0) {
565
+ throw new Error("trying to generate reply without an LLM model");
566
+ }
567
+ const functionCall = (_a = import_agent.asyncLocalStorage.getStore()) == null ? void 0 : _a.functionCall;
568
+ if (toolChoice === void 0 && functionCall !== void 0) {
569
+ toolChoice = "none";
570
+ }
571
+ const handle = import_speech_handle.SpeechHandle.create({
572
+ allowInterruptions: allowInterruptions ?? this.allowInterruptions
573
+ });
574
+ this.agentSession.emit(
575
+ import_events.AgentSessionEventTypes.SpeechCreated,
576
+ (0, import_events.createSpeechCreatedEvent)({
577
+ userInitiated: true,
578
+ source: "generate_reply",
579
+ speechHandle: handle
580
+ })
581
+ );
582
+ this.logger.info({ speech_id: handle.id }, "Creating speech handle");
583
+ if (this.llm instanceof import_llm.RealtimeModel) {
584
+ this.createSpeechTask({
585
+ promise: this.realtimeReplyTask({
586
+ speechHandle: handle,
587
+ // TODO(brian): support llm.ChatMessage for the realtime model
588
+ userInput: userMessage == null ? void 0 : userMessage.textContent,
589
+ instructions,
590
+ modelSettings: {
591
+ // isGiven(toolChoice) = toolChoice !== undefined
592
+ toolChoice: toOaiToolChoice(toolChoice !== void 0 ? toolChoice : this.toolChoice)
593
+ }
594
+ }),
595
+ ownedSpeechHandle: handle,
596
+ name: "AgentActivity.realtimeReply"
597
+ });
598
+ } else if (this.llm instanceof import_llm.LLM) {
599
+ if (instructions) {
600
+ instructions = `${this.agent.instructions}
601
+ ${instructions}`;
602
+ }
603
+ const task = this.createSpeechTask({
604
+ promise: this.pipelineReplyTask(
605
+ handle,
606
+ chatCtx ?? this.agent.chatCtx,
607
+ this.agent.toolCtx,
608
+ { toolChoice: toOaiToolChoice(toolChoice !== void 0 ? toolChoice : this.toolChoice) },
609
+ instructions ? `${this.agent.instructions}
610
+ ${instructions}` : instructions,
611
+ userMessage
612
+ ),
613
+ ownedSpeechHandle: handle,
614
+ name: "AgentActivity.pipelineReply"
615
+ });
616
+ task.finally(() => this.onPipelineReplyDone());
617
+ }
618
+ this.scheduleSpeech(handle, import_speech_handle.SpeechHandle.SPEECH_PRIORITY_NORMAL);
619
+ return handle;
620
+ }
621
+ interrupt() {
622
+ var _a;
623
+ const future = new import_utils.Future();
624
+ const currentSpeech = this._currentSpeech;
625
+ currentSpeech == null ? void 0 : currentSpeech.interrupt();
626
+ for (const [_, __, speech] of this.speechQueue) {
627
+ speech.interrupt();
628
+ }
629
+ (_a = this.realtimeSession) == null ? void 0 : _a.interrupt();
630
+ if (currentSpeech === void 0) {
631
+ future.resolve();
632
+ } else {
633
+ currentSpeech.then(() => {
634
+ if (future.done) return;
635
+ future.resolve();
636
+ });
637
+ }
638
+ return future;
639
+ }
640
+ onPipelineReplyDone() {
641
+ if (!this.speechQueue.peek() && (!this._currentSpeech || this._currentSpeech.done)) {
642
+ this.agentSession._updateAgentState("listening");
643
+ }
644
+ }
645
+ async userTurnCompleted(info, oldTask) {
646
+ var _a, _b;
647
+ if (oldTask) {
648
+ await oldTask;
649
+ }
650
+ if (this.llm instanceof import_llm.RealtimeModel) {
651
+ if (this.llm.capabilities.turnDetection) {
652
+ return;
653
+ }
654
+ (_a = this.realtimeSession) == null ? void 0 : _a.commitAudio();
655
+ }
656
+ if (this._currentSpeech) {
657
+ if (!this._currentSpeech.allowInterruptions) {
658
+ this.logger.warn(
659
+ { user_input: info.newTranscript },
660
+ "skipping user input, current speech generation cannot be interrupted"
661
+ );
662
+ return;
663
+ }
664
+ this.logger.info(
665
+ { "speech id": this._currentSpeech.id },
666
+ "speech interrupted, new user turn detected"
667
+ );
668
+ this._currentSpeech.interrupt();
669
+ (_b = this.realtimeSession) == null ? void 0 : _b.interrupt();
670
+ }
671
+ let userMessage = import_chat_context.ChatMessage.create({
672
+ role: "user",
673
+ content: info.newTranscript
674
+ });
675
+ const chatCtx = this.agent.chatCtx.copy();
676
+ const startTime = Date.now();
677
+ try {
678
+ await this.agent.onUserTurnCompleted(chatCtx, userMessage);
679
+ } catch (e) {
680
+ if (e instanceof import_agent.StopResponse) {
681
+ return;
682
+ }
683
+ this.logger.error({ error: e }, "error occurred during onUserTurnCompleted");
684
+ }
685
+ const callbackDuration = Date.now() - startTime;
686
+ if (this.llm instanceof import_llm.RealtimeModel) {
687
+ userMessage = void 0;
688
+ } else if (this.llm === void 0) {
689
+ return;
690
+ }
691
+ const speechHandle = this.generateReply({ userMessage, chatCtx });
692
+ const eouMetrics = {
693
+ type: "eou_metrics",
694
+ timestamp: Date.now(),
695
+ endOfUtteranceDelay: info.endOfUtteranceDelay,
696
+ transcriptionDelay: info.transcriptionDelay,
697
+ onUserTurnCompletedDelay: callbackDuration,
698
+ speechId: speechHandle.id
699
+ };
700
+ this.agentSession.emit(
701
+ import_events.AgentSessionEventTypes.MetricsCollected,
702
+ (0, import_events.createMetricsCollectedEvent)({ metrics: eouMetrics })
703
+ );
704
+ }
705
+ async ttsTask(speechHandle, text, addToChatCtx, modelSettings, audio) {
706
+ speechHandleStorage.enterWith(speechHandle);
707
+ const transcriptionOutput = this.agentSession.output.transcriptionEnabled ? this.agentSession.output.transcription : null;
708
+ const audioOutput = this.agentSession.output.audioEnabled ? this.agentSession.output.audio : null;
709
+ const replyAbortController = new AbortController();
710
+ await speechHandle.waitIfNotInterrupted([speechHandle._waitForAuthorization()]);
711
+ if (speechHandle.interrupted) {
712
+ return;
713
+ }
714
+ let baseStream;
715
+ if (text instanceof import_web.ReadableStream) {
716
+ baseStream = text;
717
+ } else {
718
+ baseStream = new import_web.ReadableStream({
719
+ start(controller) {
720
+ controller.enqueue(text);
721
+ controller.close();
722
+ }
723
+ });
724
+ }
725
+ const [textSource, audioSource] = baseStream.tee();
726
+ const tasks = [];
727
+ const trNode = await this.agent.transcriptionNode(textSource, {});
728
+ let textOut = null;
729
+ if (trNode) {
730
+ const [textForwardTask, _textOut] = (0, import_generation.performTextForwarding)(
731
+ trNode,
732
+ replyAbortController,
733
+ transcriptionOutput
734
+ );
735
+ textOut = _textOut;
736
+ tasks.push(textForwardTask);
737
+ }
738
+ const onFirstFrame = () => {
739
+ this.agentSession._updateAgentState("speaking");
740
+ };
741
+ if (!audioOutput) {
742
+ if (textOut) {
743
+ textOut.firstTextFut.await.finally(onFirstFrame);
744
+ }
745
+ } else {
746
+ let audioOut = null;
747
+ if (!audio) {
748
+ const [ttsTask, ttsStream] = (0, import_generation.performTTSInference)(
749
+ (...args) => this.agent.ttsNode(...args),
750
+ audioSource,
751
+ modelSettings,
752
+ replyAbortController
753
+ );
754
+ tasks.push(ttsTask);
755
+ const [forwardTask, _audioOut] = (0, import_generation.performAudioForwarding)(
756
+ ttsStream,
757
+ audioOutput,
758
+ replyAbortController
759
+ );
760
+ tasks.push(forwardTask);
761
+ audioOut = _audioOut;
762
+ } else {
763
+ const [forwardTask, _audioOut] = (0, import_generation.performAudioForwarding)(
764
+ audio,
765
+ audioOutput,
766
+ replyAbortController
767
+ );
768
+ tasks.push(forwardTask);
769
+ audioOut = _audioOut;
770
+ }
771
+ audioOut.firstFrameFut.await.finally(onFirstFrame);
772
+ }
773
+ await speechHandle.waitIfNotInterrupted(tasks.map((task) => task.result));
774
+ if (audioOutput) {
775
+ await speechHandle.waitIfNotInterrupted([audioOutput.waitForPlayout()]);
776
+ }
777
+ if (speechHandle.interrupted) {
778
+ replyAbortController.abort();
779
+ await (0, import_utils.cancelAndWait)(tasks, AgentActivity.REPLY_TASK_CANCEL_TIMEOUT);
780
+ if (audioOutput) {
781
+ audioOutput.clearBuffer();
782
+ await audioOutput.waitForPlayout();
783
+ }
784
+ }
785
+ if (addToChatCtx) {
786
+ const message = import_chat_context.ChatMessage.create({
787
+ role: "assistant",
788
+ content: (textOut == null ? void 0 : textOut.text) || "",
789
+ interrupted: speechHandle.interrupted
790
+ });
791
+ this.agent._chatCtx.insert(message);
792
+ this.agentSession._conversationItemAdded(message);
793
+ }
794
+ if (this.agentSession.agentState === "speaking") {
795
+ this.agentSession._updateAgentState("listening");
796
+ }
797
+ }
798
+ async pipelineReplyTask(speechHandle, chatCtx, toolCtx, modelSettings, instructions, newMessage, toolsMessages) {
799
+ var _a, _b, _c;
800
+ speechHandleStorage.enterWith(speechHandle);
801
+ const replyAbortController = new AbortController();
802
+ const audioOutput = this.agentSession.output.audioEnabled ? this.agentSession.output.audio : null;
803
+ const transcriptionOutput = this.agentSession.output.transcriptionEnabled ? this.agentSession.output.transcription : null;
804
+ chatCtx = chatCtx.copy();
805
+ if (newMessage) {
806
+ chatCtx.insert(newMessage);
807
+ this.agent._chatCtx.insert(newMessage);
808
+ this.agentSession._conversationItemAdded(newMessage);
809
+ }
810
+ if (instructions) {
811
+ try {
812
+ (0, import_generation.updateInstructions)({
813
+ chatCtx,
814
+ instructions,
815
+ addIfMissing: true
816
+ });
817
+ } catch (e) {
818
+ this.logger.error({ error: e }, "error occurred during updateInstructions");
819
+ }
820
+ }
821
+ this.agentSession._updateAgentState("thinking");
822
+ const tasks = [];
823
+ const [llmTask, llmGenData] = (0, import_generation.performLLMInference)(
824
+ // preserve `this` context in llmNode
825
+ (...args) => this.agent.llmNode(...args),
826
+ chatCtx,
827
+ toolCtx,
828
+ modelSettings,
829
+ replyAbortController
830
+ );
831
+ tasks.push(llmTask);
832
+ const [ttsTextInput, llmOutput] = llmGenData.textStream.tee();
833
+ let ttsTask = null;
834
+ let ttsStream = null;
835
+ if (audioOutput) {
836
+ [ttsTask, ttsStream] = (0, import_generation.performTTSInference)(
837
+ (...args) => this.agent.ttsNode(...args),
838
+ ttsTextInput,
839
+ modelSettings,
840
+ replyAbortController
841
+ );
842
+ tasks.push(ttsTask);
843
+ }
844
+ await speechHandle.waitIfNotInterrupted([speechHandle._waitForAuthorization()]);
845
+ if (speechHandle.interrupted) {
846
+ replyAbortController.abort();
847
+ await (0, import_utils.cancelAndWait)(tasks, AgentActivity.REPLY_TASK_CANCEL_TIMEOUT);
848
+ return;
849
+ }
850
+ const replyStartedAt = Date.now();
851
+ const trNodeResult = await this.agent.transcriptionNode(llmOutput, modelSettings);
852
+ let textOut = null;
853
+ if (trNodeResult) {
854
+ const [textForwardTask, _textOut] = (0, import_generation.performTextForwarding)(
855
+ trNodeResult,
856
+ replyAbortController,
857
+ transcriptionOutput
858
+ );
859
+ tasks.push(textForwardTask);
860
+ textOut = _textOut;
861
+ }
862
+ const onFirstFrame = () => {
863
+ this.agentSession._updateAgentState("speaking");
864
+ };
865
+ let audioOut = null;
866
+ if (audioOutput) {
867
+ if (ttsStream) {
868
+ const [forwardTask, _audioOut] = (0, import_generation.performAudioForwarding)(
869
+ ttsStream,
870
+ audioOutput,
871
+ replyAbortController
872
+ );
873
+ audioOut = _audioOut;
874
+ tasks.push(forwardTask);
875
+ audioOut.firstFrameFut.await.finally(onFirstFrame);
876
+ } else {
877
+ throw Error("ttsStream is null when audioOutput is enabled");
878
+ }
879
+ } else {
880
+ textOut == null ? void 0 : textOut.firstTextFut.await.finally(onFirstFrame);
881
+ }
882
+ const onToolExecutionStarted = (_) => {
883
+ };
884
+ const onToolExecutionCompleted = (_) => {
885
+ };
886
+ const [executeToolsTask, toolOutput] = (0, import_generation.performToolExecutions)({
887
+ session: this.agentSession,
888
+ speechHandle,
889
+ toolCtx,
890
+ toolChoice: modelSettings.toolChoice,
891
+ toolCallStream: llmGenData.toolCallStream,
892
+ controller: replyAbortController,
893
+ onToolExecutionStarted,
894
+ onToolExecutionCompleted
895
+ });
896
+ tasks.push(executeToolsTask);
897
+ await speechHandle.waitIfNotInterrupted(tasks.map((task) => task.result));
898
+ if (audioOutput) {
899
+ await speechHandle.waitIfNotInterrupted([audioOutput.waitForPlayout()]);
900
+ }
901
+ if (toolsMessages) {
902
+ for (const msg of toolsMessages) {
903
+ msg.createdAt = replyStartedAt;
904
+ }
905
+ this.agent._chatCtx.insert(toolsMessages);
906
+ }
907
+ if (speechHandle.interrupted) {
908
+ this.logger.debug(
909
+ { speech_id: speechHandle.id },
910
+ "Aborting all pipeline reply tasks due to interruption"
911
+ );
912
+ replyAbortController.abort();
913
+ await Promise.allSettled(
914
+ tasks.map((task) => task.cancelAndWait(AgentActivity.REPLY_TASK_CANCEL_TIMEOUT))
915
+ );
916
+ let forwardedText = (textOut == null ? void 0 : textOut.text) || "";
917
+ if (audioOutput) {
918
+ audioOutput.clearBuffer();
919
+ const playbackEv = await audioOutput.waitForPlayout();
920
+ if (audioOut == null ? void 0 : audioOut.firstFrameFut.done) {
921
+ this.logger.info(
922
+ { speech_id: speechHandle.id, playbackPosition: playbackEv.playbackPosition },
923
+ "playout interrupted"
924
+ );
925
+ if (playbackEv.synchronizedTranscript) {
926
+ forwardedText = playbackEv.synchronizedTranscript;
927
+ }
928
+ } else {
929
+ forwardedText = "";
930
+ }
931
+ }
932
+ if (forwardedText) {
933
+ const message = import_chat_context.ChatMessage.create({
934
+ role: "assistant",
935
+ content: forwardedText,
936
+ id: llmGenData.id,
937
+ interrupted: true,
938
+ createdAt: replyStartedAt
939
+ });
940
+ chatCtx.insert(message);
941
+ this.agent._chatCtx.insert(message);
942
+ this.agentSession._conversationItemAdded(message);
943
+ }
944
+ if (this.agentSession.agentState === "speaking") {
945
+ this.agentSession._updateAgentState("listening");
946
+ }
947
+ this.logger.info(
948
+ { speech_id: speechHandle.id, message: forwardedText },
949
+ "playout completed with interrupt"
950
+ );
951
+ speechHandle._markPlayoutDone();
952
+ await executeToolsTask.cancelAndWait(AgentActivity.REPLY_TASK_CANCEL_TIMEOUT);
953
+ return;
954
+ }
955
+ if (textOut && textOut.text) {
956
+ const message = import_chat_context.ChatMessage.create({
957
+ role: "assistant",
958
+ id: llmGenData.id,
959
+ interrupted: false,
960
+ createdAt: replyStartedAt,
961
+ content: textOut.text
962
+ });
963
+ chatCtx.insert(message);
964
+ this.agent._chatCtx.insert(message);
965
+ this.agentSession._conversationItemAdded(message);
966
+ this.logger.info(
967
+ { speech_id: speechHandle.id, message: textOut.text },
968
+ "playout completed without interruption"
969
+ );
970
+ }
971
+ if (toolOutput.output.length > 0) {
972
+ this.agentSession._updateAgentState("thinking");
973
+ } else if (this.agentSession.agentState === "speaking") {
974
+ this.agentSession._updateAgentState("listening");
975
+ }
976
+ speechHandle._markPlayoutDone();
977
+ await executeToolsTask.result;
978
+ if (toolOutput.output.length === 0) return;
979
+ const { maxToolSteps } = this.agentSession.options;
980
+ if (speechHandle.stepIndex >= maxToolSteps) {
981
+ this.logger.warn(
982
+ { speech_id: speechHandle.id, max_tool_steps: maxToolSteps },
983
+ "maximum number of function calls steps reached"
984
+ );
985
+ return;
986
+ }
987
+ const functionToolsExecutedEvent = (0, import_events.createFunctionToolsExecutedEvent)({
988
+ functionCalls: [],
989
+ functionCallOutputs: []
990
+ });
991
+ let shouldGenerateToolReply = false;
992
+ let newAgentTask = null;
993
+ let ignoreTaskSwitch = false;
994
+ for (const sanitizedOut of toolOutput.output) {
995
+ if (sanitizedOut.toolCallOutput !== void 0) {
996
+ functionToolsExecutedEvent.functionCalls.push(sanitizedOut.toolCall);
997
+ functionToolsExecutedEvent.functionCallOutputs.push(sanitizedOut.toolCallOutput);
998
+ if (sanitizedOut.replyRequired) {
999
+ shouldGenerateToolReply = true;
1000
+ }
1001
+ }
1002
+ if (newAgentTask !== null && sanitizedOut.agentTask !== void 0) {
1003
+ this.logger.error("expected to receive only one agent task from the tool executions");
1004
+ ignoreTaskSwitch = true;
1005
+ }
1006
+ newAgentTask = sanitizedOut.agentTask ?? null;
1007
+ this.logger.debug(
1008
+ {
1009
+ speechId: speechHandle.id,
1010
+ name: (_a = sanitizedOut.toolCall) == null ? void 0 : _a.name,
1011
+ args: sanitizedOut.toolCall.args,
1012
+ output: (_b = sanitizedOut.toolCallOutput) == null ? void 0 : _b.output,
1013
+ isError: (_c = sanitizedOut.toolCallOutput) == null ? void 0 : _c.isError
1014
+ },
1015
+ "Tool call execution finished"
1016
+ );
1017
+ }
1018
+ this.agentSession.emit(
1019
+ import_events.AgentSessionEventTypes.FunctionToolsExecuted,
1020
+ functionToolsExecutedEvent
1021
+ );
1022
+ let draining = this.draining;
1023
+ if (!ignoreTaskSwitch && newAgentTask !== null) {
1024
+ this.agentSession.updateAgent(newAgentTask);
1025
+ draining = true;
1026
+ }
1027
+ const toolMessages = [
1028
+ ...functionToolsExecutedEvent.functionCalls,
1029
+ ...functionToolsExecutedEvent.functionCallOutputs
1030
+ ];
1031
+ if (shouldGenerateToolReply) {
1032
+ chatCtx.insert(toolMessages);
1033
+ const handle = import_speech_handle.SpeechHandle.create({
1034
+ allowInterruptions: speechHandle.allowInterruptions,
1035
+ stepIndex: speechHandle.stepIndex + 1,
1036
+ parent: speechHandle
1037
+ });
1038
+ this.agentSession.emit(
1039
+ import_events.AgentSessionEventTypes.SpeechCreated,
1040
+ (0, import_events.createSpeechCreatedEvent)({
1041
+ userInitiated: false,
1042
+ source: "tool_response",
1043
+ speechHandle: handle
1044
+ })
1045
+ );
1046
+ const respondToolChoice = draining || modelSettings.toolChoice === "none" ? "none" : "auto";
1047
+ const toolResponseTask = this.createSpeechTask({
1048
+ promise: this.pipelineReplyTask(
1049
+ handle,
1050
+ chatCtx,
1051
+ toolCtx,
1052
+ { toolChoice: respondToolChoice },
1053
+ instructions,
1054
+ void 0,
1055
+ toolMessages
1056
+ ),
1057
+ ownedSpeechHandle: handle,
1058
+ name: "AgentActivity.pipelineReply"
1059
+ });
1060
+ toolResponseTask.finally(() => this.onPipelineReplyDone());
1061
+ this.scheduleSpeech(handle, import_speech_handle.SpeechHandle.SPEECH_PRIORITY_NORMAL, true);
1062
+ } else if (functionToolsExecutedEvent.functionCallOutputs.length > 0) {
1063
+ for (const msg of toolMessages) {
1064
+ msg.createdAt = replyStartedAt;
1065
+ }
1066
+ this.agent._chatCtx.insert(toolMessages);
1067
+ }
1068
+ }
1069
+ async realtimeGenerationTask(speechHandle, ev, modelSettings) {
1070
+ var _a, _b, _c;
1071
+ speechHandleStorage.enterWith(speechHandle);
1072
+ if (!this.realtimeSession) {
1073
+ throw new Error("realtime session is not initialized");
1074
+ }
1075
+ if (!(this.llm instanceof import_llm.RealtimeModel)) {
1076
+ throw new Error("llm is not a realtime model");
1077
+ }
1078
+ this.logger.debug(
1079
+ { speech_id: speechHandle.id, stepIndex: speechHandle.stepIndex },
1080
+ "realtime generation started"
1081
+ );
1082
+ const audioOutput = this.agentSession.output.audioEnabled ? this.agentSession.output.audio : null;
1083
+ const textOutput = this.agentSession.output.transcriptionEnabled ? this.agentSession.output.transcription : null;
1084
+ const toolCtx = this.realtimeSession.tools;
1085
+ await speechHandle.waitIfNotInterrupted([speechHandle._waitForAuthorization()]);
1086
+ if (speechHandle.interrupted) {
1087
+ return;
1088
+ }
1089
+ const onFirstFrame = () => {
1090
+ this.agentSession._updateAgentState("speaking");
1091
+ };
1092
+ const replyAbortController = new AbortController();
1093
+ const readMessages = async (abortController, outputs) => {
1094
+ const forwardTasks = [];
1095
+ try {
1096
+ for await (const msg of ev.messageStream) {
1097
+ if (forwardTasks.length > 0) {
1098
+ this.logger.warn(
1099
+ "expected to receive only one message generation from the realtime API"
1100
+ );
1101
+ break;
1102
+ }
1103
+ const trNodeResult = await this.agent.transcriptionNode(msg.textStream, modelSettings);
1104
+ let textOut = null;
1105
+ if (trNodeResult) {
1106
+ const [textForwardTask, _textOut] = (0, import_generation.performTextForwarding)(
1107
+ trNodeResult,
1108
+ abortController,
1109
+ textOutput
1110
+ );
1111
+ forwardTasks.push(textForwardTask);
1112
+ textOut = _textOut;
1113
+ }
1114
+ let audioOut = null;
1115
+ if (audioOutput) {
1116
+ const realtimeAudio = await this.agent.realtimeAudioOutputNode(
1117
+ msg.audioStream,
1118
+ modelSettings
1119
+ );
1120
+ if (realtimeAudio) {
1121
+ const [forwardTask, _audioOut] = (0, import_generation.performAudioForwarding)(
1122
+ realtimeAudio,
1123
+ audioOutput,
1124
+ abortController
1125
+ );
1126
+ forwardTasks.push(forwardTask);
1127
+ audioOut = _audioOut;
1128
+ audioOut.firstFrameFut.await.finally(onFirstFrame);
1129
+ } else {
1130
+ this.logger.warn(
1131
+ "audio output is enabled but neither tts nor realtime audio is available"
1132
+ );
1133
+ }
1134
+ } else if (textOut) {
1135
+ textOut.firstTextFut.await.finally(onFirstFrame);
1136
+ }
1137
+ outputs.push([msg.messageId, textOut, audioOut]);
1138
+ }
1139
+ await (0, import_utils.waitFor)(forwardTasks);
1140
+ } catch (error) {
1141
+ this.logger.error(error, "error reading messages from the realtime API");
1142
+ } finally {
1143
+ await (0, import_utils.cancelAndWait)(forwardTasks, AgentActivity.REPLY_TASK_CANCEL_TIMEOUT);
1144
+ }
1145
+ };
1146
+ const messageOutputs = [];
1147
+ const tasks = [
1148
+ import_utils.Task.from(
1149
+ (controller) => readMessages(controller, messageOutputs),
1150
+ replyAbortController,
1151
+ "AgentActivity.realtime_generation.read_messages"
1152
+ )
1153
+ ];
1154
+ const [toolCallStream, toolCallStreamForTracing] = ev.functionStream.tee();
1155
+ const toolCalls = [];
1156
+ const readToolStreamTask = async (controller, stream) => {
1157
+ const reader = stream.getReader();
1158
+ try {
1159
+ while (!controller.signal.aborted) {
1160
+ const { done, value } = await reader.read();
1161
+ if (done) break;
1162
+ this.logger.debug({ tool_call: value }, "received tool call from the realtime API");
1163
+ toolCalls.push(value);
1164
+ }
1165
+ } finally {
1166
+ reader.releaseLock();
1167
+ }
1168
+ };
1169
+ tasks.push(
1170
+ import_utils.Task.from(
1171
+ (controller) => readToolStreamTask(controller, toolCallStreamForTracing),
1172
+ replyAbortController,
1173
+ "AgentActivity.realtime_generation.read_tool_stream"
1174
+ )
1175
+ );
1176
+ const onToolExecutionStarted = (_) => {
1177
+ };
1178
+ const onToolExecutionCompleted = (_) => {
1179
+ };
1180
+ const [executeToolsTask, toolOutput] = (0, import_generation.performToolExecutions)({
1181
+ session: this.agentSession,
1182
+ speechHandle,
1183
+ toolCtx,
1184
+ toolCallStream,
1185
+ toolChoice: modelSettings.toolChoice,
1186
+ controller: replyAbortController,
1187
+ onToolExecutionStarted,
1188
+ onToolExecutionCompleted
1189
+ });
1190
+ await speechHandle.waitIfNotInterrupted(tasks.map((task) => task.result));
1191
+ if (audioOutput) {
1192
+ await speechHandle.waitIfNotInterrupted([audioOutput.waitForPlayout()]);
1193
+ this.agentSession._updateAgentState("listening");
1194
+ }
1195
+ if (speechHandle.interrupted) {
1196
+ this.logger.debug(
1197
+ { speech_id: speechHandle.id },
1198
+ "Aborting all realtime generation tasks due to interruption"
1199
+ );
1200
+ replyAbortController.abort();
1201
+ await (0, import_utils.cancelAndWait)(tasks, AgentActivity.REPLY_TASK_CANCEL_TIMEOUT);
1202
+ if (messageOutputs.length > 0) {
1203
+ const [msgId, textOut, audioOut] = messageOutputs[0];
1204
+ let forwardedText = (textOut == null ? void 0 : textOut.text) || "";
1205
+ if (audioOutput) {
1206
+ audioOutput.clearBuffer();
1207
+ const playbackEv = await audioOutput.waitForPlayout();
1208
+ let playbackPosition = playbackEv.playbackPosition;
1209
+ if (audioOut == null ? void 0 : audioOut.firstFrameFut.done) {
1210
+ this.logger.info(
1211
+ { speech_id: speechHandle.id, playbackPosition: playbackEv.playbackPosition },
1212
+ "playout interrupted"
1213
+ );
1214
+ if (playbackEv.synchronizedTranscript) {
1215
+ forwardedText = playbackEv.synchronizedTranscript;
1216
+ }
1217
+ } else {
1218
+ forwardedText = "";
1219
+ playbackPosition = 0;
1220
+ }
1221
+ this.realtimeSession.truncate({
1222
+ messageId: msgId,
1223
+ audioEndMs: Math.floor(playbackPosition)
1224
+ });
1225
+ }
1226
+ if (forwardedText) {
1227
+ const message = import_chat_context.ChatMessage.create({
1228
+ role: "assistant",
1229
+ content: forwardedText,
1230
+ id: msgId,
1231
+ interrupted: true
1232
+ });
1233
+ this.agent._chatCtx.insert(message);
1234
+ speechHandle._setChatMessage(message);
1235
+ this.agentSession._conversationItemAdded(message);
1236
+ }
1237
+ this.logger.info(
1238
+ { speech_id: speechHandle.id, message: forwardedText },
1239
+ "playout completed with interrupt"
1240
+ );
1241
+ }
1242
+ speechHandle._markPlayoutDone();
1243
+ await executeToolsTask.cancelAndWait(AgentActivity.REPLY_TASK_CANCEL_TIMEOUT);
1244
+ return;
1245
+ }
1246
+ if (messageOutputs.length > 0) {
1247
+ const [msgId, textOut, _] = messageOutputs[0];
1248
+ const message = import_chat_context.ChatMessage.create({
1249
+ role: "assistant",
1250
+ content: (textOut == null ? void 0 : textOut.text) || "",
1251
+ id: msgId,
1252
+ interrupted: false
1253
+ });
1254
+ this.agent._chatCtx.insert(message);
1255
+ speechHandle._setChatMessage(message);
1256
+ this.agentSession._conversationItemAdded(message);
1257
+ }
1258
+ speechHandle._markPlayoutDone();
1259
+ toolOutput.firstToolStartedFuture.await.finally(() => {
1260
+ this.agentSession._updateAgentState("thinking");
1261
+ });
1262
+ await executeToolsTask.result;
1263
+ if (toolOutput.output.length === 0) return;
1264
+ const { maxToolSteps } = this.agentSession.options;
1265
+ if (speechHandle.stepIndex >= maxToolSteps) {
1266
+ this.logger.warn(
1267
+ { speech_id: speechHandle.id, max_tool_steps: maxToolSteps },
1268
+ "maximum number of function calls steps reached"
1269
+ );
1270
+ return;
1271
+ }
1272
+ const functionToolsExecutedEvent = (0, import_events.createFunctionToolsExecutedEvent)({
1273
+ functionCalls: [],
1274
+ functionCallOutputs: []
1275
+ });
1276
+ let shouldGenerateToolReply = false;
1277
+ let newAgentTask = null;
1278
+ let ignoreTaskSwitch = false;
1279
+ for (const sanitizedOut of toolOutput.output) {
1280
+ if (sanitizedOut.toolCallOutput !== void 0) {
1281
+ functionToolsExecutedEvent.functionCallOutputs.push(sanitizedOut.toolCallOutput);
1282
+ if (sanitizedOut.replyRequired) {
1283
+ shouldGenerateToolReply = true;
1284
+ }
1285
+ }
1286
+ if (newAgentTask !== null && sanitizedOut.agentTask !== void 0) {
1287
+ this.logger.error("expected to receive only one agent task from the tool executions");
1288
+ ignoreTaskSwitch = true;
1289
+ }
1290
+ newAgentTask = sanitizedOut.agentTask ?? null;
1291
+ this.logger.debug(
1292
+ {
1293
+ speechId: speechHandle.id,
1294
+ name: (_a = sanitizedOut.toolCall) == null ? void 0 : _a.name,
1295
+ args: sanitizedOut.toolCall.args,
1296
+ output: (_b = sanitizedOut.toolCallOutput) == null ? void 0 : _b.output,
1297
+ isError: (_c = sanitizedOut.toolCallOutput) == null ? void 0 : _c.isError
1298
+ },
1299
+ "Tool call execution finished"
1300
+ );
1301
+ }
1302
+ this.agentSession.emit(
1303
+ import_events.AgentSessionEventTypes.FunctionToolsExecuted,
1304
+ functionToolsExecutedEvent
1305
+ );
1306
+ let draining = this.draining;
1307
+ if (!ignoreTaskSwitch && newAgentTask !== null) {
1308
+ this.agentSession.updateAgent(newAgentTask);
1309
+ draining = true;
1310
+ }
1311
+ if (functionToolsExecutedEvent.functionCallOutputs.length > 0) {
1312
+ const chatCtx = this.realtimeSession.chatCtx.copy();
1313
+ chatCtx.items.push(...functionToolsExecutedEvent.functionCallOutputs);
1314
+ try {
1315
+ await this.realtimeSession.updateChatCtx(chatCtx);
1316
+ } catch (error) {
1317
+ this.logger.warn(
1318
+ { error },
1319
+ "failed to update chat context before generating the function calls results"
1320
+ );
1321
+ }
1322
+ }
1323
+ if (!shouldGenerateToolReply || this.llm.capabilities.autoToolReplyGeneration) {
1324
+ return;
1325
+ }
1326
+ this.realtimeSession.interrupt();
1327
+ const replySpeechHandle = import_speech_handle.SpeechHandle.create({
1328
+ allowInterruptions: speechHandle.allowInterruptions,
1329
+ stepIndex: speechHandle.stepIndex + 1,
1330
+ parent: speechHandle
1331
+ });
1332
+ this.agentSession.emit(
1333
+ import_events.AgentSessionEventTypes.SpeechCreated,
1334
+ (0, import_events.createSpeechCreatedEvent)({
1335
+ userInitiated: false,
1336
+ source: "tool_response",
1337
+ speechHandle: replySpeechHandle
1338
+ })
1339
+ );
1340
+ const toolChoice = draining || modelSettings.toolChoice === "none" ? "none" : "auto";
1341
+ this.createSpeechTask({
1342
+ promise: this.realtimeReplyTask({
1343
+ speechHandle: replySpeechHandle,
1344
+ modelSettings: { toolChoice }
1345
+ }),
1346
+ ownedSpeechHandle: replySpeechHandle,
1347
+ name: "AgentActivity.realtime_reply"
1348
+ });
1349
+ this.scheduleSpeech(replySpeechHandle, import_speech_handle.SpeechHandle.SPEECH_PRIORITY_NORMAL, true);
1350
+ }
1351
+ async realtimeReplyTask({
1352
+ speechHandle,
1353
+ modelSettings: { toolChoice },
1354
+ userInput,
1355
+ instructions
1356
+ }) {
1357
+ speechHandleStorage.enterWith(speechHandle);
1358
+ if (!this.realtimeSession) {
1359
+ throw new Error("realtime session is not available");
1360
+ }
1361
+ await speechHandle.waitIfNotInterrupted([speechHandle._waitForAuthorization()]);
1362
+ if (userInput) {
1363
+ const chatCtx = this.realtimeSession.chatCtx.copy();
1364
+ const message = chatCtx.addMessage({
1365
+ role: "user",
1366
+ content: userInput
1367
+ });
1368
+ await this.realtimeSession.updateChatCtx(chatCtx);
1369
+ this.agent._chatCtx.insert(message);
1370
+ this.agentSession._conversationItemAdded(message);
1371
+ }
1372
+ const originalToolChoice = this.toolChoice;
1373
+ if (toolChoice !== void 0) {
1374
+ this.realtimeSession.updateOptions({ toolChoice });
1375
+ }
1376
+ try {
1377
+ const generationEvent = await this.realtimeSession.generateReply(instructions);
1378
+ await this.realtimeGenerationTask(speechHandle, generationEvent, { toolChoice });
1379
+ } finally {
1380
+ if (toolChoice !== void 0 && toolChoice !== originalToolChoice) {
1381
+ this.realtimeSession.updateOptions({ toolChoice: originalToolChoice });
1382
+ }
1383
+ }
1384
+ }
1385
+ scheduleSpeech(speechHandle, priority, bypassDraining = false) {
1386
+ if (this.draining && !bypassDraining) {
1387
+ throw new Error("cannot schedule new speech, the agent is draining");
1388
+ }
1389
+ this.speechQueue.push([priority, Number(process.hrtime.bigint()), speechHandle]);
1390
+ this.wakeupMainTask();
1391
+ }
1392
+ async drain() {
1393
+ var _a;
1394
+ const unlock = await this.lock.lock();
1395
+ try {
1396
+ if (this._draining) return;
1397
+ this.createSpeechTask({
1398
+ promise: this.agent.onExit(),
1399
+ name: "AgentActivity_onExit"
1400
+ });
1401
+ this.wakeupMainTask();
1402
+ this._draining = true;
1403
+ await ((_a = this._mainTask) == null ? void 0 : _a.result);
1404
+ } finally {
1405
+ unlock();
1406
+ }
1407
+ }
1408
+ async close() {
1409
+ var _a, _b, _c;
1410
+ const unlock = await this.lock.lock();
1411
+ try {
1412
+ if (!this._draining) {
1413
+ this.logger.warn("task closing without draining");
1414
+ }
1415
+ if (this.llm instanceof import_llm.LLM) {
1416
+ this.llm.off("metrics_collected", this.onMetricsCollected);
1417
+ }
1418
+ if (this.realtimeSession) {
1419
+ this.realtimeSession.off("generation_created", this.onGenerationCreated);
1420
+ this.realtimeSession.off("input_speech_started", this.onInputSpeechStarted);
1421
+ this.realtimeSession.off("input_speech_stopped", this.onInputSpeechStopped);
1422
+ this.realtimeSession.off(
1423
+ "input_audio_transcription_completed",
1424
+ this.onInputAudioTranscriptionCompleted
1425
+ );
1426
+ this.realtimeSession.off("metrics_collected", this.onMetricsCollected);
1427
+ }
1428
+ if (this.stt instanceof import_stt.STT) {
1429
+ this.stt.off("metrics_collected", this.onMetricsCollected);
1430
+ }
1431
+ if (this.tts instanceof import_tts.TTS) {
1432
+ this.tts.off("metrics_collected", this.onMetricsCollected);
1433
+ }
1434
+ if (this.vad instanceof import_vad.VAD) {
1435
+ this.vad.off("metrics_collected", this.onMetricsCollected);
1436
+ }
1437
+ this.detachAudioInput();
1438
+ await ((_a = this.realtimeSession) == null ? void 0 : _a.close());
1439
+ await ((_b = this.audioRecognition) == null ? void 0 : _b.close());
1440
+ await ((_c = this._mainTask) == null ? void 0 : _c.cancelAndWait());
1441
+ } finally {
1442
+ unlock();
1443
+ }
1444
+ }
1445
+ }
1446
+ function toOaiToolChoice(toolChoice) {
1447
+ return toolChoice !== null ? toolChoice : void 0;
1448
+ }
1449
+ // Annotate the CommonJS export names for ESM import in node:
1450
+ 0 && (module.exports = {
1451
+ AgentActivity
1452
+ });
1453
+ //# sourceMappingURL=agent_activity.cjs.map