@recombine-ai/bosun 0.10.1 → 0.11.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 (423) hide show
  1. package/README.md +12 -0
  2. package/bin/bosun.js +3 -44
  3. package/build/client/_app/immutable/assets/0.CH-WU4JN.css +1 -0
  4. package/build/client/_app/immutable/assets/0.CH-WU4JN.css.br +0 -0
  5. package/build/client/_app/immutable/assets/0.CH-WU4JN.css.gz +0 -0
  6. package/build/client/_app/immutable/assets/{10.BX46PfEJ.css → 10.DIVePEYf.css} +1 -1
  7. package/build/client/_app/immutable/assets/10.DIVePEYf.css.br +0 -0
  8. package/build/client/_app/immutable/assets/10.DIVePEYf.css.gz +0 -0
  9. package/build/client/_app/immutable/chunks/{Dp760K13.js → 07xNIa59.js} +2 -2
  10. package/build/client/_app/immutable/chunks/07xNIa59.js.br +0 -0
  11. package/build/client/_app/immutable/chunks/07xNIa59.js.gz +0 -0
  12. package/build/client/_app/immutable/chunks/BDl2QuyN.js +1 -0
  13. package/build/client/_app/immutable/chunks/BDl2QuyN.js.br +0 -0
  14. package/build/client/_app/immutable/chunks/BDl2QuyN.js.gz +0 -0
  15. package/build/client/_app/immutable/chunks/{CqxCTxvJ.js → BI42X8h_.js} +1 -1
  16. package/build/client/_app/immutable/chunks/BI42X8h_.js.br +0 -0
  17. package/build/client/_app/immutable/chunks/BI42X8h_.js.gz +0 -0
  18. package/build/client/_app/immutable/chunks/BJTwdUYr.js +1 -0
  19. package/build/client/_app/immutable/chunks/BJTwdUYr.js.br +0 -0
  20. package/build/client/_app/immutable/chunks/BJTwdUYr.js.gz +0 -0
  21. package/build/client/_app/immutable/chunks/BLu86SbA.js +1 -0
  22. package/build/client/_app/immutable/chunks/BLu86SbA.js.br +0 -0
  23. package/build/client/_app/immutable/chunks/BLu86SbA.js.gz +0 -0
  24. package/build/client/_app/immutable/chunks/BNifnXkO.js +1 -0
  25. package/build/client/_app/immutable/chunks/BNifnXkO.js.br +2 -0
  26. package/build/client/_app/immutable/chunks/BNifnXkO.js.gz +0 -0
  27. package/build/client/_app/immutable/chunks/{BM0jKynj.js → BPNEONy5.js} +1 -1
  28. package/build/client/_app/immutable/chunks/BPNEONy5.js.br +0 -0
  29. package/build/client/_app/immutable/chunks/BPNEONy5.js.gz +0 -0
  30. package/build/client/_app/immutable/chunks/B_K7D6rX.js +2 -0
  31. package/build/client/_app/immutable/chunks/B_K7D6rX.js.br +0 -0
  32. package/build/client/_app/immutable/chunks/B_K7D6rX.js.gz +0 -0
  33. package/build/client/_app/immutable/chunks/Bj8jfBTi.js +1 -0
  34. package/build/client/_app/immutable/chunks/Bj8jfBTi.js.br +0 -0
  35. package/build/client/_app/immutable/chunks/Bj8jfBTi.js.gz +0 -0
  36. package/build/client/_app/immutable/chunks/BoPSJr4b.js +1 -0
  37. package/build/client/_app/immutable/chunks/BoPSJr4b.js.br +0 -0
  38. package/build/client/_app/immutable/chunks/BoPSJr4b.js.gz +0 -0
  39. package/build/client/_app/immutable/chunks/BsDZe4N6.js +1 -0
  40. package/build/client/_app/immutable/chunks/BsDZe4N6.js.br +0 -0
  41. package/build/client/_app/immutable/chunks/BsDZe4N6.js.gz +0 -0
  42. package/build/client/_app/immutable/chunks/{CXo2BVs0.js → Buo-57fF.js} +1 -1
  43. package/build/client/_app/immutable/chunks/Buo-57fF.js.br +0 -0
  44. package/build/client/_app/immutable/chunks/Buo-57fF.js.gz +0 -0
  45. package/build/client/_app/immutable/chunks/{C-whEtKd.js → C39ai1md.js} +1 -1
  46. package/build/client/_app/immutable/chunks/C39ai1md.js.br +0 -0
  47. package/build/client/_app/immutable/chunks/C39ai1md.js.gz +0 -0
  48. package/build/client/_app/immutable/chunks/C7he4XPB.js +1 -0
  49. package/build/client/_app/immutable/chunks/C7he4XPB.js.br +0 -0
  50. package/build/client/_app/immutable/chunks/C7he4XPB.js.gz +0 -0
  51. package/build/client/_app/immutable/chunks/{DYhTBLDc.js → CAjPRvNs.js} +2 -2
  52. package/build/client/_app/immutable/chunks/CAjPRvNs.js.br +0 -0
  53. package/build/client/_app/immutable/chunks/CAjPRvNs.js.gz +0 -0
  54. package/build/client/_app/immutable/chunks/CJYOmGlC.js +1 -0
  55. package/build/client/_app/immutable/chunks/CJYOmGlC.js.br +0 -0
  56. package/build/client/_app/immutable/chunks/CJYOmGlC.js.gz +0 -0
  57. package/build/client/_app/immutable/chunks/{CNLU4B3p.js → CMQRtcOV.js} +1 -1
  58. package/build/client/_app/immutable/chunks/CMQRtcOV.js.br +0 -0
  59. package/build/client/_app/immutable/chunks/CMQRtcOV.js.gz +0 -0
  60. package/build/client/_app/immutable/chunks/{HJHYLHDn.js → CPXdAKdv.js} +1 -1
  61. package/build/client/_app/immutable/chunks/CPXdAKdv.js.br +0 -0
  62. package/build/client/_app/immutable/chunks/CPXdAKdv.js.gz +0 -0
  63. package/build/client/_app/immutable/chunks/CVlsAO8k.js +11 -0
  64. package/build/client/_app/immutable/chunks/CVlsAO8k.js.br +0 -0
  65. package/build/client/_app/immutable/chunks/CVlsAO8k.js.gz +0 -0
  66. package/build/client/_app/immutable/chunks/{DNLcpWO_.js → CX0Ekq8t.js} +1 -1
  67. package/build/client/_app/immutable/chunks/CX0Ekq8t.js.br +0 -0
  68. package/build/client/_app/immutable/chunks/CX0Ekq8t.js.gz +0 -0
  69. package/build/client/_app/immutable/chunks/Ca197UDq.js +1 -0
  70. package/build/client/_app/immutable/chunks/Ca197UDq.js.br +0 -0
  71. package/build/client/_app/immutable/chunks/Ca197UDq.js.gz +0 -0
  72. package/build/client/_app/immutable/chunks/CaHl3dME.js +1 -0
  73. package/build/client/_app/immutable/chunks/CaHl3dME.js.br +0 -0
  74. package/build/client/_app/immutable/chunks/CaHl3dME.js.gz +0 -0
  75. package/build/client/_app/immutable/chunks/Cql_e8Of.js +1 -0
  76. package/build/client/_app/immutable/chunks/Cql_e8Of.js.br +2 -0
  77. package/build/client/_app/immutable/chunks/Cql_e8Of.js.gz +0 -0
  78. package/build/client/_app/immutable/chunks/{Dv8m1cTI.js → CxLomzuE.js} +1 -1
  79. package/build/client/_app/immutable/chunks/CxLomzuE.js.br +0 -0
  80. package/build/client/_app/immutable/chunks/{Dv8m1cTI.js.gz → CxLomzuE.js.gz} +0 -0
  81. package/build/client/_app/immutable/chunks/Cyai3SOj.js +1 -0
  82. package/build/client/_app/immutable/chunks/Cyai3SOj.js.br +0 -0
  83. package/build/client/_app/immutable/chunks/Cyai3SOj.js.gz +0 -0
  84. package/build/client/_app/immutable/chunks/{DTXUDKH5.js → CyvQWZoe.js} +4 -4
  85. package/build/client/_app/immutable/chunks/CyvQWZoe.js.br +0 -0
  86. package/build/client/_app/immutable/chunks/CyvQWZoe.js.gz +0 -0
  87. package/build/client/_app/immutable/chunks/CzXNWL4m.js +1 -0
  88. package/build/client/_app/immutable/chunks/CzXNWL4m.js.br +1 -0
  89. package/build/client/_app/immutable/chunks/CzXNWL4m.js.gz +0 -0
  90. package/build/client/_app/immutable/chunks/D-B5X35l.js +1 -0
  91. package/build/client/_app/immutable/chunks/D-B5X35l.js.br +0 -0
  92. package/build/client/_app/immutable/chunks/D-B5X35l.js.gz +0 -0
  93. package/build/client/_app/immutable/chunks/DJriQKD9.js +2 -0
  94. package/build/client/_app/immutable/chunks/DJriQKD9.js.br +0 -0
  95. package/build/client/_app/immutable/chunks/DJriQKD9.js.gz +0 -0
  96. package/build/client/_app/immutable/chunks/DXUXXCDA.js +1 -0
  97. package/build/client/_app/immutable/chunks/DXUXXCDA.js.br +0 -0
  98. package/build/client/_app/immutable/chunks/DXUXXCDA.js.gz +0 -0
  99. package/build/client/_app/immutable/chunks/{CZLNSMhF.js → Dslf9OwW.js} +10 -10
  100. package/build/client/_app/immutable/chunks/Dslf9OwW.js.br +0 -0
  101. package/build/client/_app/immutable/chunks/Dslf9OwW.js.gz +0 -0
  102. package/build/client/_app/immutable/chunks/QpaC6J6s.js +1 -0
  103. package/build/client/_app/immutable/chunks/QpaC6J6s.js.br +0 -0
  104. package/build/client/_app/immutable/chunks/QpaC6J6s.js.gz +0 -0
  105. package/build/client/_app/immutable/chunks/{HXxIsSOO.js → iAhzu4tv.js} +1 -1
  106. package/build/client/_app/immutable/chunks/iAhzu4tv.js.br +0 -0
  107. package/build/client/_app/immutable/chunks/iAhzu4tv.js.gz +0 -0
  108. package/build/client/_app/immutable/chunks/i_5fJYKS.js +3 -0
  109. package/build/client/_app/immutable/chunks/i_5fJYKS.js.br +0 -0
  110. package/build/client/_app/immutable/chunks/i_5fJYKS.js.gz +0 -0
  111. package/build/client/_app/immutable/chunks/{CF66fWJN.js → nYD9wsyN.js} +1 -1
  112. package/build/client/_app/immutable/chunks/nYD9wsyN.js.br +0 -0
  113. package/build/client/_app/immutable/chunks/nYD9wsyN.js.gz +0 -0
  114. package/build/client/_app/immutable/chunks/{BIpSIzUr.js → uLGP0py1.js} +1 -1
  115. package/build/client/_app/immutable/chunks/uLGP0py1.js.br +0 -0
  116. package/build/client/_app/immutable/chunks/uLGP0py1.js.gz +0 -0
  117. package/build/client/_app/immutable/entry/app.Cr7CMG-3.js +2 -0
  118. package/build/client/_app/immutable/entry/app.Cr7CMG-3.js.br +0 -0
  119. package/build/client/_app/immutable/entry/app.Cr7CMG-3.js.gz +0 -0
  120. package/build/client/_app/immutable/entry/start.CDNd0Bml.js +1 -0
  121. package/build/client/_app/immutable/entry/start.CDNd0Bml.js.br +2 -0
  122. package/build/client/_app/immutable/entry/start.CDNd0Bml.js.gz +0 -0
  123. package/build/client/_app/immutable/nodes/{0.BCmKHiYo.js → 0.AyqKXI2h.js} +2 -2
  124. package/build/client/_app/immutable/nodes/0.AyqKXI2h.js.br +0 -0
  125. package/build/client/_app/immutable/nodes/0.AyqKXI2h.js.gz +0 -0
  126. package/build/client/_app/immutable/nodes/1.BRmfm-nN.js +1 -0
  127. package/build/client/_app/immutable/nodes/1.BRmfm-nN.js.br +0 -0
  128. package/build/client/_app/immutable/nodes/1.BRmfm-nN.js.gz +0 -0
  129. package/build/client/_app/immutable/nodes/10.D03jjkr4.js +7 -0
  130. package/build/client/_app/immutable/nodes/10.D03jjkr4.js.br +0 -0
  131. package/build/client/_app/immutable/nodes/10.D03jjkr4.js.gz +0 -0
  132. package/build/client/_app/immutable/nodes/{15.Wmhj7gOy.js → 15.BFy4oAT6.js} +1 -1
  133. package/build/client/_app/immutable/nodes/15.BFy4oAT6.js.br +0 -0
  134. package/build/client/_app/immutable/nodes/15.BFy4oAT6.js.gz +0 -0
  135. package/build/client/_app/immutable/nodes/17.BOYU_WTT.js +3 -0
  136. package/build/client/_app/immutable/nodes/17.BOYU_WTT.js.br +0 -0
  137. package/build/client/_app/immutable/nodes/17.BOYU_WTT.js.gz +0 -0
  138. package/build/client/_app/immutable/nodes/18.Ddx80a4f.js +11 -0
  139. package/build/client/_app/immutable/nodes/18.Ddx80a4f.js.br +0 -0
  140. package/build/client/_app/immutable/nodes/18.Ddx80a4f.js.gz +0 -0
  141. package/build/client/_app/immutable/nodes/{2.BdQ4KFOK.js → 2.CZEboQjo.js} +20 -20
  142. package/build/client/_app/immutable/nodes/2.CZEboQjo.js.br +0 -0
  143. package/build/client/_app/immutable/nodes/2.CZEboQjo.js.gz +0 -0
  144. package/build/client/_app/immutable/nodes/3.dAV7FviN.js +1 -0
  145. package/build/client/_app/immutable/nodes/3.dAV7FviN.js.br +0 -0
  146. package/build/client/_app/immutable/nodes/3.dAV7FviN.js.gz +0 -0
  147. package/build/client/_app/immutable/nodes/4.Cm_vMAEA.js +1 -0
  148. package/build/client/_app/immutable/nodes/4.Cm_vMAEA.js.br +0 -0
  149. package/build/client/_app/immutable/nodes/4.Cm_vMAEA.js.gz +0 -0
  150. package/build/client/_app/immutable/nodes/5.DPWuTlaI.js +1 -0
  151. package/build/client/_app/immutable/nodes/5.DPWuTlaI.js.br +0 -0
  152. package/build/client/_app/immutable/nodes/5.DPWuTlaI.js.gz +0 -0
  153. package/build/client/_app/immutable/nodes/6.DY-NLaRW.js +1 -0
  154. package/build/client/_app/immutable/nodes/6.DY-NLaRW.js.br +0 -0
  155. package/build/client/_app/immutable/nodes/6.DY-NLaRW.js.gz +0 -0
  156. package/build/client/_app/immutable/nodes/{8.DWNYX1kH.js → 8.Chuqhf8W.js} +1 -1
  157. package/build/client/_app/immutable/nodes/8.Chuqhf8W.js.br +0 -0
  158. package/build/client/_app/immutable/nodes/8.Chuqhf8W.js.gz +0 -0
  159. package/build/client/_app/immutable/nodes/9.BOEM8f6B.js +2 -0
  160. package/build/client/_app/immutable/nodes/9.BOEM8f6B.js.br +0 -0
  161. package/build/client/_app/immutable/nodes/9.BOEM8f6B.js.gz +0 -0
  162. package/build/client/_app/version.json +1 -1
  163. package/build/client/_app/version.json.br +0 -0
  164. package/build/client/_app/version.json.gz +0 -0
  165. package/build/server/chunks/0-TQkJBtAu.js +9 -0
  166. package/build/server/chunks/0-TQkJBtAu.js.map +1 -0
  167. package/build/server/chunks/1-CKxKlw1l.js +9 -0
  168. package/build/server/chunks/{1-C1mGPV-S.js.map → 1-CKxKlw1l.js.map} +1 -1
  169. package/build/server/chunks/10-Bly5Nk7M.js +9 -0
  170. package/build/server/chunks/10-Bly5Nk7M.js.map +1 -0
  171. package/build/server/chunks/{15-CZBxPMAc.js → 15-BMEAVslz.js} +2 -2
  172. package/build/server/chunks/{15-CZBxPMAc.js.map → 15-BMEAVslz.js.map} +1 -1
  173. package/build/server/chunks/17-C8CYQOYP.js +9 -0
  174. package/build/server/chunks/17-C8CYQOYP.js.map +1 -0
  175. package/build/server/chunks/18-CtXVGBbS.js +9 -0
  176. package/build/server/chunks/18-CtXVGBbS.js.map +1 -0
  177. package/build/server/chunks/2-DvD0dAh0.js +9 -0
  178. package/build/server/chunks/2-DvD0dAh0.js.map +1 -0
  179. package/build/server/chunks/3-DBzpRDK8.js +9 -0
  180. package/build/server/chunks/3-DBzpRDK8.js.map +1 -0
  181. package/build/server/chunks/4-BUNytyC2.js +9 -0
  182. package/build/server/chunks/4-BUNytyC2.js.map +1 -0
  183. package/build/server/chunks/5-DNo8_tFS.js +9 -0
  184. package/build/server/chunks/{5-DblV-OAd.js.map → 5-DNo8_tFS.js.map} +1 -1
  185. package/build/server/chunks/6-DUMdIfbf.js +9 -0
  186. package/build/server/chunks/6-DUMdIfbf.js.map +1 -0
  187. package/build/server/chunks/8-DxTJ555u.js +9 -0
  188. package/build/server/chunks/8-DxTJ555u.js.map +1 -0
  189. package/build/server/chunks/9-B4-5k50d.js +9 -0
  190. package/build/server/chunks/9-B4-5k50d.js.map +1 -0
  191. package/build/server/chunks/{AgentSidebar-XdGj1sqT.js → AgentSidebar-DvIlda-E.js} +5 -6
  192. package/build/server/chunks/AgentSidebar-DvIlda-E.js.map +1 -0
  193. package/build/server/chunks/{Button-Dsy3QY7B.js → Button-BLigKkGG.js} +2 -2
  194. package/build/server/chunks/Button-BLigKkGG.js.map +1 -0
  195. package/build/server/chunks/{ChatStepTrace-1q74tVYO.js → ChatStepTrace-CqqIjRLU.js} +47 -11
  196. package/build/server/chunks/ChatStepTrace-CqqIjRLU.js.map +1 -0
  197. package/build/server/chunks/{Input-CHFlfduw.js → Input-OdQKNdS6.js} +1 -2
  198. package/build/server/chunks/Input-OdQKNdS6.js.map +1 -0
  199. package/build/server/chunks/MockGenerator-GEpXTgX0.js +117 -0
  200. package/build/server/chunks/MockGenerator-GEpXTgX0.js.map +1 -0
  201. package/build/server/chunks/Modal-DtVsRmmO.js.map +1 -1
  202. package/build/server/chunks/{_layout.svelte-DJ4kDgDL.js → _layout.svelte-B-CkD4a0.js} +14 -8
  203. package/build/server/chunks/_layout.svelte-B-CkD4a0.js.map +1 -0
  204. package/build/server/chunks/{_layout.svelte-B2lwUacy.js → _layout.svelte-BBFCF-xw.js} +8 -4
  205. package/build/server/chunks/_layout.svelte-BBFCF-xw.js.map +1 -0
  206. package/build/server/chunks/{_layout.svelte-C7JgNCIu.js → _layout.svelte-cPhmW5bZ.js} +3 -1
  207. package/build/server/chunks/_layout.svelte-cPhmW5bZ.js.map +1 -0
  208. package/build/server/chunks/{_page.svelte-FufhMKh4.js → _page.svelte-0J2xaeyC.js} +71 -16
  209. package/build/server/chunks/_page.svelte-0J2xaeyC.js.map +1 -0
  210. package/build/server/chunks/{_page.svelte-BpRksNEG.js → _page.svelte-BgoX8Y6N.js} +2 -2
  211. package/build/server/chunks/{_page.svelte-BpRksNEG.js.map → _page.svelte-BgoX8Y6N.js.map} +1 -1
  212. package/build/server/chunks/{_page.svelte-GaxktsuT.js → _page.svelte-C_S_qUgZ.js} +480 -72
  213. package/build/server/chunks/_page.svelte-C_S_qUgZ.js.map +1 -0
  214. package/build/server/chunks/{_page.svelte-DDpBtd3X.js → _page.svelte-CqGOvPRO.js} +3 -4
  215. package/build/server/chunks/_page.svelte-CqGOvPRO.js.map +1 -0
  216. package/build/server/chunks/{_page.svelte-CA3-vgl2.js → _page.svelte-Cxh9_vUl.js} +151 -100
  217. package/build/server/chunks/_page.svelte-Cxh9_vUl.js.map +1 -0
  218. package/build/server/chunks/_page.svelte-zOI_s_3J.js +2151 -0
  219. package/build/server/chunks/_page.svelte-zOI_s_3J.js.map +1 -0
  220. package/build/server/chunks/agents-context-rV2narXG.js.map +1 -1
  221. package/build/server/chunks/conversation-view-memory-BZguFlTt.js +20 -0
  222. package/build/server/chunks/conversation-view-memory-BZguFlTt.js.map +1 -0
  223. package/build/server/chunks/edit-workspace-context-B1nYQ5hD.js.map +1 -1
  224. package/build/server/chunks/index-CSpGrMM2.js.map +1 -1
  225. package/build/server/chunks/{client-DzvEkq51.js → source-selection-CcN1cgXc.js} +122 -117
  226. package/build/server/chunks/source-selection-CcN1cgXc.js.map +1 -0
  227. package/build/server/index.js +1 -1
  228. package/build/server/index.js.map +1 -1
  229. package/build/server/manifest.js +14 -14
  230. package/build/server/manifest.js.map +1 -1
  231. package/package.json +4 -4
  232. package/src/backend/lib/get-agent-factories.spec.ts +59 -0
  233. package/src/backend/lib/get-agent-factories.ts +31 -1
  234. package/src/backend/lib/voice-agent-lifecycle.test.ts +31 -0
  235. package/src/backend/lib/voice-agent-lifecycle.ts +16 -0
  236. package/src/backend/roleplay/agents.ts +189 -69
  237. package/src/backend/roleplay/message-dispatcher.ts +0 -7
  238. package/src/backend/roleplay/router.ts +14 -17
  239. package/src/backend/roleplay/trace-serialization.spec.ts +35 -0
  240. package/src/backend/roleplay/trace-serialization.ts +57 -0
  241. package/src/backend/roleplay/variants.ts +33 -49
  242. package/src/backend/tests/academy.ts +202 -100
  243. package/src/backend/tests/analyze.ts +0 -3
  244. package/src/backend/tests/data.spec.ts +139 -0
  245. package/src/backend/tests/data.ts +452 -68
  246. package/src/backend/tests/emulate-agents.ts +60 -44
  247. package/src/backend/tests/openai-prompt-cache.ts +68 -0
  248. package/src/backend/tests/promptfoo-runtime.spec.ts +41 -0
  249. package/src/backend/tests/promptfoo-runtime.ts +27 -0
  250. package/src/backend/tests/report-files.spec.ts +42 -0
  251. package/src/backend/tests/report-files.ts +101 -0
  252. package/src/backend/tests/router.ts +28 -2
  253. package/src/backend/tests/suite.ts +13 -4
  254. package/build/client/_app/immutable/assets/0.B4t3dozz.css +0 -1
  255. package/build/client/_app/immutable/assets/0.B4t3dozz.css.br +0 -0
  256. package/build/client/_app/immutable/assets/0.B4t3dozz.css.gz +0 -0
  257. package/build/client/_app/immutable/assets/10.BX46PfEJ.css.br +0 -0
  258. package/build/client/_app/immutable/assets/10.BX46PfEJ.css.gz +0 -0
  259. package/build/client/_app/immutable/chunks/7E8m6dwk.js +0 -1
  260. package/build/client/_app/immutable/chunks/7E8m6dwk.js.br +0 -0
  261. package/build/client/_app/immutable/chunks/7E8m6dwk.js.gz +0 -0
  262. package/build/client/_app/immutable/chunks/7qRqthsa.js +0 -1
  263. package/build/client/_app/immutable/chunks/7qRqthsa.js.br +0 -2
  264. package/build/client/_app/immutable/chunks/7qRqthsa.js.gz +0 -0
  265. package/build/client/_app/immutable/chunks/Ajb1KYIn.js +0 -1
  266. package/build/client/_app/immutable/chunks/Ajb1KYIn.js.br +0 -0
  267. package/build/client/_app/immutable/chunks/Ajb1KYIn.js.gz +0 -0
  268. package/build/client/_app/immutable/chunks/B0iEglSe.js +0 -1
  269. package/build/client/_app/immutable/chunks/B0iEglSe.js.br +0 -0
  270. package/build/client/_app/immutable/chunks/B0iEglSe.js.gz +0 -0
  271. package/build/client/_app/immutable/chunks/BIpSIzUr.js.br +0 -0
  272. package/build/client/_app/immutable/chunks/BIpSIzUr.js.gz +0 -0
  273. package/build/client/_app/immutable/chunks/BM0jKynj.js.br +0 -0
  274. package/build/client/_app/immutable/chunks/BM0jKynj.js.gz +0 -0
  275. package/build/client/_app/immutable/chunks/BTvePR6r.js +0 -1
  276. package/build/client/_app/immutable/chunks/BTvePR6r.js.br +0 -2
  277. package/build/client/_app/immutable/chunks/BTvePR6r.js.gz +0 -0
  278. package/build/client/_app/immutable/chunks/Bcu62lFq.js +0 -1
  279. package/build/client/_app/immutable/chunks/Bcu62lFq.js.br +0 -0
  280. package/build/client/_app/immutable/chunks/Bcu62lFq.js.gz +0 -0
  281. package/build/client/_app/immutable/chunks/BwtfALfL.js +0 -11
  282. package/build/client/_app/immutable/chunks/BwtfALfL.js.br +0 -0
  283. package/build/client/_app/immutable/chunks/BwtfALfL.js.gz +0 -0
  284. package/build/client/_app/immutable/chunks/BxsDwlgp.js +0 -4
  285. package/build/client/_app/immutable/chunks/BxsDwlgp.js.br +0 -0
  286. package/build/client/_app/immutable/chunks/BxsDwlgp.js.gz +0 -0
  287. package/build/client/_app/immutable/chunks/C-whEtKd.js.br +0 -2
  288. package/build/client/_app/immutable/chunks/C-whEtKd.js.gz +0 -0
  289. package/build/client/_app/immutable/chunks/C1WqE8CP.js +0 -1
  290. package/build/client/_app/immutable/chunks/C1WqE8CP.js.br +0 -2
  291. package/build/client/_app/immutable/chunks/C1WqE8CP.js.gz +0 -0
  292. package/build/client/_app/immutable/chunks/C4D-JXnS.js +0 -1
  293. package/build/client/_app/immutable/chunks/C4D-JXnS.js.br +0 -0
  294. package/build/client/_app/immutable/chunks/C4D-JXnS.js.gz +0 -0
  295. package/build/client/_app/immutable/chunks/C4SnSfql.js +0 -1
  296. package/build/client/_app/immutable/chunks/C4SnSfql.js.br +0 -0
  297. package/build/client/_app/immutable/chunks/C4SnSfql.js.gz +0 -0
  298. package/build/client/_app/immutable/chunks/CF66fWJN.js.br +0 -0
  299. package/build/client/_app/immutable/chunks/CF66fWJN.js.gz +0 -0
  300. package/build/client/_app/immutable/chunks/CNLU4B3p.js.br +0 -0
  301. package/build/client/_app/immutable/chunks/CNLU4B3p.js.gz +0 -0
  302. package/build/client/_app/immutable/chunks/CXo2BVs0.js.br +0 -0
  303. package/build/client/_app/immutable/chunks/CXo2BVs0.js.gz +0 -0
  304. package/build/client/_app/immutable/chunks/CZLNSMhF.js.br +0 -0
  305. package/build/client/_app/immutable/chunks/CZLNSMhF.js.gz +0 -0
  306. package/build/client/_app/immutable/chunks/CqO5tR2_.js +0 -1
  307. package/build/client/_app/immutable/chunks/CqO5tR2_.js.br +0 -0
  308. package/build/client/_app/immutable/chunks/CqO5tR2_.js.gz +0 -0
  309. package/build/client/_app/immutable/chunks/CqxCTxvJ.js.br +0 -0
  310. package/build/client/_app/immutable/chunks/CqxCTxvJ.js.gz +0 -0
  311. package/build/client/_app/immutable/chunks/D-wf2QNc.js +0 -1
  312. package/build/client/_app/immutable/chunks/D-wf2QNc.js.br +0 -0
  313. package/build/client/_app/immutable/chunks/D-wf2QNc.js.gz +0 -0
  314. package/build/client/_app/immutable/chunks/D4obUD_s.js +0 -1
  315. package/build/client/_app/immutable/chunks/D4obUD_s.js.br +0 -0
  316. package/build/client/_app/immutable/chunks/D4obUD_s.js.gz +0 -0
  317. package/build/client/_app/immutable/chunks/D8e7SQh9.js +0 -1
  318. package/build/client/_app/immutable/chunks/D8e7SQh9.js.br +0 -0
  319. package/build/client/_app/immutable/chunks/D8e7SQh9.js.gz +0 -0
  320. package/build/client/_app/immutable/chunks/DNLcpWO_.js.br +0 -0
  321. package/build/client/_app/immutable/chunks/DNLcpWO_.js.gz +0 -0
  322. package/build/client/_app/immutable/chunks/DTXUDKH5.js.br +0 -0
  323. package/build/client/_app/immutable/chunks/DTXUDKH5.js.gz +0 -0
  324. package/build/client/_app/immutable/chunks/DYhTBLDc.js.br +0 -0
  325. package/build/client/_app/immutable/chunks/DYhTBLDc.js.gz +0 -0
  326. package/build/client/_app/immutable/chunks/DhBm2Vx9.js +0 -1
  327. package/build/client/_app/immutable/chunks/DhBm2Vx9.js.br +0 -0
  328. package/build/client/_app/immutable/chunks/DhBm2Vx9.js.gz +0 -0
  329. package/build/client/_app/immutable/chunks/Dp760K13.js.br +0 -0
  330. package/build/client/_app/immutable/chunks/Dp760K13.js.gz +0 -0
  331. package/build/client/_app/immutable/chunks/Dv0gjm25.js +0 -1
  332. package/build/client/_app/immutable/chunks/Dv0gjm25.js.br +0 -0
  333. package/build/client/_app/immutable/chunks/Dv0gjm25.js.gz +0 -0
  334. package/build/client/_app/immutable/chunks/Dv8m1cTI.js.br +0 -0
  335. package/build/client/_app/immutable/chunks/HJHYLHDn.js.br +0 -0
  336. package/build/client/_app/immutable/chunks/HJHYLHDn.js.gz +0 -0
  337. package/build/client/_app/immutable/chunks/HXxIsSOO.js.br +0 -0
  338. package/build/client/_app/immutable/chunks/HXxIsSOO.js.gz +0 -0
  339. package/build/client/_app/immutable/chunks/_yZg6Sf-.js +0 -2
  340. package/build/client/_app/immutable/chunks/_yZg6Sf-.js.br +0 -0
  341. package/build/client/_app/immutable/chunks/_yZg6Sf-.js.gz +0 -0
  342. package/build/client/_app/immutable/chunks/xebNt8-Z.js +0 -1
  343. package/build/client/_app/immutable/chunks/xebNt8-Z.js.br +0 -0
  344. package/build/client/_app/immutable/chunks/xebNt8-Z.js.gz +0 -0
  345. package/build/client/_app/immutable/entry/app.C4wJtvtH.js +0 -2
  346. package/build/client/_app/immutable/entry/app.C4wJtvtH.js.br +0 -0
  347. package/build/client/_app/immutable/entry/app.C4wJtvtH.js.gz +0 -0
  348. package/build/client/_app/immutable/entry/start.BId2vqhS.js +0 -1
  349. package/build/client/_app/immutable/entry/start.BId2vqhS.js.br +0 -2
  350. package/build/client/_app/immutable/entry/start.BId2vqhS.js.gz +0 -0
  351. package/build/client/_app/immutable/nodes/0.BCmKHiYo.js.br +0 -0
  352. package/build/client/_app/immutable/nodes/0.BCmKHiYo.js.gz +0 -0
  353. package/build/client/_app/immutable/nodes/1.8skEZBEw.js +0 -1
  354. package/build/client/_app/immutable/nodes/1.8skEZBEw.js.br +0 -0
  355. package/build/client/_app/immutable/nodes/1.8skEZBEw.js.gz +0 -0
  356. package/build/client/_app/immutable/nodes/10.YgmBfSWN.js +0 -5
  357. package/build/client/_app/immutable/nodes/10.YgmBfSWN.js.br +0 -0
  358. package/build/client/_app/immutable/nodes/10.YgmBfSWN.js.gz +0 -0
  359. package/build/client/_app/immutable/nodes/15.Wmhj7gOy.js.br +0 -0
  360. package/build/client/_app/immutable/nodes/15.Wmhj7gOy.js.gz +0 -0
  361. package/build/client/_app/immutable/nodes/17.D8ydco6g.js +0 -3
  362. package/build/client/_app/immutable/nodes/17.D8ydco6g.js.br +0 -0
  363. package/build/client/_app/immutable/nodes/17.D8ydco6g.js.gz +0 -0
  364. package/build/client/_app/immutable/nodes/18.C67CqGm5.js +0 -11
  365. package/build/client/_app/immutable/nodes/18.C67CqGm5.js.br +0 -0
  366. package/build/client/_app/immutable/nodes/18.C67CqGm5.js.gz +0 -0
  367. package/build/client/_app/immutable/nodes/2.BdQ4KFOK.js.br +0 -0
  368. package/build/client/_app/immutable/nodes/2.BdQ4KFOK.js.gz +0 -0
  369. package/build/client/_app/immutable/nodes/3.nCmkz6kS.js +0 -1
  370. package/build/client/_app/immutable/nodes/3.nCmkz6kS.js.br +0 -0
  371. package/build/client/_app/immutable/nodes/3.nCmkz6kS.js.gz +0 -0
  372. package/build/client/_app/immutable/nodes/4.DAwO0_Am.js +0 -1
  373. package/build/client/_app/immutable/nodes/4.DAwO0_Am.js.br +0 -0
  374. package/build/client/_app/immutable/nodes/4.DAwO0_Am.js.gz +0 -0
  375. package/build/client/_app/immutable/nodes/5.C_SvvZjG.js +0 -1
  376. package/build/client/_app/immutable/nodes/5.C_SvvZjG.js.br +0 -0
  377. package/build/client/_app/immutable/nodes/5.C_SvvZjG.js.gz +0 -0
  378. package/build/client/_app/immutable/nodes/6.DfOe9lph.js +0 -1
  379. package/build/client/_app/immutable/nodes/6.DfOe9lph.js.br +0 -0
  380. package/build/client/_app/immutable/nodes/6.DfOe9lph.js.gz +0 -0
  381. package/build/client/_app/immutable/nodes/8.DWNYX1kH.js.br +0 -0
  382. package/build/client/_app/immutable/nodes/8.DWNYX1kH.js.gz +0 -0
  383. package/build/client/_app/immutable/nodes/9.D7SG4T7Z.js +0 -2
  384. package/build/client/_app/immutable/nodes/9.D7SG4T7Z.js.br +0 -0
  385. package/build/client/_app/immutable/nodes/9.D7SG4T7Z.js.gz +0 -0
  386. package/build/server/chunks/0-D5BNSI7t.js +0 -9
  387. package/build/server/chunks/0-D5BNSI7t.js.map +0 -1
  388. package/build/server/chunks/1-C1mGPV-S.js +0 -9
  389. package/build/server/chunks/10-BUo1e_HG.js +0 -9
  390. package/build/server/chunks/10-BUo1e_HG.js.map +0 -1
  391. package/build/server/chunks/17-iNFqG1My.js +0 -9
  392. package/build/server/chunks/17-iNFqG1My.js.map +0 -1
  393. package/build/server/chunks/18-u8T5X6fM.js +0 -9
  394. package/build/server/chunks/18-u8T5X6fM.js.map +0 -1
  395. package/build/server/chunks/2-tLlSByHA.js +0 -9
  396. package/build/server/chunks/2-tLlSByHA.js.map +0 -1
  397. package/build/server/chunks/3-D1KY9yVZ.js +0 -9
  398. package/build/server/chunks/3-D1KY9yVZ.js.map +0 -1
  399. package/build/server/chunks/4-7zu0cJha.js +0 -9
  400. package/build/server/chunks/4-7zu0cJha.js.map +0 -1
  401. package/build/server/chunks/5-DblV-OAd.js +0 -9
  402. package/build/server/chunks/6-BDC5budM.js +0 -9
  403. package/build/server/chunks/6-BDC5budM.js.map +0 -1
  404. package/build/server/chunks/8-DhmD-opq.js +0 -9
  405. package/build/server/chunks/8-DhmD-opq.js.map +0 -1
  406. package/build/server/chunks/9-BGj28GI6.js +0 -9
  407. package/build/server/chunks/9-BGj28GI6.js.map +0 -1
  408. package/build/server/chunks/AgentSidebar-XdGj1sqT.js.map +0 -1
  409. package/build/server/chunks/Button-Dsy3QY7B.js.map +0 -1
  410. package/build/server/chunks/ChatStepTrace-1q74tVYO.js.map +0 -1
  411. package/build/server/chunks/Input-CHFlfduw.js.map +0 -1
  412. package/build/server/chunks/_layout.svelte-B2lwUacy.js.map +0 -1
  413. package/build/server/chunks/_layout.svelte-C7JgNCIu.js.map +0 -1
  414. package/build/server/chunks/_layout.svelte-DJ4kDgDL.js.map +0 -1
  415. package/build/server/chunks/_page.svelte-Bl1WcAXy.js +0 -671
  416. package/build/server/chunks/_page.svelte-Bl1WcAXy.js.map +0 -1
  417. package/build/server/chunks/_page.svelte-CA3-vgl2.js.map +0 -1
  418. package/build/server/chunks/_page.svelte-DDpBtd3X.js.map +0 -1
  419. package/build/server/chunks/_page.svelte-FufhMKh4.js.map +0 -1
  420. package/build/server/chunks/_page.svelte-GaxktsuT.js.map +0 -1
  421. package/build/server/chunks/client-DzvEkq51.js.map +0 -1
  422. package/build/server/chunks/source-selection-eA--VEKo.js +0 -124
  423. package/build/server/chunks/source-selection-eA--VEKo.js.map +0 -1
