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

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
@@ -255,47 +255,36 @@ function AttachmentPreview({
255
255
  </Button>
256
256
  ) : null;
257
257
 
258
- if (shouldRenderThumbnail && resolvedUrl) {
259
- return (
260
- <div className="relative inline-flex flex-col gap-1">
261
- <Button
262
- type="button"
263
- variant="unstyled"
264
- onClick={() => openImage(resolvedUrl, item.name)}
265
- aria-label={item.name}
266
- className={cn(
267
- 'group overflow-hidden rounded-xl border border-border/70 bg-mixer-muted/20 p-0 shadow-sm',
268
- 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
269
- variant === 'composer' ? 'size-16' : 'size-24',
270
- )}
271
- >
272
- <img
273
- src={resolvedUrl}
274
- alt={item.name}
275
- className="h-full w-full object-cover transition-transform group-hover:scale-[1.02]"
276
- />
277
- </Button>
278
- {item.statusLabel ? (
279
- <span
280
- className={cn(
281
- 'absolute bottom-1 start-1 max-w-[calc(100%-0.5rem)] truncate rounded px-1.5 py-0.5',
282
- 'text-[10px] font-medium shadow-sm',
283
- statusClassName,
284
- )}
285
- >
286
- {item.statusLabel}
287
- </span>
288
- ) : null}
289
- {removeButton}
290
- </div>
258
+ const attachmentIcon =
259
+ shouldRenderThumbnail && resolvedUrl ? (
260
+ <Button
261
+ type="button"
262
+ variant="unstyled"
263
+ size="none"
264
+ onClick={(event) => {
265
+ event.stopPropagation();
266
+ event.preventDefault();
267
+ openImage(resolvedUrl, item.name);
268
+ }}
269
+ aria-label={item.name}
270
+ title={t('agent.enlargedView')}
271
+ className={cn(
272
+ 'group shrink-0 overflow-hidden rounded border border-border/60 p-0',
273
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
274
+ variant === 'composer' ? 'size-6' : 'size-24',
275
+ )}
276
+ >
277
+ <img
278
+ src={resolvedUrl}
279
+ alt={item.name}
280
+ className="h-full w-full object-cover transition-transform group-hover:scale-[1.05]"
281
+ />
282
+ </Button>
283
+ ) : isImage ? (
284
+ <ImageIcon className="size-3.5 shrink-0 text-muted" aria-hidden="true" />
285
+ ) : (
286
+ <FileTextIcon className="size-3.5 shrink-0 text-muted" aria-hidden="true" />
291
287
  );
292
- }
293
-
294
- const attachmentIcon = isImage ? (
295
- <ImageIcon className="size-3.5 shrink-0 text-muted" aria-hidden="true" />
296
- ) : (
297
- <FileTextIcon className="size-3.5 shrink-0 text-muted" aria-hidden="true" />
298
- );
299
288
  const attachmentLabel = (
300
289
  <span className="inline-flex min-w-0 max-w-full items-center gap-1.5">
301
290
  {attachmentIcon}
@@ -313,6 +302,7 @@ function AttachmentPreview({
313
302
  if (variant === 'composer') {
314
303
  return (
315
304
  <span
305
+ title={item.name}
316
306
  className={cn(
317
307
  'inline-flex min-h-8 max-w-full items-center gap-1 rounded-xl border border-border/60',
318
308
  'bg-mixer-muted/15 px-2.5 py-1 text-sm text-foreground/80 transition-colors',
@@ -333,6 +323,7 @@ function AttachmentPreview({
333
323
 
334
324
  const chipContent = (
335
325
  <span
326
+ title={item.name}
336
327
  className={cn(
337
328
  'inline-flex max-w-full items-center gap-1.5 rounded-md border border-border/60 bg-mixer-muted/15',
338
329
  'px-2.5 py-1.5 text-xs text-foreground/80 transition-colors',
@@ -103,6 +103,32 @@ export default function Header({
103
103
  isCompact ? 'flex flex-col items-center gap-1' : 'flex justify-end items-center gap-2 ms-auto',
104
104
  )}
105
105
  >
106
+ {showPlanButton && (
107
+ <div className="relative">
108
+ <Button
109
+ size={variant === 'compact' ? 'icon' : 'sm'}
110
+ variant={showPlanPanel ? 'primary' : 'ghost'}
111
+ onClick={onTogglePlanPanel}
112
+ className={cn(
113
+ 'transition-all duration-200 rounded-md',
114
+ variant === 'compact' && 'size-8 rounded-lg',
115
+ )}
116
+ title={t('agent.toggleRightSidebar')}
117
+ >
118
+ <ClipboardList className={cn('size-4', variant === 'full' && 'me-1.5')} />
119
+ {variant === 'full' ? (
120
+ <span className="font-medium text-xs">
121
+ {showPlanPanel ? t('agent.hideSidebar') : t('agent.showSidebar')}
122
+ </span>
123
+ ) : (
124
+ <span className="sr-only">
125
+ {showPlanPanel ? t('agent.hideSidebar') : t('agent.showSidebar')}
126
+ </span>
127
+ )}
128
+ </Button>
129
+ </div>
130
+ )}
131
+
106
132
  {/* View Mode Toggle */}
107
133
  {isCompact ? (
108
134
  <Button
@@ -144,32 +170,6 @@ export default function Header({
144
170
  </div>
145
171
  )}
146
172
 
147
- {showPlanButton && (
148
- <div className="relative">
149
- <Button
150
- size={variant === 'compact' ? 'icon' : 'sm'}
151
- variant={showPlanPanel ? 'primary' : 'ghost'}
152
- onClick={onTogglePlanPanel}
153
- className={cn(
154
- 'transition-all duration-200 rounded-md',
155
- variant === 'compact' && 'size-8 rounded-lg',
156
- )}
157
- title={t('agent.toggleRightSidebar')}
158
- >
159
- <ClipboardList className={cn('size-4', variant === 'full' && 'me-1.5')} />
160
- {variant === 'full' ? (
161
- <span className="font-medium text-xs">
162
- {showPlanPanel ? t('agent.hideSidebar') : t('agent.showSidebar')}
163
- </span>
164
- ) : (
165
- <span className="sr-only">
166
- {showPlanPanel ? t('agent.hideSidebar') : t('agent.showSidebar')}
167
- </span>
168
- )}
169
- </Button>
170
- </div>
171
- )}
172
-
173
173
  {showPlaybackButton && onTogglePlayback && (
174
174
  <Button
175
175
  type="button"
@@ -240,8 +240,8 @@ export default function Header({
240
240
  className,
241
241
  )}
242
242
  >
243
- <div className="flex flex-wrap items-center space-x-2">
244
- <div className="flex items-center space-x-1">
243
+ <div className="flex flex-wrap items-center gap-2">
244
+ <div className="flex items-center gap-1">
245
245
  <Bot className="size-5 text-muted" />
246
246
  <span className="font-medium">{title}</span>
247
247
  </div>
@@ -0,0 +1,83 @@
1
+ import { type AgentMessage, type AgentMessageDetails, AgentMessageType } from '@vertesia/common';
2
+ import { cn, VTooltip } from '@vertesia/ui/core';
3
+ import { useUITranslation } from '@vertesia/ui/i18n';
4
+ import { AlertCircle, Check, CheckCheck, Clock, type LucideIcon } from 'lucide-react';
5
+ import { isUserStoppedMessage } from './utils';
6
+
7
+ export type MessageDeliveryStatusValue = NonNullable<AgentMessageDetails['_deliveryStatus']>;
8
+
9
+ interface MessageDeliveryStatusConfig {
10
+ icon: LucideIcon;
11
+ className: string;
12
+ }
13
+
14
+ const STATUS_CONFIG: Record<MessageDeliveryStatusValue, MessageDeliveryStatusConfig> = {
15
+ sending: {
16
+ icon: Clock,
17
+ className: 'text-muted/70',
18
+ },
19
+ received: {
20
+ icon: Check,
21
+ className: 'text-info',
22
+ },
23
+ consumed: {
24
+ icon: CheckCheck,
25
+ className: 'text-success',
26
+ },
27
+ failed: {
28
+ icon: AlertCircle,
29
+ className: 'text-destructive',
30
+ },
31
+ };
32
+
33
+ function isDeliveryStatus(value: unknown): value is MessageDeliveryStatusValue {
34
+ return value === 'sending' || value === 'received' || value === 'consumed' || value === 'failed';
35
+ }
36
+
37
+ export function getMessageDeliveryStatus(message: AgentMessage): MessageDeliveryStatusValue | undefined {
38
+ if (message.type !== AgentMessageType.QUESTION && !isUserStoppedMessage(message)) return undefined;
39
+
40
+ const status = message.details?._deliveryStatus;
41
+ if (isDeliveryStatus(status)) return status;
42
+ if (message.details?.ack) return 'consumed';
43
+ return undefined;
44
+ }
45
+
46
+ function getDeliveryStatusLabel(
47
+ t: ReturnType<typeof useUITranslation>['t'],
48
+ status: MessageDeliveryStatusValue,
49
+ ): string {
50
+ switch (status) {
51
+ case 'sending':
52
+ return t('agent.messageSending');
53
+ case 'received':
54
+ return t('agent.messageReceived');
55
+ case 'consumed':
56
+ return t('agent.messageConsumed');
57
+ case 'failed':
58
+ return t('agent.messageFailed');
59
+ }
60
+ return status;
61
+ }
62
+
63
+ export function MessageDeliveryStatus({ message, className }: { message: AgentMessage; className?: string }) {
64
+ const { t } = useUITranslation();
65
+ const status = getMessageDeliveryStatus(message);
66
+ if (!status) return null;
67
+
68
+ const config = STATUS_CONFIG[status];
69
+ const Icon = config.icon;
70
+ const label = getDeliveryStatusLabel(t, status);
71
+
72
+ return (
73
+ <VTooltip description={label} asChild>
74
+ <span
75
+ aria-label={label}
76
+ className={cn('inline-flex h-5 w-5 items-center justify-center', config.className, className)}
77
+ role="img"
78
+ >
79
+ <Icon className="size-3.5" aria-hidden="true" />
80
+ </span>
81
+ </VTooltip>
82
+ );
83
+ }
@@ -17,8 +17,7 @@ describe('MessageInput', () => {
17
17
  />,
18
18
  );
19
19
 
20
- expect(screen.getByPlaceholderText(/Enter to send/)).not.toBeNull();
21
- expect(screen.queryByText('Enter to send • Shift+Enter for new line')).toBeNull();
20
+ expect(screen.getByPlaceholderText(/Type your message/)).not.toBeNull();
22
21
  expect(screen.getByText('Loan package')).not.toBeNull();
23
22
 
24
23
  fireEvent.pointerDown(screen.getByRole('button', { name: /Add attachment/i }));
@@ -55,6 +54,15 @@ describe('MessageInput', () => {
55
54
  expect(onFilesSelected).toHaveBeenCalledWith([file]);
56
55
  });
57
56
 
57
+ it('renders attachment actions before the MCP slot', () => {
58
+ renderWithProviders(<MessageInput onSend={vi.fn()} mcpSlot={<button type="button">MCP</button>} isCompleted />);
59
+
60
+ const attachmentButton = screen.getByRole('button', { name: /Add attachment/i });
61
+ const mcpButton = screen.getByRole('button', { name: 'MCP' });
62
+
63
+ expect(attachmentButton.compareDocumentPosition(mcpButton) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
64
+ });
65
+
58
66
  it('accepts dropped files when upload is enabled', () => {
59
67
  const onFilesSelected = vi.fn();
60
68
  const { container } = renderWithProviders(<MessageInput onSend={vi.fn()} onFilesSelected={onFilesSelected} />);
@@ -168,6 +176,34 @@ describe('MessageInput', () => {
168
176
  expect(screen.getByText('Ready')).not.toBeNull();
169
177
  });
170
178
 
179
+ it('renders context usage and triggers manual compaction', async () => {
180
+ const onCompactContext = vi.fn();
181
+
182
+ renderWithProviders(
183
+ <MessageInput
184
+ onSend={vi.fn()}
185
+ contextWindowUsage={{
186
+ usedTokens: 50_000,
187
+ checkpointTokens: 100_000,
188
+ usedPercent: 50,
189
+ remainingPercent: 50,
190
+ }}
191
+ onCompactContext={onCompactContext}
192
+ isStreaming
193
+ />,
194
+ );
195
+
196
+ const contextButton = screen.getByRole('button', { name: /50% context used/i });
197
+
198
+ fireEvent.pointerMove(contextButton);
199
+
200
+ expect((await screen.findAllByText('Context size: 50K / 100K tokens')).length).toBeGreaterThan(0);
201
+
202
+ fireEvent.click(contextButton);
203
+
204
+ expect(onCompactContext).toHaveBeenCalledTimes(1);
205
+ });
206
+
171
207
  it('shows active workstream names above the compact composer', () => {
172
208
  renderWithProviders(
173
209
  <MessageInput
@@ -10,27 +10,16 @@ import {
10
10
  ModalTitle,
11
11
  Spinner,
12
12
  Textarea,
13
+ VTooltip,
13
14
  } from '@vertesia/ui/core';
14
15
  import { useUITranslation } from '@vertesia/ui/i18n';
15
- import {
16
- Activity,
17
- ArrowUpIcon,
18
- Bot,
19
- FileTextIcon,
20
- PaperclipIcon,
21
- PlusIcon,
22
- SquareIcon,
23
- UploadIcon,
24
- } from 'lucide-react';
16
+ import { Activity, ArrowUpIcon, FileTextIcon, PaperclipIcon, PlusIcon, SquareIcon, UploadIcon } from 'lucide-react';
25
17
  import type React from 'react';
26
18
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
27
19
  import { SelectDocument } from '../../../store/objects/components/SelectDocument';
28
- import {
29
- formatWorkstreamName,
30
- getWorkstreamDisplayName,
31
- getWorkstreamStatusClass,
32
- type WorkstreamInfo,
33
- } from '../workstreams.js';
20
+ import { extractFilesFromClipboard } from '../clipboardFiles.js';
21
+ import type { WorkstreamInfo } from '../workstreams.js';
22
+ import { ActiveWorkstreamsSummary } from './ActiveWorkstreamsSummary';
34
23
  import { type AttachmentPreviewItem, AttachmentPreviewList } from './AttachmentPreview';
35
24
 
36
25
  /** Represents an uploaded file attachment */
@@ -51,6 +40,19 @@ export interface SelectedDocument {
51
40
  name: string;
52
41
  }
53
42
 
43
+ export interface ContextWindowUsage {
44
+ usedTokens: number;
45
+ checkpointTokens: number;
46
+ usedPercent: number;
47
+ remainingPercent: number;
48
+ }
49
+
50
+ function formatTokenCountInK(tokens: number): string {
51
+ const value = Math.max(0, tokens) / 1000;
52
+ const maximumFractionDigits = value > 0 && value < 10 && !Number.isInteger(value) ? 1 : 0;
53
+ return `${new Intl.NumberFormat(undefined, { maximumFractionDigits }).format(value)}K`;
54
+ }
55
+
54
56
  interface MessageInputProps {
55
57
  onSend: (message: string) => void;
56
58
  onStop?: () => void;
@@ -59,6 +61,9 @@ interface MessageInputProps {
59
61
  isStopping?: boolean;
60
62
  isStreaming?: boolean;
61
63
  isCompleted?: boolean;
64
+ contextWindowUsage?: ContextWindowUsage;
65
+ onCompactContext?: () => void;
66
+ isCompactingContext?: boolean;
62
67
  activeTaskCount?: number;
63
68
  activeWorkstreams?: WorkstreamInfo[];
64
69
  placeholder?: string;
@@ -99,6 +104,10 @@ interface MessageInputProps {
99
104
  hideObjectLinking?: boolean;
100
105
  // Hide file upload (for apps that don't use it)
101
106
  hideFileUpload?: boolean;
107
+ /** Optional toolbar slot for the agent approval mode selector. */
108
+ approvalModeSlot?: React.ReactNode;
109
+ /** Optional toolbar slot (e.g. the MCP action menu) rendered next to the attachment actions. */
110
+ mcpSlot?: React.ReactNode;
102
111
  /** Disable the local input drop overlay when a parent view owns drag/drop handling */
103
112
  disableDropZone?: boolean;
104
113
 
@@ -112,11 +121,16 @@ interface MessageInputProps {
112
121
  export default function MessageInput({
113
122
  onSend,
114
123
  onStop,
124
+ approvalModeSlot,
125
+ mcpSlot,
115
126
  disabled = false,
116
127
  isSending = false,
117
128
  isStopping = false,
118
129
  isStreaming = false,
119
130
  isCompleted = false,
131
+ contextWindowUsage,
132
+ onCompactContext,
133
+ isCompactingContext = false,
120
134
  activeTaskCount = 0,
121
135
  activeWorkstreams = [],
122
136
  placeholder,
@@ -161,8 +175,15 @@ export default function MessageInput({
161
175
  [activeWorkstreams],
162
176
  );
163
177
  const activeWorkstreamCount = runningWorkstreams.length || activeTaskCount;
164
- const visibleRunningWorkstreams = runningWorkstreams.slice(0, 3);
165
- const hiddenRunningWorkstreamCount = Math.max(0, runningWorkstreams.length - visibleRunningWorkstreams.length);
178
+ const contextUsageLabel = contextWindowUsage
179
+ ? t('agent.contextUsageCompactLabel', { percent: contextWindowUsage.usedPercent })
180
+ : undefined;
181
+ const contextTokenUsageLabel = contextWindowUsage
182
+ ? t('agent.contextTokenUsage', {
183
+ used: formatTokenCountInK(contextWindowUsage.usedTokens),
184
+ limit: formatTokenCountInK(contextWindowUsage.checkpointTokens),
185
+ })
186
+ : undefined;
166
187
  const attachmentItems = useMemo<AttachmentPreviewItem[]>(() => {
167
188
  const items: AttachmentPreviewItem[] = [];
168
189
  if (!hideFileUpload && processingFiles) {
@@ -285,30 +306,7 @@ export default function MessageInput({
285
306
  const handlePaste = useCallback(
286
307
  (e: React.ClipboardEvent) => {
287
308
  if (!canUploadFiles) return;
288
-
289
- const items = e.clipboardData?.items;
290
- if (!items) return;
291
-
292
- const files: File[] = [];
293
- for (let i = 0; i < items.length; i++) {
294
- const item = items[i];
295
- if (item.kind === 'file') {
296
- const file = item.getAsFile();
297
- if (file) {
298
- // If it's an image without a proper name, generate one
299
- if (item.type.startsWith('image/') && (!file.name || file.name === 'image.png')) {
300
- const extension = item.type.split('/')[1] || 'png';
301
- const namedFile = new File([file], `pasted-image-${Date.now()}.${extension}`, {
302
- type: file.type,
303
- });
304
- files.push(namedFile);
305
- } else {
306
- files.push(file);
307
- }
308
- }
309
- }
310
- }
311
-
309
+ const files = extractFilesFromClipboard(e.clipboardData?.items);
312
310
  if (files.length > 0) {
313
311
  handleFiles(files);
314
312
  }
@@ -472,52 +470,7 @@ export default function MessageInput({
472
470
  />
473
471
  )}
474
472
 
475
- {runningWorkstreams.length > 0 && (
476
- <div className="mx-auto mb-2 w-full max-w-3xl px-1" data-agent-active-workstreams>
477
- <output
478
- className="flex flex-col gap-1.5 rounded-2xl border border-border/70 bg-background/95 p-2 text-xs text-muted shadow-lg shadow-black/5"
479
- aria-live="polite"
480
- >
481
- <div className="flex items-center gap-2 px-1 font-medium">
482
- <Bot className="size-3.5 text-muted" aria-hidden="true" />
483
- <span>{t('agent.activeWorkstreams', { count: runningWorkstreams.length })}</span>
484
- </div>
485
- <div className="flex flex-col gap-0.5">
486
- {visibleRunningWorkstreams.map((workstream) => {
487
- const workstreamName = getWorkstreamDisplayName(
488
- workstream.workstream_id,
489
- workstream.interaction,
490
- );
491
-
492
- return (
493
- <span
494
- key={workstream.launch_id || workstream.workstream_id}
495
- className="flex min-w-0 items-center gap-2 rounded-lg px-1 py-1 text-sm text-foreground/80"
496
- title={workstreamName}
497
- >
498
- <span
499
- className={cn(
500
- 'size-1.5 shrink-0 rounded-full',
501
- getWorkstreamStatusClass(workstream.status),
502
- )}
503
- aria-hidden="true"
504
- />
505
- <span className="truncate font-medium">{workstreamName}</span>
506
- {workstream.phase && (
507
- <span className="truncate text-xs text-muted/75">
508
- {formatWorkstreamName(workstream.phase)}
509
- </span>
510
- )}
511
- </span>
512
- );
513
- })}
514
- {hiddenRunningWorkstreamCount > 0 && (
515
- <span className="px-1 py-1 text-xs text-muted">+{hiddenRunningWorkstreamCount}</span>
516
- )}
517
- </div>
518
- </output>
519
- </div>
520
- )}
473
+ <ActiveWorkstreamsSummary activeWorkstreams={activeWorkstreams} />
521
474
 
522
475
  {/* Input row */}
523
476
  <div className="mx-auto flex max-w-3xl flex-col gap-2 rounded-2xl border border-border/70 bg-mixer-muted/15 p-2.5 shadow-lg shadow-black/5">
@@ -547,13 +500,7 @@ export default function MessageInput({
547
500
  onPaste={handlePaste}
548
501
  disabled={disabled}
549
502
  aria-label={resolvedPlaceholder}
550
- placeholder={
551
- isStreaming
552
- ? `${t('agent.agentWorking')} ${t('agent.enterToSend')}`
553
- : canUploadFiles
554
- ? `${t('agent.askAnything')} ${t('agent.enterToSend')}`
555
- : `${resolvedPlaceholder} ${t('agent.enterToSend')}`
556
- }
503
+ placeholder={resolvedPlaceholder}
557
504
  rows={1}
558
505
  style={{ maxHeight: '160px' }}
559
506
  className={cn(
@@ -573,6 +520,7 @@ export default function MessageInput({
573
520
  size="icon"
574
521
  className="size-8 rounded-full text-muted hover:bg-muted"
575
522
  aria-label={t('agent.addAttachment')}
523
+ title={t('agent.addAttachment')}
576
524
  >
577
525
  <PlusIcon className="size-4" />
578
526
  </Button>
@@ -603,6 +551,81 @@ export default function MessageInput({
603
551
  )}
604
552
  </Dropdown>
605
553
  )}
554
+ {approvalModeSlot}
555
+ {mcpSlot}
556
+ {contextWindowUsage && (
557
+ <VTooltip
558
+ asChild
559
+ placement="top"
560
+ size="md"
561
+ className="text-foreground shadow-lg"
562
+ description={
563
+ <span className="block max-w-56 text-start text-sm leading-6">
564
+ <span className="block">
565
+ {t('agent.contextRemainingUntilCompact', {
566
+ percent: contextWindowUsage.remainingPercent,
567
+ })}
568
+ </span>
569
+ {contextTokenUsageLabel && (
570
+ <span className="mt-1 block text-foreground/80">
571
+ {contextTokenUsageLabel}
572
+ </span>
573
+ )}
574
+ </span>
575
+ }
576
+ >
577
+ <Button
578
+ type="button"
579
+ variant="ghost"
580
+ size="icon"
581
+ className={cn(
582
+ 'size-8 rounded-lg text-info hover:bg-muted hover:text-info disabled:opacity-60',
583
+ 'focus-visible:ring-2 focus-visible:ring-info/40',
584
+ )}
585
+ aria-label={contextUsageLabel}
586
+ onClick={onCompactContext}
587
+ disabled={!onCompactContext || isCompactingContext}
588
+ >
589
+ {isCompactingContext ? (
590
+ <Spinner size="sm" />
591
+ ) : (
592
+ <svg
593
+ viewBox="0 0 24 24"
594
+ className={cn(
595
+ 'size-8 -rotate-90',
596
+ contextWindowUsage.usedPercent >= 90
597
+ ? 'text-destructive'
598
+ : contextWindowUsage.usedPercent >= 70
599
+ ? 'text-attention'
600
+ : 'text-info',
601
+ )}
602
+ aria-hidden="true"
603
+ >
604
+ <circle
605
+ cx="12"
606
+ cy="12"
607
+ r="9.75"
608
+ fill="none"
609
+ strokeWidth="4.5"
610
+ className="stroke-current text-muted/50"
611
+ />
612
+ <circle
613
+ cx="12"
614
+ cy="12"
615
+ r="9.75"
616
+ fill="none"
617
+ pathLength={100}
618
+ strokeWidth="4.5"
619
+ strokeLinecap="round"
620
+ strokeDasharray={100}
621
+ style={{ strokeDashoffset: 100 - contextWindowUsage.usedPercent }}
622
+ className="stroke-current"
623
+ />
624
+ </svg>
625
+ )}
626
+ </Button>
627
+ </VTooltip>
628
+ )}
606
629
  {runningWorkstreams.length === 0 && activeWorkstreamCount > 0 && (
607
630
  <output className="flex min-w-0 flex-wrap items-center gap-1.5" aria-live="polite">
608
631
  <span className="inline-flex h-8 items-center gap-1 rounded-full px-2 text-xs text-muted">
@@ -626,8 +649,8 @@ export default function MessageInput({
626
649
  'disabled:bg-mixer-muted/25 disabled:text-muted disabled:opacity-100',
627
650
  '[&_svg]:text-destructive disabled:[&_svg]:text-muted',
628
651
  )}
629
- title={t('agent.stopAgent')}
630
- aria-label={t('agent.stopAgent')}
652
+ title={t('agent.stopTooltip')}
653
+ aria-label={t('agent.stopTooltip')}
631
654
  >
632
655
  {isStopping ? (
633
656
  <Spinner size="sm" />
@@ -646,7 +669,7 @@ export default function MessageInput({
646
669
  'hover:bg-foreground/90 hover:text-background',
647
670
  'disabled:bg-mixer-muted/25 disabled:text-muted disabled:opacity-100',
648
671
  )}
649
- title={hasProcessingFiles ? t('agent.waitForFiles') : undefined}
672
+ title={hasProcessingFiles ? t('agent.waitForFiles') : t('agent.sendTooltip')}
650
673
  aria-label={hasProcessingFiles ? t('agent.waitForFiles') : t('agent.send')}
651
674
  >
652
675
  {isSending ? <Spinner size="sm" /> : <ArrowUpIcon className="size-4" />}
@@ -33,6 +33,7 @@ import { useImageLightbox } from '../ImageLightbox';
33
33
  import { getArtifactCacheKey, useArtifactUrlCache } from '../useArtifactUrlCache.js';
34
34
  import { ThinkingMessages } from '../WaitingMessages';
35
35
  import { AttachmentPreviewList, parseUserMessageAttachments } from './AttachmentPreview';
36
+ import { MessageDeliveryStatus } from './MessageDeliveryStatus';
36
37
  import { processContentForMarkdown } from './processContentForMarkdown';
37
38
  import { getWorkstreamId } from './utils';
38
39
 
@@ -105,7 +106,7 @@ export interface MessageItemProps extends MessageItemClassNames {
105
106
  message: AgentMessage;
106
107
  showPulsatingCircle?: boolean;
107
108
  /** Callback when user sends a message (e.g., from proposal selection) */
108
- onSendMessage?: (message: string) => void;
109
+ onSendMessage?: (message: string, metadata?: Record<string, unknown>) => void;
109
110
  /** Whether a REQUEST_INPUT message has already been answered by a later user message */
110
111
  requestInputAnswered?: boolean;
111
112
  /** Sparse per-type overrides for MESSAGE_STYLES (deep-merged with defaults) */
@@ -592,6 +593,7 @@ function MessageItemComponent({
592
593
  )}
593
594
  </div>
594
595
  <div className="flex items-center gap-1.5 print:hidden">
596
+ <MessageDeliveryStatus message={message} />
595
597
  <span className={cn('text-[11px] text-muted/70', resolvedStyle.timestampClassName)}>
596
598
  {dayjs(message.timestamp).format('HH:mm:ss')}
597
599
  </span>
@@ -649,6 +651,10 @@ function MessageItemComponent({
649
651
  multiSelect={uxConfig.multiSelect}
650
652
  onSelect={(optionId) => onSendMessage?.(optionId)}
651
653
  onMultiSelect={(optionIds) => onSendMessage?.(optionIds.join(', '))}
654
+ allowFreeResponse={!uxConfig.options?.length || !!uxConfig.free_response}
655
+ placeholder={uxConfig.free_response?.placeholder}
656
+ submitLabel={uxConfig.free_response?.submit_label}
657
+ onSubmit={(value) => onSendMessage?.(value, uxConfig.free_response?.metadata)}
652
658
  hideBorder
653
659
  compact
654
660
  answered={requestInputAnswered}