@moureau/pipeflow 0.0.1 → 0.0.3

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 (336) hide show
  1. package/README.md +280 -130
  2. package/dist/cjs/agents/agent.js +1 -1
  3. package/dist/cjs/agents/agent.js.map +3 -3
  4. package/dist/cjs/agents/tools/tools.js +1 -1
  5. package/dist/cjs/agents/tools/tools.js.map +3 -3
  6. package/dist/cjs/client/client.js +2 -0
  7. package/dist/cjs/client/client.js.map +7 -0
  8. package/dist/cjs/client/index.js +2 -0
  9. package/dist/cjs/client/index.js.map +7 -0
  10. package/dist/cjs/client/json.js +2 -0
  11. package/dist/cjs/client/json.js.map +7 -0
  12. package/dist/cjs/client/protocol/websocket.js +2 -0
  13. package/dist/cjs/client/protocol/websocket.js.map +7 -0
  14. package/dist/cjs/client/protocol.js +2 -0
  15. package/dist/cjs/client/protocol.js.map +7 -0
  16. package/dist/cjs/conversations/conversation/conversation.js +1 -1
  17. package/dist/cjs/conversations/conversation/conversation.js.map +3 -3
  18. package/dist/cjs/conversations/conversations.js +1 -1
  19. package/dist/cjs/conversations/conversations.js.map +3 -3
  20. package/dist/cjs/conversations/index.js +1 -1
  21. package/dist/cjs/conversations/index.js.map +3 -3
  22. package/dist/cjs/conversations/orchestration/coordination/coordination.js +10 -0
  23. package/dist/cjs/conversations/orchestration/coordination/coordination.js.map +7 -0
  24. package/dist/cjs/conversations/orchestration/coordination/index.js +2 -0
  25. package/dist/cjs/conversations/orchestration/coordination/index.js.map +7 -0
  26. package/dist/cjs/conversations/orchestration/orchestrator/coordination-runner/coordination-runner.js +4 -0
  27. package/dist/cjs/conversations/orchestration/orchestrator/coordination-runner/coordination-runner.js.map +7 -0
  28. package/dist/cjs/conversations/orchestration/orchestrator/coordination-runner/index.js +2 -0
  29. package/dist/cjs/conversations/orchestration/orchestrator/coordination-runner/index.js.map +7 -0
  30. package/dist/cjs/conversations/orchestration/orchestrator/generation/generation.js +2 -0
  31. package/dist/cjs/conversations/orchestration/orchestrator/generation/generation.js.map +7 -0
  32. package/dist/cjs/conversations/orchestration/orchestrator/generation/index.js +2 -0
  33. package/dist/cjs/conversations/orchestration/orchestrator/generation/index.js.map +7 -0
  34. package/dist/cjs/conversations/orchestration/orchestrator/history/history.js +4 -0
  35. package/dist/cjs/conversations/orchestration/orchestrator/history/history.js.map +7 -0
  36. package/dist/cjs/conversations/orchestration/orchestrator/history/index.js +2 -0
  37. package/dist/cjs/conversations/orchestration/orchestrator/history/index.js.map +7 -0
  38. package/dist/cjs/conversations/orchestration/orchestrator/index.js +1 -1
  39. package/dist/cjs/conversations/orchestration/orchestrator/index.js.map +3 -3
  40. package/dist/cjs/conversations/orchestration/orchestrator/orchestrator.js +1 -2
  41. package/dist/cjs/conversations/orchestration/orchestrator/orchestrator.js.map +3 -3
  42. package/dist/cjs/conversations/orchestration/orchestrator/routing/index.js +2 -0
  43. package/dist/cjs/conversations/orchestration/orchestrator/routing/index.js.map +7 -0
  44. package/dist/cjs/conversations/orchestration/orchestrator/routing/routing.js +23 -0
  45. package/dist/cjs/conversations/orchestration/orchestrator/routing/routing.js.map +7 -0
  46. package/dist/cjs/conversations/orchestration/orchestrator/speech/index.js +2 -0
  47. package/dist/cjs/conversations/orchestration/orchestrator/speech/index.js.map +7 -0
  48. package/dist/cjs/conversations/orchestration/orchestrator/speech/speech.js +2 -0
  49. package/dist/cjs/conversations/orchestration/orchestrator/speech/speech.js.map +7 -0
  50. package/dist/cjs/conversations/orchestration/orchestrator/tools/index.js +2 -0
  51. package/dist/cjs/conversations/orchestration/orchestrator/tools/index.js.map +7 -0
  52. package/dist/cjs/conversations/orchestration/orchestrator/tools/tools.js +2 -0
  53. package/dist/cjs/conversations/orchestration/orchestrator/tools/tools.js.map +7 -0
  54. package/dist/cjs/conversations/orchestration/test-harness.js +2 -0
  55. package/dist/cjs/conversations/orchestration/test-harness.js.map +7 -0
  56. package/dist/cjs/conversations/orchestration/text-chunker/index.js +2 -0
  57. package/dist/cjs/conversations/orchestration/text-chunker/index.js.map +7 -0
  58. package/dist/cjs/conversations/orchestration/text-chunker/text-chunker.js +3 -0
  59. package/dist/cjs/conversations/orchestration/text-chunker/text-chunker.js.map +7 -0
  60. package/dist/cjs/conversations/stream/conversation-stream.js +2 -0
  61. package/dist/cjs/conversations/stream/conversation-stream.js.map +7 -0
  62. package/dist/cjs/conversations/stream/index.js +2 -0
  63. package/dist/cjs/conversations/stream/index.js.map +7 -0
  64. package/dist/cjs/conversations/types.js +1 -1
  65. package/dist/cjs/conversations/types.js.map +2 -2
  66. package/dist/cjs/index.js +1 -1
  67. package/dist/cjs/index.js.map +3 -3
  68. package/dist/cjs/persistence/adapters/sqlite/sqlite.js +18 -14
  69. package/dist/cjs/persistence/adapters/sqlite/sqlite.js.map +3 -3
  70. package/dist/cjs/pipeflow/index.js +2 -0
  71. package/dist/cjs/pipeflow/index.js.map +7 -0
  72. package/dist/cjs/pipeflow/pipeflow.js +2 -0
  73. package/dist/cjs/pipeflow/pipeflow.js.map +7 -0
  74. package/dist/cjs/providers/index.js +1 -1
  75. package/dist/cjs/providers/index.js.map +2 -2
  76. package/dist/cjs/providers/llm/adapters/claude/claude.js +5 -0
  77. package/dist/cjs/providers/llm/adapters/claude/claude.js.map +7 -0
  78. package/dist/cjs/providers/llm/adapters/claude/index.js +2 -0
  79. package/dist/cjs/providers/llm/adapters/claude/index.js.map +7 -0
  80. package/dist/cjs/providers/llm/adapters/deepseek/deepseek.js +1 -1
  81. package/dist/cjs/providers/llm/adapters/deepseek/deepseek.js.map +3 -3
  82. package/dist/cjs/providers/llm/adapters/index.js +1 -1
  83. package/dist/cjs/providers/llm/adapters/index.js.map +3 -3
  84. package/dist/cjs/providers/llm/adapters/openai/index.js +2 -0
  85. package/dist/cjs/providers/llm/adapters/openai/index.js.map +7 -0
  86. package/dist/cjs/providers/llm/adapters/openai/openai.js +2 -0
  87. package/dist/cjs/providers/llm/adapters/openai/openai.js.map +7 -0
  88. package/dist/cjs/providers/llm/adapters/openai-compatible.js +10 -0
  89. package/dist/cjs/providers/llm/adapters/openai-compatible.js.map +7 -0
  90. package/dist/cjs/providers/llm/adapters/openrouter/index.js +2 -0
  91. package/dist/cjs/providers/llm/adapters/openrouter/index.js.map +7 -0
  92. package/dist/cjs/providers/llm/adapters/openrouter/openrouter.js +2 -0
  93. package/dist/cjs/providers/llm/adapters/openrouter/openrouter.js.map +7 -0
  94. package/dist/cjs/providers/llm/index.js +1 -1
  95. package/dist/cjs/providers/llm/index.js.map +3 -3
  96. package/dist/cjs/providers/llm/toolmode/index.js +2 -0
  97. package/dist/cjs/providers/llm/toolmode/index.js.map +7 -0
  98. package/dist/cjs/providers/llm/toolmode/toolmode.js +2 -0
  99. package/dist/cjs/providers/llm/toolmode/toolmode.js.map +7 -0
  100. package/dist/cjs/providers/llm/types.js +1 -1
  101. package/dist/cjs/providers/llm/types.js.map +3 -3
  102. package/dist/cjs/providers/stt/adapters/deepgram/deepgram.js +1 -1
  103. package/dist/cjs/providers/stt/adapters/deepgram/deepgram.js.map +3 -3
  104. package/dist/cjs/providers/stt/adapters/index.js +1 -1
  105. package/dist/cjs/providers/stt/adapters/index.js.map +3 -3
  106. package/dist/cjs/providers/stt/adapters/openrouter/index.js +2 -0
  107. package/dist/cjs/providers/stt/adapters/openrouter/index.js.map +7 -0
  108. package/dist/cjs/providers/stt/adapters/openrouter/openrouter.js +2 -0
  109. package/dist/cjs/providers/stt/adapters/openrouter/openrouter.js.map +7 -0
  110. package/dist/cjs/providers/tts/adapters/index.js +1 -1
  111. package/dist/cjs/providers/tts/adapters/index.js.map +3 -3
  112. package/dist/cjs/providers/tts/adapters/kokoro/kokoro.js +4 -1
  113. package/dist/cjs/providers/tts/adapters/kokoro/kokoro.js.map +3 -3
  114. package/dist/cjs/providers/tts/adapters/openrouter/index.js +2 -0
  115. package/dist/cjs/providers/tts/adapters/openrouter/index.js.map +7 -0
  116. package/dist/cjs/providers/tts/adapters/openrouter/openrouter.js +2 -0
  117. package/dist/cjs/providers/tts/adapters/openrouter/openrouter.js.map +7 -0
  118. package/dist/cjs/transport/streamobject/field-stream/field-stream.js +2 -0
  119. package/dist/cjs/transport/streamobject/field-stream/field-stream.js.map +7 -0
  120. package/dist/cjs/transport/streamobject/field-stream/index.js +2 -0
  121. package/dist/cjs/transport/streamobject/field-stream/index.js.map +7 -0
  122. package/dist/cjs/transport/streamobject/index.js +2 -0
  123. package/dist/cjs/transport/streamobject/index.js.map +7 -0
  124. package/dist/cjs/transport/streamobject/json-adapter/index.js +2 -0
  125. package/dist/cjs/transport/streamobject/json-adapter/index.js.map +7 -0
  126. package/dist/cjs/transport/streamobject/json-adapter/json-adapter.js +4 -0
  127. package/dist/cjs/transport/streamobject/json-adapter/json-adapter.js.map +7 -0
  128. package/dist/cjs/transport/streamobject/reference/index.js +2 -0
  129. package/dist/cjs/transport/streamobject/reference/index.js.map +7 -0
  130. package/dist/cjs/transport/streamobject/reference/reference.js +2 -0
  131. package/dist/cjs/transport/streamobject/reference/reference.js.map +7 -0
  132. package/dist/cjs/transport/streamobject/stream-object/index.js +2 -0
  133. package/dist/cjs/transport/streamobject/stream-object/index.js.map +7 -0
  134. package/dist/cjs/transport/streamobject/stream-object/stream-object.js +2 -0
  135. package/dist/cjs/transport/streamobject/stream-object/stream-object.js.map +7 -0
  136. package/dist/esm/agents/agent.js +1 -1
  137. package/dist/esm/agents/agent.js.map +3 -3
  138. package/dist/esm/agents/tools/tools.js +1 -1
  139. package/dist/esm/agents/tools/tools.js.map +3 -3
  140. package/dist/esm/client/client.js +2 -0
  141. package/dist/esm/client/client.js.map +7 -0
  142. package/dist/esm/client/index.js +2 -0
  143. package/dist/esm/client/index.js.map +7 -0
  144. package/dist/esm/client/json.js +2 -0
  145. package/dist/esm/client/json.js.map +7 -0
  146. package/dist/esm/client/protocol/websocket.js +2 -0
  147. package/dist/esm/client/protocol/websocket.js.map +7 -0
  148. package/dist/esm/client/protocol.js +1 -0
  149. package/dist/esm/client/protocol.js.map +7 -0
  150. package/dist/esm/conversations/conversation/conversation.js +1 -1
  151. package/dist/esm/conversations/conversation/conversation.js.map +3 -3
  152. package/dist/esm/conversations/conversations.js +1 -1
  153. package/dist/esm/conversations/conversations.js.map +3 -3
  154. package/dist/esm/conversations/index.js +1 -1
  155. package/dist/esm/conversations/index.js.map +3 -3
  156. package/dist/esm/conversations/orchestration/coordination/coordination.js +10 -0
  157. package/dist/esm/conversations/orchestration/coordination/coordination.js.map +7 -0
  158. package/dist/esm/conversations/orchestration/coordination/index.js +2 -0
  159. package/dist/esm/conversations/orchestration/coordination/index.js.map +7 -0
  160. package/dist/esm/conversations/orchestration/orchestrator/coordination-runner/coordination-runner.js +4 -0
  161. package/dist/esm/conversations/orchestration/orchestrator/coordination-runner/coordination-runner.js.map +7 -0
  162. package/dist/esm/conversations/orchestration/orchestrator/coordination-runner/index.js +2 -0
  163. package/dist/esm/conversations/orchestration/orchestrator/coordination-runner/index.js.map +7 -0
  164. package/dist/esm/conversations/orchestration/orchestrator/generation/generation.js +2 -0
  165. package/dist/esm/conversations/orchestration/orchestrator/generation/generation.js.map +7 -0
  166. package/dist/esm/conversations/orchestration/orchestrator/generation/index.js +2 -0
  167. package/dist/esm/conversations/orchestration/orchestrator/generation/index.js.map +7 -0
  168. package/dist/esm/conversations/orchestration/orchestrator/history/history.js +4 -0
  169. package/dist/esm/conversations/orchestration/orchestrator/history/history.js.map +7 -0
  170. package/dist/esm/conversations/orchestration/orchestrator/history/index.js +2 -0
  171. package/dist/esm/conversations/orchestration/orchestrator/history/index.js.map +7 -0
  172. package/dist/esm/conversations/orchestration/orchestrator/index.js +1 -1
  173. package/dist/esm/conversations/orchestration/orchestrator/index.js.map +3 -3
  174. package/dist/esm/conversations/orchestration/orchestrator/orchestrator.js +1 -2
  175. package/dist/esm/conversations/orchestration/orchestrator/orchestrator.js.map +3 -3
  176. package/dist/esm/conversations/orchestration/orchestrator/routing/index.js +2 -0
  177. package/dist/esm/conversations/orchestration/orchestrator/routing/index.js.map +7 -0
  178. package/dist/esm/conversations/orchestration/orchestrator/routing/routing.js +23 -0
  179. package/dist/esm/conversations/orchestration/orchestrator/routing/routing.js.map +7 -0
  180. package/dist/esm/conversations/orchestration/orchestrator/speech/index.js +2 -0
  181. package/dist/esm/conversations/orchestration/orchestrator/speech/index.js.map +7 -0
  182. package/dist/esm/conversations/orchestration/orchestrator/speech/speech.js +2 -0
  183. package/dist/esm/conversations/orchestration/orchestrator/speech/speech.js.map +7 -0
  184. package/dist/esm/conversations/orchestration/orchestrator/tools/index.js +2 -0
  185. package/dist/esm/conversations/orchestration/orchestrator/tools/index.js.map +7 -0
  186. package/dist/esm/conversations/orchestration/orchestrator/tools/tools.js +2 -0
  187. package/dist/esm/conversations/orchestration/orchestrator/tools/tools.js.map +7 -0
  188. package/dist/esm/conversations/orchestration/test-harness.js +2 -0
  189. package/dist/esm/conversations/orchestration/test-harness.js.map +7 -0
  190. package/dist/esm/conversations/orchestration/text-chunker/index.js +2 -0
  191. package/dist/esm/conversations/orchestration/text-chunker/index.js.map +7 -0
  192. package/dist/esm/conversations/orchestration/text-chunker/text-chunker.js +3 -0
  193. package/dist/esm/conversations/orchestration/text-chunker/text-chunker.js.map +7 -0
  194. package/dist/esm/conversations/stream/conversation-stream.js +2 -0
  195. package/dist/esm/conversations/stream/conversation-stream.js.map +7 -0
  196. package/dist/esm/conversations/stream/index.js +2 -0
  197. package/dist/esm/conversations/stream/index.js.map +7 -0
  198. package/dist/esm/conversations/types.js +1 -1
  199. package/dist/esm/conversations/types.js.map +2 -2
  200. package/dist/esm/index.js +1 -1
  201. package/dist/esm/index.js.map +3 -3
  202. package/dist/esm/persistence/adapters/sqlite/sqlite.js +18 -14
  203. package/dist/esm/persistence/adapters/sqlite/sqlite.js.map +3 -3
  204. package/dist/esm/pipeflow/index.js +2 -0
  205. package/dist/esm/pipeflow/index.js.map +7 -0
  206. package/dist/esm/pipeflow/pipeflow.js +2 -0
  207. package/dist/esm/pipeflow/pipeflow.js.map +7 -0
  208. package/dist/esm/providers/index.js +1 -1
  209. package/dist/esm/providers/index.js.map +3 -3
  210. package/dist/esm/providers/llm/adapters/claude/claude.js +5 -0
  211. package/dist/esm/providers/llm/adapters/claude/claude.js.map +7 -0
  212. package/dist/esm/providers/llm/adapters/claude/index.js +2 -0
  213. package/dist/esm/providers/llm/adapters/claude/index.js.map +7 -0
  214. package/dist/esm/providers/llm/adapters/deepseek/deepseek.js +1 -1
  215. package/dist/esm/providers/llm/adapters/deepseek/deepseek.js.map +3 -3
  216. package/dist/esm/providers/llm/adapters/index.js +1 -1
  217. package/dist/esm/providers/llm/adapters/index.js.map +3 -3
  218. package/dist/esm/providers/llm/adapters/openai/index.js +2 -0
  219. package/dist/esm/providers/llm/adapters/openai/index.js.map +7 -0
  220. package/dist/esm/providers/llm/adapters/openai/openai.js +2 -0
  221. package/dist/esm/providers/llm/adapters/openai/openai.js.map +7 -0
  222. package/dist/esm/providers/llm/adapters/openai-compatible.js +10 -0
  223. package/dist/esm/providers/llm/adapters/openai-compatible.js.map +7 -0
  224. package/dist/esm/providers/llm/adapters/openrouter/index.js +2 -0
  225. package/dist/esm/providers/llm/adapters/openrouter/index.js.map +7 -0
  226. package/dist/esm/providers/llm/adapters/openrouter/openrouter.js +2 -0
  227. package/dist/esm/providers/llm/adapters/openrouter/openrouter.js.map +7 -0
  228. package/dist/esm/providers/llm/index.js +1 -1
  229. package/dist/esm/providers/llm/index.js.map +3 -3
  230. package/dist/esm/providers/llm/toolmode/index.js +2 -0
  231. package/dist/esm/providers/llm/toolmode/index.js.map +7 -0
  232. package/dist/esm/providers/llm/toolmode/toolmode.js +2 -0
  233. package/dist/esm/providers/llm/toolmode/toolmode.js.map +7 -0
  234. package/dist/esm/providers/llm/types.js +1 -0
  235. package/dist/esm/providers/llm/types.js.map +4 -4
  236. package/dist/esm/providers/stt/adapters/deepgram/deepgram.js +1 -1
  237. package/dist/esm/providers/stt/adapters/deepgram/deepgram.js.map +3 -3
  238. package/dist/esm/providers/stt/adapters/index.js +1 -1
  239. package/dist/esm/providers/stt/adapters/index.js.map +3 -3
  240. package/dist/esm/providers/stt/adapters/openrouter/index.js +2 -0
  241. package/dist/esm/providers/stt/adapters/openrouter/index.js.map +7 -0
  242. package/dist/esm/providers/stt/adapters/openrouter/openrouter.js +2 -0
  243. package/dist/esm/providers/stt/adapters/openrouter/openrouter.js.map +7 -0
  244. package/dist/esm/providers/tts/adapters/index.js +1 -1
  245. package/dist/esm/providers/tts/adapters/index.js.map +3 -3
  246. package/dist/esm/providers/tts/adapters/kokoro/kokoro.js +4 -1
  247. package/dist/esm/providers/tts/adapters/kokoro/kokoro.js.map +3 -3
  248. package/dist/esm/providers/tts/adapters/openrouter/index.js +2 -0
  249. package/dist/esm/providers/tts/adapters/openrouter/index.js.map +7 -0
  250. package/dist/esm/providers/tts/adapters/openrouter/openrouter.js +2 -0
  251. package/dist/esm/providers/tts/adapters/openrouter/openrouter.js.map +7 -0
  252. package/dist/esm/transport/streamobject/field-stream/field-stream.js +2 -0
  253. package/dist/esm/transport/streamobject/field-stream/field-stream.js.map +7 -0
  254. package/dist/esm/transport/streamobject/field-stream/index.js +2 -0
  255. package/dist/esm/transport/streamobject/field-stream/index.js.map +7 -0
  256. package/dist/esm/transport/streamobject/index.js +2 -0
  257. package/dist/esm/transport/streamobject/index.js.map +7 -0
  258. package/dist/esm/transport/streamobject/json-adapter/index.js +2 -0
  259. package/dist/esm/transport/streamobject/json-adapter/index.js.map +7 -0
  260. package/dist/esm/transport/streamobject/json-adapter/json-adapter.js +4 -0
  261. package/dist/esm/transport/streamobject/json-adapter/json-adapter.js.map +7 -0
  262. package/dist/esm/transport/streamobject/reference/index.js +2 -0
  263. package/dist/esm/transport/streamobject/reference/index.js.map +7 -0
  264. package/dist/esm/transport/streamobject/reference/reference.js +2 -0
  265. package/dist/esm/transport/streamobject/reference/reference.js.map +7 -0
  266. package/dist/esm/transport/streamobject/stream-object/index.js +2 -0
  267. package/dist/esm/transport/streamobject/stream-object/index.js.map +7 -0
  268. package/dist/esm/transport/streamobject/stream-object/stream-object.js +2 -0
  269. package/dist/esm/transport/streamobject/stream-object/stream-object.js.map +7 -0
  270. package/dist/types/agents/agent.d.ts +3 -0
  271. package/dist/types/agents/tools/tools.d.ts +28 -6
  272. package/dist/types/client/client.d.ts +186 -0
  273. package/dist/types/client/index.d.ts +31 -0
  274. package/dist/types/client/json.d.ts +13 -0
  275. package/dist/types/client/protocol/websocket.d.ts +56 -0
  276. package/dist/types/client/protocol.d.ts +46 -0
  277. package/dist/types/conversations/conversation/conversation.d.ts +130 -6
  278. package/dist/types/conversations/conversations.d.ts +35 -1
  279. package/dist/types/conversations/index.d.ts +2 -1
  280. package/dist/types/conversations/orchestration/coordination/coordination.d.ts +192 -0
  281. package/dist/types/conversations/orchestration/coordination/index.d.ts +2 -0
  282. package/dist/types/conversations/orchestration/orchestrator/coordination-runner/coordination-runner.d.ts +108 -0
  283. package/dist/types/conversations/orchestration/orchestrator/coordination-runner/index.d.ts +2 -0
  284. package/dist/types/conversations/orchestration/orchestrator/generation/generation.d.ts +60 -0
  285. package/dist/types/conversations/orchestration/orchestrator/generation/index.d.ts +2 -0
  286. package/dist/types/conversations/orchestration/orchestrator/history/history.d.ts +62 -0
  287. package/dist/types/conversations/orchestration/orchestrator/history/index.d.ts +1 -0
  288. package/dist/types/conversations/orchestration/orchestrator/index.d.ts +10 -0
  289. package/dist/types/conversations/orchestration/orchestrator/orchestrator.d.ts +68 -31
  290. package/dist/types/conversations/orchestration/orchestrator/routing/index.d.ts +1 -0
  291. package/dist/types/conversations/orchestration/orchestrator/routing/routing.d.ts +19 -0
  292. package/dist/types/conversations/orchestration/orchestrator/speech/index.d.ts +2 -0
  293. package/dist/types/conversations/orchestration/orchestrator/speech/speech.d.ts +78 -0
  294. package/dist/types/conversations/orchestration/orchestrator/tools/index.d.ts +2 -0
  295. package/dist/types/conversations/orchestration/orchestrator/tools/tools.d.ts +65 -0
  296. package/dist/types/conversations/orchestration/test-harness.d.ts +100 -0
  297. package/dist/types/conversations/orchestration/text-chunker/index.d.ts +1 -0
  298. package/dist/types/conversations/orchestration/text-chunker/text-chunker.d.ts +39 -0
  299. package/dist/types/conversations/stream/conversation-stream.d.ts +42 -0
  300. package/dist/types/conversations/stream/index.d.ts +1 -0
  301. package/dist/types/conversations/types.d.ts +32 -0
  302. package/dist/types/index.d.ts +5 -38
  303. package/dist/types/pipeflow/index.d.ts +2 -0
  304. package/dist/types/pipeflow/pipeflow.d.ts +43 -0
  305. package/dist/types/providers/index.d.ts +1 -1
  306. package/dist/types/providers/llm/adapters/claude/claude.d.ts +45 -0
  307. package/dist/types/providers/llm/adapters/claude/index.d.ts +2 -0
  308. package/dist/types/providers/llm/adapters/deepseek/deepseek.d.ts +23 -2
  309. package/dist/types/providers/llm/adapters/index.d.ts +3 -0
  310. package/dist/types/providers/llm/adapters/openai/index.d.ts +2 -0
  311. package/dist/types/providers/llm/adapters/openai/openai.d.ts +45 -0
  312. package/dist/types/providers/llm/adapters/openai-compatible.d.ts +44 -0
  313. package/dist/types/providers/llm/adapters/openrouter/index.d.ts +2 -0
  314. package/dist/types/providers/llm/adapters/openrouter/openrouter.d.ts +60 -0
  315. package/dist/types/providers/llm/index.d.ts +5 -2
  316. package/dist/types/providers/llm/toolmode/index.d.ts +2 -0
  317. package/dist/types/providers/llm/toolmode/toolmode.d.ts +99 -0
  318. package/dist/types/providers/llm/types.d.ts +65 -0
  319. package/dist/types/providers/stt/adapters/deepgram/deepgram.d.ts +4 -1
  320. package/dist/types/providers/stt/adapters/index.d.ts +1 -0
  321. package/dist/types/providers/stt/adapters/openrouter/index.d.ts +2 -0
  322. package/dist/types/providers/stt/adapters/openrouter/openrouter.d.ts +196 -0
  323. package/dist/types/providers/tts/adapters/index.d.ts +1 -0
  324. package/dist/types/providers/tts/adapters/kokoro/kokoro.d.ts +18 -3
  325. package/dist/types/providers/tts/adapters/openrouter/index.d.ts +2 -0
  326. package/dist/types/providers/tts/adapters/openrouter/openrouter.d.ts +64 -0
  327. package/dist/types/transport/streamobject/field-stream/field-stream.d.ts +85 -0
  328. package/dist/types/transport/streamobject/field-stream/index.d.ts +2 -0
  329. package/dist/types/transport/streamobject/index.d.ts +8 -0
  330. package/dist/types/transport/streamobject/json-adapter/index.d.ts +2 -0
  331. package/dist/types/transport/streamobject/json-adapter/json-adapter.d.ts +65 -0
  332. package/dist/types/transport/streamobject/reference/index.d.ts +2 -0
  333. package/dist/types/transport/streamobject/reference/reference.d.ts +127 -0
  334. package/dist/types/transport/streamobject/stream-object/index.d.ts +2 -0
  335. package/dist/types/transport/streamobject/stream-object/stream-object.d.ts +31 -0
  336. package/package.json +29 -2
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/client/protocol/websocket.ts"],
4
+ "sourcesContent": ["/**\n * WebSocket-backed implementation of the `Protocol` contract.\n *\n * The URL, auth token, and subprotocols are passed through to the underlying\n * `WebSocket`. The token is resolved lazily on each `connect()` and appended\n * to the URL as a `token` query parameter so the server can authenticate the\n * upgrade (WebSocket has no `Authorization` header mechanism).\n *\n * ```ts\n * const protocol = new WebSocketProtocol({\n * url: \"wss://api.example.com/conversations/abc\",\n * token: () => localStorage.getItem(\"jwt\"),\n * });\n * ```\n */\nimport type {\n Protocol,\n ProtocolListener,\n ProtocolMessage,\n ProtocolStatus,\n StatusListener,\n} from \"../protocol\";\nimport { isJsonSerializable } from \"../json\";\n\n/**\n * Resolves the connection token. Called on every `connect()` so the caller\n * can rotate credentials without rebuilding the client. The resolved value\n * is appended to the URL as `?token=\u2026` (overwriting any existing value).\n */\nexport type TokenProvider = () => string | null | Promise<string | null>;\n\nexport interface WebSocketProtocolOptions {\n /** Fully-qualified WebSocket URL, e.g. `wss://api.example.com/conversations/abc`. */\n url: string;\n /** Optional token resolver; the resolved value is appended as `?token=\u2026`. */\n token?: TokenProvider;\n /** Subprotocols passed to the WebSocket constructor. */\n protocols?: string | string[];\n /**\n * Inject a custom WebSocket constructor (for tests, polyfills, or tracing).\n * Defaults to the global `WebSocket`.\n */\n socketFactory?: (url: string, protocols?: string | string[]) => WebSocket;\n}\n\nexport class WebSocketProtocol implements Protocol {\n readonly url: string;\n private readonly token?: TokenProvider;\n private readonly protocols?: string | string[];\n private readonly socketFactory: NonNullable<\n WebSocketProtocolOptions[\"socketFactory\"]\n >;\n\n private socket: WebSocket | null = null;\n private _status: ProtocolStatus = \"idle\";\n private readonly messageListeners = new Set<ProtocolListener>();\n private readonly statusListeners = new Set<StatusListener>();\n\n constructor(options: WebSocketProtocolOptions) {\n this.url = options.url;\n this.token = options.token;\n this.protocols = options.protocols;\n this.socketFactory =\n options.socketFactory ??\n ((url, protocols) => new WebSocket(url, protocols));\n }\n\n get status(): ProtocolStatus {\n return this._status;\n }\n\n async connect(): Promise<void> {\n if (this._status === \"open\" || this._status === \"connecting\") return;\n if (this.socket) this.teardownSocket(this.socket);\n this.setStatus(\"connecting\");\n\n // Construct the socket synchronously so callers (and tests) can interact\n // with it before the promise resolves. For async token providers, the\n // construction must be deferred: call `connect()` with a sync token\n // provider or pre-resolve the token.\n const syncToken = this.token ? await this.token() : null;\n const url = syncToken ? withToken(this.url, syncToken) : this.url;\n\n const socket = this.socketFactory(url, this.protocols);\n this.socket = socket;\n\n return new Promise<void>((resolve, reject) => {\n const onOpen = () => {\n socket.removeEventListener(\"open\", onOpen);\n socket.removeEventListener(\"error\", onError);\n this.setStatus(\"open\");\n resolve();\n };\n const onError = () => {\n socket.removeEventListener(\"open\", onOpen);\n socket.removeEventListener(\"error\", onError);\n this.setStatus(\"closed\");\n reject(new Error(`Failed to connect to ${this.url}`));\n };\n socket.addEventListener(\"open\", onOpen);\n socket.addEventListener(\"error\", onError);\n socket.addEventListener(\"message\", this.handleMessage);\n socket.addEventListener(\"close\", this.handleClose);\n });\n }\n\n async close(): Promise<void> {\n const socket = this.socket;\n if (!socket || this._status === \"closed\" || this._status === \"idle\") return;\n this.setStatus(\"closing\");\n\n await new Promise<void>((resolve) => {\n const done = () => {\n socket.removeEventListener(\"close\", done);\n resolve();\n };\n socket.addEventListener(\"close\", done);\n // readyState 0 (CONNECTING) cannot be closed gracefully; drop it.\n if (socket.readyState === WebSocket.CONNECTING) {\n socket.close();\n } else if (socket.readyState === WebSocket.OPEN) {\n socket.close(1000, \"client closing\");\n } else {\n resolve();\n }\n });\n\n this.teardownSocket(socket);\n this.setStatus(\"closed\");\n }\n\n send(message: ProtocolMessage): void {\n if (this._status !== \"open\" || !this.socket) {\n throw new Error(`Cannot send on a ${this._status} protocol`);\n }\n if (!isJsonSerializable(message.payload)) {\n throw new Error(\"ProtocolMessage.payload must be JSON-serializable\");\n }\n this.socket.send(JSON.stringify(message));\n }\n\n onMessage(listener: ProtocolListener): () => void {\n this.messageListeners.add(listener);\n return () => {\n this.messageListeners.delete(listener);\n };\n }\n\n onStatus(listener: StatusListener): () => void {\n this.statusListeners.add(listener);\n return () => {\n this.statusListeners.delete(listener);\n };\n }\n\n private readonly handleMessage = (event: MessageEvent): void => {\n const raw = typeof event.data === \"string\" ? event.data : \"\";\n if (!raw) return;\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return;\n }\n if (!isProtocolMessage(parsed)) return;\n for (const listener of [...this.messageListeners]) {\n try {\n listener(parsed);\n } catch {\n // A faulty listener must not prevent delivery to others.\n }\n }\n };\n\n private readonly handleClose = (): void => {\n if (this._status !== \"closed\") this.setStatus(\"closed\");\n if (this.socket) this.teardownSocket(this.socket);\n };\n\n private teardownSocket(socket: WebSocket): void {\n socket.removeEventListener(\"message\", this.handleMessage);\n socket.removeEventListener(\"close\", this.handleClose);\n this.socket = null;\n }\n\n private setStatus(next: ProtocolStatus): void {\n if (this._status === next) return;\n this._status = next;\n for (const listener of [...this.statusListeners]) {\n try {\n listener(next);\n } catch {\n // ignore\n }\n }\n }\n}\n\nfunction isProtocolMessage(value: unknown): value is ProtocolMessage {\n if (!value || typeof value !== \"object\") return false;\n const record = value as Record<string, unknown>;\n return typeof record.type === \"string\";\n}\n\n/** Append or replace `?token=\u2026` on a URL. */\nfunction withToken(url: string, token: string): string {\n try {\n const parsed = new URL(url);\n parsed.searchParams.set(\"token\", token);\n return parsed.toString();\n } catch {\n // Fall back to a literal concat for relative or malformed URLs (tests).\n const sep = url.includes(\"?\") ? \"&\" : \"?\";\n return `${url}${sep}token=${encodeURIComponent(token)}`;\n }\n}"],
5
+ "mappings": "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",
6
+ "names": ["isJsonSerializable", "WebSocketProtocol", "__name", "options", "url", "protocols", "syncToken", "withToken", "socket", "resolve", "reject", "onOpen", "onError", "done", "message", "listener", "event", "raw", "parsed", "isProtocolMessage", "next", "value", "token", "sep"]
7
+ }
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [],
5
+ "mappings": "",
6
+ "names": []
7
+ }
@@ -1,2 +1,2 @@
1
- var d=Object.defineProperty;var o=(a,t)=>d(a,"name",{value:t,configurable:!0});import{createConversationState as p}from"../types.js";import{Transcription as c}from"../transcription/transcription.js";class v{static{o(this,"Conversation")}id;agents;transcription;state;persistence;listeners=new Map;pendingToolCallsById=new Map;nextAudioSequence=0;constructor(t){this.id=t.id,this.agents=t.agents??[],this.persistence=t.persistence,this.transcription=new c(this.id),this.state=p()}get status(){return this.state.status}get participants(){return[...this.state.participants.values()]}start(){if(this.state.status==="stopped")throw new Error(`Conversation "${this.id}" has already been stopped`);this.state.status!=="started"&&(this.state.status="started",this.emit("start",{conversationId:this.id}),this.emitState())}async stop(){if(this.state.status==="stopped")return;this.state.status="stopped",this.pendingToolCallsById.clear();const t=this.cancelCurrentGeneration();t&&await this.persistence?.appendGeneration(this.id,t),await this.persistence?.finalizeConversation(this.id,Date.now()),this.emit("stop",{conversationId:this.id}),this.emitState()}async participate(t){if(this.state.status==="stopped")throw new Error(`Conversation "${this.id}" has already been stopped`);const e=Array.isArray(t)?t:[t],i=new Set;for(const n of e){if(i.has(n.userId))throw new Error(`Duplicate participant "${n.userId}" in batch`);if(i.add(n.userId),this.state.participants.has(n.userId))throw new Error(`Participant "${n.userId}" already exists`)}const r=[];for(const n of e){const s={userId:n.userId,aliases:[...n.aliases??[]],joinedAt:Date.now()};this.state.participants.set(s.userId,s),await this.persistence?.addParticipant(this.id,s),r.push(s),this.emit("participant",{conversationId:this.id,participant:s})}return this.emitState(),r}listen(t){if(this.state.status!=="started")throw new Error(`Conversation "${this.id}" is not started`);if(!this.state.participants.has(t.userId))throw new Error(`Unknown participant "${t.userId}"`);const e={data:t.audio,timestamp:Date.now(),sequence:this.nextAudioSequence++};this.emit("audio-in",{conversationId:this.id,userId:t.userId,audio:e})}interrupt(){const t=this.cancelCurrentGeneration();t&&this.persistence?.appendGeneration(this.id,t).catch(()=>{}),this.emit("interrupt",{conversationId:this.id}),this.emitState()}on(t,e){let i=this.listeners.get(t);return i||(i=new Set,this.listeners.set(t,i)),i.add(e),()=>{i.delete(e)}}emit(t,e){const i=this.listeners.get(t);if(i)for(const r of[...i])r(e)}pushAudio(t){this.emit("audio",{conversationId:this.id,audio:t})}async pushTurn(t){this.state.currentTurn=t,this.emit("turn",{conversationId:this.id,turn:t}),await this.persistence?.appendTurn(this.id,t),this.emitState()}async pushTranscript(t){const e=this.transcription.append({...t});return this.state.transcriptCount++,this.emit("transcript",{conversationId:this.id,entry:e}),await this.persistence?.appendTranscript(this.id,e),this.emitState(),e}async pushGeneration(t){this.state.currentGeneration=t,this.emit("generation",{conversationId:this.id,generation:t}),await this.persistence?.appendGeneration(this.id,t),this.emitState()}get pendingToolCalls(){return[...this.pendingToolCallsById.values()]}requestToolCall(t){this.pendingToolCallsById.set(t.id,t),this.emit("tool-call",{conversationId:this.id,call:t}),this.emitState()}resolveToolCall(t){if(!this.pendingToolCallsById.has(t.id))throw new Error(`No pending tool call "${t.id}"`);this.pendingToolCallsById.delete(t.id),this.emit("tool-call-result",{conversationId:this.id,result:t}),this.emitState()}async completeGeneration(t){const e=this.state.currentGeneration;e&&e.status==="streaming"&&(t!==void 0&&(e.text=t),e.status="completed",e.endedAt=Date.now(),await this.persistence?.appendGeneration(this.id,e),this.emitState())}transcript(){return this.transcription.list()}cancelCurrentGeneration(){const t=this.state.currentGeneration;return t&&t.status==="streaming"&&(t.status="cancelled",t.endedAt=Date.now()),this.state.currentGeneration=null,t??null}emitState(){this.emit("state",{conversationId:this.id,state:this.state})}}export{v as Conversation};
1
+ var u=Object.defineProperty;var d=(a,t)=>u(a,"name",{value:t,configurable:!0});import{Orchestrator as c}from"../orchestration/orchestrator/orchestrator.js";import{createConversationState as p}from"../types.js";import{Transcription as h}from"../transcription/transcription.js";function r(a){return a.timing??={startedAt:a.startedAt}}d(r,"initTiming");const l={firstToken:"firstTokenAt",firstTtsText:"firstTtsTextAt",firstTtsRequest:"firstTtsRequestAt",firstTtsAudio:"firstTtsAudioAt"};class T{static{d(this,"Conversation")}id;agents;transcription;state;persistence;stt;tts;autoExecuteTools;maxConcurrentTtsRequests;listeners=new Map;pendingToolCallsById=new Map;subGenerations=new Map;audioReorderMs;audioReorder=new Map;nextAudioSequence=0;constructor(t){this.id=t.id,this.agents=t.agents??[],this.persistence=t.persistence,this.stt=t.stt,this.tts=t.tts,this.autoExecuteTools=t.autoExecuteTools??!0,this.maxConcurrentTtsRequests=t.maxConcurrentTtsRequests,this.audioReorderMs=t.audioReorderMs??100,this.transcription=new h(this.id),this.state=p()}get status(){return this.state.status}get participants(){return[...this.state.participants.values()]}async start(){if(this.state.status==="stopped")throw new Error(`Conversation "${this.id}" has already been stopped`);if(this.state.status==="started")return;const t=this.buildRealtime();this.state.status="started",this.emit("start",{conversationId:this.id}),this.emitState(),await t?.start()}async stop(){if(this.state.status==="stopped")return;this.state.status="stopped";for(const e of this.audioReorder.values())this.clearReorderTimer(e);this.audioReorder.clear(),this.pendingToolCallsById.clear();const t=this.cancelCurrentGeneration();t&&await this.persistence?.appendGeneration(this.id,t);for(const e of[...this.subGenerations.values()])e.status==="streaming"&&(e.status="cancelled",e.endedAt=Date.now(),await this.persistence?.appendGeneration(this.id,e));await this.persistence?.finalizeConversation(this.id,Date.now()),this.emit("stop",{conversationId:this.id}),this.emitState()}async participate(t){if(this.state.status==="stopped")throw new Error(`Conversation "${this.id}" has already been stopped`);const e=Array.isArray(t)?t:[t],i=new Set;for(const s of e){if(i.has(s.userId))throw new Error(`Duplicate participant "${s.userId}" in batch`);if(i.add(s.userId),this.state.participants.has(s.userId))throw new Error(`Participant "${s.userId}" already exists`)}const n=[];for(const s of e){const o={userId:s.userId,aliases:[...s.aliases??[]],joinedAt:Date.now()};this.state.participants.set(o.userId,o),await this.persistence?.addParticipant(this.id,o),n.push(o),this.emit("participant",{conversationId:this.id,participant:o})}return this.emitState(),n}listen(t){if(this.state.status!=="started")throw new Error(`Conversation "${this.id}" is not started`);if(!this.state.participants.has(t.userId))throw new Error(`Unknown participant "${t.userId}"`);if(t.sequence===void 0){this.emitAudioIn(t.userId,t.audio);return}this.reorderAudio(t.userId,t.audio,t.sequence)}emitAudioIn(t,e){const i={data:e,timestamp:Date.now(),sequence:this.nextAudioSequence++};this.emit("audio-in",{conversationId:this.id,userId:t,audio:i})}reorderAudio(t,e,i){let n=this.audioReorder.get(t);if(n||(n={next:null,pending:new Map,timer:null},this.audioReorder.set(t,n)),n.next===null&&(n.next=i),!(i<n.next)){if(i===n.next){for(this.clearReorderTimer(n),this.emitAudioIn(t,e),n.next++;n.pending.has(n.next);){const s=n.pending.get(n.next);n.pending.delete(n.next),this.emitAudioIn(t,s),n.next++}return}n.pending.set(i,e),n.timer||(n.timer=setTimeout(()=>{n.timer=null,this.releaseReorderBuffer(t)},this.audioReorderMs))}}releaseReorderBuffer(t){const e=this.audioReorder.get(t);if(e)for(this.clearReorderTimer(e);e.pending.size>0;){const i=Math.min(...e.pending.keys()),n=e.pending.get(i);e.pending.delete(i),e.next=i+1,this.emitAudioIn(t,n)}}clearReorderTimer(t){t.timer&&(clearTimeout(t.timer),t.timer=null)}send(t){if(this.state.status!=="started")throw new Error(`Conversation "${this.id}" is not started`);if(!this.state.participants.has(t.userId))throw new Error(`Unknown participant "${t.userId}"`);this.emit("text-in",{conversationId:this.id,userId:t.userId,text:t.text})}interrupt(){const t=this.cancelCurrentGeneration();t&&this.persistence?.appendGeneration(this.id,t).catch(()=>{}),this.emit("interrupt",{conversationId:this.id}),this.emitState()}on(t,e){let i=this.listeners.get(t);return i||(i=new Set,this.listeners.set(t,i)),i.add(e),()=>{i.delete(e)}}emit(t,e){const i=this.listeners.get(t);if(i)for(const n of[...i])n(e)}pushAudio(t){const e=this.state.currentGeneration;if(e&&e.status==="streaming"){const i=r(e);i.firstAudioAt===void 0&&(i.firstAudioAt=Date.now(),this.persistence?.appendGeneration(this.id,e).catch(()=>{}),this.emitState())}this.emit("audio",{conversationId:this.id,audio:t})}async pushTurn(t){this.state.currentTurn=t,this.emit("turn",{conversationId:this.id,turn:t}),await this.persistence?.appendTurn(this.id,t),this.emitState()}async pushTranscript(t){const e=this.transcription.append({...t});return this.state.transcriptCount++,this.emit("transcript",{conversationId:this.id,entry:e}),await this.persistence?.appendTranscript(this.id,e),this.emitState(),e}pushTextDelta(t){const e=this.state.currentGeneration?.agentName;this.emit("text-delta",{conversationId:this.id,text:t,agentName:e})}async pushGeneration(t){r(t),this.state.currentGeneration=t,this.emit("generation",{conversationId:this.id,generation:t}),await this.persistence?.appendGeneration(this.id,t),this.emitState()}noteTiming(t,e){const i=e?this.subGenerations.get(e):this.state.currentGeneration;if(!i||i.status!=="streaming")return;const n=r(i),s=l[t];n[s]===void 0&&(n[s]=Date.now(),this.persistence?.appendGeneration(this.id,i).catch(()=>{}),this.emitState())}get pendingToolCalls(){return[...this.pendingToolCallsById.values()]}requestToolCall(t){this.pendingToolCallsById.set(t.id,t),this.emit("tool-call",{conversationId:this.id,call:t}),this.emitState()}resolveToolCall(t){if(!this.pendingToolCallsById.has(t.id))throw new Error(`No pending tool call "${t.id}"`);this.pendingToolCallsById.delete(t.id),this.emit("tool-call-result",{conversationId:this.id,result:t}),this.emitState()}async completeGeneration(t){const e=this.state.currentGeneration;e&&e.status==="streaming"&&(t!==void 0&&(e.text=t),e.status="completed",e.endedAt=Date.now(),r(e).completedAt=Date.now(),await this.persistence?.appendGeneration(this.id,e),this.emitState(),this.emit("generation-complete",{conversationId:this.id,generation:e}))}async pushSubGeneration(t){r(t),this.subGenerations.set(t.id,t),this.emit("generation",{conversationId:this.id,generation:t}),await this.persistence?.appendGeneration(this.id,t),this.emitState()}async completeSubGeneration(t,e){const i=this.subGenerations.get(t);!i||i.status!=="streaming"||(e!==void 0&&(i.text=e),i.status="completed",i.endedAt=Date.now(),r(i).completedAt=Date.now(),await this.persistence?.appendGeneration(this.id,i),this.emitState())}async cancelSubGeneration(t){const e=this.subGenerations.get(t);!e||e.status!=="streaming"||(e.status="cancelled",e.endedAt=Date.now(),await this.persistence?.appendGeneration(this.id,e),this.emitState())}transcript(){return this.transcription.list()}cancelCurrentGeneration(){const t=this.state.currentGeneration;return t&&t.status==="streaming"&&(t.status="cancelled",t.endedAt=Date.now()),this.state.currentGeneration=null,t??null}buildRealtime(){if(!this.stt&&!this.agents.some(e=>e.llm))return null;const t={conversation:this,stt:this.stt,persistence:this.persistence};return this.agents.length>0?new c({...t,agents:[...this.agents],tts:this.tts,autoExecuteTools:this.autoExecuteTools,...this.maxConcurrentTtsRequests!==void 0?{maxConcurrentTtsRequests:this.maxConcurrentTtsRequests}:{}}):new c(t)}emitState(){this.emit("state",{conversationId:this.id,state:this.state})}}export{T as Conversation};
2
2
  //# sourceMappingURL=conversation.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/conversations/conversation/conversation.ts"],
