@vertesia/ui 1.5.0-dev.20260725.083715Z → 1.5.0-dev.20260806.125520Z

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 (403) hide show
  1. package/lib/core/components/ComboBox.d.ts.map +1 -1
  2. package/lib/core/components/ComboBox.js +4 -4
  3. package/lib/core/components/ComboBox.js.map +1 -1
  4. package/lib/core/components/FileUpload.js.map +1 -1
  5. package/lib/core/components/MenuList.d.ts +2 -1
  6. package/lib/core/components/MenuList.d.ts.map +1 -1
  7. package/lib/core/components/TagsInput.js +1 -1
  8. package/lib/core/components/popup/PopupController.d.ts.map +1 -1
  9. package/lib/core/components/popup/PopupController.js.map +1 -1
  10. package/lib/core/components/popup/position.js.map +1 -1
  11. package/lib/core/components/popup/utils.js.map +1 -1
  12. package/lib/core/components/shadcn/LanguageSwitcher.js.map +1 -1
  13. package/lib/core/components/shadcn/MessageBox.js.map +1 -1
  14. package/lib/core/components/shadcn/Panel.js +1 -1
  15. package/lib/core/components/shadcn/badge.d.ts +2 -2
  16. package/lib/core/components/shadcn/button.d.ts +2 -2
  17. package/lib/core/components/shadcn/button.js +1 -1
  18. package/lib/core/components/shadcn/command.d.ts +4 -4
  19. package/lib/core/components/shadcn/command.d.ts.map +1 -1
  20. package/lib/core/components/shadcn/filters/DynamicLabel.js +1 -1
  21. package/lib/core/components/shadcn/filters/comboBox/DateCombobox.d.ts.map +1 -1
  22. package/lib/core/components/shadcn/filters/comboBox/DateCombobox.js +1 -1
  23. package/lib/core/components/shadcn/filters/comboBox/SelectCombobox.d.ts.map +1 -1
  24. package/lib/core/components/shadcn/filters/comboBox/SelectCombobox.js +1 -1
  25. package/lib/core/components/shadcn/filters/comboBox/StringListCombobox.d.ts.map +1 -1
  26. package/lib/core/components/shadcn/filters/comboBox/TextCombobox.d.ts.map +1 -1
  27. package/lib/core/components/shadcn/filters/filter/dateFilter.js +1 -1
  28. package/lib/core/components/shadcn/filters/filterBar.d.ts.map +1 -1
  29. package/lib/core/components/shadcn/filters/filters.js.map +1 -1
  30. package/lib/core/components/shadcn/input.d.ts +2 -2
  31. package/lib/core/components/shadcn/modal/dialog.d.ts.map +1 -1
  32. package/lib/core/components/shadcn/popover.d.ts +1 -1
  33. package/lib/core/components/shadcn/popover.d.ts.map +1 -1
  34. package/lib/core/components/shadcn/popover.js.map +1 -1
  35. package/lib/core/components/shadcn/radioGroup.d.ts.map +1 -1
  36. package/lib/core/components/shadcn/selectBox.js +1 -1
  37. package/lib/core/components/shadcn/tabs.d.ts.map +1 -1
  38. package/lib/core/components/shadcn/tabs.js +1 -1
  39. package/lib/core/components/shadcn/text.d.ts +2 -2
  40. package/lib/core/components/shadcn/theme/ThemeSwitcher.js.map +1 -1
  41. package/lib/core/components/toast/ToastProvider.js +1 -1
  42. package/lib/core/hooks/CompositeState.d.ts +1 -1
  43. package/lib/core/hooks/CompositeState.d.ts.map +1 -1
  44. package/lib/core/hooks/CompositeState.js.map +1 -1
  45. package/lib/core/hooks/SharedState.d.ts.map +1 -1
  46. package/lib/core/hooks/useFetch.d.ts.map +1 -1
  47. package/lib/core/hooks/useFetch.js +2 -1
  48. package/lib/core/hooks/useFetch.js.map +1 -1
  49. package/lib/core/hooks/useFlag.d.ts.map +1 -1
  50. package/lib/core/hooks/useIntersectionObserver.js.map +1 -1
  51. package/lib/core/hooks/useSafeLayoutEffect.d.ts +2 -2
  52. package/lib/core/hooks/useSafeLayoutEffect.d.ts.map +1 -1
  53. package/lib/core/hooks/useScrollableSearch.d.ts +1 -1
  54. package/lib/core/hooks/useScrollableSearch.d.ts.map +1 -1
  55. package/lib/core/hooks/useScrollableSearch.js +15 -2
  56. package/lib/core/hooks/useScrollableSearch.js.map +1 -1
  57. package/lib/core/hooks/useSharedValue.d.ts.map +1 -1
  58. package/lib/core/hooks/useSharedValue.js.map +1 -1
  59. package/lib/core/utils/a11y.d.ts.map +1 -1
  60. package/lib/env/index.d.ts +4 -0
  61. package/lib/env/index.d.ts.map +1 -1
  62. package/lib/env/index.js.map +1 -1
  63. package/lib/features/agent/PayloadBuilder.d.ts +1 -1
  64. package/lib/features/agent/PayloadBuilder.d.ts.map +1 -1
  65. package/lib/features/agent/PayloadBuilder.js.map +1 -1
  66. package/lib/features/agent/chat/AgentRequestInputOverlay.d.ts +1 -1
  67. package/lib/features/agent/chat/AgentRequestInputOverlay.d.ts.map +1 -1
  68. package/lib/features/agent/chat/AgentRequestInputOverlay.js +3 -8
  69. package/lib/features/agent/chat/AgentRequestInputOverlay.js.map +1 -1
  70. package/lib/features/agent/chat/ArtifactsTab.js +1 -1
  71. package/lib/features/agent/chat/AskUserWidget.js +1 -1
  72. package/lib/features/agent/chat/DocumentEditingActionCard.js +1 -1
  73. package/lib/features/agent/chat/ModernAgentConversation.d.ts +8 -1
  74. package/lib/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
  75. package/lib/features/agent/chat/ModernAgentConversation.js +79 -20
  76. package/lib/features/agent/chat/ModernAgentConversation.js.map +1 -1
  77. package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.d.ts +2 -1
  78. package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.d.ts.map +1 -1
  79. package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.js +25 -10
  80. package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.js.map +1 -1
  81. package/lib/features/agent/chat/ModernAgentOutput/AgentMarkdownAnchor.d.ts.map +1 -1
  82. package/lib/features/agent/chat/ModernAgentOutput/AgentMarkdownAnchor.js.map +1 -1
  83. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
  84. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +25 -10
  85. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
  86. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.d.ts +7 -0
  87. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.d.ts.map +1 -1
  88. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js +40 -3
  89. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js.map +1 -1
  90. package/lib/features/agent/chat/ModernAgentOutput/BatchProgressPanel.d.ts.map +1 -1
  91. package/lib/features/agent/chat/ModernAgentOutput/Header.js +2 -2
  92. package/lib/features/agent/chat/ModernAgentOutput/Header.js.map +1 -1
  93. package/lib/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.d.ts.map +1 -1
  94. package/lib/features/agent/chat/ModernAgentOutput/MessageInput.d.ts +2 -1
  95. package/lib/features/agent/chat/ModernAgentOutput/MessageInput.d.ts.map +1 -1
  96. package/lib/features/agent/chat/ModernAgentOutput/MessageInput.js +2 -2
  97. package/lib/features/agent/chat/ModernAgentOutput/MessageInput.js.map +1 -1
  98. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.d.ts.map +1 -1
  99. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js +2 -2
  100. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -1
  101. package/lib/features/agent/chat/ModernAgentOutput/ResourceChip.js +1 -1
  102. package/lib/features/agent/chat/ModernAgentOutput/SlideInPanel.js +1 -1
  103. package/lib/features/agent/chat/ModernAgentOutput/StreamingMessage.d.ts.map +1 -1
  104. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.d.ts.map +1 -1
  105. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.js +8 -0
  106. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.js.map +1 -1
  107. package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.d.ts.map +1 -1
  108. package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.js +1 -1
  109. package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js +1 -1
  110. package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.d.ts +9 -1
  111. package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.d.ts.map +1 -1
  112. package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.js +97 -2
  113. package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.js.map +1 -1
  114. package/lib/features/agent/chat/ModernAgentOutput/utils.d.ts.map +1 -1
  115. package/lib/features/agent/chat/SlidingThinkingIndicator.js +1 -1
  116. package/lib/features/agent/chat/VegaLiteChart.js +1 -1
  117. package/lib/features/agent/chat/VegaLiteChart.js.map +1 -1
  118. package/lib/features/agent/chat/hooks/useAgentStream.d.ts.map +1 -1
  119. package/lib/features/agent/chat/hooks/useAgentStream.js +38 -3
  120. package/lib/features/agent/chat/hooks/useAgentStream.js.map +1 -1
  121. package/lib/features/agent/chat/hooks/useFileProcessing.d.ts +8 -1
  122. package/lib/features/agent/chat/hooks/useFileProcessing.d.ts.map +1 -1
  123. package/lib/features/agent/chat/hooks/useFileProcessing.js +31 -2
  124. package/lib/features/agent/chat/hooks/useFileProcessing.js.map +1 -1
  125. package/lib/features/agent/chat/index.d.ts +1 -1
  126. package/lib/features/agent/chat/index.d.ts.map +1 -1
  127. package/lib/features/agent/chat/index.js.map +1 -1
  128. package/lib/features/agent/chat/useArtifactUrlCache.js.map +1 -1
  129. package/lib/features/agent/chat/workstreams.d.ts +1 -1
  130. package/lib/features/facets/AgentRunnerFacetsNav.d.ts.map +1 -1
  131. package/lib/features/facets/CollectionsFacetsNav.d.ts.map +1 -1
  132. package/lib/features/facets/DocumentsFacetsNav.d.ts.map +1 -1
  133. package/lib/features/facets/InteractionsFacetsNav.d.ts.map +1 -1
  134. package/lib/features/facets/PromptsFacetsNav.d.ts +8 -6
  135. package/lib/features/facets/PromptsFacetsNav.d.ts.map +1 -1
  136. package/lib/features/facets/PromptsFacetsNav.js +8 -3
  137. package/lib/features/facets/PromptsFacetsNav.js.map +1 -1
  138. package/lib/features/facets/RunsFacetsNav.d.ts.map +1 -1
  139. package/lib/features/facets/WorkflowExecutionsFacetsNav.d.ts.map +1 -1
  140. package/lib/features/magic-pdf/GroundedExtractionView.js +1 -1
  141. package/lib/features/magic-pdf/MagicPdfProvider.d.ts.map +1 -1
  142. package/lib/features/magic-pdf/MagicPdfProvider.js.map +1 -1
  143. package/lib/features/oauth/McpConnectionsButton.js +1 -1
  144. package/lib/features/oauth/OAuthProviderConnectButton.js +1 -1
  145. package/lib/features/oauth/RemoteMcpConnectionButton.js +1 -1
  146. package/lib/features/pdf-viewer/PdfPageRenderer.js +1 -1
  147. package/lib/features/pdf-viewer/PdfPageSlider.js +1 -1
  148. package/lib/features/permissions/UserPermissionsProvider.d.ts.map +1 -1
  149. package/lib/features/permissions/UserPermissionsProvider.js.map +1 -1
  150. package/lib/features/store/collections/CollectionsTable.js +2 -2
  151. package/lib/features/store/collections/CollectionsTable.js.map +1 -1
  152. package/lib/features/store/collections/CreateCollection.js +1 -1
  153. package/lib/features/store/collections/EditCollectionView.js +1 -1
  154. package/lib/features/store/objects/DocumentQuickFilter.js +1 -1
  155. package/lib/features/store/objects/DocumentSelectionProvider.d.ts.map +1 -1
  156. package/lib/features/store/objects/DocumentSelectionProvider.js.map +1 -1
  157. package/lib/features/store/objects/components/ContentDispositionButton.d.ts +2 -1
  158. package/lib/features/store/objects/components/ContentDispositionButton.d.ts.map +1 -1
  159. package/lib/features/store/objects/components/ContentOverview.js +5 -2
  160. package/lib/features/store/objects/components/ContentOverview.js.map +1 -1
  161. package/lib/features/store/objects/components/DocumentEditingPanel.js +1 -1
  162. package/lib/features/store/objects/components/PropertiesEditorModal.js +1 -1
  163. package/lib/features/store/objects/components/TextEditorPanel.js +1 -1
  164. package/lib/features/store/objects/components/documentEditingTarget.d.ts.map +1 -1
  165. package/lib/features/store/objects/components/useContentPanelHooks.d.ts +31 -3
  166. package/lib/features/store/objects/components/useContentPanelHooks.d.ts.map +1 -1
  167. package/lib/features/store/objects/layout/DocumentTableColumn.d.ts +1 -1
  168. package/lib/features/store/objects/layout/DocumentTableColumn.d.ts.map +1 -1
  169. package/lib/features/store/objects/layout/DocumentTableColumn.js.map +1 -1
  170. package/lib/features/store/objects/layout/documentLayout.js +1 -1
  171. package/lib/features/store/objects/layout/renderers.d.ts.map +1 -1
  172. package/lib/features/store/objects/search/DocumentSearchContext.d.ts +129 -7
  173. package/lib/features/store/objects/search/DocumentSearchContext.d.ts.map +1 -1
  174. package/lib/features/store/objects/search/DocumentSearchContext.js.map +1 -1
  175. package/lib/features/store/objects/selection/ObjectsActionContext.d.ts +2 -2
  176. package/lib/features/store/objects/selection/ObjectsActionContext.d.ts.map +1 -1
  177. package/lib/features/store/objects/selection/ObjectsActionContextClass.d.ts.map +1 -1
  178. package/lib/features/store/objects/selection/ObjectsActionContextClass.js.map +1 -1
  179. package/lib/features/store/objects/selection/ObjectsActionSpec.d.ts +2 -2
  180. package/lib/features/store/objects/selection/ObjectsActionSpec.d.ts.map +1 -1
  181. package/lib/features/store/objects/selection/SelectionActions.d.ts +2 -2
  182. package/lib/features/store/objects/selection/SelectionActions.d.ts.map +1 -1
  183. package/lib/features/store/objects/selection/SelectionActions.js +1 -1
  184. package/lib/features/store/objects/selection/actions/ConfirmAction.js +1 -1
  185. package/lib/features/store/objects/selection/actions/DeleteObjectsAction.js +1 -1
  186. package/lib/features/store/objects/selection/actions/StartWorkflowButton.js +1 -1
  187. package/lib/features/store/objects/upload/DocumentUploadModal.js +1 -1
  188. package/lib/features/store/objects/upload/DocumentUploadModal.js.map +1 -1
  189. package/lib/features/store/objects/upload/useSmartFileUploadProcessing.d.ts.map +1 -1
  190. package/lib/features/store/objects/upload/useUploadHandler.d.ts.map +1 -1
  191. package/lib/features/store/types/ContentObjectTypesSearch.js +1 -1
  192. package/lib/features/store/types/IntakePolicyEditor.d.ts +2 -2
  193. package/lib/features/store/types/IntakePolicyEditor.d.ts.map +1 -1
  194. package/lib/features/store/types/IntakePolicyEditor.js +6 -2
  195. package/lib/features/store/types/IntakePolicyEditor.js.map +1 -1
  196. package/lib/features/store/types/IntakePolicyForm.d.ts.map +1 -1
  197. package/lib/features/store/types/IntakePolicyForm.js +2 -2
  198. package/lib/features/store/types/IntakePolicyForm.js.map +1 -1
  199. package/lib/features/store/types/ObjectSchemaEditor.d.ts +2 -2
  200. package/lib/features/store/types/ObjectSchemaEditor.d.ts.map +1 -1
  201. package/lib/features/store/types/SelectContentType.d.ts +2 -2
  202. package/lib/features/store/types/SelectContentType.d.ts.map +1 -1
  203. package/lib/features/store/types/SelectContentType.js.map +1 -1
  204. package/lib/features/store/types/SelectContentTypeModal.d.ts +2 -2
  205. package/lib/features/store/types/SelectContentTypeModal.d.ts.map +1 -1
  206. package/lib/features/store/types/SelectContentTypeModal.js.map +1 -1
  207. package/lib/features/store/types/TableLayoutEditor.d.ts +2 -2
  208. package/lib/features/store/types/TableLayoutEditor.d.ts.map +1 -1
  209. package/lib/features/store/types/TypeRegistry.d.ts +1267 -6
  210. package/lib/features/store/types/TypeRegistry.d.ts.map +1 -1
  211. package/lib/features/store/types/TypeRegistry.js +5 -0
  212. package/lib/features/store/types/TypeRegistry.js.map +1 -1
  213. package/lib/features/store/types/intake-policy-editor.logic.d.ts +9 -1
  214. package/lib/features/store/types/intake-policy-editor.logic.d.ts.map +1 -1
  215. package/lib/features/store/types/intake-policy-editor.logic.js +9 -1
  216. package/lib/features/store/types/intake-policy-editor.logic.js.map +1 -1
  217. package/lib/features/store/types/search/ObjectTypeSearchContext.d.ts +1252 -2
  218. package/lib/features/store/types/search/ObjectTypeSearchContext.d.ts.map +1 -1
  219. package/lib/features/store/types/search/ObjectTypeSearchContext.js.map +1 -1
  220. package/lib/features/store/types/typeCatalogCache.d.ts +2 -2
  221. package/lib/features/store/types/typeCatalogCache.d.ts.map +1 -1
  222. package/lib/features/store/types/typeCatalogCache.js +4 -0
  223. package/lib/features/store/types/typeCatalogCache.js.map +1 -1
  224. package/lib/features/user/UserInfo.d.ts +118 -7
  225. package/lib/features/user/UserInfo.d.ts.map +1 -1
  226. package/lib/features/user/UserInfo.js +1 -1
  227. package/lib/features/user/UserInfo.js.map +1 -1
  228. package/lib/features/utils/mimeType.d.ts.map +1 -1
  229. package/lib/features/utils/rendition.js.map +1 -1
  230. package/lib/features/utils/text.js.map +1 -1
  231. package/lib/i18n/locales/ar.json +27 -1
  232. package/lib/i18n/locales/de.json +27 -1
  233. package/lib/i18n/locales/en.json +30 -1
  234. package/lib/i18n/locales/es.json +27 -1
  235. package/lib/i18n/locales/fr.json +27 -1
  236. package/lib/i18n/locales/it.json +27 -1
  237. package/lib/i18n/locales/ja.json +27 -1
  238. package/lib/i18n/locales/ko.json +27 -1
  239. package/lib/i18n/locales/pt.json +27 -1
  240. package/lib/i18n/locales/ru.json +27 -1
  241. package/lib/i18n/locales/tr.json +27 -1
  242. package/lib/i18n/locales/zh-TW.json +27 -1
  243. package/lib/i18n/locales/zh.json +27 -1
  244. package/lib/i18n/rtl.d.ts +1 -1
  245. package/lib/i18n/rtl.d.ts.map +1 -1
  246. package/lib/layout/FullHeightLayout.d.ts +7 -6
  247. package/lib/layout/FullHeightLayout.d.ts.map +1 -1
  248. package/lib/layout/Sidebar.d.ts +1 -1
  249. package/lib/layout/Sidebar.js +1 -1
  250. package/lib/rich-text/EditorToolbar.js +1 -1
  251. package/lib/router/HistoryNavigator.d.ts +2 -2
  252. package/lib/router/HistoryNavigator.d.ts.map +1 -1
  253. package/lib/router/HistoryNavigator.js.map +1 -1
  254. package/lib/router/PathMatcher.d.ts.map +1 -1
  255. package/lib/router/PathMatcher.js.map +1 -1
  256. package/lib/router/PathWithParams.d.ts.map +1 -1
  257. package/lib/router/Redirect.js.map +1 -1
  258. package/lib/router/Route404.js +1 -1
  259. package/lib/router/Router.d.ts.map +1 -1
  260. package/lib/router/Router.js.map +1 -1
  261. package/lib/session/UserSession.d.ts +18 -4
  262. package/lib/session/UserSession.d.ts.map +1 -1
  263. package/lib/session/UserSession.js.map +1 -1
  264. package/lib/session/UserSessionProvider.d.ts +2 -0
  265. package/lib/session/UserSessionProvider.d.ts.map +1 -1
  266. package/lib/session/UserSessionProvider.js +81 -53
  267. package/lib/session/UserSessionProvider.js.map +1 -1
  268. package/lib/session/auth/composable.d.ts +49 -1
  269. package/lib/session/auth/composable.d.ts.map +1 -1
  270. package/lib/session/auth/composable.js +179 -53
  271. package/lib/session/auth/composable.js.map +1 -1
  272. package/lib/shell/VertesiaShell.js +1 -1
  273. package/lib/shell/apps/AppInstallationProvider.d.ts +230 -2
  274. package/lib/shell/apps/AppInstallationProvider.d.ts.map +1 -1
  275. package/lib/shell/apps/AppProjectSelector.js +1 -1
  276. package/lib/shell/login/InviteAcceptModal.js.map +1 -1
  277. package/lib/shell/login/SignInEmailStep.js +1 -1
  278. package/lib/shell/login/SignInPrimitives.d.ts +21 -20
  279. package/lib/shell/login/SignInPrimitives.d.ts.map +1 -1
  280. package/lib/shell/login/SignInPrimitives.js.map +1 -1
  281. package/lib/shell/login/SignInRecoveryStep.d.ts +22 -0
  282. package/lib/shell/login/SignInRecoveryStep.d.ts.map +1 -0
  283. package/lib/shell/login/SignInRecoveryStep.js +59 -0
  284. package/lib/shell/login/SignInRecoveryStep.js.map +1 -0
  285. package/lib/shell/login/SigninScreen.d.ts.map +1 -1
  286. package/lib/shell/login/SigninScreen.js +84 -11
  287. package/lib/shell/login/SigninScreen.js.map +1 -1
  288. package/lib/shell/login/SignupForm.js +1 -1
  289. package/lib/shell/login/TerminalLogin.js +1 -1
  290. package/lib/shell/login/UserSessionMenu.js +1 -1
  291. package/lib/vertesia-ui-core.js +1 -1
  292. package/lib/vertesia-ui-core.js.map +1 -1
  293. package/lib/vertesia-ui-features.js +34 -34
  294. package/lib/vertesia-ui-features.js.map +1 -1
  295. package/lib/vertesia-ui-i18n.js +13 -13
  296. package/lib/vertesia-ui-layout.js.map +1 -1
  297. package/lib/vertesia-ui-rich-text.js.map +1 -1
  298. package/lib/vertesia-ui-router.js.map +1 -1
  299. package/lib/vertesia-ui-session.js +1 -1
  300. package/lib/vertesia-ui-session.js.map +1 -1
  301. package/lib/vertesia-ui-shell.js +1 -1
  302. package/lib/vertesia-ui-shell.js.map +1 -1
  303. package/lib/vertesia-ui-widgets.js +18 -18
  304. package/lib/vertesia-ui-widgets.js.map +1 -1
  305. package/lib/widgets/form/FormContext.d.ts.map +1 -1
  306. package/lib/widgets/form/FormContext.js.map +1 -1
  307. package/lib/widgets/form/ManagedObject.d.ts +2 -2
  308. package/lib/widgets/form/ManagedObject.d.ts.map +1 -1
  309. package/lib/widgets/form/ManagedObject.js.map +1 -1
  310. package/lib/widgets/form/schema.d.ts.map +1 -1
  311. package/lib/widgets/form/schema.js.map +1 -1
  312. package/lib/widgets/json-view/JSONCode.js +1 -1
  313. package/lib/widgets/json-view/JSONTable.js +1 -1
  314. package/lib/widgets/markdown/ArtifactContentRenderer.js.map +1 -1
  315. package/lib/widgets/markdown/CodeBlockPlaceholder.d.ts +1 -1
  316. package/lib/widgets/markdown/CodeBlockPlaceholder.d.ts.map +1 -1
  317. package/lib/widgets/markdown/CodeBlockPlaceholder.js +1 -1
  318. package/lib/widgets/markdown/CodeBlockRendering.d.ts.map +1 -1
  319. package/lib/widgets/markdown/CollaborativeMarkdownRenderer.js +1 -1
  320. package/lib/widgets/markdown/remarkDirectiveHandler.d.ts.map +1 -1
  321. package/lib/widgets/markdown/textDiff.js.map +1 -1
  322. package/lib/widgets/monacoEditor/MonacoEditor.d.ts +7 -1
  323. package/lib/widgets/monacoEditor/MonacoEditor.d.ts.map +1 -1
  324. package/lib/widgets/monacoEditor/MonacoEditor.js +62 -6
  325. package/lib/widgets/monacoEditor/MonacoEditor.js.map +1 -1
  326. package/lib/widgets/schema-editor/ManagedSchema.d.ts.map +1 -1
  327. package/lib/widgets/schema-editor/editor/PropertyEditor.js +1 -1
  328. package/lib/widgets/schema-editor/json-schema4-utils.js.map +1 -1
  329. package/lib/widgets/xml-viewer/components/Elements/index.js +1 -1
  330. package/lib/widgets/xml-viewer/components/Tag/index.js +1 -1
  331. package/lib/widgets/xml-viewer/constants/index.d.ts.map +1 -1
  332. package/lib/widgets/xml-viewer/helpers/index.d.ts +1 -1
  333. package/lib/widgets/xml-viewer/hooks/useCollapsible.d.ts +1 -1
  334. package/lib/widgets/xml-viewer/hooks/useCollapsible.d.ts.map +1 -1
  335. package/package.json +33 -33
  336. package/src/core/hooks/useFetch.ts +2 -1
  337. package/src/core/hooks/useScrollableSearch.test.tsx +139 -0
  338. package/src/core/hooks/useScrollableSearch.tsx +17 -3
  339. package/src/env/index.ts +2 -0
  340. package/src/features/agent/chat/AgentChatPlaybackControls.test.tsx +2 -0
  341. package/src/features/agent/chat/AgentRequestInputOverlay.test.tsx +51 -6
  342. package/src/features/agent/chat/AgentRequestInputOverlay.tsx +5 -7
  343. package/src/features/agent/chat/ModernAgentConversation.test.tsx +208 -3
  344. package/src/features/agent/chat/ModernAgentConversation.tsx +130 -25
  345. package/src/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.tsx +75 -20
  346. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.test.tsx +112 -0
  347. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +62 -10
  348. package/src/features/agent/chat/ModernAgentOutput/AttachmentPreview.test.ts +38 -0
  349. package/src/features/agent/chat/ModernAgentOutput/AttachmentPreview.tsx +62 -4
  350. package/src/features/agent/chat/ModernAgentOutput/Header.tsx +2 -2
  351. package/src/features/agent/chat/ModernAgentOutput/MessageInput.test.tsx +71 -0
  352. package/src/features/agent/chat/ModernAgentOutput/MessageInput.tsx +3 -1
  353. package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +18 -4
  354. package/src/features/agent/chat/ModernAgentOutput/SummaryConversation.ts +9 -0
  355. package/src/features/agent/chat/ModernAgentOutput/requestInputMessages.test.ts +95 -0
  356. package/src/features/agent/chat/ModernAgentOutput/requestInputMessages.ts +111 -1
  357. package/src/features/agent/chat/ModernAgentOutput/utils.test.ts +21 -0
  358. package/src/features/agent/chat/hooks/useAgentStream.test.tsx +172 -0
  359. package/src/features/agent/chat/hooks/useAgentStream.ts +38 -3
  360. package/src/features/agent/chat/hooks/useFileProcessing.test.tsx +87 -0
  361. package/src/features/agent/chat/hooks/useFileProcessing.ts +32 -1
  362. package/src/features/agent/chat/index.ts +1 -0
  363. package/src/features/facets/PromptsFacetsNav.tsx +17 -9
  364. package/src/features/store/collections/CollectionsTable.tsx +1 -1
  365. package/src/features/store/objects/components/ContentOverview.tsx +4 -1
  366. package/src/features/store/objects/selection/ObjectsActionContext.tsx +2 -2
  367. package/src/features/store/objects/selection/ObjectsActionSpec.ts +2 -2
  368. package/src/features/store/objects/selection/SelectionActions.tsx +2 -2
  369. package/src/features/store/objects/upload/DocumentUploadModal.tsx +2 -2
  370. package/src/features/store/types/IntakePolicyEditor.tsx +12 -4
  371. package/src/features/store/types/IntakePolicyForm.tsx +25 -0
  372. package/src/features/store/types/ObjectSchemaEditor.tsx +2 -2
  373. package/src/features/store/types/SelectContentType.tsx +9 -9
  374. package/src/features/store/types/SelectContentTypeModal.tsx +5 -5
  375. package/src/features/store/types/TableLayoutEditor.tsx +2 -2
  376. package/src/features/store/types/TypeRegistry.ts +8 -3
  377. package/src/features/store/types/intake-policy-editor.logic.ts +10 -2
  378. package/src/features/store/types/typeCatalogCache.ts +10 -3
  379. package/src/i18n/locales/ar.json +27 -1
  380. package/src/i18n/locales/de.json +27 -1
  381. package/src/i18n/locales/en.json +30 -1
  382. package/src/i18n/locales/es.json +27 -1
  383. package/src/i18n/locales/fr.json +27 -1
  384. package/src/i18n/locales/it.json +27 -1
  385. package/src/i18n/locales/ja.json +27 -1
  386. package/src/i18n/locales/ko.json +27 -1
  387. package/src/i18n/locales/pt.json +27 -1
  388. package/src/i18n/locales/ru.json +27 -1
  389. package/src/i18n/locales/tr.json +27 -1
  390. package/src/i18n/locales/zh-TW.json +27 -1
  391. package/src/i18n/locales/zh.json +27 -1
  392. package/src/session/UserSessionProvider.test.ts +69 -0
  393. package/src/session/UserSessionProvider.tsx +96 -60
  394. package/src/session/auth/composable.scope.test.ts +88 -0
  395. package/src/session/auth/composable.test.ts +205 -0
  396. package/src/session/auth/composable.ts +227 -58
  397. package/src/shell/login/InviteAcceptModal.tsx +4 -4
  398. package/src/shell/login/SignInPrimitives.tsx +1 -0
  399. package/src/shell/login/SignInRecoveryStep.test.tsx +112 -0
  400. package/src/shell/login/SignInRecoveryStep.tsx +177 -0
  401. package/src/shell/login/SigninScreen.tsx +145 -27
  402. package/src/widgets/markdown/ArtifactEditingSurface.test.tsx +13 -9
  403. package/src/widgets/monacoEditor/MonacoEditor.tsx +83 -7
