@vertesia/ui 1.4.0-dev.20260615.051508Z → 1.4.0-dev.20260629.130134Z

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 (337) hide show
  1. package/lib/core/components/shadcn/dropdown.d.ts.map +1 -1
  2. package/lib/core/components/shadcn/dropdown.js +6 -2
  3. package/lib/core/components/shadcn/dropdown.js.map +1 -1
  4. package/lib/core/components/shadcn/filters/filterBar.d.ts.map +1 -1
  5. package/lib/core/components/shadcn/filters/filterBar.js +9 -2
  6. package/lib/core/components/shadcn/filters/filterBar.js.map +1 -1
  7. package/lib/core/components/shadcn/modal/ConfirmModal.d.ts +16 -1
  8. package/lib/core/components/shadcn/modal/ConfirmModal.d.ts.map +1 -1
  9. package/lib/core/components/shadcn/modal/ConfirmModal.js +25 -3
  10. package/lib/core/components/shadcn/modal/ConfirmModal.js.map +1 -1
  11. package/lib/core/components/shadcn/modal/dialog.js +1 -1
  12. package/lib/core/components/shadcn/modal/dialog.js.map +1 -1
  13. package/lib/core/components/shadcn/popover.d.ts.map +1 -1
  14. package/lib/core/components/shadcn/popover.js +3 -1
  15. package/lib/core/components/shadcn/popover.js.map +1 -1
  16. package/lib/core/components/shadcn/switch.js +3 -3
  17. package/lib/core/components/shadcn/switch.js.map +1 -1
  18. package/lib/core/components/shadcn/tabs.js +1 -1
  19. package/lib/core/components/shadcn/tabs.js.map +1 -1
  20. package/lib/core/components/shadcn/tooltip.d.ts.map +1 -1
  21. package/lib/core/components/shadcn/tooltip.js +3 -1
  22. package/lib/core/components/shadcn/tooltip.js.map +1 -1
  23. package/lib/env/index.d.ts +0 -19
  24. package/lib/env/index.d.ts.map +1 -1
  25. package/lib/env/index.js +0 -6
  26. package/lib/env/index.js.map +1 -1
  27. package/lib/features/agent/PayloadBuilder.d.ts +4 -0
  28. package/lib/features/agent/PayloadBuilder.d.ts.map +1 -1
  29. package/lib/features/agent/PayloadBuilder.js +16 -0
  30. package/lib/features/agent/PayloadBuilder.js.map +1 -1
  31. package/lib/features/agent/chat/AgentApprovalModeSelector.d.ts +10 -0
  32. package/lib/features/agent/chat/AgentApprovalModeSelector.d.ts.map +1 -0
  33. package/lib/features/agent/chat/AgentApprovalModeSelector.js +50 -0
  34. package/lib/features/agent/chat/AgentApprovalModeSelector.js.map +1 -0
  35. package/lib/features/agent/chat/AgentChatFixtureReplay.d.ts +2 -1
  36. package/lib/features/agent/chat/AgentChatFixtureReplay.d.ts.map +1 -1
  37. package/lib/features/agent/chat/AgentChatFixtureReplay.js +3 -3
  38. package/lib/features/agent/chat/AgentChatFixtureReplay.js.map +1 -1
  39. package/lib/features/agent/chat/AgentRequestInputOverlay.d.ts +5 -2
  40. package/lib/features/agent/chat/AgentRequestInputOverlay.d.ts.map +1 -1
  41. package/lib/features/agent/chat/AgentRequestInputOverlay.js +41 -7
  42. package/lib/features/agent/chat/AgentRequestInputOverlay.js.map +1 -1
  43. package/lib/features/agent/chat/AgentRightPanel.d.ts.map +1 -1
  44. package/lib/features/agent/chat/AgentRightPanel.js +133 -12
  45. package/lib/features/agent/chat/AgentRightPanel.js.map +1 -1
  46. package/lib/features/agent/chat/AnimatedThinkingDots.js +1 -1
  47. package/lib/features/agent/chat/AnimatedThinkingDots.js.map +1 -1
  48. package/lib/features/agent/chat/ArtifactsTab.d.ts.map +1 -1
  49. package/lib/features/agent/chat/ArtifactsTab.js +11 -65
  50. package/lib/features/agent/chat/ArtifactsTab.js.map +1 -1
  51. package/lib/features/agent/chat/AskUserWidget.d.ts +3 -1
  52. package/lib/features/agent/chat/AskUserWidget.d.ts.map +1 -1
  53. package/lib/features/agent/chat/AskUserWidget.js +4 -3
  54. package/lib/features/agent/chat/AskUserWidget.js.map +1 -1
  55. package/lib/features/agent/chat/ModernAgentConversation.d.ts +10 -2
  56. package/lib/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
  57. package/lib/features/agent/chat/ModernAgentConversation.js +526 -117
  58. package/lib/features/agent/chat/ModernAgentConversation.js.map +1 -1
  59. package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.d.ts +8 -0
  60. package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.d.ts.map +1 -0
  61. package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.js +19 -0
  62. package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.js.map +1 -0
  63. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts +8 -2
  64. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
  65. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +551 -92
  66. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
  67. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.d.ts.map +1 -1
  68. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js +7 -6
  69. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js.map +1 -1
  70. package/lib/features/agent/chat/ModernAgentOutput/Header.js +2 -2
  71. package/lib/features/agent/chat/ModernAgentOutput/Header.js.map +1 -1
  72. package/lib/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.d.ts +8 -0
  73. package/lib/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.d.ts.map +1 -0
  74. package/lib/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.js +61 -0
  75. package/lib/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.js.map +1 -0
  76. package/lib/features/agent/chat/ModernAgentOutput/MessageInput.d.ts +15 -2
  77. package/lib/features/agent/chat/ModernAgentOutput/MessageInput.d.ts.map +1 -1
  78. package/lib/features/agent/chat/ModernAgentOutput/MessageInput.js +28 -38
  79. package/lib/features/agent/chat/ModernAgentOutput/MessageInput.js.map +1 -1
  80. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.d.ts +1 -1
  81. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.d.ts.map +1 -1
  82. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js +3 -2
  83. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -1
  84. package/lib/features/agent/chat/ModernAgentOutput/SlideInPanel.js +2 -1
  85. package/lib/features/agent/chat/ModernAgentOutput/SlideInPanel.js.map +1 -1
  86. package/lib/features/agent/chat/ModernAgentOutput/SlidingMessages.js +1 -1
  87. package/lib/features/agent/chat/ModernAgentOutput/SlidingMessages.js.map +1 -1
  88. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.d.ts +5 -0
  89. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.d.ts.map +1 -1
  90. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.js +59 -4
  91. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.js.map +1 -1
  92. package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js +2 -2
  93. package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js.map +1 -1
  94. package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.d.ts +9 -0
  95. package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.d.ts.map +1 -1
  96. package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.js +180 -0
  97. package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.js.map +1 -1
  98. package/lib/features/agent/chat/ModernAgentOutput/utils.d.ts +6 -0
  99. package/lib/features/agent/chat/ModernAgentOutput/utils.d.ts.map +1 -1
  100. package/lib/features/agent/chat/ModernAgentOutput/utils.js +92 -2
  101. package/lib/features/agent/chat/ModernAgentOutput/utils.js.map +1 -1
  102. package/lib/features/agent/chat/clipboardFiles.d.ts +15 -0
  103. package/lib/features/agent/chat/clipboardFiles.d.ts.map +1 -0
  104. package/lib/features/agent/chat/clipboardFiles.js +35 -0
  105. package/lib/features/agent/chat/clipboardFiles.js.map +1 -0
  106. package/lib/features/agent/chat/hooks/useAgentStream.d.ts +6 -0
  107. package/lib/features/agent/chat/hooks/useAgentStream.d.ts.map +1 -1
  108. package/lib/features/agent/chat/hooks/useAgentStream.js +218 -37
  109. package/lib/features/agent/chat/hooks/useAgentStream.js.map +1 -1
  110. package/lib/features/agent/chat/hooks/useArtifacts.d.ts +1 -8
  111. package/lib/features/agent/chat/hooks/useArtifacts.d.ts.map +1 -1
  112. package/lib/features/agent/chat/hooks/useArtifacts.js +10 -28
  113. package/lib/features/agent/chat/hooks/useArtifacts.js.map +1 -1
  114. package/lib/features/agent/chat/index.d.ts +2 -1
  115. package/lib/features/agent/chat/index.d.ts.map +1 -1
  116. package/lib/features/agent/chat/index.js +2 -1
  117. package/lib/features/agent/chat/index.js.map +1 -1
  118. package/lib/features/agent/chat/workstreams.d.ts +1 -0
  119. package/lib/features/agent/chat/workstreams.d.ts.map +1 -1
  120. package/lib/features/agent/chat/workstreams.js +28 -0
  121. package/lib/features/agent/chat/workstreams.js.map +1 -1
  122. package/lib/features/facets/AgentRunnerFacetsNav.d.ts +10 -1
  123. package/lib/features/facets/AgentRunnerFacetsNav.d.ts.map +1 -1
  124. package/lib/features/facets/AgentRunnerFacetsNav.js +6 -3
  125. package/lib/features/facets/AgentRunnerFacetsNav.js.map +1 -1
  126. package/lib/features/facets/CollectionsFacetsNav.d.ts +10 -1
  127. package/lib/features/facets/CollectionsFacetsNav.d.ts.map +1 -1
  128. package/lib/features/facets/CollectionsFacetsNav.js +14 -5
  129. package/lib/features/facets/CollectionsFacetsNav.js.map +1 -1
  130. package/lib/features/facets/PromptsFacetsNav.d.ts +10 -1
  131. package/lib/features/facets/PromptsFacetsNav.d.ts.map +1 -1
  132. package/lib/features/facets/PromptsFacetsNav.js +14 -5
  133. package/lib/features/facets/PromptsFacetsNav.js.map +1 -1
  134. package/lib/features/facets/RunsFacetsNav.d.ts +10 -1
  135. package/lib/features/facets/RunsFacetsNav.d.ts.map +1 -1
  136. package/lib/features/facets/RunsFacetsNav.js +14 -5
  137. package/lib/features/facets/RunsFacetsNav.js.map +1 -1
  138. package/lib/features/index.d.ts +0 -1
  139. package/lib/features/index.d.ts.map +1 -1
  140. package/lib/features/index.js +0 -1
  141. package/lib/features/index.js.map +1 -1
  142. package/lib/features/oauth/McpConnectionsButton.d.ts +30 -0
  143. package/lib/features/oauth/McpConnectionsButton.d.ts.map +1 -0
  144. package/lib/features/oauth/McpConnectionsButton.js +70 -0
  145. package/lib/features/oauth/McpConnectionsButton.js.map +1 -0
  146. package/lib/features/oauth/McpConnectionsDialog.d.ts +25 -0
  147. package/lib/features/oauth/McpConnectionsDialog.d.ts.map +1 -0
  148. package/lib/features/oauth/McpConnectionsDialog.js +26 -0
  149. package/lib/features/oauth/McpConnectionsDialog.js.map +1 -0
  150. package/lib/features/oauth/RemoteMcpConnectionButton.d.ts.map +1 -1
  151. package/lib/features/oauth/RemoteMcpConnectionButton.js +14 -6
  152. package/lib/features/oauth/RemoteMcpConnectionButton.js.map +1 -1
  153. package/lib/features/oauth/index.d.ts +3 -0
  154. package/lib/features/oauth/index.d.ts.map +1 -1
  155. package/lib/features/oauth/index.js +3 -0
  156. package/lib/features/oauth/index.js.map +1 -1
  157. package/lib/features/oauth/useMcpConnections.d.ts +44 -0
  158. package/lib/features/oauth/useMcpConnections.d.ts.map +1 -0
  159. package/lib/features/oauth/useMcpConnections.js +168 -0
  160. package/lib/features/oauth/useMcpConnections.js.map +1 -0
  161. package/lib/features/permissions/UserPermissionsProvider.d.ts +4 -6
  162. package/lib/features/permissions/UserPermissionsProvider.d.ts.map +1 -1
  163. package/lib/features/permissions/UserPermissionsProvider.js +40 -42
  164. package/lib/features/permissions/UserPermissionsProvider.js.map +1 -1
  165. package/lib/features/store/objects/DocumentPreviewPanel.d.ts.map +1 -1
  166. package/lib/features/store/objects/DocumentPreviewPanel.js +2 -1
  167. package/lib/features/store/objects/DocumentPreviewPanel.js.map +1 -1
  168. package/lib/features/store/objects/DocumentQuickFilter.d.ts +23 -0
  169. package/lib/features/store/objects/DocumentQuickFilter.d.ts.map +1 -0
  170. package/lib/features/store/objects/DocumentQuickFilter.js +30 -0
  171. package/lib/features/store/objects/DocumentQuickFilter.js.map +1 -0
  172. package/lib/features/store/objects/DocumentSearchResults.d.ts.map +1 -1
  173. package/lib/features/store/objects/DocumentSearchResults.js +17 -1
  174. package/lib/features/store/objects/DocumentSearchResults.js.map +1 -1
  175. package/lib/features/store/objects/components/ContentOverview.d.ts.map +1 -1
  176. package/lib/features/store/objects/components/ContentOverview.js +17 -74
  177. package/lib/features/store/objects/components/ContentOverview.js.map +1 -1
  178. package/lib/features/store/objects/layout/DocumentTableColumn.d.ts +7 -1
  179. package/lib/features/store/objects/layout/DocumentTableColumn.d.ts.map +1 -1
  180. package/lib/features/store/objects/layout/DocumentTableColumn.js +27 -3
  181. package/lib/features/store/objects/layout/DocumentTableColumn.js.map +1 -1
  182. package/lib/features/store/objects/layout/documentLayout.js +1 -1
  183. package/lib/features/store/objects/layout/renderers.d.ts +2 -1
  184. package/lib/features/store/objects/layout/renderers.d.ts.map +1 -1
  185. package/lib/features/store/objects/layout/renderers.js +27 -20
  186. package/lib/features/store/objects/layout/renderers.js.map +1 -1
  187. package/lib/features/store/types/ContentObjectTypesSearch.d.ts.map +1 -1
  188. package/lib/features/store/types/ContentObjectTypesSearch.js +4 -1
  189. package/lib/features/store/types/ContentObjectTypesSearch.js.map +1 -1
  190. package/lib/features/store/types/ContentObjectTypesTable.d.ts +2 -1
  191. package/lib/features/store/types/ContentObjectTypesTable.d.ts.map +1 -1
  192. package/lib/features/store/types/ContentObjectTypesTable.js +8 -3
  193. package/lib/features/store/types/ContentObjectTypesTable.js.map +1 -1
  194. package/lib/i18n/instance.d.ts.map +1 -1
  195. package/lib/i18n/instance.js +1 -0
  196. package/lib/i18n/instance.js.map +1 -1
  197. package/lib/i18n/locales/ar.json +72 -45
  198. package/lib/i18n/locales/de.json +65 -34
  199. package/lib/i18n/locales/en.json +63 -47
  200. package/lib/i18n/locales/es.json +65 -35
  201. package/lib/i18n/locales/fr.json +65 -35
  202. package/lib/i18n/locales/it.json +72 -42
  203. package/lib/i18n/locales/ja.json +72 -41
  204. package/lib/i18n/locales/ko.json +72 -41
  205. package/lib/i18n/locales/pt.json +72 -42
  206. package/lib/i18n/locales/ru.json +72 -43
  207. package/lib/i18n/locales/tr.json +72 -41
  208. package/lib/i18n/locales/zh-TW.json +72 -41
  209. package/lib/i18n/locales/zh.json +72 -41
  210. package/lib/session/UserSession.d.ts +0 -6
  211. package/lib/session/UserSession.d.ts.map +1 -1
  212. package/lib/session/UserSession.js +0 -15
  213. package/lib/session/UserSession.js.map +1 -1
  214. package/lib/session/UserSessionProvider.d.ts.map +1 -1
  215. package/lib/session/UserSessionProvider.js +39 -98
  216. package/lib/session/UserSessionProvider.js.map +1 -1
  217. package/lib/session/auth/composable.d.ts.map +1 -1
  218. package/lib/session/auth/composable.js +3 -33
  219. package/lib/session/auth/composable.js.map +1 -1
  220. package/lib/shell/login/SignInPrimitives.d.ts.map +1 -1
  221. package/lib/shell/login/SignInPrimitives.js +3 -2
  222. package/lib/shell/login/SignInPrimitives.js.map +1 -1
  223. package/lib/vertesia-ui-core.js +1 -1
  224. package/lib/vertesia-ui-core.js.map +1 -1
  225. package/lib/vertesia-ui-env.js +1 -1
  226. package/lib/vertesia-ui-env.js.map +1 -1
  227. package/lib/vertesia-ui-features.js +1 -1
  228. package/lib/vertesia-ui-features.js.map +1 -1
  229. package/lib/vertesia-ui-i18n.js +1 -1
  230. package/lib/vertesia-ui-i18n.js.map +1 -1
  231. package/lib/vertesia-ui-session.js +1 -1
  232. package/lib/vertesia-ui-session.js.map +1 -1
  233. package/lib/vertesia-ui-shell.js +1 -1
  234. package/lib/vertesia-ui-shell.js.map +1 -1
  235. package/lib/vertesia-ui-widgets.js +1 -1
  236. package/lib/vertesia-ui-widgets.js.map +1 -1
  237. package/lib/widgets/schema-editor/editor/Editable.js +1 -1
  238. package/lib/widgets/schema-editor/editor/Editable.js.map +1 -1
  239. package/llms.txt +70 -70
  240. package/package.json +35 -32
  241. package/src/core/components/shadcn/dropdown.tsx +2 -0
  242. package/src/core/components/shadcn/filters/filterBar.tsx +9 -2
  243. package/src/core/components/shadcn/modal/ConfirmModal.tsx +65 -3
  244. package/src/core/components/shadcn/modal/dialog.tsx +1 -1
  245. package/src/core/components/shadcn/popover.tsx +1 -0
  246. package/src/core/components/shadcn/switch.tsx +4 -4
  247. package/src/core/components/shadcn/tabs.tsx +1 -1
  248. package/src/core/components/shadcn/tooltip.tsx +1 -0
  249. package/src/env/index.ts +0 -24
  250. package/src/features/agent/PayloadBuilder.tsx +18 -0
  251. package/src/features/agent/chat/AgentApprovalModeSelector.tsx +130 -0
  252. package/src/features/agent/chat/AgentChatFixtureReplay.test.tsx +22 -2
  253. package/src/features/agent/chat/AgentChatFixtureReplay.tsx +33 -27
  254. package/src/features/agent/chat/AgentRequestInputOverlay.test.tsx +122 -0
  255. package/src/features/agent/chat/AgentRequestInputOverlay.tsx +91 -17
  256. package/src/features/agent/chat/AgentRightPanel.tsx +238 -50
  257. package/src/features/agent/chat/AnimatedThinkingDots.tsx +1 -1
  258. package/src/features/agent/chat/ArtifactsTab.tsx +21 -155
  259. package/src/features/agent/chat/AskUserWidget.tsx +6 -2
  260. package/src/features/agent/chat/ModernAgentConversation.test.tsx +1157 -47
  261. package/src/features/agent/chat/ModernAgentConversation.tsx +703 -136
  262. package/src/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.tsx +74 -0
  263. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.test.tsx +1420 -126
  264. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +934 -111
  265. package/src/features/agent/chat/ModernAgentOutput/AttachmentPreview.tsx +31 -40
  266. package/src/features/agent/chat/ModernAgentOutput/Header.tsx +28 -28
  267. package/src/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.tsx +83 -0
  268. package/src/features/agent/chat/ModernAgentOutput/MessageInput.test.tsx +38 -2
  269. package/src/features/agent/chat/ModernAgentOutput/MessageInput.tsx +121 -98
  270. package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +7 -1
  271. package/src/features/agent/chat/ModernAgentOutput/SlideInPanel.tsx +3 -3
  272. package/src/features/agent/chat/ModernAgentOutput/SlidingMessages.tsx +1 -1
  273. package/src/features/agent/chat/ModernAgentOutput/SummaryConversation.ts +82 -2
  274. package/src/features/agent/chat/ModernAgentOutput/WorkstreamTabs.tsx +2 -2
  275. package/src/features/agent/chat/ModernAgentOutput/requestInputMessages.ts +216 -0
  276. package/src/features/agent/chat/ModernAgentOutput/utils.test.ts +149 -0
  277. package/src/features/agent/chat/ModernAgentOutput/utils.ts +103 -2
  278. package/src/features/agent/chat/clipboardFiles.ts +33 -0
  279. package/src/features/agent/chat/hooks/useAgentStream.test.tsx +355 -4
  280. package/src/features/agent/chat/hooks/useAgentStream.ts +270 -43
  281. package/src/features/agent/chat/hooks/useArtifacts.ts +11 -44
  282. package/src/features/agent/chat/index.ts +10 -1
  283. package/src/features/agent/chat/workstreams.ts +42 -0
  284. package/src/features/facets/AgentRunnerFacetsNav.tsx +23 -3
  285. package/src/features/facets/CollectionsFacetsNav.tsx +30 -5
  286. package/src/features/facets/PromptsFacetsNav.tsx +30 -5
  287. package/src/features/facets/RunsFacetsNav.tsx +32 -5
  288. package/src/features/index.ts +0 -1
  289. package/src/features/oauth/McpConnectionsButton.test.tsx +248 -0
  290. package/src/features/oauth/McpConnectionsButton.tsx +269 -0
  291. package/src/features/oauth/McpConnectionsDialog.tsx +142 -0
  292. package/src/features/oauth/RemoteMcpConnectionButton.tsx +37 -14
  293. package/src/features/oauth/index.ts +3 -0
  294. package/src/features/oauth/useMcpConnections.test.ts +94 -0
  295. package/src/features/oauth/useMcpConnections.ts +210 -0
  296. package/src/features/permissions/UserPermissionsProvider.tsx +41 -59
  297. package/src/features/store/objects/DocumentPreviewPanel.tsx +4 -2
  298. package/src/features/store/objects/DocumentQuickFilter.tsx +72 -0
  299. package/src/features/store/objects/DocumentSearchResults.tsx +30 -11
  300. package/src/features/store/objects/components/ContentOverview.tsx +30 -99
  301. package/src/features/store/objects/layout/DocumentTableColumn.tsx +29 -4
  302. package/src/features/store/objects/layout/documentLayout.tsx +1 -1
  303. package/src/features/store/objects/layout/renderers.tsx +80 -20
  304. package/src/features/store/types/ContentObjectTypesSearch.tsx +7 -1
  305. package/src/features/store/types/ContentObjectTypesTable.tsx +34 -4
  306. package/src/i18n/instance.ts +1 -0
  307. package/src/i18n/locales/ar.json +72 -45
  308. package/src/i18n/locales/de.json +65 -34
  309. package/src/i18n/locales/en.json +63 -47
  310. package/src/i18n/locales/es.json +65 -35
  311. package/src/i18n/locales/fr.json +65 -35
  312. package/src/i18n/locales/it.json +72 -42
  313. package/src/i18n/locales/ja.json +72 -41
  314. package/src/i18n/locales/ko.json +72 -41
  315. package/src/i18n/locales/pt.json +72 -42
  316. package/src/i18n/locales/ru.json +72 -43
  317. package/src/i18n/locales/tr.json +72 -41
  318. package/src/i18n/locales/zh-TW.json +72 -41
  319. package/src/i18n/locales/zh.json +72 -41
  320. package/src/i18n/rtl.test.ts +57 -1
  321. package/src/session/UserSession.ts +0 -16
  322. package/src/session/UserSessionProvider.tsx +51 -123
  323. package/src/session/auth/composable.ts +3 -34
  324. package/src/shell/login/SignInPrimitives.tsx +3 -2
  325. package/src/widgets/schema-editor/editor/Editable.tsx +1 -1
  326. package/lib/features/document-viewer/UniversalDocumentViewer.d.ts +0 -73
  327. package/lib/features/document-viewer/UniversalDocumentViewer.d.ts.map +0 -1
  328. package/lib/features/document-viewer/UniversalDocumentViewer.js +0 -415
  329. package/lib/features/document-viewer/UniversalDocumentViewer.js.map +0 -1
  330. package/lib/features/document-viewer/index.d.ts +0 -2
  331. package/lib/features/document-viewer/index.d.ts.map +0 -1
  332. package/lib/features/document-viewer/index.js +0 -2
  333. package/lib/features/document-viewer/index.js.map +0 -1
  334. package/src/features/document-viewer/UniversalDocumentViewer.test.tsx +0 -123
  335. package/src/features/document-viewer/UniversalDocumentViewer.tsx +0 -746
  336. package/src/features/document-viewer/index.ts +0 -1
  337. package/src/session/auth/composable.test.ts +0 -79
