@vertesia/ui 1.5.0-dev.20260807.073259Z → 1.5.0-dev.20260826.064249Z

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 (432) hide show
  1. package/README.md +1 -7
  2. package/lib/core/components/shadcn/filters/comboBox/DateCombobox.js +1 -1
  3. package/lib/core/components/shadcn/filters/comboBox/DateCombobox.js.map +1 -1
  4. package/lib/core/components/shadcn/filters/filter/dateFilter.d.ts.map +1 -1
  5. package/lib/core/components/shadcn/filters/filter/dateFilter.js +1 -1
  6. package/lib/core/components/shadcn/filters/filter/dateFilter.js.map +1 -1
  7. package/lib/core/components/shadcn/filters/filters.d.ts.map +1 -1
  8. package/lib/core/components/shadcn/filters/filters.js +1 -1
  9. package/lib/core/components/shadcn/filters/filters.js.map +1 -1
  10. package/lib/core/components/shadcn/index.d.ts +1 -0
  11. package/lib/core/components/shadcn/index.d.ts.map +1 -1
  12. package/lib/core/components/shadcn/index.js +1 -0
  13. package/lib/core/components/shadcn/index.js.map +1 -1
  14. package/lib/core/components/shadcn/modal/dialog.d.ts.map +1 -1
  15. package/lib/core/components/shadcn/modal/dialog.js +1 -3
  16. package/lib/core/components/shadcn/modal/dialog.js.map +1 -1
  17. package/lib/core/components/shadcn/overflowTabs.d.ts +59 -0
  18. package/lib/core/components/shadcn/overflowTabs.d.ts.map +1 -0
  19. package/lib/core/components/shadcn/overflowTabs.js +173 -0
  20. package/lib/core/components/shadcn/overflowTabs.js.map +1 -0
  21. package/lib/core/components/shadcn/selectBox.js +2 -2
  22. package/lib/core/components/shadcn/selectBox.js.map +1 -1
  23. package/lib/core/components/shadcn/theme/ThemeProvider.d.ts +3 -1
  24. package/lib/core/components/shadcn/theme/ThemeProvider.d.ts.map +1 -1
  25. package/lib/core/components/shadcn/theme/ThemeProvider.js +8 -9
  26. package/lib/core/components/shadcn/theme/ThemeProvider.js.map +1 -1
  27. package/lib/core/utils/dayjs.d.ts +12 -0
  28. package/lib/core/utils/dayjs.d.ts.map +1 -0
  29. package/lib/core/utils/dayjs.js +16 -0
  30. package/lib/core/utils/dayjs.js.map +1 -0
  31. package/lib/env/index.d.ts +17 -0
  32. package/lib/env/index.d.ts.map +1 -1
  33. package/lib/env/index.js +18 -1
  34. package/lib/env/index.js.map +1 -1
  35. package/lib/features/agent/PayloadBuilder.d.ts +1 -0
  36. package/lib/features/agent/PayloadBuilder.d.ts.map +1 -1
  37. package/lib/features/agent/PayloadBuilder.js +22 -5
  38. package/lib/features/agent/PayloadBuilder.js.map +1 -1
  39. package/lib/features/agent/chat/AgentRightPanel.d.ts.map +1 -1
  40. package/lib/features/agent/chat/AgentRightPanel.js +3 -135
  41. package/lib/features/agent/chat/AgentRightPanel.js.map +1 -1
  42. package/lib/features/agent/chat/ArtifactsTab.d.ts.map +1 -1
  43. package/lib/features/agent/chat/ArtifactsTab.js +1 -1
  44. package/lib/features/agent/chat/ArtifactsTab.js.map +1 -1
  45. package/lib/features/agent/chat/AskUserWidget.d.ts.map +1 -1
  46. package/lib/features/agent/chat/AskUserWidget.js +19 -4
  47. package/lib/features/agent/chat/AskUserWidget.js.map +1 -1
  48. package/lib/features/agent/chat/ModernAgentConversation.d.ts +6 -0
  49. package/lib/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
  50. package/lib/features/agent/chat/ModernAgentConversation.js +99 -29
  51. package/lib/features/agent/chat/ModernAgentConversation.js.map +1 -1
  52. package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.d.ts.map +1 -1
  53. package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.js +10 -9
  54. package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.js.map +1 -1
  55. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
  56. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +5 -8
  57. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
  58. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.d.ts.map +1 -1
  59. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js +45 -4
  60. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js.map +1 -1
  61. package/lib/features/agent/chat/ModernAgentOutput/BatchProgressPanel.js +1 -1
  62. package/lib/features/agent/chat/ModernAgentOutput/BatchProgressPanel.js.map +1 -1
  63. package/lib/features/agent/chat/ModernAgentOutput/Header.d.ts.map +1 -1
  64. package/lib/features/agent/chat/ModernAgentOutput/Header.js +3 -3
  65. package/lib/features/agent/chat/ModernAgentOutput/Header.js.map +1 -1
  66. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.d.ts.map +1 -1
  67. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js +1 -1
  68. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -1
  69. package/lib/features/agent/chat/ModernAgentOutput/StreamingMessage.d.ts.map +1 -1
  70. package/lib/features/agent/chat/ModernAgentOutput/StreamingMessage.js +1 -1
  71. package/lib/features/agent/chat/ModernAgentOutput/StreamingMessage.js.map +1 -1
  72. package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.js +1 -1
  73. package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.js.map +1 -1
  74. package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.d.ts.map +1 -1
  75. package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js +9 -121
  76. package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js.map +1 -1
  77. package/lib/features/agent/chat/ModernAgentOutput/utils.d.ts +6 -0
  78. package/lib/features/agent/chat/ModernAgentOutput/utils.d.ts.map +1 -1
  79. package/lib/features/agent/chat/ModernAgentOutput/utils.js +19 -11
  80. package/lib/features/agent/chat/ModernAgentOutput/utils.js.map +1 -1
  81. package/lib/features/agent/chat/VegaLiteChart.d.ts.map +1 -1
  82. package/lib/features/agent/chat/VegaLiteChart.js +11 -3
  83. package/lib/features/agent/chat/VegaLiteChart.js.map +1 -1
  84. package/lib/features/agent/chat/hooks/useAgentStream.d.ts.map +1 -1
  85. package/lib/features/agent/chat/hooks/useAgentStream.js +3 -0
  86. package/lib/features/agent/chat/hooks/useAgentStream.js.map +1 -1
  87. package/lib/features/document-viewer/UniversalDocumentViewer.d.ts.map +1 -1
  88. package/lib/features/document-viewer/UniversalDocumentViewer.js +1 -1
  89. package/lib/features/document-viewer/UniversalDocumentViewer.js.map +1 -1
  90. package/lib/features/facets/AgentRunnerFacetsNav.d.ts +14 -2
  91. package/lib/features/facets/AgentRunnerFacetsNav.d.ts.map +1 -1
  92. package/lib/features/facets/AgentRunnerFacetsNav.js +20 -2
  93. package/lib/features/facets/AgentRunnerFacetsNav.js.map +1 -1
  94. package/lib/features/facets/CollectionsFacetsNav.d.ts +3 -3
  95. package/lib/features/facets/CollectionsFacetsNav.d.ts.map +1 -1
  96. package/lib/features/facets/CollectionsFacetsNav.js +6 -1
  97. package/lib/features/facets/CollectionsFacetsNav.js.map +1 -1
  98. package/lib/features/facets/DocumentsFacetsNav.d.ts +3 -3
  99. package/lib/features/facets/DocumentsFacetsNav.d.ts.map +1 -1
  100. package/lib/features/facets/DocumentsFacetsNav.js +20 -8
  101. package/lib/features/facets/DocumentsFacetsNav.js.map +1 -1
  102. package/lib/features/facets/InteractionsFacetsNav.d.ts +3 -3
  103. package/lib/features/facets/InteractionsFacetsNav.d.ts.map +1 -1
  104. package/lib/features/facets/InteractionsFacetsNav.js +11 -1
  105. package/lib/features/facets/InteractionsFacetsNav.js.map +1 -1
  106. package/lib/features/facets/PromptsFacetsNav.d.ts +3 -3
  107. package/lib/features/facets/PromptsFacetsNav.d.ts.map +1 -1
  108. package/lib/features/facets/PromptsFacetsNav.js +6 -1
  109. package/lib/features/facets/PromptsFacetsNav.js.map +1 -1
  110. package/lib/features/facets/RunsFacetsNav.d.ts +4 -14
  111. package/lib/features/facets/RunsFacetsNav.d.ts.map +1 -1
  112. package/lib/features/facets/RunsFacetsNav.js +26 -15
  113. package/lib/features/facets/RunsFacetsNav.js.map +1 -1
  114. package/lib/features/facets/WorkflowExecutionsFacetsNav.d.ts +4 -3
  115. package/lib/features/facets/WorkflowExecutionsFacetsNav.d.ts.map +1 -1
  116. package/lib/features/facets/WorkflowExecutionsFacetsNav.js +18 -10
  117. package/lib/features/facets/WorkflowExecutionsFacetsNav.js.map +1 -1
  118. package/lib/features/facets/index.d.ts +1 -1
  119. package/lib/features/facets/index.d.ts.map +1 -1
  120. package/lib/features/facets/index.js.map +1 -1
  121. package/lib/features/facets/utils/SearchInterface.d.ts +4 -3
  122. package/lib/features/facets/utils/SearchInterface.d.ts.map +1 -1
  123. package/lib/features/facets/utils/SearchInterface.js +4 -0
  124. package/lib/features/facets/utils/SearchInterface.js.map +1 -1
  125. package/lib/features/layout/GenericPageNavHeader.d.ts +8 -1
  126. package/lib/features/layout/GenericPageNavHeader.d.ts.map +1 -1
  127. package/lib/features/layout/GenericPageNavHeader.js +9 -1
  128. package/lib/features/layout/GenericPageNavHeader.js.map +1 -1
  129. package/lib/features/magic-pdf/DownloadPopover.d.ts +3 -2
  130. package/lib/features/magic-pdf/DownloadPopover.d.ts.map +1 -1
  131. package/lib/features/magic-pdf/DownloadPopover.js.map +1 -1
  132. package/lib/features/magic-pdf/GroundedExtractionView.d.ts.map +1 -1
  133. package/lib/features/magic-pdf/GroundedExtractionView.js +51 -64
  134. package/lib/features/magic-pdf/GroundedExtractionView.js.map +1 -1
  135. package/lib/features/oauth/McpConnectionsButton.d.ts +1 -1
  136. package/lib/features/oauth/McpConnectionsButton.d.ts.map +1 -1
  137. package/lib/features/oauth/McpConnectionsButton.js +2 -2
  138. package/lib/features/oauth/McpConnectionsButton.js.map +1 -1
  139. package/lib/features/oauth/McpConnectionsDialog.d.ts +1 -1
  140. package/lib/features/oauth/McpConnectionsDialog.js +2 -2
  141. package/lib/features/oauth/McpConnectionsDialog.js.map +1 -1
  142. package/lib/features/oauth/useMcpConnections.d.ts +4 -5
  143. package/lib/features/oauth/useMcpConnections.d.ts.map +1 -1
  144. package/lib/features/oauth/useMcpConnections.js +20 -4
  145. package/lib/features/oauth/useMcpConnections.js.map +1 -1
  146. package/lib/features/pdf-viewer/PdfPageRenderer.d.ts.map +1 -1
  147. package/lib/features/pdf-viewer/PdfPageRenderer.js +9 -11
  148. package/lib/features/pdf-viewer/PdfPageRenderer.js.map +1 -1
  149. package/lib/features/pdf-viewer/lazyReactPdf.d.ts +10 -0
  150. package/lib/features/pdf-viewer/lazyReactPdf.d.ts.map +1 -0
  151. package/lib/features/pdf-viewer/lazyReactPdf.js +25 -0
  152. package/lib/features/pdf-viewer/lazyReactPdf.js.map +1 -0
  153. package/lib/features/store/collections/CollectionsTable.d.ts.map +1 -1
  154. package/lib/features/store/collections/CollectionsTable.js +1 -3
  155. package/lib/features/store/collections/CollectionsTable.js.map +1 -1
  156. package/lib/features/store/collections/EditCollectionView.js +1 -1
  157. package/lib/features/store/collections/EditCollectionView.js.map +1 -1
  158. package/lib/features/store/objects/ExportPropertiesModal.d.ts +3 -1
  159. package/lib/features/store/objects/ExportPropertiesModal.d.ts.map +1 -1
  160. package/lib/features/store/objects/ExportPropertiesModal.js +5 -5
  161. package/lib/features/store/objects/ExportPropertiesModal.js.map +1 -1
  162. package/lib/features/store/objects/components/ContentOverview.d.ts.map +1 -1
  163. package/lib/features/store/objects/components/ContentOverview.js +4 -10
  164. package/lib/features/store/objects/components/ContentOverview.js.map +1 -1
  165. package/lib/features/store/objects/components/TextEditorPanel.d.ts.map +1 -1
  166. package/lib/features/store/objects/components/TextEditorPanel.js +8 -3
  167. package/lib/features/store/objects/components/TextEditorPanel.js.map +1 -1
  168. package/lib/features/store/objects/layout/renderers.d.ts.map +1 -1
  169. package/lib/features/store/objects/layout/renderers.js +1 -5
  170. package/lib/features/store/objects/layout/renderers.js.map +1 -1
  171. package/lib/features/store/objects/search/DocumentSearchContext.d.ts +29 -62
  172. package/lib/features/store/objects/search/DocumentSearchContext.d.ts.map +1 -1
  173. package/lib/features/store/objects/search/DocumentSearchContext.js +2 -0
  174. package/lib/features/store/objects/search/DocumentSearchContext.js.map +1 -1
  175. package/lib/features/store/objects/upload/DocumentUploadModal.d.ts +6 -1
  176. package/lib/features/store/objects/upload/DocumentUploadModal.d.ts.map +1 -1
  177. package/lib/features/store/objects/upload/DocumentUploadModal.js +4 -3
  178. package/lib/features/store/objects/upload/DocumentUploadModal.js.map +1 -1
  179. package/lib/features/store/objects/upload/useSmartFileUploadProcessing.d.ts.map +1 -1
  180. package/lib/features/store/objects/upload/useSmartFileUploadProcessing.js +2 -2
  181. package/lib/features/store/objects/upload/useSmartFileUploadProcessing.js.map +1 -1
  182. package/lib/features/store/types/ContentObjectTypesTable.d.ts.map +1 -1
  183. package/lib/features/store/types/ContentObjectTypesTable.js +1 -3
  184. package/lib/features/store/types/ContentObjectTypesTable.js.map +1 -1
  185. package/lib/features/store/types/IntakePolicyEditor.d.ts.map +1 -1
  186. package/lib/features/store/types/IntakePolicyEditor.js +11 -1
  187. package/lib/features/store/types/IntakePolicyEditor.js.map +1 -1
  188. package/lib/features/store/types/ObjectSchemaEditor.d.ts.map +1 -1
  189. package/lib/features/store/types/ObjectSchemaEditor.js +6 -2
  190. package/lib/features/store/types/ObjectSchemaEditor.js.map +1 -1
  191. package/lib/features/store/types/TableLayoutEditor.d.ts.map +1 -1
  192. package/lib/features/store/types/TableLayoutEditor.js +2 -0
  193. package/lib/features/store/types/TableLayoutEditor.js.map +1 -1
  194. package/lib/features/store/types/TypeRegistry.d.ts +272 -0
  195. package/lib/features/store/types/TypeRegistry.d.ts.map +1 -1
  196. package/lib/features/store/types/search/ObjectTypeSearchContext.d.ts +271 -0
  197. package/lib/features/store/types/search/ObjectTypeSearchContext.d.ts.map +1 -1
  198. package/lib/features/user/UserInfo.d.ts.map +1 -1
  199. package/lib/features/user/UserInfo.js +2 -4
  200. package/lib/features/user/UserInfo.js.map +1 -1
  201. package/lib/features/views/ViewActions.d.ts +32 -0
  202. package/lib/features/views/ViewActions.d.ts.map +1 -0
  203. package/lib/features/views/ViewActions.js +186 -0
  204. package/lib/features/views/ViewActions.js.map +1 -0
  205. package/lib/features/views/ViewDropTarget.d.ts +15 -0
  206. package/lib/features/views/ViewDropTarget.d.ts.map +1 -0
  207. package/lib/features/views/ViewDropTarget.js +79 -0
  208. package/lib/features/views/ViewDropTarget.js.map +1 -0
  209. package/lib/features/views/ViewExperience.d.ts +3 -2
  210. package/lib/features/views/ViewExperience.d.ts.map +1 -1
  211. package/lib/features/views/ViewExperience.js +103 -12
  212. package/lib/features/views/ViewExperience.js.map +1 -1
  213. package/lib/features/views/ViewNavigation.d.ts +1 -1
  214. package/lib/features/views/ViewNavigation.d.ts.map +1 -1
  215. package/lib/features/views/ViewNavigation.js +14 -5
  216. package/lib/features/views/ViewNavigation.js.map +1 -1
  217. package/lib/features/views/ViewResults.d.ts +1 -1
  218. package/lib/features/views/ViewResults.d.ts.map +1 -1
  219. package/lib/features/views/ViewResults.js +124 -34
  220. package/lib/features/views/ViewResults.js.map +1 -1
  221. package/lib/features/views/index.d.ts +1 -0
  222. package/lib/features/views/index.d.ts.map +1 -1
  223. package/lib/features/views/index.js +1 -0
  224. package/lib/features/views/index.js.map +1 -1
  225. package/lib/features/views/types.d.ts +46 -1
  226. package/lib/features/views/types.d.ts.map +1 -1
  227. package/lib/features/views/viewState.d.ts.map +1 -1
  228. package/lib/features/views/viewState.js +34 -0
  229. package/lib/features/views/viewState.js.map +1 -1
  230. package/lib/i18n/LanguageProvider.d.ts +3 -1
  231. package/lib/i18n/LanguageProvider.d.ts.map +1 -1
  232. package/lib/i18n/LanguageProvider.js +9 -7
  233. package/lib/i18n/LanguageProvider.js.map +1 -1
  234. package/lib/i18n/instance.d.ts +2 -0
  235. package/lib/i18n/instance.d.ts.map +1 -1
  236. package/lib/i18n/instance.js +45 -26
  237. package/lib/i18n/instance.js.map +1 -1
  238. package/lib/i18n/locales/ar.json +261 -15
  239. package/lib/i18n/locales/de.json +259 -13
  240. package/lib/i18n/locales/en.json +30 -4
  241. package/lib/i18n/locales/es.json +260 -14
  242. package/lib/i18n/locales/fr.json +259 -13
  243. package/lib/i18n/locales/it.json +259 -13
  244. package/lib/i18n/locales/ja.json +257 -10
  245. package/lib/i18n/locales/ko.json +257 -10
  246. package/lib/i18n/locales/pt.json +259 -13
  247. package/lib/i18n/locales/ru.json +256 -10
  248. package/lib/i18n/locales/tr.json +256 -10
  249. package/lib/i18n/locales/zh-TW.json +257 -10
  250. package/lib/i18n/locales/zh.json +257 -10
  251. package/lib/session/UserSessionProvider.d.ts.map +1 -1
  252. package/lib/session/UserSessionProvider.js +8 -16
  253. package/lib/session/UserSessionProvider.js.map +1 -1
  254. package/lib/session/auth/composable.d.ts.map +1 -1
  255. package/lib/session/auth/composable.js +25 -19
  256. package/lib/session/auth/composable.js.map +1 -1
  257. package/lib/session/auth/firebase.js +1 -1
  258. package/lib/session/auth/firebase.js.map +1 -1
  259. package/lib/shell/VertesiaShell.d.ts.map +1 -1
  260. package/lib/shell/VertesiaShell.js +2 -1
  261. package/lib/shell/VertesiaShell.js.map +1 -1
  262. package/lib/shell/apps/AppInstallationProvider.d.ts +4 -2
  263. package/lib/shell/apps/AppInstallationProvider.d.ts.map +1 -1
  264. package/lib/shell/apps/IframeAppContextSync.d.ts +3 -0
  265. package/lib/shell/apps/IframeAppContextSync.d.ts.map +1 -0
  266. package/lib/shell/apps/IframeAppContextSync.js +95 -0
  267. package/lib/shell/apps/IframeAppContextSync.js.map +1 -0
  268. package/lib/shell/apps/iframe-auth.d.ts +55 -0
  269. package/lib/shell/apps/iframe-auth.d.ts.map +1 -0
  270. package/lib/shell/apps/iframe-auth.js +154 -0
  271. package/lib/shell/apps/iframe-auth.js.map +1 -0
  272. package/lib/shell/apps/index.d.ts +2 -0
  273. package/lib/shell/apps/index.d.ts.map +1 -1
  274. package/lib/shell/apps/index.js +2 -0
  275. package/lib/shell/apps/index.js.map +1 -1
  276. package/lib/vertesia-ui-core.js +4 -4
  277. package/lib/vertesia-ui-core.js.map +1 -1
  278. package/lib/vertesia-ui-env.js +1 -1
  279. package/lib/vertesia-ui-env.js.map +1 -1
  280. package/lib/vertesia-ui-features.js +32 -34
  281. package/lib/vertesia-ui-features.js.map +1 -1
  282. package/lib/vertesia-ui-i18n.js +16 -16
  283. package/lib/vertesia-ui-i18n.js.map +1 -1
  284. package/lib/vertesia-ui-rich-text.js +4 -4
  285. package/lib/vertesia-ui-rich-text.js.map +1 -1
  286. package/lib/vertesia-ui-router.js +1 -1
  287. package/lib/vertesia-ui-router.js.map +1 -1
  288. package/lib/vertesia-ui-session.js +1 -1
  289. package/lib/vertesia-ui-session.js.map +1 -1
  290. package/lib/vertesia-ui-shell.js +1 -1
  291. package/lib/vertesia-ui-shell.js.map +1 -1
  292. package/lib/vertesia-ui-widgets.js +20 -20
  293. package/lib/vertesia-ui-widgets.js.map +1 -1
  294. package/lib/widgets/markdown/MarkdownRenderer.d.ts.map +1 -1
  295. package/lib/widgets/markdown/MarkdownRenderer.js +43 -2
  296. package/lib/widgets/markdown/MarkdownRenderer.js.map +1 -1
  297. package/lib/widgets/markdown/MermaidDiagram.d.ts.map +1 -1
  298. package/lib/widgets/markdown/MermaidDiagram.js +35 -22
  299. package/lib/widgets/markdown/MermaidDiagram.js.map +1 -1
  300. package/lib/widgets/monacoEditor/MonacoEditor.d.ts.map +1 -1
  301. package/lib/widgets/monacoEditor/MonacoEditor.js +14 -10
  302. package/lib/widgets/monacoEditor/MonacoEditor.js.map +1 -1
  303. package/lib/widgets/xml-viewer/hooks/useCollapsible.d.ts +1 -1
  304. package/package.json +24 -29
  305. package/src/core/components/shadcn/filters/comboBox/DateCombobox.tsx +1 -1
  306. package/src/core/components/shadcn/filters/filter/dateFilter.tsx +1 -1
  307. package/src/core/components/shadcn/filters/filters.tsx +1 -1
  308. package/src/core/components/shadcn/index.ts +1 -0
  309. package/src/core/components/shadcn/modal/dialog.test.tsx +35 -0
  310. package/src/core/components/shadcn/modal/dialog.tsx +0 -4
  311. package/src/core/components/shadcn/overflowTabs.tsx +320 -0
  312. package/src/core/components/shadcn/selectBox.tsx +2 -2
  313. package/src/core/components/shadcn/theme/ThemeProvider.tsx +10 -9
  314. package/src/core/utils/dayjs.ts +17 -0
  315. package/src/css/base.css +78 -0
  316. package/src/env/index.test.ts +94 -0
  317. package/src/env/index.ts +36 -1
  318. package/src/features/agent/PayloadBuilder.test.ts +68 -0
  319. package/src/features/agent/PayloadBuilder.tsx +28 -4
  320. package/src/features/agent/chat/AgentRightPanel.tsx +2 -252
  321. package/src/features/agent/chat/ArtifactsTab.tsx +1 -0
  322. package/src/features/agent/chat/AskUserWidget.test.tsx +20 -1
  323. package/src/features/agent/chat/AskUserWidget.tsx +22 -6
  324. package/src/features/agent/chat/ModernAgentConversation.test.tsx +160 -0
  325. package/src/features/agent/chat/ModernAgentConversation.tsx +111 -31
  326. package/src/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.tsx +86 -67
  327. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.test.tsx +90 -7
  328. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +4 -6
  329. package/src/features/agent/chat/ModernAgentOutput/AttachmentPreview.test.ts +103 -1
  330. package/src/features/agent/chat/ModernAgentOutput/AttachmentPreview.tsx +50 -4
  331. package/src/features/agent/chat/ModernAgentOutput/BatchProgressPanel.tsx +1 -1
  332. package/src/features/agent/chat/ModernAgentOutput/Header.tsx +18 -1
  333. package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +1 -1
  334. package/src/features/agent/chat/ModernAgentOutput/StreamingMessage.tsx +1 -1
  335. package/src/features/agent/chat/ModernAgentOutput/ToolCallGroup.tsx +1 -1
  336. package/src/features/agent/chat/ModernAgentOutput/WorkstreamTabs.tsx +37 -167
  337. package/src/features/agent/chat/ModernAgentOutput/utils.test.ts +94 -0
  338. package/src/features/agent/chat/ModernAgentOutput/utils.ts +19 -10
  339. package/src/features/agent/chat/VegaLiteChart.tsx +32 -14
  340. package/src/features/agent/chat/hooks/useAgentStream.test.tsx +18 -0
  341. package/src/features/agent/chat/hooks/useAgentStream.ts +3 -0
  342. package/src/features/document-viewer/UniversalDocumentViewer.tsx +1 -1
  343. package/src/features/facets/AgentRunnerFacetsNav.tsx +44 -4
  344. package/src/features/facets/CollectionsFacetsNav.tsx +15 -4
  345. package/src/features/facets/DocumentsFacetsNav.tsx +25 -8
  346. package/src/features/facets/FacetQueryHandlers.test.ts +84 -0
  347. package/src/features/facets/InteractionsFacetsNav.tsx +20 -4
  348. package/src/features/facets/PromptsFacetsNav.tsx +15 -4
  349. package/src/features/facets/RunsFacetsNav.test.ts +59 -0
  350. package/src/features/facets/RunsFacetsNav.tsx +40 -30
  351. package/src/features/facets/WorkflowExecutionsFacetsNav.test.ts +57 -0
  352. package/src/features/facets/WorkflowExecutionsFacetsNav.tsx +36 -16
  353. package/src/features/facets/index.ts +1 -0
  354. package/src/features/facets/utils/SearchInterface.tsx +12 -3
  355. package/src/features/layout/GenericPageNavHeader.tsx +16 -0
  356. package/src/features/magic-pdf/DownloadPopover.tsx +1 -2
  357. package/src/features/magic-pdf/GroundedExtractionView.test.tsx +7 -1
  358. package/src/features/magic-pdf/GroundedExtractionView.tsx +162 -242
  359. package/src/features/oauth/McpConnectionsButton.test.tsx +18 -1
  360. package/src/features/oauth/McpConnectionsButton.tsx +6 -2
  361. package/src/features/oauth/McpConnectionsDialog.tsx +3 -3
  362. package/src/features/oauth/useMcpConnections.test.ts +1 -0
  363. package/src/features/oauth/useMcpConnections.ts +24 -7
  364. package/src/features/pdf-viewer/PdfPageRenderer.tsx +76 -71
  365. package/src/features/pdf-viewer/lazyReactPdf.ts +33 -0
  366. package/src/features/store/collections/CollectionsTable.tsx +1 -4
  367. package/src/features/store/collections/EditCollectionView.tsx +1 -1
  368. package/src/features/store/objects/ExportPropertiesModal.tsx +25 -16
  369. package/src/features/store/objects/components/ContentOverview.tsx +2 -28
  370. package/src/features/store/objects/components/TextEditorPanel.tsx +13 -3
  371. package/src/features/store/objects/layout/renderers.tsx +1 -6
  372. package/src/features/store/objects/search/DocumentSearchContext.ts +4 -2
  373. package/src/features/store/objects/upload/DocumentUploadModal.tsx +10 -3
  374. package/src/features/store/objects/upload/useSmartFileUploadProcessing.ts +15 -6
  375. package/src/features/store/types/ContentObjectTypesTable.tsx +1 -4
  376. package/src/features/store/types/IntakePolicyEditor.tsx +11 -1
  377. package/src/features/store/types/ObjectSchemaEditor.tsx +6 -2
  378. package/src/features/store/types/TableLayoutEditor.tsx +2 -0
  379. package/src/features/user/UserInfo.test.tsx +10 -0
  380. package/src/features/user/UserInfo.tsx +2 -7
  381. package/src/features/views/ViewActions.test.tsx +80 -0
  382. package/src/features/views/ViewActions.tsx +352 -0
  383. package/src/features/views/ViewDropTarget.test.tsx +150 -0
  384. package/src/features/views/ViewDropTarget.tsx +140 -0
  385. package/src/features/views/ViewExperience.test.tsx +72 -0
  386. package/src/features/views/ViewExperience.tsx +189 -22
  387. package/src/features/views/ViewMedia.test.tsx +180 -0
  388. package/src/features/views/ViewNavigation.test.tsx +42 -0
  389. package/src/features/views/ViewNavigation.tsx +43 -5
  390. package/src/features/views/ViewResults.tsx +243 -26
  391. package/src/features/views/index.ts +1 -0
  392. package/src/features/views/types.ts +50 -0
  393. package/src/features/views/viewState.test.ts +7 -1
  394. package/src/features/views/viewState.ts +32 -0
  395. package/src/i18n/LanguageProvider.tsx +15 -8
  396. package/src/i18n/instance.test.ts +30 -0
  397. package/src/i18n/instance.ts +67 -40
  398. package/src/i18n/locales/ar.json +1157 -911
  399. package/src/i18n/locales/de.json +1113 -867
  400. package/src/i18n/locales/en.json +30 -4
  401. package/src/i18n/locales/es.json +1124 -878
  402. package/src/i18n/locales/fr.json +1124 -878
  403. package/src/i18n/locales/it.json +1124 -878
  404. package/src/i18n/locales/ja.json +1113 -866
  405. package/src/i18n/locales/ko.json +1113 -866
  406. package/src/i18n/locales/pt.json +1124 -878
  407. package/src/i18n/locales/ru.json +1135 -889
  408. package/src/i18n/locales/tr.json +1113 -867
  409. package/src/i18n/locales/zh-TW.json +1113 -866
  410. package/src/i18n/locales/zh.json +1113 -866
  411. package/src/i18n/rtl.test.ts +16 -7
  412. package/src/rich-text/VertesiaRichTextEditor.test.tsx +33 -1
  413. package/src/session/UserSessionProvider.tsx +8 -20
  414. package/src/session/auth/composable.scope.test.ts +1 -1
  415. package/src/session/auth/composable.test.ts +61 -1
  416. package/src/session/auth/composable.ts +29 -23
  417. package/src/session/auth/firebase.ts +1 -1
  418. package/src/shell/VertesiaShell.tsx +2 -0
  419. package/src/shell/apps/IframeAppContextSync.test.tsx +196 -0
  420. package/src/shell/apps/IframeAppContextSync.tsx +101 -0
  421. package/src/shell/apps/iframe-auth.test.ts +118 -0
  422. package/src/shell/apps/iframe-auth.ts +193 -0
  423. package/src/shell/apps/index.ts +2 -0
  424. package/src/widgets/markdown/ArtifactEditingSurface.test.tsx +12 -3
  425. package/src/widgets/markdown/MarkdownRenderer.tsx +50 -2
  426. package/src/widgets/markdown/MermaidDiagram.tsx +38 -22
  427. package/src/widgets/monacoEditor/MonacoEditor.tsx +27 -20
  428. package/lib/features/magic-pdf/GroundedExtractionAssistantPanel.d.ts +0 -25
  429. package/lib/features/magic-pdf/GroundedExtractionAssistantPanel.d.ts.map +0 -1
  430. package/lib/features/magic-pdf/GroundedExtractionAssistantPanel.js +0 -42
  431. package/lib/features/magic-pdf/GroundedExtractionAssistantPanel.js.map +0 -1
  432. package/src/features/magic-pdf/GroundedExtractionAssistantPanel.tsx +0 -86
