@moureau/pipeflow 0.0.1 → 0.0.2

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 (311) hide show
  1. package/README.md +245 -117
  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/conversations/conversation/conversation.js +1 -1
  7. package/dist/cjs/conversations/conversation/conversation.js.map +3 -3
  8. package/dist/cjs/conversations/conversations.js +1 -1
  9. package/dist/cjs/conversations/conversations.js.map +3 -3
  10. package/dist/cjs/conversations/index.js +1 -1
  11. package/dist/cjs/conversations/index.js.map +3 -3
  12. package/dist/cjs/conversations/orchestration/coordination/coordination.js +10 -0
  13. package/dist/cjs/conversations/orchestration/coordination/coordination.js.map +7 -0
  14. package/dist/cjs/conversations/orchestration/coordination/index.js +2 -0
  15. package/dist/cjs/conversations/orchestration/coordination/index.js.map +7 -0
  16. package/dist/cjs/conversations/orchestration/orchestrator/coordination-runner/coordination-runner.js +4 -0
  17. package/dist/cjs/conversations/orchestration/orchestrator/coordination-runner/coordination-runner.js.map +7 -0
  18. package/dist/cjs/conversations/orchestration/orchestrator/coordination-runner/index.js +2 -0
  19. package/dist/cjs/conversations/orchestration/orchestrator/coordination-runner/index.js.map +7 -0
  20. package/dist/cjs/conversations/orchestration/orchestrator/generation/generation.js +2 -0
  21. package/dist/cjs/conversations/orchestration/orchestrator/generation/generation.js.map +7 -0
  22. package/dist/cjs/conversations/orchestration/orchestrator/generation/index.js +2 -0
  23. package/dist/cjs/conversations/orchestration/orchestrator/generation/index.js.map +7 -0
  24. package/dist/cjs/conversations/orchestration/orchestrator/history/history.js +4 -0
  25. package/dist/cjs/conversations/orchestration/orchestrator/history/history.js.map +7 -0
  26. package/dist/cjs/conversations/orchestration/orchestrator/history/index.js +2 -0
  27. package/dist/cjs/conversations/orchestration/orchestrator/history/index.js.map +7 -0
  28. package/dist/cjs/conversations/orchestration/orchestrator/index.js +1 -1
  29. package/dist/cjs/conversations/orchestration/orchestrator/index.js.map +3 -3
  30. package/dist/cjs/conversations/orchestration/orchestrator/orchestrator.js +1 -2
  31. package/dist/cjs/conversations/orchestration/orchestrator/orchestrator.js.map +3 -3
  32. package/dist/cjs/conversations/orchestration/orchestrator/routing/index.js +2 -0
  33. package/dist/cjs/conversations/orchestration/orchestrator/routing/index.js.map +7 -0
  34. package/dist/cjs/conversations/orchestration/orchestrator/routing/routing.js +23 -0
  35. package/dist/cjs/conversations/orchestration/orchestrator/routing/routing.js.map +7 -0
  36. package/dist/cjs/conversations/orchestration/orchestrator/speech/index.js +2 -0
  37. package/dist/cjs/conversations/orchestration/orchestrator/speech/index.js.map +7 -0
  38. package/dist/cjs/conversations/orchestration/orchestrator/speech/speech.js +2 -0
  39. package/dist/cjs/conversations/orchestration/orchestrator/speech/speech.js.map +7 -0
  40. package/dist/cjs/conversations/orchestration/orchestrator/tools/index.js +2 -0
  41. package/dist/cjs/conversations/orchestration/orchestrator/tools/index.js.map +7 -0
  42. package/dist/cjs/conversations/orchestration/orchestrator/tools/tools.js +2 -0
  43. package/dist/cjs/conversations/orchestration/orchestrator/tools/tools.js.map +7 -0
  44. package/dist/cjs/conversations/orchestration/test-harness.js +2 -0
  45. package/dist/cjs/conversations/orchestration/test-harness.js.map +7 -0
  46. package/dist/cjs/conversations/orchestration/text-chunker/index.js +2 -0
  47. package/dist/cjs/conversations/orchestration/text-chunker/index.js.map +7 -0
  48. package/dist/cjs/conversations/orchestration/text-chunker/text-chunker.js +3 -0
  49. package/dist/cjs/conversations/orchestration/text-chunker/text-chunker.js.map +7 -0
  50. package/dist/cjs/conversations/stream/conversation-stream.js +2 -0
  51. package/dist/cjs/conversations/stream/conversation-stream.js.map +7 -0
  52. package/dist/cjs/conversations/stream/index.js +2 -0
  53. package/dist/cjs/conversations/stream/index.js.map +7 -0
  54. package/dist/cjs/conversations/types.js +1 -1
  55. package/dist/cjs/conversations/types.js.map +2 -2
  56. package/dist/cjs/index.js +1 -1
  57. package/dist/cjs/index.js.map +3 -3
  58. package/dist/cjs/persistence/adapters/sqlite/sqlite.js +18 -14
  59. package/dist/cjs/persistence/adapters/sqlite/sqlite.js.map +3 -3
  60. package/dist/cjs/pipeflow/index.js +2 -0
  61. package/dist/cjs/pipeflow/index.js.map +7 -0
  62. package/dist/cjs/pipeflow/pipeflow.js +2 -0
  63. package/dist/cjs/pipeflow/pipeflow.js.map +7 -0
  64. package/dist/cjs/providers/index.js +1 -1
  65. package/dist/cjs/providers/index.js.map +2 -2
  66. package/dist/cjs/providers/llm/adapters/claude/claude.js +5 -0
  67. package/dist/cjs/providers/llm/adapters/claude/claude.js.map +7 -0
  68. package/dist/cjs/providers/llm/adapters/claude/index.js +2 -0
  69. package/dist/cjs/providers/llm/adapters/claude/index.js.map +7 -0
  70. package/dist/cjs/providers/llm/adapters/deepseek/deepseek.js +1 -1
  71. package/dist/cjs/providers/llm/adapters/deepseek/deepseek.js.map +3 -3
  72. package/dist/cjs/providers/llm/adapters/index.js +1 -1
  73. package/dist/cjs/providers/llm/adapters/index.js.map +3 -3
  74. package/dist/cjs/providers/llm/adapters/openai/index.js +2 -0
  75. package/dist/cjs/providers/llm/adapters/openai/index.js.map +7 -0
  76. package/dist/cjs/providers/llm/adapters/openai/openai.js +2 -0
  77. package/dist/cjs/providers/llm/adapters/openai/openai.js.map +7 -0
  78. package/dist/cjs/providers/llm/adapters/openai-compatible.js +10 -0
  79. package/dist/cjs/providers/llm/adapters/openai-compatible.js.map +7 -0
  80. package/dist/cjs/providers/llm/adapters/openrouter/index.js +2 -0
  81. package/dist/cjs/providers/llm/adapters/openrouter/index.js.map +7 -0
  82. package/dist/cjs/providers/llm/adapters/openrouter/openrouter.js +2 -0
  83. package/dist/cjs/providers/llm/adapters/openrouter/openrouter.js.map +7 -0
  84. package/dist/cjs/providers/llm/index.js +1 -1
  85. package/dist/cjs/providers/llm/index.js.map +3 -3
  86. package/dist/cjs/providers/llm/toolmode/index.js +2 -0
  87. package/dist/cjs/providers/llm/toolmode/index.js.map +7 -0
  88. package/dist/cjs/providers/llm/toolmode/toolmode.js +2 -0
  89. package/dist/cjs/providers/llm/toolmode/toolmode.js.map +7 -0
  90. package/dist/cjs/providers/llm/types.js +1 -1
  91. package/dist/cjs/providers/llm/types.js.map +3 -3
  92. package/dist/cjs/providers/stt/adapters/deepgram/deepgram.js +1 -1
  93. package/dist/cjs/providers/stt/adapters/deepgram/deepgram.js.map +3 -3
  94. package/dist/cjs/providers/stt/adapters/index.js +1 -1
  95. package/dist/cjs/providers/stt/adapters/index.js.map +3 -3
  96. package/dist/cjs/providers/stt/adapters/openrouter/index.js +2 -0
  97. package/dist/cjs/providers/stt/adapters/openrouter/index.js.map +7 -0
  98. package/dist/cjs/providers/stt/adapters/openrouter/openrouter.js +2 -0
  99. package/dist/cjs/providers/stt/adapters/openrouter/openrouter.js.map +7 -0
  100. package/dist/cjs/providers/tts/adapters/index.js +1 -1
  101. package/dist/cjs/providers/tts/adapters/index.js.map +3 -3
  102. package/dist/cjs/providers/tts/adapters/kokoro/kokoro.js +4 -1
  103. package/dist/cjs/providers/tts/adapters/kokoro/kokoro.js.map +3 -3
  104. package/dist/cjs/providers/tts/adapters/openrouter/index.js +2 -0
  105. package/dist/cjs/providers/tts/adapters/openrouter/index.js.map +7 -0
  106. package/dist/cjs/providers/tts/adapters/openrouter/openrouter.js +2 -0
  107. package/dist/cjs/providers/tts/adapters/openrouter/openrouter.js.map +7 -0
  108. package/dist/cjs/transport/streamobject/field-stream/field-stream.js +2 -0
  109. package/dist/cjs/transport/streamobject/field-stream/field-stream.js.map +7 -0
  110. package/dist/cjs/transport/streamobject/field-stream/index.js +2 -0
  111. package/dist/cjs/transport/streamobject/field-stream/index.js.map +7 -0
  112. package/dist/cjs/transport/streamobject/index.js +2 -0
  113. package/dist/cjs/transport/streamobject/index.js.map +7 -0
  114. package/dist/cjs/transport/streamobject/json-adapter/index.js +2 -0
  115. package/dist/cjs/transport/streamobject/json-adapter/index.js.map +7 -0
  116. package/dist/cjs/transport/streamobject/json-adapter/json-adapter.js +4 -0
  117. package/dist/cjs/transport/streamobject/json-adapter/json-adapter.js.map +7 -0
  118. package/dist/cjs/transport/streamobject/reference/index.js +2 -0
  119. package/dist/cjs/transport/streamobject/reference/index.js.map +7 -0
  120. package/dist/cjs/transport/streamobject/reference/reference.js +2 -0
  121. package/dist/cjs/transport/streamobject/reference/reference.js.map +7 -0
  122. package/dist/cjs/transport/streamobject/stream-object/index.js +2 -0
  123. package/dist/cjs/transport/streamobject/stream-object/index.js.map +7 -0
  124. package/dist/cjs/transport/streamobject/stream-object/stream-object.js +2 -0
  125. package/dist/cjs/transport/streamobject/stream-object/stream-object.js.map +7 -0
  126. package/dist/esm/agents/agent.js +1 -1
  127. package/dist/esm/agents/agent.js.map +3 -3
  128. package/dist/esm/agents/tools/tools.js +1 -1
  129. package/dist/esm/agents/tools/tools.js.map +3 -3
  130. package/dist/esm/conversations/conversation/conversation.js +1 -1
  131. package/dist/esm/conversations/conversation/conversation.js.map +3 -3
  132. package/dist/esm/conversations/conversations.js +1 -1
  133. package/dist/esm/conversations/conversations.js.map +3 -3
  134. package/dist/esm/conversations/index.js +1 -1
  135. package/dist/esm/conversations/index.js.map +3 -3
  136. package/dist/esm/conversations/orchestration/coordination/coordination.js +10 -0
  137. package/dist/esm/conversations/orchestration/coordination/coordination.js.map +7 -0
  138. package/dist/esm/conversations/orchestration/coordination/index.js +2 -0
  139. package/dist/esm/conversations/orchestration/coordination/index.js.map +7 -0
  140. package/dist/esm/conversations/orchestration/orchestrator/coordination-runner/coordination-runner.js +4 -0
  141. package/dist/esm/conversations/orchestration/orchestrator/coordination-runner/coordination-runner.js.map +7 -0
  142. package/dist/esm/conversations/orchestration/orchestrator/coordination-runner/index.js +2 -0
  143. package/dist/esm/conversations/orchestration/orchestrator/coordination-runner/index.js.map +7 -0
  144. package/dist/esm/conversations/orchestration/orchestrator/generation/generation.js +2 -0
  145. package/dist/esm/conversations/orchestration/orchestrator/generation/generation.js.map +7 -0
  146. package/dist/esm/conversations/orchestration/orchestrator/generation/index.js +2 -0
  147. package/dist/esm/conversations/orchestration/orchestrator/generation/index.js.map +7 -0
  148. package/dist/esm/conversations/orchestration/orchestrator/history/history.js +4 -0
  149. package/dist/esm/conversations/orchestration/orchestrator/history/history.js.map +7 -0
  150. package/dist/esm/conversations/orchestration/orchestrator/history/index.js +2 -0
  151. package/dist/esm/conversations/orchestration/orchestrator/history/index.js.map +7 -0
  152. package/dist/esm/conversations/orchestration/orchestrator/index.js +1 -1
  153. package/dist/esm/conversations/orchestration/orchestrator/index.js.map +3 -3
  154. package/dist/esm/conversations/orchestration/orchestrator/orchestrator.js +1 -2
  155. package/dist/esm/conversations/orchestration/orchestrator/orchestrator.js.map +3 -3
  156. package/dist/esm/conversations/orchestration/orchestrator/routing/index.js +2 -0
  157. package/dist/esm/conversations/orchestration/orchestrator/routing/index.js.map +7 -0
  158. package/dist/esm/conversations/orchestration/orchestrator/routing/routing.js +23 -0
  159. package/dist/esm/conversations/orchestration/orchestrator/routing/routing.js.map +7 -0
  160. package/dist/esm/conversations/orchestration/orchestrator/speech/index.js +2 -0
  161. package/dist/esm/conversations/orchestration/orchestrator/speech/index.js.map +7 -0
  162. package/dist/esm/conversations/orchestration/orchestrator/speech/speech.js +2 -0
  163. package/dist/esm/conversations/orchestration/orchestrator/speech/speech.js.map +7 -0
  164. package/dist/esm/conversations/orchestration/orchestrator/tools/index.js +2 -0
  165. package/dist/esm/conversations/orchestration/orchestrator/tools/index.js.map +7 -0
  166. package/dist/esm/conversations/orchestration/orchestrator/tools/tools.js +2 -0
  167. package/dist/esm/conversations/orchestration/orchestrator/tools/tools.js.map +7 -0
  168. package/dist/esm/conversations/orchestration/test-harness.js +2 -0
  169. package/dist/esm/conversations/orchestration/test-harness.js.map +7 -0
  170. package/dist/esm/conversations/orchestration/text-chunker/index.js +2 -0
  171. package/dist/esm/conversations/orchestration/text-chunker/index.js.map +7 -0
  172. package/dist/esm/conversations/orchestration/text-chunker/text-chunker.js +3 -0
  173. package/dist/esm/conversations/orchestration/text-chunker/text-chunker.js.map +7 -0
  174. package/dist/esm/conversations/stream/conversation-stream.js +2 -0
  175. package/dist/esm/conversations/stream/conversation-stream.js.map +7 -0
  176. package/dist/esm/conversations/stream/index.js +2 -0
  177. package/dist/esm/conversations/stream/index.js.map +7 -0
  178. package/dist/esm/conversations/types.js +1 -1
  179. package/dist/esm/conversations/types.js.map +2 -2
  180. package/dist/esm/index.js +1 -1
  181. package/dist/esm/index.js.map +3 -3
  182. package/dist/esm/persistence/adapters/sqlite/sqlite.js +18 -14
  183. package/dist/esm/persistence/adapters/sqlite/sqlite.js.map +3 -3
  184. package/dist/esm/pipeflow/index.js +2 -0
  185. package/dist/esm/pipeflow/index.js.map +7 -0
  186. package/dist/esm/pipeflow/pipeflow.js +2 -0
  187. package/dist/esm/pipeflow/pipeflow.js.map +7 -0
  188. package/dist/esm/providers/index.js +1 -1
  189. package/dist/esm/providers/index.js.map +3 -3
  190. package/dist/esm/providers/llm/adapters/claude/claude.js +5 -0
  191. package/dist/esm/providers/llm/adapters/claude/claude.js.map +7 -0
  192. package/dist/esm/providers/llm/adapters/claude/index.js +2 -0
  193. package/dist/esm/providers/llm/adapters/claude/index.js.map +7 -0
  194. package/dist/esm/providers/llm/adapters/deepseek/deepseek.js +1 -1
  195. package/dist/esm/providers/llm/adapters/deepseek/deepseek.js.map +3 -3
  196. package/dist/esm/providers/llm/adapters/index.js +1 -1
  197. package/dist/esm/providers/llm/adapters/index.js.map +3 -3
  198. package/dist/esm/providers/llm/adapters/openai/index.js +2 -0
  199. package/dist/esm/providers/llm/adapters/openai/index.js.map +7 -0
  200. package/dist/esm/providers/llm/adapters/openai/openai.js +2 -0
  201. package/dist/esm/providers/llm/adapters/openai/openai.js.map +7 -0
  202. package/dist/esm/providers/llm/adapters/openai-compatible.js +10 -0
  203. package/dist/esm/providers/llm/adapters/openai-compatible.js.map +7 -0
  204. package/dist/esm/providers/llm/adapters/openrouter/index.js +2 -0
  205. package/dist/esm/providers/llm/adapters/openrouter/index.js.map +7 -0
  206. package/dist/esm/providers/llm/adapters/openrouter/openrouter.js +2 -0
  207. package/dist/esm/providers/llm/adapters/openrouter/openrouter.js.map +7 -0
  208. package/dist/esm/providers/llm/index.js +1 -1
  209. package/dist/esm/providers/llm/index.js.map +3 -3
  210. package/dist/esm/providers/llm/toolmode/index.js +2 -0
  211. package/dist/esm/providers/llm/toolmode/index.js.map +7 -0
  212. package/dist/esm/providers/llm/toolmode/toolmode.js +2 -0
  213. package/dist/esm/providers/llm/toolmode/toolmode.js.map +7 -0
  214. package/dist/esm/providers/llm/types.js +1 -0
  215. package/dist/esm/providers/llm/types.js.map +4 -4
  216. package/dist/esm/providers/stt/adapters/deepgram/deepgram.js +1 -1
  217. package/dist/esm/providers/stt/adapters/deepgram/deepgram.js.map +3 -3
  218. package/dist/esm/providers/stt/adapters/index.js +1 -1
  219. package/dist/esm/providers/stt/adapters/index.js.map +3 -3
  220. package/dist/esm/providers/stt/adapters/openrouter/index.js +2 -0
  221. package/dist/esm/providers/stt/adapters/openrouter/index.js.map +7 -0
  222. package/dist/esm/providers/stt/adapters/openrouter/openrouter.js +2 -0
  223. package/dist/esm/providers/stt/adapters/openrouter/openrouter.js.map +7 -0
  224. package/dist/esm/providers/tts/adapters/index.js +1 -1
  225. package/dist/esm/providers/tts/adapters/index.js.map +3 -3
  226. package/dist/esm/providers/tts/adapters/kokoro/kokoro.js +4 -1
  227. package/dist/esm/providers/tts/adapters/kokoro/kokoro.js.map +3 -3
  228. package/dist/esm/providers/tts/adapters/openrouter/index.js +2 -0
  229. package/dist/esm/providers/tts/adapters/openrouter/index.js.map +7 -0
  230. package/dist/esm/providers/tts/adapters/openrouter/openrouter.js +2 -0
  231. package/dist/esm/providers/tts/adapters/openrouter/openrouter.js.map +7 -0
  232. package/dist/esm/transport/streamobject/field-stream/field-stream.js +2 -0
  233. package/dist/esm/transport/streamobject/field-stream/field-stream.js.map +7 -0
  234. package/dist/esm/transport/streamobject/field-stream/index.js +2 -0
  235. package/dist/esm/transport/streamobject/field-stream/index.js.map +7 -0
  236. package/dist/esm/transport/streamobject/index.js +2 -0
  237. package/dist/esm/transport/streamobject/index.js.map +7 -0
  238. package/dist/esm/transport/streamobject/json-adapter/index.js +2 -0
  239. package/dist/esm/transport/streamobject/json-adapter/index.js.map +7 -0
  240. package/dist/esm/transport/streamobject/json-adapter/json-adapter.js +4 -0
  241. package/dist/esm/transport/streamobject/json-adapter/json-adapter.js.map +7 -0
  242. package/dist/esm/transport/streamobject/reference/index.js +2 -0
  243. package/dist/esm/transport/streamobject/reference/index.js.map +7 -0
  244. package/dist/esm/transport/streamobject/reference/reference.js +2 -0
  245. package/dist/esm/transport/streamobject/reference/reference.js.map +7 -0
  246. package/dist/esm/transport/streamobject/stream-object/index.js +2 -0
  247. package/dist/esm/transport/streamobject/stream-object/index.js.map +7 -0
  248. package/dist/esm/transport/streamobject/stream-object/stream-object.js +2 -0
  249. package/dist/esm/transport/streamobject/stream-object/stream-object.js.map +7 -0
  250. package/dist/types/agents/agent.d.ts +3 -0
  251. package/dist/types/agents/tools/tools.d.ts +28 -6
  252. package/dist/types/conversations/conversation/conversation.d.ts +85 -6
  253. package/dist/types/conversations/conversations.d.ts +11 -1
  254. package/dist/types/conversations/index.d.ts +2 -1
  255. package/dist/types/conversations/orchestration/coordination/coordination.d.ts +192 -0
  256. package/dist/types/conversations/orchestration/coordination/index.d.ts +2 -0
  257. package/dist/types/conversations/orchestration/orchestrator/coordination-runner/coordination-runner.d.ts +108 -0
  258. package/dist/types/conversations/orchestration/orchestrator/coordination-runner/index.d.ts +2 -0
  259. package/dist/types/conversations/orchestration/orchestrator/generation/generation.d.ts +43 -0
  260. package/dist/types/conversations/orchestration/orchestrator/generation/index.d.ts +2 -0
  261. package/dist/types/conversations/orchestration/orchestrator/history/history.d.ts +62 -0
  262. package/dist/types/conversations/orchestration/orchestrator/history/index.d.ts +1 -0
  263. package/dist/types/conversations/orchestration/orchestrator/index.d.ts +10 -0
  264. package/dist/types/conversations/orchestration/orchestrator/orchestrator.d.ts +45 -27
  265. package/dist/types/conversations/orchestration/orchestrator/routing/index.d.ts +1 -0
  266. package/dist/types/conversations/orchestration/orchestrator/routing/routing.d.ts +19 -0
  267. package/dist/types/conversations/orchestration/orchestrator/speech/index.d.ts +2 -0
  268. package/dist/types/conversations/orchestration/orchestrator/speech/speech.d.ts +49 -0
  269. package/dist/types/conversations/orchestration/orchestrator/tools/index.d.ts +2 -0
  270. package/dist/types/conversations/orchestration/orchestrator/tools/tools.d.ts +31 -0
  271. package/dist/types/conversations/orchestration/test-harness.d.ts +96 -0
  272. package/dist/types/conversations/orchestration/text-chunker/index.d.ts +1 -0
  273. package/dist/types/conversations/orchestration/text-chunker/text-chunker.d.ts +39 -0
  274. package/dist/types/conversations/stream/conversation-stream.d.ts +42 -0
  275. package/dist/types/conversations/stream/index.d.ts +1 -0
  276. package/dist/types/conversations/types.d.ts +32 -0
  277. package/dist/types/index.d.ts +5 -38
  278. package/dist/types/pipeflow/index.d.ts +2 -0
  279. package/dist/types/pipeflow/pipeflow.d.ts +35 -0
  280. package/dist/types/providers/index.d.ts +1 -1
  281. package/dist/types/providers/llm/adapters/claude/claude.d.ts +45 -0
  282. package/dist/types/providers/llm/adapters/claude/index.d.ts +2 -0
  283. package/dist/types/providers/llm/adapters/deepseek/deepseek.d.ts +23 -2
  284. package/dist/types/providers/llm/adapters/index.d.ts +3 -0
  285. package/dist/types/providers/llm/adapters/openai/index.d.ts +2 -0
  286. package/dist/types/providers/llm/adapters/openai/openai.d.ts +45 -0
  287. package/dist/types/providers/llm/adapters/openai-compatible.d.ts +44 -0
  288. package/dist/types/providers/llm/adapters/openrouter/index.d.ts +2 -0
  289. package/dist/types/providers/llm/adapters/openrouter/openrouter.d.ts +60 -0
  290. package/dist/types/providers/llm/index.d.ts +5 -2
  291. package/dist/types/providers/llm/toolmode/index.d.ts +2 -0
  292. package/dist/types/providers/llm/toolmode/toolmode.d.ts +99 -0
  293. package/dist/types/providers/llm/types.d.ts +62 -0
  294. package/dist/types/providers/stt/adapters/deepgram/deepgram.d.ts +4 -1
  295. package/dist/types/providers/stt/adapters/index.d.ts +1 -0
  296. package/dist/types/providers/stt/adapters/openrouter/index.d.ts +2 -0
  297. package/dist/types/providers/stt/adapters/openrouter/openrouter.d.ts +94 -0
  298. package/dist/types/providers/tts/adapters/index.d.ts +1 -0
  299. package/dist/types/providers/tts/adapters/kokoro/kokoro.d.ts +17 -2
  300. package/dist/types/providers/tts/adapters/openrouter/index.d.ts +2 -0
  301. package/dist/types/providers/tts/adapters/openrouter/openrouter.d.ts +45 -0
  302. package/dist/types/transport/streamobject/field-stream/field-stream.d.ts +85 -0
  303. package/dist/types/transport/streamobject/field-stream/index.d.ts +2 -0
  304. package/dist/types/transport/streamobject/index.d.ts +8 -0
  305. package/dist/types/transport/streamobject/json-adapter/index.d.ts +2 -0
  306. package/dist/types/transport/streamobject/json-adapter/json-adapter.d.ts +65 -0
  307. package/dist/types/transport/streamobject/reference/index.d.ts +2 -0
  308. package/dist/types/transport/streamobject/reference/reference.d.ts +127 -0
  309. package/dist/types/transport/streamobject/stream-object/index.d.ts +2 -0
  310. package/dist/types/transport/streamobject/stream-object/stream-object.d.ts +31 -0
  311. package/package.json +23 -2
