@datalayer/agent-runtimes 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (571) hide show
  1. package/LICENSE +32 -0
  2. package/README.md +56 -0
  3. package/lib/App.css +47 -0
  4. package/lib/App.d.ts +3 -0
  5. package/lib/App.js +18 -0
  6. package/lib/components/chat/components/AgentDetails.d.ts +19 -0
  7. package/lib/components/chat/components/AgentDetails.js +170 -0
  8. package/lib/components/chat/components/Chat.d.ts +105 -0
  9. package/lib/components/chat/components/Chat.js +275 -0
  10. package/lib/components/chat/components/ChatFloating.d.ts +146 -0
  11. package/lib/components/chat/components/ChatFloating.js +381 -0
  12. package/lib/components/chat/components/ChatInline.d.ts +42 -0
  13. package/lib/components/chat/components/ChatInline.js +327 -0
  14. package/lib/components/chat/components/ChatPopupStandalone.d.ts +110 -0
  15. package/lib/components/chat/components/ChatPopupStandalone.js +422 -0
  16. package/lib/components/chat/components/ChatSidebar.d.ts +78 -0
  17. package/lib/components/chat/components/ChatSidebar.js +224 -0
  18. package/lib/components/chat/components/ChatStandalone.d.ts +105 -0
  19. package/lib/components/chat/components/ChatStandalone.js +320 -0
  20. package/lib/components/chat/components/base/ChatBase.d.ts +285 -0
  21. package/lib/components/chat/components/base/ChatBase.js +1192 -0
  22. package/lib/components/chat/components/display/ToolCallDisplay.d.ts +26 -0
  23. package/lib/components/chat/components/display/ToolCallDisplay.js +225 -0
  24. package/lib/components/chat/components/display/index.d.ts +6 -0
  25. package/lib/components/chat/components/display/index.js +10 -0
  26. package/lib/components/chat/components/elements/ChatHeader.d.ts +43 -0
  27. package/lib/components/chat/components/elements/ChatHeader.js +67 -0
  28. package/lib/components/chat/components/elements/ChatInputPrompt.d.ts +26 -0
  29. package/lib/components/chat/components/elements/ChatInputPrompt.js +145 -0
  30. package/lib/components/chat/components/elements/ChatMessages.d.ts +36 -0
  31. package/lib/components/chat/components/elements/ChatMessages.js +195 -0
  32. package/lib/components/chat/components/elements/FloatingBrandButton.d.ts +34 -0
  33. package/lib/components/chat/components/elements/FloatingBrandButton.js +88 -0
  34. package/lib/components/chat/components/elements/MessagePart.d.ts +50 -0
  35. package/lib/components/chat/components/elements/MessagePart.js +48 -0
  36. package/lib/components/chat/components/elements/PoweredByTag.d.ts +26 -0
  37. package/lib/components/chat/components/elements/PoweredByTag.js +33 -0
  38. package/lib/components/chat/components/elements/ToolApprovalDialog.d.ts +42 -0
  39. package/lib/components/chat/components/elements/ToolApprovalDialog.js +96 -0
  40. package/lib/components/chat/components/index.d.ts +21 -0
  41. package/lib/components/chat/components/index.js +34 -0
  42. package/lib/components/chat/components/parts/DynamicToolPart.d.ts +20 -0
  43. package/lib/components/chat/components/parts/DynamicToolPart.js +13 -0
  44. package/lib/components/chat/components/parts/ReasoningPart.d.ts +17 -0
  45. package/lib/components/chat/components/parts/ReasoningPart.js +69 -0
  46. package/lib/components/chat/components/parts/TextPart.d.ts +28 -0
  47. package/lib/components/chat/components/parts/TextPart.js +103 -0
  48. package/lib/components/chat/components/parts/ToolPart.d.ts +17 -0
  49. package/lib/components/chat/components/parts/ToolPart.js +163 -0
  50. package/lib/components/chat/components/parts/index.d.ts +9 -0
  51. package/lib/components/chat/components/parts/index.js +13 -0
  52. package/lib/components/chat/extensions/A2UIExtension.d.ts +87 -0
  53. package/lib/components/chat/extensions/A2UIExtension.js +312 -0
  54. package/lib/components/chat/extensions/ExtensionRegistry.d.ts +66 -0
  55. package/lib/components/chat/extensions/ExtensionRegistry.js +128 -0
  56. package/lib/components/chat/extensions/MCPUIExtension.d.ts +77 -0
  57. package/lib/components/chat/extensions/MCPUIExtension.js +212 -0
  58. package/lib/components/chat/extensions/index.d.ts +9 -0
  59. package/lib/components/chat/extensions/index.js +12 -0
  60. package/lib/components/chat/handler.d.ts +20 -0
  61. package/lib/components/chat/handler.js +56 -0
  62. package/lib/components/chat/index.d.ts +61 -0
  63. package/lib/components/chat/index.js +76 -0
  64. package/lib/components/chat/inference/BaseInferenceProvider.d.ts +57 -0
  65. package/lib/components/chat/inference/BaseInferenceProvider.js +69 -0
  66. package/lib/components/chat/inference/DatalayerInferenceProvider.d.ts +83 -0
  67. package/lib/components/chat/inference/DatalayerInferenceProvider.js +305 -0
  68. package/lib/components/chat/inference/SelfHostedInferenceProvider.d.ts +54 -0
  69. package/lib/components/chat/inference/SelfHostedInferenceProvider.js +246 -0
  70. package/lib/components/chat/inference/index.d.ts +9 -0
  71. package/lib/components/chat/inference/index.js +12 -0
  72. package/lib/components/chat/middleware/MiddlewarePipeline.d.ts +118 -0
  73. package/lib/components/chat/middleware/MiddlewarePipeline.js +255 -0
  74. package/lib/components/chat/middleware/index.d.ts +7 -0
  75. package/lib/components/chat/middleware/index.js +10 -0
  76. package/lib/components/chat/protocols/A2AAdapter.d.ts +79 -0
  77. package/lib/components/chat/protocols/A2AAdapter.js +388 -0
  78. package/lib/components/chat/protocols/ACPAdapter.d.ts +161 -0
  79. package/lib/components/chat/protocols/ACPAdapter.js +504 -0
  80. package/lib/components/chat/protocols/AGUIAdapter.d.ts +82 -0
  81. package/lib/components/chat/protocols/AGUIAdapter.js +518 -0
  82. package/lib/components/chat/protocols/BaseProtocolAdapter.d.ts +75 -0
  83. package/lib/components/chat/protocols/BaseProtocolAdapter.js +119 -0
  84. package/lib/components/chat/protocols/VercelAIAdapter.d.ts +77 -0
  85. package/lib/components/chat/protocols/VercelAIAdapter.js +252 -0
  86. package/lib/components/chat/protocols/index.d.ts +11 -0
  87. package/lib/components/chat/protocols/index.js +14 -0
  88. package/lib/components/chat/store/chatStore.d.ts +158 -0
  89. package/lib/components/chat/store/chatStore.js +313 -0
  90. package/lib/components/chat/store/index.d.ts +6 -0
  91. package/lib/components/chat/store/index.js +10 -0
  92. package/lib/components/chat/tools/ToolExecutor.d.ts +49 -0
  93. package/lib/components/chat/tools/ToolExecutor.js +151 -0
  94. package/lib/components/chat/tools/index.d.ts +8 -0
  95. package/lib/components/chat/tools/index.js +11 -0
  96. package/lib/components/chat/types/extension.d.ts +181 -0
  97. package/lib/components/chat/types/extension.js +46 -0
  98. package/lib/components/chat/types/index.d.ts +11 -0
  99. package/lib/components/chat/types/index.js +16 -0
  100. package/lib/components/chat/types/inference.d.ts +117 -0
  101. package/lib/components/chat/types/inference.js +5 -0
  102. package/lib/components/chat/types/message.d.ts +117 -0
  103. package/lib/components/chat/types/message.js +50 -0
  104. package/lib/components/chat/types/middleware.d.ts +153 -0
  105. package/lib/components/chat/types/middleware.js +32 -0
  106. package/lib/components/chat/types/protocol.d.ts +209 -0
  107. package/lib/components/chat/types/protocol.js +5 -0
  108. package/lib/components/chat/types/tool.d.ts +140 -0
  109. package/lib/components/chat/types/tool.js +23 -0
  110. package/lib/components/index.d.ts +1 -0
  111. package/lib/components/index.js +6 -0
  112. package/lib/components/sparklines/Sparklines.d.ts +16 -0
  113. package/lib/components/sparklines/Sparklines.js +65 -0
  114. package/lib/components/sparklines/SparklinesLine.d.ts +8 -0
  115. package/lib/components/sparklines/SparklinesLine.js +37 -0
  116. package/lib/components/sparklines/dataProcessing.d.ts +25 -0
  117. package/lib/components/sparklines/dataProcessing.js +35 -0
  118. package/lib/components/sparklines/index.d.ts +4 -0
  119. package/lib/components/sparklines/index.js +7 -0
  120. package/lib/components/sparklines/types.d.ts +36 -0
  121. package/lib/components/sparklines/types.js +5 -0
  122. package/lib/components/ui/accordion.d.ts +7 -0
  123. package/lib/components/ui/accordion.js +22 -0
  124. package/lib/components/ui/alert-dialog.d.ts +14 -0
  125. package/lib/components/ui/alert-dialog.js +43 -0
  126. package/lib/components/ui/alert.d.ts +9 -0
  127. package/lib/components/ui/alert.js +24 -0
  128. package/lib/components/ui/aspect-ratio.d.ts +3 -0
  129. package/lib/components/ui/aspect-ratio.js +11 -0
  130. package/lib/components/ui/avatar.d.ts +6 -0
  131. package/lib/components/ui/avatar.js +18 -0
  132. package/lib/components/ui/badge.d.ts +9 -0
  133. package/lib/components/ui/badge.js +22 -0
  134. package/lib/components/ui/breadcrumb.d.ts +11 -0
  135. package/lib/components/ui/breadcrumb.js +27 -0
  136. package/lib/components/ui/button-group.d.ts +11 -0
  137. package/lib/components/ui/button-group.js +31 -0
  138. package/lib/components/ui/button.d.ts +13 -0
  139. package/lib/components/ui/button.js +39 -0
  140. package/lib/components/ui/calendar.d.ts +8 -0
  141. package/lib/components/ui/calendar.js +80 -0
  142. package/lib/components/ui/card.d.ts +9 -0
  143. package/lib/components/ui/card.js +24 -0
  144. package/lib/components/ui/carousel.d.ts +19 -0
  145. package/lib/components/ui/carousel.js +95 -0
  146. package/lib/components/ui/chart.d.ts +53 -0
  147. package/lib/components/ui/chart.js +136 -0
  148. package/lib/components/ui/checkbox.d.ts +4 -0
  149. package/lib/components/ui/checkbox.js +13 -0
  150. package/lib/components/ui/collapsible.d.ts +5 -0
  151. package/lib/components/ui/collapsible.js +17 -0
  152. package/lib/components/ui/command.d.ts +18 -0
  153. package/lib/components/ui/command.js +38 -0
  154. package/lib/components/ui/context-menu.d.ts +25 -0
  155. package/lib/components/ui/context-menu.js +55 -0
  156. package/lib/components/ui/dialog.d.ts +15 -0
  157. package/lib/components/ui/dialog.js +40 -0
  158. package/lib/components/ui/drawer.d.ts +13 -0
  159. package/lib/components/ui/drawer.js +39 -0
  160. package/lib/components/ui/dropdown-menu.d.ts +25 -0
  161. package/lib/components/ui/dropdown-menu.js +55 -0
  162. package/lib/components/ui/empty.d.ts +11 -0
  163. package/lib/components/ui/empty.js +37 -0
  164. package/lib/components/ui/field.d.ts +24 -0
  165. package/lib/components/ui/field.js +80 -0
  166. package/lib/components/ui/form.d.ts +24 -0
  167. package/lib/components/ui/form.js +63 -0
  168. package/lib/components/ui/hover-card.d.ts +6 -0
  169. package/lib/components/ui/hover-card.js +18 -0
  170. package/lib/components/ui/input-group.d.ts +19 -0
  171. package/lib/components/ui/input-group.js +69 -0
  172. package/lib/components/ui/input-otp.d.ts +11 -0
  173. package/lib/components/ui/input-otp.js +25 -0
  174. package/lib/components/ui/input.d.ts +3 -0
  175. package/lib/components/ui/input.js +6 -0
  176. package/lib/components/ui/item.d.ts +23 -0
  177. package/lib/components/ui/item.js +66 -0
  178. package/lib/components/ui/kbd.d.ts +3 -0
  179. package/lib/components/ui/kbd.js +13 -0
  180. package/lib/components/ui/label.d.ts +4 -0
  181. package/lib/components/ui/label.js +12 -0
  182. package/lib/components/ui/menubar.d.ts +26 -0
  183. package/lib/components/ui/menubar.js +58 -0
  184. package/lib/components/ui/navigation-menu.d.ts +14 -0
  185. package/lib/components/ui/navigation-menu.js +31 -0
  186. package/lib/components/ui/pagination.d.ts +13 -0
  187. package/lib/components/ui/pagination.js +29 -0
  188. package/lib/components/ui/popover.d.ts +7 -0
  189. package/lib/components/ui/popover.js +21 -0
  190. package/lib/components/ui/progress.d.ts +4 -0
  191. package/lib/components/ui/progress.js +12 -0
  192. package/lib/components/ui/radio-group.d.ts +5 -0
  193. package/lib/components/ui/radio-group.js +16 -0
  194. package/lib/components/ui/resizable.d.ts +8 -0
  195. package/lib/components/ui/resizable.js +19 -0
  196. package/lib/components/ui/scroll-area.d.ts +5 -0
  197. package/lib/components/ui/scroll-area.js +17 -0
  198. package/lib/components/ui/select.d.ts +15 -0
  199. package/lib/components/ui/select.js +42 -0
  200. package/lib/components/ui/separator.d.ts +4 -0
  201. package/lib/components/ui/separator.js +12 -0
  202. package/lib/components/ui/sheet.d.ts +13 -0
  203. package/lib/components/ui/sheet.js +44 -0
  204. package/lib/components/ui/sidebar.d.ts +69 -0
  205. package/lib/components/ui/sidebar.js +216 -0
  206. package/lib/components/ui/skeleton.d.ts +2 -0
  207. package/lib/components/ui/skeleton.js +10 -0
  208. package/lib/components/ui/slider.d.ts +4 -0
  209. package/lib/components/ui/slider.js +18 -0
  210. package/lib/components/ui/sonner.d.ts +3 -0
  211. package/lib/components/ui/sonner.js +25 -0
  212. package/lib/components/ui/spinner.d.ts +2 -0
  213. package/lib/components/ui/spinner.js +11 -0
  214. package/lib/components/ui/switch.d.ts +4 -0
  215. package/lib/components/ui/switch.js +12 -0
  216. package/lib/components/ui/table.d.ts +10 -0
  217. package/lib/components/ui/table.js +32 -0
  218. package/lib/components/ui/tabs.d.ts +7 -0
  219. package/lib/components/ui/tabs.js +21 -0
  220. package/lib/components/ui/textarea.d.ts +3 -0
  221. package/lib/components/ui/textarea.js +6 -0
  222. package/lib/components/ui/toast.d.ts +15 -0
  223. package/lib/components/ui/toast.js +38 -0
  224. package/lib/components/ui/toaster.d.ts +1 -0
  225. package/lib/components/ui/toaster.js +14 -0
  226. package/lib/components/ui/toggle-group.d.ts +9 -0
  227. package/lib/components/ui/toggle-group.js +26 -0
  228. package/lib/components/ui/toggle.d.ts +9 -0
  229. package/lib/components/ui/toggle.js +30 -0
  230. package/lib/components/ui/tooltip.d.ts +7 -0
  231. package/lib/components/ui/tooltip.js +21 -0
  232. package/lib/components/vercel-ai-elements/artifact.d.ts +23 -0
  233. package/lib/components/vercel-ai-elements/artifact.js +24 -0
  234. package/lib/components/vercel-ai-elements/code-block.d.ts +17 -0
  235. package/lib/components/vercel-ai-elements/code-block.js +94 -0
  236. package/lib/components/vercel-ai-elements/conversation.d.ts +15 -0
  237. package/lib/components/vercel-ai-elements/conversation.js +21 -0
  238. package/lib/components/vercel-ai-elements/loader.d.ts +5 -0
  239. package/lib/components/vercel-ai-elements/loader.js +8 -0
  240. package/lib/components/vercel-ai-elements/message.d.ts +46 -0
  241. package/lib/components/vercel-ai-elements/message.js +109 -0
  242. package/lib/components/vercel-ai-elements/model-selector.d.ts +35 -0
  243. package/lib/components/vercel-ai-elements/model-selector.js +22 -0
  244. package/lib/components/vercel-ai-elements/prompt-input.d.ts +195 -0
  245. package/lib/components/vercel-ai-elements/prompt-input.js +589 -0
  246. package/lib/components/vercel-ai-elements/reasoning.d.ts +26 -0
  247. package/lib/components/vercel-ai-elements/reasoning.js +80 -0
  248. package/lib/components/vercel-ai-elements/shimmer.d.ts +9 -0
  249. package/lib/components/vercel-ai-elements/shimmer.js +22 -0
  250. package/lib/components/vercel-ai-elements/sources.d.ts +12 -0
  251. package/lib/components/vercel-ai-elements/sources.js +13 -0
  252. package/lib/components/vercel-ai-elements/suggestion.d.ts +10 -0
  253. package/lib/components/vercel-ai-elements/suggestion.js +16 -0
  254. package/lib/components/vercel-ai-elements/tool.d.ts +23 -0
  255. package/lib/components/vercel-ai-elements/tool.js +52 -0
  256. package/lib/examples/A2UiRestaurantExample.d.ts +25 -0
  257. package/lib/examples/A2UiRestaurantExample.js +305 -0
  258. package/lib/examples/AgUiAgenticExample.d.ts +25 -0
  259. package/lib/examples/AgUiAgenticExample.js +63 -0
  260. package/lib/examples/AgUiBackendToolRenderingExample.d.ts +30 -0
  261. package/lib/examples/AgUiBackendToolRenderingExample.js +103 -0
  262. package/lib/examples/AgUiHaikuGenUIExample.d.ts +44 -0
  263. package/lib/examples/AgUiHaikuGenUIExample.js +151 -0
  264. package/lib/examples/AgUiHumanInTheLoopExample.d.ts +26 -0
  265. package/lib/examples/AgUiHumanInTheLoopExample.js +220 -0
  266. package/lib/examples/AgUiSharedStateExample.d.ts +25 -0
  267. package/lib/examples/AgUiSharedStateExample.js +181 -0
  268. package/lib/examples/AgUiToolsBasedGenUIExample.d.ts +25 -0
  269. package/lib/examples/AgUiToolsBasedGenUIExample.js +257 -0
  270. package/lib/examples/AgentRuntimeCustomExample.d.ts +9 -0
  271. package/lib/examples/AgentRuntimeCustomExample.js +68 -0
  272. package/lib/examples/AgentRuntimeLexical2Example.d.ts +42 -0
  273. package/lib/examples/AgentRuntimeLexical2Example.js +236 -0
  274. package/lib/examples/AgentRuntimeLexicalExample.d.ts +36 -0
  275. package/lib/examples/AgentRuntimeLexicalExample.js +260 -0
  276. package/lib/examples/AgentRuntimeLexicalSidebarExample.d.ts +41 -0
  277. package/lib/examples/AgentRuntimeLexicalSidebarExample.js +166 -0
  278. package/lib/examples/AgentRuntimeNotebookExample.d.ts +9 -0
  279. package/lib/examples/AgentRuntimeNotebookExample.js +148 -0
  280. package/lib/examples/AgentRuntimeNotebookSidebarExample.d.ts +13 -0
  281. package/lib/examples/AgentRuntimeNotebookSidebarExample.js +121 -0
  282. package/lib/examples/AgentRuntimeStandaloneExample.d.ts +21 -0
  283. package/lib/examples/AgentRuntimeStandaloneExample.js +158 -0
  284. package/lib/examples/AgentSpaceFormExample.d.ts +22 -0
  285. package/lib/examples/AgentSpaceFormExample.js +296 -0
  286. package/lib/examples/AgentSpaceHomeExample.d.ts +8 -0
  287. package/lib/examples/AgentSpaceHomeExample.js +171 -0
  288. package/lib/examples/CopilotKitLexicalExample.d.ts +38 -0
  289. package/lib/examples/CopilotKitLexicalExample.js +161 -0
  290. package/lib/examples/CopilotKitNotebookExample.d.ts +11 -0
  291. package/lib/examples/CopilotKitNotebookExample.js +70 -0
  292. package/lib/examples/DatalayerNotebookExample.d.ts +16 -0
  293. package/lib/examples/DatalayerNotebookExample.js +99 -0
  294. package/lib/examples/JupyterCellExample.d.ts +6 -0
  295. package/lib/examples/JupyterCellExample.js +19 -0
  296. package/lib/examples/JupyterNotebookExample.d.ts +6 -0
  297. package/lib/examples/JupyterNotebookExample.js +21 -0
  298. package/lib/examples/ag-ui/haiku/HaikuDisplay.d.ts +18 -0
  299. package/lib/examples/ag-ui/haiku/HaikuDisplay.js +110 -0
  300. package/lib/examples/ag-ui/haiku/InlineHaikuCard.d.ts +39 -0
  301. package/lib/examples/ag-ui/haiku/InlineHaikuCard.js +117 -0
  302. package/lib/examples/ag-ui/haiku/index.d.ts +11 -0
  303. package/lib/examples/ag-ui/haiku/index.js +15 -0
  304. package/lib/examples/ag-ui/index.d.ts +10 -0
  305. package/lib/examples/ag-ui/index.js +16 -0
  306. package/lib/examples/ag-ui/weather/InlineWeatherCard.d.ts +43 -0
  307. package/lib/examples/ag-ui/weather/InlineWeatherCard.js +180 -0
  308. package/lib/examples/ag-ui/weather/index.d.ts +9 -0
  309. package/lib/examples/ag-ui/weather/index.js +13 -0
  310. package/lib/examples/components/AgentConfiguration.d.ts +50 -0
  311. package/lib/examples/components/AgentConfiguration.js +115 -0
  312. package/lib/examples/components/AgentsDataTable.d.ts +13 -0
  313. package/lib/examples/components/AgentsDataTable.js +74 -0
  314. package/lib/examples/components/FooterMetrics.d.ts +12 -0
  315. package/lib/examples/components/FooterMetrics.js +17 -0
  316. package/lib/examples/components/Header.d.ts +27 -0
  317. package/lib/examples/components/Header.js +294 -0
  318. package/lib/examples/components/HeaderControls.d.ts +11 -0
  319. package/lib/examples/components/HeaderControls.js +24 -0
  320. package/lib/examples/components/LexicalEditor.d.ts +27 -0
  321. package/lib/examples/components/LexicalEditor.js +118 -0
  322. package/lib/examples/components/MainContent.d.ts +19 -0
  323. package/lib/examples/components/MainContent.js +68 -0
  324. package/lib/examples/components/MockFileBrowser.d.ts +12 -0
  325. package/lib/examples/components/MockFileBrowser.js +131 -0
  326. package/lib/examples/components/Rating.d.ts +14 -0
  327. package/lib/examples/components/Rating.js +12 -0
  328. package/lib/examples/components/SessionTabs.d.ts +21 -0
  329. package/lib/examples/components/SessionTabs.js +11 -0
  330. package/lib/examples/components/TimeTravel.d.ts +15 -0
  331. package/lib/examples/components/TimeTravel.js +23 -0
  332. package/lib/examples/components/index.d.ts +11 -0
  333. package/lib/examples/components/index.js +14 -0
  334. package/lib/examples/example-selector.d.ts +22 -0
  335. package/lib/examples/example-selector.js +62 -0
  336. package/lib/examples/index.d.ts +21 -0
  337. package/lib/examples/index.js +25 -0
  338. package/lib/examples/lexical/editorConfig.d.ts +76 -0
  339. package/lib/examples/lexical/editorConfig.js +55 -0
  340. package/lib/examples/lexical/lexical-theme.css +436 -0
  341. package/lib/examples/lexical/theme.d.ts +61 -0
  342. package/lib/examples/lexical/theme.js +72 -0
  343. package/lib/examples/main.d.ts +2 -0
  344. package/lib/examples/main.js +334 -0
  345. package/lib/examples/stores/agents/earthquake-detector.ipynb.json +111 -0
  346. package/lib/examples/stores/agents/earthquake-detector.json +13 -0
  347. package/lib/examples/stores/agents/earthquake-detector.lexical.json +2988 -0
  348. package/lib/examples/stores/agents/sales-forecaster.ipynb.json +111 -0
  349. package/lib/examples/stores/agents/sales-forecaster.json +13 -0
  350. package/lib/examples/stores/agents/sales-forecaster.lexical.json +2988 -0
  351. package/lib/examples/stores/agents/social-post-generator.ipynb.json +111 -0
  352. package/lib/examples/stores/agents/social-post-generator.json +13 -0
  353. package/lib/examples/stores/agents/social-post-generator.lexical.json +2988 -0
  354. package/lib/examples/stores/agents/stock-market.ipynb.json +56 -0
  355. package/lib/examples/stores/agents/stock-market.json +13 -0
  356. package/lib/examples/stores/agents/stock-market.lexical.json +1026 -0
  357. package/lib/examples/stores/examplesStore.d.ts +26 -0
  358. package/lib/examples/stores/examplesStore.js +60 -0
  359. package/lib/examples/stores/notebooks/Empty.ipynb.json +33 -0
  360. package/lib/examples/stores/notebooks/IPyWidgetsExample.ipynb.json +101 -0
  361. package/lib/examples/stores/notebooks/IPyWidgetsExampleWithState.ipynb.json +112 -0
  362. package/lib/examples/stores/notebooks/Lite.ipynb.json +128 -0
  363. package/lib/examples/stores/notebooks/Matplotlib.ipynb.json +137 -0
  364. package/lib/examples/stores/notebooks/NotebookExample1.ipynb.json +126 -0
  365. package/lib/examples/stores/notebooks/NotebookExample2.ipynb.json +48 -0
  366. package/lib/examples/stores/notebooks/NotebookOutputs.ipynb.json +49 -0
  367. package/lib/examples/stores/notebooks/NotebookToCExample.ipynb.json +102 -0
  368. package/lib/examples/stores/notebooks/OutputIPyWidgetsExample.d.ts +145 -0
  369. package/lib/examples/stores/notebooks/OutputIPyWidgetsExample.js +153 -0
  370. package/lib/examples/stores/notebooks/PyGWalker.ipynb.json +55 -0
  371. package/lib/examples/vercel-ai-elements/VercelAiElementsShowcase.d.ts +12 -0
  372. package/lib/examples/vercel-ai-elements/VercelAiElementsShowcase.js +69 -0
  373. package/lib/examples/vercel-ai-elements/components/ArtifactShowcase.d.ts +1 -0
  374. package/lib/examples/vercel-ai-elements/components/ArtifactShowcase.js +85 -0
  375. package/lib/examples/vercel-ai-elements/components/CodeBlockShowcase.d.ts +1 -0
  376. package/lib/examples/vercel-ai-elements/components/CodeBlockShowcase.js +62 -0
  377. package/lib/examples/vercel-ai-elements/components/ConversationShowcase.d.ts +1 -0
  378. package/lib/examples/vercel-ai-elements/components/ConversationShowcase.js +51 -0
  379. package/lib/examples/vercel-ai-elements/components/LoaderShowcase.d.ts +1 -0
  380. package/lib/examples/vercel-ai-elements/components/LoaderShowcase.js +9 -0
  381. package/lib/examples/vercel-ai-elements/components/MessageShowcase.d.ts +1 -0
  382. package/lib/examples/vercel-ai-elements/components/MessageShowcase.js +56 -0
  383. package/lib/examples/vercel-ai-elements/components/ModelSelectorShowcase.d.ts +1 -0
  384. package/lib/examples/vercel-ai-elements/components/ModelSelectorShowcase.js +50 -0
  385. package/lib/examples/vercel-ai-elements/components/PromptInputShowcase.d.ts +1 -0
  386. package/lib/examples/vercel-ai-elements/components/PromptInputShowcase.js +16 -0
  387. package/lib/examples/vercel-ai-elements/components/ReasoningShowcase.d.ts +1 -0
  388. package/lib/examples/vercel-ai-elements/components/ReasoningShowcase.js +72 -0
  389. package/lib/examples/vercel-ai-elements/components/ShimmerShowcase.d.ts +1 -0
  390. package/lib/examples/vercel-ai-elements/components/ShimmerShowcase.js +9 -0
  391. package/lib/examples/vercel-ai-elements/components/SourcesShowcase.d.ts +1 -0
  392. package/lib/examples/vercel-ai-elements/components/SourcesShowcase.js +43 -0
  393. package/lib/examples/vercel-ai-elements/components/SuggestionShowcase.d.ts +1 -0
  394. package/lib/examples/vercel-ai-elements/components/SuggestionShowcase.js +31 -0
  395. package/lib/examples/vercel-ai-elements/components/ToolShowcase.d.ts +1 -0
  396. package/lib/examples/vercel-ai-elements/components/ToolShowcase.js +54 -0
  397. package/lib/examples/vercel-ai-elements/index.d.ts +13 -0
  398. package/lib/examples/vercel-ai-elements/index.js +17 -0
  399. package/lib/examples/vercel-ai-elements/main.d.ts +1 -0
  400. package/lib/examples/vercel-ai-elements/main.js +9 -0
  401. package/lib/examples/vercel-ai-elements/showcase.css +128 -0
  402. package/lib/hooks/index.d.ts +68 -0
  403. package/lib/hooks/index.js +81 -0
  404. package/lib/hooks/useA2A.d.ts +75 -0
  405. package/lib/hooks/useA2A.js +368 -0
  406. package/lib/hooks/useAGUI.d.ts +63 -0
  407. package/lib/hooks/useAGUI.js +162 -0
  408. package/lib/hooks/useAcp.d.ts +121 -0
  409. package/lib/hooks/useAcp.js +459 -0
  410. package/lib/hooks/useAgents.d.ts +13 -0
  411. package/lib/hooks/useAgents.js +71 -0
  412. package/lib/hooks/useChat.d.ts +62 -0
  413. package/lib/hooks/useChat.js +363 -0
  414. package/lib/hooks/useKeyboardShortcuts.d.ts +47 -0
  415. package/lib/hooks/useKeyboardShortcuts.js +153 -0
  416. package/lib/hooks/useMobile.d.ts +1 -0
  417. package/lib/hooks/useMobile.js +19 -0
  418. package/lib/hooks/useNotebookAIAgent.d.ts +8 -0
  419. package/lib/hooks/useNotebookAIAgent.js +56 -0
  420. package/lib/hooks/useToast.d.ts +44 -0
  421. package/lib/hooks/useToast.js +128 -0
  422. package/lib/hooks/useTools.d.ts +107 -0
  423. package/lib/hooks/useTools.js +130 -0
  424. package/lib/hooks/useVercelChat.d.ts +45 -0
  425. package/lib/hooks/useVercelChat.js +62 -0
  426. package/lib/index.css +73 -0
  427. package/lib/index.d.ts +1 -0
  428. package/lib/index.js +5 -0
  429. package/lib/lexical/ChatInlinePlugin.d.ts +21 -0
  430. package/lib/lexical/ChatInlinePlugin.js +379 -0
  431. package/lib/lexical/index.d.ts +6 -0
  432. package/lib/lexical/index.js +10 -0
  433. package/lib/lib/utils.d.ts +2 -0
  434. package/lib/lib/utils.js +9 -0
  435. package/lib/main.d.ts +1 -0
  436. package/lib/main.js +12 -0
  437. package/lib/models/AIAgent.d.ts +17 -0
  438. package/lib/models/AIAgent.js +5 -0
  439. package/lib/models/index.d.ts +1 -0
  440. package/lib/models/index.js +5 -0
  441. package/lib/renderers/a2ui/components/A2UIRenderer.d.ts +7 -0
  442. package/lib/renderers/a2ui/components/A2UIRenderer.js +102 -0
  443. package/lib/renderers/a2ui/components/SurfaceRenderer.d.ts +7 -0
  444. package/lib/renderers/a2ui/components/SurfaceRenderer.js +101 -0
  445. package/lib/renderers/a2ui/components/content/AudioPlayer.d.ts +9 -0
  446. package/lib/renderers/a2ui/components/content/AudioPlayer.js +38 -0
  447. package/lib/renderers/a2ui/components/content/Divider.d.ts +9 -0
  448. package/lib/renderers/a2ui/components/content/Divider.js +35 -0
  449. package/lib/renderers/a2ui/components/content/Icon.d.ts +9 -0
  450. package/lib/renderers/a2ui/components/content/Icon.js +110 -0
  451. package/lib/renderers/a2ui/components/content/Image.d.ts +9 -0
  452. package/lib/renderers/a2ui/components/content/Image.js +61 -0
  453. package/lib/renderers/a2ui/components/content/Text.d.ts +9 -0
  454. package/lib/renderers/a2ui/components/content/Text.js +64 -0
  455. package/lib/renderers/a2ui/components/content/Video.d.ts +9 -0
  456. package/lib/renderers/a2ui/components/content/Video.js +37 -0
  457. package/lib/renderers/a2ui/components/content/index.d.ts +6 -0
  458. package/lib/renderers/a2ui/components/content/index.js +25 -0
  459. package/lib/renderers/a2ui/components/index.d.ts +5 -0
  460. package/lib/renderers/a2ui/components/index.js +24 -0
  461. package/lib/renderers/a2ui/components/interactive/Button.d.ts +11 -0
  462. package/lib/renderers/a2ui/components/interactive/Button.js +71 -0
  463. package/lib/renderers/a2ui/components/interactive/CheckBox.d.ts +9 -0
  464. package/lib/renderers/a2ui/components/interactive/CheckBox.js +48 -0
  465. package/lib/renderers/a2ui/components/interactive/DateTimeInput.d.ts +9 -0
  466. package/lib/renderers/a2ui/components/interactive/DateTimeInput.js +62 -0
  467. package/lib/renderers/a2ui/components/interactive/MultipleChoice.d.ts +9 -0
  468. package/lib/renderers/a2ui/components/interactive/MultipleChoice.js +73 -0
  469. package/lib/renderers/a2ui/components/interactive/Slider.d.ts +9 -0
  470. package/lib/renderers/a2ui/components/interactive/Slider.js +53 -0
  471. package/lib/renderers/a2ui/components/interactive/TextField.d.ts +9 -0
  472. package/lib/renderers/a2ui/components/interactive/TextField.js +72 -0
  473. package/lib/renderers/a2ui/components/interactive/index.d.ts +6 -0
  474. package/lib/renderers/a2ui/components/interactive/index.js +25 -0
  475. package/lib/renderers/a2ui/components/layout/Card.d.ts +11 -0
  476. package/lib/renderers/a2ui/components/layout/Card.js +30 -0
  477. package/lib/renderers/a2ui/components/layout/Column.d.ts +11 -0
  478. package/lib/renderers/a2ui/components/layout/Column.js +65 -0
  479. package/lib/renderers/a2ui/components/layout/List.d.ts +11 -0
  480. package/lib/renderers/a2ui/components/layout/List.js +55 -0
  481. package/lib/renderers/a2ui/components/layout/Modal.d.ts +11 -0
  482. package/lib/renderers/a2ui/components/layout/Modal.js +58 -0
  483. package/lib/renderers/a2ui/components/layout/Row.d.ts +11 -0
  484. package/lib/renderers/a2ui/components/layout/Row.js +65 -0
  485. package/lib/renderers/a2ui/components/layout/Tabs.d.ts +11 -0
  486. package/lib/renderers/a2ui/components/layout/Tabs.js +48 -0
  487. package/lib/renderers/a2ui/components/layout/index.d.ts +6 -0
  488. package/lib/renderers/a2ui/components/layout/index.js +25 -0
  489. package/lib/renderers/a2ui/context/A2UIContext.d.ts +17 -0
  490. package/lib/renderers/a2ui/context/A2UIContext.js +54 -0
  491. package/lib/renderers/a2ui/context/ThemeContext.d.ts +20 -0
  492. package/lib/renderers/a2ui/context/ThemeContext.js +333 -0
  493. package/lib/renderers/a2ui/hooks/useA2UI.d.ts +36 -0
  494. package/lib/renderers/a2ui/hooks/useA2UI.js +62 -0
  495. package/lib/renderers/a2ui/hooks/useDataBinding.d.ts +8 -0
  496. package/lib/renderers/a2ui/hooks/useDataBinding.js +83 -0
  497. package/lib/renderers/a2ui/index.d.ts +9 -0
  498. package/lib/renderers/a2ui/index.js +28 -0
  499. package/lib/renderers/a2ui/lib/utils.d.ts +11 -0
  500. package/lib/renderers/a2ui/lib/utils.js +38 -0
  501. package/lib/renderers/a2ui/types/index.d.ts +17 -0
  502. package/lib/renderers/a2ui/types/index.js +5 -0
  503. package/lib/renderers/index.d.ts +1 -0
  504. package/lib/renderers/index.js +5 -0
  505. package/lib/state/index.d.ts +1 -0
  506. package/lib/state/index.js +5 -0
  507. package/lib/state/substates/AIAgentState.d.ts +11 -0
  508. package/lib/state/substates/AIAgentState.js +42 -0
  509. package/lib/state/substates/index.d.ts +1 -0
  510. package/lib/state/substates/index.js +5 -0
  511. package/lib/stories/Button.d.ts +15 -0
  512. package/lib/stories/Button.js +13 -0
  513. package/lib/stories/Button.stories.d.ts +23 -0
  514. package/lib/stories/Button.stories.js +48 -0
  515. package/lib/stories/Cell.stories.d.ts +12 -0
  516. package/lib/stories/Cell.stories.js +123 -0
  517. package/lib/stories/Header.d.ts +12 -0
  518. package/lib/stories/Header.js +8 -0
  519. package/lib/stories/Header.stories.d.ts +18 -0
  520. package/lib/stories/Header.stories.js +30 -0
  521. package/lib/stories/Page.d.ts +3 -0
  522. package/lib/stories/Page.js +12 -0
  523. package/lib/stories/Page.stories.d.ts +12 -0
  524. package/lib/stories/Page.stories.js +28 -0
  525. package/lib/stories/assets/accessibility.png +0 -0
  526. package/lib/stories/assets/accessibility.svg +1 -0
  527. package/lib/stories/assets/addon-library.png +0 -0
  528. package/lib/stories/assets/assets.png +0 -0
  529. package/lib/stories/assets/context.png +0 -0
  530. package/lib/stories/assets/discord.svg +1 -0
  531. package/lib/stories/assets/docs.png +0 -0
  532. package/lib/stories/assets/figma-plugin.png +0 -0
  533. package/lib/stories/assets/github.svg +1 -0
  534. package/lib/stories/assets/share.png +0 -0
  535. package/lib/stories/assets/styling.png +0 -0
  536. package/lib/stories/assets/testing.png +0 -0
  537. package/lib/stories/assets/theming.png +0 -0
  538. package/lib/stories/assets/tutorials.svg +1 -0
  539. package/lib/stories/assets/youtube.svg +1 -0
  540. package/lib/stories/button.css +35 -0
  541. package/lib/stories/header.css +37 -0
  542. package/lib/stories/page.css +73 -0
  543. package/lib/test-setup.d.ts +1 -0
  544. package/lib/test-setup.js +80 -0
  545. package/lib/tools/adapters/agent-runtimes/AgentRuntimesToolAdapter.d.ts +40 -0
  546. package/lib/tools/adapters/agent-runtimes/AgentRuntimesToolAdapter.js +110 -0
  547. package/lib/tools/adapters/agent-runtimes/index.d.ts +9 -0
  548. package/lib/tools/adapters/agent-runtimes/index.js +13 -0
  549. package/lib/tools/adapters/agent-runtimes/lexicalHooks.d.ts +24 -0
  550. package/lib/tools/adapters/agent-runtimes/lexicalHooks.js +50 -0
  551. package/lib/tools/adapters/agent-runtimes/notebookHooks.d.ts +24 -0
  552. package/lib/tools/adapters/agent-runtimes/notebookHooks.js +51 -0
  553. package/lib/tools/adapters/copilotkit/CopilotKitToolAdapter.d.ts +73 -0
  554. package/lib/tools/adapters/copilotkit/CopilotKitToolAdapter.js +244 -0
  555. package/lib/tools/adapters/copilotkit/index.d.ts +10 -0
  556. package/lib/tools/adapters/copilotkit/index.js +14 -0
  557. package/lib/tools/adapters/copilotkit/lexicalHooks.d.ts +27 -0
  558. package/lib/tools/adapters/copilotkit/lexicalHooks.js +59 -0
  559. package/lib/tools/adapters/copilotkit/notebookHooks.d.ts +27 -0
  560. package/lib/tools/adapters/copilotkit/notebookHooks.js +58 -0
  561. package/lib/tools/adapters/index.d.ts +1 -0
  562. package/lib/tools/adapters/index.js +5 -0
  563. package/lib/tools/index.d.ts +6 -0
  564. package/lib/tools/index.js +18 -0
  565. package/lib/types.d.ts +5 -0
  566. package/lib/types.js +5 -0
  567. package/package.json +327 -0
  568. package/style/animation/Animation.module.css +174 -0
  569. package/style/base.css +204 -0
  570. package/style/index.css +6 -0
  571. package/style/showcase-vercel-ai.css +137 -0