@@ -0,0 +1,112 @@
1
+ import { fireEvent, render, screen } from '@testing-library/react';
2
+ import { afterEach, describe, expect, it, vi } from 'vitest';
3
+ import SignInRecoveryStep from './SignInRecoveryStep';
4
+
5
+ const translations: Record<string, string> = {
6
+ 'auth.recovery.scopeProject.eyebrow': 'Link Unavailable',
7
+ 'auth.recovery.scopeProject.title': 'Project not available',
8
+ 'auth.recovery.scopeProject.body':
9
+ 'You’re signed in, but the project in this link isn’t available. The link may be outdated, or you may not have access.',
10
+ 'auth.recovery.scopeAccount.eyebrow': 'Link Unavailable',
11
+ 'auth.recovery.scopeAccount.title': 'Account not available',
12
+ 'auth.recovery.scopeAccount.body': 'Account unavailable body',
13
+ 'auth.recovery.noAccessibleAccount.eyebrow': 'Account Required',
14
+ 'auth.recovery.noAccessibleAccount.title': 'No account is available',
15
+ 'auth.recovery.noAccessibleAccount.body': 'No accessible account body',
16
+ 'auth.recovery.credential.eyebrow': 'Sign-In Required',
17
+ 'auth.recovery.credential.title': 'Your sign-in could not be verified',
18
+ 'auth.recovery.credential.body': 'Credential body',
19
+ 'auth.recovery.service.eyebrow': 'Service Unavailable',
20
+ 'auth.recovery.service.title': "We couldn't complete sign-in",
21
+ 'auth.recovery.service.body': 'Service body',
22
+ 'auth.recovery.continue': 'Continue to Vertesia',
23
+ 'auth.recovery.tryAgain': 'Try again',
24
+ 'auth.recovery.useDifferentAccount': 'Use a different account',
25
+ 'auth.recovery.supportPrefix': 'If you need help, contact',
26
+ 'auth.recovery.technicalDetails': 'Technical details',
27
+ 'auth.recovery.errorCode': 'Error code',
28
+ 'auth.recovery.httpStatus': 'HTTP status',
29
+ 'auth.recovery.requestedAccount': 'Requested account',
30
+ 'auth.recovery.requestedProject': 'Requested project',
31
+ 'auth.recovery.errorMessage': 'Error message',
32
+ 'auth.returning.notYou': 'Not you?',
33
+ };
34
+
35
+ vi.mock('@vertesia/ui/i18n', () => ({
36
+ useUITranslation: () => ({ t: (key: string) => translations[key] ?? key }),
37
+ }));
38
+
39
+ describe('SignInRecoveryStep', () => {
40
+ afterEach(() => {
41
+ document.body.innerHTML = '';
42
+ });
43
+
44
+ it('shows project-safe copy, focuses the primary action, and prevents duplicate submissions', () => {
45
+ const onContinue = vi.fn();
46
+ render(<SignInRecoveryStep kind="scopeProject" onContinue={onContinue} onUseDifferentAccount={vi.fn()} />);
47
+
48
+ expect(screen.getByText('Project not available')).toBeTruthy();
49
+ expect(screen.getByText(/project in this link isn’t available/)).toBeTruthy();
50
+ const continueButton = screen.getByRole('button', { name: 'Continue to Vertesia' });
51
+ expect(document.activeElement).toBe(continueButton);
52
+
53
+ fireEvent.click(continueButton);
54
+ fireEvent.click(continueButton);
55
+
56
+ expect(onContinue).toHaveBeenCalledOnce();
57
+ expect((continueButton as HTMLButtonElement).disabled).toBe(true);
58
+ });
59
+
60
+ it('omits continue for an identity with no accessible account and includes support guidance', () => {
61
+ const onUseDifferentAccount = vi.fn();
62
+ render(<SignInRecoveryStep kind="noAccessibleAccount" onUseDifferentAccount={onUseDifferentAccount} />);
63
+
64
+ expect(screen.queryByRole('button', { name: 'Continue to Vertesia' })).toBeNull();
65
+ expect(screen.getByText('No account is available')).toBeTruthy();
66
+ expect(screen.getByRole('link', { name: 'support@vertesiahq.com' }).getAttribute('href')).toBe(
67
+ 'mailto:support@vertesiahq.com',
68
+ );
69
+ expect(document.activeElement).toBe(screen.getByRole('button', { name: 'Use a different account' }));
70
+ });
71
+
72
+ it('shows submitted selectors and the normalized server error in collapsed technical details', () => {
73
+ render(
74
+ <SignInRecoveryStep
75
+ details={{
76
+ accountId: 'apple',
77
+ errorCode: 'requested_scope_unavailable',
78
+ message: 'The requested account or project is not available.',
79
+ projectId: 'banana',
80
+ status: 403,
81
+ }}
82
+ kind="scopeProject"
83
+ onContinue={vi.fn()}
84
+ onUseDifferentAccount={vi.fn()}
85
+ />,
86
+ );
87
+
88
+ const disclosure = screen.getByText('Technical details').closest('details');
89
+ expect(disclosure?.hasAttribute('open')).toBe(false);
90
+ expect(screen.getByText('requested_scope_unavailable')).toBeTruthy();
91
+ expect(screen.getByText('apple')).toBeTruthy();
92
+ expect(screen.getByText('banana')).toBeTruthy();
93
+ expect(screen.getByText('The requested account or project is not available.')).toBeTruthy();
94
+ });
95
+
96
+ it('reuses the returning-user identity row for the authenticated credential', () => {
97
+ const onUseDifferentAccount = vi.fn();
98
+ render(
99
+ <SignInRecoveryStep
100
+ identity={{ email: 'leon@example.com', name: 'Leon Ruggiero' }}
101
+ kind="scopeProject"
102
+ onContinue={vi.fn()}
103
+ onUseDifferentAccount={onUseDifferentAccount}
104
+ />,
105
+ );
106
+
107
+ expect(screen.getByText('Leon Ruggiero')).toBeTruthy();
108
+ expect(screen.getByText('leon@example.com')).toBeTruthy();
109
+ fireEvent.click(screen.getByRole('button', { name: 'Not you?' }));
110
+ expect(onUseDifferentAccount).toHaveBeenCalledOnce();
111
+ });
112
+ });
@@ -0,0 +1,177 @@
1
+ import { useUITranslation } from '@vertesia/ui/i18n';
2
+ import { AlertTriangle } from 'lucide-react';
3
+ import { useEffect, useRef, useState } from 'react';
4
+ import {
5
+ SignInAccountRow,
6
+ SignInIconBadge,
7
+ SignInInitialsBadge,
8
+ SignInStepButton,
9
+ SignInStepHeader,
10
+ SignInStepLayout,
11
+ } from './SignInPrimitives';
12
+ import { emailInitial, firstNameFromEmail } from './signInUtils';
13
+
14
+ export type SignInRecoveryKind = 'scopeProject' | 'scopeAccount' | 'noAccessibleAccount' | 'credential' | 'service';
15
+
16
+ export interface SignInRecoveryDetails {
17
+ accountId?: string;
18
+ errorCode?: string;
19
+ message: string;
20
+ projectId?: string;
21
+ status?: number;
22
+ }
23
+
24
+ export interface SignInRecoveryIdentity {
25
+ email: string;
26
+ name?: string;
27
+ }
28
+
29
+ interface SignInRecoveryStepProps {
30
+ details?: SignInRecoveryDetails;
31
+ identity?: SignInRecoveryIdentity;
32
+ kind: SignInRecoveryKind;
33
+ onContinue?: () => void;
34
+ onUseDifferentAccount: () => void;
35
+ }
36
+
37
+ export default function SignInRecoveryStep({
38
+ details,
39
+ identity,
40
+ kind,
41
+ onContinue,
42
+ onUseDifferentAccount,
43
+ }: SignInRecoveryStepProps) {
44
+ const { t } = useUITranslation();
45
+ const [submitting, setSubmitting] = useState(false);
46
+ const initialButtonRef = useRef<HTMLButtonElement>(null);
47
+
48
+ useEffect(() => {
49
+ initialButtonRef.current?.focus();
50
+ }, []);
51
+
52
+ const isScopeFailure = kind === 'scopeProject' || kind === 'scopeAccount';
53
+ let copy: { eyebrow: string; title: string; body: string };
54
+ if (kind === 'scopeProject') {
55
+ copy = {
56
+ eyebrow: t('auth.recovery.scopeProject.eyebrow'),
57
+ title: t('auth.recovery.scopeProject.title'),
58
+ body: t('auth.recovery.scopeProject.body'),
59
+ };
60
+ } else if (kind === 'scopeAccount') {
61
+ copy = {
62
+ eyebrow: t('auth.recovery.scopeAccount.eyebrow'),
63
+ title: t('auth.recovery.scopeAccount.title'),
64
+ body: t('auth.recovery.scopeAccount.body'),
65
+ };
66
+ } else if (kind === 'noAccessibleAccount') {
67
+ copy = {
68
+ eyebrow: t('auth.recovery.noAccessibleAccount.eyebrow'),
69
+ title: t('auth.recovery.noAccessibleAccount.title'),
70
+ body: t('auth.recovery.noAccessibleAccount.body'),
71
+ };
72
+ } else if (kind === 'credential') {
73
+ copy = {
74
+ eyebrow: t('auth.recovery.credential.eyebrow'),
75
+ title: t('auth.recovery.credential.title'),
76
+ body: t('auth.recovery.credential.body'),
77
+ };
78
+ } else {
79
+ copy = {
80
+ eyebrow: t('auth.recovery.service.eyebrow'),
81
+ title: t('auth.recovery.service.title'),
82
+ body: t('auth.recovery.service.body'),
83
+ };
84
+ }
85
+
86
+ const runAction = (action: () => void) => {
87
+ if (submitting) return;
88
+ setSubmitting(true);
89
+ action();
90
+ };
91
+
92
+ return (
93
+ <SignInStepLayout>
94
+ <div role="alert" aria-live="assertive">
95
+ <SignInIconBadge>
96
+ <AlertTriangle className="size-7 text-attention" aria-hidden="true" />
97
+ </SignInIconBadge>
98
+ <SignInStepHeader eyebrow={copy.eyebrow} title={copy.title} body={copy.body} />
99
+ </div>
100
+
101
+ {identity && (
102
+ <SignInAccountRow
103
+ badge={<SignInInitialsBadge initials={emailInitial(identity.email)} />}
104
+ title={identity.name || firstNameFromEmail(identity.email)}
105
+ subtitle={identity.email}
106
+ actionLabel={t('auth.returning.notYou')}
107
+ onAction={onUseDifferentAccount}
108
+ />
109
+ )}
110
+
111
+ <div className="flex flex-col gap-2">
112
+ {onContinue && (
113
+ <SignInStepButton
114
+ ref={initialButtonRef}
115
+ className="w-full"
116
+ disabled={submitting}
117
+ onClick={() => runAction(onContinue)}
118
+ >
119
+ {isScopeFailure ? t('auth.recovery.continue') : t('auth.recovery.tryAgain')}
120
+ </SignInStepButton>
121
+ )}
122
+ <SignInStepButton
123
+ ref={onContinue ? undefined : initialButtonRef}
124
+ variant={onContinue ? 'ghost' : 'primary'}
125
+ disabled={submitting}
126
+ onClick={() => runAction(onUseDifferentAccount)}
127
+ >
128
+ {t('auth.recovery.useDifferentAccount')}
129
+ </SignInStepButton>
130
+ {(kind === 'noAccessibleAccount' || kind === 'service') && (
131
+ <p className="text-center text-xs text-muted">
132
+ {t('auth.recovery.supportPrefix')}{' '}
133
+ <a className="text-info" href="mailto:support@vertesiahq.com">
134
+ support@vertesiahq.com
135
+ </a>
136
+ </p>
137
+ )}
138
+ </div>
139
+
140
+ {details && (
141
+ <details className="rounded-lg border border-mixer-muted/30 bg-mixer-muted/10 px-4 py-3 text-sm">
142
+ <summary className="cursor-pointer font-medium text-muted marker:text-muted focus-visible:outline-2 focus-visible:outline-offset-2">
143
+ {t('auth.recovery.technicalDetails')}
144
+ </summary>
145
+ <dl className="mt-3 grid grid-cols-[max-content_minmax(0,1fr)] gap-x-3 gap-y-2 text-xs">
146
+ {details.errorCode && (
147
+ <>
148
+ <dt className="text-muted">{t('auth.recovery.errorCode')}</dt>
149
+ <dd className="wrap-break-word font-mono">{details.errorCode}</dd>
150
+ </>
151
+ )}
152
+ {details.status && (
153
+ <>
154
+ <dt className="text-muted">{t('auth.recovery.httpStatus')}</dt>
155
+ <dd className="font-mono">{details.status}</dd>
156
+ </>
157
+ )}
158
+ {details.accountId && (
159
+ <>
160
+ <dt className="text-muted">{t('auth.recovery.requestedAccount')}</dt>
161
+ <dd className="wrap-break-word font-mono">{details.accountId}</dd>
162
+ </>
163
+ )}
164
+ {details.projectId && (
165
+ <>
166
+ <dt className="text-muted">{t('auth.recovery.requestedProject')}</dt>
167
+ <dd className="wrap-break-word font-mono">{details.projectId}</dd>
168
+ </>
169
+ )}
170
+ <dt className="text-muted">{t('auth.recovery.errorMessage')}</dt>
171
+ <dd className="wrap-break-word font-mono">{details.message}</dd>
172
+ </dl>
173
+ </details>
174
+ )}
175
+ </SignInStepLayout>
176
+ );
177
+ }
@@ -1,12 +1,22 @@
1
- import type { SignupData, SignupPayload } from '@vertesia/common';
1
+ import { REQUESTED_SCOPE_UNAVAILABLE_ERROR_CODE, type SignupData, type SignupPayload } from '@vertesia/common';
2
2
  import { Env } from '@vertesia/ui/env';
