@copilotkit/react-core 1.10.7-next.0 → 1.50.0-beta.1

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 (334) hide show
  1. package/CHANGELOG.md +0 -7
  2. package/dist/chunk-24SCZAB4.mjs +143 -0
  3. package/dist/chunk-24SCZAB4.mjs.map +1 -0
  4. package/dist/chunk-36KQV2NA.mjs +1 -0
  5. package/dist/{chunk-U7QULEVO.mjs → chunk-3GURHDG7.mjs} +3 -3
  6. package/dist/{chunk-OAGAFMUM.mjs → chunk-3R423LZT.mjs} +6 -5
  7. package/dist/{chunk-OAGAFMUM.mjs.map → chunk-3R423LZT.mjs.map} +1 -1
  8. package/dist/chunk-5X5DJRQQ.mjs +71 -0
  9. package/dist/chunk-5X5DJRQQ.mjs.map +1 -0
  10. package/dist/{chunk-N4WEHORG.mjs → chunk-6PUNP7CD.mjs} +4 -4
  11. package/dist/chunk-6PUNP7CD.mjs.map +1 -0
  12. package/dist/chunk-7BYHZLPL.mjs +32 -0
  13. package/dist/chunk-7BYHZLPL.mjs.map +1 -0
  14. package/dist/chunk-7DTB7S5V.mjs +83 -0
  15. package/dist/chunk-7DTB7S5V.mjs.map +1 -0
  16. package/dist/chunk-A6NKSGH3.mjs +1 -0
  17. package/dist/{chunk-GT5WI3AF.mjs → chunk-BR5YEYZJ.mjs} +7 -9
  18. package/dist/chunk-BR5YEYZJ.mjs.map +1 -0
  19. package/dist/chunk-CB7CRBDG.mjs +48 -0
  20. package/dist/chunk-CB7CRBDG.mjs.map +1 -0
  21. package/dist/chunk-CYDWEPFL.mjs +1 -0
  22. package/dist/{chunk-BBUQMG45.mjs → chunk-D3QSYDJR.mjs} +3 -3
  23. package/dist/{chunk-BBUQMG45.mjs.map → chunk-D3QSYDJR.mjs.map} +1 -1
  24. package/dist/chunk-DCHSCK62.mjs +549 -0
  25. package/dist/chunk-DCHSCK62.mjs.map +1 -0
  26. package/dist/{chunk-ZLQVRPDS.mjs → chunk-DMLQZG75.mjs} +1 -1
  27. package/dist/chunk-DMLQZG75.mjs.map +1 -0
  28. package/dist/chunk-F555TVE4.mjs +33 -0
  29. package/dist/chunk-F555TVE4.mjs.map +1 -0
  30. package/dist/{chunk-C6IANC2R.mjs → chunk-FBD24VEH.mjs} +7 -43
  31. package/dist/chunk-FBD24VEH.mjs.map +1 -0
  32. package/dist/chunk-FD6FGKYY.mjs +1 -0
  33. package/dist/chunk-FDOMAPJY.mjs +59 -0
  34. package/dist/chunk-FDOMAPJY.mjs.map +1 -0
  35. package/dist/{chunk-E3624YDU.mjs → chunk-GMI4KO4X.mjs} +8 -6
  36. package/dist/{chunk-E3624YDU.mjs.map → chunk-GMI4KO4X.mjs.map} +1 -1
  37. package/dist/chunk-IUSKVYUI.mjs +13 -0
  38. package/dist/chunk-IUSKVYUI.mjs.map +1 -0
  39. package/dist/chunk-JD7BAH7U.mjs +1 -0
  40. package/dist/{chunk-EDBI5PCJ.mjs → chunk-JRT5BJF3.mjs} +2 -2
  41. package/dist/{chunk-N4VN2B5S.mjs → chunk-LHERIF3L.mjs} +2 -2
  42. package/dist/{chunk-DXEQPN43.mjs → chunk-LHKZJ2ND.mjs} +3 -3
  43. package/dist/chunk-NB2FKV2V.mjs +1 -0
  44. package/dist/chunk-NBK4KBLX.mjs +54 -0
  45. package/dist/chunk-NBK4KBLX.mjs.map +1 -0
  46. package/dist/chunk-NG26QEGF.mjs +46 -0
  47. package/dist/chunk-NG26QEGF.mjs.map +1 -0
  48. package/dist/chunk-NROJOTQP.mjs +163 -0
  49. package/dist/chunk-NROJOTQP.mjs.map +1 -0
  50. package/dist/{chunk-MGWRDFBE.mjs → chunk-OVYFRPSN.mjs} +2 -2
  51. package/dist/{chunk-MQYWH4E6.mjs → chunk-QU6NONOD.mjs} +2 -2
  52. package/dist/chunk-R4MR43UQ.mjs +101 -0
  53. package/dist/chunk-R4MR43UQ.mjs.map +1 -0
  54. package/dist/chunk-SPCZTZCY.mjs +1 -0
  55. package/dist/chunk-SPCZTZCY.mjs.map +1 -0
  56. package/dist/chunk-TXI72QHK.mjs +80 -0
  57. package/dist/chunk-TXI72QHK.mjs.map +1 -0
  58. package/dist/chunk-UJBV5GAG.mjs +767 -0
  59. package/dist/chunk-UJBV5GAG.mjs.map +1 -0
  60. package/dist/{chunk-OKCYPO4I.mjs → chunk-WMJVBMUX.mjs} +3 -3
  61. package/dist/{chunk-EUX2P2E7.mjs → chunk-WVLHXIFP.mjs} +11 -9
  62. package/dist/chunk-WVLHXIFP.mjs.map +1 -0
  63. package/dist/{chunk-5FHSUKQL.mjs → chunk-YYN33GSG.mjs} +5 -2
  64. package/dist/chunk-YYN33GSG.mjs.map +1 -0
  65. package/dist/chunk-ZVF5Q6IH.mjs +29 -0
  66. package/dist/chunk-ZVF5Q6IH.mjs.map +1 -0
  67. package/dist/components/CopilotListeners.d.ts +3 -0
  68. package/dist/components/CopilotListeners.js +234 -0
  69. package/dist/components/CopilotListeners.js.map +1 -0
  70. package/dist/components/CopilotListeners.mjs +14 -0
  71. package/dist/components/CopilotListeners.mjs.map +1 -0
  72. package/dist/components/copilot-provider/copilot-messages.js +14 -48
  73. package/dist/components/copilot-provider/copilot-messages.js.map +1 -1
  74. package/dist/components/copilot-provider/copilot-messages.mjs +3 -3
  75. package/dist/components/copilot-provider/copilotkit-props.d.ts +9 -2
  76. package/dist/components/copilot-provider/copilotkit-props.js.map +1 -1
  77. package/dist/components/copilot-provider/copilotkit.d.ts +2 -1
  78. package/dist/components/copilot-provider/copilotkit.js +528 -370
  79. package/dist/components/copilot-provider/copilotkit.js.map +1 -1
  80. package/dist/components/copilot-provider/copilotkit.mjs +15 -10
  81. package/dist/components/copilot-provider/index.d.ts +2 -1
  82. package/dist/components/copilot-provider/index.js +528 -370
  83. package/dist/components/copilot-provider/index.js.map +1 -1
  84. package/dist/components/copilot-provider/index.mjs +16 -10
  85. package/dist/components/dev-console/console-trigger.js +10 -8
  86. package/dist/components/dev-console/console-trigger.js.map +1 -1
  87. package/dist/components/dev-console/console-trigger.mjs +4 -4
  88. package/dist/components/dev-console/developer-console-modal.js +10 -8
  89. package/dist/components/dev-console/developer-console-modal.js.map +1 -1
  90. package/dist/components/dev-console/developer-console-modal.mjs +3 -3
  91. package/dist/components/error-boundary/error-boundary.d.ts +7 -7
  92. package/dist/components/error-boundary/error-boundary.js +3 -3
  93. package/dist/components/error-boundary/error-boundary.js.map +1 -1
  94. package/dist/components/error-boundary/error-boundary.mjs +2 -2
  95. package/dist/components/error-boundary/error-utils.d.ts +1 -1
  96. package/dist/components/error-boundary/error-utils.js +3 -3
  97. package/dist/components/error-boundary/error-utils.js.map +1 -1
  98. package/dist/components/error-boundary/error-utils.mjs +1 -1
  99. package/dist/components/index.d.ts +2 -1
  100. package/dist/components/index.js +528 -370
  101. package/dist/components/index.js.map +1 -1
  102. package/dist/components/index.mjs +17 -10
  103. package/dist/components/toast/exclamation-mark-icon.d.ts +2 -2
  104. package/dist/components/toast/toast-provider.d.ts +3 -3
  105. package/dist/components/usage-banner.d.ts +2 -2
  106. package/dist/context/coagent-state-renders-context.d.ts +24 -0
  107. package/dist/context/coagent-state-renders-context.js +91 -0
  108. package/dist/context/coagent-state-renders-context.js.map +1 -0
  109. package/dist/context/coagent-state-renders-context.mjs +12 -0
  110. package/dist/context/coagent-state-renders-context.mjs.map +1 -0
  111. package/dist/context/copilot-context.d.ts +1 -1
  112. package/dist/context/copilot-context.js +10 -8
  113. package/dist/context/copilot-context.js.map +1 -1
  114. package/dist/context/copilot-context.mjs +1 -1
  115. package/dist/context/copilot-messages-context.d.ts +18 -11
  116. package/dist/context/copilot-messages-context.js.map +1 -1
  117. package/dist/context/copilot-messages-context.mjs +1 -1
  118. package/dist/context/index.d.ts +6 -2
  119. package/dist/context/index.js +110 -10
  120. package/dist/context/index.js.map +1 -1
  121. package/dist/context/index.mjs +20 -4
  122. package/dist/context/threads-context.d.ts +16 -0
  123. package/dist/context/threads-context.js +59 -0
  124. package/dist/context/threads-context.js.map +1 -0
  125. package/dist/context/threads-context.mjs +12 -0
  126. package/dist/context/threads-context.mjs.map +1 -0
  127. package/dist/{copilot-context-cf9de848.d.ts → copilot-context-1cd70a3f.d.ts} +36 -32
  128. package/dist/hooks/index.d.ts +9 -6
  129. package/dist/hooks/index.js +1445 -1839
  130. package/dist/hooks/index.js.map +1 -1
  131. package/dist/hooks/index.mjs +47 -56
  132. package/dist/hooks/use-coagent-state-render-bridge.d.ts +100 -0
  133. package/dist/hooks/use-coagent-state-render-bridge.js +211 -0
  134. package/dist/hooks/use-coagent-state-render-bridge.js.map +1 -0
  135. package/dist/hooks/use-coagent-state-render-bridge.mjs +15 -0
  136. package/dist/hooks/use-coagent-state-render-bridge.mjs.map +1 -0
  137. package/dist/hooks/use-coagent-state-render.js +31 -20
  138. package/dist/hooks/use-coagent-state-render.js.map +1 -1
  139. package/dist/hooks/use-coagent-state-render.mjs +3 -2
  140. package/dist/hooks/use-coagent.d.ts +2 -14
  141. package/dist/hooks/use-coagent.js +109 -1906
  142. package/dist/hooks/use-coagent.js.map +1 -1
  143. package/dist/hooks/use-coagent.mjs +1 -30
  144. package/dist/hooks/use-configure-chat-suggestions.d.ts +36 -0
  145. package/dist/hooks/use-configure-chat-suggestions.js +210 -0
  146. package/dist/hooks/use-configure-chat-suggestions.js.map +1 -0
  147. package/dist/hooks/use-configure-chat-suggestions.mjs +13 -0
  148. package/dist/hooks/use-configure-chat-suggestions.mjs.map +1 -0
  149. package/dist/hooks/use-copilot-action.d.ts +8 -45
  150. package/dist/hooks/use-copilot-action.js +207 -349
  151. package/dist/hooks/use-copilot-action.js.map +1 -1
  152. package/dist/hooks/use-copilot-action.mjs +4 -5
  153. package/dist/hooks/use-copilot-additional-instructions.js +10 -8
  154. package/dist/hooks/use-copilot-additional-instructions.js.map +1 -1
  155. package/dist/hooks/use-copilot-additional-instructions.mjs +2 -2
  156. package/dist/hooks/use-copilot-authenticated-action.js +224 -248
  157. package/dist/hooks/use-copilot-authenticated-action.js.map +1 -1
  158. package/dist/hooks/use-copilot-authenticated-action.mjs +6 -6
  159. package/dist/hooks/use-copilot-chat-headless_c.d.ts +2 -10
  160. package/dist/hooks/use-copilot-chat-headless_c.js +973 -1369
  161. package/dist/hooks/use-copilot-chat-headless_c.js.map +1 -1
  162. package/dist/hooks/use-copilot-chat-headless_c.mjs +12 -22
  163. package/dist/hooks/use-copilot-chat.d.ts +2 -10
  164. package/dist/hooks/use-copilot-chat.js +967 -1388
  165. package/dist/hooks/use-copilot-chat.js.map +1 -1
  166. package/dist/hooks/use-copilot-chat.mjs +12 -22
  167. package/dist/hooks/use-copilot-chat_internal.d.ts +38 -14
  168. package/dist/hooks/use-copilot-chat_internal.js +965 -1362
  169. package/dist/hooks/use-copilot-chat_internal.js.map +1 -1
  170. package/dist/hooks/use-copilot-chat_internal.mjs +13 -23
  171. package/dist/hooks/use-copilot-readable.d.ts +1 -1
  172. package/dist/hooks/use-copilot-readable.js +6 -157
  173. package/dist/hooks/use-copilot-readable.js.map +1 -1
  174. package/dist/hooks/use-copilot-readable.mjs +1 -2
  175. package/dist/hooks/use-default-tool.js +204 -349
  176. package/dist/hooks/use-default-tool.js.map +1 -1
  177. package/dist/hooks/use-default-tool.mjs +5 -6
  178. package/dist/hooks/use-flat-category-store.js +4 -1
  179. package/dist/hooks/use-flat-category-store.js.map +1 -1
  180. package/dist/hooks/use-flat-category-store.mjs +1 -1
  181. package/dist/hooks/use-frontend-tool.d.ts +3 -3
  182. package/dist/hooks/use-frontend-tool.js +30 -370
  183. package/dist/hooks/use-frontend-tool.js.map +1 -1
  184. package/dist/hooks/use-frontend-tool.mjs +1 -6
  185. package/dist/hooks/use-human-in-the-loop.d.ts +4 -3
  186. package/dist/hooks/use-human-in-the-loop.js +61 -393
  187. package/dist/hooks/use-human-in-the-loop.js.map +1 -1
  188. package/dist/hooks/use-human-in-the-loop.mjs +1 -6
  189. package/dist/hooks/use-langgraph-interrupt-render.d.ts +3 -2
  190. package/dist/hooks/use-langgraph-interrupt-render.js +92 -36
  191. package/dist/hooks/use-langgraph-interrupt-render.js.map +1 -1
  192. package/dist/hooks/use-langgraph-interrupt-render.mjs +6 -4
  193. package/dist/hooks/use-langgraph-interrupt.d.ts +1 -1
  194. package/dist/hooks/use-langgraph-interrupt.js +24 -1642
  195. package/dist/hooks/use-langgraph-interrupt.js.map +1 -1
  196. package/dist/hooks/use-langgraph-interrupt.mjs +2 -23
  197. package/dist/hooks/use-lazy-tool-renderer.d.ts +6 -0
  198. package/dist/hooks/use-lazy-tool-renderer.js +53 -0
  199. package/dist/hooks/use-lazy-tool-renderer.js.map +1 -0
  200. package/dist/hooks/use-lazy-tool-renderer.mjs +8 -0
  201. package/dist/hooks/use-lazy-tool-renderer.mjs.map +1 -0
  202. package/dist/hooks/use-make-copilot-document-readable.js +11 -9
  203. package/dist/hooks/use-make-copilot-document-readable.js.map +1 -1
  204. package/dist/hooks/use-make-copilot-document-readable.mjs +2 -2
  205. package/dist/hooks/use-render-tool-call.d.ts +7 -6
  206. package/dist/hooks/use-render-tool-call.js +36 -386
  207. package/dist/hooks/use-render-tool-call.js.map +1 -1
  208. package/dist/hooks/use-render-tool-call.mjs +1 -6
  209. package/dist/index.d.ts +11 -6
  210. package/dist/index.js +1841 -2056
  211. package/dist/index.js.map +1 -1
  212. package/dist/index.mjs +78 -59
  213. package/dist/lib/copilot-task.d.ts +1 -1
  214. package/dist/lib/copilot-task.js +1 -0
  215. package/dist/lib/copilot-task.js.map +1 -1
  216. package/dist/lib/copilot-task.mjs +18 -11
  217. package/dist/lib/index.d.ts +1 -1
  218. package/dist/lib/index.js +1 -0
  219. package/dist/lib/index.js.map +1 -1
  220. package/dist/lib/index.mjs +18 -11
  221. package/dist/setupTests.d.ts +2 -2
  222. package/dist/types/frontend-action.d.ts +5 -5
  223. package/dist/types/index.d.ts +4 -0
  224. package/dist/types/index.js.map +1 -1
  225. package/dist/types/index.mjs +2 -1
  226. package/dist/types/interrupt-action.d.ts +1 -1
  227. package/dist/types/interrupt-action.js.map +1 -1
  228. package/dist/types/interrupt-action.mjs +1 -0
  229. package/dist/utils/index.d.ts +0 -12
  230. package/dist/utils/index.js +6 -325
  231. package/dist/utils/index.js.map +1 -1
  232. package/dist/utils/index.mjs +1 -21
  233. package/dist/utils/utils.js.map +1 -1
  234. package/dist/v2/index.d.ts +2 -0
  235. package/dist/v2/index.js +27 -0
  236. package/dist/v2/index.js.map +1 -0
  237. package/dist/v2/index.mjs +4 -0
  238. package/dist/v2/index.mjs.map +1 -0
  239. package/package.json +20 -9
  240. package/src/components/CopilotListeners.tsx +82 -0
  241. package/src/components/copilot-provider/copilot-messages.tsx +46 -47
  242. package/src/components/copilot-provider/copilotkit-props.tsx +8 -1
  243. package/src/components/copilot-provider/copilotkit.tsx +177 -144
  244. package/src/components/error-boundary/error-utils.tsx +3 -3
  245. package/src/context/coagent-state-renders-context.tsx +76 -0
  246. package/src/context/copilot-context.tsx +21 -21
  247. package/src/context/copilot-messages-context.tsx +3 -3
  248. package/src/context/index.ts +8 -0
  249. package/src/context/threads-context.tsx +41 -0
  250. package/src/hooks/index.ts +7 -3
  251. package/src/hooks/use-coagent-state-render-bridge.tsx +293 -0
  252. package/src/hooks/use-coagent-state-render.ts +4 -7
  253. package/src/hooks/use-coagent.ts +129 -249
  254. package/src/hooks/use-configure-chat-suggestions.tsx +85 -0
  255. package/src/hooks/use-copilot-action.ts +88 -199
  256. package/src/hooks/use-copilot-chat-headless_c.ts +2 -1
  257. package/src/hooks/use-copilot-chat.ts +4 -1
  258. package/src/hooks/use-copilot-chat_internal.ts +349 -258
  259. package/src/hooks/use-copilot-readable.ts +6 -26
  260. package/src/hooks/use-flat-category-store.ts +4 -3
  261. package/src/hooks/use-frontend-tool.ts +67 -8
  262. package/src/hooks/use-human-in-the-loop.ts +111 -13
  263. package/src/hooks/use-langgraph-interrupt-render.ts +90 -40
  264. package/src/hooks/use-langgraph-interrupt.ts +18 -47
  265. package/src/hooks/use-lazy-tool-renderer.tsx +30 -0
  266. package/src/hooks/use-make-copilot-document-readable.ts +1 -1
  267. package/src/hooks/use-render-tool-call.ts +73 -13
  268. package/src/types/index.ts +1 -0
  269. package/src/types/interrupt-action.ts +8 -4
  270. package/src/utils/index.ts +0 -3
  271. package/src/utils/utils.ts +7 -0
  272. package/src/v2/index.ts +2 -0
  273. package/src/v2/styles.css +1 -0
  274. package/tsup.config.ts +1 -1
  275. package/dist/chunk-5FHSUKQL.mjs.map +0 -1
  276. package/dist/chunk-6GPVUMBU.mjs +0 -13
  277. package/dist/chunk-6GPVUMBU.mjs.map +0 -1
  278. package/dist/chunk-AKR2SSUJ.mjs +0 -22
  279. package/dist/chunk-AKR2SSUJ.mjs.map +0 -1
  280. package/dist/chunk-BXXJQ2BL.mjs +0 -239
  281. package/dist/chunk-BXXJQ2BL.mjs.map +0 -1
  282. package/dist/chunk-C6IANC2R.mjs.map +0 -1
  283. package/dist/chunk-DZTU6PGS.mjs +0 -1
  284. package/dist/chunk-EUX2P2E7.mjs.map +0 -1
  285. package/dist/chunk-EVVO67QO.mjs +0 -25
  286. package/dist/chunk-EVVO67QO.mjs.map +0 -1
  287. package/dist/chunk-GGLAHG3I.mjs +0 -804
  288. package/dist/chunk-GGLAHG3I.mjs.map +0 -1
  289. package/dist/chunk-GT5WI3AF.mjs.map +0 -1
  290. package/dist/chunk-HDOG2RTM.mjs +0 -37
  291. package/dist/chunk-HDOG2RTM.mjs.map +0 -1
  292. package/dist/chunk-MIXSWZSB.mjs +0 -71
  293. package/dist/chunk-MIXSWZSB.mjs.map +0 -1
  294. package/dist/chunk-N4WEHORG.mjs.map +0 -1
  295. package/dist/chunk-NSBAWITG.mjs +0 -332
  296. package/dist/chunk-NSBAWITG.mjs.map +0 -1
  297. package/dist/chunk-OT5NHMEC.mjs +0 -723
  298. package/dist/chunk-OT5NHMEC.mjs.map +0 -1
  299. package/dist/chunk-T3376SZS.mjs +0 -142
  300. package/dist/chunk-T3376SZS.mjs.map +0 -1
  301. package/dist/chunk-YPBKY4KY.mjs +0 -1
  302. package/dist/chunk-YPSGKPDA.mjs +0 -1
  303. package/dist/chunk-ZLQVRPDS.mjs.map +0 -1
  304. package/dist/chunk-ZVOLWJCY.mjs +0 -47
  305. package/dist/chunk-ZVOLWJCY.mjs.map +0 -1
  306. package/dist/hooks/use-chat.d.ts +0 -145
  307. package/dist/hooks/use-chat.js +0 -1129
  308. package/dist/hooks/use-chat.js.map +0 -1
  309. package/dist/hooks/use-chat.mjs +0 -14
  310. package/dist/index-1f5b66ac.d.ts +0 -36
  311. package/dist/utils/extract.d.ts +0 -43
  312. package/dist/utils/extract.js +0 -208
  313. package/dist/utils/extract.js.map +0 -1
  314. package/dist/utils/extract.mjs +0 -25
  315. package/dist/utils/suggestions.d.ts +0 -11
  316. package/dist/utils/suggestions.js +0 -343
  317. package/dist/utils/suggestions.js.map +0 -1
  318. package/dist/utils/suggestions.mjs +0 -25
  319. package/src/hooks/use-chat.ts +0 -1142
  320. package/src/utils/extract.ts +0 -215
  321. package/src/utils/suggestions.ts +0 -208
  322. /package/dist/{chunk-DZTU6PGS.mjs.map → chunk-36KQV2NA.mjs.map} +0 -0
  323. /package/dist/{chunk-U7QULEVO.mjs.map → chunk-3GURHDG7.mjs.map} +0 -0
  324. /package/dist/{chunk-YPBKY4KY.mjs.map → chunk-A6NKSGH3.mjs.map} +0 -0
  325. /package/dist/{chunk-YPSGKPDA.mjs.map → chunk-CYDWEPFL.mjs.map} +0 -0
  326. /package/dist/{hooks/use-chat.mjs.map → chunk-FD6FGKYY.mjs.map} +0 -0
  327. /package/dist/{utils/extract.mjs.map → chunk-JD7BAH7U.mjs.map} +0 -0
  328. /package/dist/{chunk-EDBI5PCJ.mjs.map → chunk-JRT5BJF3.mjs.map} +0 -0
  329. /package/dist/{chunk-N4VN2B5S.mjs.map → chunk-LHERIF3L.mjs.map} +0 -0
  330. /package/dist/{chunk-DXEQPN43.mjs.map → chunk-LHKZJ2ND.mjs.map} +0 -0
  331. /package/dist/{utils/suggestions.mjs.map → chunk-NB2FKV2V.mjs.map} +0 -0
  332. /package/dist/{chunk-MGWRDFBE.mjs.map → chunk-OVYFRPSN.mjs.map} +0 -0
  333. /package/dist/{chunk-MQYWH4E6.mjs.map → chunk-QU6NONOD.mjs.map} +0 -0
  334. /package/dist/{chunk-OKCYPO4I.mjs.map → chunk-WMJVBMUX.mjs.map} +0 -0
