@vertesia/ui 1.4.0-dev.20260615.042549Z → 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,23 +1,24 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { AgentMessageType, } from '@vertesia/common';
3
- import { cn } from '@vertesia/ui/core';
3
+ import { Badge, Button, cn, VTooltip } from '@vertesia/ui/core';
4
4
  import { i18nInstance, NAMESPACE, useUITranslation } from '@vertesia/ui/i18n';
5
5
  import { NavLink } from '@vertesia/ui/router';
6
6
  import { MarkdownRenderer } from '@vertesia/ui/widgets';
7
- import { AlertTriangle, Bot, Brain, CheckCircle, ChevronDown, ChevronRight, CopyIcon, FileText, Pencil, Search, Terminal, Wrench, } from 'lucide-react';
7
+ import { AlertTriangle, ArrowLeft, Bot, Brain, CheckCircle, ChevronDown, ChevronRight, CopyIcon, FileText, Pencil, Search, Terminal, Wrench, } from 'lucide-react';
8
8
  import React, { Component, useCallback, useEffect, useMemo, useRef, useState } from 'react';
9
9
  import { AnimatedThinkingDots, PulsatingCircle } from '../AnimatedThinkingDots';
10
10
  import { AskUserWidget } from '../AskUserWidget';
11
11
  import { ThinkingMessages } from '../WaitingMessages';
12
- import { formatWorkstreamName, getWorkstreamDisplayName, getWorkstreamLaunchDetails, } from '../workstreams.js';
12
+ import { formatWorkstreamName, getWorkstreamActivityDetails, getWorkstreamDisplayName, getWorkstreamLaunchDetails, } from '../workstreams.js';
13
13
  import { AttachmentPreviewList, parseUserMessageAttachments } from './AttachmentPreview';
14
14
  import BatchProgressPanel from './BatchProgressPanel';
15
+ import { getMessageDeliveryStatus, MessageDeliveryStatus } from './MessageDeliveryStatus';
15
16
  import MessageItem from './MessageItem';
16
- import { getAnsweredRequestInputKeys, getPendingRequestInputMessage, getRequestInputMessageKey, isRequestInputAnswered, } from './requestInputMessages';
17
+ import { getAnsweredRequestInputKeys, getAnsweredToolApprovalRequestInputKeys, getHiddenToolApprovalAnswerKeys, getPendingRequestInputMessage, getRequestInputDisplayText, getRequestInputMessageKey, getResolvedToolApprovalKeys, hasRequestInputUx, isRequestInputAnswered, isToolApprovalAnswerHidden, isToolApprovalRequestInput, isToolApprovalRequestInputHidden, } from './requestInputMessages';
17
18
  import StreamingMessage from './StreamingMessage';
18
19
  import { buildSummaryConversationItems, buildSummaryDisplayMessages, getSummaryActivityAnchorTimestamp, isInitialSummaryActivityFallback, isTransientThinkingMessage, isTransientWorkStatusMessage, shouldShowSummaryActivityFallback, } from './SummaryConversation';
19
20
  import ToolCallGroup from './ToolCallGroup';
20
- import { DONE_STATES, getWorkstreamId, groupMessagesWithStreaming, isInProgress, isToolPreambleMessage, mergeConsecutiveToolGroups, shouldCollapseAdjacentRenderedMessage, } from './utils';
21
+ import { DONE_STATES, filterMessagesForActiveWorkstream, getWorkstreamId, groupMessagesWithStreaming, isInProgress, isToolPreambleMessage, isUserStoppedMessage, mergeConsecutiveToolGroups, shouldCollapseAdjacentRenderedMessage, } from './utils';
21
22
  import WorkstreamTabs, { extractWorkstreams, filterMessagesByWorkstream } from './WorkstreamTabs';
22
23
  // Check if message is a batch progress message