@@ -1,6 +1,9 @@
1
+ import { readdirSync, readFileSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
1
4
  import i18next from 'i18next';
2
5
  import { describe, expect, it } from 'vitest';
3
- import { i18nInstance, NAMESPACE } from './instance.js';
6
+ import { AVAILABLE_LOCALES, NAMESPACE } from './instance.js';
4
7
  import { isRTL, RTL_LANGUAGES, resolveLanguage, SUPPORTED_LANGUAGES } from './rtl.js';
5
8
 
6
9
  describe('isRTL', () => {
@@ -67,10 +70,10 @@ describe('RTL_LANGUAGES set', () => {
67
70
  });
68
71
 
69
72
  describe('SUPPORTED_LANGUAGES divergence guard', () => {
70
- it('matches exactly the locales registered in i18nInstance.options.resources', () => {
71
- const registered = Object.keys(i18nInstance.options.resources ?? {}).sort();
73
+ it('matches exactly the locales the i18n instance can serve', () => {
74
+ const available = [...AVAILABLE_LOCALES].sort();
72
75
  const supported = [...SUPPORTED_LANGUAGES].sort();
73
- expect(registered).toEqual(supported);
76
+ expect(available).toEqual(supported);
74
77
  });
75
78
  });
76
79
 
@@ -95,8 +98,10 @@ describe('empty translation fallback', () => {
95
98
  expect(t('test.emptyTranslationFallback')).toBe('English fallback');
96
99
  });
97
100
 
101
+ // Reads the locale files rather than `i18nInstance.options.resources`: only the `en` fallback is
102
+ // bundled there now, the rest are fetched on demand.
98
103
  it('does not ship parser-created empty locale entries', () => {
99
- const resources = i18nInstance.options.resources ?? {};
104
+ const localesDir = join(dirname(fileURLToPath(import.meta.url)), 'locales');
100
105
  const emptyEntries: string[] = [];
101
106
 
102
107
  const collectEmptyEntries = (value: unknown, path: string[]) => {
@@ -121,8 +126,12 @@ describe('empty translation fallback', () => {
121
126
  }
122
127
  };
123
128
 
124
- for (const [locale, resource] of Object.entries(resources)) {
125
- collectEmptyEntries(resource, [locale]);
129
+ const localeFiles = readdirSync(localesDir).filter((name) => name.endsWith('.json'));
130
+ expect(localeFiles.length).toBe(SUPPORTED_LANGUAGES.length);
131
+
132
+ for (const file of localeFiles) {
133
+ const resource: unknown = JSON.parse(readFileSync(join(localesDir, file), 'utf-8'));
134
+ collectEmptyEntries(resource, [file.replace(/\.json$/, '')]);
126
135
  }
127
136
 
128
137
  expect(emptyEntries).toEqual([]);
@@ -1,7 +1,12 @@
1
1
  /** @vitest-environment jsdom */
2
2
 
3
3
  import { act, fireEvent, render, screen, waitFor } from '@testing-library/react';
4
- import { MarkdownRichTextEditor, type MarkdownRichTextEditorProps, setEditorMarkdown } from '@vertesia/rich-text';
4
+ import {
5
+ DOCUMENT_EDITOR_CHANGE_DEBOUNCE_MS,
6
+ MarkdownRichTextEditor,
7
+ type MarkdownRichTextEditorProps,
8
+ setEditorMarkdown,
9
+ } from '@vertesia/rich-text';
5
10
  import { describe, expect, it, vi } from 'vitest';
6
11
  import { I18nProvider } from '../i18n/index.js';
7
12
  import {
@@ -174,6 +179,33 @@ describe('VertesiaMarkdownRichTextEditor', () => {
174
179
  expect(await screen.findByRole('heading', { name: 'Setext heading' })).not.toBeNull();
175
180
  expect(screen.getByRole('textbox', { name: 'Markdown document editor' })).not.toBeNull();
176
181
  expect(screen.queryByRole('heading', { name: 'Some Markdown formatting may change' })).toBeNull();
182
+ // The document editor debounces serialization, so wait past that window: otherwise this
183
+ // assertion passes merely because a spurious change has not been flushed yet.
184
+ await new Promise((resolve) => setTimeout(resolve, DOCUMENT_EDITOR_CHANGE_DEBOUNCE_MS * 2));
185
+ expect(onChange).not.toHaveBeenCalled();
186
+ });
187
+
188
+ it('does not report a change when the document is locked or unlocked', async () => {
189
+ const onChange = vi.fn();
190
+ const renderEditable = (editable: boolean) => (
191
+ <I18nProvider lng="en">
192
+ <VertesiaMarkdownDocumentEditor
193
+ value={'Setext heading\n=============='}
194
+ onChange={onChange}
195
+ editable={editable}
196
+ />
197
+ </I18nProvider>
198
+ );
199
+ const view = render(renderEditable(true));
200
+
201
+ expect(await screen.findByRole('heading', { name: 'Setext heading' })).not.toBeNull();
202
+ // Both directions matter: either toggle emits an editor update on its own.
203
+ view.rerender(renderEditable(false));
204
+ await new Promise((resolve) => setTimeout(resolve, DOCUMENT_EDITOR_CHANGE_DEBOUNCE_MS * 2));
205
+ expect(onChange).not.toHaveBeenCalled();
206
+
207
+ view.rerender(renderEditable(true));
208
+ await new Promise((resolve) => setTimeout(resolve, DOCUMENT_EDITOR_CHANGE_DEBOUNCE_MS * 2));
177
209
  expect(onChange).not.toHaveBeenCalled();
178
210
  });
179
211
 
@@ -123,18 +123,15 @@ export function UserSessionProvider({ children, loadOnboardingStatus = true }: U
123
123
  authFlowRef.current = () => {
124
124
  // Make this effect idempotent - only run auth flow once
125
125
  if (hasInitiatedAuthRef.current) {
126
- console.log('Auth: skipping duplicate auth flow initiation');
126
+ Env.logger.debug('Skipping duplicate auth flow initiation');
127
127
  return;
128
128
  }
129
129
  hasInitiatedAuthRef.current = true;
130
130
 
131
- console.log('Auth: starting auth flow');
132
- Env.logger.info('Starting auth flow');
131
+ Env.logger.debug('Starting auth flow');
133
132
  const currentUrl = new URL(window.location.href);
134
133
  const { accountId: selectedAccount, projectId: selectedProject } = resolveAuthSelection(currentUrl);
135
- console.log('Auth: selected account', selectedAccount);
136
- console.log('Auth: selected project', selectedProject);
137
- Env.logger.info('Selected account and project', {
134
+ Env.logger.debug('Selected account and project', {
138
135
  vertesia: {
139
136
  account_id: selectedAccount,
140
137
  project_id: selectedProject,
@@ -207,20 +204,14 @@ export function UserSessionProvider({ children, loadOnboardingStatus = true }: U
207
204
 
208
205
  // If the current host is not in the Firebase allowlist, central auth owns sign-in.
209
206
  if (!session.isLoggedIn()) {
210
- console.log('Auth: not logged in & no token/state');
211
- Env.logger.info('Not logged in & no token/state', {
207
+ Env.logger.debug('Not logged in & no token/state', {
212
208
  vertesia: {
213
209
  account_id: selectedAccount,
214
210
  project_id: selectedProject,
215
211
  },
216
212
  });
217
213
  if (shouldRedirectToCentralAuth()) {
218
- console.log(
219
- 'Auth: host is not in Firebase auth allowlist, redirecting to central auth with selection',
220
- selectedAccount,
221
- selectedProject,
222
- );
223
- Env.logger.info('Redirecting to central auth with selection', {
214
+ Env.logger.debug('Redirecting to central auth with selection', {
224
215
  vertesia: {
225
216
  account_id: selectedAccount,
226
217
  project_id: selectedProject,
@@ -230,8 +221,7 @@ export function UserSessionProvider({ children, loadOnboardingStatus = true }: U
230
221
  return; // Don't register onAuthStateChanged listener when redirecting
231
222
  }
232
223
 
233
- console.log('Auth: host is in Firebase auth allowlist');
234
- Env.logger.info('Host is in Firebase auth allowlist', {
224
+ Env.logger.debug('Host is in Firebase auth allowlist', {
235
225
  vertesia: {
236
226
  account_id: selectedAccount,
237
227
  project_id: selectedProject,
@@ -241,8 +231,7 @@ export function UserSessionProvider({ children, loadOnboardingStatus = true }: U
241
231
 
242
232
  unsubscribe = onAuthStateChanged(getFirebaseAuth(), async (firebaseUser) => {
243
233
  if (firebaseUser) {
244
- console.log('Auth: successful login with firebase');
245
- Env.logger.info('Successful login with firebase', {
234
+ Env.logger.debug('Successful login with firebase', {
246
235
  vertesia: {
247
236
  account_id: selectedAccount,
248
237
  project_id: selectedProject,
@@ -274,8 +263,7 @@ export function UserSessionProvider({ children, loadOnboardingStatus = true }: U
274
263
  });
275
264
  } else {
276
265
  // anonymous user
277
- console.log('Auth: using anonymous user');
278
- Env.logger.info('Using anonymous user', {
266
+ Env.logger.debug('Using anonymous user', {
279
267
  vertesia: {
280
268
  account_id: selectedAccount,
281
269
  project_id: selectedProject,
@@ -1,7 +1,7 @@
1
1
  // @vitest-environment jsdom
2
2
  import { beforeEach, describe, expect, it, vi } from 'vitest';
3
3
 
4
- const logger = { info: vi.fn(), warn: vi.fn(), error: vi.fn() };
4
+ const logger = { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() };
5
5
 
6
6
  vi.mock('@vertesia/ui/env', () => ({
7
7
  Env: {
@@ -5,7 +5,7 @@ function makeJwt(payload: Record<string, unknown>) {
5
5
  return `${encode({ alg: 'ES256', typ: 'JWT' })}.${encode(payload)}.signature`;
6
6
  }
7
7
 
8
- async function importComposableAuth() {
8
+ async function importComposableAuth(authTokenProvider?: () => Promise<string | undefined>) {
9
9
  vi.resetModules();
10
10
  const [{ Env }, composableAuth] = await Promise.all([import('@vertesia/ui/env'), import('./composable')]);
11
11
  Env.init({
@@ -19,6 +19,7 @@ async function importComposableAuth() {
19
19
  zeno: 'https://zeno-server-dev-feat-appgen.api.dev1.vertesia.io',
20
20
  sts: 'https://sts.dev1.vertesia.io',
21
21
  },
22
+ authTokenProvider,
22
23
  });
23
24
  return composableAuth;
24
25
  }
@@ -53,6 +54,65 @@ describe('getComposableToken', () => {
53
54
  expect(fetchMock).not.toHaveBeenCalled();
54
55
  });
55
56
 
57
+ it('reacquires a fresh injected token instead of reusing an expired cached credential', async () => {
58
+ const expiredToken = makeJwt({
59
+ iss: 'https://sts.dev1.vertesia.io',
60
+ exp: Math.floor(Date.now() / 1000) - 60,
61
+ account: { id: 'account-id', name: 'Account' },
62
+ project: { id: 'project-id', name: 'Project', account: 'account-id' },
63
+ project_roles: ['developer'],
64
+ });
65
+ const freshToken = makeJwt({
66
+ iss: 'https://sts.dev1.vertesia.io',
67
+ exp: Math.floor(Date.now() / 1000) + 3600,
68
+ account: { id: 'account-id', name: 'Account' },
69
+ project: { id: 'project-id', name: 'Project', account: 'account-id' },
70
+ project_roles: ['developer'],
71
+ });
72
+ const authTokenProvider = vi.fn(() => Promise.resolve(freshToken));
73
+ const fetchMock = vi.fn();
74
+ vi.stubGlobal('fetch', fetchMock);
75
+
76
+ const { getComposableToken } = await importComposableAuth(authTokenProvider);
77
+ const result = await getComposableToken('account-id', 'project-id', expiredToken, false, true);
78
+
79
+ expect(result.rawToken).toBe(freshToken);
80
+ expect(authTokenProvider).toHaveBeenCalledOnce();
81
+ expect(fetchMock).not.toHaveBeenCalled();
82
+ });
83
+
84
+ it('falls back to the cached credential when the injected provider is unavailable', async () => {
85
+ const expiringToken = makeJwt({
86
+ iss: 'https://sts.dev1.vertesia.io',
87
+ exp: Math.floor(Date.now() / 1000) + 60,
88
+ account: { id: 'account-id', name: 'Account' },
89
+ project: { id: 'project-id', name: 'Project', account: 'account-id' },
90
+ project_roles: ['developer'],
91
+ });
92
+ const refreshedToken = makeJwt({
93
+ iss: 'https://sts.dev1.vertesia.io',
94
+ exp: Math.floor(Date.now() / 1000) + 3600,
95
+ account: { id: 'account-id', name: 'Account' },
96
+ project: { id: 'project-id', name: 'Project', account: 'account-id' },
97
+ project_roles: ['developer'],
98
+ });
99
+ const authTokenProvider = vi.fn(() => Promise.resolve(undefined));
100
+ const fetchMock = vi.fn().mockResolvedValue({
101
+ ok: true,
102
+ status: 200,
103
+ json: () => Promise.resolve({ token: refreshedToken }),
104
+ });
105
+ vi.stubGlobal('fetch', fetchMock);
106
+
107
+ const { getComposableToken } = await importComposableAuth(authTokenProvider);
108
+ const result = await getComposableToken('account-id', 'project-id', expiringToken, false, true);
109
+
110
+ expect(result.rawToken).toBe(refreshedToken);
111
+ expect(authTokenProvider).toHaveBeenCalledOnce();
112
+ expect(fetchMock).toHaveBeenCalledOnce();
113
+ expect(fetchMock.mock.calls[0]?.[1]?.headers).toMatchObject({ Authorization: `Bearer ${expiringToken}` });
114
+ });
115
+
56
116
  it('exchanges a bare STS-issued Vertesia token so roles can be hydrated', async () => {
57
117
  const sourceToken = makeJwt({
58
118
  iss: 'https://sts.dev1.vertesia.io',
@@ -92,6 +92,9 @@ function isVertesiaIssuedToken(token: string | undefined): token is string {
92
92
 
93
93
  function canUseVertesiaTokenDirectly(token: string, accountId?: string, projectId?: string): boolean {
94
94
  const decoded = decodeToken(token);
95
+ if (!decoded.exp || decoded.exp <= Date.now() / 1000 + 300) {
96
+ return false;
97
+ }
95
98
  const hasAuthorizationClaims = Boolean(
96
99
  decoded.permissions?.length ||
97
100
  decoded.account_roles?.length ||
@@ -117,8 +120,7 @@ export async function fetchComposableToken(
117
120
  ttl?: number,
118
121
  retryCount = 0,
119
122
  ): Promise<string> {
120
- console.log(`Getting/refreshing composable token for account ${accountId} and project ${projectId} `);
121
- Env.logger.info('Getting/refreshing composable token', {
123
+ Env.logger.debug('Getting/refreshing composable token', {
122
124
  vertesia: {
123
125
  account_id: accountId,
124
126
  project_id: projectId,
@@ -128,14 +130,12 @@ export async function fetchComposableToken(
128
130
 
129
131
  const idToken = await getIdToken(); //get from firebase
130
132
  if (!idToken) {
131
- console.log('No id token found - using cookie auth');
132
133
  throw new Error('No id token found');
133
134
  }
134
135
 
135
136
  // Use STS endpoint - either configured or default to sts.vertesia.io
136
137
  const stsEndpoint = Env.endpoints.sts;
137
- console.log('Using STS for token generation:', stsEndpoint);
138
- Env.logger.info('Using STS for token generation', {
138
+ Env.logger.debug('Using STS for token generation', {
139
139
  vertesia: {
140
140
  account_id: accountId,
141
141
  project_id: projectId,
@@ -176,8 +176,7 @@ export async function fetchComposableToken(
176
176
 
177
177
  if (idToken && stsRes?.status === 404) {
178
178
  // User not found in token-server - call ensure-user endpoint
179
- console.log('404: User not found - calling ensure-user endpoint');
180
- Env.logger.info('404: User not found - calling ensure-user endpoint', {
179
+ Env.logger.debug('404: User not found - calling ensure-user endpoint', {
181
180
  vertesia: {
182
181
  account_id: accountId,
183
182
  project_id: projectId,
@@ -195,8 +194,7 @@ export async function fetchComposableToken(
195
194
 
196
195
  if (ensureResponse.status === 412) {
197
196
  // No invite - trigger signup
198
- console.log('412: No invite found - signup required');
199
- Env.logger.info('412: No invite found - signup required', {
197
+ Env.logger.debug('412: No invite found - signup required', {
200
198
  vertesia: {
201
199
  account_id: accountId,
202
200
  project_id: projectId,
@@ -234,8 +232,7 @@ export async function fetchComposableToken(
234
232
  }
235
233
 
236
234
  // User created/exists - retry token generation
237
- console.log('User ensured - retrying token generation');
238
- Env.logger.info('User ensured - retrying token generation', {
235
+ Env.logger.debug('User ensured - retrying token generation', {
239
236
  vertesia: {
240
237
  account_id: accountId,
241
238
  project_id: projectId,
@@ -245,8 +242,7 @@ export async function fetchComposableToken(
245
242
  }
246
243
 
247
244
  if (idToken && stsRes?.status === 412) {
248
- console.log("412: auth succeeded but user doesn't exist - signup required", stsRes?.status);
249
- Env.logger.error("412: auth succeeded but user doesn't exist - signup required", {
245
+ Env.logger.info("412: auth succeeded but user doesn't exist - signup required", {
250
246
  vertesia: {
251
247
  account_id: accountId,
252
248
  project_id: projectId,
@@ -258,7 +254,7 @@ export async function fetchComposableToken(
258
254
  Env.logger.error('No email found in id token');
259
255
  throw new Error('No email found in id token');
260
256
  }
261
- Env.logger.error('User not found', {
257
+ Env.logger.info('User not found', {
262
258
  vertesia: {
263
259
  account_id: accountId,
264
260
  project_id: projectId,
@@ -354,8 +350,7 @@ export async function fetchComposableToken(
354
350
  }
355
351
 
356
352
  const { token } = await stsRes.json();
357
- console.log('Successfully got token from STS');
358
- Env.logger.info('Successfully got token from STS');
353
+ Env.logger.debug('Successfully got token from STS');
359
354
  return token;
360
355
  } catch (error) {
361
356
  if (
@@ -460,13 +455,24 @@ export async function getComposableToken(
460
455
  if (!devAuthToken && !useInternalAuth && getFirebaseAuth().currentUser) {
461
456
  //we have a firebase user, get the token from there
462
457
  AUTH_TOKEN_RAW = await fetchComposableTokenFromFirebaseToken(selectedAccount, selectedProject);
463
- } else if (!devAuthToken && (initToken || AUTH_TOKEN_RAW)) {
464
- // we have a token already and no firebase user, refresh it
465
- AUTH_TOKEN_RAW = await fetchComposableToken(
466
- () => Promise.resolve(initToken ?? AUTH_TOKEN_RAW),
467
- selectedAccount,
468
- selectedProject,
469
- );
458
+ } else if (!devAuthToken) {
459
+ // Embedded apps can reacquire a fresh credential from their host after their cached token expires.
460
+ const refreshCredential = (await Env.authTokenProvider?.()) ?? initToken ?? AUTH_TOKEN_RAW;
461
+ if (
462
+ refreshCredential &&
463
+ isVertesiaIssuedToken(refreshCredential) &&
464
+ canUseVertesiaTokenDirectly(refreshCredential, selectedAccount, selectedProject)
465
+ ) {
466
+ AUTH_TOKEN_RAW = refreshCredential;
467
+ } else if (refreshCredential) {
468
+ AUTH_TOKEN_RAW = await fetchComposableToken(
469
+ () => Promise.resolve(refreshCredential),
470
+ selectedAccount,
471
+ selectedProject,
472
+ );
473
+ } else {
474
+ AUTH_TOKEN_RAW = undefined;
475
+ }
470
476
  } else if (devAuthToken) {
471
477
  AUTH_TOKEN_RAW = devAuthToken;
472
478
  }
@@ -139,7 +139,7 @@ export async function getFirebaseAuthToken(refresh?: boolean) {
139
139
  return user
140
140
  .getIdToken(refresh)
141
141
  .then((token) => {
142
- Env.logger.info('Got Firebase token', {
142
+ Env.logger.debug('Got Firebase token', {
143
143
  vertesia: {
144
144
  user_email: user.email,
145
145
  user_name: user.displayName,
@@ -3,6 +3,7 @@ import { TypeRegistryProvider, UserPermissionProvider } from '@vertesia/ui/featu
3
3
  import { LanguageBoundI18nProvider, LanguageProvider, type SupportedLanguage } from '@vertesia/ui/i18n';
4
4
  import { DevSessionProvider, UserSessionProvider } from '@vertesia/ui/session';
5
5
  import type { ReactNode } from 'react';
6
+ import { IframeAppContextSync } from './apps/IframeAppContextSync.js';
6
7
  import { SigninScreen } from './login/SigninScreen';
7
8
  import { SplashScreen } from './SplashScreen';
8
9
 
@@ -35,6 +36,7 @@ export function VertesiaShell({
35
36
  <ThemeProvider defaultTheme="system" storageKey="vite-ui-theme">
36
37
  <LanguageProvider defaultLanguage={defaultLanguage}>
37
38
  <LanguageBoundI18nProvider>
39
+ <IframeAppContextSync />
38
40
  {!authToken && (
39
41
  <>
40
42
  <SplashScreen icon={loadingIcon} />
@@ -0,0 +1,196 @@
1
+ // @vitest-environment jsdom
2
+
3
+ import { act, cleanup, render, screen, waitFor } from '@testing-library/react';
4
+ import { afterEach, describe, expect, it, vi } from 'vitest';
5
+ import { ThemeProvider, useTheme } from '../../core/index.js';
6
+ import { LanguageProvider, useLanguage } from '../../i18n/index.js';
7
+ import { IframeAppContextSync } from './IframeAppContextSync.js';
8
+ import {
9
+ IFRAME_APP_CONTEXT,
10
+ IFRAME_APP_CONTEXT_REQUEST,
11
+ IFRAME_APP_HOST_ORIGIN_PARAM,
12
+ IFRAME_APP_LOCATION_CHANGE,
13
+ IFRAME_APP_NAVIGATE,
14
+ } from './iframe-auth.js';
15
+
16
+ const originalParent = Object.getOwnPropertyDescriptor(window, 'parent');
17
+ const originalReferrer = Object.getOwnPropertyDescriptor(document, 'referrer');
18
+
19
+ afterEach(() => {
20
+ cleanup();
21
+ window.history.replaceState(null, '', '/');
22
+ localStorage.clear();
23
+ sessionStorage.clear();
24
+ document.documentElement.classList.remove('light', 'dark');
25
+ if (originalParent) Object.defineProperty(window, 'parent', originalParent);
26
+ else Reflect.deleteProperty(window, 'parent');
27
+ if (originalReferrer) Object.defineProperty(document, 'referrer', originalReferrer);
28
+ else Reflect.deleteProperty(document, 'referrer');
29
+ });
30
+
31
+ function ContextProbe() {
32
+ const { theme } = useTheme();
33
+ const { language } = useLanguage();
34
+ return <div>{`${theme}:${language}`}</div>;
35
+ }
36
+
37
+ describe('IframeAppContextSync', () => {
38
+ it('requests and applies host presentation state without overwriting standalone preferences', async () => {
39
+ const postMessage = vi.fn();
40
+ const parentWindow = { postMessage } as unknown as Window;
41
+ Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
42
+ Object.defineProperty(document, 'referrer', {
43
+ configurable: true,
44
+ value: 'https://cloud.vertesia.io/app/sample',
45
+ });
46
+ localStorage.setItem('custom-theme', 'dark');
47
+ localStorage.setItem('custom-language', 'en');
48
+
49
+ render(
50
+ <ThemeProvider storageKey="custom-theme">
51
+ <LanguageProvider storageKey="custom-language">
52
+ <IframeAppContextSync />
53
+ <ContextProbe />
54
+ </LanguageProvider>
55
+ </ThemeProvider>,
56
+ );
57
+
58
+ expect(parentWindow.postMessage).toHaveBeenCalledWith(
59
+ { type: IFRAME_APP_CONTEXT_REQUEST },
60
+ 'https://cloud.vertesia.io',
61
+ );
62
+
63
+ window.dispatchEvent(
64
+ new MessageEvent('message', {
65
+ data: { type: IFRAME_APP_CONTEXT, theme: 'light', language: 'fr' },
66
+ origin: 'https://attacker.example.com',
67
+ source: parentWindow,
68
+ }),
69
+ );
70
+ expect(screen.getByText('dark:en')).toBeTruthy();
71
+
72
+ act(() => {
73
+ window.dispatchEvent(
74
+ new MessageEvent('message', {
75
+ data: { type: IFRAME_APP_CONTEXT, theme: 'light', language: 'fr' },
76
+ origin: 'https://cloud.vertesia.io',
77
+ source: parentWindow,
78
+ }),
79
+ );
80
+ });
81
+
82
+ await waitFor(() => expect(screen.getByText('light:fr')).toBeTruthy());
83
+ expect(localStorage.getItem('custom-theme')).toBe('dark');
84
+ expect(localStorage.getItem('custom-language')).toBe('en');
85
+ expect(postMessage.mock.calls.filter(([message]) => message.type === IFRAME_APP_CONTEXT_REQUEST)).toHaveLength(
86
+ 1,
87
+ );
88
+ });
89
+
90
+ it('applies same-origin host navigation without reloading the document', () => {
91
+ const parentWindow = { postMessage: vi.fn() } as unknown as Window;
92
+ Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
93
+ Object.defineProperty(document, 'referrer', {
94
+ configurable: true,
95
+ value: 'https://cloud.vertesia.io/app/sample',
96
+ });
97
+ localStorage.setItem('vite-ui-theme', 'dark');
98
+ localStorage.setItem('vertesia-ui-language', 'en');
99
+ window.history.replaceState(null, '', '/app/');
100
+ const popstate = vi.fn();
101
+ window.addEventListener('popstate', popstate);
102
+
103
+ render(
104
+ <ThemeProvider>
105
+ <LanguageProvider>
106
+ <IframeAppContextSync />
107
+ </LanguageProvider>
108
+ </ThemeProvider>,
109
+ );
110
+
111
+ window.dispatchEvent(
112
+ new MessageEvent('message', {
113
+ data: { type: IFRAME_APP_NAVIGATE, url: 'https://attacker.example.com/stolen' },
114
+ origin: 'https://cloud.vertesia.io',
115
+ source: parentWindow,
116
+ }),
117
+ );
118
+ expect(window.location.pathname).toBe('/app/');
119
+
120
+ const target = `${window.location.origin}/app/reports?__vertesia_slot=content`;
121
+ window.dispatchEvent(
122
+ new MessageEvent('message', {
123
+ data: { type: IFRAME_APP_NAVIGATE, url: target },
124
+ origin: 'https://cloud.vertesia.io',
125
+ source: parentWindow,
126
+ }),
127
+ );
128
+
129
+ expect(window.location.pathname).toBe('/app/reports');
130
+ expect(window.location.search).toBe('?__vertesia_slot=content');
131
+ expect(popstate).toHaveBeenCalledTimes(1);
132
+ window.removeEventListener('popstate', popstate);
133
+ });
134
+
135
+ it('acknowledges host navigation when the iframe is already at the requested URL', () => {
136
+ const parentWindow = { postMessage: vi.fn() } as unknown as Window;
137
+ Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
138
+ localStorage.setItem('vite-ui-theme', 'dark');
139
+ window.history.replaceState(
140
+ null,
141
+ '',
142
+ `/app/reports?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fcloud.vertesia.io`,
143
+ );
144
+
145
+ render(
146
+ <ThemeProvider>
147
+ <LanguageProvider>
148
+ <IframeAppContextSync />
149
+ </LanguageProvider>
150
+ </ThemeProvider>,
151
+ );
152
+ parentWindow.postMessage = vi.fn();
153
+
154
+ window.dispatchEvent(
155
+ new MessageEvent('message', {
156
+ data: { type: IFRAME_APP_NAVIGATE, url: window.location.href },
157
+ origin: 'https://cloud.vertesia.io',
158
+ source: parentWindow,
159
+ }),
160
+ );
161
+
162
+ expect(parentWindow.postMessage).toHaveBeenCalledWith(
163
+ { type: IFRAME_APP_LOCATION_CHANGE, url: window.location.href },
164
+ 'https://cloud.vertesia.io',
165
+ );
166
+ });
167
+
168
+ it('reports app-initiated history navigation to the embedding Studio', () => {
169
+ const parentWindow = { postMessage: vi.fn() } as unknown as Window;
170
+ Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
171
+ window.history.replaceState(null, '', `/app/?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fcloud.vertesia.io`);
172
+ localStorage.setItem('vite-ui-theme', 'dark');
173
+ localStorage.setItem('vertesia-ui-language', 'en');
174
+
175
+ render(
176
+ <ThemeProvider>
177
+ <LanguageProvider>
178
+ <IframeAppContextSync />
179
+ </LanguageProvider>
180
+ </ThemeProvider>,
181
+ );
182
+ parentWindow.postMessage = vi.fn();
183
+
184
+ window.history.pushState(null, '', '/app/reports?period=week');
185
+
186
+ expect(parentWindow.postMessage).toHaveBeenCalledWith(
187
+ {
188
+ type: IFRAME_APP_LOCATION_CHANGE,
189
+ url:
190
+ `${window.location.origin}/app/reports?period=week&` +
191
+ `${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fcloud.vertesia.io`,
192
+ },
193
+ 'https://cloud.vertesia.io',
194
+ );
195
+ });
196
+ });