3
3
  import { useUITranslation } from '@vertesia/ui/i18n';
4
4
  import { RegionTag } from '@vertesia/ui/layout';
5
- import { RestrictedEnvironmentError, UserNotFoundError, useUserSession, useUXTracking } from '@vertesia/ui/session';
5
+ import {
6
+ AuthenticationServiceError,
7
+ CredentialError,
8
+ NoAccessibleAccountError,
9
+ RequestedScopeUnavailableError,
10
+ RestrictedEnvironmentError,
11
+ UserNotFoundError,
12
+ useUserSession,
13
+ useUXTracking,
14
+ } from '@vertesia/ui/session';
6
15
  import { useCallback, useEffect, useState } from 'react';
7
16
  import SignInAuthPending from './SignInAuthPending';
8
17
  import SignInEmailStep, { type TenantInfo } from './SignInEmailStep';
9
18
  import SignInProvidersStep from './SignInProvidersStep';
19
+ import SignInRecoveryStep, { type SignInRecoveryKind } from './SignInRecoveryStep';
10
20
  import SignInRestrictedEnvStep from './SignInRestrictedEnvStep';
11
21
  import SignInReturningStep from './SignInReturningStep';
12
22
  import SignInTenantBlockedStep from './SignInTenantBlockedStep';
@@ -65,7 +75,30 @@ function matchesPathPrefix(pathname: string, prefix?: string | string[]) {
65
75
  });