4
- "sourcesContent": ["import type { Agent } from \"../../agents/agent\";\nimport type { Persistence } from \"../../persistence/persistence\";\nimport type {\n AudioChunk,\n ConversationId,\n ConversationState,\n ConversationStatus,\n Generation,\n Participant,\n ParticipantInput,\n Turn,\n UserId,\n} from \"../types\";\nimport { createConversationState } from \"../types\";\nimport {\n Transcription,\n type TranscriptEntry,\n type TranscriptEntryInput,\n} from \"../transcription/transcription\";\nimport type { ToolCall, ToolCallResult } from \"../types\";\n\nexport interface ConversationOptions {\n id: ConversationId;\n agents?: Agent[];\n persistence?: Persistence;\n}\n\nexport interface ConversationEvents {\n start: { conversationId: ConversationId };\n stop: { conversationId: ConversationId };\n participant: { conversationId: ConversationId; participant: Participant };\n /** Raw audio fed in via `listen()`. Consumed by the orchestrator. */\n \"audio-in\": { conversationId: ConversationId; userId: UserId; audio: AudioChunk };\n /** Generated audio to be played by the application. */\n audio: { conversationId: ConversationId; audio: AudioChunk };\n turn: { conversationId: ConversationId; turn: Turn };\n transcript: { conversationId: ConversationId; entry: TranscriptEntry };\n generation: { conversationId: ConversationId; generation: Generation };\n /** Live STT partials, for captions and fast UX. Not persisted. */\n \"partial-transcript\": {\n conversationId: ConversationId;\n userId: UserId;\n text: string;\n };\n /** The model requested a tool call. Resolve it with `resolveToolCall()`. */\n \"tool-call\": { conversationId: ConversationId; call: ToolCall };\n /** A pending tool call was resolved by the application. */\n \"tool-call-result\": { conversationId: ConversationId; result: ToolCallResult };\n interrupt: { conversationId: ConversationId };\n /** A provider failure (STT, LLM, or TTS). */\n error: { conversationId: ConversationId; error: Error };\n state: { conversationId: ConversationId; state: ConversationState };\n}\n\n/**\n * The public realtime conversation API.\n *\n * A `Conversation` is a runtime handle to a persistent conversation:\n * lifecycle (`start`/`stop`), participants, audio intake (`listen`), and\n * events. The orchestrator (added later) subscribes to `audio-in` and\n * pushes generated audio, turns, transcripts, and tool calls back through\n * the `push*`/`requestToolCall` methods.\n */\nexport class Conversation {\n readonly id: ConversationId;\n readonly agents: readonly Agent[];\n readonly transcription: Transcription;\n readonly state: ConversationState;\n private readonly persistence: Persistence | undefined;\n private readonly listeners = new Map<\n keyof ConversationEvents,\n Set<(payload: never) => void>\n >();\n private readonly pendingToolCallsById = new Map<string, ToolCall>();\n private nextAudioSequence = 0;\n\n constructor(options: ConversationOptions) {\n this.id = options.id;\n this.agents = options.agents ?? [];\n this.persistence = options.persistence;\n this.transcription = new Transcription(this.id);\n this.state = createConversationState();\n }\n\n get status(): ConversationStatus {\n return this.state.status;\n }\n\n get participants(): Participant[] {\n return [...this.state.participants.values()];\n }\n\n start(): void {\n if (this.state.status === \"stopped\") {\n throw new Error(`Conversation \"${this.id}\" has already been stopped`);\n }\n if (this.state.status === \"started\") return;\n this.state.status = \"started\";\n this.emit(\"start\", { conversationId: this.id });\n this.emitState();\n }\n\n async stop(): Promise<void> {\n if (this.state.status === \"stopped\") return;\n this.state.status = \"stopped\";\n this.pendingToolCallsById.clear();\n const cancelled = this.cancelCurrentGeneration();\n if (cancelled) {\n await this.persistence?.appendGeneration(this.id, cancelled);\n }\n await this.persistence?.finalizeConversation(this.id, Date.now());\n this.emit(\"stop\", { conversationId: this.id });\n this.emitState();\n }\n\n async participate(\n input: ParticipantInput | ParticipantInput[],\n ): Promise<Participant[]> {\n if (this.state.status === \"stopped\") {\n throw new Error(`Conversation \"${this.id}\" has already been stopped`);\n }\n\n const inputs = Array.isArray(input) ? input : [input];\n\n // Validate the whole batch before mutating any state.\n const seen = new Set<UserId>();\n for (const item of inputs) {\n if (seen.has(item.userId)) {\n throw new Error(`Duplicate participant \"${item.userId}\" in batch`);\n }\n seen.add(item.userId);\n if (this.state.participants.has(item.userId)) {\n throw new Error(`Participant \"${item.userId}\" already exists`);\n }\n }\n\n const added: Participant[] = [];\n for (const item of inputs) {\n const participant: Participant = {\n userId: item.userId,\n aliases: [...(item.aliases ?? [])],\n joinedAt: Date.now(),\n };\n this.state.participants.set(participant.userId, participant);\n await this.persistence?.addParticipant(this.id, participant);\n added.push(participant);\n this.emit(\"participant\", { conversationId: this.id, participant });\n }\n this.emitState();\n return added;\n }\n\n /**\n * Send an audio packet. Intentionally synchronous: it means \"send this\n * packet\", not \"wait for this utterance to finish\".\n */\n listen(input: { userId: UserId; audio: Uint8Array }): void {\n if (this.state.status !== \"started\") {\n throw new Error(`Conversation \"${this.id}\" is not started`);\n }\n if (!this.state.participants.has(input.userId)) {\n throw new Error(`Unknown participant \"${input.userId}\"`);\n }\n const chunk: AudioChunk = {\n data: input.audio,\n timestamp: Date.now(),\n sequence: this.nextAudioSequence++,\n };\n this.emit(\"audio-in\", { conversationId: this.id, userId: input.userId, audio: chunk });\n }\n\n /** Interrupt the current agent output (stop TTS, cancel the generation). */\n interrupt(): void {\n const cancelled = this.cancelCurrentGeneration();\n // Persist asynchronously: interruption must stay synchronous for the\n // realtime path.\n if (cancelled) {\n void this.persistence?.appendGeneration(this.id, cancelled).catch(() => {});\n }\n this.emit(\"interrupt\", { conversationId: this.id });\n this.emitState();\n }\n\n on<K extends keyof ConversationEvents>(\n event: K,\n listener: (payload: ConversationEvents[K]) => void,\n ): () => void {\n let set = this.listeners.get(event);\n if (!set) {\n set = new Set();\n this.listeners.set(event, set);\n }\n set.add(listener as (payload: never) => void);\n return () => {\n set!.delete(listener as (payload: never) => void);\n };\n }\n\n /**\n * Emit an event. Primarily used by the orchestrator to push output\n * (audio, turns, transcripts) into the conversation.\n */\n emit<K extends keyof ConversationEvents>(\n event: K,\n payload: ConversationEvents[K],\n ): void {\n const set = this.listeners.get(event);\n if (!set) return;\n for (const listener of [...set]) {\n listener(payload as never);\n }\n }\n\n // -------------------------------------------------------------------------\n // Orchestrator-facing output\n // -------------------------------------------------------------------------\n\n /** Push a chunk of generated audio to the application. */\n pushAudio(audio: AudioChunk): void {\n this.emit(\"audio\", { conversationId: this.id, audio });\n }\n\n /** Push a completed participant turn into the conversation. */\n async pushTurn(turn: Turn): Promise<void> {\n this.state.currentTurn = turn;\n this.emit(\"turn\", { conversationId: this.id, turn });\n await this.persistence?.appendTurn(this.id, turn);\n this.emitState();\n }\n\n /** Append a transcript entry and notify listeners. */\n async pushTranscript(\n input: Omit<TranscriptEntryInput, \"conversationId\">,\n ): Promise<TranscriptEntry> {\n const entry = this.transcription.append({ ...input });\n this.state.transcriptCount++;\n this.emit(\"transcript\", { conversationId: this.id, entry });\n await this.persistence?.appendTranscript(this.id, entry);\n this.emitState();\n return entry;\n }\n\n /** Push an agent generation into the conversation. */\n async pushGeneration(generation: Generation): Promise<void> {\n this.state.currentGeneration = generation;\n this.emit(\"generation\", { conversationId: this.id, generation });\n await this.persistence?.appendGeneration(this.id, generation);\n this.emitState();\n }\n\n // -------------------------------------------------------------------------\n // Orchestrator-facing tool calls\n // -------------------------------------------------------------------------\n\n /** Tool calls requested by the model that are awaiting resolution. */\n get pendingToolCalls(): ToolCall[] {\n return [...this.pendingToolCallsById.values()];\n }\n\n /**\n * Track and emit a tool call requested by the model. The application\n * listens for `tool-call` events, executes the tool in its own backend,\n * and reports back through `resolveToolCall()`.\n */\n requestToolCall(call: ToolCall): void {\n this.pendingToolCallsById.set(call.id, call);\n this.emit(\"tool-call\", { conversationId: this.id, call });\n this.emitState();\n }\n\n /** Resolve a pending tool call with a result or an error. */\n resolveToolCall(result: ToolCallResult): void {\n if (!this.pendingToolCallsById.has(result.id)) {\n throw new Error(`No pending tool call \"${result.id}\"`);\n }\n this.pendingToolCallsById.delete(result.id);\n this.emit(\"tool-call-result\", { conversationId: this.id, result });\n this.emitState();\n }\n\n /** Mark the current generation as completed, recording its final text. */\n async completeGeneration(text?: string): Promise<void> {\n const generation = this.state.currentGeneration;\n if (generation && generation.status === \"streaming\") {\n if (text !== undefined) generation.text = text;\n generation.status = \"completed\";\n generation.endedAt = Date.now();\n await this.persistence?.appendGeneration(this.id, generation);\n this.emitState();\n }\n }\n\n /** The live in-memory transcript. */\n transcript(): TranscriptEntry[] {\n return this.transcription.list();\n }\n\n private cancelCurrentGeneration(): Generation | null {\n const generation = this.state.currentGeneration;\n if (generation && generation.status === \"streaming\") {\n generation.status = \"cancelled\";\n generation.endedAt = Date.now();\n }\n this.state.currentGeneration = null;\n return generation ?? null;\n }\n\n private emitState(): void {\n this.emit(\"state\", { conversationId: this.id, state: this.state });\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["createConversationState", "Transcription", "Conversation", "__name", "options", "cancelled", "input", "inputs", "seen", "item", "added", "participant", "chunk", "event", "listener", "set", "payload", "audio", "turn", "entry", "generation", "call", "result", "text"]
4
+ "sourcesContent": ["import type { Agent } from \"../../agents/agent\";\nimport type { Persistence } from \"../../persistence/persistence\";\nimport { Orchestrator } from \"../orchestration/orchestrator/orchestrator\";\nimport type { STT } from \"../../providers/stt/types\";\nimport type { TTS } from \"../../providers/tts/types\";\nimport type {\n AudioChunk,\n ConversationId,\n ConversationState,\n ConversationStatus,\n Generation,\n GenerationTiming,\n Participant,\n ParticipantInput,\n Turn,\n UserId,\n} from \"../types\";\nimport { createConversationState } from \"../types\";\nimport {\n Transcription,\n type TranscriptEntry,\n type TranscriptEntryInput,\n} from \"../transcription/transcription\";\nimport type { ToolCall, ToolCallResult } from \"../types\";\n\n/** Ensure a generation carries a timing record, initialized from its start. */\nfunction initTiming(generation: Generation): GenerationTiming {\n return (generation.timing ??= { startedAt: generation.startedAt });\n}\n\n/** Timing points a generation can record, keyed by the stream event. */\ntype TimingPoint = \"firstToken\" | \"firstTtsText\" | \"firstTtsRequest\" | \"firstTtsAudio\";\n\nconst timingField: Record<TimingPoint, keyof GenerationTiming> = {\n firstToken: \"firstTokenAt\",\n firstTtsText: \"firstTtsTextAt\",\n firstTtsRequest: \"firstTtsRequestAt\",\n firstTtsAudio: \"firstTtsAudioAt\",\n};\n\nexport interface ConversationOptions {\n id: ConversationId;\n agents?: Agent[];\n persistence?: Persistence;\n /**\n * STT provider used to attach realtime processing automatically on\n * `start()`.\n */\n stt?: STT;\n tts?: TTS;\n /**\n * Execute the agents' tools automatically (default `true`), feeding each\n * tool's result back into the model loop. Set `false` to resolve tool\n * calls from your own backend via `resolveToolCall()`.\n */\n autoExecuteTools?: boolean;\n /**\n * TTS synthesis concurrency (default 2): more in-flight requests let a\n * multi-sentence reply synthesize in parallel, removing the gaps between\n * sentences, at the cost of provider concurrency. See\n * `SpeechPipelineOptions.maxConcurrentRequests`.\n */\n maxConcurrentTtsRequests?: number;\n /**\n * Hold window (ms) for out-of-order audio (default 100). When `listen()`\n * receives a chunk whose `sequence` skips ahead of the expected one, the\n * chunk is held briefly so a packet still in flight can fill the gap \u2014\n * netcode-style reordering, like client-side prediction in multiplayer\n * games. When the window expires the gap is skipped and the buffered\n * chunks are released in order. In-order audio (the common case) is\n * emitted immediately, with no added latency.\n */\n audioReorderMs?: number;\n}\n\n/** Per-participant reorder state for sequenced audio (`listen({ sequence })`). */\ninterface AudioReorderState {\n /**\n * Next sequence expected to be emitted. `null` until the user's first\n * chunk adopts its sequence as the baseline \u2014 earlier history is unknown.\n */\n next: number | null;\n /** Chunks received ahead of `next`, keyed by sequence. */\n pending: Map<number, Uint8Array>;\n /** Timer that releases `pending` when a gap outlives the hold window. */\n timer: ReturnType<typeof setTimeout> | null;\n}\n\nexport interface ConversationEvents {\n start: { conversationId: ConversationId };\n stop: { conversationId: ConversationId };\n participant: { conversationId: ConversationId; participant: Participant };\n /** Raw audio fed in via `listen()`. Consumed by the orchestrator. */\n \"audio-in\": { conversationId: ConversationId; userId: UserId; audio: AudioChunk };\n /** A finalized text turn via `send()`. Consumed by the orchestrator. */\n \"text-in\": { conversationId: ConversationId; userId: UserId; text: string };\n /** Generated audio to be played by the application. */\n audio: { conversationId: ConversationId; audio: AudioChunk };\n turn: { conversationId: ConversationId; turn: Turn };\n transcript: { conversationId: ConversationId; entry: TranscriptEntry };\n generation: { conversationId: ConversationId; generation: Generation };\n /**\n * The current generation's text, streamed as LLM deltas arrive. Emitted by\n * the orchestrator; the agent name is included when the generation is known.\n */\n \"text-delta\": {\n conversationId: ConversationId;\n text: string;\n agentName?: string;\n };\n /** The current (top-level) generation finished generating. */\n \"generation-complete\": {\n conversationId: ConversationId;\n generation: Generation;\n };\n /** Live STT partials, for captions and fast UX. Not persisted. */\n \"partial-transcript\": {\n conversationId: ConversationId;\n userId: UserId;\n text: string;\n };\n /** The model requested a tool call. Resolve it with `resolveToolCall()`. */\n \"tool-call\": { conversationId: ConversationId; call: ToolCall };\n /** A pending tool call was resolved by the application. */\n \"tool-call-result\": { conversationId: ConversationId; result: ToolCallResult };\n interrupt: { conversationId: ConversationId };\n /** A provider failure (STT, LLM, or TTS). */\n error: { conversationId: ConversationId; error: Error };\n state: { conversationId: ConversationId; state: ConversationState };\n}\n\n/**\n * The public realtime conversation API.\n *\n * A `Conversation` is a runtime handle to a persistent conversation:\n * lifecycle (`start`/`stop`), participants, audio intake (`listen`), text\n * turns (`send`), and events. When an STT provider or agents are configured,\n * `start()` automatically attaches the orchestrator, which runs the\n * STT/LLM/TTS pipeline (or routes text turns) and pushes generated audio,\n * turns, transcripts, and tool calls back through conversation events.\n */\nexport class Conversation {\n readonly id: ConversationId;\n readonly agents: readonly Agent[];\n readonly transcription: Transcription;\n readonly state: ConversationState;\n private readonly persistence: Persistence | undefined;\n private readonly stt: STT | undefined;\n private readonly tts: TTS | undefined;\n private readonly autoExecuteTools: boolean;\n private readonly maxConcurrentTtsRequests: number | undefined;\n private readonly listeners = new Map<\n keyof ConversationEvents,\n Set<(payload: never) => void>\n >();\n private readonly pendingToolCallsById = new Map<string, ToolCall>();\n private readonly subGenerations = new Map<string, Generation>();\n private readonly audioReorderMs: number;\n private readonly audioReorder = new Map<UserId, AudioReorderState>();\n private nextAudioSequence = 0;\n\n constructor(options: ConversationOptions) {\n this.id = options.id;\n this.agents = options.agents ?? [];\n this.persistence = options.persistence;\n this.stt = options.stt;\n this.tts = options.tts;\n this.autoExecuteTools = options.autoExecuteTools ?? true;\n this.maxConcurrentTtsRequests = options.maxConcurrentTtsRequests;\n this.audioReorderMs = options.audioReorderMs ?? 100;\n this.transcription = new Transcription(this.id);\n this.state = createConversationState();\n }\n\n get status(): ConversationStatus {\n return this.state.status;\n }\n\n get participants(): Participant[] {\n return [...this.state.participants.values()];\n }\n\n /**\n * Move the conversation into the started state. This attaches the\n * orchestrator whenever there is realtime work: an STT provider (voice\n * pipeline) or agents to route text turns to (`send()`).\n */\n async start(): Promise<void> {\n if (this.state.status === \"stopped\") {\n throw new Error(`Conversation \"${this.id}\" has already been stopped`);\n }\n if (this.state.status === \"started\") return;\n\n // Validate the realtime configuration before mutating any state.\n const orchestrator = this.buildRealtime();\n\n this.state.status = \"started\";\n this.emit(\"start\", { conversationId: this.id });\n this.emitState();\n\n await orchestrator?.start();\n }\n\n async stop(): Promise<void> {\n if (this.state.status === \"stopped\") return;\n this.state.status = \"stopped\";\n for (const state of this.audioReorder.values()) this.clearReorderTimer(state);\n this.audioReorder.clear();\n this.pendingToolCallsById.clear();\n const cancelled = this.cancelCurrentGeneration();\n if (cancelled) {\n await this.persistence?.appendGeneration(this.id, cancelled);\n }\n for (const sub of [...this.subGenerations.values()]) {\n if (sub.status === \"streaming\") {\n sub.status = \"cancelled\";\n sub.endedAt = Date.now();\n await this.persistence?.appendGeneration(this.id, sub);\n }\n }\n await this.persistence?.finalizeConversation(this.id, Date.now());\n this.emit(\"stop\", { conversationId: this.id });\n this.emitState();\n }\n\n async participate(\n input: ParticipantInput | ParticipantInput[],\n ): Promise<Participant[]> {\n if (this.state.status === \"stopped\") {\n throw new Error(`Conversation \"${this.id}\" has already been stopped`);\n }\n\n const inputs = Array.isArray(input) ? input : [input];\n\n // Validate the whole batch before mutating any state.\n const seen = new Set<UserId>();\n for (const item of inputs) {\n if (seen.has(item.userId)) {\n throw new Error(`Duplicate participant \"${item.userId}\" in batch`);\n }\n seen.add(item.userId);\n if (this.state.participants.has(item.userId)) {\n throw new Error(`Participant \"${item.userId}\" already exists`);\n }\n }\n\n const added: Participant[] = [];\n for (const item of inputs) {\n const participant: Participant = {\n userId: item.userId,\n aliases: [...(item.aliases ?? [])],\n joinedAt: Date.now(),\n };\n this.state.participants.set(participant.userId, participant);\n await this.persistence?.addParticipant(this.id, participant);\n added.push(participant);\n this.emit(\"participant\", { conversationId: this.id, participant });\n }\n this.emitState();\n return added;\n }\n\n /**\n * Send an audio packet. Intentionally synchronous: it means \"send this\n * packet\", not \"wait for this utterance to finish\".\n *\n * Pass the sender's `sequence` number to enable netcode-style reordering:\n * chunks arriving ahead of a gap are held for `audioReorderMs` so an\n * earlier packet still in flight can fill it, then released in order\n * (gaps are skipped when the window expires). The orchestrator and STT\n * always see the participant's audio in sequence order. Without a\n * `sequence`, the chunk is emitted on arrival, as-is.\n */\n listen(input: { userId: UserId; audio: Uint8Array; sequence?: number }): void {\n if (this.state.status !== \"started\") {\n throw new Error(`Conversation \"${this.id}\" is not started`);\n }\n if (!this.state.participants.has(input.userId)) {\n throw new Error(`Unknown participant \"${input.userId}\"`);\n }\n if (input.sequence === undefined) {\n this.emitAudioIn(input.userId, input.audio);\n return;\n }\n this.reorderAudio(input.userId, input.audio, input.sequence);\n }\n\n /** Emit an audio-in event with the conversation's own sequence numbering. */\n private emitAudioIn(userId: UserId, data: Uint8Array): void {\n const chunk: AudioChunk = {\n data,\n timestamp: Date.now(),\n sequence: this.nextAudioSequence++,\n };\n this.emit(\"audio-in\", { conversationId: this.id, userId, audio: chunk });\n }\n\n /** Hold/drain logic for sequenced audio, keyed per participant. */\n private reorderAudio(userId: UserId, data: Uint8Array, sequence: number): void {\n let state = this.audioReorder.get(userId);\n if (!state) {\n state = { next: null, pending: new Map(), timer: null };\n this.audioReorder.set(userId, state);\n }\n // The participant's first chunk anchors the stream: anything before it\n // is unknown history.\n if (state.next === null) state.next = sequence;\n if (sequence < state.next) return; // late or duplicate \u2014 already released\n if (sequence === state.next) {\n this.clearReorderTimer(state);\n this.emitAudioIn(userId, data);\n state.next++;\n while (state.pending.has(state.next)) {\n const held = state.pending.get(state.next)!;\n state.pending.delete(state.next);\n this.emitAudioIn(userId, held);\n state.next++;\n }\n return;\n }\n // Ahead of the expected sequence: hold so the gap can fill, and start\n // the release timer if it is not already running.\n state.pending.set(sequence, data);\n if (!state.timer) {\n state.timer = setTimeout(() => {\n state.timer = null;\n this.releaseReorderBuffer(userId);\n }, this.audioReorderMs);\n }\n }\n\n /**\n * Release everything a participant has buffered, in sequence order,\n * skipping the gap that never filled.\n */\n private releaseReorderBuffer(userId: UserId): void {\n const state = this.audioReorder.get(userId);\n if (!state) return;\n this.clearReorderTimer(state);\n while (state.pending.size > 0) {\n const sequence = Math.min(...state.pending.keys());\n const data = state.pending.get(sequence)!;\n state.pending.delete(sequence);\n state.next = sequence + 1;\n this.emitAudioIn(userId, data);\n }\n }\n\n private clearReorderTimer(state: AudioReorderState): void {\n if (state.timer) {\n clearTimeout(state.timer);\n state.timer = null;\n }\n }\n\n /**\n * Send a finalized text turn, bypassing STT. Triggers the same pipeline as\n * a transcribed utterance (routing, coordination, generation, resume) \u2014\n * useful for text-first integrations such as chat or Discord text channels.\n */\n send(input: { userId: UserId; text: string }): void {\n if (this.state.status !== \"started\") {\n throw new Error(`Conversation \"${this.id}\" is not started`);\n }\n if (!this.state.participants.has(input.userId)) {\n throw new Error(`Unknown participant \"${input.userId}\"`);\n }\n this.emit(\"text-in\", {\n conversationId: this.id,\n userId: input.userId,\n text: input.text,\n });\n }\n\n /**\n * Stop the currently active generation and prevent any further generated\n * audio from reaching the conversation. The orchestrator cancels the LLM\n * and TTS streams, force-resolves pending tool calls, and discards queued\n * audio; the next participant turn starts fresh. Interrupt responsiveness\n * is a tested invariant \u2014 audio stops within ~100ms of this call.\n */\n interrupt(): void {\n const cancelled = this.cancelCurrentGeneration();\n // Persist asynchronously: interruption must stay synchronous for the\n // realtime path.\n if (cancelled) {\n void this.persistence?.appendGeneration(this.id, cancelled).catch(() => {});\n }\n this.emit(\"interrupt\", { conversationId: this.id });\n this.emitState();\n }\n\n on<K extends keyof ConversationEvents>(\n event: K,\n listener: (payload: ConversationEvents[K]) => void,\n ): () => void {\n let set = this.listeners.get(event);\n if (!set) {\n set = new Set();\n this.listeners.set(event, set);\n }\n set.add(listener as (payload: never) => void);\n return () => {\n set!.delete(listener as (payload: never) => void);\n };\n }\n\n /**\n * Emit an event. Primarily used by the orchestrator to push output\n * (audio, turns, transcripts) into the conversation.\n */\n emit<K extends keyof ConversationEvents>(\n event: K,\n payload: ConversationEvents[K],\n ): void {\n const set = this.listeners.get(event);\n if (!set) return;\n for (const listener of [...set]) {\n listener(payload as never);\n }\n }\n\n // -------------------------------------------------------------------------\n // Orchestrator-facing output\n // -------------------------------------------------------------------------\n\n /** Push a chunk of generated audio to the application. */\n pushAudio(audio: AudioChunk): void {\n // Record when the first synthesized chunk reached the application for the\n // in-flight generation (speech-to-delivery latency).\n const generation = this.state.currentGeneration;\n if (generation && generation.status === \"streaming\") {\n const timing = initTiming(generation);\n if (timing.firstAudioAt === undefined) {\n timing.firstAudioAt = Date.now();\n void this.persistence?.appendGeneration(this.id, generation).catch(() => {});\n this.emitState();\n }\n }\n this.emit(\"audio\", { conversationId: this.id, audio });\n }\n\n /** Push a completed participant turn into the conversation. */\n async pushTurn(turn: Turn): Promise<void> {\n this.state.currentTurn = turn;\n this.emit(\"turn\", { conversationId: this.id, turn });\n await this.persistence?.appendTurn(this.id, turn);\n this.emitState();\n }\n\n /** Append a transcript entry and notify listeners. */\n async pushTranscript(\n input: Omit<TranscriptEntryInput, \"conversationId\">,\n ): Promise<TranscriptEntry> {\n const entry = this.transcription.append({ ...input });\n this.state.transcriptCount++;\n this.emit(\"transcript\", { conversationId: this.id, entry });\n await this.persistence?.appendTranscript(this.id, entry);\n this.emitState();\n return entry;\n }\n\n /**\n * Stream the current generation's text, as produced by the orchestrator\n * from LLM deltas. Emits the `text-delta` event so applications can render\n * or act on partial replies.\n */\n pushTextDelta(text: string): void {\n const agentName = this.state.currentGeneration?.agentName;\n this.emit(\"text-delta\", { conversationId: this.id, text, agentName });\n }\n\n /** Push an agent generation into the conversation. */\n async pushGeneration(generation: Generation): Promise<void> {\n initTiming(generation);\n this.state.currentGeneration = generation;\n this.emit(\"generation\", { conversationId: this.id, generation });\n await this.persistence?.appendGeneration(this.id, generation);\n this.emitState();\n }\n\n /**\n * Record a timing point on a generation. Without an id this targets the\n * current generation; with one, a dispatched sub-generation. Each point is\n * recorded at most once.\n */\n noteTiming(point: TimingPoint, generationId?: string): void {\n const generation = generationId\n ? this.subGenerations.get(generationId)\n : this.state.currentGeneration;\n if (!generation || generation.status !== \"streaming\") return;\n const timing = initTiming(generation);\n const field = timingField[point];\n if (timing[field] !== undefined) return;\n timing[field] = Date.now();\n void this.persistence?.appendGeneration(this.id, generation).catch(() => {});\n this.emitState();\n }\n\n // -------------------------------------------------------------------------\n // Orchestrator-facing tool calls\n // -------------------------------------------------------------------------\n\n /** Tool calls requested by the model that are awaiting resolution. */\n get pendingToolCalls(): ToolCall[] {\n return [...this.pendingToolCallsById.values()];\n }\n\n /**\n * Track and emit a tool call requested by the model. The application\n * listens for `tool-call` events, executes the tool in its own backend,\n * and reports back through `resolveToolCall()`.\n */\n requestToolCall(call: ToolCall): void {\n this.pendingToolCallsById.set(call.id, call);\n this.emit(\"tool-call\", { conversationId: this.id, call });\n this.emitState();\n }\n\n /** Resolve a pending tool call with a result or an error. */\n resolveToolCall(result: ToolCallResult): void {\n if (!this.pendingToolCallsById.has(result.id)) {\n throw new Error(`No pending tool call \"${result.id}\"`);\n }\n this.pendingToolCallsById.delete(result.id);\n this.emit(\"tool-call-result\", { conversationId: this.id, result });\n this.emitState();\n }\n\n /** Mark the current generation as completed, recording its final text. */\n async completeGeneration(text?: string): Promise<void> {\n const generation = this.state.currentGeneration;\n if (generation && generation.status === \"streaming\") {\n if (text !== undefined) generation.text = text;\n generation.status = \"completed\";\n generation.endedAt = Date.now();\n initTiming(generation).completedAt = Date.now();\n await this.persistence?.appendGeneration(this.id, generation);\n this.emitState();\n this.emit(\"generation-complete\", { conversationId: this.id, generation });\n }\n }\n\n // -------------------------------------------------------------------------\n // Dispatched sub-generations\n // -------------------------------------------------------------------------\n\n /**\n * Push a sub-generation: a task the coordinator dispatched to another\n * agent. Unlike `pushGeneration`, it does not become the conversation's\n * current generation, so parallel tasks don't clobber the coordinator's\n * own in-flight generation.\n */\n async pushSubGeneration(generation: Generation): Promise<void> {\n initTiming(generation);\n this.subGenerations.set(generation.id, generation);\n this.emit(\"generation\", { conversationId: this.id, generation });\n await this.persistence?.appendGeneration(this.id, generation);\n this.emitState();\n }\n\n /** Mark a dispatched sub-generation as completed with its final text. */\n async completeSubGeneration(id: string, text?: string): Promise<void> {\n const generation = this.subGenerations.get(id);\n if (!generation || generation.status !== \"streaming\") return;\n if (text !== undefined) generation.text = text;\n generation.status = \"completed\";\n generation.endedAt = Date.now();\n initTiming(generation).completedAt = Date.now();\n await this.persistence?.appendGeneration(this.id, generation);\n this.emitState();\n }\n\n /** Mark a dispatched sub-generation as cancelled (e.g. barge-in). */\n async cancelSubGeneration(id: string): Promise<void> {\n const generation = this.subGenerations.get(id);\n if (!generation || generation.status !== \"streaming\") return;\n generation.status = \"cancelled\";\n generation.endedAt = Date.now();\n await this.persistence?.appendGeneration(this.id, generation);\n this.emitState();\n }\n\n /** The live in-memory transcript. */\n transcript(): TranscriptEntry[] {\n return this.transcription.list();\n }\n\n private cancelCurrentGeneration(): Generation | null {\n const generation = this.state.currentGeneration;\n if (generation && generation.status === \"streaming\") {\n generation.status = \"cancelled\";\n generation.endedAt = Date.now();\n }\n this.state.currentGeneration = null;\n return generation ?? null;\n }\n\n private buildRealtime(): Orchestrator | null {\n // Attach the orchestrator whenever there is realtime work: an STT\n // provider for voice, or agents with an LLM to route text turns to\n // (`send()`). Agents without an LLM have nothing to generate.\n if (!this.stt && !this.agents.some((agent) => agent.llm)) return null;\n const common = {\n conversation: this,\n stt: this.stt,\n persistence: this.persistence,\n };\n // With agents the orchestrator coordinates the roster, routing each turn\n // to an agent by name/alias. Without agents it runs transcription-only.\n return this.agents.length > 0\n ? new Orchestrator({\n ...common,\n agents: [...this.agents],\n tts: this.tts,\n autoExecuteTools: this.autoExecuteTools,\n ...(this.maxConcurrentTtsRequests !== undefined\n ? { maxConcurrentTtsRequests: this.maxConcurrentTtsRequests }\n : {}),\n })\n : new Orchestrator(common);\n }\n\n private emitState(): void {\n this.emit(\"state\", { conversationId: this.id, state: this.state });\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["Orchestrator", "createConversationState", "Transcription", "initTiming", "generation", "__name", "timingField", "Conversation", "options", "orchestrator", "state", "cancelled", "sub", "input", "inputs", "seen", "item", "added", "participant", "userId", "data", "chunk", "sequence", "held", "event", "listener", "set", "payload", "audio", "timing", "turn", "entry", "text", "agentName", "point", "generationId", "field", "call", "result", "id", "agent", "common"]
7
7
  }
@@ -1,2 +1,2 @@
1
- var o=Object.defineProperty;var n=(r,e)=>o(r,"name",{value:e,configurable:!0});import{Conversation as s}from"./conversation/conversation.js";class p{constructor(e){this.persistence=e}persistence;static{n(this,"Conversations")}async create(e={}){const t=await this.persistence.createConversation({agentNames:(e.agents??[]).map(i=>i.name)});return new s({id:t.id,agents:e.agents,persistence:this.persistence})}async transcript(e){return await this.requireConversation(e),this.persistence.listTranscript(e)}async get(e){const t=await this.persistence.getConversation(e);return t?new s({id:t.id,persistence:this.persistence}):null}async requireConversation(e){if(!await this.persistence.getConversation(e))throw new Error(`Conversation "${e}" not found`)}}export{p as Conversations};
1
+ var i=Object.defineProperty;var s=(r,e)=>i(r,"name",{value:e,configurable:!0});import{Conversation as n}from"./conversation/conversation.js";class u{static{s(this,"Conversations")}persistence;stt;tts;autoExecuteTools;constructor(e){this.persistence=e.persistence,this.stt=e.stt,this.tts=e.tts,this.autoExecuteTools=e.autoExecuteTools??!0}async create(e={}){const t=await this.persistence.createConversation({agentNames:(e.agents??[]).map(o=>o.name)});return new n({id:t.id,agents:e.agents,persistence:this.persistence,stt:this.stt,tts:this.tts,autoExecuteTools:e.autoExecuteTools??this.autoExecuteTools,...e.maxConcurrentTtsRequests!==void 0?{maxConcurrentTtsRequests:e.maxConcurrentTtsRequests}:{},...e.audioReorderMs!==void 0?{audioReorderMs:e.audioReorderMs}:{}})}async transcript(e){return await this.requireConversation(e),this.persistence.listTranscript(e)}async get(e){const t=await this.persistence.getConversation(e);return t?new n({id:t.id,persistence:this.persistence}):null}async requireConversation(e){if(!await this.persistence.getConversation(e))throw new Error(`Conversation "${e}" not found`)}}export{u as Conversations};
2
2
  //# sourceMappingURL=conversations.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/conversations/conversations.ts"],
4
- "sourcesContent": ["import type { Agent } from \"../agents/agent\";\nimport type { Persistence } from \"../persistence/persistence\";\nimport type { ConversationId } from \"./types\";\nimport type { TranscriptEntry } from \"./transcription/transcription\";\nimport { Conversation } from \"./conversation/conversation\";\n\nexport interface CreateConversationOptions {\n agents?: Agent[];\n}\n\n/**\n * The conversations API surface of a Pipeflow instance: create persistent\n * conversations and retrieve their transcripts.\n */\nexport class Conversations {\n constructor(private readonly persistence: Persistence) {}\n\n /** Create a persistent conversation. Realtime execution is separate. */\n async create(options: CreateConversationOptions = {}): Promise<Conversation> {\n const record = await this.persistence.createConversation({\n agentNames: (options.agents ?? []).map((agent) => agent.name),\n });\n return new Conversation({\n id: record.id,\n agents: options.agents,\n persistence: this.persistence,\n });\n }\n\n /** Retrieve the persisted transcript of a conversation. */\n async transcript(id: ConversationId): Promise<TranscriptEntry[]> {\n await this.requireConversation(id);\n return this.persistence.listTranscript(id);\n }\n\n /** Rehydrate a runtime handle for an existing conversation. */\n async get(id: ConversationId): Promise<Conversation | null> {\n const record = await this.persistence.getConversation(id);\n if (!record) return null;\n return new Conversation({ id: record.id, persistence: this.persistence });\n }\n\n private async requireConversation(id: ConversationId): Promise<void> {\n const record = await this.persistence.getConversation(id);\n if (!record) {\n throw new Error(`Conversation \"${id}\" not found`);\n }\n }\n}\n"],
5
- "mappings": "+EAIA,OAAS,gBAAAA,MAAoB,8BAUtB,MAAMC,CAAc,CACzB,YAA6BC,EAA0B,CAA1B,iBAAAA,CAA2B,CAA3B,YAf/B,MAc2B,CAAAC,EAAA,sBAIzB,MAAM,OAAOC,EAAqC,CAAC,EAA0B,CAC3E,MAAMC,EAAS,MAAM,KAAK,YAAY,mBAAmB,CACvD,YAAaD,EAAQ,QAAU,CAAC,GAAG,IAAKE,GAAUA,EAAM,IAAI,CAC9D,CAAC,EACD,OAAO,IAAIN,EAAa,CACtB,GAAIK,EAAO,GACX,OAAQD,EAAQ,OAChB,YAAa,KAAK,WACpB,CAAC,CACH,CAGA,MAAM,WAAWG,EAAgD,CAC/D,aAAM,KAAK,oBAAoBA,CAAE,EAC1B,KAAK,YAAY,eAAeA,CAAE,CAC3C,CAGA,MAAM,IAAIA,EAAkD,CAC1D,MAAMF,EAAS,MAAM,KAAK,YAAY,gBAAgBE,CAAE,EACxD,OAAKF,EACE,IAAIL,EAAa,CAAE,GAAIK,EAAO,GAAI,YAAa,KAAK,WAAY,CAAC,EADpD,IAEtB,CAEA,MAAc,oBAAoBE,EAAmC,CAEnE,GAAI,CADW,MAAM,KAAK,YAAY,gBAAgBA,CAAE,EAEtD,MAAM,IAAI,MAAM,iBAAiBA,CAAE,aAAa,CAEpD,CACF",
6
- "names": ["Conversation", "Conversations", "persistence", "__name", "options", "record", "agent", "id"]
4
+ "sourcesContent": ["import type { Agent } from \"../agents/agent\";\nimport type { Persistence } from \"../persistence/persistence\";\nimport type { STT } from \"../providers/stt/types\";\nimport type { TTS } from \"../providers/tts/types\";\nimport type { ConversationId } from \"./types\";\nimport type { TranscriptEntry } from \"./transcription/transcription\";\nimport { Conversation } from \"./conversation/conversation\";\n\nexport interface CreateConversationOptions {\n agents?: Agent[];\n /**\n * Execute the agents' tools automatically (default `true`). Set `false`\n * for this conversation to resolve tool calls from your own backend via\n * `resolveToolCall()`. Overrides the `Conversations`-level default.\n */\n autoExecuteTools?: boolean;\n /**\n * TTS synthesis concurrency (default 2). More in-flight requests let a\n * multi-sentence reply synthesize in parallel, removing the gaps between\n * sentences, at the cost of provider concurrency \u2014 some free TTS variants\n * rate-limit concurrent requests.\n */\n maxConcurrentTtsRequests?: number;\n /**\n * Hold window (ms) for out-of-order audio (default 100). See\n * `ConversationOptions.audioReorderMs`.\n */\n audioReorderMs?: number;\n}\n\nexport interface ConversationsOptions {\n persistence: Persistence;\n /** Passed to conversations so `start()` can attach realtime processing. */\n stt?: STT;\n tts?: TTS;\n /**\n * Default for created conversations: auto-execute the agents' tools\n * (default `true`). See `CreateConversationOptions.autoExecuteTools`.\n */\n autoExecuteTools?: boolean;\n}\n\n/**\n * The conversations API surface of a Pipeflow instance: create persistent\n * conversations and retrieve their transcripts.\n */\nexport class Conversations {\n private readonly persistence: Persistence;\n private readonly stt: STT | undefined;\n private readonly tts: TTS | undefined;\n private readonly autoExecuteTools: boolean;\n\n constructor(options: ConversationsOptions) {\n this.persistence = options.persistence;\n this.stt = options.stt;\n this.tts = options.tts;\n this.autoExecuteTools = options.autoExecuteTools ?? true;\n }\n\n /** Create a persistent conversation. Realtime execution is separate. */\n async create(options: CreateConversationOptions = {}): Promise<Conversation> {\n const record = await this.persistence.createConversation({\n agentNames: (options.agents ?? []).map((agent) => agent.name),\n });\n return new Conversation({\n id: record.id,\n agents: options.agents,\n persistence: this.persistence,\n stt: this.stt,\n tts: this.tts,\n autoExecuteTools: options.autoExecuteTools ?? this.autoExecuteTools,\n ...(options.maxConcurrentTtsRequests !== undefined\n ? { maxConcurrentTtsRequests: options.maxConcurrentTtsRequests }\n : {}),\n ...(options.audioReorderMs !== undefined\n ? { audioReorderMs: options.audioReorderMs }\n : {}),\n });\n }\n\n /** Retrieve the persisted transcript of a conversation. */\n async transcript(id: ConversationId): Promise<TranscriptEntry[]> {\n await this.requireConversation(id);\n return this.persistence.listTranscript(id);\n }\n\n /** Rehydrate a runtime handle for an existing conversation. */\n async get(id: ConversationId): Promise<Conversation | null> {\n const record = await this.persistence.getConversation(id);\n if (!record) return null;\n return new Conversation({ id: record.id, persistence: this.persistence });\n }\n\n private async requireConversation(id: ConversationId): Promise<void> {\n const record = await this.persistence.getConversation(id);\n if (!record) {\n throw new Error(`Conversation \"${id}\" not found`);\n }\n }\n}\n"],
5
+ "mappings": "+EAMA,OAAS,gBAAAA,MAAoB,8BAwCtB,MAAMC,CAAc,CA9C3B,MA8C2B,CAAAC,EAAA,sBACR,YACA,IACA,IACA,iBAEjB,YAAYC,EAA+B,CACzC,KAAK,YAAcA,EAAQ,YAC3B,KAAK,IAAMA,EAAQ,IACnB,KAAK,IAAMA,EAAQ,IACnB,KAAK,iBAAmBA,EAAQ,kBAAoB,EACtD,CAGA,MAAM,OAAOA,EAAqC,CAAC,EAA0B,CAC3E,MAAMC,EAAS,MAAM,KAAK,YAAY,mBAAmB,CACvD,YAAaD,EAAQ,QAAU,CAAC,GAAG,IAAKE,GAAUA,EAAM,IAAI,CAC9D,CAAC,EACD,OAAO,IAAIL,EAAa,CACtB,GAAII,EAAO,GACX,OAAQD,EAAQ,OAChB,YAAa,KAAK,YAClB,IAAK,KAAK,IACV,IAAK,KAAK,IACV,iBAAkBA,EAAQ,kBAAoB,KAAK,iBACnD,GAAIA,EAAQ,2BAA6B,OACrC,CAAE,yBAA0BA,EAAQ,wBAAyB,EAC7D,CAAC,EACL,GAAIA,EAAQ,iBAAmB,OAC3B,CAAE,eAAgBA,EAAQ,cAAe,EACzC,CAAC,CACP,CAAC,CACH,CAGA,MAAM,WAAWG,EAAgD,CAC/D,aAAM,KAAK,oBAAoBA,CAAE,EAC1B,KAAK,YAAY,eAAeA,CAAE,CAC3C,CAGA,MAAM,IAAIA,EAAkD,CAC1D,MAAMF,EAAS,MAAM,KAAK,YAAY,gBAAgBE,CAAE,EACxD,OAAKF,EACE,IAAIJ,EAAa,CAAE,GAAII,EAAO,GAAI,YAAa,KAAK,WAAY,CAAC,EADpD,IAEtB,CAEA,MAAc,oBAAoBE,EAAmC,CAEnE,GAAI,CADW,MAAM,KAAK,YAAY,gBAAgBA,CAAE,EAEtD,MAAM,IAAI,MAAM,iBAAiBA,CAAE,aAAa,CAEpD,CACF",
6
+ "names": ["Conversation", "Conversations", "__name", "options", "record", "agent", "id"]
7
7
  }
