@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
@@ -0,0 +1,101 @@
1
+ import { useEffect } from 'react';
2
+ import { useTheme } from '../../core/components/shadcn/theme/ThemeProvider.js';
3
+ import { useLanguage } from '../../i18n/LanguageProvider.js';
4
+ import {
5
+ IFRAME_APP_CONTEXT_REQUEST,
6
+ IFRAME_APP_HOST_ORIGIN_PARAM,
7
+ IFRAME_APP_LOCATION_CHANGE,
8
+ type IframeAppContextRequest,
9
+ type IframeAppLocationChange,
10
+ isIframeAppContext,
11
+ isIframeAppNavigate,
12
+ resolveIframeHostOrigin,
13
+ } from './iframe-auth.js';
14
+
15
+ function preserveIframeHostOrigin(url: string | URL | null | undefined): string | URL | null | undefined {
16
+ if (url === null || url === undefined) return url;
17
+ const hostOrigin = new URL(window.location.href).searchParams.get(IFRAME_APP_HOST_ORIGIN_PARAM);
18
+ if (!hostOrigin) return url;
19
+
20
+ try {
21
+ const target = new URL(url, window.location.href);
22
+ if (target.origin !== window.location.origin) return url;
23
+ target.searchParams.set(IFRAME_APP_HOST_ORIGIN_PARAM, hostOrigin);
24
+ return target;
25
+ } catch {
26
+ return url;
27
+ }
28
+ }
29
+
30
+ /** Applies context and navigation supplied by an embedding Studio without changing standalone preferences. */
31
+ export function IframeAppContextSync() {
32
+ const { setTheme } = useTheme();
33
+ const { setLanguage } = useLanguage();
34
+
35
+ useEffect(() => {
36
+ const parentOrigin = resolveIframeHostOrigin();
37
+ if (!parentOrigin) return;
38
+
39
+ const reportLocation = () => {
40
+ const message = {
41
+ type: IFRAME_APP_LOCATION_CHANGE,
42
+ url: window.location.href,
43
+ } satisfies IframeAppLocationChange;
44
+ window.parent.postMessage(message, parentOrigin);
45
+ };
46
+
47
+ const originalPushState = window.history.pushState;
48
+ const originalReplaceState = window.history.replaceState;
49
+ const pushState: History['pushState'] = (data, unused, url) => {
50
+ originalPushState.call(window.history, data, unused, preserveIframeHostOrigin(url));
51
+ reportLocation();
52
+ };
53
+ const replaceState: History['replaceState'] = (data, unused, url) => {
54
+ originalReplaceState.call(window.history, data, unused, preserveIframeHostOrigin(url));
55
+ reportLocation();
56
+ };
57
+ window.history.pushState = pushState;
58
+ window.history.replaceState = replaceState;
59
+
60
+ const onMessage = (event: MessageEvent<unknown>) => {
61
+ if (event.source !== window.parent || event.origin !== parentOrigin) return;
62
+ if (isIframeAppContext(event.data)) {
63
+ const context = event.data;
64
+ setTheme(context.theme, { persist: false });
65
+ setLanguage(context.language, { persist: false });
66
+ return;
67
+ }
68
+ if (isIframeAppNavigate(event.data)) {
69
+ let target: URL;
70
+ try {
71
+ target = new URL(event.data.url, window.location.href);
72
+ } catch {
73
+ return;
74
+ }
75
+ if (target.origin !== window.location.origin) return;
76
+ if (target.href === window.location.href) {
77
+ // Acknowledge no-op navigation so the host does not wait forever and suppress later app routing.
78
+ reportLocation();
79
+ return;
80
+ }
81
+ window.history.replaceState(window.history.state, '', target);
82
+ window.dispatchEvent(new PopStateEvent('popstate', { state: window.history.state }));
83
+ }
84
+ };
85
+ const request = { type: IFRAME_APP_CONTEXT_REQUEST } satisfies IframeAppContextRequest;
86
+ window.addEventListener('message', onMessage);
87
+ window.addEventListener('popstate', reportLocation);
88
+ window.addEventListener('hashchange', reportLocation);
89
+ window.parent.postMessage(request, parentOrigin);
90
+ reportLocation();
91
+ return () => {
92
+ window.removeEventListener('message', onMessage);
93
+ window.removeEventListener('popstate', reportLocation);
94
+ window.removeEventListener('hashchange', reportLocation);
95
+ if (window.history.pushState === pushState) window.history.pushState = originalPushState;
96
+ if (window.history.replaceState === replaceState) window.history.replaceState = originalReplaceState;
97
+ };
98
+ }, [setLanguage, setTheme]);
99
+
100
+ return null;
101
+ }
@@ -0,0 +1,118 @@
1
+ // @vitest-environment jsdom
2
+
3
+ import { afterEach, describe, expect, it } from 'vitest';
4
+ import {
5
+ IFRAME_APP_HOST_ORIGIN_PARAM,
6
+ IFRAME_AUTH_REQUEST,
7
+ IFRAME_AUTH_RESPONSE,
8
+ requestIframeHostAuthToken,
9
+ resolveIframeHostOrigin,
10
+ } from './iframe-auth.js';
11
+
12
+ const originalParent = Object.getOwnPropertyDescriptor(window, 'parent');
13
+ const originalReferrer = Object.getOwnPropertyDescriptor(document, 'referrer');
14
+
15
+ afterEach(() => {
16
+ window.history.replaceState(null, '', '/');
17
+ window.sessionStorage.clear();
18
+ if (originalParent) Object.defineProperty(window, 'parent', originalParent);
19
+ else Reflect.deleteProperty(window, 'parent');
20
+ if (originalReferrer) Object.defineProperty(document, 'referrer', originalReferrer);
21
+ else Reflect.deleteProperty(document, 'referrer');
22
+ });
23
+
24
+ describe('iframe host authentication', () => {
25
+ it('resolves an explicit trusted host origin', () => {
26
+ const parentWindow = { postMessage: () => undefined } as unknown as Window;
27
+ Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
28
+ window.history.replaceState(null, '', `/?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fcloud.vertesia.io`);
29
+
30
+ expect(resolveIframeHostOrigin()).toBe('https://cloud.vertesia.io');
31
+ });
32
+
33
+ it('accepts a branch Studio UI origin', () => {
34
+ const parentWindow = { postMessage: () => undefined } as unknown as Window;
35
+ Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
36
+ window.history.replaceState(
37
+ null,
38
+ '',
39
+ `/?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fdev-feat-iframe.ui.dev1.vertesia.io`,
40
+ );
41
+
42
+ expect(resolveIframeHostOrigin()).toBe('https://dev-feat-iframe.ui.dev1.vertesia.io');
43
+ });
44
+
45
+ it('rejects untrusted query and referrer origins', () => {
46
+ const parentWindow = { postMessage: () => undefined } as unknown as Window;
47
+ Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
48
+ window.history.replaceState(null, '', `/?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fevil.example.com`);
49
+ Object.defineProperty(document, 'referrer', {
50
+ configurable: true,
51
+ value: 'https://referrer.example.com/embed',
52
+ });
53
+
54
+ expect(resolveIframeHostOrigin()).toBeUndefined();
55
+ });
56
+
57
+ it('rejects a shared Vertesia app-gateway origin', () => {
58
+ const parentWindow = { postMessage: () => undefined } as unknown as Window;
59
+ Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
60
+ window.history.replaceState(null, '', `/?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fapps.dev1.vertesia.io`);
61
+
62
+ expect(resolveIframeHostOrigin()).toBeUndefined();
63
+ });
64
+
65
+ it('rejects an origin containing embedded credentials', () => {
66
+ const parentWindow = { postMessage: () => undefined } as unknown as Window;
67
+ Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
68
+ window.history.replaceState(
69
+ null,
70
+ '',
71
+ `/?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fuser%3Asecret%40cloud.vertesia.io`,
72
+ );
73
+
74
+ expect(resolveIframeHostOrigin()).toBeUndefined();
75
+ });
76
+
77
+ it('accepts a loopback host for a loopback child app', () => {
78
+ const parentWindow = { postMessage: () => undefined } as unknown as Window;
79
+ Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
80
+ window.history.replaceState(null, '', `/?${IFRAME_APP_HOST_ORIGIN_PARAM}=http%3A%2F%2Flocalhost%3A5173`);
81
+
82
+ expect(resolveIframeHostOrigin()).toBe('http://localhost:5173');
83
+ });
84
+
85
+ it('ignores an empty early response and waits for a usable host token', async () => {
86
+ const requests: unknown[] = [];
87
+ const parentWindow = { postMessage: (message: unknown) => requests.push(message) } as unknown as Window;
88
+ Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
89
+ window.history.replaceState(null, '', `/?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fcloud.vertesia.io`);
90
+
91
+ let settled = false;
92
+ const tokenPromise = requestIframeHostAuthToken().then((token) => {
93
+ settled = true;
94
+ return token;
95
+ });
96
+ const request = requests[0] as { type: string; requestId: string };
97
+ expect(request.type).toBe(IFRAME_AUTH_REQUEST);
98
+
99
+ window.dispatchEvent(
100
+ new MessageEvent('message', {
101
+ data: { type: IFRAME_AUTH_RESPONSE, requestId: request.requestId },
102
+ origin: 'https://cloud.vertesia.io',
103
+ source: parentWindow,
104
+ }),
105
+ );
106
+ await Promise.resolve();
107
+ expect(settled).toBe(false);
108
+
109
+ window.dispatchEvent(
110
+ new MessageEvent('message', {
111
+ data: { type: IFRAME_AUTH_RESPONSE, requestId: request.requestId, token: 'fresh-token' },
112
+ origin: 'https://cloud.vertesia.io',
113
+ source: parentWindow,
114
+ }),
115
+ );
116
+ await expect(tokenPromise).resolves.toBe('fresh-token');
117
+ });
118
+ });
@@ -0,0 +1,193 @@
1
+ import { SUPPORTED_LANGUAGES, type SupportedLanguage } from '../../i18n/rtl.js';
2
+
3
+ export const IFRAME_AUTH_REQUEST = 'vertesia:iframe-auth-request';
4
+ export const IFRAME_AUTH_RESPONSE = 'vertesia:iframe-auth-response';
5
+ export const IFRAME_APP_CONTEXT_REQUEST = 'vertesia:iframe-context-request';
6
+ export const IFRAME_APP_CONTEXT = 'vertesia:iframe-context';
7
+ export const IFRAME_APP_NAVIGATE = 'vertesia:iframe-navigate';
8
+ export const IFRAME_APP_LOCATION_CHANGE = 'vertesia:iframe-location-change';
9
+ export const IFRAME_APP_SLOT_PARAM = '__vertesia_slot';
10
+ export const IFRAME_APP_HOST_ORIGIN_PARAM = '__vertesia_host_origin';
11
+ export const IFRAME_APP_CONTENT_SLOT = 'content';
12
+
13
+ export interface IframeAuthRequest {
14
+ type: typeof IFRAME_AUTH_REQUEST;
15
+ requestId: string;
16
+ }
17
+
18
+ export interface IframeAuthResponse {
19
+ type: typeof IFRAME_AUTH_RESPONSE;
20
+ requestId: string;
21
+ token?: string;
22
+ }
23
+
24
+ export interface IframeAppContextRequest {
25
+ type: typeof IFRAME_APP_CONTEXT_REQUEST;
26
+ }
27
+
28
+ export interface IframeAppContext {
29
+ type: typeof IFRAME_APP_CONTEXT;
30
+ theme: 'dark' | 'light' | 'system';
31
+ language: SupportedLanguage;
32
+ }
33
+
34
+ export interface IframeAppNavigate {
35
+ type: typeof IFRAME_APP_NAVIGATE;
36
+ url: string;
37
+ }
38
+
39
+ export interface IframeAppLocationChange {
40
+ type: typeof IFRAME_APP_LOCATION_CHANGE;
41
+ url: string;
42
+ }
43
+
44
+ export function isIframeAuthRequest(value: unknown): value is IframeAuthRequest {
45
+ if (!value || typeof value !== 'object') return false;
46
+ const message = value as Partial<IframeAuthRequest>;
47
+ return message.type === IFRAME_AUTH_REQUEST && typeof message.requestId === 'string' && !!message.requestId;
48
+ }
49
+
50
+ export function isIframeAuthResponse(value: unknown): value is IframeAuthResponse {
51
+ if (!value || typeof value !== 'object') return false;
52
+ const message = value as Partial<IframeAuthResponse>;
53
+ return (
54
+ message.type === IFRAME_AUTH_RESPONSE &&
55
+ typeof message.requestId === 'string' &&
56
+ !!message.requestId &&
57
+ (message.token === undefined || typeof message.token === 'string')
58
+ );
59
+ }
60
+
61
+ export function isIframeAppContextRequest(value: unknown): value is IframeAppContextRequest {
62
+ if (!value || typeof value !== 'object') return false;
63
+ return (value as Partial<IframeAppContextRequest>).type === IFRAME_APP_CONTEXT_REQUEST;
64
+ }
65
+
66
+ export function isIframeAppContext(value: unknown): value is IframeAppContext {
67
+ if (!value || typeof value !== 'object') return false;
68
+ const message = value as Partial<IframeAppContext>;
69
+ return (
70
+ message.type === IFRAME_APP_CONTEXT &&
71
+ (message.theme === 'dark' || message.theme === 'light' || message.theme === 'system') &&
72
+ typeof message.language === 'string' &&
73
+ (SUPPORTED_LANGUAGES as readonly string[]).includes(message.language)
74
+ );
75
+ }
76
+
77
+ export function isIframeAppNavigate(value: unknown): value is IframeAppNavigate {
78
+ if (!value || typeof value !== 'object') return false;
79
+ const message = value as Partial<IframeAppNavigate>;
80
+ return message.type === IFRAME_APP_NAVIGATE && typeof message.url === 'string' && !!message.url;
81
+ }
82
+
83
+ export function isIframeAppLocationChange(value: unknown): value is IframeAppLocationChange {
84
+ if (!value || typeof value !== 'object') return false;
85
+ const message = value as Partial<IframeAppLocationChange>;
86
+ return message.type === IFRAME_APP_LOCATION_CHANGE && typeof message.url === 'string' && !!message.url;
87
+ }
88
+
89
+ const LOOPBACK_HOSTS = new Set(['localhost', '127.0.0.1', '[::1]']);
90
+
91
+ function parseHttpOrigin(value: string | null | undefined): URL | undefined {
92
+ if (!value) return undefined;
93
+ try {
94
+ const url = new URL(value);
95
+ const isLoopback = LOOPBACK_HOSTS.has(url.hostname);
96
+ return url.protocol === 'https:' || (url.protocol === 'http:' && isLoopback) ? url : undefined;
97
+ } catch {
98
+ return undefined;
99
+ }
100
+ }
101
+
102
+ function hasEmbeddedCredentials(value: string | null | undefined): boolean {
103
+ if (!value) return false;
104
+ const normalized = value.trim();
105
+ const schemeEnd = normalized.indexOf('://');
106
+ if (schemeEnd < 0) return false;
107
+
108
+ const authorityStart = schemeEnd + 3;
109
+ const authoritySuffix = normalized.slice(authorityStart);
110
+ const authorityEnd = authoritySuffix.search(/[/?#]/);
111
+ const authority = authorityEnd < 0 ? authoritySuffix : authoritySuffix.slice(0, authorityEnd);
112
+ return authority.includes('@');
113
+ }
114
+
115
+ function isVertesiaStudioHost(host: string): boolean {
116
+ if (host === 'studio.vertesia.io') return true;
117
+
118
+ const labels = host.split('.');
119
+ if (labels.at(-2) !== 'vertesia' || labels.at(-1) !== 'io') return false;
120
+
121
+ const platformLabels = labels.slice(0, -2);
122
+ const cloudIndex = platformLabels.lastIndexOf('cloud');
123
+ if (cloudIndex >= 0 && platformLabels.length - cloudIndex <= 2) return true;
124
+
125
+ const uiIndex = platformLabels.lastIndexOf('ui');
126
+ return uiIndex >= 0 && platformLabels.length - uiIndex === 2;
127
+ }
128
+
129
+ function parseTrustedIframeHostOrigin(value: string | null | undefined): string | undefined {
130
+ if (hasEmbeddedCredentials(value)) return undefined;
131
+ const url = parseHttpOrigin(value);
132
+ if (!url) return undefined;
133
+
134
+ const host = url.hostname;
135
+ const isStudioHost = isVertesiaStudioHost(host);
136
+ const isLocalDevelopment = LOOPBACK_HOSTS.has(host) && LOOPBACK_HOSTS.has(window.location.hostname);
137
+ return (url.protocol === 'https:' && isStudioHost) || isLocalDevelopment ? url.origin : undefined;
138
+ }
139
+
140
+ /**
141
+ * Resolve a trusted embedding Studio origin without relying on referrer surviving a reload or auth redirect.
142
+ * The URL value is a continuity hint rather than a trust anchor: only Studio UI host patterns are accepted, and
143
+ * loopback parents are accepted only when the child app is also running on loopback.
144
+ */
145
+ export function resolveIframeHostOrigin(): string | undefined {
146
+ if (window.parent === window) return undefined;
147
+
148
+ const explicitOrigin = parseTrustedIframeHostOrigin(
149
+ new URL(window.location.href).searchParams.get(IFRAME_APP_HOST_ORIGIN_PARAM),
150
+ );
151
+ if (explicitOrigin) return explicitOrigin;
152
+
153
+ return parseTrustedIframeHostOrigin(document.referrer);
154
+ }
155
+
156
+ /**
157
+ * Ask an embedding Studio window for a fresh Vertesia token. Both sides validate the request nonce,
158
+ * source window, and exact origin. The explicit host-origin parameter survives framed redirects and
159
+ * hard navigations; referrer remains a compatibility fallback for older hosts.
160
+ * Standalone/top-level apps return undefined and continue through the normal sign-in flow.
161
+ */
162
+ export function requestIframeHostAuthToken(timeoutMs = 5000): Promise<string | undefined> {
163
+ const parentOrigin = resolveIframeHostOrigin();
164
+ if (!parentOrigin) return Promise.resolve(undefined);
165
+
166
+ const requestId = crypto.randomUUID();
167
+ return new Promise((resolve) => {
168
+ let timeout: number;
169
+ let retry: number;
170
+ let retryDelay = 250;
171
+ const finish = (token?: string) => {
172
+ window.removeEventListener('message', onMessage);
173
+ clearTimeout(timeout);
174
+ clearTimeout(retry);
175
+ resolve(token);
176
+ };
177
+ const onMessage = (event: MessageEvent<unknown>) => {
178
+ if (event.source !== window.parent || event.origin !== parentOrigin || !isIframeAuthResponse(event.data)) {
179
+ return;
180
+ }
181
+ if (event.data.requestId === requestId && event.data.token) finish(event.data.token);
182
+ };
183
+ const request = { type: IFRAME_AUTH_REQUEST, requestId } satisfies IframeAuthRequest;
184
+ const sendRequest = () => {
185
+ window.parent.postMessage(request, parentOrigin);
186
+ retry = window.setTimeout(sendRequest, retryDelay);
187
+ retryDelay = Math.min(retryDelay * 2, 1000);
188
+ };
189
+ timeout = window.setTimeout(() => finish(), timeoutMs);
190
+ window.addEventListener('message', onMessage);
191
+ sendRequest();
192
+ });
193
+ }
@@ -1,3 +1,5 @@
1
1
  export * from './AppInstallationProvider';
2
2
  export * from './AppProjectSelector';
3
+ export * from './IframeAppContextSync';
4
+ export * from './iframe-auth';
3
5
  export * from './StandaloneApp';
@@ -44,6 +44,7 @@ function renderSurface(props?: {
44
44
  onSendChangesToAgent?: () => void;
45
45
  hasUnsentChanges?: boolean;
46
46
  toolbarStatus?: React.ReactNode;
47
+ onContentChange?: (content: string, generation?: string) => void;
47
48
  flushChangesRef?: React.MutableRefObject<(() => Promise<false | ArtifactEditingSurfaceDocumentEdit>) | null>;
48
49
  }) {
49
50
  return render(
@@ -61,6 +62,7 @@ function renderSurface(props?: {
61
62
  onSendChangesToAgent={props?.onSendChangesToAgent}
62
63
  hasUnsentChanges={props?.hasUnsentChanges}
63
64
  toolbarStatus={props?.toolbarStatus}
65
+ onContentChange={props?.onContentChange}
64
66
  flushChangesRef={props?.flushChangesRef}
65
67
  />
66
68
  </I18nProvider>,
@@ -292,6 +294,7 @@ describe('ArtifactEditingSurface', () => {
292
294
 
293
295
  it('rebases focused full-document edits over a non-overlapping agent change after 412', async () => {
294
296
  const user = userEvent.setup();
297
+ const onContentChange = vi.fn();
295
298
  const baseContent = 'First paragraph.\n\nSecond paragraph.';
296
299
  const remoteContent = 'First paragraph updated remotely.\n\nSecond paragraph.';
297
300
  mocks.getArtifactContent
@@ -314,16 +317,22 @@ describe('ArtifactEditingSurface', () => {
314
317
  .mockRejectedValueOnce({ status: 412 })
315
318
  .mockResolvedValueOnce({ path: 'drafts/document.md', generation: 'generation-merged' });
316
319
 
317
- const view = renderSurface({ viewMode: 'document' });
320
+ const view = renderSurface({ viewMode: 'document', onContentChange });
318
321
  const editor = await screen.findByRole('textbox', { name: 'Markdown document editor' }, LAZY_EDITOR_WAIT);
319
322
  await user.click(editor);
320
323
 
321
324
  view.rerender(
322
325
  <I18nProvider lng="en">
323
- <ArtifactEditingSurface runId="run-1" path="drafts/document.md" refreshKey={1} viewMode="document" />
326
+ <ArtifactEditingSurface
327
+ runId="run-1"
328
+ path="drafts/document.md"
329
+ refreshKey={1}
330
+ viewMode="document"
331
+ onContentChange={onContentChange}
332
+ />
324
333
  </I18nProvider>,
325
334
  );
326
- await waitFor(() => expect(mocks.getArtifactContent).toHaveBeenCalledTimes(2));
335
+ await waitFor(() => expect(onContentChange).toHaveBeenCalledWith(remoteContent, 'generation-agent'));
327
336
 
328
337
  editor.focus();
329
338
  const secondParagraphText = editor.querySelectorAll('p')[1]?.firstChild;
@@ -1,7 +1,6 @@
1
1
  import type { Element } from 'hast';
2
2
  import React from 'react';
3
3
  import Markdown, { type Components, defaultUrlTransform } from 'react-markdown';
4
- import rehypeKatex from 'rehype-katex';
5
4
  import { defListHastHandlers, remarkDefinitionList } from 'remark-definition-list';
6
5
  import remarkDirective from 'remark-directive';
7
6
  import remarkGfm from 'remark-gfm';
@@ -24,6 +23,55 @@ type MarkdownTree = Parameters<typeof visit>[0];
24
23
  type MarkdownNode = { value?: unknown };
25
24
  type MarkdownParent = { children?: unknown[] };
26
25
  type RemarkPluginList = NonNullable<React.ComponentProps<typeof Markdown>['remarkPlugins']>;
26
+ type RehypePluginList = NonNullable<React.ComponentProps<typeof Markdown>['rehypePlugins']>;
27
+ type RehypePlugin = RehypePluginList[number];
28
+
29
+ // A `$` that the math preprocessor left unescaped — the only way remark-math can produce a math
30
+ // node. Currency is escaped to `\$` by `preprocessMathDelimiters`, so it does not match.
31
+ const MATH_DELIMITER_REGEX = /(?:^|[^\\])\$/;
32
+ const NO_REHYPE_PLUGINS: RehypePluginList = [];
33
+
34
+ let rehypeKatex: RehypePlugin | undefined;
35
+ let rehypeKatexPromise: Promise<RehypePlugin> | undefined;
36
+
37
+ function loadRehypeKatex(): Promise<RehypePlugin> {
38
+ if (!rehypeKatexPromise) {
39
+ rehypeKatexPromise = import('rehype-katex').then(({ default: plugin }) => {
40
+ rehypeKatex = plugin;
41
+ return plugin;
42
+ });
43
+ }
44
+ return rehypeKatexPromise;
45
+ }
46
+
47
+ /**
48
+ * KaTeX is ~250 KB and most markdown has no math in it, so it is fetched the first time a document
49
+ * containing math delimiters is rendered. Until it resolves, math renders unstyled; once loaded it
50
+ * stays loaded for the rest of the session and later renderers pick it up without a second pass.
51
+ */
52
+ function useRehypePlugins(markdown: string): RehypePluginList {
53
+ const hasMath = React.useMemo(() => MATH_DELIMITER_REGEX.test(markdown), [markdown]);
54
+ const [plugin, setPlugin] = React.useState(() => rehypeKatex);
55
+
56
+ React.useEffect(() => {
57
+ if (!hasMath || plugin) return;
58
+ let cancelled = false;
59
+ loadRehypeKatex()
60
+ .then((loaded) => {
61
+ if (!cancelled) {
62
+ setPlugin(() => loaded);
63
+ }
64
+ })
65
+ .catch((err: unknown) => {
66
+ console.error('Failed to load KaTeX; math will render unstyled', err);
67
+ });
68
+ return () => {
69
+ cancelled = true;
70
+ };
71
+ }, [hasMath, plugin]);
72
+
73
+ return React.useMemo(() => (plugin ? [plugin] : NO_REHYPE_PLUGINS), [plugin]);
74
+ }
27
75
 
28
76
  // Custom URL schemes that we handle in our components
29
77
  const ALLOWED_CUSTOM_SCHEMES = [
@@ -151,7 +199,7 @@ export function MarkdownRenderer({
151
199
  }, [remarkPlugins, removeComments]);
152
200
 
153
201
  // Rehype plugins (HTML processing, including KaTeX for math)
154
- const rehypePluginsArray = React.useMemo(() => [rehypeKatex], []);
202
+ const rehypePluginsArray = useRehypePlugins(normalizedMarkdown);
155
203
 
156
204
  // Remark-rehype bridge options (custom AST handlers for definition lists)
157
205
  const remarkRehypeOptions = React.useMemo(
@@ -1,6 +1,7 @@
1
- import mermaid from 'mermaid';
2
1
  import { useEffect, useId, useRef, useState } from 'react';
3
2
 
3
+ type Mermaid = typeof import('mermaid').default;
4
+
4
5
  const MERMAID_FONT_FAMILY =
5
6
  'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';
6
7
 
@@ -78,27 +79,41 @@ export function makeSvgResponsive(svg: string): string {
78
79
  });
79
80
  }
80
81
 
81
- // Initialize mermaid with a browser-focused config close to Mermaid Playground defaults.
82
- mermaid.initialize({
83
- startOnLoad: false,
84
- theme: 'default',
85
- securityLevel: 'loose',
86
- fontFamily: MERMAID_FONT_FAMILY,
87
- suppressErrorRendering: true,
88
- flowchart: {
89
- htmlLabels: true,
90
- useMaxWidth: true,
91
- nodeSpacing: 40,
92
- rankSpacing: 50,
93
- padding: 12,
94
- },
95
- sequence: {
96
- useMaxWidth: true,
97
- },
98
- themeVariables: {
99
- fontFamily: MERMAID_FONT_FAMILY,
100
- },
101
- });
82
+ let mermaidPromise: Promise<Mermaid> | undefined;
83
+
84
+ /**
85
+ * Load Mermaid on first render of a diagram, initialized with a browser-focused config close to
86
+ * Mermaid Playground defaults. Mermaid is several hundred KB and most pages never render a diagram,
87
+ * so it is imported dynamically to keep it out of the eager bundle of every consuming app.
88
+ */
89
+ function loadMermaid(): Promise<Mermaid> {
90
+ if (!mermaidPromise) {
91
+ mermaidPromise = import('mermaid').then(({ default: mermaid }) => {
92
+ mermaid.initialize({
93
+ startOnLoad: false,
94
+ theme: 'default',
95
+ securityLevel: 'loose',
96
+ fontFamily: MERMAID_FONT_FAMILY,
97
+ suppressErrorRendering: true,
98
+ flowchart: {
99
+ htmlLabels: true,
100
+ useMaxWidth: true,
101
+ nodeSpacing: 40,
102
+ rankSpacing: 50,
103
+ padding: 12,
104
+ },
105
+ sequence: {
106
+ useMaxWidth: true,
107
+ },
108
+ themeVariables: {
109
+ fontFamily: MERMAID_FONT_FAMILY,
110
+ },
111
+ });
112
+ return mermaid;
113
+ });
114
+ }
115
+ return mermaidPromise;
116
+ }
102
117
 
103
118
  export interface MermaidDiagramProps {
104
119
  /** The mermaid diagram code */
@@ -147,6 +162,7 @@ export function MermaidDiagram({ code, className }: MermaidDiagramProps) {
147
162
  const normalizedCode = normalizeMermaidCodeForBrowser(code);
148
163
 
149
164
  // Render the diagram
165
+ const mermaid = await loadMermaid();
150
166
  const { svg: renderedSvg } = await mermaid.render(id, normalizedCode);
151
167
  const responsiveSvg = makeSvgResponsive(renderedSvg);
152
168