66
76
  }
67
77
 
68
- type Mode = 'email' | 'providers' | 'tenant' | 'blocked' | 'returning' | 'pending' | 'signup' | 'restricted';
78
+ type Mode =
79
+ | 'email'
80
+ | 'providers'
81
+ | 'tenant'
82
+ | 'blocked'
83
+ | 'returning'
84
+ | 'pending'
85
+ | 'signup'
86
+ | 'restricted'
87
+ | 'scopeUnavailable'
88
+ | 'noAccessibleAccount'
89
+ | 'credentialFailure'
90
+ | 'serviceFailure';
91
+
92
+ function isDedicatedAuthError(error: Error): boolean {
93
+ return (
94
+ error instanceof UserNotFoundError ||
95
+ error instanceof RestrictedEnvironmentError ||
96
+ error instanceof RequestedScopeUnavailableError ||
97
+ error instanceof NoAccessibleAccountError ||
98
+ error instanceof CredentialError ||
99
+ error instanceof AuthenticationServiceError
100
+ );
101
+ }
69
102
 
70
103
  function SigninScreenImpl({
71
104
  isNested = false,
@@ -87,8 +120,20 @@ function SigninScreenImpl({
87
120
  const [tenant, setTenant] = useState<TenantInfo | undefined>(undefined);
88
121
  const [pendingProvider, setPendingProvider] = useState<ProviderId | null>(null);
89
122
 
123
+ const recoveryIdentity =
124
+ authError instanceof RequestedScopeUnavailableError || authError instanceof NoAccessibleAccountError
125
+ ? authError.identity
126
+ : undefined;
127
+ const matchingStoredIdentity =
128
+ recoveryIdentity && storedSession?.email.toLowerCase() === recoveryIdentity.email.toLowerCase()
129
+ ? storedSession
130
+ : undefined;
131
+ const displayedRecoveryIdentity = recoveryIdentity
132
+ ? { email: recoveryIdentity.email, name: recoveryIdentity.name ?? matchingStoredIdentity?.name }
133
+ : undefined;
134
+
90
135
  useEffect(() => {
91
- if (!preservePath) {
136
+ if (!preservePath && !isLoading && !authError) {
92
137
  // Reset to the app's mount root, not the bare origin. A gateway-mounted app carries a
93
138
  // served `<base href>` deep mount; collapsing to '/' drops the app off that mount (the
94
139
  // bare origin serves no app) and the address bar can no longer be reloaded. This effect
@@ -99,7 +144,7 @@ function SigninScreenImpl({
99
144
  const mountRoot = new URL(document.baseURI).pathname || '/';
100
145
  history.replaceState({}, '', mountRoot);
101
146
  }
102
- }, [preservePath]);
147
+ }, [authError, isLoading, preservePath]);
103
148
 
104
149
  // Route based on authError surfaced by the session.
105
150
  useEffect(() => {
@@ -108,6 +153,14 @@ function SigninScreenImpl({
108
153
  setMode('signup');
109
154
  } else if (authError instanceof RestrictedEnvironmentError) {
110
155
  setMode('restricted');
156
+ } else if (authError instanceof RequestedScopeUnavailableError) {
157
+ setMode('scopeUnavailable');
158
+ } else if (authError instanceof NoAccessibleAccountError) {
159
+ setMode('noAccessibleAccount');
160
+ } else if (authError instanceof CredentialError) {
161
+ setMode('credentialFailure');
162
+ } else if (authError instanceof AuthenticationServiceError) {
163
+ setMode('serviceFailure');
111
164
  } else if (isInviteRequiredError(authError)) {
112
165
  const pending = readPendingSignin();
113
166
  if (pending) setEmail(pending.email);
@@ -176,6 +229,37 @@ function SigninScreenImpl({
176
229
  void resetSignInState();
177
230
  }, []);
178
231
 
232
+ const useDifferentAccount = useCallback(() => {
233
+ Env.logger.info('Authentication recovery action selected', {
234
+ vertesia: { recovery_action: 'use_different_account' },
235
+ });
236
+ setStoredSession(null);
237
+ setEmail('');
238
+ setTenant(undefined);
239
+ setMode('email');
240
+ void resetSignInState().finally(() => signOut());
241
+ }, [signOut]);
242
+
243
+ const continueWithSanitizedScope = useCallback(() => {
244
+ if (!(authError instanceof RequestedScopeUnavailableError)) return;
245
+ Env.logger.info('Authentication recovery action selected', {
246
+ vertesia: {
247
+ error_code: REQUESTED_SCOPE_UNAVAILABLE_ERROR_CODE,
248
+ selector_source: authError.selectorSource,
249
+ requested_scope: authError.requestedScope,
250
+ recovery_action: 'continue_sanitized',
251
+ },
252
+ });
253
+ window.location.replace(authError.recoveryUrl ?? window.location.href);
254
+ }, [authError]);
255
+
256
+ const retryAuthentication = useCallback(() => {
257
+ Env.logger.info('Authentication recovery action selected', {
258
+ vertesia: { recovery_action: 'retry' },
259
+ });
260
+ window.location.reload();
261
+ }, []);
262
+
179
263
  // Submits the signup form to /auth/signup, then redirects into the app.
180
264
  const onSignup = (data: SignupData, fbToken: string) => {
181
265
  const payload: SignupPayload = { signupData: data, firebaseToken: fbToken };
@@ -190,10 +274,7 @@ function SigninScreenImpl({
190
274
  };
191
275
 
192
276
  const shouldHideTransientAuthError =
193
- suppressAuthError &&
194
- authError !== undefined &&
195
- !(authError instanceof UserNotFoundError) &&
196
- !(authError instanceof RestrictedEnvironmentError);
277
+ suppressAuthError && authError !== undefined && !isDedicatedAuthError(authError);
197
278
 
198
279
  if (isLoading || user || shouldHideTransientAuthError) return null;
199
280
 
@@ -210,6 +291,49 @@ function SigninScreenImpl({
210
291
  );
211
292
  } else if (mode === 'restricted') {
212
293
  content = <SignInRestrictedEnvStep onUseDifferentEmail={startOver} />;
294
+ } else if (mode === 'scopeUnavailable' && authError instanceof RequestedScopeUnavailableError) {
295
+ const kind: SignInRecoveryKind = authError.requestedScope === 'project' ? 'scopeProject' : 'scopeAccount';
296
+ content = (
297
+ <SignInRecoveryStep
298
+ details={{
299
+ accountId: authError.accountId,
300
+ errorCode: authError.errorCode,
301
+ message: authError.message,
302
+ projectId: authError.projectId,
303
+ status: authError.status,
304
+ }}
305
+ identity={displayedRecoveryIdentity}
306
+ kind={kind}
307
+ onContinue={continueWithSanitizedScope}
308
+ onUseDifferentAccount={useDifferentAccount}
309
+ />
310
+ );
311
+ } else if (mode === 'noAccessibleAccount' && authError instanceof NoAccessibleAccountError) {
312
+ content = (
313
+ <SignInRecoveryStep
314
+ details={{ errorCode: authError.errorCode, message: authError.message, status: authError.status }}
315
+ identity={displayedRecoveryIdentity}
316
+ kind="noAccessibleAccount"
317
+ onUseDifferentAccount={useDifferentAccount}
318
+ />
319
+ );
320
+ } else if (mode === 'credentialFailure' && authError instanceof CredentialError) {
321
+ content = (
322
+ <SignInRecoveryStep
323
+ details={{ errorCode: authError.errorCode, message: authError.message, status: authError.status }}
324
+ kind="credential"
325
+ onUseDifferentAccount={useDifferentAccount}
326
+ />
327
+ );
328
+ } else if (mode === 'serviceFailure' && authError instanceof AuthenticationServiceError) {
329
+ content = (
330
+ <SignInRecoveryStep
331
+ details={{ errorCode: authError.errorCode, message: authError.message, status: authError.status }}
332
+ kind="service"
333
+ onContinue={retryAuthentication}
334
+ onUseDifferentAccount={useDifferentAccount}
335
+ />
336
+ );
213
337
  } else if (mode === 'signup' && !localStorage.getItem('tenantName')) {
214
338
  content = <SignupForm onSignup={onSignup} goBack={startOver} />;
215
339
  } else if (mode === 'tenant' && tenant) {
@@ -247,25 +371,19 @@ function SigninScreenImpl({
247
371
 
248
372
  {content}
249
373
 
250
- {authError &&
251
- !(authError instanceof UserNotFoundError) &&
252
- !(authError instanceof RestrictedEnvironmentError) &&
253
- !isInviteRequiredError(authError) && (
254
- <div className="mt-6 max-w-[420px] text-center text-sm text-muted">
255
- <div>
256
- {t('auth.signInError')}
257
- <br />
258
- {t('auth.signInErrorContact')}
259
- <a className="text-info mx-1" href="mailto:support@vertesiahq.com">
260
- support@vertesiahq.com
261
- </a>
262
- {t('auth.signInErrorPersists')}
263
- <pre className="mt-2 text-xs">
264
- {t('auth.error', { message: authError.message })}
265
- </pre>
266
- </div>
374
+ {authError && !isDedicatedAuthError(authError) && !isInviteRequiredError(authError) && (
375
+ <div className="mt-6 max-w-[420px] text-center text-sm text-muted">
376
+ <div>
377
+ {t('auth.signInError')}
378
+ <br />
379
+ {t('auth.signInErrorContact')}
380
+ <a className="text-info mx-1" href="mailto:support@vertesiahq.com">
381
+ support@vertesiahq.com
382
+ </a>
383
+ {t('auth.signInErrorPersists')}
267
384
  </div>
268
- )}
385
+ </div>
386
+ )}
269
387
 
270
388
  <div className="flex items-center gap-5 mt-10 text-xs text-muted-foreground">
271
389
  <a href="https://vertesiahq.com/privacy" className="hover:text-foreground transition">
@@ -13,6 +13,10 @@ import {
13
13
  } from './ArtifactEditingSurface.js';
14
14
  import type { MarkdownEditingAction } from './CollaborativeMarkdownRenderer.js';
15
15
 
16
+ // Document mode is loaded through React.lazy(). CI transforms many test files concurrently, so the
17
+ // first document-mode test can legitimately take longer than Testing Library's one-second default.
18
+ const LAZY_EDITOR_WAIT = { timeout: 5_000 } as const;
19
+
16
20
  const mocks = vi.hoisted(() => {
17
21
  const getArtifactContent = vi.fn();
18
22
  const updateArtifactContent = vi.fn();
@@ -151,7 +155,7 @@ describe('ArtifactEditingSurface', () => {
151
155
  const user = userEvent.setup();
152
156
  renderSurface({ viewMode: 'document' });
153
157
 
154
- const editor = await screen.findByRole('textbox', { name: 'Markdown document editor' });
158
+ const editor = await screen.findByRole('textbox', { name: 'Markdown document editor' }, LAZY_EDITOR_WAIT);
155
159
  await user.click(editor);
156
160
  await user.type(editor, ' revised');
157
161
 
@@ -174,7 +178,7 @@ describe('ArtifactEditingSurface', () => {
174
178
  onSendMessage: vi.fn(),
175
179
  });
176
180
 
177
- const editor = await screen.findByRole('textbox', { name: 'Markdown document editor' });
181
+ const editor = await screen.findByRole('textbox', { name: 'Markdown document editor' }, LAZY_EDITOR_WAIT);
178
182
  expect(editor.getAttribute('contenteditable')).toBe('false');
179
183
  expect(screen.queryByRole('button', { name: 'Comment on selection' })).toBeNull();
180
184
  });
@@ -188,7 +192,7 @@ describe('ArtifactEditingSurface', () => {
188
192
  toolbarStatus: <span>AI is editing</span>,
189
193
  });
190
194
 
191
- const button = await screen.findByRole('button', { name: 'Send changes to agent' });
195
+ const button = await screen.findByRole('button', { name: 'Send changes to agent' }, LAZY_EDITOR_WAIT);
192
196
  expect(screen.getByRole('toolbar').contains(button)).toBe(true);
193
197
  expect(button.previousElementSibling?.textContent).toBe('AI is editing');
194
198
  expect(button).toHaveProperty('disabled', false);
@@ -203,7 +207,7 @@ describe('ArtifactEditingSurface', () => {
203
207
  > = { current: null };
204
208
  renderSurface({ viewMode: 'document', flushChangesRef });
205
209
 
206
- const editor = await screen.findByRole('textbox', { name: 'Markdown document editor' });
210
+ const editor = await screen.findByRole('textbox', { name: 'Markdown document editor' }, LAZY_EDITOR_WAIT);
207
211
  await user.click(editor);
208
212
  await user.type(editor, ' immediate');
209
213
 
@@ -228,7 +232,7 @@ describe('ArtifactEditingSurface', () => {
228
232
  });
229
233
  const view = renderSurface({ viewMode: 'document' });
230
234
 
231
- fireEvent.click(await screen.findByRole('button', { name: 'Edit Markdown source' }));
235
+ fireEvent.click(await screen.findByRole('button', { name: 'Edit Markdown source' }, LAZY_EDITOR_WAIT));
232
236
  const sourceEditor = screen.getByRole('textbox', { name: 'Markdown source editor' });
233
237
  fireEvent.focus(sourceEditor);
234
238
  fireEvent.change(sourceEditor, {
@@ -249,7 +253,7 @@ describe('ArtifactEditingSurface', () => {
249
253
  it('shows a navigable ruler for changes from the original document', async () => {
250
254
  renderSurface({ viewMode: 'document', baselineContent: 'Different paragraph.' });
251
255
 
252
- await screen.findByRole('textbox', { name: 'Markdown document editor' });
256
+ await screen.findByRole('textbox', { name: 'Markdown document editor' }, LAZY_EDITOR_WAIT);
253
257
  expect(screen.getByRole('navigation', { name: 'Change ruler' })).not.toBeNull();
254
258
  expect(screen.getByRole('button', { name: 'Change near line 1' })).not.toBeNull();
255
259
  });
@@ -257,7 +261,7 @@ describe('ArtifactEditingSurface', () => {
257
261
  it('keeps the focused editor base generation when the agent refreshes the artifact', async () => {
258
262
  const user = userEvent.setup();
259
263
  const view = renderSurface({ viewMode: 'document' });
260
- const editor = await screen.findByRole('textbox', { name: 'Markdown document editor' });
264
+ const editor = await screen.findByRole('textbox', { name: 'Markdown document editor' }, LAZY_EDITOR_WAIT);
261
265
  await user.click(editor);
262
266
 
263
267
  mocks.getArtifactContent.mockResolvedValueOnce({
@@ -311,7 +315,7 @@ describe('ArtifactEditingSurface', () => {
311
315
  .mockResolvedValueOnce({ path: 'drafts/document.md', generation: 'generation-merged' });
312
316
 
313
317
  const view = renderSurface({ viewMode: 'document' });
314
- const editor = await screen.findByRole('textbox', { name: 'Markdown document editor' });
318
+ const editor = await screen.findByRole('textbox', { name: 'Markdown document editor' }, LAZY_EDITOR_WAIT);
315
319
  await user.click(editor);
316
320
 
317
321
  view.rerender(
@@ -363,7 +367,7 @@ describe('ArtifactEditingSurface', () => {
363
367
  mocks.updateArtifactContent.mockRejectedValueOnce({ status: 412 });
364
368
  renderSurface({ viewMode: 'document' });
365
369
 
366
- const editor = await screen.findByRole('textbox', { name: 'Markdown document editor' });
370
+ const editor = await screen.findByRole('textbox', { name: 'Markdown document editor' }, LAZY_EDITOR_WAIT);
367
371
  await user.click(editor);
368
372
  await user.type(editor, ' local edit');
369
373