@@ -1,31 +1,35 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { AgentMessageType, } from '@vertesia/common';
2
+ import { AgentMessageType, normalizeAgentToolApprovalMode, } from '@vertesia/common';
3
3
  import { FusionFragmentProvider } from '@vertesia/fusion-ux';
4
4
  import { Button, cn, insertNewlineAtCursor, MessageBox, Modal, ModalBody, ModalFooter, ModalTitle, Spinner, Textarea, useToast, } from '@vertesia/ui/core';
5
5
  import { useUITranslation } from '@vertesia/ui/i18n';
6
6
  import { useUserSession } from '@vertesia/ui/session';
7
7
  import { ArrowUpIcon, Bot, CheckCircle, Cpu, FileTextIcon, UploadIcon, XIcon } from 'lucide-react';
8
8
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
9
+ import { McpConnectionsActionMenu } from '../../oauth/McpConnectionsButton.js';
10
+ import { AgentApprovalModeSelector } from './AgentApprovalModeSelector';
9
11
  import { AgentChatPlaybackControls } from './AgentChatPlaybackControls';
10
12
  import { AgentRequestInputOverlay } from './AgentRequestInputOverlay';
11
13
  import { AgentRightPanel } from './AgentRightPanel.js';
12
14
  import { AnimatedThinkingDots, PulsatingCircle } from './AnimatedThinkingDots';