@@ -1,1142 +0,0 @@
1
- import React, { useCallback, useEffect, useMemo, useRef } from "react";
2
- import { flushSync } from "react-dom";
3
- import {
4
- FunctionCallHandler,
5
- COPILOT_CLOUD_PUBLIC_API_KEY_HEADER,
6
- CoAgentStateRenderHandler,
7
- randomId,
8
- parseJson,
9
- CopilotKitError,
10
- CopilotKitErrorCode,
11
- } from "@copilotkit/shared";
12
- import {
13
- Message,
14
- TextMessage,
15
- ResultMessage,
16
- convertMessagesToGqlInput,
17
- filterAdjacentAgentStateMessages,
18
- filterAgentStateMessages,
19
- convertGqlOutputToMessages,
20
- MessageStatusCode,
21
- MessageRole,
22
- Role,
23
- CopilotRequestType,
24
- ForwardedParametersInput,
25
- loadMessagesFromJsonRepresentation,
26
- ExtensionsInput,
27
- CopilotRuntimeClient,
28
- langGraphInterruptEvent,
29
- MetaEvent,
30
- MetaEventName,
31
- ActionExecutionMessage,
32
- CopilotKitLangGraphInterruptEvent,
33
- LangGraphInterruptEvent,
34
- MetaEventInput,
35
- AgentStateInput,
36
- } from "@copilotkit/runtime-client-gql";
37
-
38
- import { CopilotApiConfig } from "../context";
39
- import { FrontendAction, processActionsForRuntimeRequest } from "../types/frontend-action";
40
- import { CoagentState } from "../types/coagent-state";
41
- import { AgentSession, useCopilotContext } from "../context/copilot-context";
42
- import { useCopilotRuntimeClient } from "./use-copilot-runtime-client";
43
- import { useAsyncCallback, useErrorToast } from "../components/error-boundary/error-utils";
44
- import { useToast } from "../components/toast/toast-provider";
45
- import {
46
- LangGraphInterruptAction,
47
- LangGraphInterruptActionSetter,
48
- } from "../types/interrupt-action";
49
-
50
- export type UseChatOptions = {
51
- /**
52
- * System messages of the chat. Defaults to an empty array.
53
- */
54
- initialMessages?: Message[];
55
- /**
56
- * Callback function to be called when a function call is received.
57
- * If the function returns a `ChatRequest` object, the request will be sent
58
- * automatically to the API and will be used to update the chat.
59
- */
60
- onFunctionCall?: FunctionCallHandler;
61
-
62
- /**
63
- * Callback function to be called when a coagent action is received.
64
- */
65
- onCoAgentStateRender?: CoAgentStateRenderHandler;
66
-
67
- /**
68
- * Function definitions to be sent to the API.
69
- */
70
- actions: FrontendAction<any>[];
71
-
72
- /**
73
- * The CopilotKit API configuration.
74
- */
75
- copilotConfig: CopilotApiConfig;
76
-
77
- /**
78
- * The current list of messages in the chat.
79
- */
80
- messages: Message[];
81
- /**
82
- * The setState-powered method to update the chat messages.
83
- */
84
- setMessages: React.Dispatch<React.SetStateAction<Message[]>>;
85
-
86
- /**
87
- * A callback to get the latest system message.
88
- */
89
- makeSystemMessageCallback: () => TextMessage;
90
-
91
- /**
92
- * Whether the API request is in progress
93
- */
94
- isLoading: boolean;
95
-
96
- /**
97
- * setState-powered method to update the isChatLoading value
98
- */
99
- setIsLoading: React.Dispatch<React.SetStateAction<boolean>>;
100
-
101
- /**
102
- * The current list of coagent states.
103
- */
104
- coagentStatesRef: React.RefObject<Record<string, CoagentState>>;
105
-
106
- /**
107
- * setState-powered method to update the agent states
108
- */
109
- setCoagentStatesWithRef: React.Dispatch<React.SetStateAction<Record<string, CoagentState>>>;
110
-
111
- /**
112
- * The current agent session.
113
- */
114
- agentSession: AgentSession | null;
115
-
116
- /**
117
- * setState-powered method to update the agent session
118
- */
119
- setAgentSession: React.Dispatch<React.SetStateAction<AgentSession | null>>;
120
-
121
- /**
122
- * The forwarded parameters.
123
- */
124
- forwardedParameters?: Pick<ForwardedParametersInput, "temperature">;
125
-
126
- /**
127
- * The current thread ID.
128
- */
129
- threadId: string;
130
- /**
131
- * set the current thread ID
132
- */
133
- setThreadId: (threadId: string) => void;
134
- /**
135
- * The current run ID.
136
- */
137
- runId: string | null;
138
- /**
139
- * set the current run ID
140
- */
141
- setRunId: (runId: string | null) => void;
142
- /**
143
- * The global chat abort controller.
144
- */
145
- chatAbortControllerRef: React.MutableRefObject<AbortController | null>;
146
- /**
147
- * The agent lock.
148
- */
149
- agentLock: string | null;
150
- /**
151
- * The extensions.
152
- */
153
- extensions: ExtensionsInput;
154
- /**
155
- * The setState-powered method to update the extensions.
156
- */
157
- setExtensions: React.Dispatch<React.SetStateAction<ExtensionsInput>>;
158
-
159
- langGraphInterruptAction: LangGraphInterruptAction | null;
160
-
161
- setLangGraphInterruptAction: LangGraphInterruptActionSetter;
162
-
163
- disableSystemMessage?: boolean;
164
- };
165
-
166
- export type UseChatHelpers = {
167
- /**
168
- * Append a user message to the chat list. This triggers the API call to fetch
169
- * the assistant's response.
170
- * @param message The message to append
171
- */
172
- append: (message: Message, options?: AppendMessageOptions) => Promise<void>;
173
- /**
174
- * Reload the last AI chat response for the given chat history. If the last
175
- * message isn't from the assistant, it will request the API to generate a
176
- * new response.
177
- */
178
- reload: (messageId: string) => Promise<void>;
179
- /**
180
- * Abort the current request immediately, keep the generated tokens if any.
181
- */
182
- stop: () => void;
183
-
184
- /**
185
- * Run the chat completion.
186
- */
187
- runChatCompletion: () => Promise<Message[]>;
188
- };
189
-
190
- export interface AppendMessageOptions {
191
- /**
192
- * Whether to run the chat completion after appending the message. Defaults to `true`.
193
- */
194
- followUp?: boolean;
195
- /**
196
- * Whether to clear the suggestions after appending the message. Defaults to `true`.
197
- */
198
- clearSuggestions?: boolean;
199
- }
200
-
201
- export function useChat(options: UseChatOptions): UseChatHelpers {
202
- const {
203
- messages,
204
- setMessages,
205
- makeSystemMessageCallback,
206
- copilotConfig,
207
- setIsLoading,
208
- initialMessages,
209
- isLoading,
210
- actions,
211
- onFunctionCall,
212
- onCoAgentStateRender,
213
- setCoagentStatesWithRef,
214
- coagentStatesRef,
215
- agentSession,
216
- setAgentSession,
217
- threadId,
218
- setThreadId,
219
- runId,
220
- setRunId,
221
- chatAbortControllerRef,
222
- agentLock,
223
- extensions,
224
- setExtensions,
225
- langGraphInterruptAction,
226
- setLangGraphInterruptAction,
227
- disableSystemMessage = false,
228
- } = options;
229
- const runChatCompletionRef = useRef<(previousMessages: Message[]) => Promise<Message[]>>();
230
- const addErrorToast = useErrorToast();
231
- const { setBannerError } = useToast();
232
-
233
- // Get onError from context since it's not part of copilotConfig
234
- const { onError, showDevConsole, getAllContext } = useCopilotContext();
235
-
236
- const copilotReadableContext = getAllContext();
237
-
238
- const context = useMemo(
239
- () =>
240
- copilotReadableContext.map((contextItem) => {
241
- const [description, ...valueParts] = contextItem.value.split(":");
242
- return {
243
- description: description.trim(),
244
- value: valueParts.join(":").trim(),
245
- };
246
- }),
247
- [copilotReadableContext],
248
- );
249
-
250
- // Add tracing functionality to use-chat
251
- const traceUIError = async (error: CopilotKitError, originalError?: any) => {
252
- try {
253
- const traceEvent = {
254
- type: "error" as const,
255
- timestamp: Date.now(),
256
- context: {
257
- source: "ui" as const,
258
- request: {
259
- operation: "useChatCompletion",
260
- url: copilotConfig.chatApiEndpoint,
261
- startTime: Date.now(),
262
- },
263
- technical: {
264
- environment: "browser",
265
- userAgent: typeof navigator !== "undefined" ? navigator.userAgent : undefined,
266
- stackTrace: originalError instanceof Error ? originalError.stack : undefined,
267
- },
268
- },
269
- error,
270
- };
271
-
272
- await onError(traceEvent);
273
- } catch (traceError) {
274
- console.error("Error in use-chat onError handler:", traceError);
275
- }
276
- };
277
- // We need to keep a ref of coagent states and session because of renderAndWait - making sure
278
- // the latest state is sent to the API
279
- // This is a workaround and needs to be addressed in the future
280
- const agentSessionRef = useRef<AgentSession | null>(agentSession);
281
- agentSessionRef.current = agentSession;
282
-
283
- const runIdRef = useRef<string | null>(runId);
284
- runIdRef.current = runId;
285
- const extensionsRef = useRef<ExtensionsInput>(extensions);
286
- extensionsRef.current = extensions;
287
-
288
- const publicApiKey = copilotConfig.publicApiKey;
289
-
290
- const headers = {
291
- ...(copilotConfig.headers || {}),
292
- ...(publicApiKey ? { [COPILOT_CLOUD_PUBLIC_API_KEY_HEADER]: publicApiKey } : {}),
293
- };
294
-
295
- const runtimeClient = useCopilotRuntimeClient({
296
- url: copilotConfig.chatApiEndpoint,
297
- publicApiKey: copilotConfig.publicApiKey,
298
- headers,
299
- credentials: copilotConfig.credentials,
300
- showDevConsole,
301
- onError,
302
- });
303
-
304
- const pendingAppendsRef = useRef<{ message: Message; followUp: boolean }[]>([]);
305
-
306
- const runChatCompletion = useAsyncCallback(
307
- async (previousMessages: Message[]): Promise<Message[]> => {
308
- setIsLoading(true);
309
- const interruptEvent = langGraphInterruptAction?.event;
310
- // In case an interrupt event exist and valid but has no response yet, we cannot process further messages to an agent
311
- if (
312
- interruptEvent?.name === MetaEventName.LangGraphInterruptEvent &&
313
- interruptEvent?.value &&
314
- !interruptEvent?.response &&
315
- agentSessionRef.current
316
- ) {
317
- addErrorToast([
318
- new Error(
319
- "A message was sent while interrupt is active. This will cause failure on the agent side",
320
- ),
321
- ]);
322
- }
323
-
324
- // this message is just a placeholder. It will disappear once the first real message
325
- // is received
326
- let newMessages: Message[] = [
327
- new TextMessage({
328
- content: "",
329
- role: Role.Assistant,
330
- }),
331
- ];
332
-
333
- chatAbortControllerRef.current = new AbortController();
334
-
335
- setMessages([...previousMessages, ...newMessages]);
336
-
337
- const messagesWithContext = disableSystemMessage
338
- ? [...(initialMessages || []), ...previousMessages]
339
- : [makeSystemMessageCallback(), ...(initialMessages || []), ...previousMessages];
340
-
341
- // ----- Set mcpServers in properties -----
342
- // Create a copy of properties to avoid modifying the original object
343
- const finalProperties = { ...(copilotConfig.properties || {}) };
344
-
345
- // Look for mcpServers in either direct property or properties
346
- let mcpServersToUse = null;
347
-
348
- // First check direct mcpServers property
349
- if (
350
- copilotConfig.mcpServers &&
351
- Array.isArray(copilotConfig.mcpServers) &&
352
- copilotConfig.mcpServers.length > 0
353
- ) {
354
- mcpServersToUse = copilotConfig.mcpServers;
355
- }
356
- // Then check mcpServers in properties
357
- else if (
358
- copilotConfig.properties?.mcpServers &&
359
- Array.isArray(copilotConfig.properties.mcpServers) &&
360
- copilotConfig.properties.mcpServers.length > 0
361
- ) {
362
- mcpServersToUse = copilotConfig.properties.mcpServers;
363
- }
364
-
365
- // Apply the mcpServers to properties if found
366
- if (mcpServersToUse) {
367
- // Set in finalProperties
368
- finalProperties.mcpServers = mcpServersToUse;
369
-
370
- // Also set in copilotConfig directly for future use
371
- copilotConfig.mcpServers = mcpServersToUse;
372
- }
373
- // -------------------------------------------------------------
374
-
375
- const isAgentRun = agentSessionRef.current !== null;
376
-
377
- const stream = runtimeClient.asStream(
378
- runtimeClient.generateCopilotResponse({
379
- data: {
380
- frontend: {
381
- actions: processActionsForRuntimeRequest(actions),
382
- url: window.location.href,
383
- },
384
- threadId: threadId,
385
- runId: runIdRef.current,
386
- extensions: extensionsRef.current,
387
- metaEvents: composeAndFlushMetaEventsInput([langGraphInterruptAction?.event]),
388
- messages: convertMessagesToGqlInput(filterAgentStateMessages(messagesWithContext)),
389
- ...(copilotConfig.cloud
390
- ? {
391
- cloud: {
392
- ...(copilotConfig.cloud.guardrails?.input?.restrictToTopic?.enabled
393
- ? {
394
- guardrails: {
395
- inputValidationRules: {
396
- allowList:
397
- copilotConfig.cloud.guardrails.input.restrictToTopic.validTopics,
398
- denyList:
399
- copilotConfig.cloud.guardrails.input.restrictToTopic.invalidTopics,
400
- },
401
- },
402
- }
403
- : {}),
404
- },
405
- }
406
- : {}),
407
- metadata: {
408
- requestType: CopilotRequestType.Chat,
409
- },
410
- ...(agentSessionRef.current
411
- ? {
412
- agentSession: agentSessionRef.current,
413
- }
414
- : {}),
415
- agentStates: Object.values(coagentStatesRef.current!).map((state) => {
416
- const stateObject: AgentStateInput = {
417
- agentName: state.name,
418
- state: JSON.stringify(state.state),
419
- };
420
-
421
- if (state.config !== undefined) {
422
- stateObject.config = JSON.stringify(state.config);
423
- }
424
-
425
- return stateObject;
426
- }),
427
- forwardedParameters: options.forwardedParameters || {},
428
- context,
429
- },
430
- properties: finalProperties,
431
- signal: chatAbortControllerRef.current?.signal,
432
- }),
433
- );
434
-
435
- const guardrailsEnabled =
436
- copilotConfig.cloud?.guardrails?.input?.restrictToTopic.enabled || false;
437
-
438
- const reader = stream.getReader();
439
-
440
- let executedCoAgentStateRenders: string[] = [];
441
- let followUp: FrontendAction["followUp"] = undefined;
442
-
443
- let messages: Message[] = [];
444
- let syncedMessages: Message[] = [];
445
- let interruptMessages: Message[] = [];
446
-
447
- try {
448
- while (true) {
449
- let done, value;
450
-
451
- try {
452
- const readResult = await reader.read();
453
- done = readResult.done;
454
- value = readResult.value;
455
- } catch (readError) {
456
- break;
457
- }
458
-
459
- if (done) {
460
- if (chatAbortControllerRef.current.signal.aborted) {
461
- return [];
462
- }
463
- break;
464
- }
465
-
466
- if (!value?.generateCopilotResponse) {
467
- continue;
468
- }
469
-
470
- runIdRef.current = value.generateCopilotResponse.runId || null;
471
-
472
- // in the output, graphql inserts __typename, which leads to an error when sending it along
473
- // as input to the next request.
474
- extensionsRef.current = CopilotRuntimeClient.removeGraphQLTypename(
475
- value.generateCopilotResponse.extensions || {},
476
- );
477
-
478
- // setThreadId(threadIdRef.current);
479
- setRunId(runIdRef.current);
480
- setExtensions(extensionsRef.current);
481
- let rawMessagesResponse = value.generateCopilotResponse.messages;
482
-
483
- const metaEvents: MetaEvent[] | undefined =
484
- value.generateCopilotResponse?.metaEvents ?? [];
485
- (metaEvents ?? []).forEach((ev) => {
486
- if (ev.name === MetaEventName.LangGraphInterruptEvent) {
487
- let eventValue = langGraphInterruptEvent(ev as LangGraphInterruptEvent).value;
488
- eventValue = parseJson(eventValue, eventValue);
489
- setLangGraphInterruptAction(threadId, {
490
- event: {
491
- ...langGraphInterruptEvent(ev as LangGraphInterruptEvent),
492
- value: eventValue,
493
- },
494
- });
495
- }
496
- if (ev.name === MetaEventName.CopilotKitLangGraphInterruptEvent) {
497
- const data = (ev as CopilotKitLangGraphInterruptEvent).data;
498
-
499
- // @ts-expect-error -- same type of messages
500
- rawMessagesResponse = [...rawMessagesResponse, ...data.messages];
501
- interruptMessages = convertGqlOutputToMessages(
502
- // @ts-ignore
503
- filterAdjacentAgentStateMessages(data.messages),
504
- );
505
- }
506
- });
507
-
508
- messages = convertGqlOutputToMessages(
509
- filterAdjacentAgentStateMessages(rawMessagesResponse),
510
- );
511
-
512
- newMessages = [];
513
-
514
- // Handle error statuses BEFORE checking if there are messages
515
- // (errors can come in chunks with no messages)
516
-
517
- // request failed, display error message and quit
518
- if (
519
- value.generateCopilotResponse.status?.__typename === "FailedResponseStatus" &&
520
- value.generateCopilotResponse.status.reason === "GUARDRAILS_VALIDATION_FAILED"
521
- ) {
522
- const guardrailsReason =
523
- value.generateCopilotResponse.status.details?.guardrailsReason || "";
524
-
525
- newMessages = [
526
- new TextMessage({
527
- role: MessageRole.Assistant,
528
- content: guardrailsReason,
529
- }),
530
- ];
531
-
532
- // Trace guardrails validation failure
533
- const guardrailsError = new CopilotKitError({
534
- message: `Guardrails validation failed: ${guardrailsReason}`,
535
- code: CopilotKitErrorCode.MISUSE,
536
- });
537
- await traceUIError(guardrailsError, {
538
- statusReason: value.generateCopilotResponse.status.reason,
539
- statusDetails: value.generateCopilotResponse.status.details,
540
- });
541
- // TODO: if onError & renderError should work without key, insert here
542
-
543
- setMessages([...previousMessages, ...newMessages]);
544
- break;
545
- }
546
-
547
- // Handle UNKNOWN_ERROR failures (like authentication errors) by routing to banner error system
548
- if (
549
- value.generateCopilotResponse.status?.__typename === "FailedResponseStatus" &&
550
- value.generateCopilotResponse.status.reason === "UNKNOWN_ERROR"
551
- ) {
552
- const errorMessage =
553
- value.generateCopilotResponse.status.details?.description ||
554
- "An unknown error occurred";
555
-
556
- // Try to extract original error information from the response details
557
- const statusDetails = value.generateCopilotResponse.status.details;
558
- const originalError = statusDetails?.originalError || statusDetails?.error;
559
-
560
- // Extract structured error information if available (prioritize top-level over extensions)
561
- const originalCode = originalError?.code || originalError?.extensions?.code;
562
- const originalSeverity = originalError?.severity || originalError?.extensions?.severity;
563
- const originalVisibility =
564
- originalError?.visibility || originalError?.extensions?.visibility;
565
-
566
- // Use the original error code if available, otherwise default to NETWORK_ERROR
567
- let errorCode = CopilotKitErrorCode.NETWORK_ERROR;
568
- if (originalCode && Object.values(CopilotKitErrorCode).includes(originalCode)) {
569
- errorCode = originalCode;
570
- }
571
-
572
- // Create a structured CopilotKitError preserving original error information
573
- const structuredError = new CopilotKitError({
574
- message: errorMessage,
575
- code: errorCode,
576
- severity: originalSeverity,
577
- visibility: originalVisibility,
578
- });
579
-
580
- // Display the error in the banner
581
- setBannerError(structuredError);
582
-
583
- // Trace the error for debugging/observability
584
- await traceUIError(structuredError, {
585
- statusReason: value.generateCopilotResponse.status.reason,
586
- statusDetails: value.generateCopilotResponse.status.details,
587
- originalErrorCode: originalCode,
588
- preservedStructure: !!originalCode,
589
- });
590
- // TODO: if onError & renderError should work without key, insert here
591
-
592
- // Stop processing and break from the loop
593
- setIsLoading(false);
594
- throw new Error(structuredError.message);
595
- }
596
-
597
- // add messages to the chat
598
- else if (messages.length > 0) {
599
- newMessages = [...messages];
600
-
601
- for (const message of messages) {
602
- // execute onCoAgentStateRender handler
603
- if (
604
- message.isAgentStateMessage() &&
605
- !message.active &&
606
- !executedCoAgentStateRenders.includes(message.id) &&
607
- onCoAgentStateRender
608
- ) {
609
- // Do not execute a coagent action if guardrails are enabled but the status is not known
610
- if (guardrailsEnabled && value.generateCopilotResponse.status === undefined) {
611
- break;
612
- }
613
- // execute coagent action
614
- await onCoAgentStateRender({
615
- name: message.agentName,
616
- nodeName: message.nodeName,
617
- state: message.state,
618
- });
619
- executedCoAgentStateRenders.push(message.id);
620
- }
621
- }
622
-
623
- const lastAgentStateMessage = [...messages]
624
- .reverse()
625
- .find((message) => message.isAgentStateMessage());
626
-
627
- if (lastAgentStateMessage) {
628
- if (
629
- lastAgentStateMessage.state.messages &&
630
- lastAgentStateMessage.state.messages.length > 0
631
- ) {
632
- syncedMessages = loadMessagesFromJsonRepresentation(
633
- lastAgentStateMessage.state.messages,
634
- );
635
- }
636
- setCoagentStatesWithRef((prevAgentStates) => ({
637
- ...prevAgentStates,
638
- [lastAgentStateMessage.agentName]: {
639
- name: lastAgentStateMessage.agentName,
640
- state: lastAgentStateMessage.state,
641
- running: lastAgentStateMessage.running,
642
- active: lastAgentStateMessage.active,
643
- threadId: lastAgentStateMessage.threadId,
644
- nodeName: lastAgentStateMessage.nodeName,
645
- runId: lastAgentStateMessage.runId,
646
- // Preserve existing config from previous state
647
- config: prevAgentStates[lastAgentStateMessage.agentName]?.config,
648
- },
649
- }));
650
- if (lastAgentStateMessage.running) {
651
- setAgentSession({
652
- threadId: lastAgentStateMessage.threadId,
653
- agentName: lastAgentStateMessage.agentName,
654
- nodeName: lastAgentStateMessage.nodeName,
655
- });
656
- } else {
657
- if (agentLock) {
658
- setAgentSession({
659
- threadId: randomId(),
660
- agentName: agentLock,
661
- nodeName: undefined,
662
- });
663
- } else {
664
- setAgentSession(null);
665
- }
666
- }
667
- }
668
- }
669
-
670
- if (newMessages.length > 0) {
671
- // Update message state
672
- setMessages([...previousMessages, ...newMessages]);
673
- }
674
- }
675
- let finalMessages = constructFinalMessages(
676
- [...syncedMessages, ...interruptMessages],
677
- previousMessages,
678
- newMessages,
679
- );
680
-
681
- let didExecuteAction = false;
682
-
683
- // ----- Helper function to execute an action and manage its lifecycle -----
684
- const executeActionFromMessage = async (
685
- currentAction: FrontendAction<any>,
686
- actionMessage: ActionExecutionMessage,
687
- ) => {
688
- const isInterruptAction = interruptMessages.find((m) => m.id === actionMessage.id);
689
- // Determine follow-up behavior: use action's specific setting if defined, otherwise default based on interrupt status.
690
- followUp = currentAction?.followUp ?? !isInterruptAction;
691
-
692
- // Call _setActivatingMessageId before executing the action for HITL correlation
693
- if ((currentAction as any)?._setActivatingMessageId) {
694
- (currentAction as any)._setActivatingMessageId(actionMessage.id);
695
- }
696
-
697
- const resultMessage = await executeAction({
698
- onFunctionCall: onFunctionCall!,
699
- message: actionMessage,
700
- chatAbortControllerRef,
701
- onError: (error: Error) => {
702
- addErrorToast([error]);
703
- // console.error is kept here as it's a genuine error in action execution
704
- console.error(`Failed to execute action ${actionMessage.name}: ${error}`);
705
- },
706
- setMessages,
707
- getFinalMessages: () => finalMessages,
708
- isRenderAndWait: (currentAction as any)?._isRenderAndWait || false,
709
- });
710
- didExecuteAction = true;
711
- const messageIndex = finalMessages.findIndex((msg) => msg.id === actionMessage.id);
712
- finalMessages.splice(messageIndex + 1, 0, resultMessage);
713
-
714
- // If the executed action was a renderAndWaitForResponse type, update messages immediately
715
- // to reflect its completion in the UI, making it interactive promptly.
716
- if ((currentAction as any)?._isRenderAndWait) {
717
- const messagesForImmediateUpdate = [...finalMessages];
718
- flushSync(() => {
719
- setMessages(messagesForImmediateUpdate);
720
- });
721
- }
722
-
723
- // Clear _setActivatingMessageId after the action is done
724
- if ((currentAction as any)?._setActivatingMessageId) {
725
- (currentAction as any)._setActivatingMessageId(null);
726
- }
727
-
728
- return resultMessage;
729
- };
730
- // ----------------------------------------------------------------------
731
-
732
- // execute regular action executions that are specific to the frontend (last actions)
733
- if (onFunctionCall) {
734
- // Find consecutive action execution messages at the end
735
- const lastMessages = [];
736
-
737
- for (let i = finalMessages.length - 1; i >= 0; i--) {
738
- const message = finalMessages[i];
739
- if (
740
- (message.isActionExecutionMessage() || message.isResultMessage()) &&
741
- message.status.code !== MessageStatusCode.Pending
742
- ) {
743
- lastMessages.unshift(message);
744
- } else if (!message.isAgentStateMessage()) {
745
- break;
746
- }
747
- }
748
-
749
- for (const message of lastMessages) {
750
- // We update the message state before calling the handler so that the render
751
- // function can be called with `executing` state
752
- setMessages(finalMessages);
753
-
754
- const action = actions.find(
755
- (action) => action.name === (message as ActionExecutionMessage).name,
756
- );
757
- if (action && action.available === "frontend") {
758
- // never execute frontend actions
759
- continue;
760
- }
761
- const currentResultMessagePairedFeAction = message.isResultMessage()
762
- ? getPairedFeAction(actions, message)
763
- : null;
764
-
765
- // execution message which has an action registered with the hook (remote availability):
766
- // execute that action first, and then the "paired FE action"
767
- if (action && message.isActionExecutionMessage()) {
768
- // For HITL actions, check if they've already been processed to avoid redundant handler calls.
769
- const isRenderAndWaitAction = (action as any)?._isRenderAndWait || false;
770
- const alreadyProcessed =
771
- isRenderAndWaitAction &&
772
- finalMessages.some(
773
- (fm) => fm.isResultMessage() && fm.actionExecutionId === message.id,
774
- );
775
-
776
- if (alreadyProcessed) {
777
- // Skip re-execution if already processed
778
- } else {
779
- // Call the single, externally defined executeActionFromMessage
780
- const resultMessage = await executeActionFromMessage(
781
- action,
782
- message as ActionExecutionMessage,
783
- );
784
- const pairedFeAction = getPairedFeAction(actions, resultMessage);
785
-
786
- if (pairedFeAction) {
787
- const newExecutionMessage = new ActionExecutionMessage({
788
- name: pairedFeAction.name,
789
- arguments: parseJson(resultMessage.result, resultMessage.result),
790
- status: message.status,
791
- createdAt: message.createdAt,
792
- parentMessageId: message.parentMessageId,
793
- });
794
- // Call the single, externally defined executeActionFromMessage
795
- await executeActionFromMessage(pairedFeAction, newExecutionMessage);
796
- }
797
- }
798
- } else if (message.isResultMessage() && currentResultMessagePairedFeAction) {
799
- // Actions which are set up in runtime actions array: Grab the result, executed paired FE action with it as args.
800
- const newExecutionMessage = new ActionExecutionMessage({
801
- name: currentResultMessagePairedFeAction.name,
802
- arguments: parseJson(message.result, message.result),
803
- status: message.status,
804
- createdAt: message.createdAt,
805
- });
806
- finalMessages.push(newExecutionMessage);
807
- // Call the single, externally defined executeActionFromMessage
808
- await executeActionFromMessage(
809
- currentResultMessagePairedFeAction,
810
- newExecutionMessage,
811
- );
812
- }
813
- }
814
-
815
- setMessages(finalMessages);
816
- }
817
-
818
- // Conditionally run chat completion again if followUp is not explicitly false
819
- // and an action was executed or the last message is a server-side result (for non-agent runs).
820
- if (
821
- followUp !== false &&
822
- (didExecuteAction ||
823
- // the last message is a server side result
824
- (!isAgentRun &&
825
- finalMessages.length &&
826
- finalMessages[finalMessages.length - 1].isResultMessage())) &&
827
- // the user did not stop generation
828
- !chatAbortControllerRef.current?.signal.aborted
829
- ) {
830
- // run the completion again and return the result
831
-
832
- // wait for next tick to make sure all the react state updates
833
- // - tried using react-dom's flushSync, but it did not work
834
- await new Promise((resolve) => setTimeout(resolve, 10));
835
-
836
- return await runChatCompletionRef.current!(finalMessages);
837
- } else if (chatAbortControllerRef.current?.signal.aborted) {
838
- // filter out all the action execution messages that do not have a consecutive matching result message
839
- const repairedMessages = finalMessages.filter((message, actionExecutionIndex) => {
840
- if (message.isActionExecutionMessage()) {
841
- return finalMessages.find(
842
- (msg, resultIndex) =>
843
- msg.isResultMessage() &&
844
- msg.actionExecutionId === message.id &&
845
- resultIndex === actionExecutionIndex + 1,
846
- );
847
- }
848
- return true;
849
- });
850
- const repairedMessageIds = repairedMessages.map((message) => message.id);
851
- setMessages(repairedMessages);
852
-
853
- // LangGraph needs two pieces of information to continue execution:
854
- // 1. The threadId
855
- // 2. The nodeName it came from
856
- // When stopping the agent, we don't know the nodeName the agent would have ended with
857
- // Therefore, we set the nodeName to the most reasonable thing we can guess, which
858
- // is "__end__"
859
- if (agentSessionRef.current?.nodeName) {
860
- setAgentSession({
861
- threadId: agentSessionRef.current.threadId,
862
- agentName: agentSessionRef.current.agentName,
863
- nodeName: "__end__",
864
- });
865
- }
866
- // only return new messages that were not filtered out
867
- return newMessages.filter((message) => repairedMessageIds.includes(message.id));
868
- } else {
869
- return newMessages.slice();
870
- }
871
- } finally {
872
- setIsLoading(false);
873
- }
874
- },
875
- [
876
- messages,
877
- setMessages,
878
- makeSystemMessageCallback,
879
- copilotConfig,
880
- setIsLoading,
881
- initialMessages,
882
- isLoading,
883
- actions,
884
- onFunctionCall,
885
- onCoAgentStateRender,
886
- setCoagentStatesWithRef,
887
- coagentStatesRef,
888
- agentSession,
889
- setAgentSession,
890
- disableSystemMessage,
891
- context,
892
- ],
893
- );
894
-
895
- runChatCompletionRef.current = runChatCompletion;
896
-
897
- const runChatCompletionAndHandleFunctionCall = useAsyncCallback(
898
- async (messages: Message[]): Promise<void> => {
899
- await runChatCompletionRef.current!(messages);
900
- },
901
- [messages],
902
- );
903
-
904
- useEffect(() => {
905
- if (!isLoading && pendingAppendsRef.current.length > 0) {
906
- const pending = pendingAppendsRef.current.splice(0);
907
- const followUp = pending.some((p) => p.followUp);
908
- const newMessages = [...messages, ...pending.map((p) => p.message)];
909
- setMessages(newMessages);
910
- if (followUp) {
911
- runChatCompletionAndHandleFunctionCall(newMessages);
912
- }
913
- }
914
- }, [isLoading, messages, setMessages, runChatCompletionAndHandleFunctionCall]);
915
-
916
- // Go over all events and see that they include data that should be returned to the agent
917
- const composeAndFlushMetaEventsInput = useCallback(
918
- (metaEvents: (MetaEvent | undefined | null)[]) => {
919
- return metaEvents.reduce((acc: MetaEventInput[], event) => {
920
- if (!event) return acc;
921
-
922
- switch (event.name) {
923
- case MetaEventName.LangGraphInterruptEvent:
924
- if (event.response) {
925
- // Flush interrupt event from state
926
- setLangGraphInterruptAction(threadId, null);
927
- const value = (event as LangGraphInterruptEvent).value;
928
- return [
929
- ...acc,
930
- {
931
- name: event.name,
932
- value: typeof value === "string" ? value : JSON.stringify(value),
933
- response:
934
- typeof event.response === "string"
935
- ? event.response
936
- : JSON.stringify(event.response),
937
- },
938
- ];
939
- }
940
- return acc;
941
- default:
942
- return acc;
943
- }
944
- }, []);
945
- },
946
- [setLangGraphInterruptAction],
947
- );
948
-
949
- const append = useAsyncCallback(
950
- async (message: Message, options?: AppendMessageOptions): Promise<void> => {
951
- const followUp = options?.followUp ?? true;
952
- if (isLoading) {
953
- pendingAppendsRef.current.push({ message, followUp });
954
- return;
955
- }
956
-
957
- const newMessages = [...messages, message];
958
- setMessages(newMessages);
959
- if (followUp) {
960
- return runChatCompletionAndHandleFunctionCall(newMessages);
961
- }
962
- },
963
- [isLoading, messages, setMessages, runChatCompletionAndHandleFunctionCall],
964
- );
965
-
966
- const reload = useAsyncCallback(
967
- async (reloadMessageId: string): Promise<void> => {
968
- if (isLoading || messages.length === 0) {
969
- return;
970
- }
971
-
972
- const reloadMessageIndex = messages.findIndex((msg) => msg.id === reloadMessageId);
973
- if (reloadMessageIndex === -1) {
974
- console.warn(`Message with id ${reloadMessageId} not found`);
975
- return;
976
- }
977
-
978
- // @ts-expect-error -- message has role
979
- const reloadMessageRole = messages[reloadMessageIndex].role;
980
- if (reloadMessageRole !== MessageRole.Assistant) {
981
- console.warn(`Regenerate cannot be performed on ${reloadMessageRole} role`);
982
- return;
983
- }
984
- let historyCutoff: Message[] = [messages[0]];
985
-
986
- if (messages.length > 2 && reloadMessageIndex !== 0) {
987
- // message to regenerate from is now first.
988
- // Work backwards to find the first the closest user message
989
- const lastUserMessageBeforeRegenerate = messages
990
- .slice(0, reloadMessageIndex)
991
- .reverse()
992
- .find(
993
- (msg) =>
994
- // @ts-expect-error -- message has role
995
- msg.role === MessageRole.User,
996
- );
997
- const indexOfLastUserMessageBeforeRegenerate = messages.findIndex(
998
- (msg) => msg.id === lastUserMessageBeforeRegenerate!.id,
999
- );
1000
-
1001
- // Include the user message, remove everything after it
1002
- historyCutoff = messages.slice(0, indexOfLastUserMessageBeforeRegenerate + 1);
1003
- } else if (messages.length > 2 && reloadMessageIndex === 0) {
1004
- historyCutoff = [messages[0], messages[1]];
1005
- }
1006
-
1007
- setMessages(historyCutoff);
1008
-
1009
- return runChatCompletionAndHandleFunctionCall(historyCutoff);
1010
- },
1011
- [isLoading, messages, setMessages, runChatCompletionAndHandleFunctionCall],
1012
- );
1013
-
1014
- const stop = (): void => {
1015
- chatAbortControllerRef.current?.abort("Stop was called");
1016
- };
1017
-
1018
- return {
1019
- append,
1020
- reload,
1021
- stop,
1022
- runChatCompletion: () => runChatCompletionRef.current!(messages),
1023
- };
1024
- }
1025
-
1026
- function constructFinalMessages(
1027
- syncedMessages: Message[],
1028
- previousMessages: Message[],
1029
- newMessages: Message[],
1030
- ): Message[] {
1031
- const finalMessages =
1032
- syncedMessages.length > 0 ? [...syncedMessages] : [...previousMessages, ...newMessages];
1033
-
1034
- if (syncedMessages.length > 0) {
1035
- const messagesWithAgentState = [...previousMessages, ...newMessages];
1036
-
1037
- let previousMessageId: string | undefined = undefined;
1038
-
1039
- for (const message of messagesWithAgentState) {
1040
- if (message.isAgentStateMessage()) {
1041
- // insert this message into finalMessages after the position of previousMessageId
1042
- const index = finalMessages.findIndex((msg) => msg.id === previousMessageId);
1043
- if (index !== -1) {
1044
- finalMessages.splice(index + 1, 0, message);
1045
- }
1046
- }
1047
-
1048
- previousMessageId = message.id;
1049
- }
1050
- }
1051
-
1052
- return finalMessages;
1053
- }
1054
-
1055
- async function executeAction({
1056
- onFunctionCall,
1057
- message,
1058
- chatAbortControllerRef,
1059
- onError,
1060
- setMessages,
1061
- getFinalMessages,
1062
- isRenderAndWait,
1063
- }: {
1064
- onFunctionCall: FunctionCallHandler;
1065
- message: ActionExecutionMessage;
1066
- chatAbortControllerRef: React.MutableRefObject<AbortController | null>;
1067
- onError: (error: Error) => void;
1068
- setMessages: React.Dispatch<React.SetStateAction<Message[]>>;
1069
- getFinalMessages: () => Message[];
1070
- isRenderAndWait: boolean;
1071
- }) {
1072
- let result: any;
1073
- let error: Error | null = null;
1074
-
1075
- const currentMessagesForHandler = getFinalMessages();
1076
-
1077
- // The handler (onFunctionCall) runs its synchronous part here, potentially setting up
1078
- // renderAndWaitRef.current for HITL actions via useCopilotAction's transformed handler.
1079
- const handlerReturnedPromise = onFunctionCall({
1080
- messages: currentMessagesForHandler,
1081
- name: message.name,
1082
- args: message.arguments,
1083
- });
1084
-
1085
- // For HITL actions, call flushSync immediately after their handler has set up the promise
1086
- // and before awaiting the promise. This ensures the UI updates to an interactive state.
1087
- if (isRenderAndWait) {
1088
- const currentMessagesForRender = getFinalMessages();
1089
- flushSync(() => {
1090
- setMessages([...currentMessagesForRender]);
1091
- });
1092
- }
1093
-
1094
- try {
1095
- result = await Promise.race([
1096
- handlerReturnedPromise, // Await the promise returned by the handler
1097
- new Promise((resolve) =>
1098
- chatAbortControllerRef.current?.signal.addEventListener("abort", () =>
1099
- resolve("Operation was aborted by the user"),
1100
- ),
1101
- ),
1102
- // if the user stopped generation, we also abort consecutive actions
1103
- new Promise((resolve) => {
1104
- if (chatAbortControllerRef.current?.signal.aborted) {
1105
- resolve("Operation was aborted by the user");
1106
- }
1107
- }),
1108
- ]);
1109
- } catch (e) {
1110
- onError(e as Error);
1111
- }
1112
- return new ResultMessage({
1113
- id: "result-" + message.id,
1114
- result: ResultMessage.encodeResult(
1115
- error
1116
- ? {
1117
- content: result,
1118
- error: JSON.parse(JSON.stringify(error, Object.getOwnPropertyNames(error))),
1119
- }
1120
- : result,
1121
- ),
1122
- actionExecutionId: message.id,
1123
- actionName: message.name,
1124
- });
1125
- }
1126
-
1127
- function getPairedFeAction(
1128
- actions: FrontendAction<any>[],
1129
- message: ActionExecutionMessage | ResultMessage,
1130
- ) {
1131
- let actionName = null;
1132
- if (message.isActionExecutionMessage()) {
1133
- actionName = message.name;
1134
- } else if (message.isResultMessage()) {
1135
- actionName = message.actionName;
1136
- }
1137
- return actions.find(
1138
- (action) =>
1139
- (action.name === actionName && action.available === "frontend") ||
1140
- action.pairedAction === actionName,
1141
- );
1142
- }