@@ -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 /** 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\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 onDelta,\n resolveToolCalls,\n } = request;\n\n let text = \"\";\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 for await (const event of llm.stream({ messages, 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 // 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 { text, status: \"error\", error };\n }\n }\n}\n"],
5
+ "mappings": "4dAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,sBAAAE,IAAA,eAAAC,EAAAH,GAiDO,MAAMI,CAAiB,CAjD9B,MAiD8B,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,QAAAC,EACA,iBAAAC,CACF,EAAIV,EAEJ,IAAIW,EAAO,GAEX,GAAI,CACF,QAASC,EAAY,EAAGA,EAAYL,EAAmBK,IAAa,CAClE,GAAI,CAACJ,EAAU,EAAG,MAAO,CAAE,KAAAG,EAAM,OAAQ,aAAc,EAEvD,MAAME,EAA2B,CAAC,EAClC,IAAIC,EAAO,GAEX,gBAAiBC,KAASb,EAAI,OAAO,CAAE,SAAAC,EAAU,MAAAC,EAAO,YAAAC,EAAa,UAAAC,CAAU,CAAC,EAAG,CACjF,GAAI,CAACE,EAAU,EAAG,MAAO,CAAE,KAAAG,EAAM,OAAQ,aAAc,EACvD,OAAQI,EAAM,KAAM,CAClB,IAAK,QAAS,CACZ,MAAMC,EAASL,EACfA,GAAQI,EAAM,QACVA,EAAM,QAAQ,OAAS,GAAGN,IAAUM,EAAM,QAASC,CAAM,EAC7D,KACF,CACA,IAAK,YACHH,EAAU,KAAK,CAAE,GAAIE,EAAM,GAAI,KAAMA,EAAM,KAAM,UAAWA,EAAM,SAAU,CAAC,EAC7E,MACF,IAAK,QACH,MAAMA,EAAM,MACd,IAAK,OACHD,EAAO,EACX,CACF,CAEA,GAAI,CAACN,EAAU,EAAG,MAAO,CAAE,KAAAG,EAAM,OAAQ,aAAc,EAEvD,GAAIE,EAAU,OAAS,EAAG,CAGxBV,EAAS,KAAK,CAAE,KAAM,YAAa,KAAMF,EAAW,QAASU,EAAM,UAAAE,CAAU,CAAC,EAC9E,MAAMI,EAAU,MAAMP,EAAiBG,CAAS,EAChD,GAAI,CAACL,EAAU,EAAG,MAAO,CAAE,KAAAG,EAAM,OAAQ,aAAc,EACvD,UAAWO,KAAUD,EACnBd,EAAS,KAAK,CACZ,KAAM,OACN,WAAYe,EAAO,GACnB,KAAMA,EAAO,KACb,QAAS,KAAK,UACZA,EAAO,QAAU,OAAY,CAAE,MAAOA,EAAO,KAAM,EAAIA,EAAO,MAChE,CACF,CAAC,EAEH,QACF,CAEA,GAAIJ,EAAM,KACZ,CAEA,MAAO,CAAE,KAAAH,EAAM,OAAQ,MAAO,CAChC,OAASQ,EAAO,CACd,MAAO,CAAE,KAAAR,EAAM,OAAQ,QAAS,MAAAQ,CAAM,CACxC,CACF,CACF",
6
+ "names": ["generation_exports", "__export", "GenerationRunner", "__toCommonJS", "GenerationRunner", "__name", "request", "agentName", "llm", "messages", "tools", "temperature", "maxTokens", "maxToolIterations", "isCurrent", "onDelta", "resolveToolCalls", "text", "iteration", "toolCalls", "done", "event", "before", "results", "result", "error"]
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";var r=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var G=Object.getOwnPropertyNames;var m=Object.prototype.hasOwnProperty;var p=(n,e)=>{for(var o in e)r(n,o,{get:e[o],enumerable:!0})},f=(n,e,o,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of G(e))!m.call(n,t)&&t!==o&&r(n,t,{get:()=>e[t],enumerable:!(a=u(e,t))||a.enumerable});return n};var s=n=>f(r({},"__esModule",{value:!0}),n);var x={};p(x,{GenerationRunner:()=>i.GenerationRunner});module.exports=s(x);var i=require("./generation.js");
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": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,0DAAAE,EAAAF,GAAA,IAAAG,EAAiC",
6
+ "names": ["generation_exports", "__export", "__toCommonJS", "import_generation"]
7
+ }
@@ -0,0 +1,4 @@
1
+ "use strict";var u=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var f=Object.getOwnPropertyNames;var h=Object.prototype.hasOwnProperty;var o=(s,t)=>u(s,"name",{value:t,configurable:!0});var y=(s,t)=>{for(var n in t)u(s,n,{get:t[n],enumerable:!0})},M=(s,t,n,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of f(t))!h.call(s,r)&&r!==n&&u(s,r,{get:()=>t[r],enumerable:!(a=m(t,r))||a.enumerable});return s};var $=s=>M(u({},"__esModule",{value:!0}),s);var w={};y(w,{ConversationHistory:()=>v,formatTimeContext:()=>d,formatTurnContext:()=>l,windowHistory:()=>g});module.exports=$(w);const x=["jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"];function d(s=new Date){const t=s.getDate(),n=x[s.getMonth()],a=s.getFullYear(),r=String(s.getHours()).padStart(2,"0"),e=String(s.getMinutes()).padStart(2,"0");return`Now it is ${t} ${n} ${a}, ${r}:${e}.`}o(d,"formatTimeContext");function l(s,t,n=new Date){const a=o(i=>{const c=i.aliases[0]??i.userId,p=i.aliases.length>0?` (aliases: ${i.aliases.join(", ")})`:"";return`${c} with user id ${i.userId}${p}`},"describe"),r=t.filter(i=>i.userId!==s.userId),e=r.length>0?` The other participants are ${r.map(a).join(", ")}.`:"";return`
2
+
3
+ Additional context: ${d(n)} The current user is ${a(s)}.${e}`}o(l,"formatTurnContext");function g(s,{maxTurns:t,maxChars:n}){if(s.length===0)return s;let a=0,r=0;for(let i=s.length-1;i>=0;i--)if(s[i].role==="user"&&(r++,r===t)){a=i;break}let e=a>0?s.slice(a):s;if(n>0)for(;e.length>1&&e.reduce((i,c)=>i+c.content.length,0)>n;)e=e.slice(1);return e}o(g,"windowHistory");class v{static{o(this,"ConversationHistory")}messages=[];turnMessage(t,n){const a=n.state.participants.get(t.participantId),r=[...n.state.participants.values()],e=a?l(a,r,new Date(t.startedAt)):"";return`${t.participantName}: ${t.text}${e}`}addUserTurn(t,n){this.messages.push({role:"user",content:this.turnMessage(t,n)})}addAssistant(t,n){this.messages.push({role:"assistant",name:t,content:n})}rehydrate(t,n,a){const r=[...t.map(e=>({at:e.startedAt,kind:"turn",turn:e})),...n.filter(e=>e.status==="completed"&&e.kind!=="sub").map(e=>({at:e.startedAt,kind:"generation",agentName:e.agentName,text:e.text}))].sort((e,i)=>e.at-i.at);for(const e of r)e.kind==="turn"?this.addUserTurn(e.turn,a):this.addAssistant(e.agentName,e.text)}get all(){return this.messages}windowed(t){return t===!1?this.messages:g(this.messages,t)}}
4
+ //# sourceMappingURL=history.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/conversations/orchestration/orchestrator/history/history.ts"],
4
+ "sourcesContent": ["import type { Conversation } from \"../../../conversation/conversation\";\nimport type { Generation, Participant, Turn } from \"../../../types\";\nimport type { LLMMessage } from \"../../../../providers/llm/types\";\n\nconst MONTHS = [\n \"jan\",\n \"feb\",\n \"mar\",\n \"apr\",\n \"may\",\n \"jun\",\n \"jul\",\n \"aug\",\n \"sep\",\n \"oct\",\n \"nov\",\n \"dec\",\n];\n\n/**\n * A human-readable \"now\" stamp appended to dispatched prompts so\n * time-sensitive tasks (flights, meetings, deadlines) have temporal context.\n */\nexport function formatTimeContext(date = new Date()): string {\n const day = date.getDate();\n const month = MONTHS[date.getMonth()]!;\n const year = date.getFullYear();\n const hours = String(date.getHours()).padStart(2, \"0\");\n const minutes = String(date.getMinutes()).padStart(2, \"0\");\n return `Now it is ${day} ${month} ${year}, ${hours}:${minutes}.`;\n}\n\n/**\n * A short context suffix appended automatically to every user turn, so the\n * model knows the time and who is speaking (and who else is in the\n * conversation) \u2014 e.g. \"enhance the message I just sent\" resolves to a real\n * user id. Applied once, when the turn enters history; every generation path\n * (direct, coordination, delegated) seeds from that history.\n */\nexport function formatTurnContext(\n participant: Participant,\n participants: readonly Participant[],\n date = new Date(),\n): string {\n const describe = (p: Participant): string => {\n const displayName = p.aliases[0] ?? p.userId;\n const aliases = p.aliases.length > 0 ? ` (aliases: ${p.aliases.join(\", \")})` : \"\";\n return `${displayName} with user id ${p.userId}${aliases}`;\n };\n const others = participants.filter((p) => p.userId !== participant.userId);\n const othersLine =\n others.length > 0\n ? ` The other participants are ${others.map(describe).join(\", \")}.`\n : \"\";\n return `\\n\\nAdditional context: ${formatTimeContext(date)} The current user is ${describe(participant)}.${othersLine}`;\n}\n\n/** How much conversational history an LLM request may carry. */\nexport interface HistoryWindow {\n /** Keep at most this many user turns (the current turn is always kept). */\n maxTurns: number;\n /** Drop oldest whole messages until the window fits this many characters. */\n maxChars: number;\n}\n\n/**\n * Bounds conversation history for an LLM request: keep the most recent\n * `maxTurns` user turns (plus anything after them), then drop oldest whole\n * messages until the window fits `maxChars`. The current turn is the last\n * user message and always survives. Provider TTFT grows with input size, so\n * a bounded window keeps requests in the fast regime.\n */\nexport function windowHistory(\n history: LLMMessage[],\n { maxTurns, maxChars }: HistoryWindow,\n): LLMMessage[] {\n if (history.length === 0) return history;\n\n let start = 0;\n let userSeen = 0;\n for (let i = history.length - 1; i >= 0; i--) {\n if (history[i]!.role === \"user\") {\n userSeen++;\n if (userSeen === maxTurns) {\n start = i;\n break;\n }\n }\n }\n let windowed = start > 0 ? history.slice(start) : history;\n\n if (maxChars > 0) {\n while (\n windowed.length > 1 &&\n windowed.reduce((sum, message) => sum + message.content.length, 0) > maxChars\n ) {\n windowed = windowed.slice(1);\n }\n }\n return windowed;\n}\n\n/**\n * The conversation's LLM message log: every user turn and agent reply, plus\n * the turn-context formatting and windowing applied when a request is built.\n * The orchestrator's `Conversation` remains the source of truth for turns,\n * transcripts, and generations \u2014 this is the derived prompt log only.\n */\nexport class ConversationHistory {\n private readonly messages: LLMMessage[] = [];\n\n /**\n * The user-message form of a turn: display name, text, and the automatic\n * context suffix (time + speaker + roster) baked in at history time.\n */\n turnMessage(turn: Turn, conversation: Conversation): string {\n const participant = conversation.state.participants.get(turn.participantId);\n const participants = [...conversation.state.participants.values()];\n const context = participant\n ? formatTurnContext(participant, participants, new Date(turn.startedAt))\n : \"\";\n return `${turn.participantName}: ${turn.text}${context}`;\n }\n\n /** Append a participant turn as a user message. */\n addUserTurn(turn: Turn, conversation: Conversation): void {\n this.messages.push({ role: \"user\", content: this.turnMessage(turn, conversation) });\n }\n\n /** Append an agent reply as an assistant message. */\n addAssistant(agentName: string, text: string): void {\n this.messages.push({ role: \"assistant\", name: agentName, content: text });\n }\n\n /**\n * Rehydrate from persisted turns and completed top-level generations.\n * Sub-generations are summarized inside the coordinator's own answer, so\n * only top-level responses rehydrate into history.\n */\n rehydrate(\n turns: readonly Turn[],\n generations: readonly Generation[],\n conversation: Conversation,\n ): void {\n const entries: Array<\n | { at: number; kind: \"turn\"; turn: Turn }\n | { at: number; kind: \"generation\"; agentName: string; text: string }\n > = [\n ...turns.map((turn) => ({ at: turn.startedAt, kind: \"turn\" as const, turn })),\n ...generations\n .filter(\n (generation) =>\n generation.status === \"completed\" && generation.kind !== \"sub\",\n )\n .map((generation) => ({\n at: generation.startedAt,\n kind: \"generation\" as const,\n agentName: generation.agentName,\n text: generation.text,\n })),\n ].sort((a, b) => a.at - b.at);\n\n for (const entry of entries) {\n if (entry.kind === \"turn\") {\n this.addUserTurn(entry.turn, conversation);\n } else {\n this.addAssistant(entry.agentName, entry.text);\n }\n }\n }\n\n /** The full message log. */\n get all(): readonly LLMMessage[] {\n return this.messages;\n }\n\n /**\n * The message log bounded for an LLM request: the full log when `window`\n * is `false`, otherwise the bounded window.\n */\n windowed(window: HistoryWindow | false): LLMMessage[] {\n return window === false ? this.messages : windowHistory(this.messages, window);\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["history_exports", "__export", "ConversationHistory", "formatTimeContext", "formatTurnContext", "windowHistory", "__toCommonJS", "MONTHS", "formatTimeContext", "date", "day", "month", "year", "hours", "minutes", "__name", "formatTurnContext", "participant", "participants", "describe", "p", "displayName", "aliases", "others", "othersLine", "windowHistory", "history", "maxTurns", "maxChars", "start", "userSeen", "windowed", "sum", "message", "ConversationHistory", "turn", "conversation", "context", "agentName", "text", "turns", "generations", "entries", "generation", "a", "b", "entry", "window"]
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";var e=Object.defineProperty;var s=Object.getOwnPropertyDescriptor;var y=Object.getOwnPropertyNames;var a=Object.prototype.hasOwnProperty;var f=(r,o)=>{for(var n in o)e(r,n,{get:o[n],enumerable:!0})},w=(r,o,n,m)=>{if(o&&typeof o=="object"||typeof o=="function")for(let i of y(o))!a.call(r,i)&&i!==n&&e(r,i,{get:()=>o[i],enumerable:!(m=s(o,i))||m.enumerable});return r};var x=r=>w(e({},"__esModule",{value:!0}),r);var C={};f(C,{ConversationHistory:()=>t.ConversationHistory,formatTimeContext:()=>t.formatTimeContext,formatTurnContext:()=>t.formatTurnContext,windowHistory:()=>t.windowHistory});module.exports=x(C);var t=require("./history.js");
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/conversations/orchestration/orchestrator/history/index.ts"],
4
+ "sourcesContent": ["export {\n ConversationHistory,\n formatTimeContext,\n formatTurnContext,\n windowHistory,\n type HistoryWindow,\n} from \"./history\";\n"],
5
+ "mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,sLAAAE,EAAAF,GAAA,IAAAG,EAMO",
6
+ "names": ["history_exports", "__export", "__toCommonJS", "import_history"]
7
+ }
@@ -1,2 +1,2 @@
1
- "use strict";var p=Object.defineProperty;var c=Object.getOwnPropertyDescriptor;var h=Object.getOwnPropertyNames;var O=Object.prototype.hasOwnProperty;var f=(t,r)=>{for(var e in r)p(t,e,{get:r[e],enumerable:!0})},m=(t,r,e,s)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of h(r))!O.call(t,o)&&o!==e&&p(t,o,{get:()=>r[o],enumerable:!(s=c(r,o))||s.enumerable});return t};var x=t=>m(p({},"__esModule",{value:!0}),t);var i={};f(i,{Orchestrator:()=>a.Orchestrator});module.exports=x(i);var a=require("./orchestrator.js");
1
+ "use strict";var p=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var y=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var u=(t,o)=>{for(var i in o)p(t,i,{get:o[i],enumerable:!0})},C=(t,o,i,a)=>{if(o&&typeof o=="object"||typeof o=="function")for(let n of y(o))!c.call(t,n)&&n!==i&&p(t,n,{get:()=>o[n],enumerable:!(a=l(o,n))||a.enumerable});return t};var h=t=>C(p({},"__esModule",{value:!0}),t);var O={};u(O,{ConversationHistory:()=>e.ConversationHistory,CoordinationRunner:()=>x.CoordinationRunner,GenerationRunner:()=>s.GenerationRunner,Orchestrator:()=>m.Orchestrator,SpeechPipeline:()=>f.SpeechPipeline,ToolCallManager:()=>d.ToolCallManager,buildUnderstandPrompt:()=>r.buildUnderstandPrompt,findAddressedAgent:()=>r.findAddressedAgent,findAgentByName:()=>r.findAgentByName,formatTimeContext:()=>e.formatTimeContext,formatTurnContext:()=>e.formatTurnContext,pickAgent:()=>r.pickAgent,windowHistory:()=>e.windowHistory});module.exports=h(O);var m=require("./orchestrator.js"),e=require("./history.js"),r=require("./routing.js"),s=require("./generation.js"),f=require("./speech.js"),d=require("./tools.js"),x=require("./coordination-runner.js");
2
2
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/conversations/orchestration/orchestrator/index.ts"],
4
- "sourcesContent": ["export { Orchestrator } from \"./orchestrator\";\nexport type { OrchestratorOptions } from \"./orchestrator\";\n"],
5
- "mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,kDAAAE,EAAAF,GAAA,IAAAG,EAA6B",
6
- "names": ["orchestrator_exports", "__export", "__toCommonJS", "import_orchestrator"]
4
+ "sourcesContent": ["export { Orchestrator } from \"./orchestrator\";\nexport type { OrchestratorOptions } from \"./orchestrator\";\n\n// Extracted execution domains. The orchestrator composes these; re-exporting\n// them keeps the folder's public surface under one roof.\nexport {\n ConversationHistory,\n formatTimeContext,\n formatTurnContext,\n windowHistory,\n type HistoryWindow,\n} from \"./history\";\nexport { buildUnderstandPrompt, findAddressedAgent, findAgentByName, pickAgent } from \"./routing\";\nexport { GenerationRunner } from \"./generation\";\nexport type { GenerationOutcome, GenerationRequest, GenerationStatus } from \"./generation\";\nexport { SpeechPipeline } from \"./speech\";\nexport type { SpeechPipelineOptions } from \"./speech\";\nexport { ToolCallManager } from \"./tools\";\nexport type { ResolvedToolCall } from \"./tools\";\nexport { CoordinationRunner } from \"./coordination-runner\";\nexport type { CoordinationRunnerOptions } from \"./coordination-runner\";\n"],
5
+ "mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,khBAAAE,EAAAF,GAAA,IAAAG,EAA6B,0BAK7BC,EAMO,qBACPC,EAAsF,qBACtFC,EAAiC,wBAEjCC,EAA+B,oBAE/BC,EAAgC,mBAEhCC,EAAmC",
6
+ "names": ["orchestrator_exports", "__export", "__toCommonJS", "import_orchestrator", "import_history", "import_routing", "import_generation", "import_speech", "import_tools", "import_coordination_runner"]
7
7
  }