15
+ import { extractFilesFromClipboard } from './clipboardFiles.js';
13
16
  import { useAgentPlans } from './hooks/useAgentPlans.js';
14
17
  import { useAgentStream } from './hooks/useAgentStream.js';
15
18
  import { useDocumentPanel } from './hooks/useDocumentPanel.js';
16
19
  import { useFileProcessing } from './hooks/useFileProcessing.js';
17
20
  import { ImageLightboxProvider } from './ImageLightbox';
21
+ import { ActiveWorkstreamsSummary } from './ModernAgentOutput/ActiveWorkstreamsSummary';
18
22
  import AllMessagesMixed from './ModernAgentOutput/AllMessagesMixed';
19
23
  import Header from './ModernAgentOutput/Header';
20
24
  import MessageInput from './ModernAgentOutput/MessageInput';
21
25
  import { getPendingRequestInputMessage } from './ModernAgentOutput/requestInputMessages';
22
- import { getConversationUrl, getWorkstreamId, isInProgress } from './ModernAgentOutput/utils';
26
+ import { debugAgentChat, filterMessagesForActiveWorkstream, getConversationUrl, getWorkstreamId, isInProgress, } from './ModernAgentOutput/utils';
23
27
  import { createPlaybackState, getPlaybackCursorIndex, isAgentChatPlaybackAvailable, isAgentChatPlaybackEnabled, } from './playback';
24
28
  import { SkillWidgetProvider } from './SkillWidgetProvider';
25
29
  import { ArtifactUrlCacheProvider } from './useArtifactUrlCache.js';
26
30
  import { VegaLiteChart } from './VegaLiteChart';
27
31
  import { ThinkingMessages } from './WaitingMessages';
28
- import { getWorkstreamLaunchDetails, getWorkstreamLifecycleStatus, isWorkstreamInternalResultMessage, isWorkstreamTerminalMessage, } from './workstreams.js';
32
+ import { getWorkstreamDisplayName, getWorkstreamLaunchDetails, getWorkstreamLifecycleStatus, isWorkstreamInternalResultMessage, } from './workstreams.js';
29
33
  const EMPTY_STREAMING_MESSAGES = new Map();
30
34
  function getTimestampMs(timestamp) {
31
35
  if (typeof timestamp === 'number')
@@ -35,46 +39,216 @@ function getTimestampMs(timestamp) {
35
39
  const parsed = new Date(timestamp).getTime();
36
40
  return Number.isFinite(parsed) ? parsed : Date.now();
37
41
  }
38
- function deriveActiveWorkstreamsFromMessages(messages) {
39
- const latestByWorkstream = new Map();
40
- const launchesByWorkstream = new Map();
41
- for (const message of messages) {
42
- const launchDetails = getWorkstreamLaunchDetails(message);
43
- if (launchDetails) {
44
- launchesByWorkstream.set(launchDetails.workstreamId, {
45
- launch_id: launchDetails.launchId,
46
- interaction: launchDetails.interaction,
47
- child_workflow_id: launchDetails.childWorkflowId,
48
- child_workflow_run_id: launchDetails.childWorkflowRunId,
49
- });
50
- }
51
- if (isWorkstreamInternalResultMessage(message))
42
+ function isActiveWorkstreamStatus(status) {
43
+ return status === 'running' || status === 'canceling';
44
+ }
45
+ function isTerminalWorkstreamStatus(status) {
46
+ return !isActiveWorkstreamStatus(status);
47
+ }
48
+ function getNumberDetail(value) {
49
+ return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
50
+ }
51
+ function toContextWindowUsage(messages) {
52
+ for (let index = messages.length - 1; index >= 0; index--) {
53
+ const details = messages[index].details;
54
+ if (!details)
52
55
  continue;
53
- const workstreamId = getWorkstreamId(message);
54
- if (workstreamId === 'main' || workstreamId === 'all')
56
+ const tokenUsage = details.token_usage;
57
+ const usedTokens = getNumberDetail(tokenUsage?.total);
58
+ const checkpointTokens = getNumberDetail(details.checkpoint_threshold) ?? getNumberDetail(details.checkpoint_at);
59
+ if (typeof usedTokens !== 'number' || typeof checkpointTokens !== 'number' || checkpointTokens <= 0) {
55
60
  continue;
56
- latestByWorkstream.set(workstreamId, message);
57
- }
58
- return Array.from(latestByWorkstream.entries())
59
- .filter(([, message]) => {
60
- if ([AgentMessageType.COMPLETE, AgentMessageType.IDLE].includes(message.type))
61
- return false;
62
- return !isWorkstreamTerminalMessage(message);
63
- })
64
- .map(([workstreamId, message]) => {
65
- const launch = launchesByWorkstream.get(workstreamId);
61
+ }
62
+ const usedPercent = Math.max(0, Math.min(100, Math.round((usedTokens / checkpointTokens) * 100)));
66
63
  return {
67
- workstream_id: workstreamId,
68
- launch_id: launch?.launch_id ?? `message-derived:${workstreamId}`,
69
- interaction: launch?.interaction,
70
- elapsed_ms: 0,
71
- deadline_ms: 0,
72
- remaining_ms: 0,
73
- status: getWorkstreamLifecycleStatus(message) ?? 'running',
74
- child_workflow_id: launch?.child_workflow_id,
75
- child_workflow_run_id: launch?.child_workflow_run_id,
64
+ usedTokens,
65
+ checkpointTokens,
66
+ usedPercent,
67
+ remainingPercent: Math.max(0, 100 - usedPercent),
76
68
  };
69
+ }
70
+ return undefined;
71
+ }
72
+ function mergePreservingTerminalStatus(existing, next) {
73
+ if (!isTerminalWorkstreamStatus(existing.status) || !isActiveWorkstreamStatus(next.status)) {
74
+ return { ...existing, ...next };
75
+ }
76
+ return {
77
+ ...existing,
78
+ interaction: existing.interaction ?? next.interaction,
79
+ elapsed_ms: Math.max(existing.elapsed_ms, next.elapsed_ms),
80
+ deadline_ms: Math.max(existing.deadline_ms, next.deadline_ms),
81
+ remaining_ms: 0,
82
+ phase: existing.phase ?? next.phase,
83
+ child_workflow_id: existing.child_workflow_id ?? next.child_workflow_id,
84
+ child_workflow_run_id: existing.child_workflow_run_id ?? next.child_workflow_run_id,
85
+ };
86
+ }
87
+ function getWorkstreamMessageDetails(message) {
88
+ const details = message.details;
89
+ const workstreamId = typeof details?.workstream_id === 'string' && details.workstream_id.trim()
90
+ ? details.workstream_id
91
+ : getWorkstreamId(message);
92
+ if (workstreamId === 'main' || workstreamId === 'all')
93
+ return null;
94
+ return {
95
+ workstreamId,
96
+ launchId: typeof details?.launch_id === 'string' ? details.launch_id : undefined,
97
+ interaction: typeof details?.interaction === 'string' ? details.interaction : undefined,
98
+ childWorkflowId: typeof details?.child_workflow_id === 'string' ? details.child_workflow_id : undefined,
99
+ childWorkflowRunId: typeof details?.child_workflow_run_id === 'string' ? details.child_workflow_run_id : undefined,
100
+ };
101
+ }
102
+ function isWorkstreamActivityFailureMessage(message) {
103
+ if (message.type !== AgentMessageType.ERROR)
104
+ return false;
105
+ const details = message.details;
106
+ if (details?.event_class !== 'activity')
107
+ return false;
108
+ if (details.workstream_event)
109
+ return false;
110
+ return !(details.tool ||
111
+ details.tool_status ||
112
+ details.tool_run_id ||
113
+ details.activity_group_id ||
114
+ details.tool_event);
115
+ }
116
+ function ensureWorkstreamRecord(records, latestKeyByWorkstream, workstreamId, launchId, timestamp, order) {
117
+ if (launchId) {
118
+ const previousKey = latestKeyByWorkstream.get(workstreamId);
119
+ if (previousKey?.startsWith('message-derived:')) {
120
+ const previous = records.get(previousKey);
121
+ if (previous) {
122
+ records.delete(previousKey);
123
+ records.set(launchId, {
124
+ ...previous,
125
+ launch_id: launchId,
126
+ updated_at: Math.max(previous.updated_at, timestamp),
127
+ });
128
+ }
129
+ }
130
+ latestKeyByWorkstream.set(workstreamId, launchId);
131
+ }
132
+ const key = launchId ?? latestKeyByWorkstream.get(workstreamId) ?? `message-derived:${workstreamId}`;
133
+ const existing = records.get(key);
134
+ if (existing)
135
+ return existing;
136
+ const record = {
137
+ workstream_id: workstreamId,
138
+ launch_id: key,
139
+ elapsed_ms: 0,
140
+ deadline_ms: 0,
141
+ remaining_ms: 0,
142
+ status: 'running',
143
+ started_at: timestamp,
144
+ updated_at: timestamp,
145
+ order,
146
+ };
147
+ records.set(key, record);
148
+ if (!latestKeyByWorkstream.has(workstreamId))
149
+ latestKeyByWorkstream.set(workstreamId, key);
150
+ return record;
151
+ }
152
+ function deriveWorkstreamsFromMessages(messages) {
153
+ const records = new Map();
154
+ const latestKeyByWorkstream = new Map();
155
+ messages.forEach((message, order) => {
156
+ const timestamp = getTimestampMs(message.timestamp);
157
+ const details = getWorkstreamMessageDetails(message);
158
+ const launchDetails = getWorkstreamLaunchDetails(message);
159
+ const workstreamId = launchDetails?.workstreamId ?? details?.workstreamId;
160
+ if (!workstreamId)
161
+ return;
162
+ const launchId = launchDetails?.launchId ?? details?.launchId;
163
+ const isInternalResult = isWorkstreamInternalResultMessage(message);
164
+ if (!launchDetails && !launchId && isInternalResult && !latestKeyByWorkstream.has(workstreamId))
165
+ return;
166
+ const record = ensureWorkstreamRecord(records, latestKeyByWorkstream, workstreamId, launchId, timestamp, order);
167
+ if (launchDetails) {
168
+ record.interaction = launchDetails.interaction ?? record.interaction;
169
+ record.child_workflow_id = launchDetails.childWorkflowId ?? record.child_workflow_id;
170
+ record.child_workflow_run_id = launchDetails.childWorkflowRunId ?? record.child_workflow_run_id;
171
+ record.status = 'running';
172
+ }
173
+ else {
174
+ record.interaction = details?.interaction ?? record.interaction;
175
+ record.child_workflow_id = details?.childWorkflowId ?? record.child_workflow_id;
176
+ record.child_workflow_run_id = details?.childWorkflowRunId ?? record.child_workflow_run_id;
177
+ }
178
+ const lifecycleStatus = getWorkstreamLifecycleStatus(message);
179
+ if (lifecycleStatus) {
180
+ record.status = lifecycleStatus;
181
+ }
182
+ else if (!isInternalResult) {
183
+ if (isWorkstreamActivityFailureMessage(message)) {
184
+ record.status = 'failed';
185
+ }
186
+ else if (message.type === AgentMessageType.COMPLETE || message.type === AgentMessageType.IDLE) {
187
+ record.status = 'completed';
188
+ }
189
+ }
190
+ if (isInternalResult)
191
+ return;
192
+ record.updated_at = Math.max(record.updated_at, timestamp);
193
+ if (isActiveWorkstreamStatus(record.status)) {
194
+ record.elapsed_ms = Math.max(record.elapsed_ms, timestamp - record.started_at);
195
+ }
196
+ else {
197
+ record.elapsed_ms = Math.max(record.elapsed_ms, timestamp - record.started_at);
198
+ record.remaining_ms = 0;
199
+ }
77
200
  });
201
+ return Array.from(records.values())
202
+ .sort((a, b) => {
203
+ const activeDelta = Number(!isActiveWorkstreamStatus(a.status)) - Number(!isActiveWorkstreamStatus(b.status));
204
+ if (activeDelta !== 0)
205
+ return activeDelta;
206
+ if (isActiveWorkstreamStatus(a.status))
207
+ return a.order - b.order;
208
+ return b.updated_at - a.updated_at || a.order - b.order;
209
+ })
210
+ .map(({ started_at, updated_at, order, ...workstream }) => workstream);
211
+ }
212
+ function activeWorkstreamEntryToInfo(ws) {
213
+ return {
214
+ workstream_id: ws.workstream_id,
215
+ launch_id: ws.launch_id,
216
+ interaction: ws.interaction,
217
+ elapsed_ms: ws.elapsed_ms,
218
+ deadline_ms: ws.deadline_ms,
219
+ remaining_ms: Math.max(0, ws.deadline_ms - ws.elapsed_ms),
220
+ status: ws.status,
221
+ phase: ws.latest_progress?.phase,
222
+ child_workflow_id: ws.child_workflow_id,
223
+ child_workflow_run_id: ws.child_workflow_run_id,
224
+ };
225
+ }
226
+ function completedWorkstreamEntryToInfo(ws) {
227
+ return {
228
+ workstream_id: ws.workstream_id,
229
+ launch_id: ws.launch_id,
230
+ interaction: ws.interaction,
231
+ elapsed_ms: ws.duration_ms ?? 0,
232
+ deadline_ms: 0,
233
+ remaining_ms: 0,
234
+ status: ws.status,
235
+ phase: ws.last_progress?.phase,
236
+ child_workflow_id: ws.child_workflow_id,
237
+ child_workflow_run_id: ws.child_workflow_run_id,
238
+ };
239
+ }
240
+ function mergeWorkstreamInfo(workstreams, next) {
241
+ const existingIndex = workstreams.findIndex((ws) => ws.launch_id === next.launch_id);
242
+ if (existingIndex >= 0) {
243
+ workstreams[existingIndex] = mergePreservingTerminalStatus(workstreams[existingIndex], next);
244
+ return;
245
+ }
246
+ const fallbackIndex = workstreams.findIndex((ws) => ws.workstream_id === next.workstream_id && ws.launch_id.startsWith('message-derived:'));
247
+ if (fallbackIndex >= 0 && !next.launch_id.startsWith('message-derived:')) {
248
+ workstreams[fallbackIndex] = mergePreservingTerminalStatus(workstreams[fallbackIndex], next);
249
+ return;
250
+ }
251
+ workstreams.push(next);
78
252
  }
79
253
  function formatCompactDuration(seconds) {
80
254
  if (seconds < 60)
@@ -197,12 +371,13 @@ function EmptyState() {
197
371
  }
198
372
  // Start workflow view - allows initiating a new agent conversation
199
373
  // Files can be staged locally before workflow starts, then uploaded when the workflow is created
200
- function StartWorkflowView({ initialMessage, startWorkflow, onClose, isModal = false, fullWidth = false, placeholder, startButtonText, title,
374
+ function StartWorkflowView({ initialMessage, interactive = true, startWorkflow, onClose, isModal = false, fullWidth = false, placeholder, startButtonText, title,
201
375
  // Attachment callback - used to include existing document attachments in the first message
202
376
  getAttachedDocs, onAttachmentsSent,
203
377
  // File upload props
204
- acceptedFileTypes, maxFiles = 5, hideHeader = false, hideFileUpload = false, hideObjectLinking, headerVariant, inputContainerClassName, inputClassName, className, allowWorkflowControl, }) {
378
+ acceptedFileTypes, maxFiles = 5, hideHeader = false, hideFileUpload = false, hideObjectLinking, headerVariant, inputContainerClassName, inputClassName, className, allowWorkflowControl, initialToolApprovalMode, }) {
205
379
  const { t } = useUITranslation();
380
+ const canStageFiles = !hideFileUpload;
206
381
  const resolvedPlaceholder = placeholder ?? t('agent.typeYourMessage');
207
382
  const resolvedStartButtonText = startButtonText ?? t('agent.startAgent');
208
383
  const resolvedTitle = title ?? t('agent.startNewConversation');
@@ -212,12 +387,12 @@ acceptedFileTypes, maxFiles = 5, hideHeader = false, hideFileUpload = false, hid
212
387
  const [startedAgentRunId, setStartedAgentRunId] = useState(null);
213
388
  const [pendingStartMessage, setPendingStartMessage] = useState(null);
214
389
  const [pendingStartTimestamp, setPendingStartTimestamp] = useState(null);
390
+ const [toolApprovalMode, setToolApprovalMode] = useState(() => normalizeAgentToolApprovalMode(initialToolApprovalMode, interactive));
215
391
  const toast = useToast();
216
392
  const inputRef = useRef(null);
217
393
  const fileInputRef = useRef(null);
218
394
  // Staged files - stored locally until workflow starts
219
395
  const [stagedFiles, setStagedFiles] = useState([]);
220
- const canStageFiles = !hideFileUpload;
221
396
  // Drag and drop state
222
397
  const [isDragOver, setIsDragOver] = useState(false);
223
398
  const dragCounterRef = useRef(0);
@@ -263,6 +438,17 @@ acceptedFileTypes, maxFiles = 5, hideHeader = false, hideFileUpload = false, hid
263
438
  });
264
439
  }
265
440
  }, [maxFiles, canStageFiles]);
441
+ // Paste handler for files — mirrors MessageInput.handlePaste so the start
442
+ // screen and the live chat both accept pasted clipboard images/files. Files
443
+ // are staged locally here; they get uploaded when the workflow starts.
444
+ const handlePaste = useCallback((e) => {
445
+ if (!canStageFiles)
446
+ return;
447
+ const files = extractFilesFromClipboard(e.clipboardData?.items);
448
+ if (files.length > 0) {
449
+ setStagedFiles((prev) => [...prev, ...files].slice(0, maxFiles));
450
+ }
451
+ }, [canStageFiles, maxFiles]);
266
452
  const handleFileInputChange = useCallback((e) => {
267
453
  if (e.target.files && e.target.files.length > 0) {
268
454
  const filesArray = Array.from(e.target.files);
@@ -320,7 +506,7 @@ acceptedFileTypes, maxFiles = 5, hideHeader = false, hideFileUpload = false, hid
320
506
  }
321
507
  setPendingStartMessage(messageContent);
322
508
  setPendingStartTimestamp(Date.now());
323
- const newRun = await startWorkflow(messageContent);
509
+ const newRun = await startWorkflow(messageContent, { tool_approval_mode: toolApprovalMode });
324
510
  if (newRun) {
325
511
  const agentId = newRun.agent_run_id;
326
512
  // Upload staged files to the new run's artifact space and signal agent
@@ -429,11 +615,9 @@ acceptedFileTypes, maxFiles = 5, hideHeader = false, hideFileUpload = false, hid
429
615
  inputContainerClassName,
430
616
  inputClassName,
431
617
  className,
432
- allowWorkflowControl, agentRunId: startedAgentRunId, title: title, pendingStartMessage: pendingStartMessage ?? undefined, pendingStartTimestamp: pendingStartTimestamp ?? undefined }));
618
+ allowWorkflowControl, agentRunId: startedAgentRunId, title: title, pendingStartMessage: pendingStartMessage ?? undefined, pendingStartTimestamp: pendingStartTimestamp ?? undefined, initialToolApprovalMode: toolApprovalMode }));
433
619
  }