@@ -24,6 +24,8 @@ import { createStepRegistry } from './step-registry'
24
24
  import { getAgentFactories } from '../lib/get-agent-factories'
25
25
  import { getImportNonce } from '../lib/import-nonce'
26
26
  import { getRootPath } from '../lib/get-root-path'
27
+ import { sendCallStartMessage } from '../lib/voice-agent-lifecycle'
28
+ import { normalizeTracePayload } from './trace-serialization'
27
29
 
28
30
  interface MessageEntry {
29
31
  type: 'message'
@@ -136,7 +138,7 @@ export function createAgents(
136
138
  lastLoadedImportNonce = importNonce
137
139
  basePath = loaded.basePath
138
140
  factories = loaded.factories
139
- console.log(`createAgents, load; loaded agents: ${Object.keys(factories)}`)
141
+ console.log(`createAgents, load; loaded agents: ${Object.keys(factories).join(', ')}`)
140
142
  await dispatcher.sendLoaded(Object.keys(factories))
141
143
  },
142
144
  reload: async () => {
@@ -156,7 +158,7 @@ export function createAgents(
156
158
  currentRegion = region || null
157
159
  const agent = await getCurrentAgent()
158
160
 
159
- dispatcher.sendAgentSelected({
161
+ await dispatcher.sendAgentSelected({
160
162
  id: agentId,
161
163
  type: isVoiceAgent(agent.agent) ? 'voice' : 'text',
162
164
  steps: await Promise.all(
@@ -174,7 +176,7 @@ export function createAgents(
174
176
  if (agent.ctx.get()) {
175
177
  const context = agent.ctx.get()
176
178
  const promptContext = agent.ctx.getPromptContextMapper()(context)
177
- dispatcher.sendContext(context, promptContext)
179
+ await dispatcher.sendContext(context, promptContext)
178
180
  }
179
181
 
180
182
  const rawStates = agentStates[getAgentCacheKey(agentId, currentRegion)]
@@ -185,7 +187,7 @@ export function createAgents(
185
187
  isInitialLoad = true
186
188
  }
187
189
  currentStateId = stateId ?? null
188
- dispatcher.sendUpdateStates(
190
+ await dispatcher.sendUpdateStates(
189
191
  states.map((state) => ({
190
192
  id: state.id,
191
193
  name: state.name,
@@ -209,12 +211,11 @@ export function createAgents(
209
211
  await (await getCurrentAgent()).triggerAction(action)
210
212
  },
211
213
  handleMessage: async (message: Message) => {
212
- await dispatcher.sendMessage(message) // echo message
213
214
  currentStateId = await (await getCurrentAgent()).handleMessage(message)
214
215
  },
215
216
  hangup: async (agentId: string, region: string | null) => {
216
217
  const cacheKey = getAgentCacheKey(agentId, region)
217
- let agent = agents[cacheKey]
218
+ const agent = agents[cacheKey]
218
219
  if (!agent) {
219
220
  throw new Error(`Cannot hangup: cannot find agent: ${cacheKey}`)
220
221
  }
@@ -250,62 +251,74 @@ export async function loadAgent(props: LoadProps) {
250
251
  ctx.subscribe((context) => {
251
252
  console.log('------ context updated --------')
252
253
  const promptContext = ctx.getPromptContextMapper()(context)
253
- props.sendContext(context, promptContext)
254
+ void props.sendContext(context, promptContext)
254
255
  })
255
256
  const logger = createLogger((msg) => {
256
257
  state.history.push({
257
258
  type: 'log',
258
259
  payload: msg
259
260
  })
260
- props.sendLog(msg)
261
+ void props.sendLog(msg)
261
262
  })
262
263
 
263
264
  const stepTracer: StepTracer = {
264
265
  addStepTrace: (stepTrace) => {
266
+ const normalizedTrace = normalizeTracePayload(stepTrace)
265
267
  state.history.push({
266
268
  type: 'trace',
267
- payload: stepTrace
269
+ payload: normalizedTrace
268
270
  })
269
- props.sendTrace(stepTrace)
271
+ void props.sendTrace(normalizedTrace)
270
272
  },
271
273
  async flush() {}
272
274
  }
273
275
 
274
276
  const apiCallTracer: ApiCallTracer = {
275
277
  addApiCallTrace: (apiCallTrace) => {
278
+ const normalizedTrace = normalizeTracePayload(apiCallTrace)
276
279
  logger.log(
277
280
  '[apiCallTracer] addApiCallTrace',
278
- apiCallTrace?.operationName,
279
- apiCallTrace?.method,
280
- apiCallTrace?.path
281
+ normalizedTrace?.operationName,
282
+ normalizedTrace?.method,
283
+ normalizedTrace?.path
281
284
  )
282
285
  state.history.push({
283
286
  type: 'api-call-trace',
284
- payload: apiCallTrace
287
+ payload: normalizedTrace
285
288
  })
286
- props.sendApiCallTrace(apiCallTrace)
289
+ void props.sendApiCallTrace(normalizedTrace)
287
290
  },
288
291
  async flush() {}
289
292
  }
290
293
 
291
294
  const conversationalTracer: ConversationalTracer = {
292
295
  addConversationalTrace: (conversationalTrace) => {
293
- const rawUserMessage = userMessage(state)
294
- ;(conversationalTrace as any).bosunStateId = state.id
295
- ;(conversationalTrace as any).bosunPrevStateId = state.prev
296
- if (rawUserMessage) {
297
- ;(conversationalTrace as any).bosunUserMessage = rawUserMessage
296
+ const inputMessage = latestInputMessage(state)
297
+ attachInputMessageMetadata(conversationalTrace, state, inputMessage)
298
+ const isInboundMessageEvent =
299
+ conversationalTrace.eventName === 'received-message' ||
300
+ conversationalTrace.eventName === 'llm-handler-stream-requested'
301
+ if (isInboundMessageEvent && !String(conversationalTrace.content ?? '').trim()) {
302
+ return
303
+ }
304
+ if (
305
+ inputMessage &&
306
+ isInboundMessageEvent &&
307
+ hasInputMessageTrace(state.history, inputMessage)
308
+ ) {
309
+ return
298
310
  }
311
+ const normalizedTrace = normalizeTracePayload(conversationalTrace)
299
312
  logger.log(
300
313
  '[conversationalTracer] addConversationalTrace',
301
- conversationalTrace?.eventName,
302
- conversationalTrace?.role
314
+ normalizedTrace?.eventName,
315
+ normalizedTrace?.role
303
316
  )
304
317
  state.history.push({
305
318
  type: 'conversational-trace',
306
- payload: conversationalTrace
319
+ payload: normalizedTrace
307
320
  })
308
- props.sendConversationalTrace(conversationalTrace)
321
+ void props.sendConversationalTrace(normalizedTrace)
309
322
  },
310
323
  async flush() {}
311
324
  }
@@ -314,11 +327,25 @@ export async function loadAgent(props: LoadProps) {
314
327
 
315
328
  scheduler = createScheduler({
316
329
  logger,
317
- onUpdate: async (actions) => {
318
- await props.sendSchedule(actions)
330
+ onUpdate: (actions) => {
331
+ void props.sendSchedule(actions)
319
332
  }
320
333
  })
321
334
 
335
+ const sendAgentMessage = async (message: string | Message) => {
336
+ if (typeof message === 'string') {
337
+ state.history.push({
338
+ type: 'message',
339
+ payload: { text: message, sender: 'agent' }
340
+ })
341
+ } else {
342
+ state.history.push({
343
+ type: 'message',
344
+ payload: message
345
+ })
346
+ }
347
+ }
348
+
322
349
  agent = await props.factory({
323
350
  stepTracer: stepTracer,
324
351
  stepRegistry,
@@ -327,7 +354,7 @@ export async function loadAgent(props: LoadProps) {
327
354
  conversationalTracer,
328
355
  scheduler,
329
356
  getMessages: () => {
330
- let messages: Array<MessageEntry['payload']> = []
357
+ const messages: Array<MessageEntry['payload']> = []
331
358
  let curState = state
332
359
  while (true) {
333
360
  curState.history
@@ -343,21 +370,7 @@ export async function loadAgent(props: LoadProps) {
343
370
  }
344
371
  return messages.reverse()
345
372
  },
346
- sendMessage: async (message: string | Message) => {
347
- if (typeof message === 'string') {
348
- state.history.push({
349
- type: 'message',
350
- payload: { text: message, sender: 'agent' }
351
- })
352
- await props.sendMessage({ text: message, sender: 'agent' })
353
- } else {
354
- state.history.push({
355
- type: 'message',
356
- payload: message
357
- })
358
- await props.sendMessage({ text: message.text, sender: message.sender })
359
- }
360
- },
373
+ sendMessage: sendAgentMessage,
361
374
  ctx,
362
375
  config: {
363
376
  enableTimers: false,
@@ -393,6 +406,7 @@ export async function loadAgent(props: LoadProps) {
393
406
  id: state.id,
394
407
  name: state.name,
395
408
  userMessage: userMessage(state),
409
+ userMessageSender: userMessageSender(state),
396
410
  prev: state.prev,
397
411
  next: state.next
398
412
  }))
@@ -430,7 +444,12 @@ export async function loadAgent(props: LoadProps) {
430
444
  console.log(' --- init agent ---')
431
445
  state = createState({}, null)
432
446
  if (agent) {
433
- await (isVoiceAgent(agent) ? agent.onCallStart() : agent.start())
447
+ if (isVoiceAgent(agent)) {
448
+ const callStartResult = await agent.onCallStart()
449
+ await sendCallStartMessage(callStartResult, sendAgentMessage)
450
+ } else {
451
+ await agent.start()
452
+ }
434
453
  }
435
454
  return
436
455
  }
@@ -448,29 +467,32 @@ export async function loadAgent(props: LoadProps) {
448
467
  }
449
468
  console.log('replay: ' + replay.length)
450
469
  replay.reverse().forEach((state) => {
451
- state.history.forEach((entry) => {
470
+ state.history.forEach((entry, index) => {
452
471
  switch (entry.type) {
453
472
  case 'message':
454
- props.sendMessage(entry.payload)
473
+ if (
474
+ isInputMessage(entry.payload) &&
475
+ !hasInputMessageTrace(state.history, entry.payload)
476
+ ) {
477
+ const inputTrace = createInputMessageTrace(entry.payload, state, agentMedium(agent))
478
+ if (inputTrace) void props.sendConversationalTrace(inputTrace)
479
+ }
455
480
  break
456
481
  case 'log':
457
- props.sendLog(entry.payload)
482
+ void props.sendLog(entry.payload)
458
483
  break
459
484
  case 'trace':
460
- props.sendTrace(entry.payload)
485
+ void props.sendTrace(entry.payload)
461
486
  break
462
487
  case 'api-call-trace':
463
- props.sendApiCallTrace(entry.payload)
488
+ void props.sendApiCallTrace(entry.payload)
464
489
  break
465
- case 'conversational-trace':
466
- const rawUserMessage = userMessage(state)
467
- ;(entry.payload as any).bosunStateId = state.id
468
- ;(entry.payload as any).bosunPrevStateId = state.prev
469
- if (rawUserMessage) {
470
- ;(entry.payload as any).bosunUserMessage = rawUserMessage
471
- }
472
- props.sendConversationalTrace(entry.payload)
490
+ case 'conversational-trace': {
491
+ const inputMessage = inputMessageBefore(state.history, index)
492
+ attachInputMessageMetadata(entry.payload, state, inputMessage)
493
+ void props.sendConversationalTrace(entry.payload)
473
494
  break
495
+ }
474
496
  }
475
497
  })
476
498
  })
@@ -534,6 +556,11 @@ export async function loadAgent(props: LoadProps) {
534
556
  type: 'message',
535
557
  payload: message
536
558
  })
559
+ const inputTrace = createInputMessageTrace(message, state, agentMedium(agent))
560
+ if (inputTrace) {
561
+ state.history.push({ type: 'conversational-trace', payload: inputTrace })
562
+ void props.sendConversationalTrace(inputTrace)
563
+ }
537
564
  if (isVoiceAgent(agent)) {
538
565
  await agent.streamResponse()
539
566
  } else {
@@ -571,7 +598,7 @@ function createState(schedule: DelayedActions, prev: string | null) {
571
598
  }
572
599
 
573
600
  function clone(obj: any) {
574
- return JSON.parse(JSON.stringify(obj))
601
+ return normalizeTracePayload(obj)
575
602
  }
576
603
 
577
604
  function indexStates(stateHistory: AgentState[]) {
@@ -591,23 +618,116 @@ function createLiveStateFromHistory(stateHistory: AgentState[]) {
591
618
  return createState(clone(latestSavedState.schedule ?? {}), latestSavedState.id)
592
619
  }
593
620
 
594
- function userMessage(st: AgentState): string | undefined {
621
+ function isInputMessage(message: Message): message is Message & { sender: 'user' | 'system' } {
622
+ return message.sender === 'user' || message.sender === 'system'
623
+ }
624
+
625
+ function latestInputMessage(st: AgentState): (Message & { sender: 'user' | 'system' }) | null {
595
626
  for (let i = st.history.length - 1; i >= 0; i--) {
596
627
  const entry = st.history[i]
597
628
  if (entry.type === 'message') {
598
- const m = entry.payload as Message
599
- if (m.sender === 'user') {
600
- if (typeof (m as any).text === 'string' && (m as any).text.trim()) {
601
- return (m as any).text
602
- }
603
- if (typeof (m as any).imageUrl === 'string' && (m as any).imageUrl.trim()) {
604
- return `[image] ${(m as any).imageUrl}`
605
- }
606
- return JSON.stringify(m)
607
- }
629
+ const m = entry.payload
630
+ if (isInputMessage(m)) return m
608
631
  }
609
632
  }
610
- return undefined
633
+ return null
634
+ }
635
+
636
+ function inputMessageBefore(
637
+ history: AgentState['history'],
638
+ beforeIndex: number
639
+ ): (Message & { sender: 'user' | 'system' }) | null {
640
+ for (let i = beforeIndex - 1; i >= 0; i--) {
641
+ const entry = history[i]
642
+ if (entry.type === 'message' && isInputMessage(entry.payload)) {
643
+ return entry.payload
644
+ }
645
+ }
646
+ return null
647
+ }
648
+
649
+ function messageSummary(message: Message): string {
650
+ if (typeof message.text === 'string' && message.text.trim()) {
651
+ return message.text
652
+ }
653
+ if (typeof message.imageUrl === 'string' && message.imageUrl.trim()) {
654
+ return `[image] ${message.imageUrl}`
655
+ }
656
+ return JSON.stringify(message)
657
+ }
658
+
659
+ function attachInputMessageMetadata(
660
+ trace: ConversationalTrace,
661
+ state: AgentState,
662
+ inputMessage: (Message & { sender: 'user' | 'system' }) | null
663
+ ) {
664
+ const rawUserMessage = inputMessage ? messageSummary(inputMessage) : undefined
665
+ ;(trace as any).bosunStateId = state.id
666
+ ;(trace as any).bosunPrevStateId = state.prev
667
+ delete (trace as any).bosunUserMessage
668
+ delete (trace as any).bosunInputMessageSender
669
+ if (rawUserMessage) {
670
+ ;(trace as any).bosunUserMessage = rawUserMessage
671
+ }
672
+ if (inputMessage) {
673
+ ;(trace as any).bosunInputMessageSender = inputMessage.sender
674
+ }
675
+ }
676
+
677
+ function hasInputMessageTrace(history: AgentState['history'], message: Message): boolean {
678
+ if (!isInputMessage(message)) return true
679
+ const summary = messageSummary(message)
680
+ return history.some((entry) => {
681
+ if (entry.type !== 'conversational-trace') return false
682
+ const trace = entry.payload
683
+ if (
684
+ trace.eventName !== 'received-message' &&
685
+ trace.eventName !== 'llm-handler-stream-requested'
686
+ ) {
687
+ return false
688
+ }
689
+ const sender = (trace as any)?.bosunInputMessageSender
690
+ return trace.content === summary && (sender === message.sender || trace.role === message.sender)
691
+ })
692
+ }
693
+
694
+ function createInputMessageTrace(
695
+ message: Message,
696
+ state: AgentState,
697
+ medium: ConversationalTrace['medium']
698
+ ): ConversationalTrace | null {
699
+ if (!isInputMessage(message)) return null
700
+ const trace: ConversationalTrace = {
701
+ conversationId: state.id,
702
+ eventName: 'received-message',
703
+ role: message.sender,
704
+ medium,
705
+ content: messageSummary(message),
706
+ createdAt: stateCreatedAt(state)
707
+ }
708
+ attachInputMessageMetadata(trace, state, message)
709
+ return trace
710
+ }
711
+
712
+ function stateCreatedAt(state: AgentState): number {
713
+ const fromId = Date.parse(state.id)
714
+ if (Number.isFinite(fromId)) return fromId
715
+ const fromName = Date.parse(state.name)
716
+ if (Number.isFinite(fromName)) return fromName
717
+ return Date.now()
718
+ }
719
+
720
+ function agentMedium(agent: TestAgent | null): ConversationalTrace['medium'] {
721
+ return agent && isVoiceAgent(agent) ? 'phone' : 'whatsapp'
722
+ }
723
+
724
+ function userMessage(st: AgentState): string | undefined {
725
+ const message = latestInputMessage(st)
726
+ return message ? messageSummary(message) : undefined
727
+ }
728
+
729
+ function userMessageSender(st: AgentState): 'user' | 'system' | undefined {
730
+ return latestInputMessage(st)?.sender
611
731
  }
612
732
 
613
733
  async function loadSchemaFile(basePath: string, promptPath: string) {
@@ -5,7 +5,6 @@ import type {
5
5
  AgentSateHeader,
6
6
  WsMessage
7
7
  } from '../../lib/ws-message'
8
- import { type Message } from '@recombine-ai/engine'
9
8
 
10
9
  import {
11
10
  type ApiCallTrace,
@@ -20,8 +19,6 @@ export class MessageDispatcher {
20
19
  private sendWsMessage(message: WsMessage) {
21
20
  if (message.channel === 'app-events') {
22
21
  console.log('<-- ', message.channel, message.event.type)
23
- } else if (message.channel === 'chat') {
24
- console.log('<-- ', message.channel, message.message)
25
22
  } else if (message.channel === 'step-trace') {
26
23
  console.log('<-- ', message.channel, message.trace?.name)
27
24
  } else if (message.channel === 'api-call-trace') {
@@ -36,10 +33,6 @@ export class MessageDispatcher {
36
33
  this.ws.send(JSON.stringify(message))
37
34
  }
38
35
 
39
- sendMessage = async (message: Message) => {
40
- this.sendWsMessage({ channel: 'chat', message })
41
- }
42
-
43
36
  sendLog = async (message: LogEntry) => {
44
37
  this.sendWsMessage({ channel: 'log', message })
45
38
  }
@@ -3,7 +3,7 @@ import path from 'path'
3
3
  import { z } from 'zod'
4
4
  import { createContext } from '@recombine-ai/engine'
5
5
  import type { TRPCRootObject } from '@trpc/server/unstable-core-do-not-import'
6
- import { getAgentFactories } from '../lib/get-agent-factories'
6
+ import { getAgentCatalog, getAgentFactories } from '../lib/get-agent-factories'
7
7
  import { getProjectDataDir } from '../lib/project-data-dir'
8
8
  import { getRootPath } from '../lib/get-root-path'
9
9
  import type { TrpcContext } from '../lib/trpc-context'
@@ -19,8 +19,13 @@ export function createRolePlayRouter(t: TRPCRootObject<TrpcContext, any, any>) {
19
19
  return t.router({
20
20
  list: t.procedure.query(async () => {
21
21
  const rootPath = await getRootPath()
22
- const agentFactories = await getAgentFactories(rootPath)
23
- return Object.keys(agentFactories.factories)
22
+ const project = await getAgentFactories(rootPath)
23
+ return Object.keys(project.factories)
24
+ }),
25
+ catalog: t.procedure.query(async () => {
26
+ const rootPath = await getRootPath()
27
+ const project = await getAgentFactories(rootPath)
28
+ return getAgentCatalog(project)
24
29
  }),
25
30
  analyzeTrace: t.procedure
26
31
  .input(
@@ -104,7 +109,7 @@ export function createRolePlayRouter(t: TRPCRootObject<TrpcContext, any, any>) {
104
109
  if (entry.type !== 'message') continue
105
110
  const payload = entry.payload
106
111
  if (!payload || typeof payload !== 'object') continue
107
- if (payload.sender !== 'user') continue
112
+ if (payload.sender !== 'user' && payload.sender !== 'system') continue
108
113
 
109
114
  const rawText = payload.text
110
115
  if (typeof rawText !== 'string') continue
@@ -130,8 +135,6 @@ export function createRolePlayRouter(t: TRPCRootObject<TrpcContext, any, any>) {
130
135
  z.object({
131
136
  agentId: AgentIdSchema,
132
137
  region: z.string().trim().min(1).max(128).nullable().optional(),
133
- prevStateId: z.string().trim().min(1).max(2048).nullable(),
134
- rawUserMessage: z.string().trim().min(1).max(100_000),
135
138
  context: z.record(z.string(), z.unknown()).nullable().optional(),
136
139
  promptUpdate: z
137
140
  .object({
@@ -155,16 +158,13 @@ export function createRolePlayRouter(t: TRPCRootObject<TrpcContext, any, any>) {
155
158
  const rawStates = await fsStatePersistence.load(stateKey)
156
159
  const states = Array.isArray(rawStates) ? rawStates : []
157
160
  const context =
158
- input.context && typeof input.context === 'object'
159
- ? input.context
160
- : ((await fsContextPersistence.load('default')) as Record<string, any>) || {}
161
+ input.context ??
162
+ (((await fsContextPersistence.load('default')) as Record<string, any> | null) || {})
161
163
 
162
164
  const variants = await generateReplyVariants({
163
165
  agentId: input.agentId,
164
166
  region: input.region ?? null,
165
167
  states,
166
- prevStateId: input.prevStateId ?? null,
167
- rawUserMessage: input.rawUserMessage,
168
168
  count: input.count,
169
169
  context
170
170
  })
@@ -183,7 +183,6 @@ export function createRolePlayRouter(t: TRPCRootObject<TrpcContext, any, any>) {
183
183
  z.object({
184
184
  agentId: AgentIdSchema,
185
185
  region: z.string().trim().min(1).max(128).nullable().optional(),
186
- targetStateId: z.string().trim().min(1).max(2048),
187
186
  state: z.object({
188
187
  history: z.unknown(),
189
188
  schedule: z.unknown()
@@ -194,12 +193,10 @@ export function createRolePlayRouter(t: TRPCRootObject<TrpcContext, any, any>) {
194
193
  const stateKey = resolveAgentStateKey(input.agentId, input.region ?? null)
195
194
  const rawStates = await fsStatePersistence.load(stateKey)
196
195
  const states = Array.isArray(rawStates) ? rawStates : []
197
- if (!states.length) throw new Error('No saved roleplay states found for this agent')
198
- if (states[states.length - 1]?.id !== input.targetStateId) {
199
- throw new Error('Variants can only be applied to the latest saved reply')
200
- }
196
+ const latestState = states.at(-1)
197
+ if (!latestState) throw new Error('No saved roleplay states found for this agent')
201
198
 
202
- const nextStates = replaceSavedState(states, input.targetStateId, {
199
+ const nextStates = replaceSavedState(states, latestState.id, {
203
200
  history: input.state.history as AgentState['history'],
204
201
  schedule: input.state.schedule as AgentState['schedule']
205
202
  })
@@ -0,0 +1,35 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { normalizeTracePayload } from './trace-serialization'
3
+
4
+ describe('normalizeTracePayload', () => {
5
+ it('keeps error details when trace payloads are JSON serialized', () => {
6
+ const cause = new Error('schema expected array')
7
+ const error = new Error('Response parsing error') as Error & {
8
+ cause?: unknown
9
+ operation?: string
10
+ }
11
+ error.cause = cause
12
+ error.operation = 'fetchCustomerDetails'
13
+
14
+ const normalized = normalizeTracePayload({
15
+ name: 'request-customer-details',
16
+ error
17
+ })
18
+
19
+ expect(normalized.error).toMatchObject({
20
+ name: 'Error',
21
+ message: 'Response parsing error',
22
+ operation: 'fetchCustomerDetails',
23
+ cause: {
24
+ name: 'Error',
25
+ message: 'schema expected array'
26
+ }
27
+ })
28
+ expect(JSON.parse(JSON.stringify(normalized)).error).toMatchObject({
29
+ message: 'Response parsing error',
30
+ cause: {
31
+ message: 'schema expected array'
32
+ }
33
+ })
34
+ })
35
+ })
@@ -0,0 +1,57 @@
1
+ export function normalizeTracePayload<T>(value: T): T {
2
+ return normalizeValue(value, new WeakMap<object, unknown>()) as T
3
+ }
4
+
5
+ function normalizeValue(value: unknown, seen: WeakMap<object, unknown>): unknown {
6
+ if (value == null) return value
7
+ if (typeof value === 'bigint') return value.toString()
8
+ if (typeof value !== 'object') return value
9
+ if (value instanceof Error) return normalizeError(value, seen)
10
+ if (value instanceof Date) return value.toISOString()
11
+
12
+ const existing = seen.get(value)
13
+ if (existing) return '[Circular]'
14
+
15
+ if (Array.isArray(value)) {
16
+ const next: unknown[] = []
17
+ seen.set(value, next)
18
+ for (const item of value) {
19
+ const normalized = normalizeValue(item, seen)
20
+ next.push(normalized === undefined ? null : normalized)
21
+ }
22
+ return next
23
+ }
24
+
25
+ const next: Record<string, unknown> = {}
26
+ seen.set(value, next)
27
+ for (const [key, item] of Object.entries(value)) {
28
+ next[key] = normalizeValue(item, seen)
29
+ }
30
+ return next
31
+ }
32
+
33
+ function normalizeError(error: Error, seen: WeakMap<object, unknown>): Record<string, unknown> {
34
+ const existing = seen.get(error)
35
+ if (existing) return { name: error.name || 'Error', message: '[Circular]' }
36
+
37
+ const next: Record<string, unknown> = {
38
+ name: error.name || 'Error',
39
+ message: error.message || String(error)
40
+ }
41
+ seen.set(error, next)
42
+
43
+ if (typeof error.stack === 'string' && error.stack) {
44
+ next.stack = error.stack
45
+ }
46
+
47
+ if ('cause' in error) {
48
+ next.cause = normalizeValue((error as Error & { cause?: unknown }).cause, seen)
49
+ }
50
+
51
+ for (const key of Object.getOwnPropertyNames(error)) {
52
+ if (key in next) continue
53
+ next[key] = normalizeValue((error as unknown as Record<string, unknown>)[key], seen)
54
+ }
55
+
56
+ return next
57
+ }