@@ -1,3 +1,2 @@
1
- "use strict";var p=Object.defineProperty;var v=Object.getOwnPropertyDescriptor;var f=Object.getOwnPropertyNames;var g=Object.prototype.hasOwnProperty;var m=(a,t)=>p(a,"name",{value:t,configurable:!0});var T=(a,t)=>{for(var e in t)p(a,e,{get:t[e],enumerable:!0})},y=(a,t,e,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of f(t))!g.call(a,s)&&s!==e&&p(a,s,{get:()=>t[s],enumerable:!(r=v(t,s))||r.enumerable});return a};var w=a=>y(p({},"__esModule",{value:!0}),a);var b={};T(b,{Orchestrator:()=>S});module.exports=w(b);class S{static{m(this,"Orchestrator")}conversation;agent;llm;stt;tts;persistence;toolTimeoutMs;maxToolIterations;temperature;maxTokens;started=!1;generating=!1;epoch=0;unsubscribers=[];sttSessions=new Map;history=[];toolWaiters=new Map;generationChain=Promise.resolve();speechChain=Promise.resolve();speechBuffer="";pendingTurns=0;pendingGenerations=0;audioSequence=0;turnSequence=0;constructor(t){const e=t.llm??t.agent?.llm;if(!t.stt)throw new Error("Orchestrator requires an STT provider");if(t.agent&&!e)throw new Error("Orchestrator requires an LLM when an agent is attached: pass one explicitly or configure the agent with one");if(t.agent&&!t.tts)throw new Error("Orchestrator requires a TTS provider when an agent is attached");this.conversation=t.conversation,this.agent=t.agent,this.llm=e,this.stt=t.stt,this.tts=t.tts,this.persistence=t.persistence,this.toolTimeoutMs=t.toolTimeoutMs??3e4,this.maxToolIterations=t.maxToolIterations??10,this.temperature=t.temperature,this.maxTokens=t.maxTokens}async start(){if(!this.started){if(this.started=!0,this.persistence){const[t,e]=await Promise.all([this.persistence.listTurns(this.conversation.id),this.persistence.listGenerations(this.conversation.id)]),r=[...t.map(s=>({at:s.startedAt,kind:"turn",turn:s})),...e.filter(s=>s.status==="completed").map(s=>({at:s.startedAt,kind:"generation",text:s.text}))].sort((s,i)=>s.at-i.at);for(const s of r)s.kind==="turn"?this.history.push({role:"user",content:`${s.turn.participantName}: ${s.turn.text}`}):this.history.push({role:"assistant",content:s.text})}this.unsubscribers.push(this.conversation.on("stop",()=>{this.stop()}),this.conversation.on("audio-in",t=>this.onAudioIn(t)),this.conversation.on("interrupt",()=>this.onInterrupt()),this.conversation.on("tool-call-result",t=>this.onToolCallResult(t.result)))}}async stop(){if(!this.started)return;this.started=!1,this.epoch++,this.llm?.stop(),this.tts?.stop(),this.cancelToolWaiters("conversation stopped"),this.speechBuffer="";for(const e of this.unsubscribers)e();this.unsubscribers.length=0;const t=[...this.sttSessions.values()];this.sttSessions.clear();for(const{session:e}of t)await e.end().catch(()=>{})}async whenIdle(){for(;;){for(;this.pendingTurns>0||this.pendingGenerations>0||this.generating;)await Bun.sleep(1);if(await Promise.resolve(),this.pendingTurns===0&&this.pendingGenerations===0&&!this.generating)return}}onAudioIn(t){let e=this.sttSessions.get(t.userId);if(!e){const r=this.stt.start({});r.on("partial",s=>this.onPartial(t.userId,s)),r.on("final",s=>this.onFinal(t.userId,s)),r.on("error",s=>this.onProviderError(s)),e={session:r,turnStartedAt:null},this.sttSessions.set(t.userId,e)}e.turnStartedAt===null&&(e.turnStartedAt=Date.now()),e.session.write(t.audio.data),this.pendingGenerations>0&&this.conversation.interrupt()}onPartial(t,e){const r=e.trim();r&&this.conversation.emit("partial-transcript",{conversationId:this.conversation.id,userId:t,text:r})}onFinal(t,e){const r=e.trim();if(!r)return;const s=this.conversation.state.participants.get(t);if(!s)return;const i=this.sttSessions.get(t),n=i?.turnStartedAt??Date.now();i&&(i.turnStartedAt=null);const o={id:crypto.randomUUID(),conversationId:this.conversation.id,participantId:t,participantName:s.aliases[0]??t,text:r,sequence:this.turnSequence++,startedAt:n,endedAt:Date.now()};this.pendingTurns++,this.processTurn(o)}async processTurn(t){try{await this.conversation.pushTurn(t),await this.conversation.pushTranscript({speaker:t.participantName,speakerKind:"participant",text:t.text}),this.history.push({role:"user",content:`${t.participantName}: ${t.text}`}),this.agent&&this.queueGeneration()}finally{this.pendingTurns--}}onInterrupt(){this.epoch++,this.llm?.stop(),this.tts?.stop(),this.cancelToolWaiters("interrupted"),this.speechBuffer=""}onToolCallResult(t){const e=this.toolWaiters.get(t.id);e&&(this.toolWaiters.delete(t.id),e(t))}onProviderError(t){this.conversation.emit("error",{conversationId:this.conversation.id,error:t})}queueGeneration(){this.pendingGenerations++;const t=this.epoch;this.generationChain=this.generationChain.then(async()=>{if(this.epoch!==t){this.pendingGenerations--;return}try{await this.generate()}finally{this.pendingGenerations--}})}async generate(){const{agent:t,llm:e,tts:r}=this;if(!(!t||!e||!r)){this.generating=!0;try{await this.runGeneration(this.epoch,t,e,r)}finally{this.generating=!1}}}async runGeneration(t,e,r,s){await this.conversation.pushGeneration({id:crypto.randomUUID(),conversationId:this.conversation.id,agentName:e.name,text:"",status:"streaming",startedAt:Date.now()});const i=e.tools.map(h=>({name:h.name,description:h.description,parameters:h.parameters??{type:"object",properties:{}}})),n=[];e.context&&n.push({role:"system",content:e.context}),n.push(...this.history);let o="";try{for(let h=0;h<this.maxToolIterations;h++){if(this.epoch!==t)return;const u=[];let d=!1;for await(const c of r.stream({messages:n,tools:i,temperature:this.temperature,maxTokens:this.maxTokens})){if(this.epoch!==t)return;switch(c.type){case"delta":o+=c.content,this.feedDelta(c.content);break;case"tool_call":u.push({id:c.id,name:c.name,arguments:c.arguments});break;case"error":throw c.error;case"done":d=!0}}if(this.epoch!==t)return;if(u.length>0){this.flushSpeech(),n.push({role:"assistant",content:o,toolCalls:u});const c=await this.resolveToolCalls(u,t);if(this.epoch!==t)return;for(const l of c)n.push({role:"tool",toolCallId:l.id,name:l.name,content:JSON.stringify(l.error!==void 0?{error:l.error}:l.result)});continue}if(d)break}if(this.epoch!==t||(this.flushSpeech(),await this.speechChain,this.epoch!==t))return;await this.conversation.completeGeneration(o),await this.conversation.pushTranscript({speaker:e.name,speakerKind:"agent",text:o}),this.history.push({role:"assistant",content:o})}catch(h){if(this.epoch!==t)return;this.conversation.emit("error",{conversationId:this.conversation.id,error:h instanceof Error?h:new Error(String(h))}),await this.conversation.completeGeneration(o),o&&(await this.conversation.pushTranscript({speaker:e.name,speakerKind:"agent",text:o}),this.history.push({role:"assistant",content:o}))}}async resolveToolCalls(t,e){const r=t.map(i=>this.waitForToolResult(i.id,e));for(const i of t){let n;try{n=JSON.parse(i.arguments)}catch{n=i.arguments}this.conversation.requestToolCall({id:i.id,name:i.name,arguments:n})}return(await Promise.all(r)).map((i,n)=>{const o=t[n];return{id:i.id,name:o.name,result:"result"in i?i.result:void 0,error:"error"in i?i.error:void 0}})}waitForToolResult(t,e){return new Promise(r=>{const s=setTimeout(()=>{this.toolWaiters.delete(t),r({id:t,error:`Tool call "${t}" timed out`})},this.toolTimeoutMs);this.toolWaiters.set(t,i=>{clearTimeout(s),r(i)})})}cancelToolWaiters(t){for(const[e,r]of[...this.toolWaiters])this.toolWaiters.delete(e),r({id:e,error:t})}feedDelta(t){for(this.speechBuffer+=t;;){let e=-1;for(let s=0;s<this.speechBuffer.length;s++){const i=this.speechBuffer[s];if(i==="."||i==="!"||i==="?"||i===`
2
- `){e=s;break}}if(e<0)break;const r=this.speechBuffer.slice(0,e+1).trim();this.speechBuffer=this.speechBuffer.slice(e+1),r&&this.speak(r)}}flushSpeech(){const t=this.speechBuffer.trim();this.speechBuffer="",t&&this.speak(t)}speak(t){const e=this.tts;if(!e)return;const r=this.epoch;this.speechChain=this.speechChain.then(async()=>{if(!(!this.started||this.epoch!==r))try{for await(const s of e.stream({text:t})){if(!this.started||this.epoch!==r)break;this.conversation.pushAudio({data:s,timestamp:Date.now(),sequence:this.audioSequence++})}}catch(s){if(this.epoch!==r)return;this.conversation.emit("error",{conversationId:this.conversation.id,error:s instanceof Error?s:new Error(String(s))})}})}}
1
+ "use strict";var c=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var T=Object.getOwnPropertyNames;var w=Object.prototype.hasOwnProperty;var o=(r,t)=>c(r,"name",{value:t,configurable:!0});var x=(r,t)=>{for(var e in t)c(r,e,{get:t[e],enumerable:!0})},S=(r,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of T(t))!w.call(r,n)&&n!==e&&c(r,n,{get:()=>t[n],enumerable:!(i=y(t,n))||i.enumerable});return r};var C=r=>S(c({},"__esModule",{value:!0}),r);var A={};x(A,{Orchestrator:()=>I});module.exports=C(A);var u=require("./history/history.js"),p=require("./routing/routing.js"),m=require("./generation/generation.js"),v=require("./speech/speech.js"),g=require("./tools/tools.js"),f=require("./coordination-runner/coordination-runner.js");class I{static{o(this,"Orchestrator")}conversation;agents;llm;stt;tts;persistence;maxToolIterations;historyWindow;temperature;maxTokens;history;speech;tools;generation;coordination;started=!1;generating=!1;epoch=0;generationChain=Promise.resolve();unsubscribers=[];sttSessions=new Map;pendingTurns=0;pendingGenerations=0;turnSequence=0;constructor(t){const e=t.agents??[],i=t.llm??e[0]?.llm;if(e.length>0&&!i)throw new Error("Orchestrator requires an LLM when agents are attached: pass one explicitly or configure an agent with one");this.conversation=t.conversation,this.agents=e,this.llm=i,this.stt=t.stt,this.tts=t.tts,this.persistence=t.persistence,this.maxToolIterations=t.maxToolIterations??10,this.historyWindow=t.historyWindow??{maxTurns:5,maxChars:4e3},this.temperature=t.temperature,this.maxTokens=t.maxTokens,this.history=new u.ConversationHistory,this.speech=new v.SpeechPipeline({tts:this.tts,conversation:this.conversation,isCurrent:o(n=>this.started&&n===this.epoch,"isCurrent")}),this.tools=new g.ToolCallManager(this.conversation,t.toolTimeoutMs??3e4),this.generation=new m.GenerationRunner,this.coordination=new f.CoordinationRunner({conversation:this.conversation,agents:o(()=>this.agents,"agents"),llm:o(()=>this.llm,"llm"),history:this.history,historyWindow:this.historyWindow,speech:this.speech,generation:this.generation,tools:this.tools,maxCoordinationSteps:t.maxCoordinationSteps??20,maxToolIterations:this.maxToolIterations,temperature:this.temperature,maxTokens:this.maxTokens,currentEpoch:o(()=>this.epoch,"currentEpoch"),isCurrent:o(n=>this.started&&n===this.epoch,"isCurrent")}),this.coordination.register(t.coordinations??{},e)}async start(){if(!this.started){if(this.started=!0,this.persistence){const[t,e]=await Promise.all([this.persistence.listTurns(this.conversation.id),this.persistence.listGenerations(this.conversation.id)]);this.history.rehydrate(t,e,this.conversation)}this.unsubscribers.push(this.conversation.on("stop",()=>{this.stop()}),this.conversation.on("audio-in",t=>this.onAudioIn(t)),this.conversation.on("text-in",({userId:t,text:e})=>this.onFinal(t,e)),this.conversation.on("interrupt",()=>this.onInterrupt()),this.conversation.on("tool-call-result",({result:t})=>this.tools.handleResult(t)))}}async stop(){if(!this.started)return;this.started=!1,this.epoch++,this.coordination.cancel(),this.stopLlms(),this.speech.stop(),this.tools.cancelAll("conversation stopped");for(const e of this.unsubscribers)e();this.unsubscribers.length=0;const t=[...this.sttSessions.values()];this.sttSessions.clear();for(const{session:e}of t)await e.end().catch(()=>{})}async whenIdle(){for(;;){for(;this.pendingTurns>0||this.pendingGenerations>0||this.generating;)await Bun.sleep(1);if(await Promise.resolve(),this.pendingTurns===0&&this.pendingGenerations===0&&!this.generating)return}}onAudioIn(t){if(!this.stt)return;let e=this.sttSessions.get(t.userId);if(!e){const i=this.stt.start({});i.on("partial",n=>this.onPartial(t.userId,n)),i.on("final",n=>this.onFinal(t.userId,n)),i.on("error",n=>this.onProviderError(n)),e={session:i,turnStartedAt:null},this.sttSessions.set(t.userId,e)}if(e.turnStartedAt===null&&(e.turnStartedAt=Date.now()),e.session.write(t.audio.data),this.coordination.hasPending()){this.speech.stop();return}this.pendingGenerations>0&&this.conversation.interrupt()}onPartial(t,e){const i=e.trim();i&&this.conversation.emit("partial-transcript",{conversationId:this.conversation.id,userId:t,text:i})}onFinal(t,e){const i=e.trim();if(!i)return;const n=this.conversation.state.participants.get(t);if(!n)return;const h=this.sttSessions.get(t),l=h?.turnStartedAt??Date.now();h&&(h.turnStartedAt=null);const d={id:crypto.randomUUID(),conversationId:this.conversation.id,participantId:t,participantName:n.aliases[0]??t,text:i,sequence:this.turnSequence++,startedAt:l,endedAt:Date.now()};this.pendingTurns++,this.processTurn(d)}async processTurn(t){try{if(await this.conversation.pushTurn(t),await this.conversation.pushTranscript({speaker:t.participantName,speakerKind:"participant",text:t.text}),this.history.addUserTurn(t,this.conversation),this.agents.length===0)return;if(this.coordination.hasPending()){this.enqueueCoordinationRun(()=>this.coordination.resume(t));return}if(this.agents.length===1||(0,p.findAddressedAgent)(this.agents,t.text)){this.queueGeneration(t);return}this.enqueueCoordinationRun(()=>this.coordination.runDefault(t))}finally{this.pendingTurns--}}onInterrupt(){this.epoch++,this.coordination.cancel(),this.stopLlms(),this.speech.stop(),this.tools.cancelAll("interrupted")}stopLlms(){const t=new Set;this.llm&&t.add(this.llm);for(const e of this.agents)e.llm&&t.add(e.llm);for(const e of t)e.stop()}onProviderError(t){this.conversation.emit("error",{conversationId:this.conversation.id,error:t})}queueGeneration(t){this.pendingGenerations++;const e=this.epoch;this.generationChain=this.generationChain.then(async()=>{if(this.epoch!==e){this.pendingGenerations--;return}try{await this.generate(t)}finally{this.pendingGenerations--}})}async generate(t){if(this.agents.length===0)return;const e=(0,p.pickAgent)(this.agents,t.text);if(!e)return;const i=e.llm??this.llm;if(i){this.generating=!0;try{await this.runGeneration(this.epoch,t,e,i)}finally{this.generating=!1}}}async runGeneration(t,e,i,n){const h=crypto.randomUUID();await this.conversation.pushGeneration({id:h,conversationId:this.conversation.id,agentName:i.name,text:"",status:"streaming",startedAt:Date.now()});const l=i.tools.map(a=>({name:a.name,description:a.description,parameters:a.parameters??{type:"object",properties:{}}})),d=[];i.context&&d.push({role:"system",name:i.name,content:i.context}),d.push(...this.history.windowed(this.historyWindow));const s=await this.generation.run({agentName:i.name,llm:n,messages:d,tools:l,temperature:this.temperature,maxTokens:this.maxTokens,maxToolIterations:this.maxToolIterations,isCurrent:o(()=>this.epoch===t,"isCurrent"),onDelta:o(a=>this.speech.feed(a,t),"onDelta"),resolveToolCalls:o(a=>this.tools.resolveCalls(a),"resolveToolCalls")});if(this.epoch===t&&s.status!=="interrupted"){if(s.status==="error"){this.conversation.emit("error",{conversationId:this.conversation.id,error:s.error instanceof Error?s.error:new Error(String(s.error))}),await this.conversation.completeGeneration(s.text),s.text&&(await this.conversation.pushTranscript({speaker:i.name,speakerKind:"agent",text:s.text}),this.history.addAssistant(i.name,s.text));return}this.speech.flush(t),await this.speech.waitForIdle(),this.epoch===t&&(await this.conversation.completeGeneration(s.text),await this.conversation.pushTranscript({speaker:i.name,speakerKind:"agent",text:s.text}),this.history.addAssistant(i.name,s.text))}}enqueueCoordinationRun(t){this.pendingGenerations++,this.generationChain=this.generationChain.then(async()=>{this.generating=!0;try{await t()}finally{this.generating=!1,this.pendingGenerations--}})}}
3
2
  //# sourceMappingURL=orchestrator.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/conversations/orchestration/orchestrator/orchestrator.ts"],