434
- return (_jsx("div", { className: cn('flex h-full flex-col items-center bg-background', className), children: _jsxs("div", { className: cn('relative flex h-full w-full flex-col overflow-hidden border-0', fullWidth ? '' : 'max-w-4xl'), onDragEnter: canStageFiles ? handleDragEnter : undefined, onDragOver: canStageFiles ? handleDragOver : undefined, onDragLeave: canStageFiles ? handleDragLeave : undefined, onDrop: canStageFiles ? handleDrop : undefined, children: [canStageFiles && isDragOver && (_jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-info-background z-50 pointer-events-none rounded-lg", children: _jsxs("div", { className: "text-info font-medium flex items-center gap-2 text-lg", children: [_jsx(UploadIcon, { className: "size-6" }), "Drop files to stage for upload"] }) })), canStageFiles && (_jsx("input", { ref: fileInputRef, type: "file", multiple: true, accept: acceptedFileTypes, onChange: handleFileInputChange, className: "hidden" })), !hideHeader && (_jsxs("div", { className: "flex items-center justify-between border-b border-border/60 bg-background px-3 py-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "p-1", children: _jsx(Cpu, { className: "size-3.5 text-muted" }) }), _jsx("span", { className: "text-sm font-medium text-foreground", children: resolvedTitle })] }), onClose && !isModal && (_jsx(Button, { size: "xs", variant: "ghost", onClick: onClose, "aria-label": t('agent.close'), title: t('agent.close'), className: "text-muted hover:text-foreground", children: _jsx(XIcon, { className: "size-4" }) }))] })), _jsx("div", { className: "flex flex-1 flex-col items-center justify-end overflow-y-auto bg-background px-4", children: pendingStartMessage && pendingStartTimestamp ? (_jsx(PendingStartConversation, { message: pendingStartMessage, startedAt: pendingStartTimestamp })) : (_jsx("div", { className: "mx-auto flex min-h-full w-full max-w-3xl flex-col justify-end py-8", children: initialMessage && (_jsx("div", { className: "text-[15px] leading-relaxed text-foreground/80", children: initialMessage })) })) }), _jsxs("div", { className: "shrink-0 bg-background px-4 pb-safe-area-4 pt-2", children: [_jsxs("div", { className: cn('mx-auto flex max-w-3xl flex-col gap-3 rounded-2xl border border-border/70 bg-mixer-muted/15 p-3 shadow-lg shadow-black/5', inputContainerClassName), children: [canStageFiles && stagedFiles.length > 0 && (_jsx("div", { className: "flex flex-wrap gap-2", children: stagedFiles.map((file, index) => (_jsxs("div", { className: "flex items-center gap-1.5 rounded-md bg-attention/10 px-2 py-1 text-sm text-attention", children: [_jsx(FileTextIcon, { className: "size-3.5" }), _jsx("span", { className: "max-w-[120px] truncate", children: file.name }), _jsx("span", { className: "text-xs opacity-70", children: t('agent.staged') }), _jsx(Button, { variant: "unstyled", "aria-label": `Remove staged file ${file.name}`, onClick: () => removeStagedFile(index), className: "ms-1 rounded p-0.5 hover:bg-attention/20", children: _jsx(XIcon, { className: "size-3" }) })] }, `${file.name}-${file.size}-${file.lastModified}`))) })), _jsx(Textarea, { ref: inputRef, value: inputValue, onChange: (e) => setInputValue(e.target.value), onKeyDown: handleKeyDown, placeholder: resolvedPlaceholder, disabled: isSending, rows: 2, className: cn('min-h-[72px] resize-none overflow-hidden border-0 bg-transparent px-0 py-0 text-sm leading-6 shadow-none focus-visible:ring-0', inputClassName), style: { minHeight: '72px', maxHeight: '200px' } }), _jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx("div", { className: "flex min-w-0 items-center gap-2", children: canStageFiles && (_jsx(Button, { variant: "ghost", size: "icon", onClick: () => fileInputRef.current?.click(), disabled: isSending || stagedFiles.length >= maxFiles, "aria-label": t('agent.upload'), className: "rounded-full text-muted", title: t('agent.upload'), children: _jsx(UploadIcon, { className: "size-4" }) })) }), _jsx(Button, { onClick: startWorkflowWithMessage, disabled: !inputValue.trim() || isSending, variant: "ghost", size: "icon", className: cn('size-9 rounded-full border border-border/60 bg-foreground text-background shadow-sm', 'hover:bg-foreground/90 hover:text-background', 'disabled:bg-mixer-muted/25 disabled:text-muted disabled:opacity-100'), title: resolvedStartButtonText, "aria-label": resolvedStartButtonText, children: isSending ? _jsx(Spinner, { size: "sm" }) : _jsx(ArrowUpIcon, { className: "size-4" }) })] })] }), _jsx("div", { className: "mx-auto mt-2 max-w-3xl text-center text-xs text-muted", children: canStageFiles && stagedFiles.length > 0
435
- ? t('agent.filesStagedCount', { count: stagedFiles.length })
436
- : t('agent.enterToSend') })] })] }) }));
620
+ return (_jsx("div", { className: cn('flex h-full flex-col items-center bg-background', className), children: _jsxs("div", { className: cn('relative flex h-full w-full flex-col overflow-hidden border-0', fullWidth ? '' : 'max-w-4xl'), onDragEnter: canStageFiles ? handleDragEnter : undefined, onDragOver: canStageFiles ? handleDragOver : undefined, onDragLeave: canStageFiles ? handleDragLeave : undefined, onDrop: canStageFiles ? handleDrop : undefined, children: [canStageFiles && isDragOver && (_jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-info-background z-50 pointer-events-none rounded-lg", children: _jsxs("div", { className: "text-info font-medium flex items-center gap-2 text-lg", children: [_jsx(UploadIcon, { className: "size-6" }), "Drop files to stage for upload"] }) })), canStageFiles && (_jsx("input", { ref: fileInputRef, type: "file", multiple: true, accept: acceptedFileTypes, onChange: handleFileInputChange, className: "hidden" })), !hideHeader && (_jsxs("div", { className: "flex items-center justify-between border-b border-border/60 bg-background px-3 py-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "p-1", children: _jsx(Cpu, { className: "size-3.5 text-muted" }) }), _jsx("span", { className: "text-sm font-medium text-foreground", children: resolvedTitle })] }), onClose && !isModal && (_jsx(Button, { size: "xs", variant: "ghost", onClick: onClose, "aria-label": t('agent.close'), title: t('agent.close'), className: "text-muted hover:text-foreground", children: _jsx(XIcon, { className: "size-4" }) }))] })), _jsx("div", { className: "flex flex-1 flex-col items-center justify-end overflow-y-auto bg-background px-4", children: pendingStartMessage && pendingStartTimestamp ? (_jsx(PendingStartConversation, { message: pendingStartMessage, startedAt: pendingStartTimestamp })) : (_jsx("div", { className: "mx-auto flex min-h-full w-full max-w-3xl flex-col justify-end py-8", children: initialMessage && (_jsx("div", { className: "text-[15px] leading-relaxed text-foreground/80", children: initialMessage })) })) }), _jsx("div", { className: "shrink-0 bg-background px-4 pb-safe-area-4 pt-2", children: _jsxs("div", { className: cn('mx-auto flex max-w-3xl flex-col gap-3 rounded-2xl border border-border/70 bg-mixer-muted/15 p-3 shadow-lg shadow-black/5', inputContainerClassName), children: [canStageFiles && stagedFiles.length > 0 && (_jsx("div", { className: "flex flex-wrap gap-2", children: stagedFiles.map((file, index) => (_jsxs("div", { className: "flex items-center gap-1.5 rounded-md bg-attention/10 px-2 py-1 text-sm text-attention", title: t('agent.fileStagedTooltip'), children: [_jsx(FileTextIcon, { className: "size-3.5" }), _jsx("span", { className: "max-w-[120px] truncate", children: file.name }), _jsx("span", { className: "text-xs opacity-70", children: t('agent.staged') }), _jsx(Button, { variant: "unstyled", "aria-label": `Remove staged file ${file.name}`, onClick: () => removeStagedFile(index), className: "ms-1 rounded p-0.5 hover:bg-attention/20", children: _jsx(XIcon, { className: "size-3" }) })] }, `${file.name}-${file.size}-${file.lastModified}`))) })), _jsx(Textarea, { ref: inputRef, value: inputValue, onChange: (e) => setInputValue(e.target.value), onKeyDown: handleKeyDown, onPaste: handlePaste, placeholder: resolvedPlaceholder, disabled: isSending, rows: 2, className: cn('min-h-[72px] resize-none overflow-hidden border-0 bg-transparent px-0 py-0 text-sm leading-6 shadow-none focus-visible:ring-0', inputClassName), style: { minHeight: '72px', maxHeight: '200px' } }), _jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [canStageFiles && (_jsx(Button, { variant: "ghost", size: "icon", onClick: () => fileInputRef.current?.click(), disabled: isSending || stagedFiles.length >= maxFiles, "aria-label": t('agent.upload'), className: "rounded-full text-muted", title: t('agent.upload'), children: _jsx(UploadIcon, { className: "size-4" }) })), interactive && (_jsx(AgentApprovalModeSelector, { mode: toolApprovalMode, onChange: setToolApprovalMode, disabled: isSending }))] }), _jsx(Button, { onClick: startWorkflowWithMessage, disabled: !inputValue.trim() || isSending, variant: "ghost", size: "icon", className: cn('size-9 rounded-full border border-border/60 bg-foreground text-background shadow-sm', 'hover:bg-foreground/90 hover:text-background', 'disabled:bg-mixer-muted/25 disabled:text-muted disabled:opacity-100'), title: resolvedStartButtonText, "aria-label": resolvedStartButtonText, children: isSending ? _jsx(Spinner, { size: "sm" }) : _jsx(ArrowUpIcon, { className: "size-4" }) })] })] }) })] }) }));
437
621
  }