@@ -1,2 +1,2 @@
1
- import{createConversationState as o}from"./types.js";import{Conversation as e}from"./conversation/index.js";import{Conversations as i}from"./conversations.js";import{Orchestrator as p}from"./orchestration/orchestrator/index.js";import{Transcription as x,TranscriptEntry as C}from"./transcription/index.js";export{e as Conversation,i as Conversations,p as Orchestrator,C as TranscriptEntry,x as Transcription,o as createConversationState};
1
+ import{createConversationState as o}from"./types.js";import{Conversation as e}from"./conversation/index.js";import{Conversations as i}from"./conversations.js";import{Orchestrator as p}from"./orchestration/orchestrator/index.js";import{ConversationStream as x}from"./stream/index.js";import{Transcription as m,TranscriptEntry as v}from"./transcription/index.js";export{e as Conversation,x as ConversationStream,i as Conversations,p as Orchestrator,v as TranscriptEntry,m as Transcription,o as createConversationState};
2
2
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/conversations/index.ts"],
4
- "sourcesContent": ["export type {\n AudioChunk,\n ConversationId,\n ConversationState,\n ConversationStatus,\n Generation,\n GenerationStatus,\n Participant,\n ParticipantInput,\n ToolCall,\n ToolCallResult,\n Turn,\n TurnId,\n UserId,\n} from \"./types\";\nexport { createConversationState } from \"./types\";\nexport { Conversation } from \"./conversation/index\";\nexport type {\n ConversationEvents,\n ConversationOptions,\n} from \"./conversation/index\";\nexport { Conversations } from \"./conversations\";\nexport type { CreateConversationOptions } from \"./conversations\";\nexport { Orchestrator } from \"./orchestration/orchestrator/index\";\nexport type { OrchestratorOptions } from \"./orchestration/orchestrator/index\";\nexport { Transcription, TranscriptEntry } from \"./transcription/index\";\nexport type {\n TranscriptEntryInput,\n TranscriptSpeakerKind,\n} from \"./transcription/index\";\n"],
5
- "mappings": "AAeA,OAAS,2BAAAA,MAA+B,UACxC,OAAS,gBAAAC,MAAoB,uBAK7B,OAAS,iBAAAC,MAAqB,kBAE9B,OAAS,gBAAAC,MAAoB,qCAE7B,OAAS,iBAAAC,EAAe,mBAAAC,MAAuB",
6
- "names": ["createConversationState", "Conversation", "Conversations", "Orchestrator", "Transcription", "TranscriptEntry"]
4
+ "sourcesContent": ["export type {\n AudioChunk,\n ConversationId,\n ConversationState,\n ConversationStatus,\n Generation,\n GenerationStatus,\n GenerationTiming,\n Participant,\n ParticipantInput,\n ToolCall,\n ToolCallResult,\n Turn,\n TurnId,\n UserId,\n} from \"./types\";\nexport { createConversationState } from \"./types\";\nexport { Conversation } from \"./conversation/index\";\nexport type {\n ConversationEvents,\n ConversationOptions,\n} from \"./conversation/index\";\nexport { Conversations } from \"./conversations\";\nexport type { CreateConversationOptions } from \"./conversations\";\nexport { Orchestrator } from \"./orchestration/orchestrator/index\";\nexport type { OrchestratorOptions } from \"./orchestration/orchestrator/index\";\nexport { ConversationStream } from \"./stream/index\";\nexport { Transcription, TranscriptEntry } from \"./transcription/index\";\nexport type {\n TranscriptEntryInput,\n TranscriptSpeakerKind,\n} from \"./transcription/index\";\n"],
5
+ "mappings": "AAgBA,OAAS,2BAAAA,MAA+B,UACxC,OAAS,gBAAAC,MAAoB,uBAK7B,OAAS,iBAAAC,MAAqB,kBAE9B,OAAS,gBAAAC,MAAoB,qCAE7B,OAAS,sBAAAC,MAA0B,iBACnC,OAAS,iBAAAC,EAAe,mBAAAC,MAAuB",
6
+ "names": ["createConversationState", "Conversation", "Conversations", "Orchestrator", "ConversationStream", "Transcription", "TranscriptEntry"]
7
7
  }