@@ -0,0 +1,1192 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /*
3
+ * Copyright (c) 2025-2026 Datalayer, Inc.
4
+ * Distributed under the terms of the Modified BSD License.
5
+ */
6
+ /**
7
+ * Main ChatBase component.
8
+ * Provides a full chat interface with messages and input.
9
+ * This is the base component used by all other chat container components.
10
+ *
11
+ * Supports multiple modes:
12
+ * 1. Store mode: Uses Zustand store for state management (default)
13
+ * 2. Protocol mode: Connects to backend via AG-UI, A2A, ACP, or Vercel AI protocols
14
+ * 3. Custom mode: Uses onSendMessage prop for custom message handling
15
+ *
16
+ * @module components/chat/components/ChatBase
17
+ */
18
+ import { useContext } from 'react';
19
+ import { useCallback, useEffect, useRef, useState, } from 'react';
20
+ import { Heading, Text, Spinner, IconButton, Textarea, Button, ActionMenu, ActionList, LabelGroup, Label, } from '@primer/react';
21
+ import { Box } from '@datalayer/primer-addons';
22
+ import { AlertIcon, PlusIcon, TrashIcon, GearIcon, PersonIcon, PaperAirplaneIcon, SquareCircleIcon, ToolsIcon, AiModelIcon, } from '@primer/octicons-react';
23
+ import { AiAgentIcon } from '@datalayer/icons-react';
24
+ import { useQuery, QueryClientContext } from '@tanstack/react-query';
25
+ import { Streamdown } from 'streamdown';
26
+ import { PoweredByTag } from '../elements/PoweredByTag';
27
+ import { requestAPI } from '../../handler';
28
+ import { useChatStore } from '../../store/chatStore';
29
+ import { generateMessageId, createUserMessage, createAssistantMessage, } from '../../types/message';
30
+ import { AGUIAdapter, A2AAdapter, VercelAIAdapter, ACPAdapter, } from '../../protocols';
31
+ import { ToolCallDisplay } from '../display/ToolCallDisplay';
32
+ /**
33
+ * Check if an item is a tool call message
34
+ */
35
+ function isToolCallMessage(item) {
36
+ return 'type' in item && item.type === 'tool-call';
37
+ }
38
+ /**
39
+ * Extract text content from a ChatMessage
40
+ */
41
+ function getMessageText(message) {
42
+ if (typeof message.content === 'string') {
43
+ return message.content;
44
+ }
45
+ // Array of ContentPart - extract text parts
46
+ return message.content
47
+ .filter((part) => part.type === 'text')
48
+ .map(part => part.text)
49
+ .join('');
50
+ }
51
+ /**
52
+ * Create protocol adapter based on configuration
53
+ */
54
+ function createProtocolAdapter(config) {
55
+ const adapterConfig = {
56
+ type: config.type,
57
+ baseUrl: config.endpoint,
58
+ authToken: config.authToken,
59
+ agentId: config.agentId,
60
+ ...config.options,
61
+ };
62
+ switch (config.type) {
63
+ case 'ag-ui':
64
+ return new AGUIAdapter(adapterConfig);
65
+ case 'a2a':
66
+ return new A2AAdapter(adapterConfig);
67
+ case 'vercel-ai':
68
+ return new VercelAIAdapter(adapterConfig);
69
+ case 'acp':
70
+ return new ACPAdapter(adapterConfig);
71
+ default:
72
+ console.warn(`[ChatBase] Unknown protocol type: ${config.type}`);
73
+ return null;
74
+ }
75
+ }
76
+ /**
77
+ * Hook to safely use query when QueryClient is available
78
+ * Returns null if no QueryClientProvider is present
79
+ */
80
+ function useConfigQuery(enabled, configEndpoint, authToken) {
81
+ const queryClient = useContext(QueryClientContext);
82
+ // If no QueryClient is available, return a mock result
83
+ if (!queryClient) {
84
+ return {
85
+ data: undefined,
86
+ isLoading: false,
87
+ isError: false,
88
+ error: null,
89
+ };
90
+ }
91
+ // eslint-disable-next-line react-hooks/rules-of-hooks
92
+ return useQuery({
93
+ queryFn: async () => {
94
+ // If configEndpoint is provided, use direct fetch (for FastAPI)
95
+ if (configEndpoint) {
96
+ const headers = {
97
+ 'Content-Type': 'application/json',
98
+ };
99
+ if (authToken) {
100
+ headers['Authorization'] = `Bearer ${authToken}`;
101
+ }
102
+ const response = await fetch(configEndpoint, { headers });
103
+ if (!response.ok) {
104
+ throw new Error(`Config fetch failed: ${response.statusText}`);
105
+ }
106
+ return response.json();
107
+ }
108
+ // Otherwise use Jupyter requestAPI
109
+ return requestAPI('configure');
110
+ },
111
+ queryKey: ['models', configEndpoint || 'jupyter'],
112
+ enabled,
113
+ });
114
+ }
115
+ /**
116
+ * ChatBase component - Universal chat panel supporting store, protocol, and custom modes
117
+ */
118
+ export function ChatBase({ title, showHeader = false, showLoadingIndicator = true, showErrors = true, showInput = true, showModelSelector = false, showToolsMenu = false, className, loadingState, headerActions,
119
+ // Mode selection
120
+ useStore: useStoreMode = true, protocol, onSendMessage, enableStreaming = false,
121
+ // Extended props
122
+ brandIcon, avatarConfig, headerButtons, showPoweredBy = false, poweredByProps, emptyState, renderToolResult, footerContent, headerContent, children, borderRadius, backgroundColor, border, boxShadow, compact = false, placeholder, description = 'Start a conversation with the AI agent.', onStateUpdate, onNewChat, onClear, onMessagesChange, autoFocus = false, suggestions, submitOnSuggestionClick = true, hideMessagesAfterToolUI = false, focusTrigger, frontendTools, }) {
123
+ // Store (optional for message persistence)
124
+ const clearStoreMessages = useChatStore(state => state.clearMessages);
125
+ // Component state
126
+ const [displayItems, setDisplayItems] = useState([]);
127
+ const [isLoading, setIsLoading] = useState(false);
128
+ const [isStreaming, setIsStreaming] = useState(false);
129
+ const [error, setError] = useState(null);
130
+ const [input, setInput] = useState('');
131
+ // Model and tools state
132
+ const [selectedModel, setSelectedModel] = useState('');
133
+ // Note: enabledTools is used for backend-defined tools from config query
134
+ // Frontend tools are passed via frontendTools prop
135
+ const [enabledTools, setEnabledTools] = useState([]);
136
+ void enabledTools; // Suppress unused warning - may be used in future
137
+ // Config query (for protocols that support it)
138
+ // Safely handles missing QueryClientProvider
139
+ const configQuery = useConfigQuery(Boolean(protocol?.enableConfigQuery), protocol?.configEndpoint, protocol?.authToken);
140
+ // Refs
141
+ const adapterRef = useRef(null);
142
+ const unsubscribeRef = useRef(null);
143
+ const toolCallsRef = useRef(new Map());
144
+ const currentAssistantMessageRef = useRef(null);
145
+ const threadIdRef = useRef(generateMessageId());
146
+ const messagesEndRef = useRef(null);
147
+ const inputRef = useRef(null);
148
+ const abortControllerRef = useRef(null);
149
+ // Auto-focus input on mount
150
+ useEffect(() => {
151
+ if (autoFocus && inputRef.current) {
152
+ // Small delay to ensure the component is fully rendered
153
+ const timeoutId = setTimeout(() => {
154
+ inputRef.current?.focus();
155
+ }, 100);
156
+ return () => clearTimeout(timeoutId);
157
+ }
158
+ }, [autoFocus]);
159
+ // Refocus input when focusTrigger changes
160
+ useEffect(() => {
161
+ if (focusTrigger !== undefined && focusTrigger > 0 && inputRef.current) {
162
+ // Small delay to ensure any layout changes have completed
163
+ const timeoutId = setTimeout(() => {
164
+ inputRef.current?.focus();
165
+ }, 150);
166
+ return () => clearTimeout(timeoutId);
167
+ }
168
+ }, [focusTrigger]);
169
+ // Track previous loading state to detect when loading completes
170
+ const wasLoadingRef = useRef(false);
171
+ // Refocus input when loading completes
172
+ useEffect(() => {
173
+ if (wasLoadingRef.current && !isLoading && inputRef.current) {
174
+ // Small delay to ensure the input is fully enabled
175
+ const timeoutId = setTimeout(() => {
176
+ inputRef.current?.focus();
177
+ }, 50);
178
+ return () => clearTimeout(timeoutId);
179
+ }
180
+ wasLoadingRef.current = isLoading;
181
+ }, [isLoading]);
182
+ // Auto-resize textarea based on content
183
+ const adjustTextareaHeight = useCallback(() => {
184
+ const textarea = inputRef.current;
185
+ if (textarea) {
186
+ // Reset height to auto to get proper scrollHeight
187
+ textarea.style.height = 'auto';
188
+ // Set height to scrollHeight, capped at maxHeight (120px)
189
+ const maxHeight = 120;
190
+ const newHeight = Math.min(textarea.scrollHeight, maxHeight);
191
+ textarea.style.height = `${newHeight}px`;
192
+ // Add overflow if content exceeds maxHeight
193
+ textarea.style.overflowY =
194
+ textarea.scrollHeight > maxHeight ? 'auto' : 'hidden';
195
+ }
196
+ }, []);
197
+ // Adjust textarea height when input changes
198
+ useEffect(() => {
199
+ adjustTextareaHeight();
200
+ }, [input, adjustTextareaHeight]);
201
+ // Initialize model and tools when config is available
202
+ useEffect(() => {
203
+ if (configQuery.data && !selectedModel) {
204
+ const firstModel = configQuery.data.models[0];
205
+ if (firstModel) {
206
+ setSelectedModel(firstModel.id);
207
+ const allToolIds = configQuery.data.builtinTools?.map(tool => tool.id) || [];
208
+ setEnabledTools(allToolIds);
209
+ }
210
+ }
211
+ }, [configQuery.data, selectedModel]);
212
+ // Load messages from store on mount when useStoreMode is enabled
213
+ useEffect(() => {
214
+ if (useStoreMode) {
215
+ const storeMessages = useChatStore.getState().messages;
216
+ if (storeMessages.length > 0) {
217
+ setDisplayItems(storeMessages);
218
+ }
219
+ }
220
+ }, [useStoreMode]);
221
+ // Derived state
222
+ const messages = displayItems.filter((item) => !isToolCallMessage(item));
223
+ const ready = true;
224
+ // Notify parent when messages change
225
+ useEffect(() => {
226
+ onMessagesChange?.(messages);
227
+ }, [messages, onMessagesChange]);
228
+ // Padding based on compact mode
229
+ const padding = compact ? 2 : 3;
230
+ // Default avatar config
231
+ const defaultAvatarConfig = {
232
+ userAvatar: _jsx(PersonIcon, { size: 16 }),
233
+ assistantAvatar: _jsx(AiAgentIcon, { colored: true, size: 16 }),
234
+ showAvatars: true,
235
+ avatarSize: 32,
236
+ userAvatarBg: 'neutral.muted',
237
+ assistantAvatarBg: 'accent.emphasis',
238
+ ...avatarConfig,
239
+ };
240
+ // Initialize protocol adapter
241
+ useEffect(() => {
242
+ if (!protocol)
243
+ return;
244
+ const adapter = createProtocolAdapter(protocol);
245
+ if (!adapter)
246
+ return;
247
+ adapterRef.current = adapter;
248
+ // Subscribe to protocol events
249
+ unsubscribeRef.current = adapter.subscribe((event) => {
250
+ switch (event.type) {
251
+ case 'message':
252
+ // Update or create assistant message
253
+ if (event.message) {
254
+ const incomingId = event.message.id;
255
+ const currentId = currentAssistantMessageRef.current?.id;
256
+ const isNewMessage = !currentId || (incomingId && incomingId !== currentId);
257
+ if (currentAssistantMessageRef.current && !isNewMessage) {
258
+ // Update existing message (same ID)
259
+ setDisplayItems(prev => {
260
+ const newItems = [...prev];
261
+ const idx = newItems.findIndex(item => !isToolCallMessage(item) &&
262
+ item.id === currentAssistantMessageRef.current?.id);
263
+ if (idx >= 0 && !isToolCallMessage(newItems[idx])) {
264
+ newItems[idx] = {
265
+ ...newItems[idx],
266
+ content: event.message?.content ?? '',
267
+ };
268
+ }
269
+ return newItems;
270
+ });
271
+ // Update message in store
272
+ if (useStoreMode && currentAssistantMessageRef.current) {
273
+ useChatStore
274
+ .getState()
275
+ .updateMessage(currentAssistantMessageRef.current.id, {
276
+ content: event.message?.content ?? '',
277
+ });
278
+ }
279
+ }
280
+ else {
281
+ // Create new assistant message (new ID or first message)
282
+ const content = event.message.content;
283
+ const contentStr = typeof content === 'string' ? content : (content ?? '');
284
+ const newMessage = createAssistantMessage(typeof contentStr === 'string' ? contentStr : '');
285
+ newMessage.id = event.message.id || newMessage.id;
286
+ currentAssistantMessageRef.current = newMessage;
287
+ setDisplayItems(prev => [...prev, newMessage]);
288
+ // Add message to store
289
+ if (useStoreMode) {
290
+ useChatStore.getState().addMessage(newMessage);
291
+ }
292
+ }
293
+ }
294
+ break;
295
+ case 'tool-call':
296
+ // Handle tool call start or update
297
+ if (event.toolCall) {
298
+ const toolCallId = event.toolCall.toolCallId || generateMessageId();
299
+ const toolName = event.toolCall.toolName;
300
+ const args = event.toolCall.args || {};
301
+ // Check if this tool call already exists (update args)
302
+ if (toolCallsRef.current.has(toolCallId)) {
303
+ const existingToolCall = toolCallsRef.current.get(toolCallId);
304
+ if (existingToolCall) {
305
+ // Merge new args with existing (update from TOOL_CALL_END)
306
+ const updatedToolCall = {
307
+ ...existingToolCall,
308
+ args: {
309
+ ...existingToolCall.args,
310
+ ...args,
311
+ },
312
+ };
313
+ toolCallsRef.current.set(toolCallId, updatedToolCall);
314
+ // Always update displayItems (default ToolCallDisplay will be used if no custom renderer)
315
+ setDisplayItems(prev => prev.map(item => isToolCallMessage(item) && item.toolCallId === toolCallId
316
+ ? updatedToolCall
317
+ : item));
318
+ // Check if this is a frontend tool and we have complete args
319
+ // Execute the tool handler if available
320
+ const frontendTool = frontendTools?.find(t => t.name === toolName);
321
+ const toolHandler = frontendTool?.handler;
322
+ if (toolHandler && Object.keys(args).length > 0) {
323
+ // Execute frontend tool
324
+ (async () => {
325
+ try {
326
+ const result = await toolHandler(updatedToolCall.args);
327
+ // Send result back to adapter
328
+ if (adapterRef.current) {
329
+ await adapterRef.current.sendToolResult(toolCallId, {
330
+ toolCallId,
331
+ success: true,
332
+ result,
333
+ });
334
+ }
335
+ // Update tool call with result
336
+ const completedToolCall = {
337
+ ...updatedToolCall,
338
+ result,
339
+ status: 'complete',
340
+ };
341
+ toolCallsRef.current.set(toolCallId, completedToolCall);
342
+ setDisplayItems(prev => prev.map(item => isToolCallMessage(item) &&
343
+ item.toolCallId === toolCallId
344
+ ? completedToolCall
345
+ : item));
346
+ }
347
+ catch (err) {
348
+ console.error('[ChatBase] Frontend tool execution error:', err);
349
+ const errorToolCall = {
350
+ ...updatedToolCall,
351
+ status: 'error',
352
+ error: err.message,
353
+ };
354
+ toolCallsRef.current.set(toolCallId, errorToolCall);
355
+ setDisplayItems(prev => prev.map(item => isToolCallMessage(item) &&
356
+ item.toolCallId === toolCallId
357
+ ? errorToolCall
358
+ : item));
359
+ }
360
+ })();
361
+ }
362
+ }
363
+ }
364
+ else {
365
+ // New tool call - add it
366
+ const toolCallMsg = {
367
+ id: `tool-${toolCallId}`,
368
+ type: 'tool-call',
369
+ toolCallId,
370
+ toolName,
371
+ args,
372
+ status: 'executing',
373
+ };
374
+ toolCallsRef.current.set(toolCallId, toolCallMsg);
375
+ // Always add to displayItems (default ToolCallDisplay will be used if no custom renderer)
376
+ setDisplayItems(prev => [...prev, toolCallMsg]);
377
+ // Execute frontend tool if available and args are present
378
+ const frontendTool = frontendTools?.find(t => t.name === toolName);
379
+ const toolHandler = frontendTool?.handler;
380
+ if (toolHandler && Object.keys(args).length > 0) {
381
+ (async () => {
382
+ try {
383
+ const result = await toolHandler(args);
384
+ // Send result back to adapter
385
+ if (adapterRef.current) {
386
+ await adapterRef.current.sendToolResult(toolCallId, {
387
+ toolCallId,
388
+ success: true,
389
+ result,
390
+ });
391
+ }
392
+ // Update tool call with result
393
+ const completedToolCall = {
394
+ ...toolCallMsg,
395
+ result,
396
+ status: 'complete',
397
+ };
398
+ toolCallsRef.current.set(toolCallId, completedToolCall);
399
+ setDisplayItems(prev => prev.map(item => isToolCallMessage(item) &&
400
+ item.toolCallId === toolCallId
401
+ ? completedToolCall
402
+ : item));
403
+ }
404
+ catch (err) {
405
+ console.error('[ChatBase] Frontend tool execution error:', err);
406
+ const errorToolCall = {
407
+ ...toolCallMsg,
408
+ status: 'error',
409
+ error: err.message,
410
+ };
411
+ toolCallsRef.current.set(toolCallId, errorToolCall);
412
+ setDisplayItems(prev => prev.map(item => isToolCallMessage(item) &&
413
+ item.toolCallId === toolCallId
414
+ ? errorToolCall
415
+ : item));
416
+ }
417
+ })();
418
+ }
419
+ }
420
+ }
421
+ break;
422
+ case 'tool-result':
423
+ // Handle tool result - always update status even without custom renderToolResult
424
+ if (event.toolResult) {
425
+ const toolCallId = event.toolResult.toolCallId;
426
+ if (toolCallId && toolCallsRef.current.has(toolCallId)) {
427
+ const existingToolCall = toolCallsRef.current.get(toolCallId);
428
+ if (existingToolCall) {
429
+ // Check if this is a human-in-the-loop tool (has steps in args)
430
+ // If so, keep status as 'executing' until user responds
431
+ const isHumanInTheLoop = existingToolCall.args &&
432
+ 'steps' in existingToolCall.args &&
433
+ Array.isArray(existingToolCall.args.steps);
434
+ const updatedToolCall = {
435
+ ...existingToolCall,
436
+ result: event.toolResult.result,
437
+ // Keep executing for HITL, otherwise mark complete/error
438
+ status: event.toolResult.error
439
+ ? 'error'
440
+ : isHumanInTheLoop
441
+ ? 'executing'
442
+ : 'complete',
443
+ error: event.toolResult.error,
444
+ };
445
+ toolCallsRef.current.set(toolCallId, updatedToolCall);
446
+ setDisplayItems(prev => prev.map(item => isToolCallMessage(item) && item.toolCallId === toolCallId
447
+ ? updatedToolCall
448
+ : item));
449
+ }
450
+ }
451
+ }
452
+ break;
453
+ case 'state-update':
454
+ onStateUpdate?.(event.data);
455
+ // When we receive a state update, mark the last executing tool as complete
456
+ // This handles tools that return state events (STATE_SNAPSHOT/STATE_DELTA) instead of TOOL_CALL_RESULT
457
+ if (event.data) {
458
+ // Find any tool calls that are still in 'executing' status
459
+ const executingToolCalls = Array.from(toolCallsRef.current.entries()).filter(([_, tc]) => tc.status === 'executing');
460
+ // Mark the most recent executing tool as complete
461
+ if (executingToolCalls.length > 0) {
462
+ const [lastToolCallId, existingToolCall] = executingToolCalls[executingToolCalls.length - 1];
463
+ // Check if this is NOT a human-in-the-loop tool
464
+ const isHumanInTheLoop = existingToolCall.args &&
465
+ 'steps' in existingToolCall.args &&
466
+ Array.isArray(existingToolCall.args.steps);
467
+ if (!isHumanInTheLoop) {
468
+ // Extract result from state data if available
469
+ const stateData = event.data;
470
+ const result = stateData.weather ??
471
+ stateData.result ??
472
+ stateData.toolResult ??
473
+ stateData;
474
+ const updatedToolCall = {
475
+ ...existingToolCall,
476
+ result,
477
+ status: 'complete',
478
+ };
479
+ toolCallsRef.current.set(lastToolCallId, updatedToolCall);
480
+ setDisplayItems(prev => prev.map(item => isToolCallMessage(item) &&
481
+ item.toolCallId === lastToolCallId
482
+ ? updatedToolCall
483
+ : item));
484
+ }
485
+ }
486
+ }
487
+ break;
488
+ case 'error':
489
+ console.error('[ChatBase] Protocol error:', event.error);
490
+ setError(event.error || new Error('Unknown error'));
491
+ setIsLoading(false);
492
+ setIsStreaming(false);
493
+ break;
494
+ }
495
+ });
496
+ // Connect to protocol
497
+ adapter.connect().catch(console.error);
498
+ return () => {
499
+ unsubscribeRef.current?.();
500
+ adapterRef.current?.disconnect();
501
+ };
502
+ }, [protocol, renderToolResult, onStateUpdate, useStoreMode]);
503
+ // Auto-scroll to bottom
504
+ useEffect(() => {
505
+ messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
506
+ }, [displayItems]);
507
+ // Handle sending message in protocol mode or custom mode
508
+ const handleSend = useCallback(async () => {
509
+ if (!input.trim() || isLoading)
510
+ return;
511
+ // Need either an adapter (protocol mode) or onSendMessage handler (custom mode)
512
+ if (!adapterRef.current && !onSendMessage)
513
+ return;
514
+ const messageContent = input.trim();
515
+ const userMessage = createUserMessage(messageContent);
516
+ const currentMessages = displayItems.filter((item) => !isToolCallMessage(item));
517
+ const allMessages = [...currentMessages, userMessage];
518
+ setDisplayItems(prev => [...prev, userMessage]);
519
+ setInput('');
520
+ setIsLoading(true);
521
+ setIsStreaming(true);
522
+ setError(null);
523
+ currentAssistantMessageRef.current = null;
524
+ // Persist user message to store if enabled
525
+ if (useStoreMode) {
526
+ useChatStore.getState().addMessage(userMessage);
527
+ }
528
+ try {
529
+ if (onSendMessage) {
530
+ // Custom mode: use the provided message handler
531
+ if (enableStreaming) {
532
+ // Streaming mode: create assistant message placeholder and stream updates
533
+ const assistantMessageId = generateMessageId();
534
+ const assistantMessage = createAssistantMessage('');
535
+ assistantMessage.id = assistantMessageId;
536
+ setDisplayItems(prev => [...prev, assistantMessage]);
537
+ currentAssistantMessageRef.current = assistantMessage;
538
+ if (useStoreMode) {
539
+ useChatStore.getState().addMessage(assistantMessage);
540
+ useChatStore.getState().startStreaming(assistantMessageId);
541
+ }
542
+ // Create abort controller for cancellation
543
+ abortControllerRef.current = new AbortController();
544
+ await onSendMessage(messageContent, allMessages, {
545
+ onChunk: (chunk) => {
546
+ // Append chunk to the assistant message
547
+ setDisplayItems(prev => prev.map(item => item.id === assistantMessageId
548
+ ? {
549
+ ...item,
550
+ content: item.content + chunk,
551
+ }
552
+ : item));
553
+ if (useStoreMode) {
554
+ useChatStore
555
+ .getState()
556
+ .appendToStream(assistantMessageId, chunk);
557
+ }
558
+ },
559
+ onComplete: (fullResponse) => {
560
+ // Update assistant message with final content
561
+ setDisplayItems(prev => prev.map(item => item.id === assistantMessageId
562
+ ? { ...item, content: fullResponse }
563
+ : item));
564
+ if (useStoreMode) {
565
+ useChatStore
566
+ .getState()
567
+ .updateMessage(assistantMessageId, { content: fullResponse });
568
+ useChatStore.getState().stopStreaming();
569
+ }
570
+ },
571
+ onError: (error) => {
572
+ // Update assistant message with error
573
+ const errorContent = `Error: ${error.message}`;
574
+ setDisplayItems(prev => prev.map(item => item.id === assistantMessageId
575
+ ? { ...item, content: errorContent }
576
+ : item));
577
+ if (useStoreMode) {
578
+ useChatStore
579
+ .getState()
580
+ .updateMessage(assistantMessageId, { content: errorContent });
581
+ useChatStore.getState().stopStreaming();
582
+ }
583
+ setError(error);
584
+ },
585
+ signal: abortControllerRef.current.signal,
586
+ });
587
+ }
588
+ else {
589
+ // Non-streaming mode: wait for full response
590
+ const response = await onSendMessage(messageContent, allMessages);
591
+ if (response) {
592
+ const assistantMessage = createAssistantMessage(response);
593
+ setDisplayItems(prev => [...prev, assistantMessage]);
594
+ if (useStoreMode) {
595
+ useChatStore.getState().addMessage(assistantMessage);
596
+ }
597
+ }
598
+ }
599
+ }
600
+ else if (adapterRef.current) {
601
+ // Protocol mode: use the adapter
602
+ // Convert frontend tools to AG-UI format (only serializable properties)
603
+ const toolsForRequest = (frontendTools || []).map(tool => ({
604
+ name: tool.name,
605
+ description: tool.description,
606
+ parameters: tool.parameters || { type: 'object', properties: {} },
607
+ }));
608
+ if (toolsForRequest.length > 0) {
609
+ console.log('[ChatBase] Sending tools to AG-UI:', toolsForRequest.map(t => t.name));
610
+ }
611
+ await adapterRef.current.sendMessage(userMessage, {
612
+ threadId: threadIdRef.current,
613
+ messages: allMessages,
614
+ ...(selectedModel && { model: selectedModel }),
615
+ tools: toolsForRequest,
616
+ });
617
+ }
618
+ }
619
+ catch (err) {
620
+ if (err.name !== 'AbortError') {
621
+ console.error('[ChatBase] Send error:', err);
622
+ const errorMessage = createAssistantMessage(`Error: ${err.message}`);
623
+ setDisplayItems(prev => [...prev, errorMessage]);
624
+ setError(err);
625
+ }
626
+ }
627
+ finally {
628
+ setIsLoading(false);
629
+ setIsStreaming(false);
630
+ currentAssistantMessageRef.current = null;
631
+ abortControllerRef.current = null;
632
+ }
633
+ }, [
634
+ input,
635
+ isLoading,
636
+ displayItems,
637
+ selectedModel,
638
+ frontendTools,
639
+ useStoreMode,
640
+ onSendMessage,
641
+ enableStreaming,
642
+ ]);
643
+ // Handle stop
644
+ const handleStop = useCallback(() => {
645
+ // Abort custom mode request
646
+ abortControllerRef.current?.abort();
647
+ // Disconnect protocol adapter
648
+ adapterRef.current?.disconnect();
649
+ // Stop streaming in store
650
+ if (useStoreMode) {
651
+ useChatStore.getState().stopStreaming();
652
+ }
653
+ setIsLoading(false);
654
+ setIsStreaming(false);
655
+ }, [useStoreMode]);
656
+ // Handle key press
657
+ const handleKeyDown = useCallback((e) => {
658
+ if (e.key === 'Enter' && !e.shiftKey) {
659
+ e.preventDefault();
660
+ handleSend();
661
+ }
662
+ }, [handleSend]);
663
+ // Handle new chat
664
+ const handleNewChat = useCallback(() => {
665
+ setDisplayItems([]);
666
+ toolCallsRef.current.clear();
667
+ setInput('');
668
+ threadIdRef.current = generateMessageId();
669
+ if (useStoreMode) {
670
+ clearStoreMessages();
671
+ }
672
+ onNewChat?.();
673
+ headerButtons?.onNewChat?.();
674
+ }, [clearStoreMessages, onNewChat, headerButtons, useStoreMode]);
675
+ // Handle clear
676
+ const handleClear = useCallback(() => {
677
+ if (window.confirm('Clear all messages?')) {
678
+ setDisplayItems([]);
679
+ toolCallsRef.current.clear();
680
+ if (useStoreMode) {
681
+ clearStoreMessages();
682
+ }
683
+ onClear?.();
684
+ headerButtons?.onClear?.();
685
+ }
686
+ }, [clearStoreMessages, onClear, headerButtons, useStoreMode]);
687
+ // Not ready yet (store mode only)
688
+ if (!ready) {
689
+ return (_jsx(Box, { className: className, sx: {
690
+ display: 'flex',
691
+ flexDirection: 'column',
692
+ alignItems: 'center',
693
+ justifyContent: 'center',
694
+ height: '100%',
695
+ p: 4,
696
+ borderRadius: borderRadius,
697
+ bg: backgroundColor || 'canvas.default',
698
+ border: border,
699
+ boxShadow: boxShadow,
700
+ }, children: loadingState || (_jsxs(_Fragment, { children: [_jsx(Spinner, { size: "large" }), _jsx(Text, { sx: { mt: 3, color: 'fg.muted' }, children: "Initializing chat..." })] })) }));
701
+ }
702
+ // Render header with buttons
703
+ const renderHeader = () => {
704
+ if (!showHeader)
705
+ return null;
706
+ return (_jsx(Box, { sx: {
707
+ display: 'flex',
708
+ flexDirection: 'column',
709
+ borderBottom: '1px solid',
710
+ borderColor: 'border.default',
711
+ }, children: _jsxs(Box, { sx: {
712
+ display: 'flex',
713
+ alignItems: 'center',
714
+ justifyContent: 'space-between',
715
+ p: padding,
716
+ }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [brandIcon || _jsx(AiAgentIcon, { colored: true, size: 20 }), title && (_jsx(Heading, { as: "h3", sx: { fontSize: 2, fontWeight: 'semibold' }, children: title })), headerContent] }), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 }, children: [headerButtons?.showNewChat && (_jsx(IconButton, { icon: PlusIcon, "aria-label": "New chat", variant: "invisible", size: "small", onClick: handleNewChat })), headerButtons?.showClear && messages.length > 0 && (_jsx(IconButton, { icon: TrashIcon, "aria-label": "Clear messages", variant: "invisible", size: "small", onClick: handleClear })), headerButtons?.showSettings && (_jsx(IconButton, { icon: GearIcon, "aria-label": "Settings", variant: "invisible", size: "small", onClick: headerButtons.onSettings })), headerActions] })] }) }));
717
+ };
718
+ // Render empty state
719
+ const renderEmptyState = () => {
720
+ if (emptyState?.render) {
721
+ return emptyState.render();
722
+ }
723
+ // Handler for suggestion clicks
724
+ const handleSuggestionClick = (suggestion) => {
725
+ if (submitOnSuggestionClick) {
726
+ // Auto-submit the suggestion message
727
+ const userMessage = {
728
+ id: generateMessageId(),
729
+ role: 'user',
730
+ content: suggestion.message,
731
+ createdAt: new Date(),
732
+ };
733
+ setDisplayItems(prev => [...prev, userMessage]);
734
+ setIsLoading(true);
735
+ setIsStreaming(true);
736
+ // Convert frontend tools to AG-UI format (same as regular message send)
737
+ const toolsForSuggestion = (frontendTools || []).map(tool => ({
738
+ name: tool.name,
739
+ description: tool.description,
740
+ parameters: tool.parameters || { type: 'object', properties: {} },
741
+ }));
742
+ adapterRef.current
743
+ ?.sendMessage(userMessage, {
744
+ threadId: threadIdRef.current,
745
+ messages: [userMessage],
746
+ tools: toolsForSuggestion,
747
+ })
748
+ .catch(err => {
749
+ console.error('[ChatBase] Suggestion send error:', err);
750
+ setError(err instanceof Error ? err : new Error(String(err)));
751
+ })
752
+ .finally(() => {
753
+ setIsLoading(false);
754
+ setIsStreaming(false);
755
+ });
756
+ }
757
+ else {
758
+ // Just fill the input without submitting
759
+ setInput(suggestion.message);
760
+ setTimeout(() => {
761
+ inputRef.current?.focus();
762
+ }, 0);
763
+ }
764
+ };
765
+ return (_jsxs(Box, { sx: {
766
+ display: 'flex',
767
+ flexDirection: 'column',
768
+ alignItems: 'center',
769
+ justifyContent: 'center',
770
+ height: '100%',
771
+ p: 4,
772
+ color: 'fg.muted',
773
+ textAlign: 'center',
774
+ gap: 2,
775
+ }, children: [emptyState?.icon || brandIcon || _jsx(AiAgentIcon, { colored: true, size: 48 }), _jsx(Text, { sx: { fontSize: 2 }, children: emptyState?.title || 'Start a conversation' }), (emptyState?.subtitle || description) && (_jsx(Text, { sx: { fontSize: 1 }, children: emptyState?.subtitle || description })), suggestions && suggestions.length > 0 && (_jsx(LabelGroup, { sx: { mt: 2, justifyContent: 'center' }, children: suggestions.map((suggestion, index) => (_jsx(Label, { variant: "accent", sx: {
776
+ cursor: 'pointer',
777
+ '&:hover': {
778
+ bg: 'accent.muted',
779
+ },
780
+ }, onClick: () => handleSuggestionClick(suggestion), children: suggestion.title }, index))) }))] }));
781
+ };
782
+ // Render protocol mode messages with tool call support
783
+ const renderProtocolMessages = () => {
784
+ if (displayItems.length === 0) {
785
+ return renderEmptyState();
786
+ }
787
+ // Create respond callback for a tool call (human-in-the-loop)
788
+ const createRespondCallback = (toolCallId) => {
789
+ return async (result) => {
790
+ // Update tool call status to complete with the user's response
791
+ const existingToolCall = toolCallsRef.current.get(toolCallId);
792
+ if (existingToolCall && existingToolCall.status === 'executing') {
793
+ const updatedToolCall = {
794
+ ...existingToolCall,
795
+ result,
796
+ status: 'complete',
797
+ };
798
+ toolCallsRef.current.set(toolCallId, updatedToolCall);
799
+ setDisplayItems(prev => prev.map(item => isToolCallMessage(item) && item.toolCallId === toolCallId
800
+ ? updatedToolCall
801
+ : item));
802
+ // Send the user's response back to the agent as a new message
803
+ // This continues the conversation with the HITL response
804
+ if (adapterRef.current) {
805
+ // Format the response as a clear text message the agent can understand
806
+ let responseText;
807
+ if (typeof result === 'string') {
808
+ responseText = result;
809
+ }
810
+ else if (result &&
811
+ typeof result === 'object' &&
812
+ 'accepted' in result) {
813
+ const hitlResult = result;
814
+ if (hitlResult.accepted) {
815
+ const stepDescriptions = hitlResult.steps?.map(s => s.description).join(', ') || '';
816
+ responseText = stepDescriptions
817
+ ? `I confirm and approve the following steps: ${stepDescriptions}`
818
+ : 'I confirm and approve the plan.';
819
+ }
820
+ else {
821
+ responseText =
822
+ 'I reject this plan. Please suggest something else.';
823
+ }
824
+ }
825
+ else {
826
+ responseText = JSON.stringify(result, null, 2);
827
+ }
828
+ // Create a user message with the HITL response
829
+ const userMessage = {
830
+ id: generateMessageId(),
831
+ role: 'user',
832
+ content: responseText,
833
+ createdAt: new Date(),
834
+ };
835
+ setIsLoading(true);
836
+ setIsStreaming(true);
837
+ try {
838
+ // Get all chat messages for context
839
+ const allMessages = displayItems.filter((item) => !isToolCallMessage(item));
840
+ await adapterRef.current.sendMessage(userMessage, {
841
+ threadId: threadIdRef.current,
842
+ messages: [...allMessages, userMessage],
843
+ });
844
+ }
845
+ catch (err) {
846
+ console.error('[ChatBase] HITL respond error:', err);
847
+ }
848
+ finally {
849
+ setIsLoading(false);
850
+ setIsStreaming(false);
851
+ }
852
+ }
853
+ }
854
+ };
855
+ };
856
+ // Check if there are tool calls being rendered
857
+ // This is used to hide duplicate assistant text when UI is shown
858
+ const renderedToolCallIds = new Set();
859
+ displayItems.forEach(item => {
860
+ if (isToolCallMessage(item)) {
861
+ if (renderToolResult) {
862
+ // Check if custom renderer produces a rendered UI
863
+ const rendered = renderToolResult({
864
+ toolCallId: item.toolCallId,
865
+ toolName: item.toolName,
866
+ name: item.toolName,
867
+ args: item.args,
868
+ result: item.result,
869
+ status: item.status,
870
+ error: item.error,
871
+ });
872
+ if (rendered !== null && rendered !== undefined) {
873
+ renderedToolCallIds.add(item.toolCallId);
874
+ }
875
+ }
876
+ else {
877
+ // Default display always renders tool calls
878
+ renderedToolCallIds.add(item.toolCallId);
879
+ }
880
+ }
881
+ });
882
+ const hasRenderedToolCall = renderedToolCallIds.size > 0;
883
+ return (_jsxs(_Fragment, { children: [displayItems.map((item, index) => {
884
+ // Render tool call
885
+ if (isToolCallMessage(item)) {
886
+ // Only provide respond callback when status is 'executing'
887
+ const respond = item.status === 'executing'
888
+ ? createRespondCallback(item.toolCallId)
889
+ : undefined;
890
+ // Use custom renderToolResult if provided, otherwise use default display
891
+ const toolUI = renderToolResult ? (renderToolResult({
892
+ toolCallId: item.toolCallId,
893
+ toolName: item.toolName,
894
+ name: item.toolName,
895
+ args: item.args,
896
+ result: item.result,
897
+ status: item.status,
898
+ error: item.error,
899
+ respond,
900
+ })) : (_jsx(ToolCallDisplay, { toolCallId: item.toolCallId, toolName: item.toolName, args: item.args, result: item.result, status: item.status, error: item.error }));
901
+ // Skip if custom render returns null/undefined
902
+ if (toolUI === null || toolUI === undefined)
903
+ return null;
904
+ return (_jsx(Box, { sx: {
905
+ display: 'flex',
906
+ flexDirection: 'column',
907
+ alignItems: 'flex-start',
908
+ maxWidth: '95%',
909
+ px: padding,
910
+ py: 1,
911
+ }, children: toolUI }, item.id));
912
+ }
913
+ // Render regular chat message
914
+ const message = item;
915
+ const isUser = message.role === 'user';
916
+ // Skip assistant messages when hideMessagesAfterToolUI is enabled and there's a rendered tool call
917
+ if (!isUser && hideMessagesAfterToolUI && hasRenderedToolCall) {
918
+ // Get message text safely
919
+ const messageText = getMessageText(message);
920
+ // Check if this assistant message follows a rendered tool call
921
+ const prevIndex = index - 1;
922
+ if (prevIndex >= 0) {
923
+ const prevItem = displayItems[prevIndex];
924
+ if (isToolCallMessage(prevItem) &&
925
+ renderedToolCallIds.has(prevItem.toolCallId)) {
926
+ // Skip this assistant message as it describes the tool result
927
+ return null;
928
+ }
929
+ }
930
+ // Also check for HITL-specific patterns (step descriptions)
931
+ const hitlToolCall = displayItems.find(item => isToolCallMessage(item) &&
932
+ renderedToolCallIds.has(item.toolCallId) &&
933
+ item.args &&
934
+ 'steps' in item.args &&
935
+ Array.isArray(item.args.steps));
936
+ if (hitlToolCall && messageText) {
937
+ const steps = hitlToolCall.args.steps;
938
+ // Check if message contains step descriptions or step-like patterns
939
+ const hasStepContent = steps.some(step => step.description &&
940
+ messageText
941
+ .toLowerCase()
942
+ .includes(step.description.toLowerCase().slice(0, 20))) ||
943
+ // Also hide if message contains numbered list patterns
944
+ /^\s*(\d+\.\s|[-*]\s|\*\*)/.test(messageText) ||
945
+ messageText.includes('**Enabled**') ||
946
+ messageText.includes('steps below');
947
+ if (hasStepContent) {
948
+ return null;
949
+ }
950
+ }
951
+ }
952
+ return (_jsx(Box, { sx: {
953
+ display: 'flex',
954
+ flexDirection: 'column',
955
+ alignItems: isUser ? 'flex-end' : 'flex-start',
956
+ px: padding,
957
+ py: 1,
958
+ }, children: _jsxs(Box, { sx: {
959
+ display: 'flex',
960
+ gap: 2,
961
+ flexDirection: isUser ? 'row-reverse' : 'row',
962
+ alignItems: 'flex-start',
963
+ }, children: [defaultAvatarConfig.showAvatars && (_jsx(Box, { sx: {
964
+ width: defaultAvatarConfig.avatarSize,
965
+ height: defaultAvatarConfig.avatarSize,
966
+ borderRadius: '50%',
967
+ bg: isUser
968
+ ? defaultAvatarConfig.userAvatarBg
969
+ : defaultAvatarConfig.assistantAvatarBg,
970
+ color: isUser ? 'fg.default' : 'fg.onEmphasis',
971
+ display: 'flex',
972
+ alignItems: 'center',
973
+ justifyContent: 'center',
974
+ flexShrink: 0,
975
+ }, children: isUser
976
+ ? defaultAvatarConfig.userAvatar
977
+ : defaultAvatarConfig.assistantAvatar })), _jsx(Box, { sx: {
978
+ maxWidth: '85%',
979
+ p: 2,
980
+ borderRadius: 2,
981
+ backgroundColor: isUser ? 'accent.emphasis' : '#f6f8fa',
982
+ color: isUser ? 'fg.onEmphasis' : 'fg.default',
983
+ // Streamdown code block styling
984
+ // Code block container
985
+ '& [data-streamdown="code-block"]': {
986
+ borderRadius: '8px',
987
+ border: '1px solid',
988
+ borderColor: 'border.default',
989
+ overflow: 'hidden',
990
+ my: 2,
991
+ },
992
+ // Code block header with language label and buttons
993
+ '& [data-streamdown="code-block-header"]': {
994
+ display: 'flex',
995
+ alignItems: 'center',
996
+ justifyContent: 'space-between',
997
+ backgroundColor: '#e1e4e8',
998
+ padding: '8px 12px',
999
+ fontSize: '12px',
1000
+ color: '#586069',
1001
+ },
1002
+ // Style the buttons in the header
1003
+ '& [data-streamdown="code-block-header"] button': {
1004
+ background: 'none',
1005
+ border: 'none',
1006
+ cursor: 'pointer',
1007
+ padding: '4px',
1008
+ color: '#586069',
1009
+ borderRadius: '4px',
1010
+ '&:hover': {
1011
+ backgroundColor: 'rgba(0,0,0,0.1)',
1012
+ color: '#24292e',
1013
+ },
1014
+ },
1015
+ // Code block body
1016
+ '& [data-streamdown="code-block-body"]': {
1017
+ backgroundColor: '#f6f8fa',
1018
+ padding: '12px',
1019
+ margin: 0,
1020
+ overflow: 'auto',
1021
+ fontSize: '13px',
1022
+ lineHeight: 1.5,
1023
+ },
1024
+ // Make each line display as a block for line breaks
1025
+ '& [data-streamdown="code-block-body"] code': {
1026
+ display: 'block',
1027
+ fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace',
1028
+ },
1029
+ '& [data-streamdown="code-block-body"] code > span.block': {
1030
+ display: 'block',
1031
+ },
1032
+ '& [data-streamdown="code-block-body"] code > span': {
1033
+ display: 'block',
1034
+ },
1035
+ // General pre/code styling fallback
1036
+ '& pre': {
1037
+ whiteSpace: 'pre-wrap',
1038
+ wordBreak: 'break-word',
1039
+ overflowX: 'auto',
1040
+ margin: 0,
1041
+ },
1042
+ '& pre code': {
1043
+ whiteSpace: 'pre-wrap',
1044
+ },
1045
+ '& code': {
1046
+ fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace',
1047
+ },
1048
+ }, children: isUser ? (_jsx(Text, { sx: {
1049
+ fontSize: 1,
1050
+ whiteSpace: 'pre-wrap',
1051
+ wordBreak: 'break-word',
1052
+ }, children: getMessageText(message) })) : (_jsx(Box, { sx: { fontSize: 1, lineHeight: 1.5 }, children: _jsx(Streamdown, { children: getMessageText(message) || (isStreaming ? '...' : '') }) })) })] }) }, message.id));
1053
+ }), (isLoading || isStreaming) && (_jsx(Box, { sx: {
1054
+ display: 'flex',
1055
+ alignItems: 'flex-start',
1056
+ px: padding,
1057
+ py: 1,
1058
+ }, children: _jsxs(Box, { sx: {
1059
+ display: 'flex',
1060
+ gap: 2,
1061
+ alignItems: 'flex-start',
1062
+ }, children: [defaultAvatarConfig.showAvatars && (_jsx(Box, { sx: {
1063
+ width: defaultAvatarConfig.avatarSize,
1064
+ height: defaultAvatarConfig.avatarSize,
1065
+ borderRadius: '50%',
1066
+ bg: defaultAvatarConfig.assistantAvatarBg,
1067
+ color: 'fg.onEmphasis',
1068
+ display: 'flex',
1069
+ alignItems: 'center',
1070
+ justifyContent: 'center',
1071
+ flexShrink: 0,
1072
+ }, children: defaultAvatarConfig.assistantAvatar })), _jsxs(Box, { sx: {
1073
+ display: 'flex',
1074
+ alignItems: 'center',
1075
+ gap: '4px',
1076
+ p: 2,
1077
+ borderRadius: 2,
1078
+ bg: 'canvas.subtle',
1079
+ minHeight: '32px',
1080
+ }, children: [_jsx(Box, { sx: {
1081
+ width: '8px',
1082
+ height: '8px',
1083
+ borderRadius: '50%',
1084
+ bg: 'fg.muted',
1085
+ animation: 'typingPulse 1.4s ease-in-out infinite',
1086
+ '@keyframes typingPulse': {
1087
+ '0%, 60%, 100%': {
1088
+ transform: 'scale(0.6)',
1089
+ opacity: 0.4,
1090
+ },
1091
+ '30%': {
1092
+ transform: 'scale(1)',
1093
+ opacity: 1,
1094
+ },
1095
+ },
1096
+ } }), _jsx(Box, { sx: {
1097
+ width: '8px',
1098
+ height: '8px',
1099
+ borderRadius: '50%',
1100
+ bg: 'fg.muted',
1101
+ animation: 'typingPulse 1.4s ease-in-out infinite',
1102
+ animationDelay: '0.2s',
1103
+ '@keyframes typingPulse': {
1104
+ '0%, 60%, 100%': {
1105
+ transform: 'scale(0.6)',
1106
+ opacity: 0.4,
1107
+ },
1108
+ '30%': {
1109
+ transform: 'scale(1)',
1110
+ opacity: 1,
1111
+ },
1112
+ },
1113
+ } }), _jsx(Box, { sx: {
1114
+ width: '8px',
1115
+ height: '8px',
1116
+ borderRadius: '50%',
1117
+ bg: 'fg.muted',
1118
+ animation: 'typingPulse 1.4s ease-in-out infinite',
1119
+ animationDelay: '0.4s',
1120
+ '@keyframes typingPulse': {
1121
+ '0%, 60%, 100%': {
1122
+ transform: 'scale(0.6)',
1123
+ opacity: 0.4,
1124
+ },
1125
+ '30%': {
1126
+ transform: 'scale(1)',
1127
+ opacity: 1,
1128
+ },
1129
+ },
1130
+ } })] })] }) })), _jsx("div", { ref: messagesEndRef })] }));
1131
+ };
1132
+ // Render protocol mode input
1133
+ const renderProtocolInput = () => {
1134
+ const availableTools = configQuery.data?.builtinTools || [];
1135
+ const models = configQuery.data?.models || [];
1136
+ return (_jsxs(Box, { children: [_jsx(Box, { sx: {
1137
+ p: padding,
1138
+ borderTop: '1px solid',
1139
+ borderColor: 'border.default',
1140
+ bg: 'canvas.subtle',
1141
+ }, children: _jsxs(Box, { sx: { display: 'flex', gap: 2, alignItems: 'flex-end' }, children: [_jsx(Textarea, { ref: inputRef, value: input, onChange: e => {
1142
+ setInput(e.target.value);
1143
+ // Height adjustment happens via useEffect watching input
1144
+ }, onKeyDown: handleKeyDown, placeholder: placeholder || 'Type a message...', disabled: isLoading, sx: {
1145
+ flex: 1,
1146
+ resize: 'none',
1147
+ minHeight: '40px',
1148
+ maxHeight: '120px',
1149
+ overflow: 'hidden',
1150
+ transition: 'height 0.1s ease-out',
1151
+ }, rows: 1 }), isLoading ? (_jsx(IconButton, { icon: SquareCircleIcon, "aria-label": "Stop", onClick: handleStop, sx: { alignSelf: 'flex-end' } })) : (_jsx(IconButton, { icon: PaperAirplaneIcon, "aria-label": "Send", onClick: handleSend, disabled: !input.trim(), sx: { alignSelf: 'flex-end' } }))] }) }), (showModelSelector || showToolsMenu) && configQuery.data && (_jsxs(Box, { sx: {
1152
+ display: 'flex',
1153
+ gap: 2,
1154
+ px: padding,
1155
+ py: 1,
1156
+ borderTop: '1px solid',
1157
+ borderColor: 'border.default',
1158
+ alignItems: 'center',
1159
+ bg: 'canvas.subtle',
1160
+ }, children: [showToolsMenu && (_jsxs(ActionMenu, { children: [_jsx(ActionMenu.Anchor, { children: _jsx(IconButton, { icon: ToolsIcon, "aria-label": "Tools", variant: "invisible", size: "small" }) }), _jsx(ActionMenu.Overlay, { side: "outside-top", align: "start", children: _jsx(ActionList, { children: _jsx(ActionList.Group, { title: "Available Tools", children: availableTools.length > 0 ? (availableTools.map(tool => (_jsxs(ActionList.Item, { disabled: true, children: [_jsx(ActionList.LeadingVisual, { children: _jsx(Box, { sx: {
1161
+ width: 8,
1162
+ height: 8,
1163
+ borderRadius: '50%',
1164
+ backgroundColor: 'success.emphasis',
1165
+ } }) }), tool.name] }, tool.id)))) : (_jsx(ActionList.Item, { disabled: true, children: _jsx(Text, { sx: { color: 'fg.muted', fontStyle: 'italic' }, children: "No tools available" }) })) }) }) })] })), showModelSelector && models.length > 0 && selectedModel && (_jsxs(ActionMenu, { children: [_jsx(ActionMenu.Anchor, { children: _jsx(Button, { type: "button", variant: "invisible", size: "small", leadingVisual: AiModelIcon, children: _jsx(Text, { sx: { fontSize: 0 }, children: models.find(m => m.id === selectedModel)?.name ||
1166
+ 'Select Model' }) }) }), _jsx(ActionMenu.Overlay, { side: "outside-top", align: "end", children: _jsx(ActionList, { selectionVariant: "single", children: models.map(modelItem => (_jsx(ActionList.Item, { selected: selectedModel === modelItem.id, onSelect: () => setSelectedModel(modelItem.id), children: modelItem.name }, modelItem.id))) }) })] }))] }))] }));
1167
+ };
1168
+ return (_jsxs(Box, { className: className, sx: {
1169
+ display: 'flex',
1170
+ flexDirection: 'column',
1171
+ height: '100%',
1172
+ bg: backgroundColor || 'canvas.default',
1173
+ borderRadius: borderRadius,
1174
+ border: border,
1175
+ boxShadow: boxShadow,
1176
+ overflow: 'hidden',
1177
+ }, children: [renderHeader(), showErrors && error && (_jsxs(Box, { sx: {
1178
+ display: 'flex',
1179
+ alignItems: 'center',
1180
+ gap: 2,
1181
+ p: padding,
1182
+ bg: 'danger.subtle',
1183
+ borderBottom: '1px solid',
1184
+ borderColor: 'danger.muted',
1185
+ }, children: [_jsx(AlertIcon, { size: 16 }), _jsx(Text, { sx: { color: 'danger.fg', fontSize: 1 }, children: error.message })] })), _jsx(Box, { sx: { flex: 1, overflow: 'auto', bg: 'canvas.default' }, children: children ? (children) : (_jsx(Box, { sx: {
1186
+ display: 'flex',
1187
+ flexDirection: 'column',
1188
+ minHeight: '100%',
1189
+ bg: 'canvas.default',
1190
+ }, children: renderProtocolMessages() })) }), footerContent, showInput && renderProtocolInput(), showPoweredBy && _jsx(PoweredByTag, { ...poweredByProps })] }));
1191
+ }
1192
+ export default ChatBase;