4
- "sourcesContent": ["import type { Agent } from \"../../../agents/agent\";\nimport type { Conversation } from \"../../conversation/conversation\";\nimport type { Persistence } from \"../../../persistence/persistence\";\nimport type {\n LLM,\n LLMMessage,\n LLMToolCall,\n LLMToolDefinition,\n} from \"../../../providers/llm/types\";\nimport type { STT, STTSession } from \"../../../providers/stt/types\";\nimport type { TTS } from \"../../../providers/tts/types\";\nimport type { AudioChunk, ToolCallResult, Turn, UserId } from \"../../types\";\n\nexport interface OrchestratorOptions {\n conversation: Conversation;\n /**\n * The agent driving the realtime loop. Omit it for transcription-only\n * mode (audio in, turns and transcripts out \u2014 no LLM or TTS required).\n */\n agent?: Agent;\n /** Defaults to the agent's LLM. */\n llm?: LLM;\n stt: STT;\n /** Required when an agent is attached. */\n tts?: TTS;\n /** Used to rehydrate conversation history on start. */\n persistence?: Persistence;\n /** How long to wait for the application to resolve a tool call. */\n toolTimeoutMs?: number;\n /** Safety bound on tool-call round trips per generation. */\n maxToolIterations?: number;\n temperature?: number;\n maxTokens?: number;\n}\n\ninterface SttSessionEntry {\n session: STTSession;\n turnStartedAt: number | null;\n}\n\ninterface ResolvedToolCall {\n id: string;\n name: string;\n result?: unknown;\n error?: string;\n}\n\n/**\n * The realtime conversation state machine.\n *\n * Wires the conversation to the providers:\n *\n * ```text\n * audio-in \u2500\u2500\u25BA STT \u2500\u2500\u25BA turn \u2500\u2500\u25BA LLM \u2500\u2500\u25BA TTS \u2500\u2500\u25BA audio-out\n * \u2502\n * \u2514\u2500\u25BA tool-call \u2500\u2500\u25BA app resolves \u2500\u2500\u25BA resume\n * ```\n *\n * Deltas stream to TTS immediately (so the agent can narrate while a tool\n * runs), tool calls pause the generation until the application resolves\n * them, and interruptions cancel the current generation \u2014 discarding any\n * stale tool results or audio via a generation epoch.\n */\nexport class Orchestrator {\n private readonly conversation: Conversation;\n private readonly agent: Agent | undefined;\n private readonly llm: LLM | undefined;\n private readonly stt: STT;\n private readonly tts: TTS | undefined;\n private readonly persistence: Persistence | undefined;\n private readonly toolTimeoutMs: number;\n private readonly maxToolIterations: number;\n private readonly temperature: number | undefined;\n private readonly maxTokens: number | undefined;\n\n private started = false;\n private generating = false;\n private epoch = 0;\n private readonly unsubscribers: (() => void)[] = [];\n private readonly sttSessions = new Map<UserId, SttSessionEntry>();\n private readonly history: LLMMessage[] = [];\n private readonly toolWaiters = new Map<string, (result: ToolCallResult) => void>();\n private generationChain: Promise<void> = Promise.resolve();\n private speechChain: Promise<void> = Promise.resolve();\n private speechBuffer = \"\";\n private pendingTurns = 0;\n private pendingGenerations = 0;\n private audioSequence = 0;\n private turnSequence = 0;\n\n constructor(options: OrchestratorOptions) {\n const llm = options.llm ?? options.agent?.llm;\n if (!options.stt) {\n throw new Error(\"Orchestrator requires an STT provider\");\n }\n if (options.agent && !llm) {\n throw new Error(\n \"Orchestrator requires an LLM when an agent is attached: \" +\n \"pass one explicitly or configure the agent with one\",\n );\n }\n if (options.agent && !options.tts) {\n throw new Error(\"Orchestrator requires a TTS provider when an agent is attached\");\n }\n this.conversation = options.conversation;\n this.agent = options.agent;\n this.llm = llm;\n this.stt = options.stt;\n this.tts = options.tts;\n this.persistence = options.persistence;\n this.toolTimeoutMs = options.toolTimeoutMs ?? 30_000;\n this.maxToolIterations = options.maxToolIterations ?? 10;\n this.temperature = options.temperature;\n this.maxTokens = options.maxTokens;\n }\n\n /**\n * Attach to the conversation: rehydrate history from persistence and\n * subscribe to conversation events.\n */\n async start(): Promise<void> {\n if (this.started) return;\n this.started = true;\n\n if (this.persistence) {\n const [turns, generations] = await Promise.all([\n this.persistence.listTurns(this.conversation.id),\n this.persistence.listGenerations(this.conversation.id),\n ]);\n const entries: Array<\n | { at: number; kind: \"turn\"; turn: Turn }\n | { at: number; kind: \"generation\"; text: string }\n > = [\n ...turns.map((turn) => ({ at: turn.startedAt, kind: \"turn\" as const, turn })),\n ...generations\n .filter((generation) => generation.status === \"completed\")\n .map((generation) => ({\n at: generation.startedAt,\n kind: \"generation\" as const,\n text: generation.text,\n })),\n ].sort((a, b) => a.at - b.at);\n\n for (const entry of entries) {\n if (entry.kind === \"turn\") {\n this.history.push({\n role: \"user\",\n content: `${entry.turn.participantName}: ${entry.turn.text}`,\n });\n } else {\n this.history.push({ role: \"assistant\", content: entry.text });\n }\n }\n }\n\n this.unsubscribers.push(\n this.conversation.on(\"stop\", () => void this.stop()),\n this.conversation.on(\"audio-in\", (payload) => this.onAudioIn(payload)),\n this.conversation.on(\"interrupt\", () => this.onInterrupt()),\n this.conversation.on(\"tool-call-result\", (payload) =>\n this.onToolCallResult(payload.result),\n ),\n );\n }\n\n async stop(): Promise<void> {\n if (!this.started) return;\n this.started = false;\n this.epoch++;\n this.llm?.stop();\n this.tts?.stop();\n this.cancelToolWaiters(\"conversation stopped\");\n this.speechBuffer = \"\";\n for (const unsubscribe of this.unsubscribers) unsubscribe();\n this.unsubscribers.length = 0;\n const sessions = [...this.sttSessions.values()];\n this.sttSessions.clear();\n for (const { session } of sessions) {\n await session.end().catch(() => {});\n }\n }\n\n /**\n * Resolve once every queued and in-flight turn and generation has\n * finished processing. Useful for tests and graceful shutdown.\n */\n async whenIdle(): Promise<void> {\n for (;;) {\n while (\n this.pendingTurns > 0 ||\n this.pendingGenerations > 0 ||\n this.generating\n ) {\n await Bun.sleep(1);\n }\n // Give work scheduled in the same microtask turn a chance to register.\n await Promise.resolve();\n if (\n this.pendingTurns === 0 &&\n this.pendingGenerations === 0 &&\n !this.generating\n ) {\n return;\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Conversation event handlers\n // -------------------------------------------------------------------------\n\n private onAudioIn(payload: { userId: UserId; audio: AudioChunk }): void {\n let entry = this.sttSessions.get(payload.userId);\n if (!entry) {\n const session = this.stt.start({});\n session.on(\"partial\", (text) => this.onPartial(payload.userId, text));\n session.on(\"final\", (text) => this.onFinal(payload.userId, text));\n session.on(\"error\", (error) => this.onProviderError(error));\n entry = { session, turnStartedAt: null };\n this.sttSessions.set(payload.userId, entry);\n }\n\n if (entry.turnStartedAt === null) {\n entry.turnStartedAt = Date.now();\n }\n entry.session.write(payload.audio.data);\n\n // Barge-in: a participant speaks while the agent is responding (or about\n // to). The interrupting audio is already queued to STT above.\n if (this.pendingGenerations > 0) {\n this.conversation.interrupt();\n }\n }\n\n private onPartial(userId: UserId, text: string): void {\n const trimmed = text.trim();\n if (!trimmed) return;\n this.conversation.emit(\"partial-transcript\", {\n conversationId: this.conversation.id,\n userId,\n text: trimmed,\n });\n }\n\n private onFinal(userId: UserId, text: string): void {\n const trimmed = text.trim();\n if (!trimmed) return;\n const participant = this.conversation.state.participants.get(userId);\n if (!participant) return;\n\n const entry = this.sttSessions.get(userId);\n const startedAt = entry?.turnStartedAt ?? Date.now();\n if (entry) entry.turnStartedAt = null;\n\n const turn: Turn = {\n id: crypto.randomUUID(),\n conversationId: this.conversation.id,\n participantId: userId,\n participantName: participant.aliases[0] ?? userId,\n text: trimmed,\n sequence: this.turnSequence++,\n startedAt,\n endedAt: Date.now(),\n };\n\n // Track synchronously so `whenIdle()` can observe in-flight work.\n this.pendingTurns++;\n void this.processTurn(turn);\n }\n\n private async processTurn(turn: Turn): Promise<void> {\n try {\n await this.conversation.pushTurn(turn);\n await this.conversation.pushTranscript({\n speaker: turn.participantName,\n speakerKind: \"participant\",\n text: turn.text,\n });\n this.history.push({\n role: \"user\",\n content: `${turn.participantName}: ${turn.text}`,\n });\n if (this.agent) {\n this.queueGeneration();\n }\n } finally {\n this.pendingTurns--;\n }\n }\n\n private onInterrupt(): void {\n this.epoch++;\n this.llm?.stop();\n this.tts?.stop();\n this.cancelToolWaiters(\"interrupted\");\n this.speechBuffer = \"\";\n }\n\n private onToolCallResult(result: ToolCallResult): void {\n const resolve = this.toolWaiters.get(result.id);\n if (!resolve) return; // stale, timed out, or already resolved\n this.toolWaiters.delete(result.id);\n resolve(result);\n }\n\n private onProviderError(error: Error): void {\n this.conversation.emit(\"error\", { conversationId: this.conversation.id, error });\n }\n\n // -------------------------------------------------------------------------\n // Generation\n // -------------------------------------------------------------------------\n\n private queueGeneration(): void {\n this.pendingGenerations++;\n const epoch = this.epoch;\n this.generationChain = this.generationChain.then(async () => {\n if (this.epoch !== epoch) {\n // Superseded by an interruption while queued.\n this.pendingGenerations--;\n return;\n }\n try {\n await this.generate();\n } finally {\n this.pendingGenerations--;\n }\n });\n }\n\n private async generate(): Promise<void> {\n const { agent, llm, tts } = this;\n if (!agent || !llm || !tts) return;\n this.generating = true;\n try {\n await this.runGeneration(this.epoch, agent, llm, tts);\n } finally {\n this.generating = false;\n }\n }\n\n private async runGeneration(\n epoch: number,\n agent: Agent,\n llm: LLM,\n tts: TTS,\n ): Promise<void> {\n await this.conversation.pushGeneration({\n id: crypto.randomUUID(),\n conversationId: this.conversation.id,\n agentName: agent.name,\n text: \"\",\n status: \"streaming\",\n startedAt: Date.now(),\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\", content: agent.context });\n }\n messages.push(...this.history);\n\n let text = \"\";\n\n try {\n for (let iteration = 0; iteration < this.maxToolIterations; iteration++) {\n if (this.epoch !== epoch) return;\n\n const toolCalls: LLMToolCall[] = [];\n let done = false;\n\n for await (const event of llm.stream({\n messages,\n tools: definitions,\n temperature: this.temperature,\n maxTokens: this.maxTokens,\n })) {\n if (this.epoch !== epoch) return;\n switch (event.type) {\n case \"delta\":\n text += event.content;\n this.feedDelta(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 if (this.epoch !== epoch) return;\n\n if (toolCalls.length > 0) {\n // Pause the response: let the narration finish, hand the calls to\n // the application, and resume once they are resolved.\n this.flushSpeech();\n messages.push({ role: \"assistant\", content: text, toolCalls });\n const results = await this.resolveToolCalls(toolCalls, epoch);\n if (this.epoch !== epoch) return;\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 if (this.epoch !== epoch) return;\n\n this.flushSpeech();\n await this.speechChain;\n\n if (this.epoch !== epoch) return;\n\n await this.conversation.completeGeneration(text);\n await this.conversation.pushTranscript({\n speaker: agent.name,\n speakerKind: \"agent\",\n text,\n });\n this.history.push({ role: \"assistant\", content: text });\n } catch (error) {\n if (this.epoch !== epoch) return; // interrupted \u2014 discard everything\n this.conversation.emit(\"error\", {\n conversationId: this.conversation.id,\n error: error instanceof Error ? error : new Error(String(error)),\n });\n // Finalize whatever was generated so the conversation state stays\n // consistent even though the provider failed.\n await this.conversation.completeGeneration(text);\n if (text) {\n await this.conversation.pushTranscript({\n speaker: agent.name,\n speakerKind: \"agent\",\n text,\n });\n this.history.push({ role: \"assistant\", content: text });\n }\n }\n }\n\n private async resolveToolCalls(\n calls: LLMToolCall[],\n epoch: number,\n ): Promise<ResolvedToolCall[]> {\n const resolutions = calls.map((call) => this.waitForToolResult(call.id, epoch));\n for (const call of calls) {\n let args: unknown;\n try {\n args = JSON.parse(call.arguments);\n } catch {\n args = call.arguments;\n }\n this.conversation.requestToolCall({\n id: call.id,\n name: call.name,\n arguments: args,\n });\n }\n\n const results = await Promise.all(resolutions);\n return results.map((result, index) => {\n const call = calls[index]!;\n return {\n id: result.id,\n name: call.name,\n result: \"result\" in result ? result.result : undefined,\n error: \"error\" in result ? result.error : undefined,\n };\n });\n }\n\n private waitForToolResult(id: string, _epoch: number): Promise<ToolCallResult> {\n return new Promise((resolve) => {\n const timeout = setTimeout(() => {\n this.toolWaiters.delete(id);\n resolve({ id, error: `Tool call \"${id}\" timed out` });\n }, this.toolTimeoutMs);\n this.toolWaiters.set(id, (result) => {\n clearTimeout(timeout);\n resolve(result);\n });\n });\n }\n\n private cancelToolWaiters(reason: string): void {\n for (const [id, resolve] of [...this.toolWaiters]) {\n this.toolWaiters.delete(id);\n resolve({ id, error: reason });\n }\n }\n\n // -------------------------------------------------------------------------\n // Speech (LLM deltas \u2192 sentence buffering \u2192 TTS \u2192 audio-out)\n // -------------------------------------------------------------------------\n\n private feedDelta(delta: string): void {\n this.speechBuffer += delta;\n // Flush every complete sentence so multi-sentence deltas (and deltas\n // that span several sentences) are spoken as separate TTS requests.\n for (;;) {\n let boundary = -1;\n for (let i = 0; i < this.speechBuffer.length; i++) {\n const ch = this.speechBuffer[i];\n if (ch === \".\" || ch === \"!\" || ch === \"?\" || ch === \"\\n\") {\n boundary = i;\n break;\n }\n }\n if (boundary < 0) break;\n const sentence = this.speechBuffer.slice(0, boundary + 1).trim();\n this.speechBuffer = this.speechBuffer.slice(boundary + 1);\n if (sentence) this.speak(sentence);\n }\n }\n\n private flushSpeech(): void {\n const rest = this.speechBuffer.trim();\n this.speechBuffer = \"\";\n if (rest) this.speak(rest);\n }\n\n /** Synthesize a sentence and push the audio chunks out to the app. */\n private speak(sentence: string): void {\n const tts = this.tts;\n if (!tts) return;\n const epoch = this.epoch;\n this.speechChain = this.speechChain.then(async () => {\n if (!this.started || this.epoch !== epoch) return;\n try {\n for await (const chunk of tts.stream({ text: sentence })) {\n if (!this.started || this.epoch !== epoch) break;\n this.conversation.pushAudio({\n data: chunk,\n timestamp: Date.now(),\n sequence: this.audioSequence++,\n });\n }\n } catch (error) {\n if (this.epoch !== epoch) return; // interrupted\n this.conversation.emit(\"error\", {\n conversationId: this.conversation.id,\n error: error instanceof Error ? error : new Error(String(error)),\n });\n }\n });\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["orchestrator_exports", "__export", "Orchestrator", "__toCommonJS", "Orchestrator", "__name", "options", "llm", "turns", "generations", "entries", "turn", "generation", "a", "b", "entry", "payload", "unsubscribe", "sessions", "session", "text", "error", "userId", "trimmed", "participant", "startedAt", "result", "resolve", "epoch", "agent", "tts", "definitions", "tool", "messages", "iteration", "toolCalls", "done", "event", "results", "calls", "resolutions", "call", "args", "index", "id", "_epoch", "timeout", "reason", "delta", "boundary", "i", "ch", "sentence", "rest", "chunk"]
4
+ "sourcesContent": ["import type { Agent } from \"../../../agents/agent\";\nimport type { Conversation } from \"../../conversation/conversation\";\nimport type { Persistence } from \"../../../persistence/persistence\";\nimport type {\n LLM,\n LLMMessage,\n LLMToolDefinition,\n} from \"../../../providers/llm/types\";\nimport type { STT, STTSession } from \"../../../providers/stt/types\";\nimport type { TTS } from \"../../../providers/tts/types\";\nimport type { AudioChunk, Turn, UserId } from \"../../types\";\nimport type { CoordinationRegistration } from \"../coordination/coordination\";\nimport { ConversationHistory, type HistoryWindow } from \"./history/history\";\nimport { findAddressedAgent, pickAgent } from \"./routing/routing\";\nimport { GenerationRunner } from \"./generation/generation\";\nimport { SpeechPipeline } from \"./speech/speech\";\nimport { ToolCallManager } from \"./tools/tools\";\nimport { CoordinationRunner } from \"./coordination-runner/coordination-runner\";\n\nexport interface OrchestratorOptions {\n conversation: Conversation;\n /**\n * The agents the orchestrator routes turns to. With more than one agent,\n * unaddressed turns run through the built-in `understand` coordination,\n * which can delegate to agents, ask the user, or answer directly. Omit\n * for transcription-only mode (audio in, turns and transcripts out \u2014 no\n * LLM or TTS required).\n */\n agents?: Agent[];\n /** Defaults to the first agent's LLM. */\n llm?: LLM;\n /** STT for voice turns. Omit for text-only conversations (`send()`). */\n stt?: STT;\n /** TTS for spoken output. Not required for text-only conversations. */\n tts?: TTS;\n /** Used to rehydrate conversation history on start. */\n persistence?: Persistence;\n /** How long to wait for the application to resolve a tool call. */\n toolTimeoutMs?: number;\n /** Safety bound on tool-call round trips per generation. */\n maxToolIterations?: number;\n /**\n * Additional coordinations the runtime can delegate to, registered by\n * name (the key is the coordination's name).\n */\n coordinations?: Record<string, CoordinationRegistration>;\n /** Safety bound on LLM reasoning steps per coordination execution. */\n maxCoordinationSteps?: number;\n temperature?: number;\n maxTokens?: number;\n /**\n * Bounds how much conversation history each LLM request carries (default\n * `{ maxTurns: 5, maxChars: 4000 }` \u2014 provider TTFT grows with input size,\n * and a bounded window keeps requests in the fast regime). Pass `false` to\n * always send the full history.\n */\n historyWindow?: HistoryWindow | false;\n}\n\ninterface SttSessionEntry {\n session: STTSession;\n turnStartedAt: number | null;\n}\n\n/**\n * The realtime conversation state machine and multi-agent coordinator.\n *\n * Wires the conversation to the providers and routes each turn to an agent.\n * The heavy machinery lives in focused collaborators \u2014 history, routing,\n * generation, speech, tools, and coordination \u2014 so this class owns only the\n * lifecycle and event wiring:\n *\n * ```text\n * audio-in \u2500\u2500\u25BA STT \u2500\u2500\u25BA turn \u2500\u2500\u25BA coordinator \u2500\u2500\u25BA agent \u2500\u2500\u25BA LLM \u2500\u2500\u25BA TTS \u2500\u2500\u25BA audio-out\n * \u2502\n * \u2514\u2500\u25BA tool-call \u2500\u2500\u25BA app resolves \u2500\u2500\u25BA resume\n * ```\n *\n * Deltas stream to TTS immediately (so the agent can narrate while a tool\n * runs), tool calls pause the generation until the application resolves\n * them, and interruptions cancel the current generation \u2014 discarding any\n * stale tool results or audio via a generation epoch.\n */\nexport class Orchestrator {\n private readonly conversation: Conversation;\n private readonly agents: Agent[];\n private readonly llm: LLM | undefined;\n private readonly stt: STT | undefined;\n private readonly tts: TTS | undefined;\n private readonly persistence: Persistence | undefined;\n private readonly maxToolIterations: number;\n private readonly historyWindow: HistoryWindow | false;\n private readonly temperature: number | undefined;\n private readonly maxTokens: number | undefined;\n\n private readonly history: ConversationHistory;\n private readonly speech: SpeechPipeline;\n private readonly tools: ToolCallManager;\n private readonly generation: GenerationRunner;\n private readonly coordination: CoordinationRunner;\n\n private started = false;\n private generating = false;\n private epoch = 0;\n private generationChain: Promise<void> = Promise.resolve();\n private readonly unsubscribers: (() => void)[] = [];\n private readonly sttSessions = new Map<UserId, SttSessionEntry>();\n private pendingTurns = 0;\n private pendingGenerations = 0;\n private turnSequence = 0;\n\n constructor(options: OrchestratorOptions) {\n const agents = options.agents ?? [];\n const llm = options.llm ?? agents[0]?.llm;\n if (agents.length > 0 && !llm) {\n throw new Error(\n \"Orchestrator requires an LLM when agents are attached: \" +\n \"pass one explicitly or configure an agent with one\",\n );\n }\n this.conversation = options.conversation;\n this.agents = agents;\n this.llm = llm;\n this.stt = options.stt;\n this.tts = options.tts;\n this.persistence = options.persistence;\n this.maxToolIterations = options.maxToolIterations ?? 10;\n this.historyWindow = options.historyWindow ?? { maxTurns: 5, maxChars: 4_000 };\n this.temperature = options.temperature;\n this.maxTokens = options.maxTokens;\n\n this.history = new ConversationHistory();\n this.speech = new SpeechPipeline({\n tts: this.tts,\n conversation: this.conversation,\n isCurrent: (epoch) => this.started && epoch === this.epoch,\n });\n this.tools = new ToolCallManager(this.conversation, options.toolTimeoutMs ?? 30_000);\n this.generation = new GenerationRunner();\n this.coordination = new CoordinationRunner({\n conversation: this.conversation,\n agents: () => this.agents,\n llm: () => this.llm,\n history: this.history,\n historyWindow: this.historyWindow,\n speech: this.speech,\n generation: this.generation,\n tools: this.tools,\n maxCoordinationSteps: options.maxCoordinationSteps ?? 20,\n maxToolIterations: this.maxToolIterations,\n temperature: this.temperature,\n maxTokens: this.maxTokens,\n currentEpoch: () => this.epoch,\n isCurrent: (epoch) => this.started && epoch === this.epoch,\n });\n this.coordination.register(options.coordinations ?? {}, agents);\n }\n\n /**\n * Attach to the conversation: rehydrate history from persistence and\n * subscribe to conversation events.\n */\n async start(): Promise<void> {\n if (this.started) return;\n this.started = true;\n\n if (this.persistence) {\n const [turns, generations] = await Promise.all([\n this.persistence.listTurns(this.conversation.id),\n this.persistence.listGenerations(this.conversation.id),\n ]);\n this.history.rehydrate(turns, generations, this.conversation);\n }\n\n this.unsubscribers.push(\n this.conversation.on(\"stop\", () => void this.stop()),\n this.conversation.on(\"audio-in\", (payload) => this.onAudioIn(payload)),\n this.conversation.on(\"text-in\", ({ userId, text }) => this.onFinal(userId, text)),\n this.conversation.on(\"interrupt\", () => this.onInterrupt()),\n this.conversation.on(\"tool-call-result\", ({ result }) => this.tools.handleResult(result)),\n );\n }\n\n async stop(): Promise<void> {\n if (!this.started) return;\n this.started = false;\n this.epoch++;\n this.coordination.cancel();\n this.stopLlms();\n this.speech.stop();\n this.tools.cancelAll(\"conversation stopped\");\n for (const unsubscribe of this.unsubscribers) unsubscribe();\n this.unsubscribers.length = 0;\n const sessions = [...this.sttSessions.values()];\n this.sttSessions.clear();\n for (const { session } of sessions) {\n await session.end().catch(() => {});\n }\n }\n\n /**\n * Resolve once every queued and in-flight turn and generation has\n * finished processing. Useful for tests and graceful shutdown.\n */\n async whenIdle(): Promise<void> {\n for (;;) {\n while (\n this.pendingTurns > 0 ||\n this.pendingGenerations > 0 ||\n this.generating\n ) {\n await Bun.sleep(1);\n }\n // Give work scheduled in the same microtask turn a chance to register.\n await Promise.resolve();\n if (\n this.pendingTurns === 0 &&\n this.pendingGenerations === 0 &&\n !this.generating\n ) {\n return;\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Conversation event handlers\n // -------------------------------------------------------------------------\n\n private onAudioIn(payload: { userId: UserId; audio: AudioChunk }): void {\n if (!this.stt) return; // text-only conversation\n let entry = this.sttSessions.get(payload.userId);\n if (!entry) {\n const session = this.stt.start({});\n session.on(\"partial\", (text) => this.onPartial(payload.userId, text));\n session.on(\"final\", (text) => this.onFinal(payload.userId, text));\n session.on(\"error\", (error) => this.onProviderError(error));\n entry = { session, turnStartedAt: null };\n this.sttSessions.set(payload.userId, entry);\n }\n\n if (entry.turnStartedAt === null) {\n entry.turnStartedAt = Date.now();\n }\n entry.session.write(payload.audio.data);\n\n if (this.coordination.hasPending()) {\n // The participant is answering a pending question \u2014 this audio is the\n // answer, not an interruption. Stop the question's playback only; the\n // coordination stays parked and resumes on the final transcript.\n this.speech.stop();\n return;\n }\n\n // Barge-in: a participant speaks while the agent is responding (or about\n // to). The interrupting audio is already queued to STT above.\n if (this.pendingGenerations > 0) {\n this.conversation.interrupt();\n }\n }\n\n private onPartial(userId: UserId, text: string): void {\n const trimmed = text.trim();\n if (!trimmed) return;\n this.conversation.emit(\"partial-transcript\", {\n conversationId: this.conversation.id,\n userId,\n text: trimmed,\n });\n }\n\n private onFinal(userId: UserId, text: string): void {\n const trimmed = text.trim();\n if (!trimmed) return;\n const participant = this.conversation.state.participants.get(userId);\n if (!participant) return;\n\n const entry = this.sttSessions.get(userId);\n const startedAt = entry?.turnStartedAt ?? Date.now();\n if (entry) entry.turnStartedAt = null;\n\n const turn: Turn = {\n id: crypto.randomUUID(),\n conversationId: this.conversation.id,\n participantId: userId,\n participantName: participant.aliases[0] ?? userId,\n text: trimmed,\n sequence: this.turnSequence++,\n startedAt,\n endedAt: Date.now(),\n };\n\n // Track synchronously so `whenIdle()` can observe in-flight work.\n this.pendingTurns++;\n void this.processTurn(turn);\n }\n\n private async processTurn(turn: Turn): Promise<void> {\n try {\n await this.conversation.pushTurn(turn);\n await this.conversation.pushTranscript({\n speaker: turn.participantName,\n speakerKind: \"participant\",\n text: turn.text,\n });\n this.history.addUserTurn(turn, this.conversation);\n if (this.agents.length === 0) return;\n\n if (this.coordination.hasPending()) {\n // The user answered a pending coordination question: resume it with\n // this turn instead of starting a fresh generation.\n this.enqueueCoordinationRun(() => this.coordination.resume(turn));\n return;\n }\n\n if (this.agents.length === 1 || findAddressedAgent(this.agents, turn.text)) {\n // Single-agent conversations, and turns that explicitly address an\n // agent by name/alias, route straight to that agent.\n this.queueGeneration(turn);\n return;\n }\n\n // Otherwise the built-in `understand` coordination decides: delegate to\n // agents, ask the user, or answer directly.\n this.enqueueCoordinationRun(() => this.coordination.runDefault(turn));\n } finally {\n this.pendingTurns--;\n }\n }\n\n private onInterrupt(): void {\n this.epoch++;\n this.coordination.cancel();\n this.stopLlms();\n this.speech.stop();\n this.tools.cancelAll(\"interrupted\");\n }\n\n /** Cancel every LLM in play: the shared one and each agent's own. */\n private stopLlms(): void {\n const seen = new Set<LLM>();\n if (this.llm) seen.add(this.llm);\n for (const agent of this.agents) {\n if (agent.llm) seen.add(agent.llm);\n }\n for (const llm of seen) llm.stop();\n }\n\n private onProviderError(error: Error): void {\n this.conversation.emit(\"error\", { conversationId: this.conversation.id, error });\n }\n\n // -------------------------------------------------------------------------\n // Generation\n // -------------------------------------------------------------------------\n\n private queueGeneration(turn: Turn): void {\n this.pendingGenerations++;\n const epoch = this.epoch;\n this.generationChain = this.generationChain.then(async () => {\n if (this.epoch !== epoch) {\n // Superseded by an interruption while queued.\n this.pendingGenerations--;\n return;\n }\n try {\n await this.generate(turn);\n } finally {\n this.pendingGenerations--;\n }\n });\n }\n\n private async generate(turn: Turn): Promise<void> {\n if (this.agents.length === 0) return;\n // The coordinator routes this turn to an agent by name/alias, falling\n // back to the first agent in the roster.\n const agent = pickAgent(this.agents, turn.text);\n if (!agent) return;\n // Prefer the routed agent's own LLM so agents with different providers\n // keep their intelligence; fall back to the shared LLM.\n const llm = agent.llm ?? this.llm;\n if (!llm) return;\n this.generating = true;\n try {\n await this.runGeneration(this.epoch, turn, agent, llm);\n } finally {\n this.generating = false;\n }\n }\n\n private async runGeneration(\n epoch: number,\n turn: Turn,\n agent: Agent,\n llm: LLM,\n ): Promise<void> {\n const generationId = crypto.randomUUID();\n await this.conversation.pushGeneration({\n id: generationId,\n conversationId: this.conversation.id,\n agentName: agent.name,\n text: \"\",\n status: \"streaming\",\n startedAt: Date.now(),\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\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.epoch === epoch,\n onDelta: (delta) => this.speech.feed(delta, epoch),\n resolveToolCalls: (calls) => this.tools.resolveCalls(calls),\n });\n\n // A stale run (interrupt/stop) is discarded entirely \u2014 the conversation\n // already marked the generation cancelled.\n if (this.epoch !== epoch) return;\n if (outcome.status === \"interrupted\") return;\n\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 // Finalize whatever was generated so the conversation state stays\n // consistent even though the provider failed.\n await this.conversation.completeGeneration(outcome.text);\n if (outcome.text) {\n await this.conversation.pushTranscript({\n speaker: agent.name,\n speakerKind: \"agent\",\n text: outcome.text,\n });\n this.history.addAssistant(agent.name, outcome.text);\n }\n return;\n }\n\n this.speech.flush(epoch);\n await this.speech.waitForIdle();\n if (this.epoch !== epoch) return;\n\n await this.conversation.completeGeneration(outcome.text);\n await this.conversation.pushTranscript({\n speaker: agent.name,\n speakerKind: \"agent\",\n text: outcome.text,\n });\n this.history.addAssistant(agent.name, outcome.text);\n }\n\n // -------------------------------------------------------------------------\n // Coordination (serialized with agent generations: one track at a time)\n // -------------------------------------------------------------------------\n\n private enqueueCoordinationRun(run: () => Promise<void>): void {\n this.pendingGenerations++;\n this.generationChain = this.generationChain.then(async () => {\n this.generating = true;\n try {\n await run();\n } finally {\n this.generating = false;\n this.pendingGenerations--;\n }\n });\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["orchestrator_exports", "__export", "Orchestrator", "__toCommonJS", "import_history", "import_routing", "import_generation", "import_speech", "import_tools", "import_coordination_runner", "Orchestrator", "__name", "options", "agents", "llm", "epoch", "turns", "generations", "payload", "userId", "text", "result", "unsubscribe", "sessions", "session", "entry", "error", "trimmed", "participant", "startedAt", "turn", "seen", "agent", "generationId", "definitions", "tool", "messages", "outcome", "delta", "calls", "run"]
7
7
  }
@@ -0,0 +1,2 @@
1
+ "use strict";var i=Object.defineProperty;var f=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var m=Object.prototype.hasOwnProperty;var o=(n,d)=>{for(var r in d)i(n,r,{get:d[r],enumerable:!0})},p=(n,d,r,A)=>{if(d&&typeof d=="object"||typeof d=="function")for(let t of g(d))!m.call(n,t)&&t!==r&&i(n,t,{get:()=>d[t],enumerable:!(A=f(d,t))||A.enumerable});return n};var s=n=>p(i({},"__esModule",{value:!0}),n);var a={};o(a,{buildUnderstandPrompt:()=>e.buildUnderstandPrompt,findAddressedAgent:()=>e.findAddressedAgent,findAgentByName:()=>e.findAgentByName,pickAgent:()=>e.pickAgent});module.exports=s(a);var e=require("./routing.js");
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/conversations/orchestration/orchestrator/routing/index.ts"],
4
+ "sourcesContent": ["export {\n buildUnderstandPrompt,\n findAddressedAgent,\n findAgentByName,\n pickAgent,\n} from \"./routing\";\n"],
5
+ "mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,gLAAAE,EAAAF,GAAA,IAAAG,EAKO",
6
+ "names": ["routing_exports", "__export", "__toCommonJS", "import_routing"]
7
+ }
@@ -0,0 +1,23 @@
1
+ "use strict";var s=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var l=Object.getOwnPropertyNames;var u=Object.prototype.hasOwnProperty;var r=(n,t)=>s(n,"name",{value:t,configurable:!0});var c=(n,t)=>{for(var o in t)s(n,o,{get:t[o],enumerable:!0})},d=(n,t,o,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of l(t))!u.call(n,a)&&a!==o&&s(n,a,{get:()=>t[a],enumerable:!(e=i(t,a))||e.enumerable});return n};var f=n=>d(s({},"__esModule",{value:!0}),n);var p={};c(p,{buildUnderstandPrompt:()=>y,findAddressedAgent:()=>m,findAgentByName:()=>h,pickAgent:()=>g});module.exports=f(p);function g(n,t){if(n.length===0)return null;const o=t.toLowerCase();for(const e of n){if(e.name&&o.includes(e.name.toLowerCase()))return e;for(const a of e.aliases)if(o.includes(a.toLowerCase()))return e}return n[0]}r(g,"pickAgent");function m(n,t){const o=t.toLowerCase();for(const e of n){if(e.name&&o.includes(e.name.toLowerCase()))return e;for(const a of e.aliases)if(o.includes(a.toLowerCase()))return e}return null}r(m,"findAddressedAgent");function h(n,t){const o=t.trim().toLowerCase();for(const e of n){if(e.name.toLowerCase()===o)return e;for(const a of e.aliases)if(a.toLowerCase()===o)return e}return null}r(h,"findAgentByName");function y(n){return`You are the conversation coordinator.
2
+
3
+ Your job is to understand what the user is trying to accomplish and decide what
4
+ should happen next. You never perform domain work yourself.
5
+
6
+ The available agents are:
7
+ ${n.map(o=>{const e=o.aliases.length>0?` (aliases: ${o.aliases.join(", ")})`:"";return`- ${o.name}${e}`}).join(`
8
+ `)}
9
+
10
+ Decide the best next step and take exactly one:
11
+ - delegate to one or more agents ("agents"), each with a self-contained prompt
12
+ describing exactly what to do and any context they need;
13
+ - pass the work to another coordination ("coordination");
14
+ - ask the user for missing details ("clarify") when the request is ambiguous or
15
+ missing critical information \u2014 batch every missing detail into the "missing"
16
+ array in one call, never one question at a time. You may ask at most twice
17
+ per request; after that, state reasonable assumptions and answer;
18
+ - answer directly ("complete") when you have everything you need.
19
+
20
+ When you delegate, briefly narrate what you are doing, wait for the results,
21
+ then compose a single concise spoken answer and complete. Do not narrate your
22
+ internal reasoning.`}r(y,"buildUnderstandPrompt");
23
+ //# sourceMappingURL=routing.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/conversations/orchestration/orchestrator/routing/routing.ts"],
4
+ "sourcesContent": ["import type { Agent } from \"../../../../agents/agent\";\n\n/**\n * Pick the agent that should handle a turn.\n *\n * The first agent whose name or alias appears in the turn text wins;\n * otherwise the first agent in the roster is the default. Matching is\n * case-insensitive substring matching, so \"ask the technical specialist\"\n * addresses an agent named \"Technical Specialist\" (or aliased \"tech\").\n */\nexport function pickAgent(agents: readonly Agent[], text: string): Agent | null {\n if (agents.length === 0) return null;\n const normalized = text.toLowerCase();\n for (const agent of agents) {\n if (agent.name && normalized.includes(agent.name.toLowerCase())) return agent;\n for (const alias of agent.aliases) {\n if (normalized.includes(alias.toLowerCase())) return agent;\n }\n }\n return agents[0]!;\n}\n\n/**\n * Like `pickAgent` but without the default: only returns an agent the turn\n * explicitly addresses by name or alias.\n */\nexport function findAddressedAgent(\n agents: readonly Agent[],\n text: string,\n): Agent | null {\n const normalized = text.toLowerCase();\n for (const agent of agents) {\n if (agent.name && normalized.includes(agent.name.toLowerCase())) return agent;\n for (const alias of agent.aliases) {\n if (normalized.includes(alias.toLowerCase())) return agent;\n }\n }\n return null;\n}\n\n/** Resolve a task's agent by exact name or alias (case-insensitive). */\nexport function findAgentByName(\n agents: readonly Agent[],\n nameOrAlias: string,\n): Agent | null {\n const normalized = nameOrAlias.trim().toLowerCase();\n for (const agent of agents) {\n if (agent.name.toLowerCase() === normalized) return agent;\n for (const alias of agent.aliases) {\n if (alias.toLowerCase() === normalized) return agent;\n }\n }\n return null;\n}\n\n/** The built-in coordinator: understands the request and decides what's next. */\nexport function buildUnderstandPrompt(agents: readonly Agent[]): string {\n const roster = agents\n .map((agent) => {\n const aliases =\n agent.aliases.length > 0 ? ` (aliases: ${agent.aliases.join(\", \")})` : \"\";\n return `- ${agent.name}${aliases}`;\n })\n .join(\"\\n\");\n return `You are the conversation coordinator.\n\nYour job is to understand what the user is trying to accomplish and decide what\nshould happen next. You never perform domain work yourself.\n\nThe available agents are:\n${roster}\n\nDecide the best next step and take exactly one:\n- delegate to one or more agents (\"agents\"), each with a self-contained prompt\n describing exactly what to do and any context they need;\n- pass the work to another coordination (\"coordination\");\n- ask the user for missing details (\"clarify\") when the request is ambiguous or\n missing critical information \u2014 batch every missing detail into the \"missing\"\n array in one call, never one question at a time. You may ask at most twice\n per request; after that, state reasonable assumptions and answer;\n- answer directly (\"complete\") when you have everything you need.\n\nWhen you delegate, briefly narrate what you are doing, wait for the results,\nthen compose a single concise spoken answer and complete. Do not narrate your\ninternal reasoning.`;\n}\n"],
5
+ "mappings": "4dAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,2BAAAE,EAAA,uBAAAC,EAAA,oBAAAC,EAAA,cAAAC,IAAA,eAAAC,EAAAN,GAUO,SAASO,EAAUC,EAA0BC,EAA4B,CAC9E,GAAID,EAAO,SAAW,EAAG,OAAO,KAChC,MAAME,EAAaD,EAAK,YAAY,EACpC,UAAWE,KAASH,EAAQ,CAC1B,GAAIG,EAAM,MAAQD,EAAW,SAASC,EAAM,KAAK,YAAY,CAAC,EAAG,OAAOA,EACxE,UAAWC,KAASD,EAAM,QACxB,GAAID,EAAW,SAASE,EAAM,YAAY,CAAC,EAAG,OAAOD,CAEzD,CACA,OAAOH,EAAO,CAAC,CACjB,CAVgBK,EAAAN,EAAA,aAgBT,SAASO,EACdN,EACAC,EACc,CACd,MAAMC,EAAaD,EAAK,YAAY,EACpC,UAAWE,KAASH,EAAQ,CAC1B,GAAIG,EAAM,MAAQD,EAAW,SAASC,EAAM,KAAK,YAAY,CAAC,EAAG,OAAOA,EACxE,UAAWC,KAASD,EAAM,QACxB,GAAID,EAAW,SAASE,EAAM,YAAY,CAAC,EAAG,OAAOD,CAEzD,CACA,OAAO,IACT,CAZgBE,EAAAC,EAAA,sBAeT,SAASC,EACdP,EACAQ,EACc,CACd,MAAMN,EAAaM,EAAY,KAAK,EAAE,YAAY,EAClD,UAAWL,KAASH,EAAQ,CAC1B,GAAIG,EAAM,KAAK,YAAY,IAAMD,EAAY,OAAOC,EACpD,UAAWC,KAASD,EAAM,QACxB,GAAIC,EAAM,YAAY,IAAMF,EAAY,OAAOC,CAEnD,CACA,OAAO,IACT,CAZgBE,EAAAE,EAAA,mBAeT,SAASE,EAAsBT,EAAkC,CAQtE,MAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAPQA,EACZ,IAAKG,GAAU,CACd,MAAMO,EACJP,EAAM,QAAQ,OAAS,EAAI,cAAcA,EAAM,QAAQ,KAAK,IAAI,CAAC,IAAM,GACzE,MAAO,KAAKA,EAAM,IAAI,GAAGO,CAAO,EAClC,CAAC,EACA,KAAK;AAAA,CAAI,CAON;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAeR,CA7BgBL,EAAAI,EAAA",
6
+ "names": ["routing_exports", "__export", "buildUnderstandPrompt", "findAddressedAgent", "findAgentByName", "pickAgent", "__toCommonJS", "pickAgent", "agents", "text", "normalized", "agent", "alias", "__name", "findAddressedAgent", "findAgentByName", "nameOrAlias", "buildUnderstandPrompt", "aliases"]
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";var r=Object.defineProperty;var h=Object.getOwnPropertyDescriptor;var n=Object.getOwnPropertyNames;var f=Object.prototype.hasOwnProperty;var l=(p,e)=>{for(var o in e)r(p,o,{get:e[o],enumerable:!0})},m=(p,e,o,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of n(e))!f.call(p,i)&&i!==o&&r(p,i,{get:()=>e[i],enumerable:!(t=h(e,i))||t.enumerable});return p};var s=p=>m(r({},"__esModule",{value:!0}),p);var x={};l(x,{SpeechPipeline:()=>c.SpeechPipeline});module.exports=s(x);var c=require("./speech.js");
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/conversations/orchestration/orchestrator/speech/index.ts"],
4
+ "sourcesContent": ["export { SpeechPipeline } from \"./speech\";\nexport type { SpeechPipelineOptions } from \"./speech\";\n"],
5
+ "mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,sDAAAE,EAAAF,GAAA,IAAAG,EAA+B",
6
+ "names": ["speech_exports", "__export", "__toCommonJS", "import_speech"]
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";var o=Object.defineProperty;var p=Object.getOwnPropertyDescriptor;var u=Object.getOwnPropertyNames;var v=Object.prototype.hasOwnProperty;var h=(i,t)=>o(i,"name",{value:t,configurable:!0});var f=(i,t)=>{for(var e in t)o(i,e,{get:t[e],enumerable:!0})},m=(i,t,e,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of u(t))!v.call(i,r)&&r!==e&&o(i,r,{get:()=>t[r],enumerable:!(s=p(t,r))||s.enumerable});return i};var d=i=>m(o({},"__esModule",{value:!0}),i);var T={};f(T,{SpeechPipeline:()=>l});module.exports=d(T);var c=require("../../text-chunker/text-chunker.js");class l{static{h(this,"SpeechPipeline")}tts;conversation;isCurrent;chunker=new c.TextChunker;speechEpoch=0;chain=Promise.resolve();audioSequence=0;constructor(t){this.tts=t.tts,this.conversation=t.conversation,this.isCurrent=t.isCurrent}feed(t,e){if(t.length!==0){this.conversation.noteTiming("firstToken"),this.conversation.pushTextDelta(t);for(const s of this.chunker.push(t))this.speak(s,e)}}flush(t){const e=this.chunker.flush();e&&this.speak(e,t)}speak(t,e){const s=this.tts;if(!s)return;this.conversation.noteTiming("firstTtsText");const r=this.speechEpoch;this.chain=this.chain.then(async()=>{if(!(!this.isCurrent(e)||this.speechEpoch!==r)){this.conversation.noteTiming("firstTtsRequest");try{let n=!0;for await(const a of s.stream({text:t})){if(!this.isCurrent(e)||this.speechEpoch!==r)break;n&&(n=!1,this.conversation.noteTiming("firstTtsAudio")),this.conversation.pushAudio({data:a,timestamp:Date.now(),sequence:this.audioSequence++})}}catch(n){if(!this.isCurrent(e))return;this.conversation.emit("error",{conversationId:this.conversation.id,error:n instanceof Error?n:new Error(String(n))})}}})}stop(){this.speechEpoch++,this.chunker.clear(),this.tts?.stop()}waitForIdle(){return this.chain}}
2
+ //# sourceMappingURL=speech.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/conversations/orchestration/orchestrator/speech/speech.ts"],
4
+ "sourcesContent": ["import type { Conversation } from \"../../../conversation/conversation\";\nimport type { TTS } from \"../../../../providers/tts/types\";\nimport { TextChunker } from \"../../text-chunker/text-chunker\";\n\nexport interface SpeechPipelineOptions {\n /** TTS provider; omitted for text-only conversations. */\n tts?: TTS;\n conversation: Conversation;\n /**\n * True while the generation that produced the speech is still current.\n * The captured generation epoch is passed back in, so an interrupt (epoch\n * bump) or a stop drops queued and in-flight synthesis.\n */\n isCurrent(epoch: number): boolean;\n}\n\n/**\n * Turns the LLM delta stream into speakable audio: expose the text stream\n * semantically (`text-delta`), buffer sentences through the `TextChunker`,\n * and synthesize each chunk through the TTS provider on a serial chain.\n *\n * Owns the chunker, the speech epoch (bumped by `stop()`), the synthesis\n * chain, and the audio sequence \u2014 the orchestrator only decides *when*\n * speech is current.\n */\nexport class SpeechPipeline {\n private readonly tts: TTS | undefined;\n private readonly conversation: Conversation;\n private readonly isCurrent: (epoch: number) => boolean;\n private readonly chunker = new TextChunker();\n private speechEpoch = 0;\n private chain: Promise<void> = Promise.resolve();\n private audioSequence = 0;\n\n constructor(options: SpeechPipelineOptions) {\n this.tts = options.tts;\n this.conversation = options.conversation;\n this.isCurrent = options.isCurrent;\n }\n\n /**\n * Stream an LLM delta to the application and the TTS pipeline. Empty\n * deltas (reasoning-only frames) are skipped so they never reach the\n * text-delta event or the chunker.\n */\n feed(delta: string, epoch: number): void {\n if (delta.length === 0) return;\n // First-token latency for the in-flight generation.\n this.conversation.noteTiming(\"firstToken\");\n // Expose the text stream semantically: applications can render or act on\n // partial replies without waiting for the generation to complete.\n this.conversation.pushTextDelta(delta);\n // The chunker turns the token stream into speakable chunks: strong\n // sentence boundaries flush immediately, long clauses flush at soft\n // boundaries, and nothing waits indefinitely for punctuation.\n for (const chunk of this.chunker.push(delta)) {\n this.speak(chunk, epoch);\n }\n }\n\n /** Speak any remaining buffered text as a final chunk. */\n flush(epoch: number): void {\n const rest = this.chunker.flush();\n if (rest) this.speak(rest, epoch);\n }\n\n /** Synthesize a sentence and push the audio chunks out to the app. */\n speak(sentence: string, epoch: number): void {\n const tts = this.tts;\n if (!tts) return;\n // Buffering boundary: the first sentence flushed to TTS.\n this.conversation.noteTiming(\"firstTtsText\");\n const speechEpoch = this.speechEpoch;\n this.chain = this.chain.then(async () => {\n if (!this.isCurrent(epoch) || this.speechEpoch !== speechEpoch) {\n return;\n }\n // The TTS provider was asked to synthesize.\n this.conversation.noteTiming(\"firstTtsRequest\");\n try {\n let first = true;\n for await (const chunk of tts.stream({ text: sentence })) {\n if (!this.isCurrent(epoch) || this.speechEpoch !== speechEpoch) {\n break;\n }\n if (first) {\n first = false;\n // The provider produced its first audio chunk.\n this.conversation.noteTiming(\"firstTtsAudio\");\n }\n this.conversation.pushAudio({\n data: chunk,\n timestamp: Date.now(),\n sequence: this.audioSequence++,\n });\n }\n } catch (error) {\n if (!this.isCurrent(epoch)) return; // interrupted\n this.conversation.emit(\"error\", {\n conversationId: this.conversation.id,\n error: error instanceof Error ? error : new Error(String(error)),\n });\n }\n });\n }\n\n /**\n * Stop the current TTS playback and drop buffered text without cancelling\n * the generation (barge-in, interrupt, stop).\n */\n stop(): void {\n this.speechEpoch++;\n this.chunker.clear();\n this.tts?.stop();\n }\n\n /** Resolve when queued TTS synthesis has settled. */\n waitForIdle(): Promise<void> {\n return this.chain;\n }\n}\n"],
5
+ "mappings": "4dAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,oBAAAE,IAAA,eAAAC,EAAAH,GAEA,IAAAI,EAA4B,2CAuBrB,MAAMC,CAAe,CAzB5B,MAyB4B,CAAAC,EAAA,uBACT,IACA,aACA,UACA,QAAU,IAAI,cACvB,YAAc,EACd,MAAuB,QAAQ,QAAQ,EACvC,cAAgB,EAExB,YAAYC,EAAgC,CAC1C,KAAK,IAAMA,EAAQ,IACnB,KAAK,aAAeA,EAAQ,aAC5B,KAAK,UAAYA,EAAQ,SAC3B,CAOA,KAAKC,EAAeC,EAAqB,CACvC,GAAID,EAAM,SAAW,EAErB,MAAK,aAAa,WAAW,YAAY,EAGzC,KAAK,aAAa,cAAcA,CAAK,EAIrC,UAAWE,KAAS,KAAK,QAAQ,KAAKF,CAAK,EACzC,KAAK,MAAME,EAAOD,CAAK,EAE3B,CAGA,MAAMA,EAAqB,CACzB,MAAME,EAAO,KAAK,QAAQ,MAAM,EAC5BA,GAAM,KAAK,MAAMA,EAAMF,CAAK,CAClC,CAGA,MAAMG,EAAkBH,EAAqB,CAC3C,MAAMI,EAAM,KAAK,IACjB,GAAI,CAACA,EAAK,OAEV,KAAK,aAAa,WAAW,cAAc,EAC3C,MAAMC,EAAc,KAAK,YACzB,KAAK,MAAQ,KAAK,MAAM,KAAK,SAAY,CACvC,GAAI,GAAC,KAAK,UAAUL,CAAK,GAAK,KAAK,cAAgBK,GAInD,MAAK,aAAa,WAAW,iBAAiB,EAC9C,GAAI,CACF,IAAIC,EAAQ,GACZ,gBAAiBL,KAASG,EAAI,OAAO,CAAE,KAAMD,CAAS,CAAC,EAAG,CACxD,GAAI,CAAC,KAAK,UAAUH,CAAK,GAAK,KAAK,cAAgBK,EACjD,MAEEC,IACFA,EAAQ,GAER,KAAK,aAAa,WAAW,eAAe,GAE9C,KAAK,aAAa,UAAU,CAC1B,KAAML,EACN,UAAW,KAAK,IAAI,EACpB,SAAU,KAAK,eACjB,CAAC,CACH,CACF,OAASM,EAAO,CACd,GAAI,CAAC,KAAK,UAAUP,CAAK,EAAG,OAC5B,KAAK,aAAa,KAAK,QAAS,CAC9B,eAAgB,KAAK,aAAa,GAClC,MAAOO,aAAiB,MAAQA,EAAQ,IAAI,MAAM,OAAOA,CAAK,CAAC,CACjE,CAAC,CACH,EACF,CAAC,CACH,CAMA,MAAa,CACX,KAAK,cACL,KAAK,QAAQ,MAAM,EACnB,KAAK,KAAK,KAAK,CACjB,CAGA,aAA6B,CAC3B,OAAO,KAAK,KACd,CACF",
6
+ "names": ["speech_exports", "__export", "SpeechPipeline", "__toCommonJS", "import_text_chunker", "SpeechPipeline", "__name", "options", "delta", "epoch", "chunk", "rest", "sentence", "tts", "speechEpoch", "first", "error"]
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";var a=Object.defineProperty;var f=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var s=Object.prototype.hasOwnProperty;var x=(l,o)=>{for(var r in o)a(l,r,{get:o[r],enumerable:!0})},C=(l,o,r,t)=>{if(o&&typeof o=="object"||typeof o=="function")for(let e of m(o))!s.call(l,e)&&e!==r&&a(l,e,{get:()=>o[e],enumerable:!(t=f(o,e))||t.enumerable});return l};var T=l=>C(a({},"__esModule",{value:!0}),l);var d={};x(d,{ToolCallManager:()=>p.ToolCallManager});module.exports=T(d);var p=require("./tools.js");
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/conversations/orchestration/orchestrator/tools/index.ts"],
4
+ "sourcesContent": ["export { ToolCallManager } from \"./tools\";\nexport type { ResolvedToolCall } from \"./tools\";\n"],
5
+ "mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,wDAAAE,EAAAF,GAAA,IAAAG,EAAgC",
6
+ "names": ["tools_exports", "__export", "__toCommonJS", "import_tools"]
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";var n=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var u=Object.getOwnPropertyNames;var d=Object.prototype.hasOwnProperty;var l=(r,e)=>n(r,"name",{value:e,configurable:!0});var c=(r,e)=>{for(var o in e)n(r,o,{get:e[o],enumerable:!0})},v=(r,e,o,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of u(e))!d.call(r,t)&&t!==o&&n(r,t,{get:()=>e[t],enumerable:!(s=m(e,t))||s.enumerable});return r};var p=r=>v(n({},"__esModule",{value:!0}),r);var C={};c(C,{ToolCallManager:()=>w});module.exports=p(C);class w{static{l(this,"ToolCallManager")}conversation;timeoutMs;waiters=new Map;constructor(e,o){this.conversation=e,this.timeoutMs=o}async resolveCalls(e){const o=e.map(t=>this.wait(t.id));for(const t of e){let i;try{i=JSON.parse(t.arguments)}catch{i=t.arguments}this.conversation.requestToolCall({id:t.id,name:t.name,arguments:i})}return(await Promise.all(o)).map((t,i)=>{const a=e[i];return{id:t.id,name:a.name,result:"result"in t?t.result:void 0,error:"error"in t?t.error:void 0}})}handleResult(e){const o=this.waiters.get(e.id);o&&(this.waiters.delete(e.id),o(e))}cancelAll(e){for(const[o,s]of[...this.waiters])this.waiters.delete(o),s({id:o,error:e})}wait(e){return new Promise(o=>{const s=setTimeout(()=>{this.waiters.delete(e),o({id:e,error:`Tool call "${e}" timed out`})},this.timeoutMs);this.waiters.set(e,t=>{clearTimeout(s),o(t)})})}}
2
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/conversations/orchestration/orchestrator/tools/tools.ts"],
4
+ "sourcesContent": ["import type { Conversation } from \"../../../conversation/conversation\";\nimport type { LLMToolCall } from \"../../../../providers/llm/types\";\nimport type { ToolCallResult } from \"../../../types\";\n\nexport interface ResolvedToolCall {\n id: string;\n name: string;\n result?: unknown;\n error?: string;\n}\n\n/**\n * Tracks tool calls handed to the application and resolves them once the\n * application reports back (or a timeout fires). Stale results \u2014 timed out,\n * already resolved, or superseded by an interrupt \u2014 are dropped.\n */\nexport class ToolCallManager {\n private readonly conversation: Conversation;\n private readonly timeoutMs: number;\n private readonly waiters = new Map<string, (result: ToolCallResult) => void>();\n\n constructor(conversation: Conversation, timeoutMs: number) {\n this.conversation = conversation;\n this.timeoutMs = timeoutMs;\n }\n\n /**\n * Hand the calls to the application and resolve each one once it is\n * answered or times out. Returns them in call order, with either a result\n * or an error string.\n */\n async resolveCalls(calls: LLMToolCall[]): Promise<ResolvedToolCall[]> {\n const resolutions = calls.map((call) => this.wait(call.id));\n for (const call of calls) {\n let args: unknown;\n try {\n args = JSON.parse(call.arguments);\n } catch {\n args = call.arguments;\n }\n this.conversation.requestToolCall({\n id: call.id,\n name: call.name,\n arguments: args,\n });\n }\n\n const results = await Promise.all(resolutions);\n return results.map((result, index) => {\n const call = calls[index]!;\n return {\n id: result.id,\n name: call.name,\n result: \"result\" in result ? result.result : undefined,\n error: \"error\" in result ? result.error : undefined,\n };\n });\n }\n\n /** Resolve a waiter from a `tool-call-result` event; stale results drop. */\n handleResult(result: ToolCallResult): void {\n const resolve = this.waiters.get(result.id);\n if (!resolve) return;\n this.waiters.delete(result.id);\n resolve(result);\n }\n\n /** Force-resolve every pending call (interrupt, stop). */\n cancelAll(reason: string): void {\n for (const [id, resolve] of [...this.waiters]) {\n this.waiters.delete(id);\n resolve({ id, error: reason });\n }\n }\n\n private wait(id: string): Promise<ToolCallResult> {\n return new Promise((resolve) => {\n const timeout = setTimeout(() => {\n this.waiters.delete(id);\n resolve({ id, error: `Tool call \"${id}\" timed out` });\n }, this.timeoutMs);\n this.waiters.set(id, (result) => {\n clearTimeout(timeout);\n resolve(result);\n });\n });\n }\n}\n"],
5
+ "mappings": "4dAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,qBAAAE,IAAA,eAAAC,EAAAH,GAgBO,MAAMI,CAAgB,CAhB7B,MAgB6B,CAAAC,EAAA,wBACV,aACA,UACA,QAAU,IAAI,IAE/B,YAAYC,EAA4BC,EAAmB,CACzD,KAAK,aAAeD,EACpB,KAAK,UAAYC,CACnB,CAOA,MAAM,aAAaC,EAAmD,CACpE,MAAMC,EAAcD,EAAM,IAAKE,GAAS,KAAK,KAAKA,EAAK,EAAE,CAAC,EAC1D,UAAWA,KAAQF,EAAO,CACxB,IAAIG,EACJ,GAAI,CACFA,EAAO,KAAK,MAAMD,EAAK,SAAS,CAClC,MAAQ,CACNC,EAAOD,EAAK,SACd,CACA,KAAK,aAAa,gBAAgB,CAChC,GAAIA,EAAK,GACT,KAAMA,EAAK,KACX,UAAWC,CACb,CAAC,CACH,CAGA,OADgB,MAAM,QAAQ,IAAIF,CAAW,GAC9B,IAAI,CAACG,EAAQC,IAAU,CACpC,MAAMH,EAAOF,EAAMK,CAAK,EACxB,MAAO,CACL,GAAID,EAAO,GACX,KAAMF,EAAK,KACX,OAAQ,WAAYE,EAASA,EAAO,OAAS,OAC7C,MAAO,UAAWA,EAASA,EAAO,MAAQ,MAC5C,CACF,CAAC,CACH,CAGA,aAAaA,EAA8B,CACzC,MAAME,EAAU,KAAK,QAAQ,IAAIF,EAAO,EAAE,EACrCE,IACL,KAAK,QAAQ,OAAOF,EAAO,EAAE,EAC7BE,EAAQF,CAAM,EAChB,CAGA,UAAUG,EAAsB,CAC9B,SAAW,CAACC,EAAIF,CAAO,GAAK,CAAC,GAAG,KAAK,OAAO,EAC1C,KAAK,QAAQ,OAAOE,CAAE,EACtBF,EAAQ,CAAE,GAAAE,EAAI,MAAOD,CAAO,CAAC,CAEjC,CAEQ,KAAKC,EAAqC,CAChD,OAAO,IAAI,QAASF,GAAY,CAC9B,MAAMG,EAAU,WAAW,IAAM,CAC/B,KAAK,QAAQ,OAAOD,CAAE,EACtBF,EAAQ,CAAE,GAAAE,EAAI,MAAO,cAAcA,CAAE,aAAc,CAAC,CACtD,EAAG,KAAK,SAAS,EACjB,KAAK,QAAQ,IAAIA,EAAKJ,GAAW,CAC/B,aAAaK,CAAO,EACpBH,EAAQF,CAAM,CAChB,CAAC,CACH,CAAC,CACH,CACF",
6
+ "names": ["tools_exports", "__export", "ToolCallManager", "__toCommonJS", "ToolCallManager", "__name", "conversation", "timeoutMs", "calls", "resolutions", "call", "args", "result", "index", "resolve", "reason", "id", "timeout"]
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";var y=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var k=Object.prototype.hasOwnProperty;var i=(r,t)=>y(r,"name",{value:t,configurable:!0});var b=(r,t)=>{for(var e in t)y(r,e,{get:t[e],enumerable:!0})},A=(r,t,e,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of g(t))!k.call(r,s)&&s!==e&&y(r,s,{get:()=>t[s],enumerable:!(o=M(t,s))||o.enumerable});return r};var F=r=>A(y({},"__esModule",{value:!0}),r);var O={};b(O,{FakeLLM:()=>d,FakeSTT:()=>v,FakeSTTSession:()=>L,FakeTTS:()=>S,SlowTTS:()=>E,respond:()=>x,setup:()=>R,setupRoster:()=>H,speak:()=>q,waitFor:()=>C});module.exports=F(O);var p=require("../../agents/agent.js"),U=require("../../agents/tools/tools.js"),h=require("../conversation/conversation.js"),u=require("../../persistence/adapters/memory/memory.js"),T=require("./orchestrator/orchestrator.js");class d{constructor(t){this.script=t}script;static{i(this,"FakeLLM")}requests=[];stopCalls=[];controllers=new Set;async*stream(t){const e=new AbortController;this.controllers.add(e),this.requests.push(t);try{for await(const o of this.script(t,e.signal)){if(e.signal.aborted)throw new DOMException("The operation was aborted.","AbortError");yield o}}finally{this.controllers.delete(e)}}stop(){this.stopCalls.push(Date.now());for(const t of this.controllers)t.abort()}}class v{static{i(this,"FakeSTT")}sessions=[];startOptions=[];start(t={}){const e=new L;return this.sessions.push(e),this.startOptions.push(t),e}cancel(){}}class L{static{i(this,"FakeSTTSession")}written=[];ended=0;listeners={partial:new Set,final:new Set,error:new Set};write(t){this.written.push(t)}async end(){this.ended++}on(t,e){this.listeners[t].add(e)}emitPartial(t){for(const e of this.listeners.partial)e(t)}emitFinal(t){for(const e of this.listeners.final)e(t)}emitError(t){for(const e of this.listeners.error)e(t)}}class S{constructor(t){this.chunksFor=t}chunksFor;static{i(this,"FakeTTS")}requests=[];controllers=new Set;async*stream(t){this.requests.push(t);const e=new AbortController;this.controllers.add(e);try{for(const o of this.chunksFor(t.text)){if(e.signal.aborted)throw new DOMException("The operation was aborted.","AbortError");yield o}}finally{this.controllers.delete(e)}}stop(){for(const t of this.controllers)t.abort()}}class E{constructor(t,e=20){this.chunksFor=t;this.delayMs=e}chunksFor;delayMs;static{i(this,"SlowTTS")}requests=[];controllers=new Set;async*stream(t){this.requests.push(t);const e=new AbortController;this.controllers.add(e);try{for(const o of this.chunksFor(t.text)){if(await Bun.sleep(this.delayMs),e.signal.aborted)throw new DOMException("The operation was aborted.","AbortError");yield o}}finally{this.controllers.delete(e)}}stop(){for(const t of this.controllers)t.abort()}}function R(r){return(async()=>{const t=new u.MemoryPersistence,e=new h.Conversation({id:"conv-1",persistence:t}),o=r.llm??new d(r.script),s=new v,a=r.tts??new S(r.ttsChunks??(m=>[new TextEncoder().encode(m)])),c=new p.Agent({name:"Jarvis",context:r.context??"Be concise.",llm:o,tools:r.tools}),l=new T.Orchestrator({conversation:e,agents:[c],llm:o,stt:s,tts:a,persistence:t,toolTimeoutMs:r.toolTimeoutMs??3e4,historyWindow:r.historyWindow});return e.start(),await e.participate({userId:"alice",aliases:["al"]}),await l.start(),{conversation:e,orchestrator:l,llm:o,stt:s,tts:a,persistence:t}})()}i(R,"setup");async function C(r,t=2e3){const e=Date.now();for(;!r();){if(Date.now()-e>t)throw new Error("waitFor timed out");await Bun.sleep(2)}}i(C,"waitFor");async function q(r,t,e){r.conversation.listen({userId:t,audio:new Uint8Array([1])}),r.stt.sessions.at(-1).emitFinal(e),await r.orchestrator.whenIdle()}i(q,"speak");function x(r){return async function*(){yield{type:"delta",content:r},yield{type:"done"}}}i(x,"respond");function H(r){return(async()=>{const t=new u.MemoryPersistence,e=new h.Conversation({id:"conv-1",persistence:t}),o=new v,s=new S(n=>[new TextEncoder().encode(n)]),a=new d(r.coordinatorScript),c=new Map([["Jarvis",a]]),l=[new p.Agent({name:"Jarvis",context:"Be concise.",llm:a})];for(const[n,w]of Object.entries(r.scripts)){const f=new d(w);c.set(n,f),l.push(new p.Agent({name:n,context:`You are ${n}.`,llm:f,tools:r.tools?.[n]}))}if(l.length===1){const n=new d(x("ok"));c.set("Helper",n),l.push(new p.Agent({name:"Helper",context:"You help.",llm:n}))}for(const[n,w]of Object.entries(r.coordinations??{}))c.set(n,w.llm);const m=new T.Orchestrator({conversation:e,agents:l,llm:a,coordinations:r.coordinations,maxCoordinationSteps:r.maxCoordinationSteps,stt:o,tts:s,persistence:t});return e.start(),await e.participate({userId:"alice",aliases:["al"]}),await m.start(),{conversation:e,orchestrator:m,llm:a,stt:o,tts:s,persistence:t,llms:c}})()}i(H,"setupRoster");
2
+ //# sourceMappingURL=test-harness.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/conversations/orchestration/test-harness.ts"],
4
+ "sourcesContent": ["// Shared test doubles and harnesses for the orchestrator integration suites.\n// Import from here rather than re-implementing fakes per test file.\n\nimport { Agent } from \"../../agents/agent\";\nimport { Tool } from \"../../agents/tools/tools\";\nimport { Conversation } from \"../conversation/conversation\";\nimport { MemoryPersistence } from \"../../persistence/adapters/memory/memory\";\nimport { Orchestrator } from \"./orchestrator/orchestrator\";\nimport type { HistoryWindow } from \"./orchestrator/history/history\";\nimport type {\n LLM,\n LLMEvent,\n LLMRequest,\n} from \"../../providers/llm/types\";\nimport type { STT, STTOptions, STTSession } from \"../../providers/stt/types\";\nimport type { TTS, TTSRequest } from \"../../providers/tts/types\";\n\n// ---------------------------------------------------------------------------\n// Fake providers\n// ---------------------------------------------------------------------------\n\nexport type LLMScript = (request: LLMRequest, signal: AbortSignal) => AsyncIterable<LLMEvent>;\n\nexport class FakeLLM implements LLM {\n readonly requests: LLMRequest[] = [];\n readonly stopCalls: number[] = [];\n private readonly controllers = new Set<AbortController>();\n\n constructor(private readonly script: LLMScript) {}\n\n async *stream(request: LLMRequest): AsyncGenerator<LLMEvent> {\n const controller = new AbortController();\n this.controllers.add(controller);\n this.requests.push(request);\n try {\n for await (const event of this.script(request, controller.signal)) {\n if (controller.signal.aborted) {\n throw new DOMException(\"The operation was aborted.\", \"AbortError\");\n }\n yield event;\n }\n } finally {\n this.controllers.delete(controller);\n }\n }\n\n stop(): void {\n this.stopCalls.push(Date.now());\n for (const controller of this.controllers) controller.abort();\n }\n}\n\nexport class FakeSTT implements STT {\n readonly sessions: FakeSTTSession[] = [];\n readonly startOptions: STTOptions[] = [];\n\n start(options: STTOptions = {}): FakeSTTSession {\n const session = new FakeSTTSession();\n this.sessions.push(session);\n this.startOptions.push(options);\n return session;\n }\n\n cancel(): void {}\n}\n\nexport type FakeSessionEvent = \"partial\" | \"final\" | \"error\";\n\nexport class FakeSTTSession implements STTSession {\n readonly written: Uint8Array[] = [];\n ended = 0;\n private readonly listeners: Record<\n FakeSessionEvent,\n Set<(...args: any[]) => void>\n > = {\n partial: new Set(),\n final: new Set(),\n error: new Set(),\n };\n\n write(audio: Uint8Array): void {\n this.written.push(audio);\n }\n\n async end(): Promise<void> {\n this.ended++;\n }\n\n on(event: \"partial\", listener: (transcript: string) => void): void;\n on(event: \"final\", listener: (transcript: string) => void): void;\n on(event: \"error\", listener: (error: Error) => void): void;\n on(event: FakeSessionEvent, listener: (...args: any[]) => void): void {\n this.listeners[event].add(listener);\n }\n\n emitPartial(text: string): void {\n for (const listener of this.listeners.partial) listener(text);\n }\n\n emitFinal(text: string): void {\n for (const listener of this.listeners.final) listener(text);\n }\n\n emitError(error: Error): void {\n for (const listener of this.listeners.error) listener(error);\n }\n}\n\nexport class FakeTTS implements TTS {\n readonly requests: TTSRequest[] = [];\n private readonly controllers = new Set<AbortController>();\n\n constructor(private readonly chunksFor: (text: string) => Uint8Array[]) {}\n\n async *stream(request: TTSRequest): AsyncGenerator<Uint8Array> {\n this.requests.push(request);\n const controller = new AbortController();\n this.controllers.add(controller);\n try {\n for (const chunk of this.chunksFor(request.text)) {\n if (controller.signal.aborted) {\n throw new DOMException(\"The operation was aborted.\", \"AbortError\");\n }\n yield chunk;\n }\n } finally {\n this.controllers.delete(controller);\n }\n }\n\n stop(): void {\n for (const controller of this.controllers) controller.abort();\n }\n}\n\n/**\n * A TTS that streams one chunk at a time with a delay, so audio is still\n * mid-flight when an interrupt arrives.\n */\nexport class SlowTTS implements TTS {\n readonly requests: TTSRequest[] = [];\n private readonly controllers = new Set<AbortController>();\n\n constructor(\n private readonly chunksFor: (text: string) => Uint8Array[],\n private readonly delayMs = 20,\n ) {}\n\n async *stream(request: TTSRequest): AsyncGenerator<Uint8Array> {\n this.requests.push(request);\n const controller = new AbortController();\n this.controllers.add(controller);\n try {\n for (const chunk of this.chunksFor(request.text)) {\n await Bun.sleep(this.delayMs);\n if (controller.signal.aborted) {\n throw new DOMException(\"The operation was aborted.\", \"AbortError\");\n }\n yield chunk;\n }\n } finally {\n this.controllers.delete(controller);\n }\n }\n\n stop(): void {\n for (const controller of this.controllers) controller.abort();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Harness\n// ---------------------------------------------------------------------------\n\nexport type TtsHarness = FakeTTS | SlowTTS;\n\nexport interface Harness {\n conversation: Conversation;\n orchestrator: Orchestrator;\n llm: FakeLLM;\n stt: FakeSTT;\n tts: TtsHarness;\n persistence: MemoryPersistence;\n}\n\nexport function setup(options: {\n script: LLMScript;\n ttsChunks?: (text: string) => Uint8Array[];\n tts?: TtsHarness;\n tools?: Tool<never, unknown>[];\n toolTimeoutMs?: number;\n context?: string;\n /** Inject a real LLM (e.g. an adapter over a mocked fetch) instead of a scripted fake. */\n llm?: LLM;\n /** Override the conversation-history window (default 5 turns / 4k chars). */\n historyWindow?: HistoryWindow | false;\n}): Promise<Harness> {\n return (async () => {\n const persistence = new MemoryPersistence();\n const conversation = new Conversation({ id: \"conv-1\", persistence });\n const llm = options.llm ?? new FakeLLM(options.script);\n const stt = new FakeSTT();\n const tts =\n options.tts ??\n new FakeTTS(\n options.ttsChunks ?? ((text) => [new TextEncoder().encode(text)]),\n );\n const agent = new Agent({\n name: \"Jarvis\",\n context: options.context ?? \"Be concise.\",\n llm,\n tools: options.tools,\n });\n const orchestrator = new Orchestrator({\n conversation,\n agents: [agent],\n llm,\n stt,\n tts,\n persistence,\n toolTimeoutMs: options.toolTimeoutMs ?? 30_000,\n historyWindow: options.historyWindow,\n });\n\n conversation.start();\n await conversation.participate({ userId: \"alice\", aliases: [\"al\"] });\n await orchestrator.start();\n\n return {\n conversation,\n orchestrator,\n // When a real LLM is injected (the stall-recovery suite) it replaces\n // the fake; that suite never reads `.requests`, so the type stays the\n // fake's for the rest of the file.\n llm: llm as FakeLLM,\n stt,\n tts,\n persistence,\n };\n })();\n}\n\nexport async function waitFor(condition: () => boolean, timeoutMs = 2000): Promise<void> {\n const start = Date.now();\n while (!condition()) {\n if (Date.now() - start > timeoutMs) {\n throw new Error(\"waitFor timed out\");\n }\n await Bun.sleep(2);\n }\n}\n\nexport async function speak(harness: Harness, userId: string, text: string): Promise<void> {\n harness.conversation.listen({ userId, audio: new Uint8Array([1]) });\n harness.stt.sessions.at(-1)!.emitFinal(text);\n await harness.orchestrator.whenIdle();\n}\n\nexport function respond(text: string): LLMScript {\n return async function* () {\n yield { type: \"delta\", content: text };\n yield { type: \"done\" };\n };\n}\n\n// ---------------------------------------------------------------------------\n// Multi-agent roster harness (coordinator + named specialists)\n// ---------------------------------------------------------------------------\n\nexport type RosterHarness = Harness & { llms: Map<string, FakeLLM> };\n\nexport function setupRoster(options: {\n coordinatorScript: LLMScript;\n scripts: Record<string, LLMScript>;\n tools?: Record<string, Tool<never, unknown>[]>;\n coordinations?: Record<string, { prompt: string; llm: FakeLLM }>;\n maxCoordinationSteps?: number;\n}): Promise<RosterHarness> {\n return (async () => {\n const persistence = new MemoryPersistence();\n const conversation = new Conversation({ id: \"conv-1\", persistence });\n const stt = new FakeSTT();\n const tts = new FakeTTS((text) => [new TextEncoder().encode(text)]);\n\n const coordinatorLlm = new FakeLLM(options.coordinatorScript);\n const llms = new Map<string, FakeLLM>([[\"Jarvis\", coordinatorLlm]]);\n const agents: Agent[] = [\n new Agent({ name: \"Jarvis\", context: \"Be concise.\", llm: coordinatorLlm }),\n ];\n for (const [name, script] of Object.entries(options.scripts)) {\n const llm = new FakeLLM(script);\n llms.set(name, llm);\n agents.push(\n new Agent({\n name,\n context: `You are ${name}.`,\n llm,\n tools: options.tools?.[name],\n }),\n );\n }\n // The built-in `understand` coordination only activates with a roster of\n // more than one agent, so guarantee one for tests that only exercise the\n // coordination itself.\n if (agents.length === 1) {\n const helperLlm = new FakeLLM(respond(\"ok\"));\n llms.set(\"Helper\", helperLlm);\n agents.push(new Agent({ name: \"Helper\", context: \"You help.\", llm: helperLlm }));\n }\n for (const [name, coordination] of Object.entries(options.coordinations ?? {})) {\n llms.set(name, coordination.llm);\n }\n\n const orchestrator = new Orchestrator({\n conversation,\n agents,\n llm: coordinatorLlm,\n coordinations: options.coordinations,\n maxCoordinationSteps: options.maxCoordinationSteps,\n stt,\n tts,\n persistence,\n });\n\n conversation.start();\n await conversation.participate({ userId: \"alice\", aliases: [\"al\"] });\n await orchestrator.start();\n\n return { conversation, orchestrator, llm: coordinatorLlm, stt, tts, persistence, llms };\n })();\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["test_harness_exports", "__export", "FakeLLM", "FakeSTT", "FakeSTTSession", "FakeTTS", "SlowTTS", "respond", "setup", "setupRoster", "speak", "waitFor", "__toCommonJS", "import_agent", "import_tools", "import_conversation", "import_memory", "import_orchestrator", "FakeLLM", "script", "__name", "request", "controller", "event", "FakeSTT", "options", "session", "FakeSTTSession", "audio", "listener", "text", "error", "FakeTTS", "chunksFor", "chunk", "SlowTTS", "delayMs", "setup", "persistence", "conversation", "llm", "stt", "tts", "agent", "orchestrator", "waitFor", "condition", "timeoutMs", "start", "speak", "harness", "userId", "respond", "setupRoster", "coordinatorLlm", "llms", "agents", "name", "helperLlm", "coordination"]
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";var a=Object.defineProperty;var b=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var d=Object.prototype.hasOwnProperty;var p=(r,o,f,x)=>{if(o&&typeof o=="object"||typeof o=="function")for(let e of c(o))!d.call(r,e)&&e!==f&&a(r,e,{get:()=>o[e],enumerable:!(x=b(o,e))||x.enumerable});return r},t=(r,o,f)=>(p(r,o,"default"),f&&p(f,o,"default"));var g=r=>p(a({},"__esModule",{value:!0}),r);var m={};module.exports=g(m);t(m,require("./text-chunker.js"),module.exports);
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/conversations/orchestration/text-chunker/index.ts"],
4
+ "sourcesContent": ["export * from './text-chunker';\n"],
5
+ "mappings": "iaAAA,IAAAA,EAAA,kBAAAC,EAAAD,GAAAE,EAAAF,EAAc,0BAAd",
6
+ "names": ["text_chunker_exports", "__toCommonJS", "__reExport"]
7
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";var i=Object.defineProperty;var s=Object.getOwnPropertyDescriptor;var f=Object.getOwnPropertyNames;var g=Object.prototype.hasOwnProperty;var u=(e,t)=>i(e,"name",{value:t,configurable:!0});var a=(e,t)=>{for(var r in t)i(e,r,{get:t[r],enumerable:!0})},l=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let h of f(t))!g.call(e,h)&&h!==r&&i(e,h,{get:()=>t[h],enumerable:!(n=s(t,h))||n.enumerable});return e};var b=e=>l(i({},"__esModule",{value:!0}),e);var L={};a(L,{TextChunker:()=>c});module.exports=b(L);const o=new Set([".","!","?",`
2
+ `]),m=new Set([",",";",":"]);class c{static{u(this,"TextChunker")}targetLength;maxLength;minSoftLength;buffer="";constructor(t={}){this.targetLength=t.targetLength??80,this.maxLength=t.maxLength??140,this.minSoftLength=t.minSoftLength??40}push(t){this.buffer+=t;const r=[];for(;;){const n=this.takeNext();if(n===null)break;n.length>0&&r.push(n)}return r}flush(){const t=this.buffer.trim();return this.buffer="",t.length>0?t:null}clear(){this.buffer=""}takeNext(){if(this.buffer.length===0)return null;for(let t=0;t<this.buffer.length;t++)if(o.has(this.buffer[t]))return this.takeThrough(t);if(this.buffer.length>=this.targetLength){for(let t=this.buffer.length-1;t>=0;t--)if(m.has(this.buffer[t])){if(t+1>=this.minSoftLength)return this.takeThrough(t);break}}return this.buffer.length>=this.maxLength?this.takeThrough(this.maxLength-1):null}takeThrough(t){const r=this.buffer.slice(0,t+1).trim();return this.buffer=this.buffer.slice(t+1),r}}
3
+ //# sourceMappingURL=text-chunker.js.map