438
622
  // Inner component that handles the agent conversation - similar to ModernAgentOutput
439
623
  function ModernAgentConversationInner({ agentRunId, title, interactive = true, onClose, isModal = false, fullWidth = false, placeholder, resetWorkflow, onRestart, onClone, onShowDetails, allowWorkflowControl = true,
@@ -472,14 +656,14 @@ streamingMessageClassNames,
472
656
  // BatchProgressPanel className overrides
473
657
  batchProgressPanelClassNames,
474
658
  // AllMessagesMixed className overrides
475
- workingIndicatorClassName, messageListClassName, StoreLinkComponent, CollectionLinkComponent, prependFriendlyMessage, initialRequestData, initialRequestSchema, initialRequestTitle, initialRequestTemplate, payloadContent, conversationContent, conversationTab = false, pendingStartMessage, pendingStartTimestamp, enablePlayback, showPlaybackToggle = true, }) {
659
+ workingIndicatorClassName, messageListClassName, StoreLinkComponent, CollectionLinkComponent, prependFriendlyMessage, initialRequestData, initialRequestSchema, initialRequestTitle, initialRequestTemplate, payloadContent, conversationContent, conversationTab = false, pendingStartMessage, pendingStartTimestamp, initialToolApprovalMode, enablePlayback, showPlaybackToggle = true, }) {
476
660
  const { t } = useUITranslation();
477
661
  const { client } = useUserSession();
478
662
  const toast = useToast();
479
663
  // ────────────────────────────────────────────
480
664
  // Extracted hooks
481
665
  // ────────────────────────────────────────────
482
- const { messages, streamingMessages, isCompleted, debugChunkFlash, addOptimisticMessage, removeOptimisticMessages, reconnect: reconnectStream, agentRunStatus, workflowRunId, serverFileUpdates, } = useAgentStream(client, agentRunId);
666
+ const { messages, streamingMessages, isCompleted, initialHistoryStatus, debugChunkFlash, addOptimisticMessage, updateOptimisticMessageStatus, reconnect: reconnectStream, agentRunStatus, workflowRunId, serverFileUpdates, } = useAgentStream(client, agentRunId);
483
667
  const { plans, activePlanIndex, setActivePlanIndex, workstreamStatusMap, showInput, showSlidingPanel, setShowSlidingPanel, } = useAgentPlans(messages, interactive, isModal);
484
668
  const { openDocuments, activeDocumentId, isDocPanelOpen, docRefreshKey, closeDocPanel: handleCloseDocPanel, closeDocument: handleCloseDocument, selectDocument, openDocInPanel, updateDocumentTitle, } = useDocumentPanel(messages);
485
669
  const { processingFiles, hasProcessingFiles, handleFileUpload, removeProcessingFile } = useFileProcessing(client, agentRunId, serverFileUpdates, toast);
@@ -494,6 +678,7 @@ workingIndicatorClassName, messageListClassName, StoreLinkComponent, CollectionL
494
678
  const conversationRef = useRef(null);
495
679
  const conversationLayoutRef = useRef(null);
496
680
  const [isSending, setIsSending] = useState(false);
681
+ const [isCompactingContext, setIsCompactingContext] = useState(false);
497
682
  const [internalViewMode, setInternalViewMode] = useState('sliding');
498
683
  const viewMode = controlledViewMode ?? internalViewMode;
499
684
  const handleViewModeChange = useCallback((mode) => {
@@ -506,14 +691,23 @@ workingIndicatorClassName, messageListClassName, StoreLinkComponent, CollectionL
506
691
  }, [onViewModeChangeProp]);
507
692
  const [isStopping, setIsStopping] = useState(false);
508
693
  const [isDragOver, setIsDragOver] = useState(false);
694
+ const [activeWorkstream, setActiveWorkstream] = useState('all');
509
695
  const [playbackCursor, setPlaybackCursor] = useState('live');
510
696
  const [isPlaybackToggleEnabled, setIsPlaybackToggleEnabled] = useState(false);
511
697
  const [playbackScrollRequestId, setPlaybackScrollRequestId] = useState(0);
512
- const [activeWorkstreams, setActiveWorkstreams] = useState([]);
513
- const [completedWorkstreams, setCompletedWorkstreams] = useState([]);
698
+ const [queriedActiveWorkstreams, setQueriedActiveWorkstreams] = useState([]);
699
+ const [queriedCompletedWorkstreams, setQueriedCompletedWorkstreams] = useState([]);
700
+ const [isWorkstreamQueryUnavailable, setIsWorkstreamQueryUnavailable] = useState(false);
701
+ const initialResolvedToolApprovalMode = useMemo(() => initialToolApprovalMode === undefined && interactive
702
+ ? undefined
703
+ : normalizeAgentToolApprovalMode(initialToolApprovalMode, interactive), [initialToolApprovalMode, interactive]);
704
+ const [toolApprovalMode, setToolApprovalMode] = useState(initialResolvedToolApprovalMode);
514
705
  const workstreamFetchFailedRef = useRef(false);
515
706
  const dragCounterRef = useRef(0);
516
707
  const pendingPlaybackScrollRef = useRef(false);
708
+ useEffect(() => {
709
+ setToolApprovalMode(initialResolvedToolApprovalMode);
710
+ }, [initialResolvedToolApprovalMode]);
517
711
  // PERFORMANCE: Refs for values used inside useCallback to avoid re-creating the callback
518
712
  const isSendingRef = useRef(isSending);
519
713
  isSendingRef.current = isSending;
@@ -572,63 +766,125 @@ workingIndicatorClassName, messageListClassName, StoreLinkComponent, CollectionL
572
766
  workstreamStatus: currentWorkstreamStatus,
573
767
  };
574
768
  }, [plans, activePlanIndex, workstreamStatusMap]);