23
24
  const isBatchProgressMessage = (message) => {
@@ -44,6 +45,22 @@ function formatDuration(seconds) {
44
45
  const remainingSeconds = seconds % 60;
45
46
  return remainingSeconds > 0 ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`;
46
47
  }
48
+ function parseTimestampMs(timestamp) {
49
+ if (timestamp === undefined || timestamp === null || timestamp === '')
50
+ return undefined;
51
+ const value = typeof timestamp === 'number' ? timestamp : new Date(timestamp).getTime();
52
+ return Number.isFinite(value) ? value : undefined;
53
+ }
54
+ function formatToolDetailTimestamp(timestamp) {
55
+ const value = parseTimestampMs(timestamp);
56
+ if (value === undefined)
57
+ return undefined;
58
+ return new Intl.DateTimeFormat(undefined, {
59
+ hour: '2-digit',
60
+ minute: '2-digit',
61
+ second: '2-digit',
62
+ }).format(new Date(value));
63
+ }
47
64
  function getReadableToolLabel(message) {
48
65
  const details = message.details;
49
66
  const rawTool = details?.tool || '';
@@ -73,24 +90,98 @@ function getReadableToolLabel(message) {
73
90
  return text;
74
91
  return 'Using tool';
75
92
  }
76
- function getSummaryWorkLabel(status, isActive) {
77
- if (status === 'error')
78
- return 'Work needs attention';
79
- if (status === 'warning')
80
- return 'Work had warnings';
93
+ function getSummaryWorkLabel(isActive) {
81
94
  return isActive ? 'Working' : 'Worked';
82
95
  }
83
96
  function isTransientThinkingWork(messages) {
84
97
  return messages.length > 0 && messages.every(isTransientWorkStatusMessage);
85
98
  }
86
- function getSummaryActivityLabel(status, isActive) {
87
- return getSummaryWorkLabel(status, isActive);
99
+ function getSummaryActivityLabel(isActive) {
100
+ return getSummaryWorkLabel(isActive);
88
101
  }
89
102
  function hasOpenUserTurn(messages) {
90
103
  const mainMessages = messages.filter((message) => getWorkstreamId(message) === 'main');
91
104
  const latestMessage = mainMessages[mainMessages.length - 1] ?? messages[messages.length - 1];
92
105
  return latestMessage?.type === AgentMessageType.QUESTION;
93
106
  }
107
+ function hasLatestToolApprovalAllowTurn(messages, hiddenToolApprovalAnswerKeys) {
108
+ const mainMessages = messages.filter((message) => getWorkstreamId(message) === 'main');
109
+ const latestMessage = mainMessages[mainMessages.length - 1] ?? messages[messages.length - 1];
110
+ if (!latestMessage || !isToolApprovalAnswerHidden(latestMessage, hiddenToolApprovalAnswerKeys))
111
+ return false;
112
+ const response = getToolApprovalResponse(latestMessage);
113
+ return response === 'allow_once' || response === 'allow_for_run';
114
+ }
115
+ function getWriteArtifactCompletionPath(message) {
116
+ if (message.type !== AgentMessageType.UPDATE)
117
+ return undefined;
118
+ const details = getDetailsRecord(message);
119
+ if (details.tool !== undefined || details.activity_group_id !== undefined)
120
+ return undefined;
121
+ const path = typeof details.path === 'string' && details.path.trim() ? details.path.trim() : undefined;
122
+ if (!path)
123
+ return undefined;
124
+ return getMessageText(message) === `Prepared and saved artifact to ${path}` ? path : undefined;
125
+ }
126
+ function findPreviousWriteArtifactToolMessage(messages, index) {
127
+ const workstreamId = getWorkstreamId(messages[index]);
128
+ for (let prevIndex = index - 1; prevIndex >= 0; prevIndex -= 1) {
129
+ const previous = messages[prevIndex];
130
+ if (getWorkstreamId(previous) !== workstreamId)
131
+ continue;
132
+ const details = getDetailsRecord(previous);
133
+ if (details.tool === 'write_artifact' && typeof details.activity_group_id === 'string')
134
+ return previous;
135
+ if (previous.type === AgentMessageType.REQUEST_INPUT)
136
+ continue;
137
+ if (getToolApprovalResponse(previous))
138
+ continue;
139
+ if (details.display_role === 'thinking')
140
+ continue;
141
+ if (typeof details.tool === 'string' && details.tool !== 'write_artifact')
142
+ return undefined;
143
+ if (previous.type === AgentMessageType.ANSWER ||
144
+ previous.type === AgentMessageType.COMPLETE ||
145
+ previous.type === AgentMessageType.IDLE ||
146
+ previous.type === AgentMessageType.TERMINATED) {
147
+ return undefined;
148
+ }
149
+ }
150
+ return undefined;
151
+ }
152
+ function attachWriteArtifactCompletionMessages(messages) {
153
+ return messages.map((message, index) => {
154
+ const path = getWriteArtifactCompletionPath(message);
155
+ if (!path)
156
+ return message;
157
+ const previousToolMessage = findPreviousWriteArtifactToolMessage(messages, index);
158
+ const previousDetails = previousToolMessage ? getDetailsRecord(previousToolMessage) : undefined;
159
+ if (!previousDetails)
160
+ return message;
161
+ const activityGroupId = typeof previousDetails.activity_group_id === 'string' ? previousDetails.activity_group_id : undefined;
162
+ const toolRunId = typeof previousDetails.tool_run_id === 'string' ? previousDetails.tool_run_id : undefined;
163
+ const toolUseId = typeof previousDetails.tool_use_id === 'string' ? previousDetails.tool_use_id : undefined;
164
+ const toolIteration = typeof previousDetails.tool_iteration === 'number' ? previousDetails.tool_iteration : undefined;
165
+ if (!activityGroupId)
166
+ return message;
167
+ return {
168
+ ...message,
169
+ details: {
170
+ ...message.details,
171
+ event_class: 'activity',
172
+ tool: 'write_artifact',
173
+ tool_run_id: toolRunId ?? 'write_artifact',
174
+ tool_use_id: toolUseId ?? toolRunId ?? 'write_artifact',
175
+ tool_iteration: toolIteration,
176
+ tool_status: 'completed',
177
+ tool_event: 'progress',
178
+ activity_group_id: activityGroupId,
179
+ output: getMessageText(message),
180
+ path,
181
+ },
182
+ };
183
+ });
184
+ }
94
185
  function getMessageText(message) {
95
186
  if (!message.message)
96
187
  return '';
@@ -98,12 +189,12 @@ function getMessageText(message) {
98
189
  return JSON.stringify(message.message, null, 2);
99
190
  return String(message.message).trim();
100
191
  }
101
- function SummaryWorkstreamLaunchMessage({ message, details, }) {
192
+ function SummaryWorkstreamLaunchMessage({ message, details, onSelectWorkstream, }) {
102
193
  const { t } = useUITranslation();
103
194
  const workstreamName = getWorkstreamDisplayName(details.workstreamId, details.interaction);
104
195
  const interactionName = details.interaction ? formatWorkstreamName(details.interaction) : '';
105
196
  const secondaryName = interactionName && interactionName !== workstreamName ? interactionName : undefined;
106
- return (_jsx("div", { className: "mx-auto w-full max-w-3xl px-1", "data-workstream-id": details.workstreamId, children: _jsxs("div", { className: "flex items-start gap-3 border-b border-border/70 py-2 text-sm text-muted", children: [_jsx(Bot, { className: "mt-0.5 size-4 shrink-0 text-muted", "aria-hidden": "true" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [_jsx("span", { className: "font-medium text-muted", children: t('agent.workstreams') }), _jsx("span", { className: "min-w-0 truncate text-foreground/85", children: workstreamName })] }), secondaryName && _jsx("div", { className: "mt-0.5 truncate text-xs text-muted/75", children: secondaryName }), _jsx("span", { className: "sr-only", children: getMessageText(message) })] })] }) }));
197
+ return (_jsx("div", { className: "mx-auto w-full max-w-3xl px-1", "data-workstream-id": details.workstreamId, children: _jsxs("button", { type: "button", className: cn('group flex w-full items-start gap-3 border-b border-border/70 py-2 text-start text-sm text-muted', 'transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2', 'focus-visible:ring-focus focus-visible:ring-offset-2 focus-visible:ring-offset-background'), onClick: () => onSelectWorkstream?.(details.workstreamId), children: [_jsx(Bot, { className: "mt-0.5 size-4 shrink-0 text-muted", "aria-hidden": "true" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [_jsx("span", { className: "font-medium text-muted", children: t('agent.workstreams') }), _jsx("span", { className: "min-w-0 truncate text-foreground/85", children: workstreamName })] }), secondaryName && _jsx("div", { className: "mt-0.5 truncate text-xs text-muted/75", children: secondaryName }), _jsx("span", { className: "sr-only", children: getMessageText(message) })] }), _jsx(ChevronRight, { className: "mt-0.5 size-4 shrink-0 text-muted transition-transform group-hover:translate-x-0.5 rtl:rotate-180 rtl:group-hover:-translate-x-0.5" })] }) }));
107
198
  }
108
199
  const SUMMARY_PROSE_CLASS = [
109
200
  'agent-markdown vprose prose max-w-none break-words text-sm leading-6 text-foreground/80',
@@ -113,6 +204,8 @@ const SUMMARY_PROSE_CLASS = [
113
204
  '[&_p]:text-foreground/80 [&_li]:text-foreground/80 [&_li::marker]:text-muted',
114
205
  ].join(' ');
115
206
  const USER_BUBBLE_COLLAPSE_THRESHOLD = 520;
207
+ const SUMMARY_THOUGHT_COLLAPSE_LINES = 6;
208
+ const SUMMARY_THOUGHT_COLLAPSE_THRESHOLD = 520;
116
209
  const STORE_LINK_MARKDOWN_RE = /\[[^\]]+\]\((?:\/store\/(?:objects|collections)\/|store:|document:|document:\/\/|collection:)[^)]+\)/;
117
210
  const DEFAULT_AGENT_MARKDOWN_COMPONENTS = {
118
211
  table: AgentMarkdownTable,
@@ -265,7 +358,7 @@ function useRotatingThinkingMessageIndex(enabled = true) {
265
358
  }, [enabled]);
266
359
  return thinkingMessageIndex;
267
360
  }
268
- function SummaryUserBubble({ children, workstreamId, className, artifactRunId, markdownComponents, }) {
361
+ function SummaryUserBubble({ children, message, workstreamId, className, artifactRunId, markdownComponents, }) {
269
362
  const { t } = useUITranslation();
270
363
  const [isExpanded, setIsExpanded] = useState(false);
271
364
  const contentLength = useMemo(() => getReactNodeTextLength(children), [children]);
@@ -273,6 +366,7 @@ function SummaryUserBubble({ children, workstreamId, className, artifactRunId, m
273
366
  const isPlainText = typeof children === 'string' || typeof children === 'number';
274
367
  const textContent = isPlainText ? String(children) : '';
275
368
  const shouldRenderMarkdown = typeof children === 'string' && STORE_LINK_MARKDOWN_RE.test(children);
369
+ const deliveryStatus = message ? getMessageDeliveryStatus(message) : undefined;
276
370
  useEffect(() => {
277
371
  if (!shouldCollapse && isExpanded) {
278
372
  setIsExpanded(false);
@@ -280,11 +374,11 @@ function SummaryUserBubble({ children, workstreamId, className, artifactRunId, m
280
374
  }, [isExpanded, shouldCollapse]);
281
375
  return (_jsx("div", { className: "mx-auto flex w-full max-w-3xl justify-end px-1", children: _jsxs("div", { className: cn('max-w-[min(44rem,82%)] rounded-[1.35rem] bg-mixer-muted/35 px-4 py-2.5', 'text-sm font-normal leading-6 text-foreground/90 shadow-sm shadow-black/5 dark:bg-mixer-muted/15 dark:text-foreground/88 dark:shadow-none', 'break-words [overflow-wrap:anywhere]', className), "data-workstream-id": workstreamId, children: [_jsx("div", { className: cn(isPlainText && !shouldRenderMarkdown && 'whitespace-pre-wrap', shouldCollapse &&
282
376
  !isExpanded &&
283
- 'max-h-72 overflow-hidden [mask-image:linear-gradient(to_bottom,black_76%,transparent_100%)]'), children: shouldRenderMarkdown ? (_jsx(MarkdownRenderer, { artifactRunId: artifactRunId, components: markdownComponents, className: cn('agent-markdown vprose prose max-w-none break-words text-sm leading-6 text-foreground/90', 'prose-p:my-0 prose-p:leading-6 prose-a:text-foreground prose-a:underline prose-a:decoration-muted prose-a:underline-offset-4', '[&_p+_p]:mt-2'), children: textContent })) : (children) }), shouldCollapse && (_jsxs("button", { type: "button", "aria-expanded": isExpanded, className: "mt-2 inline-flex items-center gap-1 text-sm font-medium text-muted transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", onClick: () => setIsExpanded((current) => !current), children: [isExpanded ? t('agent.showLess') : t('agent.showMore'), _jsx(ChevronDown, { className: cn('size-4 transition-transform', isExpanded && 'rotate-180'), "aria-hidden": "true" })] }))] }) }));
377
+ 'max-h-72 overflow-hidden [mask-image:linear-gradient(to_bottom,black_76%,transparent_100%)]'), children: shouldRenderMarkdown ? (_jsx(MarkdownRenderer, { artifactRunId: artifactRunId, components: markdownComponents, className: cn('agent-markdown vprose prose max-w-none break-words text-sm leading-6 text-foreground/90', 'prose-p:my-0 prose-p:leading-6 prose-a:text-foreground prose-a:underline prose-a:decoration-muted prose-a:underline-offset-4', '[&_p+_p]:mt-2'), children: textContent })) : (children) }), shouldCollapse && (_jsxs("button", { type: "button", "aria-expanded": isExpanded, className: "mt-2 inline-flex items-center gap-1 text-sm font-medium text-muted transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", onClick: () => setIsExpanded((current) => !current), children: [isExpanded ? t('agent.showLess') : t('agent.showMore'), _jsx(ChevronDown, { className: cn('size-4 transition-transform', isExpanded && 'rotate-180'), "aria-hidden": "true" })] })), message && deliveryStatus ? (_jsx("div", { className: "mt-1.5 flex justify-end", children: _jsx(MessageDeliveryStatus, { message: message, className: "h-4 w-4" }) })) : null] }) }));
284
378
  }
285
- function SummaryMessage({ message, onSendMessage, requestInputAnswered = false, StoreLinkComponent, CollectionLinkComponent, }) {
286
- const content = getMessageText(message);
287
- const workstreamLaunchDetails = getWorkstreamLaunchDetails(message);
379
+ function SummaryMessage({ message, onSendMessage, onSelectWorkstream, requestInputAnswered = false, StoreLinkComponent, CollectionLinkComponent, }) {
380
+ const content = message.type === AgentMessageType.REQUEST_INPUT ? getRequestInputDisplayText(message) : getMessageText(message);
381
+ const workstreamLaunchDetails = getWorkstreamLaunchDetails(message) ?? getWorkstreamActivityDetails(message);
288
382
  const workstreamId = getWorkstreamId(message);
289
383
  const runId = message.workflow_run_id;
290
384
  const parsedQuestion = useMemo(() => (message.type === AgentMessageType.QUESTION ? parseUserMessageAttachments(content) : null), [content, message.type]);
@@ -310,17 +404,17 @@ function SummaryMessage({ message, onSendMessage, requestInputAnswered = false,
310
404
  },
311
405
  }), [StoreLinkComponent, CollectionLinkComponent]);
312
406
  if (workstreamLaunchDetails) {
313
- return _jsx(SummaryWorkstreamLaunchMessage, { message: message, details: workstreamLaunchDetails });
407
+ return (_jsx(SummaryWorkstreamLaunchMessage, { message: message, details: workstreamLaunchDetails, onSelectWorkstream: onSelectWorkstream }));
314
408
  }
315
409
  if (message.type === AgentMessageType.QUESTION) {
316
410
  const questionBody = parsedQuestion?.body ?? content;
317
411
  const attachments = parsedQuestion?.attachments ?? [];
318
- return (_jsxs(_Fragment, { children: [attachments.length > 0 && (_jsx("div", { className: "mx-auto flex w-full max-w-3xl justify-end px-1", children: _jsx(AttachmentPreviewList, { items: attachments, artifactRunId: runId, align: "end", variant: "message", StoreLinkComponent: StoreLinkComponent, CollectionLinkComponent: CollectionLinkComponent }) })), questionBody && (_jsx(SummaryUserBubble, { workstreamId: workstreamId, artifactRunId: runId, markdownComponents: markdownComponents, children: questionBody }))] }));
412
+ return (_jsxs(_Fragment, { children: [attachments.length > 0 && (_jsx("div", { className: "mx-auto flex w-full max-w-3xl justify-end px-1", children: _jsx(AttachmentPreviewList, { items: attachments, artifactRunId: runId, align: "end", variant: "message", StoreLinkComponent: StoreLinkComponent, CollectionLinkComponent: CollectionLinkComponent }) })), questionBody && (_jsx(SummaryUserBubble, { message: message, workstreamId: workstreamId, artifactRunId: runId, markdownComponents: markdownComponents, children: questionBody }))] }));
319
413
  }
320
414
  const requestInputDetails = message.details;
321
415
  if (message.type === AgentMessageType.REQUEST_INPUT && requestInputDetails?.ux) {
322
416
  const uxConfig = requestInputDetails.ux;
323
- return (_jsx("div", { className: "mx-auto w-full max-w-3xl px-1", children: _jsx(AskUserWidget, { question: content, options: uxConfig.options, variant: uxConfig.variant, multiSelect: uxConfig.multiSelect, onSelect: (optionId) => onSendMessage?.(optionId), onMultiSelect: (optionIds) => onSendMessage?.(optionIds.join(', ')), hideBorder: true, compact: true, answered: requestInputAnswered }) }));
417
+ return (_jsx("div", { className: "mx-auto w-full max-w-3xl px-1", children: _jsx(AskUserWidget, { question: content, options: uxConfig.options, variant: uxConfig.variant, multiSelect: uxConfig.multiSelect, onSelect: (optionId) => onSendMessage?.(optionId), onMultiSelect: (optionIds) => onSendMessage?.(optionIds.join(', ')), allowFreeResponse: !uxConfig.options?.length || !!uxConfig.free_response, placeholder: uxConfig.free_response?.placeholder, submitLabel: uxConfig.free_response?.submit_label, onSubmit: (value) => onSendMessage?.(value, uxConfig.free_response?.metadata), hideBorder: true, compact: true, answered: requestInputAnswered }) }));
324
418
  }
325
419
  const isError = message.type === AgentMessageType.ERROR || message.type === AgentMessageType.WARNING;
326
420
  return (_jsxs("div", { className: "mx-auto w-full max-w-3xl px-1", "data-workstream-id": workstreamId, children: [isError && (_jsx("div", { className: "mb-2 text-xs font-medium text-destructive", children: message.type === AgentMessageType.WARNING ? 'Warning' : 'Error' })), content && (_jsx("div", { className: cn(SUMMARY_PROSE_CLASS, isError && 'rounded-lg border border-destructive/20 bg-destructive/5 px-3 py-2'), style: { overflowWrap: 'anywhere' }, children: _jsx(MarkdownRenderer, { artifactRunId: runId, onProposalSelect: (optionId) => onSendMessage?.(optionId), onProposalSubmit: (text) => onSendMessage?.(text), components: markdownComponents, children: content }) }))] }));
@@ -437,6 +531,9 @@ function InitialRequestWaitingCard({ label, timestamp, className, }) {
437
531
  const elapsed = useLiveElapsedSeconds(timestamp, true);
438
532
  return (_jsx("div", { className: cn('mx-auto w-full max-w-3xl px-1', className), children: _jsxs("div", { className: "border-b border-border/70 pb-4 text-sm text-muted", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx(PulsatingCircle, { size: "sm", color: "blue" }), _jsxs("div", { className: "min-w-0", children: [_jsxs("div", { children: [_jsx("span", { className: "font-medium", children: label }), _jsxs("span", { className: "ms-2 text-muted/75", children: ["for ", formatDuration(elapsed)] })] }), _jsx("div", { className: "mt-1 truncate text-muted/80", children: ThinkingMessages[thinkingMessageIndex] })] })] }), _jsx("div", { className: "mt-3 ps-6", children: _jsx(AnimatedThinkingDots, { color: "blue" }) })] }) }));
439
533
  }
534
+ const SUMMARY_TOOL_STARTED_AT_DETAIL_KEY = '_summary_started_at';
535
+ const SUMMARY_TOOL_FINISHED_AT_DETAIL_KEY = '_summary_finished_at';
536
+ const SYNTHETIC_TOOL_APPROVAL_EVENT_SOURCE = 'synthetic_tool_approval_decision';
440
537
  const TOOL_DETAIL_SYSTEM_KEYS = new Set([
441
538
  'account_id',
442
539
  'activity_group_id',
@@ -462,11 +559,26 @@ const TOOL_DETAIL_SYSTEM_KEYS = new Set([
462
559
  'tools',
463
560
  'message_to_human',
464
561
  'progress_messages',
562
+ 'source',
563
+ 'token_usage',
564
+ 'checkpoint_at',
565
+ 'checkpoint_threshold',
566
+ 'approval_decision',
567
+ 'approval_request',
568
+ 'cancellation_reason',
569
+ SUMMARY_TOOL_STARTED_AT_DETAIL_KEY,
570
+ SUMMARY_TOOL_FINISHED_AT_DETAIL_KEY,
465
571
  'workflow_run_id',
466
572
  ]);
467
573
  function getDetailsRecord(message) {
468
574
  return isRecordValue(message.details) ? message.details : {};
469
575
  }
576
+ function isDocumentPanelEventMessage(message) {
577
+ if (message.type !== AgentMessageType.UPDATE)
578
+ return false;
579
+ const eventClass = getDetailsRecord(message).event_class;
580
+ return eventClass === 'document_created' || eventClass === 'document_updated';
581
+ }
470
582
  function humanizeIdentifier(value) {
471
583
  return value
472
584
  .replace(/[_-]+/g, ' ')
@@ -492,6 +604,13 @@ function getToolNames(details) {
492
604
  }
493
605
  return names;
494
606
  }
607
+ function getUniqueToolName(details) {
608
+ const names = Array.from(new Set(getToolNames(details)));
609
+ return names.length > 0 ? names.join(', ') : undefined;
610
+ }
611
+ function getTimestampDetail(value) {
612
+ return typeof value === 'number' || typeof value === 'string' ? value : undefined;
613
+ }
495
614
  const TOOL_TARGET_KEYS = [
496
615
  'query',
497
616
  'path',
@@ -520,17 +639,15 @@ function getToolDetailKind(message) {
520
639
  const details = getDetailsRecord(message);
521
640
  const toolNames = getToolNames(details).join(' ').toLowerCase();
522
641
  const concreteTool = typeof details.tool === 'string' ? details.tool.toLowerCase() : '';
523
- const text = getMessageText(message).toLowerCase();
524
- const haystack = `${toolNames} ${text}`;
642
+ const classifierText = concreteTool || toolNames;
525
643
  if (isToolPreambleMessage(message))
526
644
  return 'think';
527
- if (concreteTool.startsWith('learn_') || haystack.includes('learn_') || /\bskill\b/.test(text))
645
+ if (concreteTool.startsWith('learn_') || toolNames.includes('learn_'))
528
646
  return 'skill';
529
647
  if (concreteTool === 'discover_tools')
530
648
  return 'discover';
531
649
  if (message.type === AgentMessageType.THOUGHT && !concreteTool)
532
650
  return 'think';
533
- const classifierText = concreteTool || haystack;
534
651
  if (classifierText.includes('search') || classifierText.includes('web') || classifierText.includes('fetch'))
535
652
  return 'search';
536
653
  if (classifierText.includes('read') || classifierText.includes('document') || classifierText.includes('file'))
@@ -579,6 +696,125 @@ function getToolTarget(details) {
579
696
  }
580
697
  return undefined;
581
698
  }
699
+ function getApprovalDecisionLabel(decision, toolLabel) {
700
+ switch (decision) {
701
+ case 'denied':
702
+ case 'denied_with_feedback':
703
+ return `User declined to use ${toolLabel}.`;
704
+ case 'timeout':
705
+ return `Approval timed out for ${toolLabel}.`;
706
+ case 'reviewer_denied':
707
+ return `Approval reviewer denied ${toolLabel}.`;
708
+ case 'cancelled_after_denial':
709
+ return `Cancelled ${toolLabel} after another tool was denied.`;
710
+ default:
711
+ return undefined;
712
+ }
713
+ }
714
+ function getApprovalDecisionStatusText(decision) {
715
+ switch (decision) {
716
+ case 'denied':
717
+ case 'denied_with_feedback':
718
+ return 'Declined by user';
719
+ case 'timeout':
720
+ return 'Approval timed out';
721
+ case 'reviewer_denied':
722
+ return 'Denied by reviewer';
723
+ case 'cancelled_after_denial':
724
+ return 'Cancelled after denial';
725
+ default:
726
+ return undefined;
727
+ }
728
+ }
729
+ function getToolApprovalRecord(message) {
730
+ const details = getDetailsRecord(message);
731
+ const toolApproval = details.tool_approval;
732
+ return isRecordValue(toolApproval) ? toolApproval : undefined;
733
+ }
734
+ function getApprovalKeyFromToolApproval(toolApproval) {
735
+ const approvalKey = toolApproval?.approval_key;
736
+ return typeof approvalKey === 'string' && approvalKey.trim() ? approvalKey.trim() : undefined;
737
+ }
738
+ function getToolApprovalResponse(message) {
739
+ if (message.type !== AgentMessageType.QUESTION)
740
+ return undefined;
741
+ const normalized = getMessageText(message).trim().toLowerCase();
742
+ if (normalized === 'allow_once' || normalized === 'allow_for_run' || normalized === 'deny')
743
+ return normalized;
744
+ return undefined;
745
+ }
746
+ function getToolApprovalDisplayName(toolApproval) {
747
+ const title = toolApproval.tool_title;
748
+ if (typeof title === 'string' && title.trim())
749
+ return title.trim();
750
+ const name = toolApproval.tool_name;
751
+ if (typeof name === 'string' && name.trim())
752
+ return humanizeIdentifier(name.trim());
753
+ return 'tool action';
754
+ }
755
+ function buildSyntheticToolApprovalDecisionMessages(messages, resolvedToolApprovalKeys) {
756
+ const syntheticMessages = [];
757
+ messages.forEach((message, index) => {
758
+ if (message.type !== AgentMessageType.REQUEST_INPUT)
759
+ return;
760
+ const toolApproval = getToolApprovalRecord(message);
761
+ const approvalKey = getApprovalKeyFromToolApproval(toolApproval);
762
+ if (!toolApproval || !approvalKey || resolvedToolApprovalKeys.has(approvalKey))
763
+ return;
764
+ const workstreamId = getWorkstreamId(message);
765
+ let responseMessage;
766
+ for (let nextIndex = index + 1; nextIndex < messages.length; nextIndex += 1) {
767
+ const nextMessage = messages[nextIndex];
768
+ if (getWorkstreamId(nextMessage) !== workstreamId)
769
+ continue;
770
+ if (nextMessage.type === AgentMessageType.REQUEST_INPUT)
771
+ break;
772
+ if (nextMessage.type === AgentMessageType.QUESTION) {
773
+ responseMessage = nextMessage;
774
+ break;
775
+ }
776
+ }
777
+ if (!responseMessage || getToolApprovalResponse(responseMessage) !== 'deny')
778
+ return;
779
+ const toolName = typeof toolApproval.tool_name === 'string' && toolApproval.tool_name.trim()
780
+ ? toolApproval.tool_name.trim()
781
+ : 'tool_action';
782
+ const toolLabel = getToolApprovalDisplayName(toolApproval);
783
+ const target = typeof toolApproval.target === 'string' && toolApproval.target.trim() ? toolApproval.target : '';
784
+ const approvalRequest = {
785
+ tool_name: toolName,
786
+ tool_title: toolApproval.tool_title,
787
+ action_summary: toolApproval.action_summary,
788
+ target: toolApproval.target,
789
+ approval_key: approvalKey,
790
+ };
791
+ syntheticMessages.push({
792
+ timestamp: responseMessage.timestamp ?? message.timestamp,
793
+ workflow_run_id: responseMessage.workflow_run_id || message.workflow_run_id,
794
+ type: AgentMessageType.THOUGHT,
795
+ message: getApprovalDecisionLabel('denied', toolLabel) ?? `User declined to use ${toolLabel}.`,
796
+ workstream_id: workstreamId,
797
+ details: {
798
+ event_class: 'activity',
799
+ tool: toolName,
800
+ tool_run_id: `approval:${approvalKey}`,
801
+ tool_use_id: `approval:${approvalKey}`,
802
+ tool_status: 'error',
803
+ tool_event: 'failed',
804
+ activity_group_id: `approval:${approvalKey}`,
805
+ approval_decision: 'denied',
806
+ approval_request: approvalRequest,
807
+ input: toolApproval.input,
808
+ target,
809
+ observation: 'The user declined this tool action.',
810
+ source: SYNTHETIC_TOOL_APPROVAL_EVENT_SOURCE,
811
+ },
812
+ });
813
+ });
814
+ if (syntheticMessages.length === 0)
815
+ return messages;
816
+ return [...messages, ...syntheticMessages].sort((a, b) => getTimestampMs(a.timestamp) - getTimestampMs(b.timestamp));
817
+ }
582
818
  function compactInlineText(value, maxLength = 160) {
583
819
  const normalized = value.replace(/\s+/g, ' ').trim();
584
820
  return normalized.length > maxLength ? `${normalized.slice(0, maxLength - 1)}...` : normalized;
@@ -632,6 +868,18 @@ function getRenderableGroupKey(group) {
632
868
  const lastKey = lastMessage ? getAgentMessageRenderKey(lastMessage, 'last') : group.firstTimestamp;
633
869
  return ['group', group.toolRunId, group.firstTimestamp, firstKey, lastKey].filter(Boolean).join(':');
634
870
  }
871
+ function getPreviousRenderableGroupTimestamp(groups, index) {
872
+ for (let previousIndex = index - 1; previousIndex >= 0; previousIndex--) {
873
+ const group = groups[previousIndex];
874
+ if (group.type === 'single')
875
+ return group.message.timestamp;
876
+ if (group.type === 'tool_group')
877
+ return group.firstTimestamp;
878
+ if (group.type === 'streaming')
879
+ return group.startTimestamp;
880
+ }
881
+ return undefined;
882
+ }
635
883
  function formatToolSectionValue(value) {
636
884
  const text = stringifyRequestValue(value).trim();
637
885
  return text.length > 2400 ? `${text.slice(0, 2400)}\n...` : text;
@@ -673,16 +921,7 @@ function getToolDetailSections(message) {
673
921
  };
674
922
  addSection('Query', ['query']);
675
923
  addSection('Input', ['input', 'params', 'arguments', 'args']);
676
- addSection('Output', [
677
- 'output',
678
- 'stdout',
679
- 'result',
680
- 'results',
681
- 'content',
682
- 'result_summary',
683
- 'observation',
684
- 'display_message',
685
- ]);
924
+ addSection('Output', ['output', 'stdout', 'result', 'results', 'content', 'result_summary', 'observation', 'display_message'], typeof details.approval_decision === 'string' ? 'error' : undefined);
686
925
  addSection('Files', ['files', 'outputFiles']);
687
926
  addSection('Error', ['error', 'stderr'], 'error');
688
927
  if (targetEntry)
@@ -694,20 +933,28 @@ function getToolDetailSections(message) {
694
933
  return sections;
695
934
  }
696
935
  function buildSummaryToolDetailItem(message, index) {
936
+ if (message.type === AgentMessageType.REQUEST_INPUT)
937
+ return undefined;
697
938
  const text = getMessageText(message);
698
939
  const details = getDetailsRecord(message);
940
+ const isPreamble = isToolPreambleMessage(message);
699
941
  const kind = getToolDetailKind(message);
700
942
  const toolNames = getToolNames(details);
701
943
  const target = getToolTarget(details);
702
944
  const command = typeof details.command === 'string' && details.command.trim() ? details.command.trim() : undefined;
703
945
  const fallbackTitle = toolNames[0] ? humanizeIdentifier(toolNames[0]) : getReadableToolLabel(message);
946
+ const approvalDecisionTitle = getApprovalDecisionLabel(details.approval_decision, fallbackTitle);
947
+ const decisionText = getApprovalDecisionStatusText(details.approval_decision);
948
+ const messageToHuman = typeof details.message_to_human === 'string' && details.message_to_human.trim()
949
+ ? details.message_to_human.trim()
950
+ : undefined;
704
951
  const title = kind === 'think'
705
952
  ? text || fallbackTitle
706
953
  : kind === 'command'
707
- ? compactInlineText(text || command || fallbackTitle)
708
- : compactInlineText(target || text || fallbackTitle);
954
+ ? compactInlineText(messageToHuman || (!approvalDecisionTitle ? text : '') || command || fallbackTitle)
955
+ : compactInlineText(messageToHuman || target || (!approvalDecisionTitle ? text : '') || fallbackTitle);
709
956
  const normalizedText = text ? (kind === 'think' ? text : compactInlineText(text, 420)) : undefined;
710
- const shouldShowText = normalizedText && normalizedText !== title;
957
+ const shouldShowText = normalizedText && normalizedText !== title && !approvalDecisionTitle;
711
958
  if (!title && !shouldShowText)
712
959
  return undefined;
713
960
  return {
@@ -715,36 +962,113 @@ function buildSummaryToolDetailItem(message, index) {
715
962
  kind,
716
963
  label: getToolDetailLabel(kind),
717
964
  title,
965
+ isPreamble,
718
966
  command,
719
967
  text: shouldShowText ? normalizedText : undefined,
720
- status: details.tool_status,
968
+ toolName: getUniqueToolName(details),
969
+ startedAt: getTimestampDetail(details[SUMMARY_TOOL_STARTED_AT_DETAIL_KEY]) ?? message.timestamp,
970
+ finishedAt: getTimestampDetail(details[SUMMARY_TOOL_FINISHED_AT_DETAIL_KEY]) ?? message.timestamp,
971
+ status: approvalDecisionTitle ? 'error' : details.tool_status,
972
+ decisionText,
721
973
  sections: getToolDetailSections(message),
722
974
  };
723
975
  }
976
+ function isPlanToolMessage(message) {
977
+ const details = getDetailsRecord(message);
978
+ return details.tool === 'plan' || details.tool === 'update_plan';
979
+ }
980
+ function isPlanLifecycleMessage(message) {
981
+ const details = getDetailsRecord(message);
982
+ if (message.type === AgentMessageType.UPDATE && Array.isArray(details.updates))
983
+ return true;
984
+ return message.type === AgentMessageType.PLAN && Array.isArray(details.plan);
985
+ }
986
+ function getActivityGroupIdentity(details) {
987
+ return typeof details.activity_group_id === 'string' && details.activity_group_id.trim()
988
+ ? details.activity_group_id.trim()
989
+ : undefined;
990
+ }
991
+ function getToolIdentity(details) {
992
+ if (typeof details.tool_use_id === 'string' && details.tool_use_id.trim())
993
+ return details.tool_use_id.trim();
994
+ if (typeof details.tool_run_id === 'string' && details.tool_run_id.trim())
995
+ return details.tool_run_id.trim();
996
+ if (typeof details.tool === 'string' && details.tool.trim())
997
+ return details.tool.trim();
998
+ return undefined;
999
+ }
1000
+ function getSplitActivityGroups(messages) {
1001
+ const startedToolIdentities = new Map();
1002
+ const approvalDecisionToolIdentities = new Map();
1003
+ const addIdentity = (groups, activityGroupId, toolIdentity) => {
1004
+ if (!activityGroupId || !toolIdentity)
1005
+ return;
1006
+ const identities = groups.get(activityGroupId) ?? new Set();
1007
+ identities.add(toolIdentity);
1008
+ groups.set(activityGroupId, identities);
1009
+ };
1010
+ for (const message of messages) {
1011
+ const details = getDetailsRecord(message);
1012
+ const activityGroupId = getActivityGroupIdentity(details);
1013
+ const toolIdentity = getToolIdentity(details);
1014
+ if (details.tool_event === 'started') {
1015
+ addIdentity(startedToolIdentities, activityGroupId, toolIdentity);
1016
+ }
1017
+ if (typeof details.approval_decision === 'string') {
1018
+ addIdentity(approvalDecisionToolIdentities, activityGroupId, toolIdentity);
1019
+ }
1020
+ }
1021
+ return new Set([...startedToolIdentities.entries(), ...approvalDecisionToolIdentities.entries()]
1022
+ .filter(([, identities]) => identities.size > 1)
1023
+ .map(([activityGroupId]) => activityGroupId));
1024
+ }
1025
+ function getSummaryToolGroupId(details, splitActivityGroups) {
1026
+ const activityGroupId = getActivityGroupIdentity(details);
1027
+ const toolIdentity = getToolIdentity(details);
1028
+ if (activityGroupId) {
1029
+ if (toolIdentity && splitActivityGroups.has(activityGroupId)) {
1030
+ return `activity:${activityGroupId}:tool:${toolIdentity}`;
1031
+ }
1032
+ return `activity:${activityGroupId}`;
1033
+ }
1034
+ if (typeof details.tool_use_id === 'string' && details.tool_use_id.trim()) {
1035
+ return `tool-use:${details.tool_use_id.trim()}`;
1036
+ }
1037
+ if (typeof details.tool_run_id === 'string' && details.tool_run_id.trim())
1038
+ return `run:${details.tool_run_id.trim()}`;
1039
+ return undefined;
1040
+ }
724
1041
  function mergeSummaryToolMessages(messages) {
725
1042
  const byGroupId = new Map();
726
1043
  const ungrouped = [];
1044
+ let currentPlanGroupId;
1045
+ const splitActivityGroups = getSplitActivityGroups(messages);
727
1046
  messages.forEach((message, index) => {
728
1047
  const details = getDetailsRecord(message);
729
1048
  if (isToolPreambleMessage(message)) {
730
1049
  ungrouped.push({ index, message });
1050
+ currentPlanGroupId = undefined;
731
1051
  return;
732
1052
  }
733
- const activityGroupId = typeof details.activity_group_id === 'string' && details.activity_group_id.trim()
734
- ? details.activity_group_id
735
- : undefined;
736
- const runId = typeof details.tool_run_id === 'string' && details.tool_run_id.trim() ? details.tool_run_id : undefined;
737
- const groupId = activityGroupId ? `activity:${activityGroupId}` : runId ? `run:${runId}` : undefined;
738
- if (!groupId) {
1053
+ const groupId = getSummaryToolGroupId(details, splitActivityGroups);
1054
+ const legacyPlanGroupId = !groupId && isPlanLifecycleMessage(message) ? currentPlanGroupId : undefined;
1055
+ const effectiveGroupId = groupId ?? legacyPlanGroupId;
1056
+ if (!effectiveGroupId) {
739
1057
  ungrouped.push({ index, message });
740
1058
  return;
741
1059
  }
742
- const group = byGroupId.get(groupId);
1060
+ const group = byGroupId.get(effectiveGroupId);
743
1061
  if (group) {
744
1062
  group.messages.push(message);
745
1063
  }
746
1064
  else {
747
- byGroupId.set(groupId, { index, messages: [message] });
1065
+ byGroupId.set(effectiveGroupId, { index, messages: [message] });
1066
+ }
1067
+ if (isPlanToolMessage(message)) {
1068
+ currentPlanGroupId = effectiveGroupId;
1069
+ }
1070
+ else if (message.type === AgentMessageType.PLAN) {
1071
+ currentPlanGroupId = undefined;
748
1072
  }
749
1073
  });
750
1074
  const grouped = Array.from(byGroupId.values()).map(({ index, messages: runMessages }) => {
@@ -752,6 +1076,10 @@ function mergeSummaryToolMessages(messages) {
752
1076
  const baseMessage = sortedMessages[sortedMessages.length - 1];
753
1077
  const startMessage = sortedMessages.find((message) => getDetailsRecord(message).tool_event === 'started');
754
1078
  const firstTextMessage = sortedMessages.find((message) => getMessageText(message));
1079
+ const latestApprovalDecisionMessage = sortedMessages.findLast((message) => {
1080
+ const details = getDetailsRecord(message);
1081
+ return typeof details.approval_decision === 'string' && Boolean(getMessageText(message));
1082
+ });
755
1083
  const commandTextMessage = sortedMessages.findLast((message) => getMessageText(message).startsWith('$ '));
756
1084
  const latestStatusMessage = sortedMessages.findLast((message) => (message.type === AgentMessageType.ERROR || message.type === AgentMessageType.WARNING) &&
757
1085
  getMessageText(message));
@@ -762,15 +1090,23 @@ function mergeSummaryToolMessages(messages) {
762
1090
  if (latestStatusMessage && mergedDetails.error === undefined && mergedDetails.stderr === undefined) {
763
1091
  mergedDetails.error = getMessageText(latestStatusMessage);
764
1092
  }
1093
+ if (!latestStatusMessage &&
1094
+ sortedMessages.some((message) => message.type === AgentMessageType.PLAN && Array.isArray(message.details?.plan))) {
1095
+ mergedDetails.tool_status = 'completed';
1096
+ }
765
1097
  if (commandTextMessage && mergedDetails.command === undefined) {
766
1098
  mergedDetails.command = getMessageText(commandTextMessage);
767
1099
  }
1100
+ mergedDetails[SUMMARY_TOOL_STARTED_AT_DETAIL_KEY] = sortedMessages[0]?.timestamp;
1101
+ mergedDetails[SUMMARY_TOOL_FINISHED_AT_DETAIL_KEY] = sortedMessages[sortedMessages.length - 1]?.timestamp;
768
1102
  const messageToHuman = typeof startMessage?.details?.message_to_human === 'string' ? startMessage.details.message_to_human : '';
769
1103
  return {
770
1104
  index,
771
1105
  message: {
772
1106
  ...baseMessage,
773
- message: messageToHuman || (firstTextMessage ? firstTextMessage.message : baseMessage.message),
1107
+ message: latestApprovalDecisionMessage?.message ||
1108
+ messageToHuman ||
1109
+ (firstTextMessage ? firstTextMessage.message : baseMessage.message),
774
1110
  details: mergedDetails,
775
1111
  },
776
1112
  };
@@ -815,6 +1151,31 @@ function ToolDetailIcon({ kind, status }) {
815
1151
  return _jsx(Wrench, { className: "size-3.5" });
816
1152
  }
817
1153
  }
1154
+ function getToolDetailMetadata(item) {
1155
+ const entries = [];
1156
+ const startedMs = parseTimestampMs(item.startedAt);
1157
+ const finishedMs = parseTimestampMs(item.finishedAt);
1158
+ const startedAt = formatToolDetailTimestamp(item.startedAt);
1159
+ const finishedAt = formatToolDetailTimestamp(item.finishedAt);
1160
+ if (item.toolName) {
1161
+ entries.push({ label: 'Tool', value: item.toolName });
1162
+ }
1163
+ if (startedAt && finishedAt && startedMs !== undefined && finishedMs !== undefined && startedMs !== finishedMs) {
1164
+ entries.push({ label: 'Started', value: startedAt });
1165
+ entries.push({ label: 'Ended', value: finishedAt });
1166
+ entries.push({ label: 'Duration', value: formatDuration(getDurationSeconds(item.startedAt, item.finishedAt)) });
1167
+ }
1168
+ else if (startedAt || finishedAt) {
1169
+ entries.push({ label: 'Time', value: startedAt ?? finishedAt ?? '' });
1170
+ }
1171
+ return entries;
1172
+ }
1173
+ function ToolDetailMetadata({ hasDetailContent, item }) {
1174
+ const entries = getToolDetailMetadata(item);
1175
+ if (entries.length === 0)
1176
+ return null;
1177
+ return (_jsx("dl", { className: cn('flex flex-wrap gap-x-4 gap-y-1 text-xs', hasDetailContent && 'mb-3 border-b border-border/60 pb-2'), children: entries.map((entry) => (_jsxs("div", { className: "flex min-w-0 items-baseline gap-1.5", children: [_jsx("dt", { className: "shrink-0 text-muted", children: entry.label }), _jsx("dd", { className: "min-w-0 wrap-break-word font-medium text-foreground/80", children: entry.value })] }, entry.label))) }));
1178
+ }
818
1179
  function ToolDetailSection({ section }) {
819
1180
  const value = section.value;
820
1181
  const isPrimitive = typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean';
@@ -841,6 +1202,9 @@ function formatToolPrimaryText(item) {
841
1202
  }
842
1203
  function formatToolDetailCopyText(item) {
843
1204
  const parts = [getToolPanelTitle(item), formatToolPrimaryText(item)];
1205
+ const metadata = getToolDetailMetadata(item).map((entry) => `${entry.label}: ${entry.value}`);
1206
+ if (metadata.length > 0)
1207
+ parts.push(metadata.join('\n'));
844
1208
  if (item.text)
845
1209
  parts.push(item.text);
846
1210
  for (const section of item.sections) {
@@ -880,9 +1244,10 @@ async function copyTextToClipboard(text) {
880
1244
  }
881
1245
  }
882
1246
  function SummaryToolDetailPanel({ item }) {
883
- const copyText = formatToolDetailCopyText(item);
884
1247
  const commandText = item.kind === 'command' && item.command ? formatToolPrimaryText(item) : undefined;
885
1248
  const fallbackText = !commandText && item.sections.length === 0 ? item.text : undefined;
1249
+ const hasDetailContent = Boolean(commandText || fallbackText || item.sections.length);
1250
+ const copyText = formatToolDetailCopyText(item);
886
1251
  const [copyState, setCopyState] = useState('idle');
887
1252
  const copyResetRef = useRef(undefined);
888
1253
  useEffect(() => {
@@ -899,34 +1264,56 @@ function SummaryToolDetailPanel({ item }) {
899
1264
  copyResetRef.current = window.setTimeout(() => setCopyState('idle'), 2000);
900
1265
  });
901
1266
  };
902
- return (_jsxs("div", { className: "relative mt-2 rounded-lg border border-border/70 bg-mixer-muted/10 p-3 shadow-sm", children: [_jsx("div", { className: "absolute end-2 top-2", children: _jsx("button", { type: "button", className: cn('inline-flex size-7 shrink-0 items-center justify-center rounded-md text-muted opacity-70 transition', 'hover:bg-mixer-muted/20 hover:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring', copyState === 'copied' && 'text-success opacity-100', copyState === 'failed' && 'text-destructive opacity-100'), onClick: copyDetails, "aria-label": "Copy tool details", title: "Copy tool details", children: copyState === 'copied' ? _jsx(CheckCircle, { className: "size-4" }) : _jsx(CopyIcon, { className: "size-4" }) }) }), _jsxs("div", { className: "pe-7", children: [commandText ? (_jsx("pre", { className: "mb-3 whitespace-pre-wrap break-words font-mono text-sm leading-6 text-foreground/85", children: commandText })) : null, fallbackText ? (_jsx("div", { className: "mb-3 break-words text-sm leading-6 text-foreground/75", children: fallbackText })) : null, item.sections.length > 0 ? (_jsx("div", { className: "space-y-3", children: item.sections.map((section) => (_jsx(ToolDetailSection, { section: section }, section.key))) })) : null] }), copyState === 'failed' ? _jsx("div", { className: "mt-3 text-xs text-destructive", children: "Copy failed" }) : null] }));
1267
+ return (_jsxs("div", { className: "relative mt-2 rounded-lg border border-border/70 bg-mixer-muted/10 p-3 shadow-sm", children: [hasDetailContent ? (_jsx("div", { className: "absolute end-2 top-2", children: _jsx("button", { type: "button", className: cn('inline-flex size-7 shrink-0 items-center justify-center rounded-md text-muted opacity-70 transition', 'hover:bg-mixer-muted/20 hover:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring', copyState === 'copied' && 'text-success opacity-100', copyState === 'failed' && 'text-destructive opacity-100'), onClick: copyDetails, "aria-label": "Copy tool details", title: "Copy tool details", children: copyState === 'copied' ? _jsx(CheckCircle, { className: "size-4" }) : _jsx(CopyIcon, { className: "size-4" }) }) })) : null, _jsxs("div", { className: cn(hasDetailContent && 'pe-7'), children: [_jsx(ToolDetailMetadata, { item: item, hasDetailContent: hasDetailContent }), commandText ? (_jsx("pre", { className: "mb-3 whitespace-pre-wrap break-words font-mono text-sm leading-6 text-foreground/85", children: commandText })) : null, fallbackText ? (_jsx("div", { className: "mb-3 break-words text-sm leading-6 text-foreground/75", children: fallbackText })) : null, item.sections.length > 0 ? (_jsx("div", { className: "space-y-3", children: item.sections.map((section) => (_jsx(ToolDetailSection, { section: section }, section.key))) })) : null] }), copyState === 'failed' && hasDetailContent ? (_jsx("div", { className: "mt-3 text-xs text-destructive", children: "Copy failed" })) : null] }));
903
1268
  }
904
1269
  function SummaryToolTimelineItem({ item }) {
905
- const isAttention = item.status === 'error' || item.status === 'warning';
906
- const hasDetails = Boolean(item.command || item.text || item.sections.length);
1270
+ const isDecision = Boolean(item.decisionText);
1271
+ const isAttention = !isDecision && (item.status === 'error' || item.status === 'warning');
1272
+ const hasMetadata = getToolDetailMetadata(item).length > 0;
1273
+ const hasDetails = Boolean(item.command || item.text || item.sections.length || hasMetadata);
907
1274
  const [isExpanded, setIsExpanded] = useState(false);
908
- return (_jsxs("div", { className: "min-w-0", children: [_jsxs("button", { type: "button", className: cn('grid w-full grid-cols-[1.5rem_1fr_auto] gap-2 text-start outline-none transition-colors', 'focus-visible:text-foreground focus-visible:underline focus-visible:underline-offset-4', hasDetails ? 'cursor-pointer hover:text-foreground' : 'cursor-default'), onClick: () => hasDetails && setIsExpanded((current) => !current), "aria-expanded": hasDetails ? isExpanded : undefined, disabled: !hasDetails, children: [_jsx("span", { className: cn('flex size-5 items-center justify-center pt-0.5', isAttention ? 'text-attention' : 'text-muted'), children: _jsx(ToolDetailIcon, { kind: item.kind, status: item.status }) }), _jsxs("span", { className: "flex min-w-0 flex-wrap items-baseline gap-x-2 gap-y-0.5", children: [_jsx("span", { className: "text-sm font-medium text-muted", children: item.label }), _jsx("span", { className: "min-w-0 break-words text-sm text-muted", children: item.title })] }), hasDetails ? (_jsx(ChevronDown, { className: cn('mt-0.5 size-4 shrink-0 text-muted opacity-50 transition-transform', !isExpanded && '-rotate-90'), "aria-hidden": "true" })) : null] }), hasDetails && isExpanded ? (_jsx("div", { className: "mt-1", children: _jsx(SummaryToolDetailPanel, { item: item }) })) : null] }));
1275
+ const iconStatus = isDecision ? undefined : item.status;
1276
+ return (_jsxs("div", { className: "min-w-0", children: [_jsxs("button", { type: "button", className: cn('grid w-full grid-cols-[1.5rem_1fr_auto] gap-2 text-start outline-none transition-colors', 'focus-visible:text-foreground focus-visible:underline focus-visible:underline-offset-4', hasDetails ? 'cursor-pointer hover:text-foreground' : 'cursor-default'), onClick: () => hasDetails && setIsExpanded((current) => !current), "aria-expanded": hasDetails ? isExpanded : undefined, disabled: !hasDetails, children: [_jsx("span", { className: cn('flex size-5 items-center justify-center pt-0.5', isAttention ? 'text-attention' : 'text-muted'), children: _jsx(ToolDetailIcon, { kind: item.kind, status: iconStatus }) }), _jsxs("span", { className: "min-w-0 text-sm text-muted", children: [_jsx("span", { className: "break-words", children: item.title }), item.decisionText ? (_jsx(Badge, { variant: "destructive", className: "ms-2 rounded-full shadow-sm shadow-destructive/10", children: item.decisionText })) : null] }), hasDetails ? (_jsx(ChevronDown, { className: cn('mt-0.5 size-4 shrink-0 text-muted opacity-50 transition-transform', !isExpanded && '-rotate-90'), "aria-hidden": "true" })) : null] }), hasDetails && isExpanded ? (_jsx("div", { className: "mt-1", children: _jsx(SummaryToolDetailPanel, { item: item }) })) : null] }));
909
1277
  }
910
- function SummaryThoughtTimelineItem({ item, artifactRunId }) {
1278
+ function SummaryThoughtProseItem({ item, artifactRunId, disableCollapse, }) {
1279
+ const { t } = useUITranslation();
911
1280
  const text = item.text ?? item.title;
912
- return (_jsx("div", { className: "min-w-0 py-1 text-sm leading-6 text-foreground/85", children: _jsx("div", { className: SUMMARY_PROSE_CLASS, style: { overflowWrap: 'anywhere' }, children: _jsx(MarkdownRenderer, { artifactRunId: artifactRunId, components: DEFAULT_AGENT_MARKDOWN_COMPONENTS, children: text }) }) }));
913
- }
914
- function SummaryToolTimeline({ items, artifactRunId }) {
915
- return (_jsx("div", { className: "mt-3", children: _jsx("div", { className: "space-y-3", children: items.map((item) => item.kind === 'think' ? (_jsx(SummaryThoughtTimelineItem, { item: item, artifactRunId: artifactRunId }, item.key)) : (_jsx(SummaryToolTimelineItem, { item: item }, item.key))) }) }));
1281
+ const normalizedText = text.trim();
1282
+ const [isExpanded, setIsExpanded] = useState(false);
1283
+ const explicitLineCount = normalizedText ? normalizedText.split(/\r?\n/).length : 0;
1284
+ const isLong = normalizedText.length > SUMMARY_THOUGHT_COLLAPSE_THRESHOLD ||
1285
+ explicitLineCount > SUMMARY_THOUGHT_COLLAPSE_LINES;
1286
+ const toggleLabel = isExpanded ? t('agent.showLess') : t('agent.showMore');
1287
+ return (_jsxs("div", { className: "min-w-0 py-1", children: [_jsx("div", { "data-testid": "summary-thought-prose", className: cn(SUMMARY_PROSE_CLASS, isLong &&
1288
+ !disableCollapse &&
1289
+ !isExpanded &&
1290
+ '[display:-webkit-box] overflow-hidden [-webkit-box-orient:vertical] [-webkit-line-clamp:6]'), style: { overflowWrap: 'anywhere' }, children: _jsx(MarkdownRenderer, { artifactRunId: artifactRunId, components: DEFAULT_AGENT_MARKDOWN_COMPONENTS, children: text }) }), isLong && !disableCollapse ? (_jsx("div", { className: "mt-1.5 flex justify-end", children: _jsxs("button", { type: "button", "aria-expanded": isExpanded, className: cn('inline-flex items-center gap-1 text-sm font-medium text-muted transition-colors', '[text-decoration:none] hover:text-foreground hover:[text-decoration:none]', 'focus-visible:text-foreground focus-visible:[text-decoration:none]', 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring'), onClick: () => setIsExpanded((current) => !current), children: [toggleLabel, _jsx(ChevronDown, { className: cn('size-4 transition-transform', isExpanded && 'rotate-180'), "aria-hidden": "true" })] }) })) : null] }));
1291
+ }
1292
+ function SummaryToolTimeline({ items, artifactRunId, disablePreambleCollapse, }) {
1293
+ return (_jsx("div", { className: "mt-3", children: _jsx("div", { className: "space-y-3", children: items.map((item) => item.isPreamble || item.kind === 'think' ? (_jsx(SummaryThoughtProseItem, { item: item, artifactRunId: artifactRunId, disableCollapse: disablePreambleCollapse }, item.key)) : (_jsx(SummaryToolTimelineItem, { item: item }, item.key))) }) }));
916
1294
  }
917
1295
  function SummaryStreamingMessage({ text, artifactRunId, workstreamId, }) {
918
1296
  return (_jsx("div", { className: "mx-auto w-full max-w-3xl px-1", "data-workstream-id": workstreamId, children: _jsx("div", { className: SUMMARY_PROSE_CLASS, style: { overflowWrap: 'anywhere' }, children: _jsx(MarkdownRenderer, { artifactRunId: artifactRunId, components: DEFAULT_AGENT_MARKDOWN_COMPONENTS, children: text }) }) }));
919
1297
  }
920
- function SummaryActivityRow({ label, status, timestamp, durationSeconds, showElapsed, details, emptyDetailsLabel, defaultExpanded = false, className, artifactRunId, }) {
1298
+ function SummaryStoppedMessage({ message, startTimestamp, endTimestamp, className, }) {
1299
+ const { t } = useUITranslation();
1300
+ const duration = formatDuration(getDurationSeconds(startTimestamp ?? message.timestamp, endTimestamp ?? message.timestamp));
1301
+ return (_jsxs("div", { className: cn('mx-auto w-full max-w-3xl px-1', className), "data-testid": "summary-stopped-message", children: [_jsxs("div", { className: "flex items-center justify-end gap-2 text-lg font-medium text-muted sm:text-xl", children: [_jsx("span", { children: t('agent.youStoppedAfter', { duration }) }), _jsx(MessageDeliveryStatus, { message: message, className: "h-5 w-5" })] }), _jsx("div", { className: "mt-5 border-b border-border/70" })] }));
1302
+ }
1303
+ function SummaryActivityRow({ label, timestamp, durationSeconds, showElapsed, details, emptyDetailsLabel, defaultExpanded = false, disablePreambleCollapse = false, className, artifactRunId, onSendMessage, answeredToolApprovalRequestInputKeys, resolvedToolApprovalKeys, }) {
921
1304
  const [isExpanded, setIsExpanded] = useState(defaultExpanded);
922
1305
  const isLiveElapsed = showElapsed && durationSeconds === undefined;
923
1306
  const liveElapsed = useLiveElapsedSeconds(timestamp, isLiveElapsed);
924
1307
  const elapsed = durationSeconds ?? liveElapsed;
925
1308
  const shouldShowElapsed = showElapsed && timestamp !== undefined;
926
- const isAttention = status === 'error' || status === 'warning';
927
1309
  const detailItems = useMemo(() => buildSummaryToolDetailItems(details ?? []), [details]);
928
- const canExpand = detailItems.length > 0 || Boolean(emptyDetailsLabel);
929
- return (_jsx("div", { className: cn('mx-auto w-full max-w-3xl px-1', className), children: _jsxs("div", { className: cn('border-b border-border/70 pb-3 text-sm', isAttention ? 'text-attention' : 'text-muted'), children: [_jsxs("button", { type: "button", className: cn('inline-flex max-w-full items-center gap-2 text-start outline-none', 'focus-visible:text-foreground focus-visible:underline focus-visible:underline-offset-4', canExpand ? 'cursor-pointer hover:text-foreground' : 'cursor-default'), onClick: () => canExpand && setIsExpanded((current) => !current), "aria-expanded": canExpand ? isExpanded : undefined, disabled: !canExpand, children: [_jsx("span", { className: "min-w-0 truncate font-medium", children: label }), shouldShowElapsed ? (_jsxs("span", { className: "shrink-0 text-muted/75", children: ["for ", formatDuration(elapsed)] })) : null, canExpand ? (isExpanded ? (_jsx(ChevronDown, { className: "size-4 shrink-0 opacity-50" })) : (_jsx(ChevronRight, { className: "size-4 shrink-0 opacity-50" }))) : null] }), canExpand && isExpanded ? (detailItems.length > 0 ? (_jsx(SummaryToolTimeline, { items: detailItems, artifactRunId: artifactRunId })) : (_jsxs("div", { className: "mt-3 flex items-center gap-2 text-sm text-muted", children: [_jsx(Terminal, { className: "size-4 opacity-70", "aria-hidden": "true" }), _jsx("span", { children: emptyDetailsLabel })] }))) : null] }) }));
1310
+ const requestInputMessages = useMemo(() => (details ?? []).filter((message) => hasRequestInputUx(message) &&
1311
+ !isToolApprovalRequestInputHidden(message, answeredToolApprovalRequestInputKeys ?? new Set(), resolvedToolApprovalKeys ?? new Set())), [answeredToolApprovalRequestInputKeys, details, resolvedToolApprovalKeys]);
1312
+ const canExpand = detailItems.length > 0 || requestInputMessages.length > 0 || Boolean(emptyDetailsLabel);
1313
+ return (_jsx("div", { className: cn('mx-auto w-full max-w-3xl px-1', className), children: _jsxs("div", { className: "border-b border-border/70 pb-3 text-sm text-muted", children: [_jsxs("button", { type: "button", className: cn('inline-flex max-w-full items-center gap-2 text-start outline-none', 'focus-visible:text-foreground focus-visible:underline focus-visible:underline-offset-4', canExpand ? 'cursor-pointer hover:text-foreground' : 'cursor-default'), onClick: () => canExpand && setIsExpanded((current) => !current), "aria-expanded": canExpand ? isExpanded : undefined, disabled: !canExpand, children: [_jsx("span", { className: "min-w-0 truncate font-medium", children: label }), shouldShowElapsed ? (_jsxs("span", { className: "shrink-0 text-muted/75", children: ["for ", formatDuration(elapsed)] })) : null, canExpand ? (isExpanded ? (_jsx(ChevronDown, { className: "size-4 shrink-0 opacity-50" })) : (_jsx(ChevronRight, { className: "size-4 shrink-0 opacity-50" }))) : null] }), canExpand && isExpanded ? (detailItems.length > 0 || requestInputMessages.length > 0 ? (_jsxs(_Fragment, { children: [detailItems.length > 0 ? (_jsx(SummaryToolTimeline, { items: detailItems, artifactRunId: artifactRunId, disablePreambleCollapse: disablePreambleCollapse })) : null, requestInputMessages.length > 0 ? (_jsx("div", { className: "mt-3 space-y-3", children: requestInputMessages.map((message) => {
1314
+ const uxConfig = message.details.ux;
1315
+ return (_jsx(AskUserWidget, { question: getRequestInputDisplayText(message), options: uxConfig.options, variant: uxConfig.variant, multiSelect: uxConfig.multiSelect, onSelect: (optionId) => onSendMessage?.(optionId), onMultiSelect: (optionIds) => onSendMessage?.(optionIds.join(', ')), allowFreeResponse: !uxConfig.options?.length || !!uxConfig.free_response, placeholder: uxConfig.free_response?.placeholder, submitLabel: uxConfig.free_response?.submit_label, onSubmit: (value) => onSendMessage?.(value, uxConfig.free_response?.metadata), hideBorder: true, compact: true, className: "my-0", cardClassName: "bg-background/60 shadow-none" }, getAgentMessageRenderKey(message, 'work-request-input')));
1316
+ }) })) : null] })) : (_jsxs("div", { className: "mt-3 flex items-center gap-2 text-sm text-muted", children: [_jsx(Terminal, { className: "size-4 opacity-70", "aria-hidden": "true" }), _jsx("span", { children: emptyDetailsLabel })] }))) : null] }) }));
930
1317
  }
931
1318
  function TimelineEntry({ children, status }) {
932
1319
  const dotClass = status === 'error'
@@ -966,13 +1353,20 @@ class MessageErrorBoundary extends Component {
966
1353
  }
967
1354
  // PERFORMANCE: Throttle interval for auto-scroll (ms)
968
1355
  const SCROLL_THROTTLE_MS = 100; // Max 10 scrolls per second
969
- function AllMessagesMixedComponent({ messages, bottomRef, viewMode = 'stacked', isCompleted = false, streamingMessages = new Map(), onSendMessage, messageItemClassNames, messageStyleOverrides, toolCallGroupClassNames, hideToolCallsInViewMode, streamingMessageClassNames, batchProgressPanelClassNames, artifactRunId, hideWorkstreamTabs, workingIndicatorClassName, messageListClassName, StoreLinkComponent, CollectionLinkComponent, prependFriendlyMessage, initialRequestData, initialRequestSchema, initialRequestTitle, initialRequestTemplate, hiddenMessageTypes, disableAutoScroll = false, renderRequestInputControls = true, }) {
1356
+ function AllMessagesMixedComponent({ messages, bottomRef, viewMode = 'stacked', isCompleted = false, streamingMessages = new Map(), onSendMessage, messageItemClassNames, messageStyleOverrides, toolCallGroupClassNames, hideToolCallsInViewMode, streamingMessageClassNames, batchProgressPanelClassNames, artifactRunId, hideWorkstreamTabs, workingIndicatorClassName, messageListClassName, StoreLinkComponent, CollectionLinkComponent, prependFriendlyMessage, initialRequestData, initialRequestSchema, initialRequestTitle, initialRequestTemplate, showInitialRequest, hiddenMessageTypes, disableAutoScroll = false, renderRequestInputControls = true, activeWorkstream: controlledActiveWorkstream, onActiveWorkstreamChange, }) {
970
1357
  if (!artifactRunId) {
971
1358
  console.warn('[AllMessagesMixed] artifactRunId prop is missing!');
972
1359
  }
973
1360
  const { t } = useUITranslation();
974
1361
  const containerRef = useRef(null);
975
- const [activeWorkstream, setActiveWorkstream] = useState('all');
1362
+ const [internalActiveWorkstream, setInternalActiveWorkstream] = useState('all');
1363
+ const activeWorkstream = controlledActiveWorkstream ?? internalActiveWorkstream;
1364
+ const setActiveWorkstream = useCallback((workstreamId) => {
1365
+ if (controlledActiveWorkstream === undefined) {
1366
+ setInternalActiveWorkstream(workstreamId);
1367
+ }
1368
+ onActiveWorkstreamChange?.(workstreamId);
1369
+ }, [controlledActiveWorkstream, onActiveWorkstreamChange]);
976
1370
  // PERFORMANCE: Throttle auto-scroll to prevent layout thrashing
977
1371
  // During streaming, scrollIntoView was being called 30+ times/sec
978
1372
  const lastScrollTimeRef = useRef(0);
@@ -1058,9 +1452,7 @@ function AllMessagesMixedComponent({ messages, bottomRef, viewMode = 'stacked',
1058
1452
  // Sort all messages chronologically and dedupe adjacent identical messages
1059
1453
  // Low-signal messages are suppressed at the source (server-side) via shouldSuppressLowSignalMessage
1060
1454
  const sortedMessages = React.useMemo(() => {
1061
- const filtered = hiddenMessageTypes?.length
1062
- ? messages.filter((m) => !hiddenMessageTypes.includes(m.type))
1063
- : messages;
1455
+ const filtered = messages.filter((message) => !isDocumentPanelEventMessage(message) && !hiddenMessageTypes?.includes(message.type));
1064
1456
  const sorted = [...filtered].sort((a, b) => {
1065
1457
  const timeA = typeof a.timestamp === 'number' ? a.timestamp : new Date(a.timestamp).getTime();
1066
1458
  const timeB = typeof b.timestamp === 'number' ? b.timestamp : new Date(b.timestamp).getTime();
@@ -1079,14 +1471,49 @@ function AllMessagesMixedComponent({ messages, bottomRef, viewMode = 'stacked',
1079
1471
  }
1080
1472
  return deduped;
1081
1473
  }, [messages, hiddenMessageTypes]);
1082
- // Get workstreams from messages - only from message.workstream_id
1083
1474
  const workstreams = React.useMemo(() => {
1084
- // Just get the basic workstreams from the messages
1085
1475
  const extractedWorkstreams = extractWorkstreams(sortedMessages);
1086
- // We'll keep taskLabels - they might be used for display purposes elsewhere
1087
- // but we won't use them to create new workstream tabs
1476
+ sortedMessages.forEach((message) => {
1477
+ const details = getWorkstreamLaunchDetails(message) ?? getWorkstreamActivityDetails(message);
1478
+ if (!details)
1479
+ return;
1480
+ extractedWorkstreams.set(details.workstreamId, getWorkstreamDisplayName(details.workstreamId, details.interaction));
1481
+ });
1088
1482
  return extractedWorkstreams;
1089
1483
  }, [sortedMessages]);
1484
+ const activeWorkstreamName = React.useMemo(() => {
1485
+ if (activeWorkstream === 'all')
1486
+ return undefined;
1487
+ return workstreams.get(activeWorkstream) ?? formatWorkstreamName(activeWorkstream);
1488
+ }, [activeWorkstream, workstreams]);
1489
+ const scrollToTop = useCallback(() => {
1490
+ const container = containerRef.current;
1491
+ if (!container)
1492
+ return;
1493
+ programmaticScrollRef.current = true;
1494
+ if (typeof container.scrollTo === 'function') {
1495
+ container.scrollTo({ top: 0, behavior: 'smooth' });
1496
+ }
1497
+ else {
1498
+ container.scrollTop = 0;
1499
+ }
1500
+ requestAnimationFrame(() => {
1501
+ programmaticScrollRef.current = false;
1502
+ });
1503
+ }, []);
1504
+ const handleSelectWorkstream = useCallback((workstreamId) => {
1505
+ setActiveWorkstream(workstreamId);
1506
+ requestAnimationFrame(scrollToTop);
1507
+ }, [scrollToTop, setActiveWorkstream]);
1508
+ const handleShowMainAgentChat = useCallback(() => {
1509
+ setActiveWorkstream('all');
1510
+ requestAnimationFrame(scrollToTop);
1511
+ }, [scrollToTop, setActiveWorkstream]);
1512
+ useEffect(() => {
1513
+ if (activeWorkstream !== 'all' && !workstreams.has(activeWorkstream)) {
1514
+ setActiveWorkstream('all');
1515
+ }
1516
+ }, [activeWorkstream, workstreams, setActiveWorkstream]);
1090
1517
  // Count messages per workstream
1091
1518
  const workstreamCounts = React.useMemo(() => {
1092
1519
  const counts = new Map();
@@ -1105,12 +1532,12 @@ function AllMessagesMixedComponent({ messages, bottomRef, viewMode = 'stacked',
1105
1532
  }, [sortedMessages]);
1106
1533
  // Filter messages based on active workstream
1107
1534
  const displayMessages = React.useMemo(() => {
1108
- if (activeWorkstream === 'all') {
1109
- return sortedMessages;
1110
- }
1111
- return filterMessagesByWorkstream(sortedMessages, activeWorkstream);
1535
+ return attachWriteArtifactCompletionMessages(filterMessagesForActiveWorkstream(sortedMessages, activeWorkstream));
1112
1536
  }, [sortedMessages, activeWorkstream]);
1113
1537
  const answeredRequestInputKeys = React.useMemo(() => getAnsweredRequestInputKeys(displayMessages), [displayMessages]);
1538
+ const resolvedToolApprovalKeys = React.useMemo(() => getResolvedToolApprovalKeys(displayMessages), [displayMessages]);
1539
+ const answeredToolApprovalRequestInputKeys = React.useMemo(() => getAnsweredToolApprovalRequestInputKeys(displayMessages), [displayMessages]);
1540
+ const hiddenToolApprovalAnswerKeys = React.useMemo(() => getHiddenToolApprovalAnswerKeys(displayMessages), [displayMessages]);
1114
1541
  const externallyRenderedRequestInputKey = React.useMemo(() => {
1115
1542
  if (renderRequestInputControls)
1116
1543
  return undefined;
@@ -1118,13 +1545,18 @@ function AllMessagesMixedComponent({ messages, bottomRef, viewMode = 'stacked',
1118
1545
  return pendingRequestInput ? getRequestInputMessageKey(pendingRequestInput) : undefined;
1119
1546
  }, [displayMessages, renderRequestInputControls]);
1120
1547
  const shouldHideRequestInputMessage = React.useCallback((message) => message.type === AgentMessageType.REQUEST_INPUT &&
1121
- externallyRenderedRequestInputKey === getRequestInputMessageKey(message), [externallyRenderedRequestInputKey]);
1548
+ (externallyRenderedRequestInputKey === getRequestInputMessageKey(message) ||
1549
+ isToolApprovalRequestInputHidden(message, answeredToolApprovalRequestInputKeys, resolvedToolApprovalKeys)), [answeredToolApprovalRequestInputKeys, externallyRenderedRequestInputKey, resolvedToolApprovalKeys]);
1550
+ const shouldHideToolApprovalAnswerMessage = React.useCallback((message) => isToolApprovalAnswerHidden(message, hiddenToolApprovalAnswerKeys), [hiddenToolApprovalAnswerKeys]);
1551
+ const completionDisplayMessages = React.useMemo(() => displayMessages.filter((message) => !shouldHideToolApprovalAnswerMessage(message)), [displayMessages, shouldHideToolApprovalAnswerMessage]);
1122
1552
  const fallbackWorkingStartedAtRef = useRef(Date.now());
1123
1553
  const hasInitialRequest = Boolean(prependFriendlyMessage?.trim()) ||
1124
1554
  hasInitialRequestValue(initialRequestData) ||
1125
1555
  initialRequestTemplate !== undefined;
1556
+ const canRenderInitialRequest = showInitialRequest ?? true;
1557
+ const hasRenderableInitialRequest = hasInitialRequest && canRenderInitialRequest;
1126
1558
  const hasPersistedUserQuestion = useMemo(() => displayMessages.some((message) => message.type === AgentMessageType.QUESTION), [displayMessages]);
1127
- const shouldRenderInitialRequest = hasInitialRequest && !hasPersistedUserQuestion;
1559
+ const shouldRenderInitialRequest = activeWorkstream === 'all' && hasRenderableInitialRequest && !hasPersistedUserQuestion;
1128
1560
  const latestDisplayMessageTimestamp = useMemo(() => {
1129
1561
  return displayMessages.reduce((latest, msg) => Math.max(latest, getTimestampMs(msg.timestamp)), -Infinity);
1130
1562
  }, [displayMessages]);
@@ -1135,11 +1567,18 @@ function AllMessagesMixedComponent({ messages, bottomRef, viewMode = 'stacked',
1135
1567
  return Math.max(latest, getTimestampMs(msg.timestamp));
1136
1568
  }, -Infinity);
1137
1569
  }, [displayMessages]);
1570
+ const hasPendingToolApprovalRequest = useMemo(() => displayMessages.some((message) => isToolApprovalRequestInput(message) &&
1571
+ !isToolApprovalRequestInputHidden(message, answeredToolApprovalRequestInputKeys, resolvedToolApprovalKeys)), [answeredToolApprovalRequestInputKeys, displayMessages, resolvedToolApprovalKeys]);
1572
+ const hasLatestToolApprovalAllow = useMemo(() => hasLatestToolApprovalAllowTurn(displayMessages, hiddenToolApprovalAnswerKeys), [displayMessages, hiddenToolApprovalAnswerKeys]);
1138
1573
  const isDisplayCompleted = useMemo(() => {
1139
- if (hasOpenUserTurn(displayMessages))
1574
+ if (hasPendingToolApprovalRequest)
1575
+ return false;
1576
+ if (hasLatestToolApprovalAllow)
1140
1577
  return false;
1141
- return isCompleted || !isInProgress(displayMessages);
1142
- }, [displayMessages, isCompleted]);
1578
+ if (hasOpenUserTurn(completionDisplayMessages))
1579
+ return false;
1580
+ return isCompleted || !isInProgress(completionDisplayMessages);
1581
+ }, [completionDisplayMessages, hasLatestToolApprovalAllow, hasPendingToolApprovalRequest, isCompleted]);
1143
1582
  // Split streaming messages:
1144
1583
  // - complete (or stale incomplete) ones are interleaved chronologically
1145
1584
  // - actively incomplete ones render at the end
@@ -1171,7 +1610,8 @@ function AllMessagesMixedComponent({ messages, bottomRef, viewMode = 'stacked',
1171
1610
  });
1172
1611
  return { completeStreaming: complete, incompleteStreaming: incomplete };
1173
1612
  }, [streamingMessages, activeWorkstream, latestNonTransientDisplayMessageTimestamp]);
1174
- const summaryDisplayMessages = React.useMemo(() => buildSummaryDisplayMessages(displayMessages, completeStreaming), [displayMessages, completeStreaming]);
1613
+ const summaryDisplayMessages = React.useMemo(() => buildSyntheticToolApprovalDecisionMessages(buildSummaryDisplayMessages(displayMessages, completeStreaming), resolvedToolApprovalKeys), [displayMessages, completeStreaming, resolvedToolApprovalKeys]);
1614
+ const visibleSummaryDisplayMessages = React.useMemo(() => summaryDisplayMessages.filter((message) => !shouldHideRequestInputMessage(message) && !shouldHideToolApprovalAnswerMessage(message)), [summaryDisplayMessages, shouldHideRequestInputMessage, shouldHideToolApprovalAnswerMessage]);
1175
1615
  const latestSummaryObservedTimestamp = useMemo(() => {
1176
1616
  const hasVisibleLiveStream = incompleteStreaming.some(({ data }) => data.text.trim().length > 0);
1177
1617
  if (hasVisibleLiveStream)
@@ -1179,7 +1619,7 @@ function AllMessagesMixedComponent({ messages, bottomRef, viewMode = 'stacked',
1179
1619
  const latestStreamingTimestamp = incompleteStreaming.reduce((latest, { data }) => Math.max(latest, data.startTimestamp), -Infinity);
1180
1620
  return Math.max(latestDisplayMessageTimestamp, latestStreamingTimestamp);
1181
1621
  }, [incompleteStreaming, latestDisplayMessageTimestamp]);
1182
- const summaryConversationItems = React.useMemo(() => buildSummaryConversationItems(summaryDisplayMessages, isDisplayCompleted, latestSummaryObservedTimestamp), [summaryDisplayMessages, isDisplayCompleted, latestSummaryObservedTimestamp]);
1622
+ const summaryConversationItems = React.useMemo(() => buildSummaryConversationItems(visibleSummaryDisplayMessages, isDisplayCompleted, latestSummaryObservedTimestamp), [visibleSummaryDisplayMessages, isDisplayCompleted, latestSummaryObservedTimestamp]);
1183
1623
  // Group messages with ONLY complete streaming interleaved for stacked view.
1184
1624
  // Incomplete streaming is rendered separately at the end (avoids re-grouping on every chunk).
1185
1625
  // Assistant prose stays as its own timeline item so thoughts remain visible between tool calls.
@@ -1187,14 +1627,21 @@ function AllMessagesMixedComponent({ messages, bottomRef, viewMode = 'stacked',
1187
1627
  // Show an activity indicator when the latest visible conversation state is not terminal.
1188
1628
  // Older idle/complete messages from previous turns must not suppress the new turn.
1189
1629
  const isAgentWorking = useMemo(() => {
1190
- return !isDisplayCompleted;
1191
- }, [isDisplayCompleted]);
1630
+ // Also treat an open user turn (the latest message is the user's, awaiting the agent's
1631
+ // first output) as "working" — otherwise nothing animates in the gap between sending a
1632
+ // message and the first streamed token, especially after a stop where the run reads as
1633
+ // completed until the agent posts its next message.
1634
+ return !isDisplayCompleted || hasOpenUserTurn(completionDisplayMessages);
1635
+ }, [completionDisplayMessages, isDisplayCompleted]);
1192
1636
  const showActivityFallback = shouldShowSummaryActivityFallback(summaryConversationItems, isAgentWorking, incompleteStreaming.length > 0);
1193
1637
  const summaryActivityFallbackLabel = isInitialSummaryActivityFallback(summaryConversationItems)
1194
1638
  ? t('agent.preparing')
1195
1639
  : t('agent.working');
1196
- const showInitialRequestWaitingCard = displayMessages.length === 0 && hasInitialRequest && isAgentWorking && incompleteStreaming.length === 0;
1197
- const activityAnchorCandidate = useMemo(() => getSummaryActivityAnchorTimestamp(summaryConversationItems, summaryDisplayMessages, fallbackWorkingStartedAtRef.current), [summaryConversationItems, summaryDisplayMessages]);
1640
+ const showInitialRequestWaitingCard = displayMessages.length === 0 &&
1641
+ hasRenderableInitialRequest &&
1642
+ isAgentWorking &&
1643
+ incompleteStreaming.length === 0;
1644
+ const activityAnchorCandidate = useMemo(() => getSummaryActivityAnchorTimestamp(summaryConversationItems, visibleSummaryDisplayMessages, fallbackWorkingStartedAtRef.current), [summaryConversationItems, visibleSummaryDisplayMessages]);
1198
1645
  const activityStartedTimestampRef = useRef(activityAnchorCandidate);
1199
1646
  const wasActivityFallbackVisibleRef = useRef(false);
1200
1647
  const activityStartedTimestamp = useMemo(() => {
@@ -1504,9 +1951,11 @@ function AllMessagesMixedComponent({ messages, bottomRef, viewMode = 'stacked',
1504
1951
  .agent-markdown tbody tr:hover {
1505
1952
  background: transparent;
1506
1953
  }
1507
- ` }), viewMode === 'stacked' && (_jsx("div", { className: cn('sticky top-0 z-10', hideWorkstreamTabs && 'hidden'), children: _jsx(WorkstreamTabs, { workstreams: workstreams, activeWorkstream: activeWorkstream, onSelectWorkstream: setActiveWorkstream, count: workstreamCounts, completionStatus: workstreamCompletionStatus }) })), displayMessages.length === 0 && !hasInitialRequest && !(isSummaryView && showActivityFallback) ? (activeWorkstream === 'all' && isAgentWorking && incompleteStreaming.length === 0 ? (_jsx("div", { className: "flex-1 px-2 py-6 sm:px-4", children: _jsx(InitialRequestWaitingCard, { label: t('agent.preparing'), timestamp: fallbackWorkingStartedAtRef.current, className: workingIndicatorClassName }) })) : (_jsx("div", { className: "flex items-center justify-center h-full text-center py-8", children: _jsx("div", { className: "flex items-center px-3 py-2 text-sm text-muted", children: activeWorkstream === 'all'
1954
+ ` }), viewMode === 'stacked' && (_jsx("div", { className: cn('sticky top-0 z-10', hideWorkstreamTabs && 'hidden'), children: _jsx(WorkstreamTabs, { workstreams: workstreams, activeWorkstream: activeWorkstream, onSelectWorkstream: handleSelectWorkstream, count: workstreamCounts, completionStatus: workstreamCompletionStatus }) })), displayMessages.length === 0 &&
1955
+ !hasRenderableInitialRequest &&
1956
+ !(isSummaryView && showActivityFallback) ? (activeWorkstream === 'all' && isAgentWorking && incompleteStreaming.length === 0 ? (_jsx("div", { className: "flex-1 px-2 py-6 sm:px-4", children: _jsx(InitialRequestWaitingCard, { label: t('agent.preparing'), timestamp: fallbackWorkingStartedAtRef.current, className: workingIndicatorClassName }) })) : (_jsx("div", { className: "flex items-center justify-center h-full text-center py-8", children: _jsx("div", { className: "flex items-center px-3 py-2 text-sm text-muted", children: activeWorkstream === 'all'
1508
1957
  ? t('agent.waitingForAgentResponse')
1509
- : t('agent.noMessagesInWorkstream') }) }))) : (_jsxs("div", { className: cn('flex-1 flex flex-col justify-start w-full max-w-full', isSummaryView ? 'gap-6 px-2 py-6 sm:px-4' : 'gap-3 pb-4', messageListClassName), children: [shouldRenderInitialRequest && (_jsx(InitialRequestMessage, { data: initialRequestData, schema: initialRequestSchema, title: initialRequestTitle, template: initialRequestTemplate, prependFriendlyMessage: prependFriendlyMessage, timestamp: displayMessages[0]?.timestamp ?? Date.now(), isSummaryView: isSummaryView, messageItemClassNames: messageItemClassNames, messageStyleOverrides: messageStyleOverrides, StoreLinkComponent: StoreLinkComponent, CollectionLinkComponent: CollectionLinkComponent }, "initial-request")), showInitialRequestWaitingCard && (_jsx(InitialRequestWaitingCard, { label: summaryActivityFallbackLabel, timestamp: activityStartedTimestamp, className: workingIndicatorClassName })), viewMode === 'stacked' ? (_jsxs(_Fragment, { children: [groupedMessages.map((group, groupIndex) => {
1958
+ : t('agent.noMessagesInWorkstream') }) }))) : (_jsxs("div", { className: cn('flex-1 flex flex-col justify-start w-full max-w-full', isSummaryView ? 'gap-6 px-2 py-6 sm:px-4' : 'gap-3 pb-4', messageListClassName), children: [isSummaryView && activeWorkstream !== 'all' && activeWorkstreamName && (_jsx("div", { className: "sticky top-0 z-20 -mx-2 bg-background/95 px-2 pb-2 pt-1 backdrop-blur sm:-mx-4 sm:px-4", children: _jsxs("div", { className: "mx-auto flex w-full max-w-3xl items-center gap-2 border-b border-border/70 pb-3", children: [_jsx(VTooltip, { description: t('agent.backToMainAgent'), asChild: true, children: _jsx(Button, { type: "button", variant: "ghost", size: "icon", className: "size-8 shrink-0 text-muted hover:text-foreground", "aria-label": t('agent.backToMainAgent'), onClick: handleShowMainAgentChat, children: _jsx(ArrowLeft, { className: "size-4", "aria-hidden": "true" }) }) }), _jsx("div", { className: "min-w-0 flex-1 truncate text-sm font-medium text-foreground", children: activeWorkstreamName })] }) })), shouldRenderInitialRequest && (_jsx(InitialRequestMessage, { data: initialRequestData, schema: initialRequestSchema, title: initialRequestTitle, template: initialRequestTemplate, prependFriendlyMessage: prependFriendlyMessage, timestamp: displayMessages[0]?.timestamp ?? Date.now(), isSummaryView: isSummaryView, messageItemClassNames: messageItemClassNames, messageStyleOverrides: messageStyleOverrides, StoreLinkComponent: StoreLinkComponent, CollectionLinkComponent: CollectionLinkComponent }, "initial-request")), showInitialRequestWaitingCard && (_jsx(InitialRequestWaitingCard, { label: summaryActivityFallbackLabel, timestamp: activityStartedTimestamp, className: workingIndicatorClassName })), viewMode === 'stacked' ? (_jsxs(_Fragment, { children: [groupedMessages.map((group, groupIndex) => {
1510
1959
  const isLastGroup = groupIndex === groupedMessages.length - 1;
1511
1960
  if (group.type === 'tool_group') {
1512
1961
  // Render grouped tool calls
@@ -1531,6 +1980,11 @@ function AllMessagesMixedComponent({ messages, bottomRef, viewMode = 'stacked',
1531
1980
  const message = group.message;
1532
1981
  if (shouldHideRequestInputMessage(message))
1533
1982
  return null;
1983
+ if (shouldHideToolApprovalAnswerMessage(message))
1984
+ return null;
1985
+ if (isUserStoppedMessage(message)) {
1986
+ return (_jsx(TimelineEntry, { children: _jsx(SummaryStoppedMessage, { message: message, startTimestamp: getPreviousRenderableGroupTimestamp(groupedMessages, groupIndex) ?? message.timestamp, endTimestamp: message.timestamp }) }, getAgentMessageRenderKey(message, 'stopped')));
1987
+ }
1534
1988
  const isLatestMessage = !isCompleted && isLastGroup && !DONE_STATES.includes(message.type);
1535
1989
  // Special handling for batch progress messages
1536
1990
  if (isBatchProgressMessage(message)) {
@@ -1543,17 +1997,22 @@ function AllMessagesMixedComponent({ messages, bottomRef, viewMode = 'stacked',
1543
1997
  if (hideToolCallsInViewMode?.includes(viewMode))
1544
1998
  return null;
1545
1999
  const isThinkingOnlyWork = isTransientThinkingWork(item.messages);
1546
- return (_jsx(SummaryActivityRow, { label: getSummaryActivityLabel(item.status, item.isActive), status: item.status, timestamp: item.startTimestamp, durationSeconds: item.isActive
2000
+ return (_jsx(SummaryActivityRow, { label: getSummaryActivityLabel(item.isActive), status: item.status, timestamp: item.startTimestamp, durationSeconds: item.isActive
1547
2001
  ? undefined
1548
- : getDurationSeconds(item.startTimestamp, item.endTimestamp), showElapsed: true, details: isThinkingOnlyWork ? undefined : item.messages, defaultExpanded: item.isActive && !isThinkingOnlyWork, className: workingIndicatorClassName }, `work-${item.id}-${item.isActive ? 'active' : 'done'}-${item.status}`));
2002
+ : getDurationSeconds(item.startTimestamp, item.endTimestamp), showElapsed: true, details: isThinkingOnlyWork ? undefined : item.messages, defaultExpanded: item.isActive && !isThinkingOnlyWork, disablePreambleCollapse: item.isActive, className: workingIndicatorClassName, onSendMessage: onSendMessage, answeredToolApprovalRequestInputKeys: answeredToolApprovalRequestInputKeys, resolvedToolApprovalKeys: resolvedToolApprovalKeys }, `work-${item.id}-${item.isActive ? 'active' : 'done'}-${item.status}`));
2003
+ }
2004
+ if (item.type === 'stopped') {
2005
+ return (_jsx(SummaryStoppedMessage, { message: item.message, startTimestamp: item.startTimestamp, endTimestamp: item.endTimestamp }, getAgentMessageRenderKey(item.message, 'stopped-summary')));
1549
2006
  }
1550
2007
  const message = item.message;
1551
2008
  if (shouldHideRequestInputMessage(message))
1552
2009
  return null;
2010
+ if (shouldHideToolApprovalAnswerMessage(message))
2011
+ return null;
1553
2012
  if (isBatchProgressMessage(message)) {
1554
2013
  return (_jsx(MessageErrorBoundary, { children: _jsx(BatchProgressPanel, { message: message, batchData: message.details, isRunning: !message.details.completed_at, ...batchProgressPanelClassNames }) }, getAgentMessageRenderKey(message, 'batch')));
1555
2014
  }
1556
- return (_jsx(MessageErrorBoundary, { children: _jsx(SummaryMessage, { message: message, onSendMessage: onSendMessage, requestInputAnswered: isRequestInputAnswered(message, answeredRequestInputKeys), StoreLinkComponent: StoreLinkComponent, CollectionLinkComponent: CollectionLinkComponent }) }, getAgentMessageRenderKey(message, 'summary')));
2015
+ return (_jsx(MessageErrorBoundary, { children: _jsx(SummaryMessage, { message: message, onSendMessage: onSendMessage, onSelectWorkstream: handleSelectWorkstream, requestInputAnswered: isRequestInputAnswered(message, answeredRequestInputKeys), StoreLinkComponent: StoreLinkComponent, CollectionLinkComponent: CollectionLinkComponent }) }, getAgentMessageRenderKey(message, 'summary')));
1557
2016
  }), incompleteStreaming.map(({ id, data }) => (_jsx(SummaryStreamingMessage, { text: data.text, workstreamId: data.workstreamId, artifactRunId: artifactRunId }, `streaming-incomplete-${id}`))), showActivityFallback && !showInitialRequestWaitingCard && (_jsx(SummaryActivityRow, { label: summaryActivityFallbackLabel, status: "running", timestamp: activityStartedTimestamp, showElapsed: true, className: workingIndicatorClassName }))] })), _jsx("div", { ref: bottomRef, className: "h-2" })] }))] }));
1558
2017
  }
1559
2018
  const shouldDedupeAdjacentCompletedToolMessage = (previous, current) => {