@vertesia/ui 1.4.0 → 1.5.0-dev.20260713.151751Z

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 (344) hide show
  1. package/lib/core/components/InputList.d.ts.map +1 -1
  2. package/lib/core/components/InputList.js +3 -2
  3. package/lib/core/components/InputList.js.map +1 -1
  4. package/lib/core/components/SelectList.d.ts.map +1 -1
  5. package/lib/core/components/SelectList.js +1 -1
  6. package/lib/core/components/SelectList.js.map +1 -1
  7. package/lib/core/components/TagsInput.d.ts.map +1 -1
  8. package/lib/core/components/TagsInput.js +36 -4
  9. package/lib/core/components/TagsInput.js.map +1 -1
  10. package/lib/core/components/popup/Popup.js +2 -1
  11. package/lib/core/components/popup/Popup.js.map +1 -1
  12. package/lib/core/components/popup/position.d.ts.map +1 -1
  13. package/lib/core/components/popup/position.js +3 -6
  14. package/lib/core/components/popup/position.js.map +1 -1
  15. package/lib/core/components/shadcn/badge.d.ts +2 -2
  16. package/lib/core/components/shadcn/badge.d.ts.map +1 -1
  17. package/lib/core/components/shadcn/badge.js +3 -0
  18. package/lib/core/components/shadcn/badge.js.map +1 -1
  19. package/lib/core/components/shadcn/breadcrumb.d.ts.map +1 -1
  20. package/lib/core/components/shadcn/breadcrumb.js +2 -2
  21. package/lib/core/components/shadcn/breadcrumb.js.map +1 -1
  22. package/lib/core/components/shadcn/filters/filterBar.d.ts.map +1 -1
  23. package/lib/core/components/shadcn/filters/filterBar.js +1 -3
  24. package/lib/core/components/shadcn/filters/filterBar.js.map +1 -1
  25. package/lib/core/components/shadcn/resizeable.d.ts +1 -1
  26. package/lib/core/components/shadcn/resizeable.d.ts.map +1 -1
  27. package/lib/core/components/shadcn/resizeable.js +12 -2
  28. package/lib/core/components/shadcn/resizeable.js.map +1 -1
  29. package/lib/core/components/shadcn/selectBox.d.ts +7 -1
  30. package/lib/core/components/shadcn/selectBox.d.ts.map +1 -1
  31. package/lib/core/components/shadcn/selectBox.js +29 -12
  32. package/lib/core/components/shadcn/selectBox.js.map +1 -1
  33. package/lib/core/components/table/index.d.ts.map +1 -1
  34. package/lib/core/components/table/index.js +1 -1
  35. package/lib/core/components/table/index.js.map +1 -1
  36. package/lib/core/hooks/useIntersectionObserver.d.ts.map +1 -1
  37. package/lib/core/hooks/useIntersectionObserver.js +3 -1
  38. package/lib/core/hooks/useIntersectionObserver.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 -6
  41. package/lib/features/agent/chat/AgentRightPanel.js.map +1 -1
  42. package/lib/features/agent/chat/AnimatedThinkingDots.d.ts.map +1 -1
  43. package/lib/features/agent/chat/AnimatedThinkingDots.js +1 -1
  44. package/lib/features/agent/chat/AnimatedThinkingDots.js.map +1 -1
  45. package/lib/features/agent/chat/AskUserWidget.d.ts.map +1 -1
  46. package/lib/features/agent/chat/AskUserWidget.js +4 -3
  47. package/lib/features/agent/chat/AskUserWidget.js.map +1 -1
  48. package/lib/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
  49. package/lib/features/agent/chat/ModernAgentConversation.js +56 -11
  50. package/lib/features/agent/chat/ModernAgentConversation.js.map +1 -1
  51. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts +8 -1
  52. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
  53. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +40 -31
  54. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
  55. package/lib/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.js +3 -3
  56. package/lib/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.js.map +1 -1
  57. package/lib/features/agent/chat/ModernAgentOutput/MessageInput.d.ts.map +1 -1
  58. package/lib/features/agent/chat/ModernAgentOutput/MessageInput.js +5 -1
  59. package/lib/features/agent/chat/ModernAgentOutput/MessageInput.js.map +1 -1
  60. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js +3 -7
  61. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -1
  62. package/lib/features/agent/chat/ModernAgentOutput/PlanPanel.d.ts.map +1 -1
  63. package/lib/features/agent/chat/ModernAgentOutput/PlanPanel.js +5 -5
  64. package/lib/features/agent/chat/ModernAgentOutput/PlanPanel.js.map +1 -1
  65. package/lib/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.d.ts.map +1 -1
  66. package/lib/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.js +4 -4
  67. package/lib/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.js.map +1 -1
  68. package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.d.ts.map +1 -1
  69. package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.js +3 -3
  70. package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.js.map +1 -1
  71. package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.d.ts.map +1 -1
  72. package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js +156 -8
  73. package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js.map +1 -1
  74. package/lib/features/agent/chat/hooks/useFileProcessing.d.ts +1 -0
  75. package/lib/features/agent/chat/hooks/useFileProcessing.d.ts.map +1 -1
  76. package/lib/features/agent/chat/hooks/useFileProcessing.js +37 -3
  77. package/lib/features/agent/chat/hooks/useFileProcessing.js.map +1 -1
  78. package/lib/features/facets/AgentRunnerFacetsNav.d.ts.map +1 -1
  79. package/lib/features/facets/AgentRunnerFacetsNav.js +1 -1
  80. package/lib/features/facets/AgentRunnerFacetsNav.js.map +1 -1
  81. package/lib/features/facets/InteractionsFacetsNav.d.ts +10 -1
  82. package/lib/features/facets/InteractionsFacetsNav.d.ts.map +1 -1
  83. package/lib/features/facets/InteractionsFacetsNav.js +14 -5
  84. package/lib/features/facets/InteractionsFacetsNav.js.map +1 -1
  85. package/lib/features/facets/PromptsFacetsNav.d.ts.map +1 -1
  86. package/lib/features/facets/PromptsFacetsNav.js +12 -1
  87. package/lib/features/facets/PromptsFacetsNav.js.map +1 -1
  88. package/lib/features/facets/RunsFacetsNav.d.ts.map +1 -1
  89. package/lib/features/facets/RunsFacetsNav.js +1 -1
  90. package/lib/features/facets/RunsFacetsNav.js.map +1 -1
  91. package/lib/features/magic-pdf/AnnotatedImageSlider.d.ts.map +1 -1
  92. package/lib/features/magic-pdf/AnnotatedImageSlider.js +1 -3
  93. package/lib/features/magic-pdf/AnnotatedImageSlider.js.map +1 -1
  94. package/lib/features/magic-pdf/MagicPdfProvider.js +2 -3
  95. package/lib/features/magic-pdf/MagicPdfProvider.js.map +1 -1
  96. package/lib/features/store/objects/DocumentSearchResults.d.ts +6 -2
  97. package/lib/features/store/objects/DocumentSearchResults.d.ts.map +1 -1
  98. package/lib/features/store/objects/DocumentSearchResults.js +6 -6
  99. package/lib/features/store/objects/DocumentSearchResults.js.map +1 -1
  100. package/lib/features/store/objects/components/ContentOverview.js +1 -1
  101. package/lib/features/store/objects/components/ContentOverview.js.map +1 -1
  102. package/lib/features/store/objects/components/DocumentIcon.d.ts.map +1 -1
  103. package/lib/features/store/objects/components/DocumentIcon.js +1 -1
  104. package/lib/features/store/objects/components/DocumentIcon.js.map +1 -1
  105. package/lib/features/store/objects/components/DocumentInput.js.map +1 -1
  106. package/lib/features/store/objects/search/DocumentSearchContext.d.ts +4 -4
  107. package/lib/features/store/objects/search/DocumentSearchContext.d.ts.map +1 -1
  108. package/lib/features/store/objects/search/DocumentSearchContext.js +1 -1
  109. package/lib/features/store/objects/search/DocumentSearchContext.js.map +1 -1
  110. package/lib/features/store/objects/selection/ObjectsActionContext.d.ts.map +1 -1
  111. package/lib/features/store/objects/selection/ObjectsActionContext.js +2 -25
  112. package/lib/features/store/objects/selection/ObjectsActionContext.js.map +1 -1
  113. package/lib/features/store/objects/selection/ObjectsActionContextClass.d.ts +0 -2
  114. package/lib/features/store/objects/selection/ObjectsActionContextClass.d.ts.map +1 -1
  115. package/lib/features/store/objects/selection/ObjectsActionContextClass.js +1 -7
  116. package/lib/features/store/objects/selection/ObjectsActionContextClass.js.map +1 -1
  117. package/lib/features/store/objects/selection/ObjectsActionHooks.d.ts +0 -1
  118. package/lib/features/store/objects/selection/ObjectsActionHooks.d.ts.map +1 -1
  119. package/lib/features/store/objects/selection/ObjectsActionHooks.js +0 -10
  120. package/lib/features/store/objects/selection/ObjectsActionHooks.js.map +1 -1
  121. package/lib/features/store/objects/selection/SelectionActions.d.ts +4 -0
  122. package/lib/features/store/objects/selection/SelectionActions.d.ts.map +1 -1
  123. package/lib/features/store/objects/selection/SelectionActions.js +4 -18
  124. package/lib/features/store/objects/selection/SelectionActions.js.map +1 -1
  125. package/lib/features/store/objects/selection/actions/DeleteObjectsAction.d.ts.map +1 -1
  126. package/lib/features/store/objects/selection/actions/DeleteObjectsAction.js +16 -7
  127. package/lib/features/store/objects/selection/actions/DeleteObjectsAction.js.map +1 -1
  128. package/lib/features/store/objects/selection/actions/StartWorkflowButton.d.ts +7 -0
  129. package/lib/features/store/objects/selection/actions/StartWorkflowButton.d.ts.map +1 -0
  130. package/lib/features/store/objects/selection/actions/StartWorkflowButton.js +51 -0
  131. package/lib/features/store/objects/selection/actions/StartWorkflowButton.js.map +1 -0
  132. package/lib/features/store/objects/selection/actions/index.d.ts +0 -1
  133. package/lib/features/store/objects/selection/actions/index.d.ts.map +1 -1
  134. package/lib/features/store/objects/selection/actions/index.js +0 -1
  135. package/lib/features/store/objects/selection/actions/index.js.map +1 -1
  136. package/lib/features/store/types/ContentObjectTypesSearch.d.ts.map +1 -1
  137. package/lib/features/store/types/ContentObjectTypesSearch.js +55 -3
  138. package/lib/features/store/types/ContentObjectTypesSearch.js.map +1 -1
  139. package/lib/features/store/types/ContentObjectTypesTable.d.ts +5 -1
  140. package/lib/features/store/types/ContentObjectTypesTable.d.ts.map +1 -1
  141. package/lib/features/store/types/ContentObjectTypesTable.js +4 -2
  142. package/lib/features/store/types/ContentObjectTypesTable.js.map +1 -1
  143. package/lib/features/store/types/search/ObjectTypeSearchContext.js +1 -1
  144. package/lib/features/store/types/search/ObjectTypeSearchContext.js.map +1 -1
  145. package/lib/i18n/locales/ar.json +17 -0
  146. package/lib/i18n/locales/de.json +17 -0
  147. package/lib/i18n/locales/en.json +33 -0
  148. package/lib/i18n/locales/es.json +17 -0
  149. package/lib/i18n/locales/fr.json +17 -0
  150. package/lib/i18n/locales/it.json +17 -0
  151. package/lib/i18n/locales/ja.json +17 -0
  152. package/lib/i18n/locales/ko.json +17 -0
  153. package/lib/i18n/locales/pt.json +17 -0
  154. package/lib/i18n/locales/ru.json +17 -0
  155. package/lib/i18n/locales/tr.json +17 -0
  156. package/lib/i18n/locales/zh-TW.json +17 -0
  157. package/lib/i18n/locales/zh.json +17 -0
  158. package/lib/layout/Sidebar.d.ts +5 -1
  159. package/lib/layout/Sidebar.d.ts.map +1 -1
  160. package/lib/layout/Sidebar.js.map +1 -1
  161. package/lib/router/NestedRouterProvider.d.ts +1 -1
  162. package/lib/router/NestedRouterProvider.d.ts.map +1 -1
  163. package/lib/router/NestedRouterProvider.js +2 -2
  164. package/lib/router/NestedRouterProvider.js.map +1 -1
  165. package/lib/router/Redirect.d.ts +13 -0
  166. package/lib/router/Redirect.d.ts.map +1 -0
  167. package/lib/router/Redirect.js +20 -0
  168. package/lib/router/Redirect.js.map +1 -0
  169. package/lib/router/Router.d.ts.map +1 -1
  170. package/lib/router/Router.js +1 -2
  171. package/lib/router/Router.js.map +1 -1
  172. package/lib/router/index.d.ts +1 -0
  173. package/lib/router/index.d.ts.map +1 -1
  174. package/lib/router/index.js +1 -0
  175. package/lib/router/index.js.map +1 -1
  176. package/lib/session/DevSessionProvider.d.ts +8 -0
  177. package/lib/session/DevSessionProvider.d.ts.map +1 -0
  178. package/lib/session/DevSessionProvider.js +33 -0
  179. package/lib/session/DevSessionProvider.js.map +1 -0
  180. package/lib/session/UserSessionProvider.d.ts.map +1 -1
  181. package/lib/session/UserSessionProvider.js +16 -2
  182. package/lib/session/UserSessionProvider.js.map +1 -1
  183. package/lib/session/auth/composable.d.ts +10 -1
  184. package/lib/session/auth/composable.d.ts.map +1 -1
  185. package/lib/session/auth/composable.js +38 -2
  186. package/lib/session/auth/composable.js.map +1 -1
  187. package/lib/session/index.d.ts +1 -0
  188. package/lib/session/index.d.ts.map +1 -1
  189. package/lib/session/index.js +1 -0
  190. package/lib/session/index.js.map +1 -1
  191. package/lib/shell/VertesiaShell.d.ts +3 -1
  192. package/lib/shell/VertesiaShell.d.ts.map +1 -1
  193. package/lib/shell/VertesiaShell.js +5 -4
  194. package/lib/shell/VertesiaShell.js.map +1 -1
  195. package/lib/shell/login/SignInRestrictedEnvStep.d.ts +14 -0
  196. package/lib/shell/login/SignInRestrictedEnvStep.d.ts.map +1 -0
  197. package/lib/shell/login/SignInRestrictedEnvStep.js +50 -0
  198. package/lib/shell/login/SignInRestrictedEnvStep.js.map +1 -0
  199. package/lib/shell/login/SigninScreen.d.ts.map +1 -1
  200. package/lib/shell/login/SigninScreen.js +16 -3
  201. package/lib/shell/login/SigninScreen.js.map +1 -1
  202. package/lib/shell/login/productionUrl.d.ts +16 -0
  203. package/lib/shell/login/productionUrl.d.ts.map +1 -0
  204. package/lib/shell/login/productionUrl.js +19 -0
  205. package/lib/shell/login/productionUrl.js.map +1 -0
  206. package/lib/shell/login/signInUtils.d.ts.map +1 -1
  207. package/lib/shell/login/signInUtils.js +14 -1
  208. package/lib/shell/login/signInUtils.js.map +1 -1
  209. package/lib/vertesia-ui-core.js +95 -2
  210. package/lib/vertesia-ui-core.js.map +1 -1
  211. package/lib/vertesia-ui-env.js +2 -2
  212. package/lib/vertesia-ui-env.js.map +1 -1
  213. package/lib/vertesia-ui-features.js +454 -2
  214. package/lib/vertesia-ui-features.js.map +1 -1
  215. package/lib/vertesia-ui-i18n.js +41 -2
  216. package/lib/vertesia-ui-i18n.js.map +1 -1
  217. package/lib/vertesia-ui-layout.js +2 -2
  218. package/lib/vertesia-ui-layout.js.map +1 -1
  219. package/lib/vertesia-ui-router.js +2 -2
  220. package/lib/vertesia-ui-router.js.map +1 -1
  221. package/lib/vertesia-ui-session.js +2 -2
  222. package/lib/vertesia-ui-session.js.map +1 -1
  223. package/lib/vertesia-ui-shell.js +2 -2
  224. package/lib/vertesia-ui-shell.js.map +1 -1
  225. package/lib/vertesia-ui-widgets.js +9 -2
  226. package/lib/vertesia-ui-widgets.js.map +1 -1
  227. package/lib/widgets/json-view/JSONCode.d.ts.map +1 -1
  228. package/lib/widgets/json-view/JSONCode.js +1 -1
  229. package/lib/widgets/json-view/JSONCode.js.map +1 -1
  230. package/lib/widgets/json-view/JSONTable.d.ts.map +1 -1
  231. package/lib/widgets/json-view/JSONTable.js +1 -1
  232. package/lib/widgets/json-view/JSONTable.js.map +1 -1
  233. package/lib/widgets/markdown/ArtifactContentRenderer.d.ts.map +1 -1
  234. package/lib/widgets/markdown/ArtifactContentRenderer.js +1 -1
  235. package/lib/widgets/markdown/ArtifactContentRenderer.js.map +1 -1
  236. package/lib/widgets/markdown/CodeBlockPlaceholder.d.ts.map +1 -1
  237. package/lib/widgets/markdown/CodeBlockPlaceholder.js +1 -1
  238. package/lib/widgets/markdown/CodeBlockPlaceholder.js.map +1 -1
  239. package/lib/widgets/monacoEditor/foldingProviders.d.ts.map +1 -1
  240. package/lib/widgets/monacoEditor/foldingProviders.js +5 -10
  241. package/lib/widgets/monacoEditor/foldingProviders.js.map +1 -1
  242. package/lib/widgets/schema-editor/ManagedSchema.d.ts.map +1 -1
  243. package/lib/widgets/schema-editor/ManagedSchema.js +1 -2
  244. package/lib/widgets/schema-editor/ManagedSchema.js.map +1 -1
  245. package/lib/widgets/upload/UploadResultCategory.d.ts.map +1 -1
  246. package/lib/widgets/upload/UploadResultCategory.js +1 -1
  247. package/lib/widgets/upload/UploadResultCategory.js.map +1 -1
  248. package/lib/widgets/xml-viewer/components/TextElement/index.d.ts.map +1 -1
  249. package/lib/widgets/xml-viewer/components/TextElement/index.js +1 -1
  250. package/lib/widgets/xml-viewer/components/TextElement/index.js.map +1 -1
  251. package/package.json +38 -43
  252. package/src/core/components/InputList.tsx +5 -10
  253. package/src/core/components/SelectList.tsx +7 -2
  254. package/src/core/components/TagsInput.tsx +41 -4
  255. package/src/core/components/popup/Popup.tsx +3 -3
  256. package/src/core/components/popup/position.ts +3 -6
  257. package/src/core/components/shadcn/badge.tsx +3 -0
  258. package/src/core/components/shadcn/breadcrumb.tsx +2 -4
  259. package/src/core/components/shadcn/filters/filterBar.tsx +2 -3
  260. package/src/core/components/shadcn/resizeable.test.tsx +77 -0
  261. package/src/core/components/shadcn/resizeable.tsx +28 -2
  262. package/src/core/components/shadcn/selectBox.tsx +70 -36
  263. package/src/core/components/table/index.tsx +1 -2
  264. package/src/core/hooks/useIntersectionObserver.tsx +3 -1
  265. package/src/features/agent/chat/AgentRightPanel.tsx +5 -6
  266. package/src/features/agent/chat/AnimatedThinkingDots.tsx +1 -2
  267. package/src/features/agent/chat/AskUserWidget.test.tsx +49 -0
  268. package/src/features/agent/chat/AskUserWidget.tsx +32 -22
  269. package/src/features/agent/chat/ModernAgentConversation.test.tsx +198 -1
  270. package/src/features/agent/chat/ModernAgentConversation.tsx +62 -15
  271. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +60 -34
  272. package/src/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.tsx +3 -3
  273. package/src/features/agent/chat/ModernAgentOutput/MessageInput.test.tsx +25 -0
  274. package/src/features/agent/chat/ModernAgentOutput/MessageInput.tsx +5 -1
  275. package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +30 -30
  276. package/src/features/agent/chat/ModernAgentOutput/PlanPanel.tsx +5 -6
  277. package/src/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.tsx +4 -5
  278. package/src/features/agent/chat/ModernAgentOutput/ToolCallGroup.tsx +3 -5
  279. package/src/features/agent/chat/ModernAgentOutput/WorkstreamTabs.tsx +326 -42
  280. package/src/features/agent/chat/hooks/useFileProcessing.test.tsx +70 -0
  281. package/src/features/agent/chat/hooks/useFileProcessing.ts +37 -6
  282. package/src/features/facets/AgentRunnerFacetsNav.tsx +1 -2
  283. package/src/features/facets/InteractionsFacetsNav.tsx +30 -5
  284. package/src/features/facets/PromptsFacetsNav.tsx +13 -1
  285. package/src/features/facets/RunsFacetsNav.tsx +1 -2
  286. package/src/features/magic-pdf/AnnotatedImageSlider.tsx +1 -2
  287. package/src/features/magic-pdf/MagicPdfProvider.tsx +4 -4
  288. package/src/features/store/objects/DocumentSearchResults.tsx +11 -1
  289. package/src/features/store/objects/components/ContentOverview.tsx +1 -2
  290. package/src/features/store/objects/components/DocumentIcon.tsx +1 -2
  291. package/src/features/store/objects/components/DocumentInput.tsx +2 -2
  292. package/src/features/store/objects/search/DocumentSearchContext.test.ts +2 -2
  293. package/src/features/store/objects/search/DocumentSearchContext.ts +3 -3
  294. package/src/features/store/objects/selection/ObjectsActionContext.tsx +2 -27
  295. package/src/features/store/objects/selection/ObjectsActionContextClass.ts +1 -7
  296. package/src/features/store/objects/selection/ObjectsActionHooks.ts +0 -11
  297. package/src/features/store/objects/selection/SelectionActions.tsx +9 -34
  298. package/src/features/store/objects/selection/actions/DeleteObjectsAction.tsx +40 -7
  299. package/src/features/store/objects/selection/actions/StartWorkflowButton.tsx +104 -0
  300. package/src/features/store/objects/selection/actions/index.ts +0 -1
  301. package/src/features/store/types/ContentObjectTypesSearch.tsx +110 -1
  302. package/src/features/store/types/ContentObjectTypesTable.tsx +42 -3
  303. package/src/features/store/types/search/ObjectTypeSearchContext.tsx +1 -1
  304. package/src/i18n/locales/ar.json +17 -0
  305. package/src/i18n/locales/de.json +17 -0
  306. package/src/i18n/locales/en.json +33 -0
  307. package/src/i18n/locales/es.json +17 -0
  308. package/src/i18n/locales/fr.json +17 -0
  309. package/src/i18n/locales/it.json +17 -0
  310. package/src/i18n/locales/ja.json +17 -0
  311. package/src/i18n/locales/ko.json +17 -0
  312. package/src/i18n/locales/pt.json +17 -0
  313. package/src/i18n/locales/ru.json +17 -0
  314. package/src/i18n/locales/tr.json +17 -0
  315. package/src/i18n/locales/zh-TW.json +17 -0
  316. package/src/i18n/locales/zh.json +17 -0
  317. package/src/layout/Sidebar.tsx +6 -1
  318. package/src/router/NestedRouterProvider.tsx +2 -2
  319. package/src/router/Redirect.tsx +29 -0
  320. package/src/router/Router.tsx +1 -2
  321. package/src/router/index.ts +1 -0
  322. package/src/session/DevSessionProvider.tsx +46 -0
  323. package/src/session/UserSessionProvider.tsx +18 -2
  324. package/src/session/auth/composable.ts +41 -3
  325. package/src/session/index.ts +1 -0
  326. package/src/shell/VertesiaShell.tsx +27 -14
  327. package/src/shell/login/SignInRestrictedEnvStep.tsx +87 -0
  328. package/src/shell/login/SigninScreen.tsx +29 -16
  329. package/src/shell/login/productionUrl.test.ts +19 -0
  330. package/src/shell/login/productionUrl.ts +18 -0
  331. package/src/shell/login/signInUtils.ts +14 -1
  332. package/src/widgets/json-view/JSONCode.tsx +1 -2
  333. package/src/widgets/json-view/JSONTable.tsx +1 -2
  334. package/src/widgets/markdown/ArtifactContentRenderer.tsx +4 -7
  335. package/src/widgets/markdown/CodeBlockPlaceholder.tsx +1 -2
  336. package/src/widgets/monacoEditor/foldingProviders.ts +10 -15
  337. package/src/widgets/schema-editor/ManagedSchema.ts +1 -2
  338. package/src/widgets/upload/UploadResultCategory.tsx +2 -3
  339. package/src/widgets/xml-viewer/components/TextElement/index.tsx +1 -2
  340. package/lib/features/store/objects/selection/actions/StartWorkflowComponent.d.ts +0 -4
  341. package/lib/features/store/objects/selection/actions/StartWorkflowComponent.d.ts.map +0 -1
  342. package/lib/features/store/objects/selection/actions/StartWorkflowComponent.js +0 -77
  343. package/lib/features/store/objects/selection/actions/StartWorkflowComponent.js.map +0 -1
  344. package/src/features/store/objects/selection/actions/StartWorkflowComponent.tsx +0 -127