575
- const messageDerivedActiveWorkstreams = useMemo(() => deriveActiveWorkstreamsFromMessages(messages), [messages]);
769
+ const messageDerivedWorkstreams = useMemo(() => deriveWorkstreamsFromMessages(messages), [messages]);
576
770
  const panelWorkstreams = useMemo(() => {
577
- const running = activeWorkstreams.length > 0
578
- ? activeWorkstreams.map((ws) => ({
579
- workstream_id: ws.workstream_id,
580
- launch_id: ws.launch_id,
581
- interaction: ws.interaction,
582
- elapsed_ms: ws.elapsed_ms,
583
- deadline_ms: ws.deadline_ms,
584
- remaining_ms: Math.max(0, ws.deadline_ms - ws.elapsed_ms),
585
- status: ws.status,
586
- phase: ws.latest_progress?.phase,
587
- child_workflow_id: ws.child_workflow_id,
588
- child_workflow_run_id: ws.child_workflow_run_id,
589
- }))
590
- : messageDerivedActiveWorkstreams;
591
- const runningWorkstreamIds = new Set(running.map((ws) => ws.workstream_id));
592
- const completed = completedWorkstreams
593
- .filter((ws) => !runningWorkstreamIds.has(ws.workstream_id))
594
- .map((ws) => ({
595
- workstream_id: ws.workstream_id,
596
- launch_id: ws.launch_id,
597
- elapsed_ms: 0,
598
- deadline_ms: 0,
599
- remaining_ms: 0,
600
- status: ws.status,
601
- }));
602
- return [...running, ...completed];
603
- }, [activeWorkstreams, completedWorkstreams, messageDerivedActiveWorkstreams]);
604
- const activeTaskCount = useMemo(() => panelWorkstreams.filter((ws) => ws.status === 'running').length, [panelWorkstreams]);
771
+ const merged = [...messageDerivedWorkstreams];
772
+ for (const ws of queriedCompletedWorkstreams) {
773
+ mergeWorkstreamInfo(merged, completedWorkstreamEntryToInfo(ws));
774
+ }
775
+ for (const ws of queriedActiveWorkstreams) {
776
+ mergeWorkstreamInfo(merged, activeWorkstreamEntryToInfo(ws));
777
+ }
778
+ return merged
779
+ .map((workstream, index) => ({ workstream, index }))
780
+ .sort((a, b) => {
781
+ const activeDelta = Number(!isActiveWorkstreamStatus(a.workstream.status)) -
782
+ Number(!isActiveWorkstreamStatus(b.workstream.status));
783
+ return activeDelta || a.index - b.index;
784
+ })
785
+ .map(({ workstream }) => workstream);
786
+ }, [messageDerivedWorkstreams, queriedActiveWorkstreams, queriedCompletedWorkstreams]);
787
+ const composerActiveWorkstreams = useMemo(() => panelWorkstreams.filter((ws) => isActiveWorkstreamStatus(ws.status)), [panelWorkstreams]);
788
+ const activeTaskCount = useMemo(() => composerActiveWorkstreams.filter((ws) => ws.status === 'running').length, [composerActiveWorkstreams]);
789
+ const activeWorkstreamDisplayName = useMemo(() => {
790
+ if (activeWorkstream === 'all')
791
+ return undefined;
792
+ const workstream = panelWorkstreams.find((ws) => ws.workstream_id === activeWorkstream || ws.launch_id === activeWorkstream);
793
+ if (!workstream)
794
+ return getWorkstreamDisplayName(activeWorkstream);
795
+ return getWorkstreamDisplayName(workstream.workstream_id, workstream.interaction);
796
+ }, [activeWorkstream, panelWorkstreams]);
797
+ const composerPlaceholder = useMemo(() => {
798
+ if (placeholder)
799
+ return placeholder;
800
+ if (activeWorkstreamDisplayName) {
801
+ return t('agent.messageMainAgentWhileViewingWorkstream', { workstream: activeWorkstreamDisplayName });
802
+ }
803
+ return undefined;
804
+ }, [activeWorkstreamDisplayName, placeholder, t]);
605
805
  const canShowPlaybackToggle = showPlaybackToggle && enablePlayback === undefined && isAgentChatPlaybackAvailable();
606
806
  const isPlaybackEnabled = enablePlayback ?? (isAgentChatPlaybackEnabled() || isPlaybackToggleEnabled);
607
- const playbackState = useMemo(() => createPlaybackState(messages, playbackCursor, isPlaybackEnabled), [isPlaybackEnabled, messages, playbackCursor]);
807
+ const playbackSourceMessages = useMemo(() => {
808
+ const visibleMessages = hiddenMessageTypes?.length
809
+ ? messages.filter((message) => !hiddenMessageTypes.includes(message.type))
810
+ : messages;
811
+ return filterMessagesForActiveWorkstream(visibleMessages, activeWorkstream);
812
+ }, [activeWorkstream, hiddenMessageTypes, messages]);
813
+ const playbackState = useMemo(() => createPlaybackState(playbackSourceMessages, playbackCursor, isPlaybackEnabled), [isPlaybackEnabled, playbackCursor, playbackSourceMessages]);
608
814
  const clampedPlaybackCursor = playbackState.cursor;
609
815
  const isPlaybackLive = playbackState.isLive;
816
+ const isPlaybackAtLatest = isPlaybackEnabled && !isPlaybackLive && playbackState.cursorIndex === playbackSourceMessages.length - 1;
610
817
  const displayedMessages = playbackState.displayedMessages;
611
818
  const displayedStreamingMessages = isPlaybackLive ? streamingMessages : EMPTY_STREAMING_MESSAGES;
819
+ const playbackDerivedWorkstreams = useMemo(() => deriveWorkstreamsFromMessages(displayedMessages), [displayedMessages]);
820
+ const playbackActiveWorkstreams = useMemo(() => playbackDerivedWorkstreams.filter((ws) => isActiveWorkstreamStatus(ws.status)), [playbackDerivedWorkstreams]);
612
821
  const effectiveIsCompleted = useMemo(() => isCompleted || !isInProgress(messages), [isCompleted, messages]);
613
- const displayedIsCompleted = isPlaybackLive ? effectiveIsCompleted : false;
822
+ const displayedIsCompleted = isPlaybackLive || isPlaybackAtLatest ? effectiveIsCompleted : false;
614
823
  const pendingRequestInputMessage = useMemo(() => getPendingRequestInputMessage(displayedMessages), [displayedMessages]);
615
824
  const shouldShowRequestInputOverlay = Boolean(pendingRequestInputMessage) && !isFailed;
616
825
  const isViewingPlaybackHistory = isPlaybackEnabled && !isPlaybackLive;
617
- const shouldShowLiveRequestInputOverlay = shouldShowRequestInputOverlay && !isViewingPlaybackHistory;
618
826
  const shouldRenderLiveMessageInputArea = shouldRenderMessageInputArea && !isViewingPlaybackHistory;
827
+ const contextWindowUsage = useMemo(() => toContextWindowUsage(messages), [messages]);
828
+ // The run is still "alive" while it waits for user input (idle on ask_user), so keep the
829
+ // context-usage indicator visible then — it's only truly hidden once the run terminates.
830
+ const canCompactContext = allowWorkflowControl && !isWorkflowTerminal && isPlaybackLive && Boolean(contextWindowUsage);
831
+ useEffect(() => {
832
+ debugAgentChat('conversation render state', {
833
+ agentRunId,
834
+ messageCount: messages.length,
835
+ playbackMessageCount: playbackSourceMessages.length,
836
+ displayedMessageCount: displayedMessages.length,
837
+ streamingCount: streamingMessages.size,
838
+ displayedStreamingCount: displayedStreamingMessages.size,
839
+ initialHistoryStatus,
840
+ isCompleted,
841
+ effectiveIsCompleted,
842
+ displayedIsCompleted,
843
+ agentRunStatus,
844
+ effectiveWorkflowStatus,
845
+ isWorkflowTerminal,
846
+ playbackCursor: clampedPlaybackCursor,
847
+ isPlaybackEnabled,
848
+ isPlaybackLive,
849
+ isPlaybackAtLatest,
850
+ activeWorkstream,
851
+ showInitialRequest: initialHistoryStatus === 'empty' && messages.length === 0,
852
+ pendingStartVisible: messages.length === 0 && !effectiveIsCompleted && Boolean(pendingStartMessage),
853
+ });
854
+ }, [
855
+ activeWorkstream,
856
+ agentRunId,
857
+ agentRunStatus,
858
+ clampedPlaybackCursor,
859
+ displayedIsCompleted,
860
+ displayedMessages.length,
861
+ displayedStreamingMessages.size,
862
+ effectiveIsCompleted,
863
+ effectiveWorkflowStatus,
864
+ initialHistoryStatus,
865
+ isCompleted,
866
+ isPlaybackAtLatest,
867
+ isPlaybackEnabled,
868
+ isPlaybackLive,
869
+ isWorkflowTerminal,
870
+ messages.length,
871
+ pendingStartMessage,
872
+ playbackSourceMessages.length,
873
+ streamingMessages.size,
874
+ ]);
619
875
  const handleTogglePlayback = useCallback(() => {
620
876
  setIsPlaybackToggleEnabled((prev) => !prev);
621
877
  }, []);
622
878
  const handleChangePlaybackCursor = useCallback((nextCursor) => {
623
- const currentIndex = getPlaybackCursorIndex(clampedPlaybackCursor, messages.length);
624
- const nextIndex = getPlaybackCursorIndex(nextCursor, messages.length);
879
+ const currentIndex = getPlaybackCursorIndex(clampedPlaybackCursor, playbackSourceMessages.length);
880
+ const nextIndex = getPlaybackCursorIndex(nextCursor, playbackSourceMessages.length);
625
881
  const returningToLive = nextCursor === 'live' && clampedPlaybackCursor !== 'live';
626
882
  if (isPlaybackEnabled && (nextIndex > currentIndex || returningToLive)) {
627
883
  pendingPlaybackScrollRef.current = true;
628
884
  setPlaybackScrollRequestId((requestId) => requestId + 1);
629
885
  }
630
886
  setPlaybackCursor(nextCursor);
631
- }, [clampedPlaybackCursor, isPlaybackEnabled, messages.length]);
887
+ }, [clampedPlaybackCursor, isPlaybackEnabled, playbackSourceMessages.length]);
632
888
  useEffect(() => {
633
889
  if (!isPlaybackEnabled) {
634
890
  if (playbackCursor !== 'live')
@@ -742,39 +998,76 @@ workingIndicatorClassName, messageListClassName, StoreLinkComponent, CollectionL
742
998
  useEffect(() => {
743
999
  onWorkstreamStatusChange?.(workstreamStatusMap);
744
1000
  }, [workstreamStatusMap, onWorkstreamStatusChange]);
745
- // Poll active workstreams from backend query for right-panel visibility and details.
746
1001
  useEffect(() => {
747
- const shouldPoll = !effectiveIsCompleted || activeWorkstreams.length > 0;
1002
+ void agentRunId;
1003
+ workstreamFetchFailedRef.current = false;
1004
+ setIsWorkstreamQueryUnavailable(false);
1005
+ setQueriedActiveWorkstreams([]);
1006
+ setQueriedCompletedWorkstreams([]);
1007
+ }, [agentRunId]);
1008
+ // Poll the backend query only as live enrichment. Persisted messages remain the
1009
+ // source of truth for the right-panel history once a workflow can no longer be queried.
1010
+ useEffect(() => {
1011
+ const shouldPoll = initialHistoryStatus !== 'loading' &&
1012
+ !effectiveIsCompleted &&
1013
+ !isWorkflowTerminal &&
1014
+ !isWorkstreamQueryUnavailable;
1015
+ debugAgentChat('active workstreams poll state', {
1016
+ agentRunId,
1017
+ shouldPoll,
1018
+ initialHistoryStatus,
1019
+ effectiveIsCompleted,
1020
+ isWorkflowTerminal,
1021
+ isWorkstreamQueryUnavailable,
1022
+ });
748
1023
  if (!shouldPoll) {
749
- setActiveWorkstreams((prev) => (prev.length === 0 ? prev : []));
1024
+ setQueriedActiveWorkstreams((prev) => (prev.length === 0 ? prev : []));
750
1025
  return;
751
1026
  }
752
1027
  let isCancelled = false;
1028
+ let isFetchInFlight = false;
753
1029
  const fetchActiveWorkstreams = async () => {
1030
+ if (isFetchInFlight) {
1031
+ debugAgentChat('active workstreams fetch skipped while previous request is pending', { agentRunId });
1032
+ return;
1033
+ }
1034
+ isFetchInFlight = true;
754
1035
  try {
1036
+ debugAgentChat('active workstreams fetch start', { agentRunId });
755
1037
  const result = await client.agents.getActiveWorkstreams(agentRunId);
756
1038
  if (isCancelled)
757
1039
  return;
758
- setActiveWorkstreams(result.running ?? []);
759
- const completed = result.completed ?? [];
760
- setCompletedWorkstreams(completed.map((c) => ({
761
- launch_id: c.launch_id,
762
- workstream_id: c.workstream_id,
763
- status: c.status === 'canceled' || c.status === 'failed' || c.status === 'timeout'
764
- ? c.status
765
- : 'completed',
766
- })));
1040
+ debugAgentChat('active workstreams fetch success', {
1041
+ agentRunId,
1042
+ runningCount: result.running?.length ?? 0,
1043
+ completedCount: result.completed?.length ?? 0,
1044
+ unavailable: result.unavailable === true,
1045
+ });
1046
+ setQueriedActiveWorkstreams(result.running ?? []);
1047
+ setQueriedCompletedWorkstreams(result.completed ?? []);
1048
+ if (result.unavailable) {
1049
+ setIsWorkstreamQueryUnavailable(true);
1050
+ return;
1051
+ }
767
1052
  workstreamFetchFailedRef.current = false;
768
1053
  }
769
1054
  catch (error) {
770
1055
  if (isCancelled)
771
1056
  return;
772
- setActiveWorkstreams([]);
1057
+ setQueriedActiveWorkstreams((prev) => (prev.length === 0 ? prev : []));
1058
+ setIsWorkstreamQueryUnavailable(true);
1059
+ debugAgentChat('active workstreams fetch failed', {
1060
+ agentRunId,
1061
+ error: error instanceof Error ? error.message : String(error),
1062
+ });
773
1063
  if (!workstreamFetchFailedRef.current) {
774
1064
  console.warn('Failed to fetch active workstreams:', error);
775
1065
  workstreamFetchFailedRef.current = true;
776
1066
  }
777
1067
  }
1068
+ finally {
1069
+ isFetchInFlight = false;
1070
+ }
778
1071
  };
779
1072
  void fetchActiveWorkstreams();
780
1073
  const pollHandle = window.setInterval(fetchActiveWorkstreams, 10000);
@@ -782,7 +1075,14 @@ workingIndicatorClassName, messageListClassName, StoreLinkComponent, CollectionL
782
1075
  isCancelled = true;
783
1076
  window.clearInterval(pollHandle);
784
1077
  };
785
- }, [client.agents, agentRunId, effectiveIsCompleted, activeWorkstreams.length]);
1078
+ }, [
1079
+ client.agents,
1080
+ agentRunId,
1081
+ effectiveIsCompleted,
1082
+ initialHistoryStatus,
1083
+ isWorkflowTerminal,
1084
+ isWorkstreamQueryUnavailable,
1085
+ ]);
786
1086
  // Notify parent when input availability is determined