@@ -0,0 +1,10 @@
1
+ var p=Object.defineProperty;var d=(s,e)=>p(s,"name",{value:e,configurable:!0});import{z as t}from"zod";function f(s){return`Before I continue, could you tell me: ${new Intl.ListFormat("en",{style:"long",type:"conjunction"}).format(s)}?`}d(f,"renderClarifyQuestion");function x(){return`You are the "clarify" coordination: a generic information-acquisition unit.
2
+
3
+ Your job is to turn an underspecified request into a sufficiently clear one by asking the user for whatever is missing. You know nothing about the request's domain \u2014 you only notice missing details and ask for them.
4
+
5
+ Use the delegate tool:
6
+ - action "clarify": list every missing detail in the "missing" array in one call \u2014 one round-trip covers all of them, never one question at a time, and never ask for anything that can be reasonably inferred.
7
+ - action "complete": finish once the request is clear enough to act on, restating it precisely including every answer the user gave.
8
+
9
+ You may ask the user questions at most twice per run. After each answer, reassess: is the request now clear enough to act on? If yes, complete. If not, call "clarify" again with the remaining missing details. After the second round, if anything is still missing, state reasonable assumptions and complete. Never delegate to agents \u2014 your job is only to gather information.`}d(x,"buildClarifyPrompt");class y extends Error{static{d(this,"CoordinationSuspension")}frames;question;constructor(e,o){super(`Coordination suspended: ${o}`),this.name="CoordinationSuspension",this.frames=e,this.question=o}}class g extends Error{static{d(this,"CoordinationCancelled")}constructor(){super("Coordination cancelled"),this.name="CoordinationCancelled"}}class m extends Error{static{d(this,"CoordinationBudgetExceeded")}constructor(e){super(`Coordination budget exceeded: ${e}`),this.name="CoordinationBudgetExceeded"}}const w="Decide what should happen next in order to produce the desired result. You may run one or more agents (each with a self-contained prompt), pass the work to another coordination, ask the user for missing information (batched into one call), or complete with the final spoken answer. Only ever take one action per call.";function u(s){return s.length>0?t.enum(s):t.string()}d(u,"targetsEnum");function h(s,e){const o=s.map(a=>[a.name,...a.aliases]).flat(),i=e.map(a=>a.name);return t.discriminatedUnion("action",[t.object({action:t.literal("agents"),tasks:t.array(t.object({agent:u(o).describe("Agent name or alias from the roster."),prompt:t.string().trim().min(1,"a prompt is required").describe("Self-contained instruction for that agent.")})).describe("Agents to run in parallel.").min(1,"at least one task is required")}),t.object({action:t.literal("coordination"),coordination:u(i).describe("The coordination to pass the work to."),input:t.unknown().describe("Input for the delegated coordination.").optional()}),t.object({action:t.literal("clarify"),missing:t.array(t.string().trim().min(1,"a missing detail is required")).min(1,"at least one missing detail is required").describe("The missing details to ask the user for, batched into one turn.")}),t.object({action:t.literal("user"),question:t.string().trim().min(1,"a question is required").describe("Clarifying question for the user.")}),t.object({action:t.literal("complete"),output:t.string().trim().min(1,"an output is required").describe("The final spoken answer.")})])}d(h,"delegateActionSchema");function b(s,e){const o=s.map(r=>[r.name,...r.aliases]).flat(),i=e.map(r=>r.name),a=t.object({action:t.enum(["agents","coordination","clarify","user","complete"]).describe("What to do next."),tasks:t.array(t.object({agent:u(o).describe("Agent name or alias from the roster."),prompt:t.string().trim().min(1,"a prompt is required").describe("Self-contained instruction for that agent.")})).describe("Agents to run in parallel (action 'agents').").optional(),coordination:u(i).describe("The coordination to pass the work to (action 'coordination').").optional(),input:t.unknown().describe("Input for the delegated coordination (action 'coordination').").optional(),missing:t.array(t.string().trim().min(1,"a missing detail is required")).min(1,"at least one missing detail is required").describe("The missing details to ask the user for (action 'clarify'), batched into one turn.").optional(),question:t.string().trim().min(1,"a question is required").describe("Clarifying question for the user (action 'user').").optional(),output:t.string().trim().min(1,"an output is required").describe("The final spoken answer (action 'complete').").optional()}),n=t.toJSONSchema(a);return delete n.$schema,{name:"delegate",description:w,parameters:n}}d(b,"delegateToolDefinition");function D(s,e,o){let i;try{i=JSON.parse(s)}catch{throw new Error("delegate arguments must be valid JSON")}const a=h(e,o).safeParse(i);if(!a.success){const n=a.error.issues.map(r=>r.path.length>0?`${r.path.join(".")}: ${r.message}`:r.message).join("; ");throw new Error(`invalid delegate arguments: ${n}`)}return a.data}d(D,"parseDelegateAction");class q{static{d(this,"Coordination")}name;prompt;maxTokens;maxDurationMs;maxQuestionRounds;runtime;llm;cachedToolDefinition=null;cachedSchema=null;constructor(e,o){if(!e.name.trim())throw new Error("Coordination requires a non-empty name");this.name=e.name.trim(),this.prompt=e.prompt?.trim()??"",this.maxTokens=e.maxTokens,this.maxDurationMs=e.maxDurationMs,this.maxQuestionRounds=e.maxQuestionRounds??2,this.runtime=o,this.llm=e.llm??o.llm}toolDefinition(){return this.cachedToolDefinition??=b(this.runtime.agents,this.runtime.coordinations),this.cachedToolDefinition}parseDelegate(e){this.cachedSchema??=h(this.runtime.agents,this.runtime.coordinations);let o;try{o=JSON.parse(e)}catch{throw new Error("delegate arguments must be valid JSON")}const i=this.cachedSchema.safeParse(o);if(!i.success){const a=i.error.issues.map(n=>n.path.length>0?`${n.path.join(".")}: ${n.message}`:n.message).join("; ");throw new Error(`invalid delegate arguments: ${a}`)}return i.data}async run(e){const o={messages:[],startedAt:Date.now(),narration:"",questionRounds:0};return this.prompt&&o.messages.push({role:"system",name:this.name,content:this.prompt}),o.messages.push(...this.runtime.history),e!==void 0&&o.messages.push({role:"user",content:typeof e=="string"?e:JSON.stringify(e)}),this.loop(o)}async resume(e,o){return e.narration="",e.messages.push({role:"user",content:o}),this.loop(e)}async continueWith(e,o){return e.narration="",e.messages.push(o),this.loop(e)}async loop(e){const o=e.startedAt;for(;;){if(this.runtime.checkBudget(),this.runtime.isCancelled())throw new g;if(this.maxDurationMs&&Date.now()-o>this.maxDurationMs)throw new m(`"${this.name}" exceeded ${this.maxDurationMs}ms`);const i=[];let a=!1;for await(const n of this.llm.stream({messages:e.messages,tools:[this.toolDefinition()],maxTokens:this.maxTokens})){if(this.runtime.isCancelled())throw new g;switch(n.type){case"delta":e.narration+=n.content,this.runtime.onDelta(n.content);break;case"tool_call":i.push({id:n.id,name:n.name,arguments:n.arguments});break;case"error":throw n.error;case"done":a=!0}}if(this.maxDurationMs&&Date.now()-o>this.maxDurationMs)throw new m(`"${this.name}" exceeded ${this.maxDurationMs}ms`);if(i.length>0){this.runtime.flushSpeech(),e.messages.push({role:"assistant",name:this.name,content:e.narration,toolCalls:i});for(const n of i){let r;try{r=this.parseDelegate(n.arguments)}catch(l){e.messages.push({role:"tool",toolCallId:n.id,name:"delegate",content:JSON.stringify({error:l instanceof Error?l.message:String(l)})});continue}switch(r.action){case"agents":{const l=await this.runtime.delegateAgentTasks(r.tasks);e.messages.push({role:"tool",toolCallId:n.id,name:"delegate",content:JSON.stringify(l)});break}case"coordination":{const l=this.runtime.coordinations.find(c=>c.name===r.coordination);if(!l){e.messages.push({role:"tool",toolCallId:n.id,name:"delegate",content:JSON.stringify({error:`Unknown coordination "${r.coordination}"`})});break}try{const c=await this.delegateToCoordination(l,r.input,e,n.id);e.messages.push({role:"tool",toolCallId:n.id,name:"delegate",content:JSON.stringify(c)})}catch(c){if(c instanceof m)e.messages.push({role:"tool",toolCallId:n.id,name:"delegate",content:JSON.stringify({error:c.message})});else throw c}break}case"clarify":{if(e.questionRounds>=this.maxQuestionRounds){e.messages.push({role:"tool",toolCallId:n.id,name:"delegate",content:JSON.stringify({error:`question budget exceeded (max ${this.maxQuestionRounds} rounds) \u2014 state reasonable assumptions and complete`})});continue}e.questionRounds++;const l=f(r.missing);throw this.runtime.speak(l),e.messages.push({role:"tool",toolCallId:n.id,name:"delegate",content:JSON.stringify({action:"clarify",missing:r.missing})}),await this.runtime.askUser({coordination:this,state:e},l),new Error("unreachable")}case"user":{if(e.questionRounds>=this.maxQuestionRounds){e.messages.push({role:"tool",toolCallId:n.id,name:"delegate",content:JSON.stringify({error:`question budget exceeded (max ${this.maxQuestionRounds} rounds) \u2014 state reasonable assumptions and complete`})});continue}throw e.questionRounds++,e.messages.push({role:"tool",toolCallId:n.id,name:"delegate",content:JSON.stringify({action:"user",question:r.question})}),await this.runtime.askUser({coordination:this,state:e},r.question),new Error("unreachable")}case"complete":return this.runtime.speak(r.output),this.completeOutput(e.narration,r.output)}}continue}if(a)return this.completeOutput(e.narration,"")}}async delegateToCoordination(e,o,i,a){i.pendingToolCallId=a;try{return await e.run(o)}catch(n){throw n instanceof y&&n.frames.unshift({coordination:this,state:i}),n}}completeOutput(e,o){const i=e.trim();return o?`${i?i+" ":""}${o}`:i}}export{q as Coordination,m as CoordinationBudgetExceeded,g as CoordinationCancelled,y as CoordinationSuspension,x as buildClarifyPrompt,b as delegateToolDefinition,D as parseDelegateAction,f as renderClarifyQuestion};
10
+ //# sourceMappingURL=coordination.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/conversations/orchestration/coordination/coordination.ts"],
4
+ "sourcesContent": ["import type { Agent } from \"../../../agents/agent\";\nimport { z } from \"zod\";\nimport type { LLM, LLMMessage, LLMToolCall, LLMToolDefinition } from \"../../../providers/llm/types\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * One task delegated to an agent: a self-contained prompt for a roster member.\n */\nexport interface DelegatedTask {\n agent: string;\n prompt: string;\n}\n\n/**\n * The outcome of a delegated agent run (or sub-coordination, via `error`).\n */\nexport interface DelegationResult {\n agent: string;\n text: string;\n error?: string;\n}\n\n/** What a coordination's LLM may decide to do next. */\nexport type DelegateAction =\n | { action: \"agents\"; tasks: DelegatedTask[] }\n | { action: \"coordination\"; coordination: string; input?: unknown }\n | { action: \"clarify\"; missing: string[] }\n | { action: \"user\"; question: string }\n | { action: \"complete\"; output: string };\n\n/**\n * The runtime a coordination reasons against: the roster, every registered\n * coordination, and the primitives for delegating work. Supplied by the\n * orchestrator, so coordinations never couple to it directly.\n */\nexport interface CoordinationRuntime {\n readonly agents: readonly Agent[];\n readonly coordinations: readonly Coordination[];\n /** Shared LLM used for coordination reasoning. */\n readonly llm: LLM;\n /** Shared conversation history, seeded into fresh runs. */\n readonly history: readonly LLMMessage[];\n\n /** Run one or more agents in parallel (text-only) and return their outputs. */\n delegateAgentTasks(tasks: DelegatedTask[]): Promise<DelegationResult[]>;\n /**\n * Ask the user a question. Never returns: it throws `CoordinationSuspension`\n * carrying the innermost frame, which the orchestrator catches to park the\n * execution until the user answers.\n */\n askUser(frame: PendingFrame, question: string): Promise<never>;\n /** Stream a delta to speech (TTS narration). */\n onDelta(delta: string): void;\n /** Flush pending narration (e.g. before delegating or suspending). */\n flushSpeech(): void;\n /** Speak a standalone sentence (e.g. a `complete` output). */\n speak(sentence: string): void;\n /** True once an interrupt/stop has cancelled this run. */\n isCancelled(): boolean;\n /** Throw if the run exceeded the coordination step budget. */\n checkBudget(): void;\n}\n\nexport interface CoordinationOptions {\n name: string;\n /** System prompt describing the coordination's reasoning role. */\n prompt?: string;\n /** Overrides the runtime's shared LLM for this coordination. */\n llm?: LLM;\n maxTokens?: number;\n /** Hard wall-clock limit for a single run (including suspensions). */\n maxDurationMs?: number;\n /**\n * Deterministic cap on user-question rounds per run (both the structured\n * `clarify` action and open-ended `user` questions, across suspensions).\n * Once exhausted, the coordination is told to state reasonable\n * assumptions and complete. Defaults to 2.\n */\n maxQuestionRounds?: number;\n}\n\n/**\n * A coordination registered in the orchestrator by name \u2014 the registry key\n * is the coordination's name, so it is not repeated here.\n */\nexport type CoordinationRegistration = Omit<CoordinationOptions, \"name\">;\n\n/**\n * Render a batched clarification question from the missing details, so the\n * wording is deterministic regardless of how the model phrases the labels.\n */\nexport function renderClarifyQuestion(missing: string[]): string {\n const list = new Intl.ListFormat(\"en\", { style: \"long\", type: \"conjunction\" }).format(missing);\n return `Before I continue, could you tell me: ${list}?`;\n}\n\n/**\n * The system prompt for a `clarify` coordination: a generic,\n * domain-agnostic information-acquisition unit. It turns an underspecified\n * request into a clear one by asking the user for missing details via the\n * structured `clarify` action (batched), with a hard two-round cap enforced\n * by the runtime. Register it alongside `understand`:\n *\n * ```ts\n * coordinations: { clarify: { prompt: buildClarifyPrompt() } }\n * ```\n */\nexport function buildClarifyPrompt(): string {\n return `You are the \"clarify\" coordination: a generic information-acquisition unit.\n\nYour job is to turn an underspecified request into a sufficiently clear one by asking the user for whatever is missing. You know nothing about the request's domain \u2014 you only notice missing details and ask for them.\n\nUse the delegate tool:\n- action \"clarify\": list every missing detail in the \"missing\" array in one call \u2014 one round-trip covers all of them, never one question at a time, and never ask for anything that can be reasonably inferred.\n- action \"complete\": finish once the request is clear enough to act on, restating it precisely including every answer the user gave.\n\nYou may ask the user questions at most twice per run. After each answer, reassess: is the request now clear enough to act on? If yes, complete. If not, call \"clarify\" again with the remaining missing details. After the second round, if anything is still missing, state reasonable assumptions and complete. Never delegate to agents \u2014 your job is only to gather information.`;\n}\n\n/**\n * The resumable state of one coordination invocation. Plain data so it can be\n * parked in a `PendingExecution` while waiting for the user.\n */\nexport interface CoordinationState {\n messages: LLMMessage[];\n startedAt: number;\n /** Everything the coordination has spoken so far, for the final record. */\n narration: string;\n /** How many user-question rounds this run has used (across suspensions). */\n questionRounds: number;\n /** Tool call id awaiting a sub-coordination result, for resume replies. */\n pendingToolCallId?: string;\n}\n\n/** One frame of a suspended execution stack (outermost first). */\nexport interface PendingFrame {\n coordination: Coordination;\n state: CoordinationState;\n}\n\n/** Thrown when a coordination asks the user; carries the whole frame stack. */\nexport class CoordinationSuspension extends Error {\n readonly frames: PendingFrame[];\n readonly question: string;\n\n constructor(frames: PendingFrame[], question: string) {\n super(`Coordination suspended: ${question}`);\n this.name = \"CoordinationSuspension\";\n this.frames = frames;\n this.question = question;\n }\n}\n\n/** Thrown when a coordination run is cancelled (interrupt/stop). */\nexport class CoordinationCancelled extends Error {\n constructor() {\n super(\"Coordination cancelled\");\n this.name = \"CoordinationCancelled\";\n }\n}\n\n/** Thrown when a coordination exceeded its step or duration budget. */\nexport class CoordinationBudgetExceeded extends Error {\n constructor(detail: string) {\n super(`Coordination budget exceeded: ${detail}`);\n this.name = \"CoordinationBudgetExceeded\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Delegate tool\n// ---------------------------------------------------------------------------\n\nconst DELEGATE_DESCRIPTION =\n \"Decide what should happen next in order to produce the desired result. \" +\n \"You may run one or more agents (each with a self-contained prompt), pass the work to \" +\n \"another coordination, ask the user for missing information (batched into one call), or \" +\n \"complete with the final spoken answer. Only ever take one action per call.\";\n\n/** Non-empty zod enum, or a plain string when there are no targets. */\nfunction targetsEnum(targets: string[]): z.ZodType<string> {\n return targets.length > 0\n ? z.enum(targets as [string, ...string[]])\n : z.string();\n}\n\n/**\n * The strict schema a coordination's LLM output must satisfy. A discriminated\n * union on `action` \u2014 each variant carries exactly its own fields.\n */\nfunction delegateActionSchema(\n agents: readonly Agent[],\n coordinations: readonly Coordination[],\n): z.ZodType<DelegateAction> {\n const agentTargets = agents.map((agent) => [agent.name, ...agent.aliases]).flat();\n const coordinationTargets = coordinations.map((coordination) => coordination.name);\n return z.discriminatedUnion(\"action\", [\n z.object({\n action: z.literal(\"agents\"),\n tasks: z\n .array(\n z.object({\n agent: targetsEnum(agentTargets).describe(\"Agent name or alias from the roster.\"),\n prompt: z.string().trim().min(1, \"a prompt is required\").describe(\"Self-contained instruction for that agent.\"),\n }),\n )\n .describe(\"Agents to run in parallel.\")\n .min(1, \"at least one task is required\"),\n }),\n z.object({\n action: z.literal(\"coordination\"),\n coordination: targetsEnum(coordinationTargets).describe(\n \"The coordination to pass the work to.\",\n ),\n input: z.unknown().describe(\"Input for the delegated coordination.\").optional(),\n }),\n z.object({\n action: z.literal(\"clarify\"),\n missing: z\n .array(z.string().trim().min(1, \"a missing detail is required\"))\n .min(1, \"at least one missing detail is required\")\n .describe(\"The missing details to ask the user for, batched into one turn.\"),\n }),\n z.object({\n action: z.literal(\"user\"),\n question: z.string().trim().min(1, \"a question is required\").describe(\"Clarifying question for the user.\"),\n }),\n z.object({\n action: z.literal(\"complete\"),\n output: z.string().trim().min(1, \"an output is required\").describe(\"The final spoken answer.\"),\n }),\n ]);\n}\n\n/**\n * The tool definition that lets a coordination's LLM choose the next execution\n * target: agents (one or more, in parallel), another coordination, the user,\n * or completion.\n *\n * The parameters are deliberately FLAT (action enum + optional fields) even\n * though the parser enforces a discriminated union per action. Why: Amazon\n * Bedrock (nova) ignores `oneOf` in tool input schemas, which makes the tool\n * effectively empty \u2014 the model stops calling it and answers directly instead\n * (measured: 0/2 tool calls and ~5k-token essays vs reliable ~1s calls with\n * the flat shape). The flat schema works across every provider tested; the\n * discriminated contract is enforced when the call is parsed, and an invalid\n * combination costs one bounded retry rather than a broken tool.\n */\nexport function delegateToolDefinition(\n agents: readonly Agent[],\n coordinations: readonly Coordination[],\n): LLMToolDefinition {\n const agentTargets = agents.map((agent) => [agent.name, ...agent.aliases]).flat();\n const coordinationTargets = coordinations.map((coordination) => coordination.name);\n const parameters = z.object({\n action: z\n .enum([\"agents\", \"coordination\", \"clarify\", \"user\", \"complete\"])\n .describe(\"What to do next.\"),\n tasks: z\n .array(\n z.object({\n agent: targetsEnum(agentTargets).describe(\"Agent name or alias from the roster.\"),\n prompt: z.string().trim().min(1, \"a prompt is required\").describe(\"Self-contained instruction for that agent.\"),\n }),\n )\n .describe(\"Agents to run in parallel (action 'agents').\")\n .optional(),\n coordination: targetsEnum(coordinationTargets)\n .describe(\"The coordination to pass the work to (action 'coordination').\")\n .optional(),\n input: z\n .unknown()\n .describe(\"Input for the delegated coordination (action 'coordination').\")\n .optional(),\n missing: z\n .array(z.string().trim().min(1, \"a missing detail is required\"))\n .min(1, \"at least one missing detail is required\")\n .describe(\"The missing details to ask the user for (action 'clarify'), batched into one turn.\")\n .optional(),\n question: z\n .string()\n .trim()\n .min(1, \"a question is required\")\n .describe(\"Clarifying question for the user (action 'user').\")\n .optional(),\n output: z\n .string()\n .trim()\n .min(1, \"an output is required\")\n .describe(\"The final spoken answer (action 'complete').\")\n .optional(),\n });\n const jsonSchema = z.toJSONSchema(parameters) as Record<string, unknown>;\n delete jsonSchema.$schema;\n return { name: \"delegate\", description: DELEGATE_DESCRIPTION, parameters: jsonSchema };\n}\n\nexport function parseDelegateAction(\n argumentsJson: string,\n agents: readonly Agent[],\n coordinations: readonly Coordination[],\n): DelegateAction {\n let parsed: unknown;\n try {\n parsed = JSON.parse(argumentsJson);\n } catch {\n throw new Error(\"delegate arguments must be valid JSON\");\n }\n const result = delegateActionSchema(agents, coordinations).safeParse(parsed);\n if (!result.success) {\n const details = result.error.issues\n .map((issue) => (issue.path.length > 0 ? `${issue.path.join(\".\")}: ${issue.message}` : issue.message))\n .join(\"; \");\n throw new Error(`invalid delegate arguments: ${details}`);\n }\n return result.data;\n}\n\n// ---------------------------------------------------------------------------\n// Coordination\n// ---------------------------------------------------------------------------\n\n/**\n * A hardcoded reasoning/control-flow unit. Unlike an `Agent` (input \u2192 LLM \u2192\n * output), a coordination decides *what should happen next*: run agents, pass\n * work to another coordination, ask the user, or complete. Definitions are\n * stateless; each invocation carries its own `CoordinationState`, which can be\n * parked (suspended) while waiting for the user and resumed later.\n */\nexport class Coordination {\n readonly name: string;\n readonly prompt: string;\n readonly maxTokens: number | undefined;\n readonly maxDurationMs: number | undefined;\n readonly maxQuestionRounds: number;\n private readonly runtime: CoordinationRuntime;\n private readonly llm: LLM;\n private cachedToolDefinition: LLMToolDefinition | null = null;\n private cachedSchema: ReturnType<typeof delegateActionSchema> | null = null;\n\n constructor(options: CoordinationOptions, runtime: CoordinationRuntime) {\n if (!options.name.trim()) {\n throw new Error(\"Coordination requires a non-empty name\");\n }\n this.name = options.name.trim();\n this.prompt = options.prompt?.trim() ?? \"\";\n this.maxTokens = options.maxTokens;\n this.maxDurationMs = options.maxDurationMs;\n this.maxQuestionRounds = options.maxQuestionRounds ?? 2;\n this.runtime = runtime;\n this.llm = options.llm ?? runtime.llm;\n }\n\n /** The delegate tool definition, generated once from the roster. */\n private toolDefinition(): LLMToolDefinition {\n this.cachedToolDefinition ??= delegateToolDefinition(\n this.runtime.agents,\n this.runtime.coordinations,\n );\n return this.cachedToolDefinition;\n }\n\n /** Parse a `delegate` tool call against the roster's strict schema. */\n private parseDelegate(argumentsJson: string): DelegateAction {\n this.cachedSchema ??= delegateActionSchema(\n this.runtime.agents,\n this.runtime.coordinations,\n );\n let parsed: unknown;\n try {\n parsed = JSON.parse(argumentsJson);\n } catch {\n throw new Error(\"delegate arguments must be valid JSON\");\n }\n const result = this.cachedSchema.safeParse(parsed);\n if (!result.success) {\n const details = result.error.issues\n .map((issue) =>\n issue.path.length > 0\n ? `${issue.path.join(\".\")}: ${issue.message}`\n : issue.message,\n )\n .join(\"; \");\n throw new Error(`invalid delegate arguments: ${details}`);\n }\n return result.data;\n }\n\n /** Run the coordination with fresh state (seeded with the shared history). */\n async run(input?: unknown): Promise<unknown> {\n const state: CoordinationState = {\n messages: [],\n startedAt: Date.now(),\n narration: \"\",\n questionRounds: 0,\n };\n if (this.prompt) {\n state.messages.push({ role: \"system\", name: this.name, content: this.prompt });\n }\n state.messages.push(...this.runtime.history);\n if (input !== undefined) {\n state.messages.push({\n role: \"user\",\n content: typeof input === \"string\" ? input : JSON.stringify(input),\n });\n }\n return this.loop(state);\n }\n\n /** Resume a suspended state with the user's answer. */\n async resume(state: CoordinationState, answer: string): Promise<unknown> {\n // The pre-suspension narration was already recorded as the question.\n state.narration = \"\";\n state.messages.push({ role: \"user\", content: answer });\n return this.loop(state);\n }\n\n /** Continue a suspended state with an injected message (e.g. a sub-result). */\n async continueWith(state: CoordinationState, message: LLMMessage): Promise<unknown> {\n state.narration = \"\";\n state.messages.push(message);\n return this.loop(state);\n }\n\n /**\n * The coordination loop: one LLM round trip per iteration, choosing the next\n * execution target via the `delegate` tool. Throws `CoordinationSuspension`\n * when asking the user; the state carried in the suspension is resumable.\n */\n private async loop(state: CoordinationState): Promise<unknown> {\n const startedAt = state.startedAt;\n\n for (;;) {\n this.runtime.checkBudget();\n if (this.runtime.isCancelled()) throw new CoordinationCancelled();\n if (this.maxDurationMs && Date.now() - startedAt > this.maxDurationMs) {\n throw new CoordinationBudgetExceeded(`\"${this.name}\" exceeded ${this.maxDurationMs}ms`);\n }\n\n const toolCalls: LLMToolCall[] = [];\n let done = false;\n\n for await (const event of this.llm.stream({\n messages: state.messages,\n tools: [this.toolDefinition()],\n maxTokens: this.maxTokens,\n })) {\n if (this.runtime.isCancelled()) throw new CoordinationCancelled();\n switch (event.type) {\n case \"delta\":\n state.narration += event.content;\n this.runtime.onDelta(event.content);\n break;\n case \"tool_call\":\n toolCalls.push({ id: event.id, name: event.name, arguments: event.arguments });\n break;\n case \"error\":\n throw event.error;\n case \"done\":\n done = true;\n }\n }\n\n // Re-check the wall-clock limit after the round trip: a single slow\n // iteration must still count against maxDurationMs.\n if (this.maxDurationMs && Date.now() - startedAt > this.maxDurationMs) {\n throw new CoordinationBudgetExceeded(`\"${this.name}\" exceeded ${this.maxDurationMs}ms`);\n }\n\n if (toolCalls.length > 0) {\n this.runtime.flushSpeech();\n state.messages.push({\n role: \"assistant\",\n name: this.name,\n content: state.narration,\n toolCalls,\n });\n for (const call of toolCalls) {\n let action: DelegateAction;\n try {\n action = this.parseDelegate(call.arguments);\n } catch (error) {\n // Malformed arguments: report to the coordination's LLM so it can\n // recover instead of crashing the run.\n state.messages.push({\n role: \"tool\",\n toolCallId: call.id,\n name: \"delegate\",\n content: JSON.stringify({\n error: error instanceof Error ? error.message : String(error),\n }),\n });\n continue;\n }\n switch (action.action) {\n case \"agents\": {\n const results = await this.runtime.delegateAgentTasks(action.tasks);\n state.messages.push({\n role: \"tool\",\n toolCallId: call.id,\n name: \"delegate\",\n content: JSON.stringify(results),\n });\n break;\n }\n case \"coordination\": {\n const target = this.runtime.coordinations.find(\n (coordination) => coordination.name === action.coordination,\n );\n if (!target) {\n state.messages.push({\n role: \"tool\",\n toolCallId: call.id,\n name: \"delegate\",\n content: JSON.stringify({\n error: `Unknown coordination \"${action.coordination}\"`,\n }),\n });\n break;\n }\n try {\n const result = await this.delegateToCoordination(\n target,\n action.input,\n state,\n call.id,\n );\n state.messages.push({\n role: \"tool\",\n toolCallId: call.id,\n name: \"delegate\",\n content: JSON.stringify(result),\n });\n } catch (error) {\n if (error instanceof CoordinationBudgetExceeded) {\n state.messages.push({\n role: \"tool\",\n toolCallId: call.id,\n name: \"delegate\",\n content: JSON.stringify({ error: error.message }),\n });\n } else {\n throw error; // suspension or cancellation propagates\n }\n }\n break;\n }\n case \"clarify\": {\n // Structured, batched clarification: the model declares which\n // details are missing; the framework renders and speaks the\n // question so batching and the round cap are deterministic.\n if (state.questionRounds >= this.maxQuestionRounds) {\n state.messages.push({\n role: \"tool\",\n toolCallId: call.id,\n name: \"delegate\",\n content: JSON.stringify({\n error: `question budget exceeded (max ${this.maxQuestionRounds} rounds) \u2014 state reasonable assumptions and complete`,\n }),\n });\n continue;\n }\n state.questionRounds++;\n const question = renderClarifyQuestion(action.missing);\n this.runtime.speak(question);\n state.messages.push({\n role: \"tool\",\n toolCallId: call.id,\n name: \"delegate\",\n content: JSON.stringify({ action: \"clarify\", missing: action.missing }),\n });\n await this.runtime.askUser({ coordination: this, state }, question);\n throw new Error(\"unreachable\");\n }\n case \"user\": {\n // Open-ended questions count against the same deterministic\n // question-round budget as structured clarification.\n if (state.questionRounds >= this.maxQuestionRounds) {\n state.messages.push({\n role: \"tool\",\n toolCallId: call.id,\n name: \"delegate\",\n content: JSON.stringify({\n error: `question budget exceeded (max ${this.maxQuestionRounds} rounds) \u2014 state reasonable assumptions and complete`,\n }),\n });\n continue;\n }\n state.questionRounds++;\n state.messages.push({\n role: \"tool\",\n toolCallId: call.id,\n name: \"delegate\",\n content: JSON.stringify({ action: \"user\", question: action.question }),\n });\n await this.runtime.askUser({ coordination: this, state }, action.question);\n throw new Error(\"unreachable\");\n }\n case \"complete\":\n this.runtime.speak(action.output);\n return this.completeOutput(state.narration, action.output);\n }\n }\n continue;\n }\n\n if (done) {\n // No delegate call: the coordination answered directly.\n return this.completeOutput(state.narration, \"\");\n }\n }\n }\n\n /** Delegate to a sub-coordination, attaching this frame on suspension. */\n private async delegateToCoordination(\n target: Coordination,\n input: unknown,\n state: CoordinationState,\n toolCallId: string,\n ): Promise<unknown> {\n state.pendingToolCallId = toolCallId;\n try {\n return await target.run(input);\n } catch (error) {\n if (error instanceof CoordinationSuspension) {\n error.frames.unshift({ coordination: this, state });\n throw error;\n }\n throw error;\n }\n }\n\n private completeOutput(narration: string, output: string): string {\n const trimmed = narration.trim();\n return output ? `${trimmed ? trimmed + \" \" : \"\"}${output}` : trimmed;\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["z", "renderClarifyQuestion", "missing", "__name", "buildClarifyPrompt", "CoordinationSuspension", "frames", "question", "CoordinationCancelled", "CoordinationBudgetExceeded", "detail", "DELEGATE_DESCRIPTION", "targetsEnum", "targets", "delegateActionSchema", "agents", "coordinations", "agentTargets", "agent", "coordinationTargets", "coordination", "delegateToolDefinition", "parameters", "jsonSchema", "parseDelegateAction", "argumentsJson", "parsed", "result", "details", "issue", "Coordination", "options", "runtime", "input", "state", "answer", "message", "startedAt", "toolCalls", "done", "event", "call", "action", "error", "results", "target", "toolCallId", "narration", "output", "trimmed"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import{Coordination as n,CoordinationSuspension as i,CoordinationCancelled as t,CoordinationBudgetExceeded as a,delegateToolDefinition as d,parseDelegateAction as r}from"./coordination.js";export{n as Coordination,a as CoordinationBudgetExceeded,t as CoordinationCancelled,i as CoordinationSuspension,d as delegateToolDefinition,r as parseDelegateAction};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/conversations/orchestration/coordination/index.ts"],
4
+ "sourcesContent": ["export {\n Coordination,\n CoordinationSuspension,\n CoordinationCancelled,\n CoordinationBudgetExceeded,\n delegateToolDefinition,\n parseDelegateAction,\n} from \"./coordination\";\nexport type {\n CoordinationOptions,\n CoordinationRuntime,\n CoordinationState,\n DelegateAction,\n DelegatedTask,\n DelegationResult,\n PendingFrame,\n} from \"./coordination\";\n"],
5
+ "mappings": "AAAA,OACE,gBAAAA,EACA,0BAAAC,EACA,yBAAAC,EACA,8BAAAC,EACA,0BAAAC,EACA,uBAAAC,MACK",
6
+ "names": ["Coordination", "CoordinationSuspension", "CoordinationCancelled", "CoordinationBudgetExceeded", "delegateToolDefinition", "parseDelegateAction"]
7
+ }
@@ -0,0 +1,4 @@
1
+ var g=Object.defineProperty;var i=(l,t)=>g(l,"name",{value:t,configurable:!0});import{Coordination as v,CoordinationBudgetExceeded as f,CoordinationCancelled as p,CoordinationSuspension as h}from"../../coordination/coordination.js";import{formatTimeContext as y}from"../history/history.js";import{buildUnderstandPrompt as C,findAgentByName as w}from"../routing/routing.js";class b{static{i(this,"CoordinationRunner")}coordinations={};understand=null;conversation;agents;llm;history;historyWindow;speech;generation;tools;maxCoordinationSteps;maxToolIterations;temperature;maxTokens;currentEpoch;isCurrent;coordinationEpoch=0;coordinationStepCount=0;coordinationRunId="";pendingExecution=null;constructor(t){this.conversation=t.conversation,this.agents=t.agents,this.llm=t.llm,this.history=t.history,this.historyWindow=t.historyWindow,this.speech=t.speech,this.generation=t.generation,this.tools=t.tools,this.maxCoordinationSteps=t.maxCoordinationSteps,this.maxToolIterations=t.maxToolIterations,this.temperature=t.temperature,this.maxTokens=t.maxTokens,this.currentEpoch=t.currentEpoch,this.isCurrent=t.isCurrent}register(t,n){const o={...t};n.length>1&&!o.understand&&(o.understand={prompt:C(n)});for(const[e,a]of Object.entries(o))this.coordinations[e]=new v({name:e,...a},this.runtime());this.understand=this.coordinations.understand??null}hasPending(){return this.pendingExecution!==null}cancel(){this.pendingExecution=null}async runDefault(t){const n=this.understand,o=this.llm();if(!(!n||!o)){this.coordinationEpoch=this.currentEpoch(),this.coordinationStepCount=0,this.coordinationRunId=crypto.randomUUID(),await this.conversation.pushGeneration({id:this.coordinationRunId,conversationId:this.conversation.id,agentName:this.agents()[0].name,text:"",status:"streaming",startedAt:Date.now()});try{const e=await n.run();await this.finalizeOutput(String(e))}catch(e){e instanceof h?await this.recordSuspension(e):e instanceof p||this.emitError(e)}}}async resume(t){const n=this.pendingExecution;if(!n)return;this.pendingExecution=null,this.coordinationEpoch=this.currentEpoch(),this.coordinationStepCount=n.stepCount,this.coordinationRunId=crypto.randomUUID(),await this.conversation.pushGeneration({id:this.coordinationRunId,conversationId:this.conversation.id,agentName:this.agents()[0].name,text:"",status:"streaming",startedAt:Date.now()});const o=[...n.frames],e=o.pop();if(!e)return;let a;try{a=await e.coordination.resume(e.state,t.text)}catch(r){r instanceof h?(r.frames.unshift(...o),await this.recordSuspension(r)):r instanceof p||this.emitError(r);return}for(;o.length>0;){const r=o.pop(),u=r.state.pendingToolCallId??crypto.randomUUID();try{a=await r.coordination.continueWith(r.state,{role:"tool",toolCallId:u,name:"delegate",content:JSON.stringify(a)})}catch(c){c instanceof h?(c.frames.unshift(...o),await this.recordSuspension(c)):c instanceof p||this.emitError(c);return}}await this.finalizeOutput(String(a))}runtime(){const t=this;return{get agents(){return t.agents()},get coordinations(){return Object.values(t.coordinations)},get llm(){return t.llm()},get history(){return t.history.windowed(t.historyWindow)},delegateAgentTasks:i(n=>this.delegateAgentTasks(n),"delegateAgentTasks"),askUser:i((n,o)=>this.askUser(n,o),"askUser"),onDelta:i(n=>this.speech.feed(n,this.currentEpoch()),"onDelta"),flushSpeech:i(()=>this.speech.flush(this.currentEpoch()),"flushSpeech"),speak:i(n=>this.speech.speak(n,this.currentEpoch()),"speak"),isCancelled:i(()=>this.currentEpoch()!==this.coordinationEpoch,"isCancelled"),checkBudget:i(()=>this.checkBudget(),"checkBudget")}}async finalizeOutput(t){this.speech.flush(this.currentEpoch()),await this.speech.waitForIdle(),this.currentEpoch()===this.coordinationEpoch&&(await this.conversation.completeGeneration(t),await this.conversation.pushTranscript({speaker:this.agents()[0].name,speakerKind:"agent",text:t}),this.history.addAssistant(this.agents()[0].name,t))}async recordSuspension(t){await this.conversation.completeGeneration(t.question),await this.conversation.pushTranscript({speaker:this.agents()[0].name,speakerKind:"agent",text:t.question}),this.history.addAssistant(this.agents()[0].name,t.question),this.pendingExecution={frames:t.frames,question:t.question,stepCount:this.coordinationStepCount}}askUser(t,n){throw new h([t],n)}checkBudget(){if(this.coordinationStepCount++,this.coordinationStepCount>this.maxCoordinationSteps)throw new f(`exceeded ${this.maxCoordinationSteps} coordination steps`)}emitError(t){this.conversation.emit("error",{conversationId:this.conversation.id,error:t instanceof Error?t:new Error(String(t))}),this.currentEpoch()===this.coordinationEpoch&&this.conversation.completeGeneration("")}async delegateAgentTasks(t){const n=await Promise.all(t.map(o=>this.runSubGeneration(this.coordinationEpoch,o,this.coordinationRunId)));if(!this.isCurrent(this.coordinationEpoch))return n.map(({agent:o,text:e,error:a})=>({agent:o,text:e,error:a}));for(const o of n)o.text&&!o.error&&await this.conversation.pushTranscript({speaker:o.agent,speakerKind:"agent",text:o.text});return n}async runSubGeneration(t,n,o){const e=w(this.agents(),n.agent);if(!e)return{agent:n.agent,text:"",error:`Unknown agent "${n.agent}"`};const a=e.llm??this.llm();if(!a)return{agent:e.name,text:"",error:`Agent "${e.name}" has no LLM configured`};const r=crypto.randomUUID();await this.conversation.pushSubGeneration({id:r,conversationId:this.conversation.id,agentName:e.name,text:"",status:"streaming",startedAt:Date.now(),kind:"sub",parentGenerationId:o});const u=e.tools.map(d=>({name:d.name,description:d.description,parameters:d.parameters??{type:"object",properties:{}}})),c=[];e.context&&c.push({role:"system",name:e.name,content:e.context}),c.push(...this.history.windowed(this.historyWindow)),c.push({role:"user",content:`${n.prompt}
2
+
3
+ ${y()}`});const s=await this.generation.run({agentName:e.name,llm:a,messages:c,tools:u,temperature:this.temperature,maxTokens:this.maxTokens,maxToolIterations:this.maxToolIterations,isCurrent:i(()=>this.isCurrent(t),"isCurrent"),onDelta:i((d,m)=>{m.length===0&&this.conversation.noteTiming("firstToken",r)},"onDelta"),resolveToolCalls:i(d=>this.tools.resolveCalls(d),"resolveToolCalls")});return!this.isCurrent(t)||s.status==="interrupted"?(await this.conversation.cancelSubGeneration(r),{agent:e.name,text:"",error:"interrupted"}):(await this.conversation.completeSubGeneration(r,s.text),s.status==="error"?(this.conversation.emit("error",{conversationId:this.conversation.id,error:s.error instanceof Error?s.error:new Error(String(s.error))}),{agent:e.name,text:s.text,error:s.error instanceof Error?s.error.message:String(s.error)}):{agent:e.name,text:s.text})}}export{b as CoordinationRunner};
4
+ //# sourceMappingURL=coordination-runner.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/conversations/orchestration/orchestrator/coordination-runner/coordination-runner.ts"],
4
+ "sourcesContent": ["import type { Agent } from \"../../../../agents/agent\";\nimport type { Conversation } from \"../../../conversation/conversation\";\nimport type { LLM, LLMMessage, LLMToolDefinition } from \"../../../../providers/llm/types\";\nimport type { Turn } from \"../../../types\";\nimport {\n Coordination,\n CoordinationBudgetExceeded,\n CoordinationCancelled,\n CoordinationSuspension,\n type CoordinationRegistration,\n type CoordinationRuntime,\n type DelegatedTask,\n type DelegationResult,\n type PendingFrame,\n} from \"../../coordination/coordination\";\nimport { ConversationHistory, formatTimeContext } from \"../history/history\";\nimport { buildUnderstandPrompt, findAgentByName } from \"../routing/routing\";\nimport type { GenerationRunner } from \"../generation/generation\";\nimport type { SpeechPipeline } from \"../speech/speech\";\nimport type { ToolCallManager } from \"../tools/tools\";\n\nexport interface CoordinationRunnerOptions {\n conversation: Conversation;\n /** Live roster accessor (read at coordination-run time). */\n agents(): Agent[];\n /** Live shared-LLM accessor (undefined in transcription-only mode). */\n llm(): LLM | undefined;\n /** The conversation's message log, seeded into fresh coordination runs. */\n history: ConversationHistory;\n historyWindow: Parameters<ConversationHistory[\"windowed\"]>[0];\n speech: SpeechPipeline;\n generation: GenerationRunner;\n tools: ToolCallManager;\n /** Safety bound on LLM reasoning steps per coordination execution. */\n maxCoordinationSteps: number;\n maxToolIterations: number;\n temperature?: number;\n maxTokens?: number;\n /** The orchestrator's current generation epoch (bumped on interrupt/stop). */\n currentEpoch(): number;\n /** True while the orchestrator is started and the epoch is current. */\n isCurrent(epoch: number): boolean;\n}\n\n/** A coordination execution parked while waiting for the user to answer. */\ninterface PendingExecution {\n /** Execution stack, outermost frame first. */\n frames: PendingFrame[];\n question: string;\n /** Coordination step count so the budget survives the suspension. */\n stepCount: number;\n}\n\n/**\n * The application-specific execution of coordinations: binds the generic\n * `Coordination` primitives to the orchestrator's machinery (roster, shared\n * LLM, history, speech, delegation, budgets, cancellation) and owns the\n * suspension/resume lifecycle \u2014 the parked frame stack, the step budget, and\n * the coordination generation records.\n */\nexport class CoordinationRunner {\n /** Coordinations registered by name (the key is the coordination's name). */\n readonly coordinations: Record<string, Coordination> = {};\n /** The built-in `understand` coordination, when one is active. */\n understand: Coordination | null = null;\n\n private readonly conversation: Conversation;\n private readonly agents: () => Agent[];\n private readonly llm: () => LLM | undefined;\n private readonly history: ConversationHistory;\n private readonly historyWindow: Parameters<ConversationHistory[\"windowed\"]>[0];\n private readonly speech: SpeechPipeline;\n private readonly generation: GenerationRunner;\n private readonly tools: ToolCallManager;\n private readonly maxCoordinationSteps: number;\n private readonly maxToolIterations: number;\n private readonly temperature: number | undefined;\n private readonly maxTokens: number | undefined;\n private readonly currentEpoch: () => number;\n private readonly isCurrent: (epoch: number) => boolean;\n\n private coordinationEpoch = 0;\n private coordinationStepCount = 0;\n private coordinationRunId = \"\";\n private pendingExecution: PendingExecution | null = null;\n\n constructor(options: CoordinationRunnerOptions) {\n this.conversation = options.conversation;\n this.agents = options.agents;\n this.llm = options.llm;\n this.history = options.history;\n this.historyWindow = options.historyWindow;\n this.speech = options.speech;\n this.generation = options.generation;\n this.tools = options.tools;\n this.maxCoordinationSteps = options.maxCoordinationSteps;\n this.maxToolIterations = options.maxToolIterations;\n this.temperature = options.temperature;\n this.maxTokens = options.maxTokens;\n this.currentEpoch = options.currentEpoch;\n this.isCurrent = options.isCurrent;\n }\n\n /**\n * Register coordinations by name. The built-in `understand` runs unaddressed\n * turns: it decides whether to delegate to agents, ask the user, or answer\n * directly. Apps can override it by registering their own \"understand\" key,\n * and add their own (e.g. clarify, review).\n */\n register(\n registrations: Record<string, CoordinationRegistration>,\n agents: readonly Agent[],\n ): void {\n const merged: Record<string, CoordinationRegistration> = {\n ...registrations,\n };\n if (agents.length > 1 && !merged.understand) {\n merged.understand = { prompt: buildUnderstandPrompt(agents) };\n }\n for (const [name, registration] of Object.entries(merged)) {\n this.coordinations[name] = new Coordination(\n { name, ...registration },\n this.runtime(),\n );\n }\n this.understand = this.coordinations[\"understand\"] ?? null;\n }\n\n /** True while a coordination is parked waiting for the user to answer. */\n hasPending(): boolean {\n return this.pendingExecution !== null;\n }\n\n /** Drop a parked execution (interrupt, stop). */\n cancel(): void {\n this.pendingExecution = null;\n }\n\n /**\n * Run the built-in `understand` coordination on an unaddressed turn. A\n * streaming generation is opened for the conversation's default agent; the\n * coordination's final answer (or question) completes it.\n */\n async runDefault(turn: Turn): Promise<void> {\n const understand = this.understand;\n const llm = this.llm();\n if (!understand || !llm) return;\n this.coordinationEpoch = this.currentEpoch();\n this.coordinationStepCount = 0;\n this.coordinationRunId = crypto.randomUUID();\n await this.conversation.pushGeneration({\n id: this.coordinationRunId,\n conversationId: this.conversation.id,\n agentName: this.agents()[0]!.name,\n text: \"\",\n status: \"streaming\",\n startedAt: Date.now(),\n });\n\n try {\n // The current turn is already in history, so no separate input message.\n const output = await understand.run();\n await this.finalizeOutput(String(output));\n } catch (error) {\n if (error instanceof CoordinationSuspension) {\n await this.recordSuspension(error);\n } else if (error instanceof CoordinationCancelled) {\n // Discarded by an interrupt \u2014 nothing to finalize.\n } else {\n this.emitError(error);\n }\n }\n }\n\n /**\n * Resume a parked coordination with the user's answer, propagating the\n * result back up the frame stack to the outermost coordination.\n */\n async resume(turn: Turn): Promise<void> {\n const pending = this.pendingExecution;\n if (!pending) return;\n this.pendingExecution = null;\n this.coordinationEpoch = this.currentEpoch();\n this.coordinationStepCount = pending.stepCount;\n this.coordinationRunId = crypto.randomUUID();\n await this.conversation.pushGeneration({\n id: this.coordinationRunId,\n conversationId: this.conversation.id,\n agentName: this.agents()[0]!.name,\n text: \"\",\n status: \"streaming\",\n startedAt: Date.now(),\n });\n\n const frames = [...pending.frames]; // outermost first\n const innermost = frames.pop();\n if (!innermost) return;\n\n let result: unknown;\n try {\n result = await innermost.coordination.resume(innermost.state, turn.text);\n } catch (error) {\n if (error instanceof CoordinationSuspension) {\n error.frames.unshift(...frames);\n await this.recordSuspension(error);\n } else if (!(error instanceof CoordinationCancelled)) {\n this.emitError(error);\n }\n return;\n }\n\n // Feed the result back into each remaining parent frame, innermost first.\n while (frames.length > 0) {\n const parent = frames.pop()!;\n const toolCallId = parent.state.pendingToolCallId ?? crypto.randomUUID();\n try {\n result = await parent.coordination.continueWith(parent.state, {\n role: \"tool\",\n toolCallId,\n name: \"delegate\",\n content: JSON.stringify(result),\n });\n } catch (error) {\n if (error instanceof CoordinationSuspension) {\n error.frames.unshift(...frames);\n await this.recordSuspension(error);\n } else if (!(error instanceof CoordinationCancelled)) {\n this.emitError(error);\n }\n return;\n }\n }\n\n await this.finalizeOutput(String(result));\n }\n\n /**\n * The runtime the coordinations reason against. Binds the coordination\n * primitives (delegate to agents, ask the user, speech, budget, cancellation)\n * to the runner's machinery without coupling `Coordination` to it.\n */\n runtime(): CoordinationRuntime {\n const runner = this;\n return {\n // Getters: read the current state at call time (the coordinations are\n // built after the runtime object is created).\n get agents() {\n return runner.agents();\n },\n get coordinations() {\n return Object.values(runner.coordinations);\n },\n get llm() {\n return runner.llm()!;\n },\n get history() {\n return runner.history.windowed(runner.historyWindow);\n },\n delegateAgentTasks: (tasks) => this.delegateAgentTasks(tasks),\n askUser: (frame, question) => this.askUser(frame, question),\n onDelta: (delta) => this.speech.feed(delta, this.currentEpoch()),\n flushSpeech: () => this.speech.flush(this.currentEpoch()),\n speak: (sentence) => this.speech.speak(sentence, this.currentEpoch()),\n isCancelled: () => this.currentEpoch() !== this.coordinationEpoch,\n checkBudget: () => this.checkBudget(),\n };\n }\n\n /** Complete the current generation and record the coordination's answer. */\n private async finalizeOutput(text: string): Promise<void> {\n this.speech.flush(this.currentEpoch());\n await this.speech.waitForIdle();\n if (this.currentEpoch() !== this.coordinationEpoch) return;\n await this.conversation.completeGeneration(text);\n await this.conversation.pushTranscript({\n speaker: this.agents()[0]!.name,\n speakerKind: \"agent\",\n text,\n });\n this.history.addAssistant(this.agents()[0]!.name, text);\n }\n\n /** Park a suspended coordination: record the question and store the stack. */\n private async recordSuspension(suspension: CoordinationSuspension): Promise<void> {\n await this.conversation.completeGeneration(suspension.question);\n await this.conversation.pushTranscript({\n speaker: this.agents()[0]!.name,\n speakerKind: \"agent\",\n text: suspension.question,\n });\n this.history.addAssistant(this.agents()[0]!.name, suspension.question);\n this.pendingExecution = {\n frames: suspension.frames,\n question: suspension.question,\n stepCount: this.coordinationStepCount,\n };\n }\n\n /** Throw the suspension that parks a coordination waiting for the user. */\n private askUser(frame: PendingFrame, question: string): never {\n // Recording (transcript, history, generation) happens when the suspension\n // is caught at the top of the stack, where the full frame set is known.\n throw new CoordinationSuspension([frame], question);\n }\n\n /** Enforce the per-execution reasoning step budget. */\n private checkBudget(): void {\n this.coordinationStepCount++;\n if (this.coordinationStepCount > this.maxCoordinationSteps) {\n throw new CoordinationBudgetExceeded(\n `exceeded ${this.maxCoordinationSteps} coordination steps`,\n );\n }\n }\n\n private emitError(error: unknown): void {\n this.conversation.emit(\"error\", {\n conversationId: this.conversation.id,\n error: error instanceof Error ? error : new Error(String(error)),\n });\n // Finalize the current coordination generation so an errored run does not\n // leave a dangling \"streaming\" record. The narration was streamed to\n // speech; the failure surfaces through the error event.\n if (this.currentEpoch() === this.coordinationEpoch) {\n void this.conversation.completeGeneration(\"\");\n }\n }\n\n /** Run delegated agent tasks in parallel and surface their work. */\n private async delegateAgentTasks(tasks: DelegatedTask[]): Promise<DelegationResult[]> {\n const results = await Promise.all(\n tasks.map((task) =>\n this.runSubGeneration(this.coordinationEpoch, task, this.coordinationRunId),\n ),\n );\n\n if (!this.isCurrent(this.coordinationEpoch)) {\n return results.map(({ agent, text, error }) => ({ agent, text, error }));\n }\n\n // Surface each specialist's work in the transcript, in task order.\n for (const result of results) {\n if (result.text && !result.error) {\n await this.conversation.pushTranscript({\n speaker: result.agent,\n speakerKind: \"agent\",\n text: result.text,\n });\n }\n }\n return results;\n }\n\n /**\n * Execute one dispatched task as a sub-generation: the target agent's own\n * LLM, context, and tools, running text-only (no TTS). The final text is\n * returned so the coordinator can merge it into the spoken answer.\n */\n private async runSubGeneration(\n epoch: number,\n task: DelegatedTask,\n parentGenerationId: string,\n ): Promise<DelegationResult> {\n const agent = findAgentByName(this.agents(), task.agent);\n if (!agent) {\n return { agent: task.agent, text: \"\", error: `Unknown agent \"${task.agent}\"` };\n }\n const llm = agent.llm ?? this.llm();\n if (!llm) {\n return {\n agent: agent.name,\n text: \"\",\n error: `Agent \"${agent.name}\" has no LLM configured`,\n };\n }\n\n const id = crypto.randomUUID();\n await this.conversation.pushSubGeneration({\n id,\n conversationId: this.conversation.id,\n agentName: agent.name,\n text: \"\",\n status: \"streaming\",\n startedAt: Date.now(),\n kind: \"sub\",\n parentGenerationId,\n });\n\n const definitions: LLMToolDefinition[] = agent.tools.map((tool) => ({\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters ?? { type: \"object\", properties: {} },\n }));\n\n const messages: LLMMessage[] = [];\n if (agent.context) {\n messages.push({ role: \"system\", name: agent.name, content: agent.context });\n }\n messages.push(...this.history.windowed(this.historyWindow));\n // The prompt carries a time stamp so time-sensitive tasks (flights,\n // meetings, deadlines) don't reason about a stale \"now\".\n messages.push({ role: \"user\", content: `${task.prompt}\\n\\n${formatTimeContext()}` });\n\n const outcome = await this.generation.run({\n agentName: agent.name,\n llm,\n messages,\n tools: definitions,\n temperature: this.temperature,\n maxTokens: this.maxTokens,\n maxToolIterations: this.maxToolIterations,\n isCurrent: () => this.isCurrent(epoch),\n onDelta: (delta, textBefore) => {\n if (textBefore.length === 0) this.conversation.noteTiming(\"firstToken\", id);\n },\n resolveToolCalls: (calls) => this.tools.resolveCalls(calls),\n });\n\n if (!this.isCurrent(epoch) || outcome.status === \"interrupted\") {\n await this.conversation.cancelSubGeneration(id);\n return { agent: agent.name, text: \"\", error: \"interrupted\" };\n }\n\n await this.conversation.completeSubGeneration(id, outcome.text);\n if (outcome.status === \"error\") {\n this.conversation.emit(\"error\", {\n conversationId: this.conversation.id,\n error: outcome.error instanceof Error ? outcome.error : new Error(String(outcome.error)),\n });\n return {\n agent: agent.name,\n text: outcome.text,\n error: outcome.error instanceof Error ? outcome.error.message : String(outcome.error),\n };\n }\n return { agent: agent.name, text: outcome.text };\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["Coordination", "CoordinationBudgetExceeded", "CoordinationCancelled", "CoordinationSuspension", "formatTimeContext", "buildUnderstandPrompt", "findAgentByName", "CoordinationRunner", "__name", "options", "registrations", "agents", "merged", "name", "registration", "turn", "understand", "llm", "output", "error", "pending", "frames", "innermost", "result", "parent", "toolCallId", "runner", "tasks", "frame", "question", "delta", "sentence", "text", "suspension", "results", "task", "agent", "epoch", "parentGenerationId", "id", "definitions", "tool", "messages", "outcome", "textBefore", "calls"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import{CoordinationRunner as r}from"./coordination-runner.js";export{r as CoordinationRunner};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/conversations/orchestration/orchestrator/coordination-runner/index.ts"],
4
+ "sourcesContent": ["export { CoordinationRunner } from \"./coordination-runner\";\nexport type { CoordinationRunnerOptions } from \"./coordination-runner\";\n"],
5
+ "mappings": "AAAA,OAAS,sBAAAA,MAA0B",
6
+ "names": ["CoordinationRunner"]
7
+ }
@@ -0,0 +1,2 @@
1
+ var h=Object.defineProperty;var c=(n,s)=>h(n,"name",{value:s,configurable:!0});class v{static{c(this,"GenerationRunner")}async run(s){const{agentName:e,llm:d,messages:a,tools:p,temperature:L,maxTokens:g,maxToolIterations:M,isCurrent:l,agentNames:T=!0,onDelta:b,resolveToolCalls:x}=s;let o="",m=0;try{for(let i=0;i<M;i++){if(!l())return{text:o,status:"interrupted"};const u=[];let f=!1;const C=T?a:y(a);for await(const t of d.stream({messages:C,tools:p,temperature:L,maxTokens:g})){if(!l())return{text:o,status:"interrupted"};switch(t.type){case"delta":{const r=o;o+=t.content,t.content.length>0&&b?.(t.content,r);break}case"tool_call":u.push({id:t.id,name:t.name,arguments:t.arguments});break;case"error":throw t.error;case"done":f=!0}}if(!l())return{text:o,status:"interrupted"};if(u.length>0){m++,a.push({role:"assistant",name:e,content:o,toolCalls:u});const t=await x(u);if(!l())return{text:o,status:"interrupted"};for(const r of t)a.push({role:"tool",toolCallId:r.id,name:r.name,content:JSON.stringify(r.error!==void 0?{error:r.error}:r.result)});continue}if(f)break}return{text:o,status:"done"}}catch(i){return{text:o,status:"error",error:i,...m>0?{toolRounds:m}:{}}}}}function y(n){let s=!1;for(const e of n)if(e.name&&(e.role==="system"||e.role==="assistant")){s=!0;break}return s?n.map(e=>e.name&&(e.role==="system"||e.role==="assistant")?{...e,name:void 0}:e):n}c(y,"withoutAgentNames");export{v as GenerationRunner};
2
+ //# sourceMappingURL=generation.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/conversations/orchestration/orchestrator/generation/generation.ts"],
4
+ "sourcesContent": ["import type {\n LLM,\n LLMToolCall,\n LLMToolDefinition,\n LLMMessage,\n} from \"../../../../providers/llm/types\";\nimport type { ResolvedToolCall } from \"../tools/tools\";\n\nexport interface GenerationRequest {\n /** Display name stamped on assistant tool-call messages. */\n agentName: string;\n llm: LLM;\n /**\n * The conversation messages; the loop appends the assistant tool-call\n * message and the resolved tool results onto this array.\n */\n messages: LLMMessage[];\n tools: LLMToolDefinition[];\n temperature?: number;\n maxTokens?: number;\n /** Safety bound on tool-call round trips per generation. */\n maxToolIterations: number;\n /** False once the run is stale (interrupt/stop); aborts the loop. */\n isCurrent(): boolean;\n /**\n * Whether outgoing messages keep per-agent `name` fields on system and\n * assistant messages. Multi-agent conversations need them so the model can\n * tell which agent said what in the shared history. Single-agent\n * conversations drop them: with one agent the names carry no information,\n * and some providers render a message `name` as a role header (\"Scout:\")\n * that weaker models imitate \u2014 every reply then starts by speaking the\n * agent's name. Default true.\n */\n agentNames?: boolean;\n /** Streamed text; `textBefore` is the running text prior to this delta. */\n onDelta?(delta: string, textBefore: string): void;\n /** Hand tool calls to the application and resolve their results. */\n resolveToolCalls(calls: LLMToolCall[]): Promise<ResolvedToolCall[]>;\n}\n\nexport type GenerationStatus = \"done\" | \"interrupted\" | \"error\";\n\nexport interface GenerationOutcome {\n /** Everything the model produced (or produced before failing). */\n text: string;\n status: GenerationStatus;\n /** The provider error, when `status` is \"error\". */\n error?: unknown;\n /**\n * How many tool rounds were resolved before the run ended (only present\n * when at least one). Lets callers retry a no-output failure safely:\n * re-running a generation whose tools already executed would repeat their\n * side effects.\n */\n toolRounds?: number;\n}\n\n/**\n * Owns the LLM tool loop shared by top-level generations and delegated\n * sub-generations: stream deltas, collect tool calls, resolve them through\n * the application, and repeat up to `maxToolIterations`.\n *\n * It is deliberately ignorant of the conversation lifecycle \u2014 persistence,\n * transcripts, speech, and history are the caller's concern, decided from\n * the returned `GenerationOutcome`.\n */\nexport class GenerationRunner {\n async run(request: GenerationRequest): Promise<GenerationOutcome> {\n const {\n agentName,\n llm,\n messages,\n tools,\n temperature,\n maxTokens,\n maxToolIterations,\n isCurrent,\n agentNames = true,\n onDelta,\n resolveToolCalls,\n } = request;\n\n let text = \"\";\n let toolRounds = 0;\n\n try {\n for (let iteration = 0; iteration < maxToolIterations; iteration++) {\n if (!isCurrent()) return { text, status: \"interrupted\" };\n\n const toolCalls: LLMToolCall[] = [];\n let done = false;\n\n // Single-agent conversations don't need per-agent `name` fields (see\n // GenerationRequest.agentNames): strip them before every call, since\n // the tool loop appends fresh messages between iterations. Never\n // mutate the caller's array.\n const wireMessages = agentNames ? messages : withoutAgentNames(messages);\n\n for await (const event of llm.stream({ messages: wireMessages, tools, temperature, maxTokens })) {\n if (!isCurrent()) return { text, status: \"interrupted\" };\n switch (event.type) {\n case \"delta\": {\n const before = text;\n text += event.content;\n if (event.content.length > 0) onDelta?.(event.content, before);\n break;\n }\n case \"tool_call\":\n toolCalls.push({ id: event.id, name: event.name, arguments: event.arguments });\n break;\n case \"error\":\n throw event.error;\n case \"done\":\n done = true;\n }\n }\n\n if (!isCurrent()) return { text, status: \"interrupted\" };\n\n if (toolCalls.length > 0) {\n toolRounds++;\n // Pause the response: hand the calls to the application, then\n // resume once they are resolved.\n messages.push({ role: \"assistant\", name: agentName, content: text, toolCalls });\n const results = await resolveToolCalls(toolCalls);\n if (!isCurrent()) return { text, status: \"interrupted\" };\n for (const result of results) {\n messages.push({\n role: \"tool\",\n toolCallId: result.id,\n name: result.name,\n content: JSON.stringify(\n result.error !== undefined ? { error: result.error } : result.result,\n ),\n });\n }\n continue;\n }\n\n if (done) break;\n }\n\n return { text, status: \"done\" };\n } catch (error) {\n return {\n text,\n status: \"error\",\n error,\n ...(toolRounds > 0 ? { toolRounds } : {}),\n };\n }\n }\n}\n\n/**\n * Clone the messages with per-agent `name` fields removed from system and\n * assistant messages. Tool messages keep their `name` (the wire format\n * requires it on `role: \"tool\"`), and user messages never carry one.\n */\nfunction withoutAgentNames(messages: LLMMessage[]): LLMMessage[] {\n let hasNames = false;\n for (const message of messages) {\n if (message.name && (message.role === \"system\" || message.role === \"assistant\")) {\n hasNames = true;\n break;\n }\n }\n if (!hasNames) return messages;\n return messages.map((message) =>\n message.name && (message.role === \"system\" || message.role === \"assistant\")\n ? { ...message, name: undefined }\n : message,\n );\n}\n"],
5
+ "mappings": "+EAkEO,MAAMA,CAAiB,CAlE9B,MAkE8B,CAAAC,EAAA,yBAC5B,MAAM,IAAIC,EAAwD,CAChE,KAAM,CACJ,UAAAC,EACA,IAAAC,EACA,SAAAC,EACA,MAAAC,EACA,YAAAC,EACA,UAAAC,EACA,kBAAAC,EACA,UAAAC,EACA,WAAAC,EAAa,GACb,QAAAC,EACA,iBAAAC,CACF,EAAIX,EAEJ,IAAIY,EAAO,GACPC,EAAa,EAEjB,GAAI,CACF,QAASC,EAAY,EAAGA,EAAYP,EAAmBO,IAAa,CAClE,GAAI,CAACN,EAAU,EAAG,MAAO,CAAE,KAAAI,EAAM,OAAQ,aAAc,EAEvD,MAAMG,EAA2B,CAAC,EAClC,IAAIC,EAAO,GAMX,MAAMC,EAAeR,EAAaN,EAAWe,EAAkBf,CAAQ,EAEvE,gBAAiBgB,KAASjB,EAAI,OAAO,CAAE,SAAUe,EAAc,MAAAb,EAAO,YAAAC,EAAa,UAAAC,CAAU,CAAC,EAAG,CAC/F,GAAI,CAACE,EAAU,EAAG,MAAO,CAAE,KAAAI,EAAM,OAAQ,aAAc,EACvD,OAAQO,EAAM,KAAM,CAClB,IAAK,QAAS,CACZ,MAAMC,EAASR,EACfA,GAAQO,EAAM,QACVA,EAAM,QAAQ,OAAS,GAAGT,IAAUS,EAAM,QAASC,CAAM,EAC7D,KACF,CACA,IAAK,YACHL,EAAU,KAAK,CAAE,GAAII,EAAM,GAAI,KAAMA,EAAM,KAAM,UAAWA,EAAM,SAAU,CAAC,EAC7E,MACF,IAAK,QACH,MAAMA,EAAM,MACd,IAAK,OACHH,EAAO,EACX,CACF,CAEA,GAAI,CAACR,EAAU,EAAG,MAAO,CAAE,KAAAI,EAAM,OAAQ,aAAc,EAEvD,GAAIG,EAAU,OAAS,EAAG,CACxBF,IAGAV,EAAS,KAAK,CAAE,KAAM,YAAa,KAAMF,EAAW,QAASW,EAAM,UAAAG,CAAU,CAAC,EAC9E,MAAMM,EAAU,MAAMV,EAAiBI,CAAS,EAChD,GAAI,CAACP,EAAU,EAAG,MAAO,CAAE,KAAAI,EAAM,OAAQ,aAAc,EACvD,UAAWU,KAAUD,EACnBlB,EAAS,KAAK,CACZ,KAAM,OACN,WAAYmB,EAAO,GACnB,KAAMA,EAAO,KACb,QAAS,KAAK,UACZA,EAAO,QAAU,OAAY,CAAE,MAAOA,EAAO,KAAM,EAAIA,EAAO,MAChE,CACF,CAAC,EAEH,QACF,CAEA,GAAIN,EAAM,KACZ,CAEA,MAAO,CAAE,KAAAJ,EAAM,OAAQ,MAAO,CAChC,OAASW,EAAO,CACd,MAAO,CACL,KAAAX,EACA,OAAQ,QACR,MAAAW,EACA,GAAIV,EAAa,EAAI,CAAE,WAAAA,CAAW,EAAI,CAAC,CACzC,CACF,CACF,CACF,CAOA,SAASK,EAAkBf,EAAsC,CAC/D,IAAIqB,EAAW,GACf,UAAWC,KAAWtB,EACpB,GAAIsB,EAAQ,OAASA,EAAQ,OAAS,UAAYA,EAAQ,OAAS,aAAc,CAC/ED,EAAW,GACX,KACF,CAEF,OAAKA,EACErB,EAAS,IAAKsB,GACnBA,EAAQ,OAASA,EAAQ,OAAS,UAAYA,EAAQ,OAAS,aAC3D,CAAE,GAAGA,EAAS,KAAM,MAAU,EAC9BA,CACN,EALsBtB,CAMxB,CAdSJ,EAAAmB,EAAA",
6
+ "names": ["GenerationRunner", "__name", "request", "agentName", "llm", "messages", "tools", "temperature", "maxTokens", "maxToolIterations", "isCurrent", "agentNames", "onDelta", "resolveToolCalls", "text", "toolRounds", "iteration", "toolCalls", "done", "wireMessages", "withoutAgentNames", "event", "before", "results", "result", "error", "hasNames", "message"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import{GenerationRunner as t}from"./generation.js";export{t as GenerationRunner};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/conversations/orchestration/orchestrator/generation/index.ts"],
4
+ "sourcesContent": ["export { GenerationRunner } from \"./generation\";\nexport type {\n GenerationOutcome,\n GenerationRequest,\n GenerationStatus,\n} from \"./generation\";\n"],
5
+ "mappings": "AAAA,OAAS,oBAAAA,MAAwB",
6
+ "names": ["GenerationRunner"]
7
+ }
@@ -0,0 +1,4 @@
1
+ var d=Object.defineProperty;var o=(s,e)=>d(s,"name",{value:e,configurable:!0});const l=["jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"];function g(s=new Date){const e=s.getDate(),r=l[s.getMonth()],a=s.getFullYear(),i=String(s.getHours()).padStart(2,"0"),t=String(s.getMinutes()).padStart(2,"0");return`Now it is ${e} ${r} ${a}, ${i}:${t}.`}o(g,"formatTimeContext");function p(s,e,r=new Date){const a=o(n=>{const u=n.aliases[0]??n.userId,c=n.aliases.length>0?` (aliases: ${n.aliases.join(", ")})`:"";return`${u} with user id ${n.userId}${c}`},"describe"),i=e.filter(n=>n.userId!==s.userId),t=i.length>0?` The other participants are ${i.map(a).join(", ")}.`:"";return`
2
+
3
+ Additional context: ${g(r)} The current user is ${a(s)}.${t}`}o(p,"formatTurnContext");function m(s,{maxTurns:e,maxChars:r}){if(s.length===0)return s;let a=0,i=0;for(let n=s.length-1;n>=0;n--)if(s[n].role==="user"&&(i++,i===e)){a=n;break}let t=a>0?s.slice(a):s;if(r>0)for(;t.length>1&&t.reduce((n,u)=>n+u.content.length,0)>r;)t=t.slice(1);return t}o(m,"windowHistory");class h{static{o(this,"ConversationHistory")}messages=[];turnMessage(e,r){const a=r.state.participants.get(e.participantId),i=[...r.state.participants.values()],t=a?p(a,i,new Date(e.startedAt)):"";return`${e.participantName}: ${e.text}${t}`}addUserTurn(e,r){this.messages.push({role:"user",content:this.turnMessage(e,r)})}addAssistant(e,r){this.messages.push({role:"assistant",name:e,content:r})}rehydrate(e,r,a){const i=[...e.map(t=>({at:t.startedAt,kind:"turn",turn:t})),...r.filter(t=>t.status==="completed"&&t.kind!=="sub").map(t=>({at:t.startedAt,kind:"generation",agentName:t.agentName,text:t.text}))].sort((t,n)=>t.at-n.at);for(const t of i)t.kind==="turn"?this.addUserTurn(t.turn,a):this.addAssistant(t.agentName,t.text)}get all(){return this.messages}windowed(e){return e===!1?this.messages:m(this.messages,e)}}export{h as ConversationHistory,g as formatTimeContext,p as formatTurnContext,m as windowHistory};
4
+ //# sourceMappingURL=history.js.map