@@ -82,8 +82,13 @@ export function SelectList<T>({
82
82
  layout = defaultOptionLayout(option, isSelected);
83
83
  }
84
84
  return (
85
- // biome-ignore lint/suspicious/noArrayIndexKey: list order is stable for this render
86
- <SelectListOption key={i} option={option} onSelect={onSelect} layout={layout} noCheck={noCheck} />
85
+ <SelectListOption
86
+ key={`option-${i}`}
87
+ option={option}
88
+ onSelect={onSelect}
89
+ layout={layout}
90
+ noCheck={noCheck}
91
+ />
87
92
  );
88
93
  })}
89
94
  </div>
@@ -105,6 +105,43 @@ function TagsInputContent({
105
105
  }
106
106
  }, [isOpen]);
107
107
 
108
+ useEffect(() => {
109
+ if (!isOpen) {
110
+ return;
111
+ }
112
+
113
+ const isInsideTagsInput = (target: EventTarget | null) => {
114
+ return (
115
+ target instanceof Node &&
116
+ (triggerRef.current?.contains(target) === true || dropdownRef.current?.contains(target) === true)
117
+ );
118
+ };
119
+ const closeOnOutsidePointer = (event: PointerEvent) => {
120
+ if (!isInsideTagsInput(event.target)) {
121
+ setIsOpen(false);
122
+ }
123
+ };
124
+ const closeOnOutsideFocus = (event: FocusEvent) => {
125
+ if (!isInsideTagsInput(event.target)) {
126
+ setIsOpen(false);
127
+ }
128
+ };
129
+ const closeOnWindowBlur = () => {
130
+ setIsOpen(false);
131
+ };
132
+
133
+ document.addEventListener('pointerdown', closeOnOutsidePointer, true);
134
+ document.addEventListener('focusin', closeOnOutsideFocus, true);
135
+ window.addEventListener('blur', closeOnWindowBlur);
136
+ document.addEventListener('visibilitychange', closeOnWindowBlur);
137
+ return () => {
138
+ document.removeEventListener('pointerdown', closeOnOutsidePointer, true);
139
+ document.removeEventListener('focusin', closeOnOutsideFocus, true);
140
+ window.removeEventListener('blur', closeOnWindowBlur);
141
+ document.removeEventListener('visibilitychange', closeOnWindowBlur);
142
+ };
143
+ }, [isOpen, setIsOpen]);
144
+
108
145
  const handleSelect = (option: string) => {
109
146
  onChange([...value, option]);
110
147
  setSearchTerm('');
@@ -241,7 +278,7 @@ function TagsInputContent({
241
278
  <span
242
279
  key={item}
243
280
  className={clsx(
244
- 'inline-flex items-center justify-between gap-2 px-2 py-1 text-sm bg-primary/10 text-primary rounded-md w-full transition-all',
281
+ 'inline-flex items-center justify-between gap-2 px-2 py-1 text-sm bg-primary/20 text-foreground ring-1 ring-primary/30 rounded-md w-full transition-all',
245
282
  pendingDeleteIndex === index &&
246
283
  'ring-2 ring-red-300 shadow-[0_0_8px_rgba(252,165,165,0.5)]',
247
284
  )}
@@ -251,7 +288,7 @@ function TagsInputContent({
251
288
  type="button"
252
289
  onClick={(e) => handleRemove(item, e)}
253
290
  disabled={disabled}
254
- className="hover:bg-primary/20 rounded-sm transition-colors flex-shrink-0"
291
+ className="hover:bg-primary/30 rounded-sm transition-colors flex-shrink-0"
255
292
  >
256
293
  <X className="h-3 w-3" />
257
294
  </button>
@@ -266,7 +303,7 @@ function TagsInputContent({
266
303
  <span
267
304
  key={item}
268
305
  className={clsx(
269
- 'inline-flex items-center gap-1 px-2 py-1 text-sm bg-primary/10 text-primary rounded-md transition-all',
306
+ 'inline-flex items-center gap-1 px-2 py-1 text-sm bg-primary/20 text-foreground ring-1 ring-primary/30 rounded-md transition-all',
270
307
  pendingDeleteIndex === index &&
271
308
  'ring-2 ring-red-300 shadow-[0_0_8px_rgba(252,165,165,0.5)]',
272
309
  )}
@@ -276,7 +313,7 @@ function TagsInputContent({
276
313
  type="button"
277
314
  onClick={(e) => handleRemove(item, e)}
278
315
  disabled={disabled}
279
- className="hover:bg-primary/20 rounded-sm transition-colors"
316
+ className="hover:bg-primary/30 rounded-sm transition-colors"
280
317
  >
281
318
  <X className="h-3 w-3" />
282
319
  </button>
@@ -116,9 +116,9 @@ export interface PopupProps extends Omit<DOMPopupProps, 'anchor' | 'root'> {
116
116
  root?: React.RefObject<HTMLElement | null | undefined>;
117
117
  }
118
118
  export function Popup({ anchor, root, children, ...others }: PopupProps) {
119
- return anchor.current && (!root || root.current) ? (
120
- // biome-ignore lint/style/noNonNullAssertion: intentional non-null assertion; TS can't prove narrowing here
121
- <DOMPopup anchor={anchor.current!} root={root?.current || undefined} {...others}>
119
+ const anchorEl = anchor.current;
120
+ return anchorEl && (!root || root.current) ? (
121
+ <DOMPopup anchor={anchorEl} root={root?.current || undefined} {...others}>
122
122
  {children}
123
123
  </DOMPopup>
124
124
  ) : null;
@@ -209,13 +209,10 @@ class PositionResolver {
209
209
  }
210
210
  const constrainWidth = this.width != null;
211
211
  const constrainHeight = this.height != null;
212
- // biome-ignore lint/style/noNonNullAssertion: intentional non-null assertion; TS can't prove narrowing here
213
- const width = constrainWidth ? this.width! : elemRect.width;
214
- // biome-ignore lint/style/noNonNullAssertion: intentional non-null assertion; TS can't prove narrowing here
215
- const height = constrainHeight ? this.height! : elemRect.height;
212
+ const width = this.width ?? elemRect.width;
213
+ const height = this.height ?? elemRect.height;
216
214
  return {
217
- // biome-ignore lint/style/noNonNullAssertion: intentional non-null assertion; TS can't prove narrowing here
218
- rect: new DOMRect(this.left!, this.top!, width, height),
215
+ rect: new DOMRect(this.left ?? 0, this.top ?? 0, width, height),
219
216
  constrainWidth,
220
217
  constrainHeight,
221
218
  position: constraints.position,
@@ -14,6 +14,7 @@ const badgeVariants = cva('inline-flex items-center rounded-md px-2 py-1 text-xs
14
14
  success: 'bg-success text-success',
15
15
  info: 'bg-info text-info',
16
16
  done: 'bg-done text-done',
17
+ outline: 'bg-transparent border border-border text-foreground',
17
18
  },
18
19
  },
19
20
  defaultVariants: {
@@ -49,6 +50,7 @@ const dotBadgeVariants = cva(
49
50
  attention: '',
50
51
  done: '',
51
52
  info: '',
53
+ outline: '',
52
54
  },
53
55
  },
54
56
  defaultVariants: {
@@ -67,6 +69,7 @@ const dotVariants = cva('h-1.5 w-1.5', {
67
69
  attention: 'fill-attention',
68
70
  done: 'fill-done',
69
71
  info: 'fill-info',
72
+ outline: 'fill-foreground',
70
73
  },
71
74
  },
72
75
  defaultVariants: {
@@ -47,8 +47,7 @@ export function Breadcrumbs({ path, maxItems = 3, className, separator }: Breadc
47
47
  <Breadcrumb className={cn('w-full flex items-center', className)}>
48
48
  <BreadcrumbList>
49
49
  {items.map((item, index) => (
50
- // biome-ignore lint/suspicious/noArrayIndexKey: list order is stable for this render
51
- <React.Fragment key={index}>
50
+ <React.Fragment key={`crumb-${index}`}>
52
51
  <BreadcrumbItem>{renderBreadcrumbItem(item)}</BreadcrumbItem>
53
52
  {index < items.length - 1 && (
54
53
  <BreadcrumbSeparator>
@@ -73,8 +72,7 @@ export function Breadcrumbs({ path, maxItems = 3, className, separator }: Breadc
73
72
  <BreadcrumbSeparator>{separator ?? <ChevronRight className="cn-rtl-flip" />}</BreadcrumbSeparator>
74
73
 
75
74
  {lastThreeItems.map((item, index) => (
76
- // biome-ignore lint/suspicious/noArrayIndexKey: list order is stable for this render
77
- <React.Fragment key={index}>
75
+ <React.Fragment key={`crumb-${index}`}>
78
76
  <BreadcrumbItem>{renderBreadcrumbItem(item)}</BreadcrumbItem>
79
77
  {index < lastThreeItems.length - 1 && (
80
78
  <BreadcrumbSeparator>
@@ -227,10 +227,9 @@ const FilterBtn = ({ className }: { className?: string }) => {
227
227
  return <CommandEmpty>{t('filter.noAvailableFilters')}</CommandEmpty>;
228
228
  }
229
229
 
230
- return options.map((group: FilterGroup, index: number) => (
230
+ return options.map((group: FilterGroup) => (
231
231
  <CommandItem
232
- // biome-ignore lint/suspicious/noArrayIndexKey: list order is stable for this render
233
- key={index}
232
+ key={group.name}
234
233
  onSelect={() => handleSelect(group.name)}
235
234
  className="group flex gap-2 items-center hover:bg-muted"
236
235
  >
@@ -0,0 +1,77 @@
1
+ import { render } from '@testing-library/react';
2
+ import type React from 'react';
3
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
4
+
5
+ // Capture the props the wrapper forwards to the underlying react-resizable-panels
6
+ // primitive, and stub out its layout machinery so the assertions run in jsdom.
7
+ const mocks = vi.hoisted(() => ({ panelProps: vi.fn() }));
8
+
9
+ vi.mock('react-resizable-panels', () => ({
10
+ Group: ({ children }: { children?: React.ReactNode }) => <div data-testid="group">{children}</div>,
11
+ Panel: (props: Record<string, unknown>) => {
12
+ mocks.panelProps(props);
13
+ return <div data-testid="panel" />;
14
+ },
15
+ Separator: ({ children }: { children?: React.ReactNode }) => <div data-testid="separator">{children}</div>,
16
+ }));
17
+
18
+ import { ResizablePanel, ResizablePanelGroup } from './resizeable';
19
+
20
+ function forwardedPanelProps() {
21
+ return mocks.panelProps.mock.calls[0]?.[0] as Record<string, unknown>;
22
+ }
23
+
24
+ describe('ResizablePanel size coercion', () => {
25
+ beforeEach(() => {
26
+ mocks.panelProps.mockClear();
27
+ });
28
+
29
+ // Regression guard for the react-resizable-panels v3 -> v4 upgrade: v4 treats bare
30
+ // numeric sizes as PIXELS (v3 and below treated them as percentages). Every call site
31
+ // passes percentage-intended numbers, so the wrapper must re-add the "%" unit — without
32
+ // it, panels get clamped to a few pixels and the split can no longer be resized.
33
+ it('coerces bare numeric sizes to percentage strings', () => {
34
+ render(
35
+ <ResizablePanelGroup direction="horizontal">
36
+ <ResizablePanel defaultSize={50} minSize={20} maxSize={80} collapsedSize={5} />
37
+ </ResizablePanelGroup>,
38
+ );
39
+
40
+ expect(mocks.panelProps).toHaveBeenCalledTimes(1);
41
+ expect(forwardedPanelProps()).toMatchObject({
42
+ defaultSize: '50%',
43
+ minSize: '20%',
44
+ maxSize: '80%',
45
+ collapsedSize: '5%',
46
+ });
47
+ });
48
+
49
+ it('passes explicit unit strings through unchanged', () => {
50
+ render(
51
+ <ResizablePanelGroup direction="horizontal">
52
+ <ResizablePanel defaultSize="300px" minSize="10rem" maxSize="50%" />
53
+ </ResizablePanelGroup>,
54
+ );
55
+
56
+ expect(mocks.panelProps).toHaveBeenCalledTimes(1);
57
+ expect(forwardedPanelProps()).toMatchObject({
58
+ defaultSize: '300px',
59
+ minSize: '10rem',
60
+ maxSize: '50%',
61
+ });
62
+ });
63
+
64
+ it('leaves unspecified sizes undefined', () => {
65
+ render(
66
+ <ResizablePanelGroup direction="horizontal">
67
+ <ResizablePanel />
68
+ </ResizablePanelGroup>,
69
+ );
70
+
71
+ expect(mocks.panelProps).toHaveBeenCalledTimes(1);
72
+ const props = forwardedPanelProps();
73
+ expect(props.defaultSize).toBeUndefined();
74
+ expect(props.minSize).toBeUndefined();
75
+ expect(props.maxSize).toBeUndefined();
76
+ });
77
+ });
@@ -23,8 +23,34 @@ function ResizablePanelGroup({ className, direction = 'horizontal', orientation,
23
23
  );
24
24
  }
25
25
 
26
- function ResizablePanel({ ...props }: React.ComponentProps<typeof ResizablePrimitive.Panel>) {
27
- return <ResizablePrimitive.Panel data-slot="resizable-panel" {...props} />;
26
+ /**
27
+ * react-resizable-panels v4 treats bare numeric sizes as **pixels**; earlier majors
28
+ * (v3 and below) treated them as **percentages** of the group. Every call site in this
29
+ * codebase passes percentage-intended numbers (e.g. `defaultSize={50}`), so coerce bare
30
+ * numbers to percentage strings to preserve that contract after the v3→v4 upgrade.
31
+ * Explicit unit strings ("300px", "50%", "10rem", ...) are passed through untouched.
32
+ */
33
+ function toPercentSize(value: number | string | undefined): number | string | undefined {
34
+ return typeof value === 'number' ? `${value}%` : value;
35
+ }
36
+
37
+ function ResizablePanel({
38
+ defaultSize,
39
+ minSize,
40
+ maxSize,
41
+ collapsedSize,
42
+ ...props
43
+ }: React.ComponentProps<typeof ResizablePrimitive.Panel>) {
44
+ return (
45
+ <ResizablePrimitive.Panel
46
+ data-slot="resizable-panel"
47
+ defaultSize={toPercentSize(defaultSize)}
48
+ minSize={toPercentSize(minSize)}
49
+ maxSize={toPercentSize(maxSize)}
50
+ collapsedSize={toPercentSize(collapsedSize)}
51
+ {...props}
52
+ />
53
+ );
28
54
  }
29
55
 
30
56
  function ResizableHandle({
@@ -11,6 +11,12 @@ import { VTooltip } from './tooltip';
11
11
  export interface SelectBoxBaseProps<T> {
12
12
  options: T[] | undefined;
13
13
  optionLabel?: (option: T) => React.ReactNode;
14
+ /**
15
+ * Optional grouping. Returns the group heading for an option; options that return the same
16
+ * heading are rendered together beneath it. Groups appear in order of first occurrence in
17
+ * `options`, so the caller controls group order by ordering the options accordingly.
18
+ */
19
+ groupBy?: (option: T) => string;
14
20
  onBlur?: () => void;
15
21
  onKeyDown?: (e: React.KeyboardEvent, isOpen: boolean) => void;
16
22
  label?: string;
@@ -62,6 +68,7 @@ type SelectBoxProps<T> = SelectBoxSingleProps<T> | SelectBoxMultipleProps<T>;
62
68
  export function SelectBox<T = unknown>({
63
69
  options,
64
70
  optionLabel,
71
+ groupBy,
65
72
  value,
66
73
  onChange,
67
74
  addNew,
@@ -214,8 +221,10 @@ export function SelectBox<T = unknown>({
214
221
  return (
215
222
  <div className="flex flex-wrap gap-1">
216
223
  {arrayValue.slice(0, 1).map((item, index) => (
217
- // biome-ignore lint/suspicious/noArrayIndexKey: list order is stable for this render
218
- <span key={index} className="inline-flex items-center gap-1 px-2 py-1 text-xs bg-muted rounded">
224
+ <span
225
+ key={`chip-${index}`}
226
+ className="inline-flex items-center gap-1 px-2 py-1 text-xs bg-muted rounded"
227
+ >
219
228
  {optionLabel ? optionLabel(item) : (item as string)}
220
229
  </span>
221
230
  ))}
@@ -228,6 +237,52 @@ export function SelectBox<T = unknown>({
228
237
  );
229
238
  };
230
239
 
240
+ const renderOption = (opt: T, key: React.Key) => {
241
+ const isSelected = multiple
242
+ ? isOptionSelected(opt, Array.isArray(value) ? value : [])
243
+ : value != null
244
+ ? isOptionsEqual(value as T, opt)
245
+ : false;
246
+
247
+ return (
248
+ <CommandItem key={`option-${key}`} onSelect={() => _onClick(opt)} className="w-full">
249
+ {multiple || inline ? (
250
+ <div className="w-full flex justify-between items-center cursor-pointer">
251
+ <div className="w-full truncate text-start">
252
+ {optionLabel ? optionLabel(opt) : (opt as string)}
253
+ </div>
254
+ {isSelected && <Check className="size-4" />}
255
+ </div>
256
+ ) : (
257
+ <PopoverClose className="w-full flex justify-between items-center">
258
+ <div className="w-full truncate text-start">
259
+ {optionLabel ? optionLabel(opt) : (opt as string)}
260
+ </div>
261
+ {isSelected && <Check className="size-4" />}
262
+ </PopoverClose>
263
+ )}
264
+ </CommandItem>
265
+ );
266
+ };
267
+
268
+ // Group filtered options by `groupBy`, preserving first-occurrence order of groups.
269
+ const groupedOptions = (() => {
270
+ if (!groupBy) return null;
271
+ const groups: { key: string; items: T[] }[] = [];
272
+ const byKey = new Map<string, T[]>();
273
+ for (const opt of filteredOptions) {
274
+ const key = groupBy(opt);
275
+ let bucket = byKey.get(key);
276
+ if (!bucket) {
277
+ bucket = [];
278
+ byKey.set(key, bucket);
279
+ groups.push({ key, items: bucket });
280
+ }
281
+ bucket.push(opt);
282
+ }
283
+ return groups;
284
+ })();
285
+
231
286
  // Render the options list content
232
287
  const renderOptionsContent = () => (
233
288
  <>
@@ -253,40 +308,19 @@ export function SelectBox<T = unknown>({
253
308
  }}
254
309
  >
255
310
  <CommandEmpty>No result found.</CommandEmpty>
256
- <CommandGroup>
257
- {filteredOptions?.map((opt, index) => {
258
- const isSelected = multiple
259
- ? isOptionSelected(opt, Array.isArray(value) ? value : [])
260
- : value != null
261
- ? isOptionsEqual(value as T, opt)
262
- : false;
263
-
264
- return (
265
- <CommandItem
266
- // biome-ignore lint/suspicious/noArrayIndexKey: list order is stable for this render
267
- key={index}
268
- onSelect={() => _onClick(opt)}
269
- className="w-full"
270
- >
271
- {multiple || inline ? (
272
- <div className="w-full flex justify-between items-center cursor-pointer">
273
- <div className="w-full truncate text-start">
274
- {optionLabel ? optionLabel(opt) : (opt as string)}
275
- </div>
276
- {isSelected && <Check className="size-4" />}
277
- </div>
278
- ) : (
279
- <PopoverClose className="w-full flex justify-between items-center">
280
- <div className="w-full truncate text-start">
281
- {optionLabel ? optionLabel(opt) : (opt as string)}
282
- </div>
283
- {isSelected && <Check className="size-4" />}
284
- </PopoverClose>
285
- )}
286
- </CommandItem>
287
- );
288
- })}
289
- </CommandGroup>
311
+ {groupedOptions ? (
312
+ groupedOptions.map((group) => (
313
+ <CommandGroup
314
+ key={group.key}
315
+ heading={group.key}
316
+ className="[&_[cmdk-group-heading]]:text-muted [&_[cmdk-group-heading]]:border-b [&_[cmdk-group-heading]]:border-border [&_[cmdk-group-heading]]:ml-[-0.5rem] [&_[cmdk-group-heading]]:text-xs"
317
+ >
318
+ {group.items.map((opt, index) => renderOption(opt, `${group.key}-${index}`))}
319
+ </CommandGroup>
320
+ ))
321
+ ) : (
322
+ <CommandGroup>{filteredOptions?.map((opt, index) => renderOption(opt, index))}</CommandGroup>
323
+ )}
290
324
  </CommandList>
291
325
  </Command>
292
326
  {addNew && (
@@ -33,8 +33,7 @@ export function RowSkeleton({ columns }: { columns: number }) {
33
33
  {Array(columns)
34
34
  .fill(0)
35
35
  .map((_, index) => (
36
- // biome-ignore lint/suspicious/noArrayIndexKey: list order is stable for this render
37
- <td key={index}>
36
+ <td key={`skeleton-cell-${index}`}>
38
37
  <div className="animate-pulse rounded-xs h-5 bg-muted"></div>
39
38
  </td>
40
39
  ))}
@@ -45,5 +45,7 @@ export function useIntersectionObserver(
45
45
  observer.unobserve(element);
46
46
  }
47
47
  };
48
- }, [target, threshold]);
48
+ // opts.deps let callers re-attach the observer once the target element mounts
49
+ // (e.g. an infinite-scroll sentinel that renders only after the first page loads).
50
+ }, [target, threshold, ...(opts.deps ?? [])]);
49
51
  }
@@ -226,6 +226,7 @@ function WorkstreamsTab({ workstreams, messages, runId }: WorkstreamsTabProps) {
226
226
  ws.deadline_ms > 0 ? Math.min(100, Math.round((ws.elapsed_ms / ws.deadline_ms) * 100)) : 0;
227
227
  const browserUse = browserUseByWorkstream.get(ws.workstream_id);
228
228
  const hasDeadline = ws.deadline_ms > 0;
229
+ const childRunId = ws.child_workflow_run_id;
229
230
  const meta = [
230
231
  ws.phase ? formatWorkstreamName(ws.phase) : undefined,
231
232
  elapsed > 0 ? t('agent.elapsed', { seconds: elapsed }) : undefined,
@@ -313,14 +314,13 @@ function WorkstreamsTab({ workstreams, messages, runId }: WorkstreamsTabProps) {
313
314
  </RightPanelErrorBoundary>
314
315
  )}
315
316
 
316
- {ws.child_workflow_run_id && (
317
+ {childRunId && (
317
318
  <div className="mt-2 flex flex-wrap gap-1">
318
319
  <Button
319
320
  variant="ghost"
320
321
  size="sm"
321
322
  className="h-7 px-2 text-xs text-muted hover:text-foreground"
322
- // biome-ignore lint/style/noNonNullAssertion: TS can't prove narrowing here.
323
- onClick={() => copyRunId(ws.child_workflow_run_id!)}
323
+ onClick={() => copyRunId(childRunId)}
324
324
  >
325
325
  <ClipboardCopyIcon className="size-3 me-1" />
326
326
  {t('agent.copyRunId')}
@@ -329,8 +329,7 @@ function WorkstreamsTab({ workstreams, messages, runId }: WorkstreamsTabProps) {
329
329
  variant="ghost"
330
330
  size="sm"
331
331
  className="h-7 px-2 text-xs text-muted hover:text-foreground"
332
- // biome-ignore lint/style/noNonNullAssertion: TS can't prove narrowing here.
333
- onClick={() => downloadConversation(ws.child_workflow_run_id!)}
332
+ onClick={() => downloadConversation(childRunId)}
334
333
  >
335
334
  <DownloadCloudIcon className="size-3 me-1" />
336
335
  {t('agent.download')}
@@ -537,7 +536,7 @@ function OverflowTabsBar({ tabs, current, onTabChange, className }: OverflowTabs
537
536
  <div ref={containerRef} className={cn('relative', className)}>
538
537
  {/* Hidden measurement row: all tabs + More at natural width, kept separate
539
538
  from the visible row so measuring can't feed back into the layout. */}
540
- <div aria-hidden className="pointer-events-none invisible absolute left-0 top-0 flex w-max gap-1">
539
+ <div aria-hidden className="pointer-events-none invisible absolute start-0 top-0 flex w-max gap-1">
541
540
  {tabs.map((tab, i) => (
542
541
  <button
543
542
  type="button"
@@ -393,8 +393,7 @@ export function WavyThinking({ className, color = 'blue', size = 'md' }: WavyThi
393
393
  >
394
394
  {barHeights.map((height, i) => (
395
395
  <div
396
- // biome-ignore lint/suspicious/noArrayIndexKey: fixed-length array of 7 visual bars never re-orders
397
- key={i}
396
+ key={`bar-${i}`}
398
397
  className={cn(sizeClasses[size].barWidth, 'rounded-full transform-gpu', colorClasses[color])}
399
398
  style={{
400
399
  height: `${height}%`,
@@ -0,0 +1,49 @@
1
+ import type { ReactNode } from 'react';
2
+ import { describe, expect, it, vi } from 'vitest';
3
+ import { renderWithProviders } from '../../../__tests__/test-utils.js';
4
+ import { AskUserWidget } from './AskUserWidget';
5
+
6
+ vi.mock('../../../widgets/markdown/MarkdownRenderer', () => ({
7
+ MarkdownRenderer: ({ children }: { children: ReactNode }) => <>{children}</>,
8
+ }));
9
+
10
+ function getScrollablePrompt(container: HTMLElement): HTMLElement {
11
+ const question = container.querySelector('.agent-ask-question');
12
+ const scrollable = question?.parentElement;
13
+ if (!scrollable) {
14
+ throw new Error('Expected ask user question to be wrapped in a scrollable prompt container');
15
+ }
16
+ return scrollable;
17
+ }
18
+
19
+ describe('AskUserWidget', () => {
20
+ it('keeps compact prompt text in a bounded scrollable area', () => {
21
+ const { container } = renderWithProviders(
22
+ <AskUserWidget
23
+ compact
24
+ hideBorder
25
+ question={'Long prompt\n\n'.repeat(80)}
26
+ allowFreeResponse
27
+ submitLabel="Send"
28
+ />,
29
+ );
30
+
31
+ const scrollable = getScrollablePrompt(container);
32
+
33
+ expect(scrollable.className).toContain('max-h-80');
34
+ expect(scrollable.className).toContain('overflow-y-auto');
35
+ expect(scrollable.className).toContain('overscroll-contain');
36
+ });
37
+
38
+ it('keeps default prompt text in a bounded scrollable area', () => {
39
+ const { container } = renderWithProviders(
40
+ <AskUserWidget question={'Long prompt\n\n'.repeat(80)} allowFreeResponse submitLabel="Send" />,
41
+ );
42
+
43
+ const scrollable = getScrollablePrompt(container);
44
+
45
+ expect(scrollable.className).toContain('max-h-80');
46
+ expect(scrollable.className).toContain('overflow-y-auto');
47
+ expect(scrollable.className).toContain('overscroll-contain');
48
+ });
49
+ });