787
1087
  useEffect(() => {
788
1088
  if (messages.length === 0)
@@ -807,7 +1107,7 @@ workingIndicatorClassName, messageListClassName, StoreLinkComponent, CollectionL
807
1107
  // Handlers
808
1108
  // ────────────────────────────────────────────
809
1109
  // Send a message to the agent
810
- const handleSendMessage = useCallback((message) => {
1110
+ const handleSendMessage = useCallback((message, inputMetadata) => {
811
1111
  const trimmed = message.trim();
812
1112
  if (!trimmed || isSendingRef.current)
813
1113
  return;
@@ -841,18 +1141,25 @@ workingIndicatorClassName, messageListClassName, StoreLinkComponent, CollectionL
841
1141
  type: AgentMessageType.QUESTION,
842
1142
  message: messageContent,
843
1143
  workstream_id: 'main',
844
- details: { _optimistic: true, _messageId: messageId },
1144
+ details: { _optimistic: true, _messageId: messageId, _deliveryStatus: 'sending' },
845
1145
  };
846
1146
  addOptimisticMessage(optimisticMessage);
847
1147
  const metadata = {
848
1148
  ...(attachedDocs.length > 0 ? { attached_docs: attachedDocs.map((d) => d.id) } : {}),
849
1149
  ...contextMetadata,
1150
+ ...inputMetadata,
1151
+ id: messageId,
850
1152
  _messageId: messageId,
851
1153
  };
852
1154
  const sendUserInput = () => client.agents.sendSignal(agentRunId, 'UserInput', {
853
1155
  message: messageContent,
1156
+ client_message_id: messageId,
854
1157
  metadata,
855
1158
  });
1159
+ const markReceived = () => {
1160
+ updateOptimisticMessageStatus(messageId, 'received');
1161
+ onAttachmentsSent?.();
1162
+ };
856
1163
  // When the workflow has already completed, restart it first so it resumes
857
1164
  // from the existing conversation history, then deliver the message. Temporal
858
1165
  // buffers the signal until the new run is ready to receive it. We reconnect
@@ -861,16 +1168,12 @@ workingIndicatorClassName, messageListClassName, StoreLinkComponent, CollectionL
861
1168
  const deliver = isWorkflowTerminalRef.current
862
1169
  ? client.agents.restart(agentRunId).then(() => {
863
1170
  reconnectStream();
864
- return sendUserInput().then(() => {
865
- onAttachmentsSent?.();
866
- });
1171
+ return sendUserInput().then(markReceived);
867
1172
  })
868
- : sendUserInput().then(() => {
869
- onAttachmentsSent?.();
870
- });
1173
+ : sendUserInput().then(markReceived);
871
1174
  deliver
872
1175
  .catch((err) => {
873
- removeOptimisticMessages((m) => m.details?._messageId === messageId);
1176
+ updateOptimisticMessageStatus(messageId, 'failed');
874
1177
  toast({
875
1178
  status: 'error',
876
1179
  title: t('agent.failedToSend'),
@@ -890,9 +1193,77 @@ workingIndicatorClassName, messageListClassName, StoreLinkComponent, CollectionL
890
1193
  onAttachmentsSent,
891
1194
  reconnectStream,
892
1195
  addOptimisticMessage,
893
- removeOptimisticMessages,
1196
+ updateOptimisticMessageStatus,
894
1197
  t,
895
1198
  ]);
1199
+ // After the user connects an MCP server requested via request_mcp_connection, flag the
1200
+ // conversation for tool re-discovery and resume it with a confirmation message so the agent
1201
+ // continues automatically with the newly-available tools.
1202
+ const handleMcpConnected = useCallback(async (cfg) => {
1203
+ // Await the dirty-flag signal BEFORE sending the follow-up message so Temporal records
1204
+ // McpConfigChanged ahead of the UserInput. Otherwise the resume turn could run before
1205
+ // the flag is set and use the stale tool catalog. An omitted disabled list preserves
1206
+ // the user's current deactivation set.
1207
+ try {
1208
+ await client.agents.sendSignal(agentRunId, 'McpConfigChanged', {});
1209
+ }
1210
+ catch (err) {
1211
+ console.error('Failed to signal MCP config change', err);
1212
+ }
1213
+ handleSendMessage(t('agent.mcpConnectedMessage', { name: cfg.name }));
1214
+ }, [client, agentRunId, handleSendMessage, t]);
1215
+ // Per-conversation MCP deactivation set, seeded from the run and updated live via the
1216
+ // MCP action menu in the composer toolbar. Changes are pushed to the running workflow
1217
+ // (which re-discovers tools at the next turn).
1218
+ const [mcpDisabled, setMcpDisabled] = useState(undefined);
1219
+ useEffect(() => {
1220
+ let cancelled = false;
1221
+ client.agents
1222
+ .retrieve(agentRunId)
1223
+ .then((run) => {
1224
+ if (!cancelled) {
1225
+ setMcpDisabled(run.disabled_mcp_collections);
1226
+ if (run.tool_approval_mode !== undefined || run.interactive !== undefined) {
1227
+ setToolApprovalMode(normalizeAgentToolApprovalMode(run.tool_approval_mode, run.interactive));
1228
+ }
1229
+ }
1230
+ })
1231
+ .catch(() => {
1232
+ /* best-effort: toggles default to all-active */
1233
+ });
1234
+ return () => {
1235
+ cancelled = true;
1236
+ };
1237
+ }, [client, agentRunId]);
1238
+ const handleMcpDisabledChange = useCallback((disabled) => {
1239
+ const next = disabled.length > 0 ? disabled : undefined;
1240
+ setMcpDisabled(next);
1241
+ client.agents
1242
+ .sendSignal(agentRunId, 'McpConfigChanged', { disabled_mcp_collections: disabled })
1243
+ .catch((err) => console.error('Failed to signal MCP config change', err));
1244
+ }, [client, agentRunId]);
1245
+ const handleMcpConnectionChange = useCallback(() => {
1246
+ // A connect/disconnect doesn't change the activation set — omit disabled_mcp_collections so
1247
+ // the workflow preserves the current denylist (rather than overwriting it with possibly
1248
+ // stale UI state) and just re-discovers tools.
1249
+ client.agents
1250
+ .sendSignal(agentRunId, 'McpConfigChanged', {})
1251
+ .catch((err) => console.error('Failed to signal MCP config change', err));
1252
+ }, [client, agentRunId]);
1253
+ const handleToolApprovalModeChange = useCallback((mode) => {
1254
+ const nextMode = normalizeAgentToolApprovalMode(mode, interactive);
1255
+ setToolApprovalMode(nextMode);
1256
+ client.agents
1257
+ .sendSignal(agentRunId, 'ToolApprovalModeChanged', { mode: nextMode })
1258
+ .catch((err) => {
1259
+ toast({
1260
+ status: 'error',
1261
+ title: t('agent.approvalMode.changeFailed'),
1262
+ description: err instanceof Error ? err.message : t('agent.unknownError'),
1263
+ duration: 3000,
1264
+ });
1265
+ });
1266
+ }, [agentRunId, client, interactive, t, toast]);
896
1267
  // Drag and drop handlers for full-panel file upload
897
1268
  const handleDragEnter = useCallback((e) => {
898
1269
  if (!canUploadFiles)
@@ -936,30 +1307,68 @@ workingIndicatorClassName, messageListClassName, StoreLinkComponent, CollectionL
936
1307
  const handleStopWorkflow = useCallback(async () => {
937
1308
  if (isStopping)
938
1309
  return;
1310
+ const messageId = `stop-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
1311
+ const optimisticMessage = {
1312
+ timestamp: Date.now(),
1313
+ workflow_run_id: agentRunId,
1314
+ type: AgentMessageType.IDLE,
1315
+ message: 'Stopped. Waiting for your command...',
1316
+ workstream_id: 'main',
1317
+ details: {
1318
+ _optimistic: true,
1319
+ _messageId: messageId,
1320
+ _deliveryStatus: 'sending',
1321
+ display_role: 'user_stopped',
1322
+ status_reason: 'user_stopped',
1323
+ },
1324
+ };
1325
+ addOptimisticMessage(optimisticMessage);
939
1326
  setIsStopping(true);
940
1327
  try {
941
1328
  await client.agents.sendSignal(agentRunId, 'Stop', {
942
1329
  message: 'User requested stop',
1330
+ client_message_id: messageId,
1331
+ metadata: {
1332
+ id: messageId,
1333
+ _messageId: messageId,
1334
+ },
943
1335
  });
1336
+ updateOptimisticMessageStatus(messageId, 'received');
1337
+ }
1338
+ catch (err) {
944
1339
  toast({
945
- status: 'info',
946
- title: t('agent.agentInterrupted'),
947
- description: t('agent.typeNewInstructions'),
1340
+ status: 'error',
1341
+ title: t('agent.failedToInterrupt'),
1342
+ description: err instanceof Error ? err.message : t('agent.unknownError'),
948
1343
  duration: 3000,
949
1344
  });
1345
+ updateOptimisticMessageStatus(messageId, 'failed');
1346
+ }
1347
+ finally {
1348
+ setIsStopping(false);
1349
+ }
1350
+ }, [isStopping, agentRunId, addOptimisticMessage, client.agents, toast, t, updateOptimisticMessageStatus]);
1351
+ const handleCompactContext = useCallback(async () => {
1352
+ if (isCompactingContext || effectiveIsCompleted || !isPlaybackLive)
1353
+ return;
1354
+ setIsCompactingContext(true);
1355
+ try {
1356
+ await client.agents.sendSignal(agentRunId, 'TriggerCheckpoint', {
1357
+ reason: 'manual user request',
1358
+ });
950
1359
  }
951
1360
  catch (err) {
952
1361
  toast({
953
1362
  status: 'error',
954
- title: t('agent.failedToInterrupt'),
1363
+ title: t('agent.failedToCompactContext'),
955
1364
  description: err instanceof Error ? err.message : t('agent.unknownError'),
956
1365
  duration: 3000,
957
1366
  });
958
1367
  }
959
1368
  finally {
960
- setIsStopping(false);
1369
+ setIsCompactingContext(false);
961
1370
  }
962
- }, [isStopping, client, agentRunId, toast, t]);
1371
+ }, [agentRunId, client.agents, effectiveIsCompleted, isCompactingContext, isPlaybackLive, t, toast]);
963
1372
  // Expose stop handler to external callers via ref
964
1373
  useEffect(() => {
965
1374
  if (stopRef)
@@ -1087,13 +1496,13 @@ workingIndicatorClassName, messageListClassName, StoreLinkComponent, CollectionL
1087
1496
  ? 'w-full flex-1 min-h-[50vh]'
1088
1497
  : fullWidth
1089
1498
  ? 'flex-1 w-full'
1090
- : `flex-1 mx-auto ${!isModal ? 'max-w-4xl' : ''}`), children: [!hideHeader && headerVariant === 'compact' && (_jsx("div", { className: "flex flex-shrink-0 justify-end border-b border-border/60 px-2 py-1 lg:hidden", children: renderConversationHeader('compact') })), !hideHeader && headerVariant !== 'compact' && (_jsx("div", { className: "flex-shrink-0", children: renderConversationHeader(headerVariant) })), isPlaybackEnabled && (_jsx("div", { className: "flex flex-shrink-0 justify-end px-2 py-1.5", children: _jsx(AgentChatPlaybackControls, { cursor: clampedPlaybackCursor, messages: messages, onChangeCursor: handleChangePlaybackCursor }) })), messages.length === 0 && !effectiveIsCompleted && pendingStartMessage && pendingStartTimestamp ? (_jsx(PendingStartConversation, { message: pendingStartMessage, startedAt: pendingStartTimestamp })) : (_jsx(AllMessagesMixed, { messages: displayedMessages, bottomRef: bottomRef, isCompleted: displayedIsCompleted, plan: getActivePlan.plan, workstreamStatus: getActivePlan.workstreamStatus, showPlanPanel: showRightPanelProp && showSlidingPanel, onTogglePlanPanel: handleTogglePlanPanel, plans: plans, activePlanIndex: activePlanIndex, onChangePlan: handleChangePlan, taskLabels: taskLabels, streamingMessages: displayedStreamingMessages, onSendMessage: isPlaybackLive ? handleSendMessage : undefined, messageItemClassNames: messageItemClassNames, messageStyleOverrides: messageStyleOverrides, toolCallGroupClassNames: toolCallGroupClassNames, hideToolCallsInViewMode: hideToolCallsInViewMode, streamingMessageClassNames: streamingMessageClassNames, batchProgressPanelClassNames: batchProgressPanelClassNames, artifactRunId: agentRunId, viewMode: viewMode, hideWorkstreamTabs: hideWorkstreamTabs, workingIndicatorClassName: workingIndicatorClassName, messageListClassName: messageListClassName, StoreLinkComponent: effectiveStoreLinkComponent, CollectionLinkComponent: CollectionLinkComponent, prependFriendlyMessage: prependFriendlyMessage, initialRequestData: initialRequestData, initialRequestSchema: initialRequestSchema, initialRequestTitle: initialRequestTitle, initialRequestTemplate: initialRequestTemplate, hiddenMessageTypes: hiddenMessageTypes, disableAutoScroll: !isPlaybackLive, renderRequestInputControls: isPlaybackLive && !shouldShowLiveRequestInputOverlay })), shouldShowLiveRequestInputOverlay ? (_jsx(AgentRequestInputOverlay, { message: pendingRequestInputMessage, onSendMessage: handleSendMessage, disabled: isUploading || !isPlaybackLive, isLoading: isSending || isUploading })) : (shouldRenderLiveMessageInputArea && (_jsx("div", { className: "flex-shrink-0 pb-safe-area", children: isFailed ? (
1499
+ : `flex-1 mx-auto ${!isModal ? 'max-w-4xl' : ''}`), children: [!hideHeader && headerVariant === 'compact' && (_jsx("div", { className: "flex flex-shrink-0 justify-end border-b border-border/60 px-2 py-1 lg:hidden", children: renderConversationHeader('compact') })), !hideHeader && headerVariant !== 'compact' && (_jsx("div", { className: "flex-shrink-0", children: renderConversationHeader(headerVariant) })), isPlaybackEnabled && (_jsx("div", { className: "flex flex-shrink-0 justify-end px-2 py-1.5", children: _jsx(AgentChatPlaybackControls, { cursor: clampedPlaybackCursor, messages: playbackSourceMessages, onChangeCursor: handleChangePlaybackCursor }) })), messages.length === 0 && !effectiveIsCompleted && pendingStartMessage && pendingStartTimestamp ? (_jsx(PendingStartConversation, { message: pendingStartMessage, startedAt: pendingStartTimestamp })) : (_jsx(AllMessagesMixed, { messages: displayedMessages, bottomRef: bottomRef, isCompleted: displayedIsCompleted, plan: getActivePlan.plan, workstreamStatus: getActivePlan.workstreamStatus, showPlanPanel: showRightPanelProp && showSlidingPanel, onTogglePlanPanel: handleTogglePlanPanel, plans: plans, activePlanIndex: activePlanIndex, onChangePlan: handleChangePlan, taskLabels: taskLabels, streamingMessages: displayedStreamingMessages, onSendMessage: isPlaybackLive ? handleSendMessage : undefined, messageItemClassNames: messageItemClassNames, messageStyleOverrides: messageStyleOverrides, toolCallGroupClassNames: toolCallGroupClassNames, hideToolCallsInViewMode: hideToolCallsInViewMode, streamingMessageClassNames: streamingMessageClassNames, batchProgressPanelClassNames: batchProgressPanelClassNames, artifactRunId: agentRunId, viewMode: viewMode, hideWorkstreamTabs: hideWorkstreamTabs, workingIndicatorClassName: workingIndicatorClassName, messageListClassName: messageListClassName, StoreLinkComponent: effectiveStoreLinkComponent, CollectionLinkComponent: CollectionLinkComponent, prependFriendlyMessage: prependFriendlyMessage, initialRequestData: initialRequestData, initialRequestSchema: initialRequestSchema, initialRequestTitle: initialRequestTitle, initialRequestTemplate: initialRequestTemplate, showInitialRequest: initialHistoryStatus === 'empty' && messages.length === 0, hiddenMessageTypes: hiddenMessageTypes, disableAutoScroll: !isPlaybackLive, renderRequestInputControls: !shouldShowRequestInputOverlay, activeWorkstream: activeWorkstream, onActiveWorkstreamChange: setActiveWorkstream })), shouldShowRequestInputOverlay ? (_jsx(AgentRequestInputOverlay, { message: pendingRequestInputMessage, onSendMessage: isPlaybackLive ? handleSendMessage : undefined, onMcpConnected: isPlaybackLive ? handleMcpConnected : undefined, disabled: isUploading || !isPlaybackLive, isLoading: isSending || isUploading })) : isViewingPlaybackHistory && playbackActiveWorkstreams.length > 0 ? (_jsx("div", { className: "flex-shrink-0 pb-safe-area", children: _jsx(ActiveWorkstreamsSummary, { activeWorkstreams: playbackActiveWorkstreams }) })) : (shouldRenderLiveMessageInputArea && (_jsx("div", { className: "flex-shrink-0 pb-safe-area", children: isFailed ? (
1091
1500
  // FAILED takes priority over every other branch so the composer can
1092
1501
  // never render for a failed run. Use the caller's action when provided,
1093
1502
  // otherwise fall back to the default failed message box.
1094
1503
  (failedAction ?? (_jsx(MessageBox, { status: "error", icon: null, className: "m-2", children: "This Workflow is FAILED" })))) : effectiveWorkflowStatus &&
1095
1504
  effectiveWorkflowStatus !== 'RUNNING' &&
1096
- !canContinueConversation ? (viewMode === 'sliding' && effectiveWorkflowStatus === 'COMPLETED' ? (_jsx("div", { className: "mx-auto w-full max-w-3xl px-4 py-3 text-sm text-muted", children: _jsxs("div", { className: "flex items-center gap-2 border-t border-success/25 pt-3 text-success", children: [_jsx(CheckCircle, { className: "size-4" }), _jsx("span", { className: "font-medium", children: "Workflow completed" })] }) })) : (_jsxs(MessageBox, { status: effectiveWorkflowStatus === 'COMPLETED' ? 'success' : 'done', icon: null, className: "m-2", children: ["This Workflow is ", effectiveWorkflowStatus] }))) : ((showInput || canContinueConversation) && (_jsx(MessageInput, { onSend: handleSendMessage, onStop: allowWorkflowControl ? handleStopWorkflow : undefined, disabled: isUploading || !isPlaybackLive, isSending: isSending || isUploading, isStopping: isStopping, isStreaming: !effectiveIsCompleted, isCompleted: effectiveIsCompleted, activeTaskCount: activeTaskCount, activeWorkstreams: panelWorkstreams, placeholder: placeholder ?? 'Type your message...', onFilesSelected: canUploadFiles ? handleFileUpload : undefined, uploadedFiles: uploadedFiles, onRemoveFile: onRemoveFile, onRemoveProcessingFile: handleRemoveProcessingFile, acceptedFileTypes: acceptedFileTypes, maxFiles: maxFiles, processingFiles: processingFiles, artifactRunId: agentRunId, hasProcessingFiles: hasProcessingFiles, renderDocumentSearch: renderDocumentSearch, selectedDocuments: selectedDocuments, onRemoveDocument: onRemoveDocument, hideObjectLinking: hideObjectLinking, hideFileUpload: !canUploadFiles, disableDropZone: canUploadFiles, className: inputContainerClassName, inputClassName: inputClassName }))) })))] }));
1505
+ !canContinueConversation ? (viewMode === 'sliding' && effectiveWorkflowStatus === 'COMPLETED' ? (_jsx("div", { className: "mx-auto w-full max-w-3xl px-4 py-3 text-sm text-muted", children: _jsxs("div", { className: "flex items-center gap-2 border-t border-success/25 pt-3 text-success", children: [_jsx(CheckCircle, { className: "size-4" }), _jsx("span", { className: "font-medium", children: "Workflow completed" })] }) })) : (_jsxs(MessageBox, { status: effectiveWorkflowStatus === 'COMPLETED' ? 'success' : 'done', icon: null, className: "m-2", children: ["This Workflow is ", effectiveWorkflowStatus] }))) : ((showInput || canContinueConversation) && (_jsx(MessageInput, { onSend: handleSendMessage, onStop: allowWorkflowControl ? handleStopWorkflow : undefined, approvalModeSlot: interactive && toolApprovalMode ? (_jsx(AgentApprovalModeSelector, { mode: toolApprovalMode, onChange: handleToolApprovalModeChange, disabled: !isPlaybackLive || isWorkflowTerminal || !allowWorkflowControl })) : undefined, mcpSlot: _jsx(McpConnectionsActionMenu, { disabledCollections: mcpDisabled, onChange: handleMcpDisabledChange, onConnectionChange: handleMcpConnectionChange }), disabled: isUploading || !isPlaybackLive, isSending: isSending || isUploading, isStopping: isStopping, isStreaming: !effectiveIsCompleted, isCompleted: effectiveIsCompleted, contextWindowUsage: canCompactContext ? contextWindowUsage : undefined, onCompactContext: canCompactContext ? handleCompactContext : undefined, isCompactingContext: isCompactingContext, activeTaskCount: activeTaskCount, activeWorkstreams: composerActiveWorkstreams, placeholder: composerPlaceholder, onFilesSelected: canUploadFiles ? handleFileUpload : undefined, uploadedFiles: uploadedFiles, onRemoveFile: onRemoveFile, onRemoveProcessingFile: handleRemoveProcessingFile, acceptedFileTypes: acceptedFileTypes, maxFiles: maxFiles, processingFiles: processingFiles, artifactRunId: agentRunId, hasProcessingFiles: hasProcessingFiles, renderDocumentSearch: renderDocumentSearch, selectedDocuments: selectedDocuments, onRemoveDocument: onRemoveDocument, hideObjectLinking: hideObjectLinking, hideFileUpload: !canUploadFiles, disableDropZone: canUploadFiles, className: inputContainerClassName, inputClassName: inputClassName }))) })))] }));
1097
1506
  // Main content - wrapped with FusionFragmentProvider when fusionData is provided
1098
1507
  const mainContent = (_jsx(ArtifactUrlCacheProvider, { children: _jsx(ImageLightboxProvider, { children: _jsxs("div", { ref: conversationLayoutRef, className: cn('flex flex-col lg:flex-row gap-2 w-full h-full relative overflow-hidden', canUploadFiles && isDragOver && 'ring-2 ring-blue-400 ring-inset', className), onDragEnter: canUploadFiles ? handleDragEnter : undefined, onDragOver: canUploadFiles ? handleDragOver : undefined, onDragLeave: canUploadFiles ? handleDragLeave : undefined, onDrop: canUploadFiles ? handleDrop : undefined, children: [canUploadFiles && isDragOver && (_jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-blue-100/80 dark:bg-blue-900/40 z-50 pointer-events-none rounded-lg", children: _jsxs("div", { className: "text-blue-600 dark:text-blue-400 font-medium flex items-center gap-2 text-lg", children: [_jsx(UploadIcon, { className: "size-6" }), "Drop files to upload"] }) })), !conversationTab && conversationAreaJsx, !conversationTab && headerVariant === 'compact' && !hideHeader && (_jsx("div", { className: "hidden h-full w-12 shrink-0 items-start justify-center px-1 pt-2 lg:flex", children: renderConversationHeader('compact') })), isRightPanelVisible && (_jsxs(_Fragment, { children: [!conversationTab && (_jsx("div", { role: "separator", "aria-orientation": "vertical", "aria-label": "Resize right panel", "aria-valuenow": Math.round(rightPanelWidth), "aria-valuemin": 300, "aria-valuetext": `${Math.round(rightPanelWidth)} pixels`, tabIndex: 0, className: "hidden lg:block lg:w-1 lg:shrink-0 cursor-col-resize bg-border/70 hover:bg-border transition-colors", onMouseDown: () => setIsRightPanelResizing(true), onKeyDown: (event) => {
1099
1508
  if (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight')