@livekit/agents 1.0.48 → 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 (373) hide show
  1. package/dist/constants.cjs +27 -0
  2. package/dist/constants.cjs.map +1 -1
  3. package/dist/constants.d.cts +9 -0
  4. package/dist/constants.d.ts +9 -0
  5. package/dist/constants.d.ts.map +1 -1
  6. package/dist/constants.js +18 -0
  7. package/dist/constants.js.map +1 -1
  8. package/dist/inference/api_protos.d.cts +71 -71
  9. package/dist/inference/api_protos.d.ts +71 -71
  10. package/dist/inference/interruption/defaults.cjs +81 -0
  11. package/dist/inference/interruption/defaults.cjs.map +1 -0
  12. package/dist/inference/interruption/defaults.d.cts +19 -0
  13. package/dist/inference/interruption/defaults.d.ts +19 -0
  14. package/dist/inference/interruption/defaults.d.ts.map +1 -0
  15. package/dist/inference/interruption/defaults.js +46 -0
  16. package/dist/inference/interruption/defaults.js.map +1 -0
  17. package/dist/inference/interruption/errors.cjs +44 -0
  18. package/dist/inference/interruption/errors.cjs.map +1 -0
  19. package/dist/inference/interruption/errors.d.cts +12 -0
  20. package/dist/inference/interruption/errors.d.ts +12 -0
  21. package/dist/inference/interruption/errors.d.ts.map +1 -0
  22. package/dist/inference/interruption/errors.js +20 -0
  23. package/dist/inference/interruption/errors.js.map +1 -0
  24. package/dist/inference/interruption/http_transport.cjs +147 -0
  25. package/dist/inference/interruption/http_transport.cjs.map +1 -0
  26. package/dist/inference/interruption/http_transport.d.cts +63 -0
  27. package/dist/inference/interruption/http_transport.d.ts +63 -0
  28. package/dist/inference/interruption/http_transport.d.ts.map +1 -0
  29. package/dist/inference/interruption/http_transport.js +121 -0
  30. package/dist/inference/interruption/http_transport.js.map +1 -0
  31. package/dist/inference/interruption/interruption_cache_entry.cjs +58 -0
  32. package/dist/inference/interruption/interruption_cache_entry.cjs.map +1 -0
  33. package/dist/inference/interruption/interruption_cache_entry.d.cts +30 -0
  34. package/dist/inference/interruption/interruption_cache_entry.d.ts +30 -0
  35. package/dist/inference/interruption/interruption_cache_entry.d.ts.map +1 -0
  36. package/dist/inference/interruption/interruption_cache_entry.js +34 -0
  37. package/dist/inference/interruption/interruption_cache_entry.js.map +1 -0
  38. package/dist/inference/interruption/interruption_detector.cjs +181 -0
  39. package/dist/inference/interruption/interruption_detector.cjs.map +1 -0
  40. package/dist/inference/interruption/interruption_detector.d.cts +59 -0
  41. package/dist/inference/interruption/interruption_detector.d.ts +59 -0
  42. package/dist/inference/interruption/interruption_detector.d.ts.map +1 -0
  43. package/dist/inference/interruption/interruption_detector.js +147 -0
  44. package/dist/inference/interruption/interruption_detector.js.map +1 -0
  45. package/dist/inference/interruption/interruption_stream.cjs +368 -0
  46. package/dist/inference/interruption/interruption_stream.cjs.map +1 -0
  47. package/dist/inference/interruption/interruption_stream.d.cts +46 -0
  48. package/dist/inference/interruption/interruption_stream.d.ts +46 -0
  49. package/dist/inference/interruption/interruption_stream.d.ts.map +1 -0
  50. package/dist/inference/interruption/interruption_stream.js +344 -0
  51. package/dist/inference/interruption/interruption_stream.js.map +1 -0
  52. package/dist/inference/interruption/types.cjs +17 -0
  53. package/dist/inference/interruption/types.cjs.map +1 -0
  54. package/dist/inference/interruption/types.d.cts +66 -0
  55. package/dist/inference/interruption/types.d.ts +66 -0
  56. package/dist/inference/interruption/types.d.ts.map +1 -0
  57. package/dist/inference/interruption/types.js +1 -0
  58. package/dist/inference/interruption/types.js.map +1 -0
  59. package/dist/inference/interruption/utils.cjs +130 -0
  60. package/dist/inference/interruption/utils.cjs.map +1 -0
  61. package/dist/inference/interruption/utils.d.cts +41 -0
  62. package/dist/inference/interruption/utils.d.ts +41 -0
  63. package/dist/inference/interruption/utils.d.ts.map +1 -0
  64. package/dist/inference/interruption/utils.js +105 -0
  65. package/dist/inference/interruption/utils.js.map +1 -0
  66. package/dist/inference/interruption/utils.test.cjs +105 -0
  67. package/dist/inference/interruption/utils.test.cjs.map +1 -0
  68. package/dist/inference/interruption/utils.test.js +104 -0
  69. package/dist/inference/interruption/utils.test.js.map +1 -0
  70. package/dist/inference/interruption/ws_transport.cjs +329 -0
  71. package/dist/inference/interruption/ws_transport.cjs.map +1 -0
  72. package/dist/inference/interruption/ws_transport.d.cts +33 -0
  73. package/dist/inference/interruption/ws_transport.d.ts +33 -0
  74. package/dist/inference/interruption/ws_transport.d.ts.map +1 -0
  75. package/dist/inference/interruption/ws_transport.js +295 -0
  76. package/dist/inference/interruption/ws_transport.js.map +1 -0
  77. package/dist/inference/llm.cjs +14 -10
  78. package/dist/inference/llm.cjs.map +1 -1
  79. package/dist/inference/llm.d.cts +2 -1
  80. package/dist/inference/llm.d.ts +2 -1
  81. package/dist/inference/llm.d.ts.map +1 -1
  82. package/dist/inference/llm.js +8 -10
  83. package/dist/inference/llm.js.map +1 -1
  84. package/dist/inference/stt.cjs +7 -2
  85. package/dist/inference/stt.cjs.map +1 -1
  86. package/dist/inference/stt.d.cts +2 -0
  87. package/dist/inference/stt.d.ts +2 -0
  88. package/dist/inference/stt.d.ts.map +1 -1
  89. package/dist/inference/stt.js +8 -3
  90. package/dist/inference/stt.js.map +1 -1
  91. package/dist/inference/tts.cjs +7 -2
  92. package/dist/inference/tts.cjs.map +1 -1
  93. package/dist/inference/tts.d.cts +2 -0
  94. package/dist/inference/tts.d.ts +2 -0
  95. package/dist/inference/tts.d.ts.map +1 -1
  96. package/dist/inference/tts.js +8 -3
  97. package/dist/inference/tts.js.map +1 -1
  98. package/dist/inference/utils.cjs +26 -7
  99. package/dist/inference/utils.cjs.map +1 -1
  100. package/dist/inference/utils.d.cts +13 -0
  101. package/dist/inference/utils.d.ts +13 -0
  102. package/dist/inference/utils.d.ts.map +1 -1
  103. package/dist/inference/utils.js +18 -2
  104. package/dist/inference/utils.js.map +1 -1
  105. package/dist/llm/chat_context.cjs +20 -2
  106. package/dist/llm/chat_context.cjs.map +1 -1
  107. package/dist/llm/chat_context.d.cts +19 -1
  108. package/dist/llm/chat_context.d.ts +19 -1
  109. package/dist/llm/chat_context.d.ts.map +1 -1
  110. package/dist/llm/chat_context.js +20 -2
  111. package/dist/llm/chat_context.js.map +1 -1
  112. package/dist/llm/index.cjs.map +1 -1
  113. package/dist/llm/index.d.cts +1 -1
  114. package/dist/llm/index.d.ts +1 -1
  115. package/dist/llm/index.d.ts.map +1 -1
  116. package/dist/llm/index.js.map +1 -1
  117. package/dist/llm/llm.cjs +16 -1
  118. package/dist/llm/llm.cjs.map +1 -1
  119. package/dist/llm/llm.d.cts +9 -0
  120. package/dist/llm/llm.d.ts +9 -0
  121. package/dist/llm/llm.d.ts.map +1 -1
  122. package/dist/llm/llm.js +16 -1
  123. package/dist/llm/llm.js.map +1 -1
  124. package/dist/llm/realtime.cjs +3 -0
  125. package/dist/llm/realtime.cjs.map +1 -1
  126. package/dist/llm/realtime.d.cts +1 -0
  127. package/dist/llm/realtime.d.ts +1 -0
  128. package/dist/llm/realtime.d.ts.map +1 -1
  129. package/dist/llm/realtime.js +3 -0
  130. package/dist/llm/realtime.js.map +1 -1
  131. package/dist/metrics/base.cjs.map +1 -1
  132. package/dist/metrics/base.d.cts +45 -1
  133. package/dist/metrics/base.d.ts +45 -1
  134. package/dist/metrics/base.d.ts.map +1 -1
  135. package/dist/metrics/index.cjs +5 -0
  136. package/dist/metrics/index.cjs.map +1 -1
  137. package/dist/metrics/index.d.cts +2 -1
  138. package/dist/metrics/index.d.ts +2 -1
  139. package/dist/metrics/index.d.ts.map +1 -1
  140. package/dist/metrics/index.js +6 -0
  141. package/dist/metrics/index.js.map +1 -1
  142. package/dist/metrics/model_usage.cjs +189 -0
  143. package/dist/metrics/model_usage.cjs.map +1 -0
  144. package/dist/metrics/model_usage.d.cts +92 -0
  145. package/dist/metrics/model_usage.d.ts +92 -0
  146. package/dist/metrics/model_usage.d.ts.map +1 -0
  147. package/dist/metrics/model_usage.js +164 -0
  148. package/dist/metrics/model_usage.js.map +1 -0
  149. package/dist/metrics/model_usage.test.cjs +474 -0
  150. package/dist/metrics/model_usage.test.cjs.map +1 -0
  151. package/dist/metrics/model_usage.test.js +476 -0
  152. package/dist/metrics/model_usage.test.js.map +1 -0
  153. package/dist/metrics/usage_collector.cjs +3 -0
  154. package/dist/metrics/usage_collector.cjs.map +1 -1
  155. package/dist/metrics/usage_collector.d.cts +9 -0
  156. package/dist/metrics/usage_collector.d.ts +9 -0
  157. package/dist/metrics/usage_collector.d.ts.map +1 -1
  158. package/dist/metrics/usage_collector.js +3 -0
  159. package/dist/metrics/usage_collector.js.map +1 -1
  160. package/dist/metrics/utils.cjs +9 -0
  161. package/dist/metrics/utils.cjs.map +1 -1
  162. package/dist/metrics/utils.d.ts.map +1 -1
  163. package/dist/metrics/utils.js +9 -0
  164. package/dist/metrics/utils.js.map +1 -1
  165. package/dist/stream/multi_input_stream.test.cjs +4 -0
  166. package/dist/stream/multi_input_stream.test.cjs.map +1 -1
  167. package/dist/stream/multi_input_stream.test.js +5 -1
  168. package/dist/stream/multi_input_stream.test.js.map +1 -1
  169. package/dist/stream/stream_channel.cjs +31 -0
  170. package/dist/stream/stream_channel.cjs.map +1 -1
  171. package/dist/stream/stream_channel.d.cts +4 -2
  172. package/dist/stream/stream_channel.d.ts +4 -2
  173. package/dist/stream/stream_channel.d.ts.map +1 -1
  174. package/dist/stream/stream_channel.js +31 -0
  175. package/dist/stream/stream_channel.js.map +1 -1
  176. package/dist/stt/stt.cjs +34 -2
  177. package/dist/stt/stt.cjs.map +1 -1
  178. package/dist/stt/stt.d.cts +22 -0
  179. package/dist/stt/stt.d.ts +22 -0
  180. package/dist/stt/stt.d.ts.map +1 -1
  181. package/dist/stt/stt.js +34 -2
  182. package/dist/stt/stt.js.map +1 -1
  183. package/dist/telemetry/otel_http_exporter.cjs +24 -5
  184. package/dist/telemetry/otel_http_exporter.cjs.map +1 -1
  185. package/dist/telemetry/otel_http_exporter.d.cts +1 -0
  186. package/dist/telemetry/otel_http_exporter.d.ts +1 -0
  187. package/dist/telemetry/otel_http_exporter.d.ts.map +1 -1
  188. package/dist/telemetry/otel_http_exporter.js +24 -5
  189. package/dist/telemetry/otel_http_exporter.js.map +1 -1
  190. package/dist/telemetry/trace_types.cjs +5 -5
  191. package/dist/telemetry/trace_types.cjs.map +1 -1
  192. package/dist/telemetry/trace_types.d.cts +9 -5
  193. package/dist/telemetry/trace_types.d.ts +9 -5
  194. package/dist/telemetry/trace_types.d.ts.map +1 -1
  195. package/dist/telemetry/trace_types.js +5 -5
  196. package/dist/telemetry/trace_types.js.map +1 -1
  197. package/dist/telemetry/traces.cjs +47 -8
  198. package/dist/telemetry/traces.cjs.map +1 -1
  199. package/dist/telemetry/traces.d.ts.map +1 -1
  200. package/dist/telemetry/traces.js +47 -8
  201. package/dist/telemetry/traces.js.map +1 -1
  202. package/dist/tts/tts.cjs +64 -2
  203. package/dist/tts/tts.cjs.map +1 -1
  204. package/dist/tts/tts.d.cts +34 -0
  205. package/dist/tts/tts.d.ts +34 -0
  206. package/dist/tts/tts.d.ts.map +1 -1
  207. package/dist/tts/tts.js +64 -2
  208. package/dist/tts/tts.js.map +1 -1
  209. package/dist/version.cjs +1 -1
  210. package/dist/version.js +1 -1
  211. package/dist/voice/agent.cjs +25 -4
  212. package/dist/voice/agent.cjs.map +1 -1
  213. package/dist/voice/agent.d.cts +10 -2
  214. package/dist/voice/agent.d.ts +10 -2
  215. package/dist/voice/agent.d.ts.map +1 -1
  216. package/dist/voice/agent.js +25 -4
  217. package/dist/voice/agent.js.map +1 -1
  218. package/dist/voice/agent_activity.cjs +261 -36
  219. package/dist/voice/agent_activity.cjs.map +1 -1
  220. package/dist/voice/agent_activity.d.cts +20 -6
  221. package/dist/voice/agent_activity.d.ts +20 -6
  222. package/dist/voice/agent_activity.d.ts.map +1 -1
  223. package/dist/voice/agent_activity.js +262 -37
  224. package/dist/voice/agent_activity.js.map +1 -1
  225. package/dist/voice/agent_session.cjs +105 -48
  226. package/dist/voice/agent_session.cjs.map +1 -1
  227. package/dist/voice/agent_session.d.cts +90 -20
  228. package/dist/voice/agent_session.d.ts +90 -20
  229. package/dist/voice/agent_session.d.ts.map +1 -1
  230. package/dist/voice/agent_session.js +105 -46
  231. package/dist/voice/agent_session.js.map +1 -1
  232. package/dist/voice/audio_recognition.cjs +287 -6
  233. package/dist/voice/audio_recognition.cjs.map +1 -1
  234. package/dist/voice/audio_recognition.d.cts +42 -3
  235. package/dist/voice/audio_recognition.d.ts +42 -3
  236. package/dist/voice/audio_recognition.d.ts.map +1 -1
  237. package/dist/voice/audio_recognition.js +289 -7
  238. package/dist/voice/audio_recognition.js.map +1 -1
  239. package/dist/voice/client_events.cjs +554 -0
  240. package/dist/voice/client_events.cjs.map +1 -0
  241. package/dist/voice/client_events.d.cts +195 -0
  242. package/dist/voice/client_events.d.ts +195 -0
  243. package/dist/voice/client_events.d.ts.map +1 -0
  244. package/dist/voice/client_events.js +548 -0
  245. package/dist/voice/client_events.js.map +1 -0
  246. package/dist/voice/events.cjs +1 -0
  247. package/dist/voice/events.cjs.map +1 -1
  248. package/dist/voice/events.d.cts +8 -5
  249. package/dist/voice/events.d.ts +8 -5
  250. package/dist/voice/events.d.ts.map +1 -1
  251. package/dist/voice/events.js +1 -0
  252. package/dist/voice/events.js.map +1 -1
  253. package/dist/voice/generation.cjs +43 -8
  254. package/dist/voice/generation.cjs.map +1 -1
  255. package/dist/voice/generation.d.cts +3 -3
  256. package/dist/voice/generation.d.ts +3 -3
  257. package/dist/voice/generation.d.ts.map +1 -1
  258. package/dist/voice/generation.js +43 -8
  259. package/dist/voice/generation.js.map +1 -1
  260. package/dist/voice/index.cjs +1 -0
  261. package/dist/voice/index.cjs.map +1 -1
  262. package/dist/voice/index.d.cts +1 -0
  263. package/dist/voice/index.d.ts +1 -0
  264. package/dist/voice/index.d.ts.map +1 -1
  265. package/dist/voice/index.js +1 -0
  266. package/dist/voice/index.js.map +1 -1
  267. package/dist/voice/report.cjs +20 -8
  268. package/dist/voice/report.cjs.map +1 -1
  269. package/dist/voice/report.d.cts +5 -0
  270. package/dist/voice/report.d.ts +5 -0
  271. package/dist/voice/report.d.ts.map +1 -1
  272. package/dist/voice/report.js +20 -8
  273. package/dist/voice/report.js.map +1 -1
  274. package/dist/voice/report.test.cjs +106 -0
  275. package/dist/voice/report.test.cjs.map +1 -0
  276. package/dist/voice/report.test.js +105 -0
  277. package/dist/voice/report.test.js.map +1 -0
  278. package/dist/voice/room_io/room_io.cjs +5 -39
  279. package/dist/voice/room_io/room_io.cjs.map +1 -1
  280. package/dist/voice/room_io/room_io.d.cts +4 -9
  281. package/dist/voice/room_io/room_io.d.ts +4 -9
  282. package/dist/voice/room_io/room_io.d.ts.map +1 -1
  283. package/dist/voice/room_io/room_io.js +5 -40
  284. package/dist/voice/room_io/room_io.js.map +1 -1
  285. package/dist/voice/turn_config/endpointing.cjs +33 -0
  286. package/dist/voice/turn_config/endpointing.cjs.map +1 -0
  287. package/dist/voice/turn_config/endpointing.d.cts +30 -0
  288. package/dist/voice/turn_config/endpointing.d.ts +30 -0
  289. package/dist/voice/turn_config/endpointing.d.ts.map +1 -0
  290. package/dist/voice/turn_config/endpointing.js +9 -0
  291. package/dist/voice/turn_config/endpointing.js.map +1 -0
  292. package/dist/voice/turn_config/interruption.cjs +37 -0
  293. package/dist/voice/turn_config/interruption.cjs.map +1 -0
  294. package/dist/voice/turn_config/interruption.d.cts +53 -0
  295. package/dist/voice/turn_config/interruption.d.ts +53 -0
  296. package/dist/voice/turn_config/interruption.d.ts.map +1 -0
  297. package/dist/voice/turn_config/interruption.js +13 -0
  298. package/dist/voice/turn_config/interruption.js.map +1 -0
  299. package/dist/voice/turn_config/turn_handling.cjs +35 -0
  300. package/dist/voice/turn_config/turn_handling.cjs.map +1 -0
  301. package/dist/voice/turn_config/turn_handling.d.cts +36 -0
  302. package/dist/voice/turn_config/turn_handling.d.ts +36 -0
  303. package/dist/voice/turn_config/turn_handling.d.ts.map +1 -0
  304. package/dist/voice/turn_config/turn_handling.js +11 -0
  305. package/dist/voice/turn_config/turn_handling.js.map +1 -0
  306. package/dist/voice/turn_config/utils.cjs +97 -0
  307. package/dist/voice/turn_config/utils.cjs.map +1 -0
  308. package/dist/voice/turn_config/utils.d.cts +25 -0
  309. package/dist/voice/turn_config/utils.d.ts +25 -0
  310. package/dist/voice/turn_config/utils.d.ts.map +1 -0
  311. package/dist/voice/turn_config/utils.js +73 -0
  312. package/dist/voice/turn_config/utils.js.map +1 -0
  313. package/dist/voice/turn_config/utils.test.cjs +86 -0
  314. package/dist/voice/turn_config/utils.test.cjs.map +1 -0
  315. package/dist/voice/turn_config/utils.test.js +85 -0
  316. package/dist/voice/turn_config/utils.test.js.map +1 -0
  317. package/dist/voice/wire_format.cjs +798 -0
  318. package/dist/voice/wire_format.cjs.map +1 -0
  319. package/dist/voice/wire_format.d.cts +5503 -0
  320. package/dist/voice/wire_format.d.ts +5503 -0
  321. package/dist/voice/wire_format.d.ts.map +1 -0
  322. package/dist/voice/wire_format.js +728 -0
  323. package/dist/voice/wire_format.js.map +1 -0
  324. package/package.json +2 -1
  325. package/src/constants.ts +13 -0
  326. package/src/inference/interruption/defaults.ts +51 -0
  327. package/src/inference/interruption/errors.ts +25 -0
  328. package/src/inference/interruption/http_transport.ts +187 -0
  329. package/src/inference/interruption/interruption_cache_entry.ts +50 -0
  330. package/src/inference/interruption/interruption_detector.ts +188 -0
  331. package/src/inference/interruption/interruption_stream.ts +467 -0
  332. package/src/inference/interruption/types.ts +84 -0
  333. package/src/inference/interruption/utils.test.ts +132 -0
  334. package/src/inference/interruption/utils.ts +137 -0
  335. package/src/inference/interruption/ws_transport.ts +402 -0
  336. package/src/inference/llm.ts +9 -12
  337. package/src/inference/stt.ts +10 -3
  338. package/src/inference/tts.ts +10 -3
  339. package/src/inference/utils.ts +29 -1
  340. package/src/llm/chat_context.ts +40 -2
  341. package/src/llm/index.ts +1 -0
  342. package/src/llm/llm.ts +16 -0
  343. package/src/llm/realtime.ts +4 -0
  344. package/src/metrics/base.ts +48 -1
  345. package/src/metrics/index.ts +11 -0
  346. package/src/metrics/model_usage.test.ts +545 -0
  347. package/src/metrics/model_usage.ts +262 -0
  348. package/src/metrics/usage_collector.ts +11 -0
  349. package/src/metrics/utils.ts +11 -0
  350. package/src/stream/multi_input_stream.test.ts +6 -1
  351. package/src/stream/stream_channel.ts +34 -2
  352. package/src/stt/stt.ts +38 -0
  353. package/src/telemetry/otel_http_exporter.ts +28 -5
  354. package/src/telemetry/trace_types.ts +11 -8
  355. package/src/telemetry/traces.ts +111 -54
  356. package/src/tts/tts.ts +69 -1
  357. package/src/voice/agent.ts +30 -3
  358. package/src/voice/agent_activity.ts +327 -28
  359. package/src/voice/agent_session.ts +207 -59
  360. package/src/voice/audio_recognition.ts +385 -9
  361. package/src/voice/client_events.ts +838 -0
  362. package/src/voice/events.ts +14 -4
  363. package/src/voice/generation.ts +52 -9
  364. package/src/voice/index.ts +1 -0
  365. package/src/voice/report.test.ts +117 -0
  366. package/src/voice/report.ts +29 -6
  367. package/src/voice/room_io/room_io.ts +7 -61
  368. package/src/voice/turn_config/endpointing.ts +33 -0
  369. package/src/voice/turn_config/interruption.ts +56 -0
  370. package/src/voice/turn_config/turn_handling.ts +45 -0
  371. package/src/voice/turn_config/utils.test.ts +100 -0
  372. package/src/voice/turn_config/utils.ts +103 -0
  373. package/src/voice/wire_format.ts +827 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/voice/wire_format.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n// Explicit wire-format converters that produce the exact JSON shape emitted by\n// Python Pydantic models (snake_case keys, durations in seconds).\n// The agents-playground frontend (types.ts / useClientEvents.ts) consumes this\n// format directly via JSON.parse — any mismatch breaks the UI.\nimport { z } from 'zod';\nimport type {\n AgentHandoffItem,\n AudioContent,\n ChatContent,\n ChatItem,\n ChatMessage,\n FunctionCall,\n FunctionCallOutput,\n ImageContent,\n MetricsReport,\n} from '../llm/chat_context.js';\nimport type {\n AgentMetrics,\n EOUMetrics,\n InterruptionMetrics,\n LLMMetrics,\n MetricsMetadata,\n RealtimeModelMetrics,\n RealtimeModelMetricsCachedTokenDetails,\n RealtimeModelMetricsInputTokenDetails,\n RealtimeModelMetricsOutputTokenDetails,\n STTMetrics,\n TTSMetrics,\n VADMetrics,\n} from '../metrics/base.js';\nimport type {\n InterruptionModelUsage,\n LLMModelUsage,\n ModelUsage,\n STTModelUsage,\n TTSModelUsage,\n} from '../metrics/model_usage.js';\nimport type { AgentSessionUsage } from './agent_session.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\ntype WireObject = Record<string, unknown>;\n\nexport function msToS(ms: number): number {\n return ms / 1000;\n}\n\nfunction omitUndefined(obj: WireObject): WireObject {\n const result: WireObject = {};\n for (const [k, v] of Object.entries(obj)) {\n if (v !== undefined) {\n result[k] = v;\n }\n }\n return result;\n}\n\nfunction imageContentToWire(img: ImageContent): WireObject {\n return omitUndefined({\n id: img.id,\n type: img.type,\n image: typeof img.image === 'string' ? img.image : undefined,\n inference_detail: img.inferenceDetail,\n inference_width: img.inferenceWidth,\n inference_height: img.inferenceHeight,\n mime_type: img.mimeType,\n });\n}\n\nfunction audioContentToWire(audio: AudioContent): WireObject {\n return omitUndefined({\n type: audio.type,\n transcript: audio.transcript,\n });\n}\n\nfunction chatContentToWire(content: ChatContent): unknown {\n if (typeof content === 'string') return content;\n if (content.type === 'image_content') return imageContentToWire(content);\n return audioContentToWire(content);\n}\n\nfunction metricsReportToWire(m: MetricsReport): WireObject {\n return omitUndefined({\n started_speaking_at: m.startedSpeakingAt,\n stopped_speaking_at: m.stoppedSpeakingAt,\n transcription_delay: m.transcriptionDelay,\n end_of_turn_delay: m.endOfTurnDelay,\n on_user_turn_completed_delay: m.onUserTurnCompletedDelay,\n llm_node_ttft: m.llmNodeTtft,\n tts_node_ttfb: m.ttsNodeTtfb,\n e2e_latency: m.e2eLatency,\n });\n}\n\nexport function chatMessageToWire(msg: ChatMessage): WireObject {\n const result: WireObject = {\n id: msg.id,\n type: msg.type,\n role: msg.role,\n content: msg.content.map(chatContentToWire),\n interrupted: msg.interrupted,\n created_at: msToS(msg.createdAt),\n };\n\n if (msg.transcriptConfidence !== undefined) {\n result.transcript_confidence = msg.transcriptConfidence;\n }\n if (Object.keys(msg.metrics).length > 0) {\n result.metrics = metricsReportToWire(msg.metrics);\n }\n if (Object.keys(msg.extra).length > 0) {\n result.extra = msg.extra;\n }\n return result;\n}\n\nexport function functionCallToWire(fc: FunctionCall): WireObject {\n const result: WireObject = {\n id: fc.id,\n type: fc.type,\n call_id: fc.callId,\n arguments: fc.args,\n name: fc.name,\n created_at: msToS(fc.createdAt),\n };\n\n if (Object.keys(fc.extra).length > 0) {\n result.extra = fc.extra;\n }\n if (fc.groupId !== undefined) {\n result.group_id = fc.groupId;\n }\n return result;\n}\n\nexport function functionCallOutputToWire(fco: FunctionCallOutput): WireObject {\n return {\n id: fco.id,\n type: fco.type,\n name: fco.name,\n call_id: fco.callId,\n output: fco.output,\n is_error: fco.isError,\n created_at: msToS(fco.createdAt),\n };\n}\n\nexport function agentHandoffToWire(ah: AgentHandoffItem): WireObject {\n const result: WireObject = {\n id: ah.id,\n type: ah.type,\n new_agent_id: ah.newAgentId,\n created_at: msToS(ah.createdAt),\n };\n if (ah.oldAgentId !== undefined) {\n result.old_agent_id = ah.oldAgentId;\n }\n return result;\n}\n\nexport function chatItemToWire(item: ChatItem): WireObject {\n switch (item.type) {\n case 'message':\n return chatMessageToWire(item);\n case 'function_call':\n return functionCallToWire(item);\n case 'function_call_output':\n return functionCallOutputToWire(item);\n case 'agent_handoff':\n return agentHandoffToWire(item);\n }\n}\n\nfunction metadataToWire(m: MetricsMetadata | undefined): WireObject | null {\n if (!m) return null;\n return omitUndefined({\n model_name: m.modelName,\n model_provider: m.modelProvider,\n });\n}\n\nfunction llmMetricsToWire(m: LLMMetrics): WireObject {\n return omitUndefined({\n type: m.type,\n label: m.label,\n request_id: m.requestId,\n timestamp: msToS(m.timestamp),\n duration: msToS(m.durationMs),\n ttft: msToS(m.ttftMs),\n cancelled: m.cancelled,\n completion_tokens: m.completionTokens,\n prompt_tokens: m.promptTokens,\n prompt_cached_tokens: m.promptCachedTokens,\n total_tokens: m.totalTokens,\n tokens_per_second: m.tokensPerSecond,\n speech_id: m.speechId,\n metadata: metadataToWire(m.metadata),\n });\n}\n\nfunction sttMetricsToWire(m: STTMetrics): WireObject {\n return omitUndefined({\n type: m.type,\n label: m.label,\n request_id: m.requestId,\n timestamp: msToS(m.timestamp),\n duration: msToS(m.durationMs),\n audio_duration: msToS(m.audioDurationMs),\n input_tokens: m.inputTokens,\n output_tokens: m.outputTokens,\n streamed: m.streamed,\n metadata: metadataToWire(m.metadata),\n });\n}\n\nfunction ttsMetricsToWire(m: TTSMetrics): WireObject {\n return omitUndefined({\n type: m.type,\n label: m.label,\n request_id: m.requestId,\n timestamp: msToS(m.timestamp),\n ttfb: msToS(m.ttfbMs),\n duration: msToS(m.durationMs),\n audio_duration: msToS(m.audioDurationMs),\n cancelled: m.cancelled,\n characters_count: m.charactersCount,\n input_tokens: m.inputTokens,\n output_tokens: m.outputTokens,\n streamed: m.streamed,\n segment_id: m.segmentId,\n speech_id: m.speechId,\n metadata: metadataToWire(m.metadata),\n });\n}\n\nfunction vadMetricsToWire(m: VADMetrics): WireObject {\n return {\n type: m.type,\n label: m.label,\n timestamp: msToS(m.timestamp),\n idle_time: msToS(m.idleTimeMs),\n inference_duration_total: msToS(m.inferenceDurationTotalMs),\n inference_count: m.inferenceCount,\n };\n}\n\nfunction eouMetricsToWire(m: EOUMetrics): WireObject {\n return omitUndefined({\n type: m.type,\n timestamp: msToS(m.timestamp),\n end_of_utterance_delay: msToS(m.endOfUtteranceDelayMs),\n transcription_delay: msToS(m.transcriptionDelayMs),\n on_user_turn_completed_delay: msToS(m.onUserTurnCompletedDelayMs),\n speech_id: m.speechId,\n });\n}\n\nfunction cachedTokenDetailsToWire(d: RealtimeModelMetricsCachedTokenDetails): WireObject {\n return {\n audio_tokens: d.audioTokens,\n text_tokens: d.textTokens,\n image_tokens: d.imageTokens,\n };\n}\n\nfunction inputTokenDetailsToWire(d: RealtimeModelMetricsInputTokenDetails): WireObject {\n return omitUndefined({\n audio_tokens: d.audioTokens,\n text_tokens: d.textTokens,\n image_tokens: d.imageTokens,\n cached_tokens: d.cachedTokens,\n cached_tokens_details: d.cachedTokensDetails\n ? cachedTokenDetailsToWire(d.cachedTokensDetails)\n : undefined,\n });\n}\n\nfunction outputTokenDetailsToWire(d: RealtimeModelMetricsOutputTokenDetails): WireObject {\n return {\n text_tokens: d.textTokens,\n audio_tokens: d.audioTokens,\n image_tokens: d.imageTokens,\n };\n}\n\nfunction realtimeModelMetricsToWire(m: RealtimeModelMetrics): WireObject {\n return omitUndefined({\n type: m.type,\n label: m.label,\n request_id: m.requestId,\n timestamp: msToS(m.timestamp),\n duration: msToS(m.durationMs),\n session_duration: m.sessionDurationMs !== undefined ? msToS(m.sessionDurationMs) : undefined,\n ttft: msToS(m.ttftMs),\n cancelled: m.cancelled,\n input_tokens: m.inputTokens,\n output_tokens: m.outputTokens,\n total_tokens: m.totalTokens,\n tokens_per_second: m.tokensPerSecond,\n input_token_details: inputTokenDetailsToWire(m.inputTokenDetails),\n output_token_details: outputTokenDetailsToWire(m.outputTokenDetails),\n metadata: metadataToWire(m.metadata),\n });\n}\n\nfunction interruptionMetricsToWire(m: InterruptionMetrics): WireObject {\n return omitUndefined({\n type: m.type,\n timestamp: msToS(m.timestamp),\n total_duration: msToS(m.totalDuration),\n prediction_duration: msToS(m.predictionDuration),\n detection_delay: msToS(m.detectionDelay),\n num_interruptions: m.numInterruptions,\n num_backchannels: m.numBackchannels,\n num_requests: m.numRequests,\n metadata: metadataToWire(m.metadata),\n });\n}\n\nexport function agentMetricsToWire(m: AgentMetrics): WireObject {\n switch (m.type) {\n case 'llm_metrics':\n return llmMetricsToWire(m);\n case 'stt_metrics':\n return sttMetricsToWire(m);\n case 'tts_metrics':\n return ttsMetricsToWire(m);\n case 'vad_metrics':\n return vadMetricsToWire(m);\n case 'eou_metrics':\n return eouMetricsToWire(m);\n case 'realtime_model_metrics':\n return realtimeModelMetricsToWire(m);\n case 'interruption_metrics':\n return interruptionMetricsToWire(m);\n }\n}\n\nfunction llmModelUsageToWire(u: Partial<LLMModelUsage>): WireObject {\n return {\n type: u.type,\n provider: u.provider ?? '',\n model: u.model ?? '',\n input_tokens: u.inputTokens ?? 0,\n input_cached_tokens: u.inputCachedTokens ?? 0,\n input_audio_tokens: u.inputAudioTokens ?? 0,\n input_cached_audio_tokens: u.inputCachedAudioTokens ?? 0,\n input_text_tokens: u.inputTextTokens ?? 0,\n input_cached_text_tokens: u.inputCachedTextTokens ?? 0,\n input_image_tokens: u.inputImageTokens ?? 0,\n input_cached_image_tokens: u.inputCachedImageTokens ?? 0,\n output_tokens: u.outputTokens ?? 0,\n output_audio_tokens: u.outputAudioTokens ?? 0,\n output_text_tokens: u.outputTextTokens ?? 0,\n session_duration: msToS(u.sessionDurationMs ?? 0),\n };\n}\n\nfunction ttsModelUsageToWire(u: Partial<TTSModelUsage>): WireObject {\n return {\n type: u.type,\n provider: u.provider ?? '',\n model: u.model ?? '',\n input_tokens: u.inputTokens ?? 0,\n output_tokens: u.outputTokens ?? 0,\n characters_count: u.charactersCount ?? 0,\n audio_duration: msToS(u.audioDurationMs ?? 0),\n };\n}\n\nfunction sttModelUsageToWire(u: Partial<STTModelUsage>): WireObject {\n return {\n type: u.type,\n provider: u.provider ?? '',\n model: u.model ?? '',\n input_tokens: u.inputTokens ?? 0,\n output_tokens: u.outputTokens ?? 0,\n audio_duration: msToS(u.audioDurationMs ?? 0),\n };\n}\n\nfunction interruptionModelUsageToWire(u: Partial<InterruptionModelUsage>): WireObject {\n return {\n type: u.type,\n provider: u.provider ?? '',\n model: u.model ?? '',\n total_requests: u.totalRequests ?? 0,\n };\n}\n\nexport function modelUsageToWire(u: Partial<ModelUsage>): WireObject {\n switch (u.type) {\n case 'llm_usage':\n return llmModelUsageToWire(u as Partial<LLMModelUsage>);\n case 'tts_usage':\n return ttsModelUsageToWire(u as Partial<TTSModelUsage>);\n case 'stt_usage':\n return sttModelUsageToWire(u as Partial<STTModelUsage>);\n case 'interruption_usage':\n return interruptionModelUsageToWire(u as Partial<InterruptionModelUsage>);\n default:\n return u as WireObject;\n }\n}\n\nexport function agentSessionUsageToWire(u: AgentSessionUsage): WireObject {\n return {\n model_usage: u.modelUsage.map(modelUsageToWire),\n };\n}\n\n// ===========================================================================\n// Zod wire-format schemas\n// These validate the exact JSON shape that Python Pydantic emits on the wire.\n// Inferred types via z.infer give fully typed parse results.\n// ===========================================================================\nconst imageContentWireSchema = z.object({\n id: z.string(),\n type: z.literal('image_content'),\n image: z.string(),\n inference_detail: z.enum(['auto', 'high', 'low']).optional(),\n inference_width: z.number().optional(),\n inference_height: z.number().optional(),\n mime_type: z.string().optional(),\n});\n\nconst audioContentWireSchema = z.object({\n type: z.literal('audio_content'),\n transcript: z.string().nullable().optional(),\n});\n\nconst chatContentWireSchema = z.union([z.string(), imageContentWireSchema, audioContentWireSchema]);\n\nconst metricsReportWireSchema = z\n .object({\n started_speaking_at: z.number().optional(),\n stopped_speaking_at: z.number().optional(),\n transcription_delay: z.number().optional(),\n end_of_turn_delay: z.number().optional(),\n on_user_turn_completed_delay: z.number().optional(),\n llm_node_ttft: z.number().optional(),\n tts_node_ttfb: z.number().optional(),\n e2e_latency: z.number().optional(),\n })\n .optional();\n\nexport const chatMessageWireSchema = z.object({\n id: z.string(),\n type: z.literal('message'),\n role: z.enum(['developer', 'system', 'user', 'assistant']),\n content: z.array(chatContentWireSchema),\n interrupted: z.boolean(),\n created_at: z.number(),\n transcript_confidence: z.number().optional(),\n metrics: metricsReportWireSchema,\n extra: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport const functionCallWireSchema = z.object({\n id: z.string(),\n type: z.literal('function_call'),\n call_id: z.string(),\n arguments: z.string(),\n name: z.string(),\n created_at: z.number(),\n extra: z.record(z.string(), z.unknown()).optional(),\n group_id: z.string().optional(),\n});\n\nexport const functionCallOutputWireSchema = z.object({\n id: z.string(),\n type: z.literal('function_call_output'),\n name: z.string(),\n call_id: z.string(),\n output: z.string(),\n is_error: z.boolean(),\n created_at: z.number(),\n});\n\nexport const agentHandoffWireSchema = z.object({\n id: z.string(),\n type: z.literal('agent_handoff'),\n new_agent_id: z.string(),\n created_at: z.number(),\n old_agent_id: z.string().optional(),\n});\n\nexport const chatItemWireSchema = z.discriminatedUnion('type', [\n chatMessageWireSchema,\n functionCallWireSchema,\n functionCallOutputWireSchema,\n agentHandoffWireSchema,\n]);\n\nconst metadataWireSchema = z\n .object({\n model_name: z.string().optional(),\n model_provider: z.string().optional(),\n })\n .nullable()\n .optional();\n\nexport const llmMetricsWireSchema = z.object({\n type: z.literal('llm_metrics'),\n label: z.string(),\n request_id: z.string(),\n timestamp: z.number(),\n duration: z.number(),\n ttft: z.number(),\n cancelled: z.boolean(),\n completion_tokens: z.number(),\n prompt_tokens: z.number(),\n prompt_cached_tokens: z.number(),\n total_tokens: z.number(),\n tokens_per_second: z.number(),\n speech_id: z.string().nullable().optional(),\n metadata: metadataWireSchema,\n});\n\nexport const sttMetricsWireSchema = z.object({\n type: z.literal('stt_metrics'),\n label: z.string(),\n request_id: z.string(),\n timestamp: z.number(),\n duration: z.number(),\n audio_duration: z.number(),\n input_tokens: z.number().optional(),\n output_tokens: z.number().optional(),\n streamed: z.boolean(),\n metadata: metadataWireSchema,\n});\n\nexport const ttsMetricsWireSchema = z.object({\n type: z.literal('tts_metrics'),\n label: z.string(),\n request_id: z.string(),\n timestamp: z.number(),\n ttfb: z.number(),\n duration: z.number(),\n audio_duration: z.number(),\n cancelled: z.boolean(),\n characters_count: z.number(),\n input_tokens: z.number().optional(),\n output_tokens: z.number().optional(),\n streamed: z.boolean(),\n segment_id: z.string().nullable().optional(),\n speech_id: z.string().nullable().optional(),\n metadata: metadataWireSchema,\n});\n\nexport const vadMetricsWireSchema = z.object({\n type: z.literal('vad_metrics'),\n label: z.string(),\n timestamp: z.number(),\n idle_time: z.number(),\n inference_duration_total: z.number(),\n inference_count: z.number(),\n});\n\nexport const eouMetricsWireSchema = z.object({\n type: z.literal('eou_metrics'),\n timestamp: z.number(),\n end_of_utterance_delay: z.number(),\n transcription_delay: z.number(),\n on_user_turn_completed_delay: z.number(),\n speech_id: z.string().nullable().optional(),\n});\n\nconst cachedTokenDetailsWireSchema = z.object({\n audio_tokens: z.number(),\n text_tokens: z.number(),\n image_tokens: z.number(),\n});\n\nconst inputTokenDetailsWireSchema = z.object({\n audio_tokens: z.number(),\n text_tokens: z.number(),\n image_tokens: z.number(),\n cached_tokens: z.number(),\n cached_tokens_details: cachedTokenDetailsWireSchema.nullable().optional(),\n});\n\nconst outputTokenDetailsWireSchema = z.object({\n text_tokens: z.number(),\n audio_tokens: z.number(),\n image_tokens: z.number(),\n});\n\nexport const realtimeModelMetricsWireSchema = z.object({\n type: z.literal('realtime_model_metrics'),\n label: z.string(),\n request_id: z.string(),\n timestamp: z.number(),\n duration: z.number(),\n session_duration: z.number().optional(),\n ttft: z.number(),\n cancelled: z.boolean(),\n input_tokens: z.number(),\n output_tokens: z.number(),\n total_tokens: z.number(),\n tokens_per_second: z.number(),\n input_token_details: inputTokenDetailsWireSchema,\n output_token_details: outputTokenDetailsWireSchema,\n metadata: metadataWireSchema,\n});\n\nexport const interruptionMetricsWireSchema = z.object({\n type: z.literal('interruption_metrics'),\n timestamp: z.number(),\n total_duration: z.number(),\n prediction_duration: z.number(),\n detection_delay: z.number(),\n num_interruptions: z.number(),\n num_backchannels: z.number(),\n num_requests: z.number(),\n metadata: metadataWireSchema,\n});\n\nexport const agentMetricsWireSchema = z.discriminatedUnion('type', [\n llmMetricsWireSchema,\n sttMetricsWireSchema,\n ttsMetricsWireSchema,\n vadMetricsWireSchema,\n eouMetricsWireSchema,\n realtimeModelMetricsWireSchema,\n interruptionMetricsWireSchema,\n]);\n\n// ---------------------------------------------------------------------------\n// Model usage schemas\n// ---------------------------------------------------------------------------\n\nexport const llmModelUsageWireSchema = z.object({\n type: z.literal('llm_usage'),\n provider: z.string().optional(),\n model: z.string().optional(),\n input_tokens: z.number().optional(),\n input_cached_tokens: z.number().optional(),\n input_audio_tokens: z.number().optional(),\n input_cached_audio_tokens: z.number().optional(),\n input_text_tokens: z.number().optional(),\n input_cached_text_tokens: z.number().optional(),\n input_image_tokens: z.number().optional(),\n input_cached_image_tokens: z.number().optional(),\n output_tokens: z.number().optional(),\n output_audio_tokens: z.number().optional(),\n output_text_tokens: z.number().optional(),\n session_duration: z.number().optional(),\n});\n\nexport const ttsModelUsageWireSchema = z.object({\n type: z.literal('tts_usage'),\n provider: z.string().optional(),\n model: z.string().optional(),\n input_tokens: z.number().optional(),\n output_tokens: z.number().optional(),\n characters_count: z.number().optional(),\n audio_duration: z.number().optional(),\n});\n\nexport const sttModelUsageWireSchema = z.object({\n type: z.literal('stt_usage'),\n provider: z.string().optional(),\n model: z.string().optional(),\n input_tokens: z.number().optional(),\n output_tokens: z.number().optional(),\n audio_duration: z.number().optional(),\n});\n\nexport const interruptionModelUsageWireSchema = z.object({\n type: z.literal('interruption_usage'),\n provider: z.string().optional(),\n model: z.string().optional(),\n total_requests: z.number().optional(),\n});\n\nexport const modelUsageWireSchema = z.discriminatedUnion('type', [\n llmModelUsageWireSchema,\n ttsModelUsageWireSchema,\n sttModelUsageWireSchema,\n interruptionModelUsageWireSchema,\n]);\n\nexport const agentSessionUsageWireSchema = z.object({\n model_usage: z.array(modelUsageWireSchema),\n});\n\n// ---------------------------------------------------------------------------\n// Client event schemas\n// ---------------------------------------------------------------------------\n\nconst agentStateSchema = z.enum(['initializing', 'idle', 'listening', 'thinking', 'speaking']);\nconst userStateSchema = z.enum(['speaking', 'listening', 'away']);\n\nexport const clientAgentStateChangedSchema = z.object({\n type: z.literal('agent_state_changed'),\n old_state: agentStateSchema,\n new_state: agentStateSchema,\n created_at: z.number(),\n});\n\nexport const clientUserStateChangedSchema = z.object({\n type: z.literal('user_state_changed'),\n old_state: userStateSchema,\n new_state: userStateSchema,\n created_at: z.number(),\n});\n\nexport const clientConversationItemAddedSchema = z.object({\n type: z.literal('conversation_item_added'),\n item: chatMessageWireSchema,\n created_at: z.number(),\n});\n\nexport const clientUserInputTranscribedSchema = z.object({\n type: z.literal('user_input_transcribed'),\n transcript: z.string(),\n is_final: z.boolean(),\n language: z.string().nullable(),\n created_at: z.number(),\n});\n\nexport const clientFunctionToolsExecutedSchema = z.object({\n type: z.literal('function_tools_executed'),\n function_calls: z.array(functionCallWireSchema),\n function_call_outputs: z.array(functionCallOutputWireSchema.nullable()),\n created_at: z.number(),\n});\n\nexport const clientMetricsCollectedSchema = z.object({\n type: z.literal('metrics_collected'),\n metrics: agentMetricsWireSchema,\n created_at: z.number(),\n});\n\nexport const clientErrorSchema = z.object({\n type: z.literal('error'),\n message: z.string(),\n created_at: z.number(),\n});\n\nexport const clientUserOverlappingSpeechSchema = z.object({\n type: z.literal('user_overlapping_speech'),\n is_interruption: z.boolean(),\n created_at: z.number(),\n sent_at: z.number(),\n detection_delay: z.number(),\n overlap_started_at: z.number().nullable(),\n});\n\nexport const clientSessionUsageSchema = z.object({\n type: z.literal('session_usage'),\n usage: agentSessionUsageWireSchema,\n created_at: z.number(),\n});\n\nexport const clientEventSchema = z.discriminatedUnion('type', [\n clientAgentStateChangedSchema,\n clientUserStateChangedSchema,\n clientConversationItemAddedSchema,\n clientUserInputTranscribedSchema,\n clientFunctionToolsExecutedSchema,\n clientMetricsCollectedSchema,\n clientErrorSchema,\n clientUserOverlappingSpeechSchema,\n clientSessionUsageSchema,\n]);\n\n// ---------------------------------------------------------------------------\n// RPC schemas\n// ---------------------------------------------------------------------------\n\nexport const sendMessageRequestSchema = z.object({\n text: z.string(),\n});\n\nexport const streamRequestSchema = z.object({\n request_id: z.string(),\n method: z.string(),\n payload: z.string(),\n});\n\nexport const streamResponseSchema = z.object({\n request_id: z.string(),\n payload: z.string(),\n error: z.string().nullable().optional(),\n});\n\nexport const getSessionStateResponseSchema = z.object({\n agent_state: agentStateSchema,\n user_state: userStateSchema,\n agent_id: z.string(),\n options: z.record(z.string(), z.unknown()),\n created_at: z.number(),\n});\n\nexport const getChatHistoryResponseSchema = z.object({\n items: z.array(chatItemWireSchema),\n});\n\nexport const getAgentInfoResponseSchema = z.object({\n id: z.string(),\n instructions: z.string().nullable(),\n tools: z.array(z.string()),\n chat_ctx: z.array(chatItemWireSchema),\n});\n\nexport const sendMessageResponseSchema = z.object({\n items: z.array(chatItemWireSchema),\n});\n\nexport const getRTCStatsResponseSchema = z.object({\n publisher_stats: z.array(z.record(z.string(), z.unknown())),\n subscriber_stats: z.array(z.record(z.string(), z.unknown())),\n});\n\nexport const getSessionUsageResponseSchema = z.object({\n usage: agentSessionUsageWireSchema,\n created_at: z.number(),\n});\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livekit/agents",
3
- "version": "1.0.48",
3
+ "version": "1.1.0-dev.0",
4
4
  "description": "LiveKit Agents - Node.js",
5
5
  "main": "dist/index.js",
6
6
  "require": "dist/index.cjs",
@@ -60,6 +60,7 @@
60
60
  "heap-js": "^2.6.0",
61
61
  "json-schema": "^0.4.0",
62
62
  "livekit-server-sdk": "^2.14.1",
63
+ "ofetch": "^1.5.1",
63
64
  "openai": "^6.8.1",
64
65
  "pidusage": "^4.0.1",
65
66
  "pino": "^8.19.0",
package/src/constants.ts CHANGED
@@ -7,3 +7,16 @@ export const TOPIC_TRANSCRIPTION = 'lk.transcription';
7
7
  export const ATTRIBUTE_TRANSCRIPTION_SEGMENT_ID = 'lk.segment_id';
8
8
  export const ATTRIBUTE_PUBLISH_ON_BEHALF = 'lk.publish_on_behalf';
9
9
  export const TOPIC_CHAT = 'lk.chat';
10
+
11
+ export const ATTRIBUTE_AGENT_STATE = 'lk.agent.state';
12
+ export const ATTRIBUTE_AGENT_NAME = 'lk.agent.name';
13
+
14
+ // TODO(eval): export const ATTRIBUTE_SIMULATOR = 'lk.simulator';
15
+
16
+ export const TOPIC_CLIENT_EVENTS = 'lk.agent.events';
17
+ export const RPC_GET_SESSION_STATE = 'lk.agent.get_session_state';
18
+ export const RPC_GET_CHAT_HISTORY = 'lk.agent.get_chat_history';
19
+ export const RPC_GET_AGENT_INFO = 'lk.agent.get_agent_info';
20
+ export const RPC_SEND_MESSAGE = 'lk.agent.send_message';
21
+ export const TOPIC_AGENT_REQUEST = 'lk.agent.request';
22
+ export const TOPIC_AGENT_RESPONSE = 'lk.agent.response';
@@ -0,0 +1,51 @@
1
+ // SPDX-FileCopyrightText: 2026 LiveKit, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import type { ApiConnectOptions } from './interruption_stream.js';
5
+ import type { InterruptionOptions } from './types.js';
6
+
7
+ export const MIN_INTERRUPTION_DURATION_IN_S = 0.025 * 2; // 25ms per frame, 2 consecutive frames
8
+ export const THRESHOLD = 0.5;
9
+ export const MAX_AUDIO_DURATION_IN_S = 3.0;
10
+ export const AUDIO_PREFIX_DURATION_IN_S = 0.5;
11
+ export const DETECTION_INTERVAL_IN_S = 0.1;
12
+ export const REMOTE_INFERENCE_TIMEOUT_IN_S = 1.0;
13
+ export const SAMPLE_RATE = 16000;
14
+ export const FRAMES_PER_SECOND = 40;
15
+ export const FRAME_DURATION_IN_S = 0.025; // 25ms per frame
16
+
17
+ export const apiConnectDefaults: ApiConnectOptions = {
18
+ maxRetries: 3,
19
+ retryInterval: 2_000,
20
+ timeout: 10_000,
21
+ } as const;
22
+
23
+ /**
24
+ * Calculate the retry interval using exponential backoff with jitter.
25
+ * Matches the Python implementation's _interval_for_retry behavior.
26
+ */
27
+ export function intervalForRetry(
28
+ attempt: number,
29
+ baseInterval: number = apiConnectDefaults.retryInterval,
30
+ ): number {
31
+ // Exponential backoff: baseInterval * 2^attempt with some jitter
32
+ const exponentialDelay = baseInterval * Math.pow(2, attempt);
33
+ // Add jitter (0-25% of the delay)
34
+ const jitter = exponentialDelay * Math.random() * 0.25;
35
+ return exponentialDelay + jitter;
36
+ }
37
+
38
+ // baseUrl and useProxy are resolved dynamically in the constructor
39
+ // to respect LIVEKIT_REMOTE_EOT_URL environment variable
40
+ export const interruptionOptionDefaults: Omit<InterruptionOptions, 'baseUrl' | 'useProxy'> = {
41
+ sampleRate: SAMPLE_RATE,
42
+ threshold: THRESHOLD,
43
+ minFrames: Math.ceil(MIN_INTERRUPTION_DURATION_IN_S * FRAMES_PER_SECOND),
44
+ maxAudioDurationInS: MAX_AUDIO_DURATION_IN_S,
45
+ audioPrefixDurationInS: AUDIO_PREFIX_DURATION_IN_S,
46
+ detectionIntervalInS: DETECTION_INTERVAL_IN_S,
47
+ inferenceTimeout: REMOTE_INFERENCE_TIMEOUT_IN_S * 1_000,
48
+ apiKey: process.env.LIVEKIT_API_KEY || '',
49
+ apiSecret: process.env.LIVEKIT_API_SECRET || '',
50
+ minInterruptionDurationInS: MIN_INTERRUPTION_DURATION_IN_S,
51
+ } as const;
@@ -0,0 +1,25 @@
1
+ // SPDX-FileCopyrightText: 2026 LiveKit, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ /**
5
+ * Error thrown during interruption detection.
6
+ */
7
+ export class InterruptionDetectionError extends Error {
8
+ readonly type = 'interruption_detection_error' as const;
9
+
10
+ readonly timestamp: number;
11
+ readonly label: string;
12
+ readonly recoverable: boolean;
13
+
14
+ constructor(message: string, timestamp: number, label: string, recoverable: boolean) {
15
+ super(message);
16
+ this.name = 'InterruptionDetectionError';
17
+ this.timestamp = timestamp;
18
+ this.label = label;
19
+ this.recoverable = recoverable;
20
+ }
21
+
22
+ toString(): string {
23
+ return `${this.name}: ${this.message} (label=${this.label}, timestamp=${this.timestamp}, recoverable=${this.recoverable})`;
24
+ }
25
+ }
@@ -0,0 +1,187 @@
1
+ // SPDX-FileCopyrightText: 2026 LiveKit, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import { ofetch } from 'ofetch';
5
+ import { TransformStream } from 'stream/web';
6
+ import { z } from 'zod';
7
+ import { log } from '../../log.js';
8
+ import { createAccessToken } from '../utils.js';
9
+ import { intervalForRetry } from './defaults.js';
10
+ import { InterruptionCacheEntry } from './interruption_cache_entry.js';
11
+ import type { OverlappingSpeechEvent } from './types.js';
12
+ import type { BoundedCache } from './utils.js';
13
+
14
+ export interface PostOptions {
15
+ baseUrl: string;
16
+ token: string;
17
+ signal?: AbortSignal;
18
+ timeout?: number;
19
+ maxRetries?: number;
20
+ }
21
+
22
+ export interface PredictOptions {
23
+ threshold: number;
24
+ minFrames: number;
25
+ }
26
+
27
+ export const predictEndpointResponseSchema = z.object({
28
+ created_at: z.number(),
29
+ is_bargein: z.boolean(),
30
+ probabilities: z.array(z.number()),
31
+ });
32
+
33
+ export type PredictEndpointResponse = z.infer<typeof predictEndpointResponseSchema>;
34
+
35
+ export interface PredictResponse {
36
+ createdAt: number;
37
+ isBargein: boolean;
38
+ probabilities: number[];
39
+ predictionDurationInS: number;
40
+ }
41
+
42
+ export async function predictHTTP(
43
+ data: Int16Array,
44
+ predictOptions: PredictOptions,
45
+ options: PostOptions,
46
+ ): Promise<PredictResponse> {
47
+ const createdAt = performance.now();
48
+ const url = new URL(`/bargein`, options.baseUrl);
49
+ url.searchParams.append('threshold', predictOptions.threshold.toString());
50
+ url.searchParams.append('min_frames', predictOptions.minFrames.toFixed());
51
+ url.searchParams.append('created_at', createdAt.toFixed());
52
+
53
+ let retryCount = 0;
54
+ const response = await ofetch(url.toString(), {
55
+ retry: options.maxRetries ?? 3,
56
+ retryDelay: () => {
57
+ const delay = intervalForRetry(retryCount);
58
+ retryCount++;
59
+ return delay;
60
+ },
61
+ headers: {
62
+ 'Content-Type': 'application/octet-stream',
63
+ Authorization: `Bearer ${options.token}`,
64
+ },
65
+ signal: options.signal,
66
+ timeout: options.timeout,
67
+ method: 'POST',
68
+ body: data,
69
+ });
70
+ const { created_at, is_bargein, probabilities } = predictEndpointResponseSchema.parse(response);
71
+
72
+ return {
73
+ createdAt: created_at,
74
+ isBargein: is_bargein,
75
+ probabilities,
76
+ predictionDurationInS: (performance.now() - createdAt) / 1000,
77
+ };
78
+ }
79
+
80
+ export interface HttpTransportOptions {
81
+ baseUrl: string;
82
+ apiKey: string;
83
+ apiSecret: string;
84
+ threshold: number;
85
+ minFrames: number;
86
+ timeout: number;
87
+ maxRetries?: number;
88
+ }
89
+
90
+ export interface HttpTransportState {
91
+ overlapSpeechStarted: boolean;
92
+ overlapSpeechStartedAt: number | undefined;
93
+ cache: BoundedCache<number, InterruptionCacheEntry>;
94
+ }
95
+
96
+ /**
97
+ * Creates an HTTP transport TransformStream for interruption detection.
98
+ *
99
+ * This transport receives Int16Array audio slices and outputs InterruptionEvents.
100
+ * Each audio slice triggers an HTTP POST request.
101
+ *
102
+ * @param options - Transport options object. This is read on each request, so mutations
103
+ * to threshold/minFrames will be picked up dynamically.
104
+ */
105
+ export function createHttpTransport(
106
+ options: HttpTransportOptions,
107
+ getState: () => HttpTransportState,
108
+ setState: (partial: Partial<HttpTransportState>) => void,
109
+ updateUserSpeakingSpan?: (entry: InterruptionCacheEntry) => void,
110
+ getAndResetNumRequests?: () => number,
111
+ ): TransformStream<Int16Array | OverlappingSpeechEvent, OverlappingSpeechEvent> {
112
+ const logger = log();
113
+
114
+ return new TransformStream<Int16Array | OverlappingSpeechEvent, OverlappingSpeechEvent>(
115
+ {
116
+ async transform(chunk, controller) {
117
+ if (!(chunk instanceof Int16Array)) {
118
+ controller.enqueue(chunk);
119
+ return;
120
+ }
121
+
122
+ const state = getState();
123
+ const overlapSpeechStartedAt = state.overlapSpeechStartedAt;
124
+ if (overlapSpeechStartedAt === undefined || !state.overlapSpeechStarted) return;
125
+
126
+ try {
127
+ const resp = await predictHTTP(
128
+ chunk,
129
+ { threshold: options.threshold, minFrames: options.minFrames },
130
+ {
131
+ baseUrl: options.baseUrl,
132
+ timeout: options.timeout,
133
+ maxRetries: options.maxRetries,
134
+ token: await createAccessToken(options.apiKey, options.apiSecret),
135
+ },
136
+ );
137
+
138
+ const { createdAt, isBargein, probabilities, predictionDurationInS } = resp;
139
+ const entry = state.cache.setOrUpdate(
140
+ createdAt,
141
+ () => new InterruptionCacheEntry({ createdAt }),
142
+ {
143
+ probabilities,
144
+ isInterruption: isBargein,
145
+ speechInput: chunk,
146
+ totalDurationInS: (performance.now() - createdAt) / 1000,
147
+ detectionDelayInS: (Date.now() - overlapSpeechStartedAt) / 1000,
148
+ predictionDurationInS,
149
+ },
150
+ );
151
+
152
+ if (state.overlapSpeechStarted && entry.isInterruption) {
153
+ if (updateUserSpeakingSpan) {
154
+ updateUserSpeakingSpan(entry);
155
+ }
156
+ const event: OverlappingSpeechEvent = {
157
+ type: 'user_overlapping_speech',
158
+ timestamp: Date.now(),
159
+ overlapStartedAt: overlapSpeechStartedAt,
160
+ isInterruption: entry.isInterruption,
161
+ speechInput: entry.speechInput,
162
+ probabilities: entry.probabilities,
163
+ totalDurationInS: entry.totalDurationInS,
164
+ predictionDurationInS: entry.predictionDurationInS,
165
+ detectionDelayInS: entry.detectionDelayInS,
166
+ probability: entry.probability,
167
+ numRequests: getAndResetNumRequests?.() ?? 0,
168
+ };
169
+ logger.debug(
170
+ {
171
+ detectionDelayInS: entry.detectionDelayInS,
172
+ totalDurationInS: entry.totalDurationInS,
173
+ },
174
+ 'interruption detected',
175
+ );
176
+ setState({ overlapSpeechStarted: false });
177
+ controller.enqueue(event);
178
+ }
179
+ } catch (err) {
180
+ logger.error({ err }, 'Failed to send audio data over HTTP');
181
+ }
182
+ },
183
+ },
184
+ { highWaterMark: 2 },
185
+ { highWaterMark: 2 },
186
+ );
187
+ }
@@ -0,0 +1,50 @@
1
+ // SPDX-FileCopyrightText: 2026 LiveKit, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import { estimateProbability } from './utils.js';
5
+
6
+ /**
7
+ * Typed cache entry for interruption inference results.
8
+ * Mutable to support setOrUpdate pattern from Python's _BoundedCache.
9
+ */
10
+ export class InterruptionCacheEntry {
11
+ createdAt: number;
12
+ requestStartedAt?: number;
13
+ totalDurationInS: number;
14
+ predictionDurationInS: number;
15
+ detectionDelayInS: number;
16
+ speechInput?: Int16Array;
17
+ probabilities?: number[];
18
+ isInterruption?: boolean;
19
+
20
+ constructor(params: {
21
+ createdAt: number;
22
+ requestStartedAt?: number;
23
+ speechInput?: Int16Array;
24
+ totalDurationInS?: number;
25
+ predictionDurationInS?: number;
26
+ detectionDelayInS?: number;
27
+ probabilities?: number[];
28
+ isInterruption?: boolean;
29
+ }) {
30
+ this.createdAt = params.createdAt;
31
+ this.requestStartedAt = params.requestStartedAt;
32
+ this.totalDurationInS = params.totalDurationInS ?? 0;
33
+ this.predictionDurationInS = params.predictionDurationInS ?? 0;
34
+ this.detectionDelayInS = params.detectionDelayInS ?? 0;
35
+ this.speechInput = params.speechInput;
36
+ this.probabilities = params.probabilities;
37
+ this.isInterruption = params.isInterruption;
38
+ }
39
+
40
+ /**
41
+ * The conservative estimated probability of the interruption event.
42
+ */
43
+ get probability(): number {
44
+ return this.probabilities ? estimateProbability(this.probabilities) : 0;
45
+ }
46
+
47
+ static default(): InterruptionCacheEntry {
48
+ return new InterruptionCacheEntry({ createdAt: 0 });
49
+ }
50
+ }
@@ -0,0 +1,188 @@
1
+ // SPDX-FileCopyrightText: 2026 LiveKit, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import type { TypedEventEmitter } from '@livekit/typed-emitter';
5
+ import EventEmitter from 'events';
6
+ import { log } from '../../log.js';
7
+ import type { InterruptionMetrics } from '../../metrics/base.js';
8
+ import { DEFAULT_INFERENCE_URL, STAGING_INFERENCE_URL, getDefaultInferenceUrl } from '../utils.js';
9
+ import { FRAMES_PER_SECOND, SAMPLE_RATE, interruptionOptionDefaults } from './defaults.js';
10
+ import type { InterruptionDetectionError } from './errors.js';
11
+ import { InterruptionStreamBase } from './interruption_stream.js';
12
+ import type { InterruptionOptions, OverlappingSpeechEvent } from './types.js';
13
+
14
+ type InterruptionCallbacks = {
15
+ user_overlapping_speech: (event: OverlappingSpeechEvent) => void;
16
+ metrics_collected: (metrics: InterruptionMetrics) => void;
17
+ error: (error: InterruptionDetectionError) => void;
18
+ };
19
+
20
+ export type AdaptiveInterruptionDetectorOptions = Omit<Partial<InterruptionOptions>, 'useProxy'>;
21
+
22
+ export class AdaptiveInterruptionDetector extends (EventEmitter as new () => TypedEventEmitter<InterruptionCallbacks>) {
23
+ options: InterruptionOptions;
24
+ private readonly _label: string;
25
+ private logger = log();
26
+ // Use Set instead of WeakSet to allow iteration for propagating option updates
27
+ private streams: Set<InterruptionStreamBase> = new Set();
28
+
29
+ constructor(options: AdaptiveInterruptionDetectorOptions = {}) {
30
+ super();
31
+
32
+ const {
33
+ maxAudioDurationInS,
34
+ baseUrl,
35
+ apiKey,
36
+ apiSecret,
37
+ audioPrefixDurationInS,
38
+ threshold,
39
+ detectionIntervalInS,
40
+ inferenceTimeout,
41
+ minInterruptionDurationInS,
42
+ } = { ...interruptionOptionDefaults, ...options };
43
+
44
+ if (maxAudioDurationInS > 3.0) {
45
+ throw new RangeError('maxAudioDurationInS must be less than or equal to 3.0 seconds');
46
+ }
47
+
48
+ const lkBaseUrl = baseUrl ?? process.env.LIVEKIT_REMOTE_EOT_URL ?? getDefaultInferenceUrl();
49
+ let lkApiKey = apiKey ?? '';
50
+ let lkApiSecret = apiSecret ?? '';
51
+ let useProxy: boolean;
52
+
53
+ // Use LiveKit credentials if using the inference service (production or staging)
54
+ const isInferenceUrl =
55
+ lkBaseUrl === DEFAULT_INFERENCE_URL || lkBaseUrl === STAGING_INFERENCE_URL;
56
+ if (isInferenceUrl) {
57
+ lkApiKey =
58
+ apiKey ?? process.env.LIVEKIT_INFERENCE_API_KEY ?? process.env.LIVEKIT_API_KEY ?? '';
59
+ if (!lkApiKey) {
60
+ throw new TypeError(
61
+ 'apiKey is required, either as argument or set LIVEKIT_API_KEY environmental variable',
62
+ );
63
+ }
64
+
65
+ lkApiSecret =
66
+ apiSecret ??
67
+ process.env.LIVEKIT_INFERENCE_API_SECRET ??
68
+ process.env.LIVEKIT_API_SECRET ??
69
+ '';
70
+ if (!lkApiSecret) {
71
+ throw new TypeError(
72
+ 'apiSecret is required, either as argument or set LIVEKIT_API_SECRET environmental variable',
73
+ );
74
+ }
75
+ useProxy = true;
76
+ } else {
77
+ useProxy = false;
78
+ }
79
+
80
+ this.options = {
81
+ sampleRate: SAMPLE_RATE,
82
+ threshold,
83
+ minFrames: Math.ceil(minInterruptionDurationInS * FRAMES_PER_SECOND),
84
+ maxAudioDurationInS,
85
+ audioPrefixDurationInS,
86
+ detectionIntervalInS,
87
+ inferenceTimeout,
88
+ baseUrl: lkBaseUrl,
89
+ apiKey: lkApiKey,
90
+ apiSecret: lkApiSecret,
91
+ useProxy,
92
+ minInterruptionDurationInS,
93
+ };
94
+
95
+ this._label = `${this.constructor.name}`;
96
+
97
+ this.logger.debug(
98
+ {
99
+ baseUrl: this.options.baseUrl,
100
+ detectionIntervalInS: this.options.detectionIntervalInS,
101
+ audioPrefixDurationInS: this.options.audioPrefixDurationInS,
102
+ maxAudioDurationInS: this.options.maxAudioDurationInS,
103
+ minFrames: this.options.minFrames,
104
+ threshold: this.options.threshold,
105
+ inferenceTimeout: this.options.inferenceTimeout,
106
+ useProxy: this.options.useProxy,
107
+ },
108
+ 'adaptive interruption detector initialized',
109
+ );
110
+ }
111
+
112
+ /**
113
+ * The model identifier for this detector.
114
+ */
115
+ get model(): string {
116
+ return 'adaptive interruption';
117
+ }
118
+
119
+ /**
120
+ * The provider identifier for this detector.
121
+ */
122
+ get provider(): string {
123
+ return 'livekit';
124
+ }
125
+
126
+ /**
127
+ * The label for this detector instance.
128
+ */
129
+ get label(): string {
130
+ return this._label;
131
+ }
132
+
133
+ /**
134
+ * The sample rate used for audio processing.
135
+ */
136
+ get sampleRate(): number {
137
+ return this.options.sampleRate;
138
+ }
139
+
140
+ /**
141
+ * Emit an error event from the detector.
142
+ */
143
+ emitError(error: InterruptionDetectionError): void {
144
+ this.emit('error', error);
145
+ }
146
+
147
+ /**
148
+ * Creates a new InterruptionStreamBase for internal use.
149
+ * The stream can receive audio frames and sentinels via pushFrame().
150
+ * Use this when you need direct access to the stream for pushing frames.
151
+ */
152
+ createStream(): InterruptionStreamBase {
153
+ const streamBase = new InterruptionStreamBase(this, {});
154
+ this.streams.add(streamBase);
155
+ return streamBase;
156
+ }
157
+
158
+ /**
159
+ * Remove a stream from tracking (called when stream is closed).
160
+ */
161
+ removeStream(stream: InterruptionStreamBase): void {
162
+ this.streams.delete(stream);
163
+ }
164
+
165
+ /**
166
+ * Update options for the detector and propagate to all active streams.
167
+ * For WebSocket streams, this triggers a reconnection with new settings.
168
+ */
169
+ async updateOptions(options: {
170
+ threshold?: number;
171
+ minInterruptionDurationInS?: number;
172
+ }): Promise<void> {
173
+ if (options.threshold !== undefined) {
174
+ this.options.threshold = options.threshold;
175
+ }
176
+ if (options.minInterruptionDurationInS !== undefined) {
177
+ this.options.minInterruptionDurationInS = options.minInterruptionDurationInS;
178
+ this.options.minFrames = Math.ceil(options.minInterruptionDurationInS * FRAMES_PER_SECOND);
179
+ }
180
+
181
+ // Propagate option updates to all active streams (matching Python behavior)
182
+ const updatePromises: Promise<void>[] = [];
183
+ for (const stream of this.streams) {
184
+ updatePromises.push(stream.updateOptions(options));
185
+ }
186
+ await Promise.all(updatePromises);
187
+ }
188
+ }