@vertesia/ui 1.5.0 → 1.6.0-dev.20260918.061604Z

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 (336) hide show
  1. package/README.md +125 -0
  2. package/lib/boot/branding.d.ts +58 -0
  3. package/lib/boot/branding.d.ts.map +1 -0
  4. package/lib/boot/branding.js +62 -0
  5. package/lib/boot/branding.js.map +1 -0
  6. package/lib/boot/index.d.ts +27 -0
  7. package/lib/boot/index.d.ts.map +1 -0
  8. package/lib/boot/index.js +325 -0
  9. package/lib/boot/index.js.map +1 -0
  10. package/lib/boot/vite.d.ts +63 -0
  11. package/lib/boot/vite.d.ts.map +1 -0
  12. package/lib/boot/vite.js +108 -0
  13. package/lib/boot/vite.js.map +1 -0
  14. package/lib/core/components/shadcn/button.d.ts.map +1 -1
  15. package/lib/core/components/shadcn/button.js +1 -2
  16. package/lib/core/components/shadcn/button.js.map +1 -1
  17. package/lib/core/components/shadcn/filters/filter-styles.d.ts +1 -1
  18. package/lib/core/components/shadcn/filters/filter-styles.d.ts.map +1 -1
  19. package/lib/core/components/shadcn/filters/filter-styles.js +4 -4
  20. package/lib/core/components/shadcn/label.js +1 -1
  21. package/lib/core/components/shadcn/label.js.map +1 -1
  22. package/lib/env/index.d.ts +32 -1
  23. package/lib/env/index.d.ts.map +1 -1
  24. package/lib/env/index.js +55 -3
  25. package/lib/env/index.js.map +1 -1
  26. package/lib/features/agent/PayloadBuilder.d.ts +4 -0
  27. package/lib/features/agent/PayloadBuilder.d.ts.map +1 -1
  28. package/lib/features/agent/PayloadBuilder.js +6 -1
  29. package/lib/features/agent/PayloadBuilder.js.map +1 -1
  30. package/lib/features/agent/chat/AgentRunFeedback.d.ts +66 -0
  31. package/lib/features/agent/chat/AgentRunFeedback.d.ts.map +1 -0
  32. package/lib/features/agent/chat/AgentRunFeedback.js +298 -0
  33. package/lib/features/agent/chat/AgentRunFeedback.js.map +1 -0
  34. package/lib/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
  35. package/lib/features/agent/chat/ModernAgentConversation.js +7 -5
  36. package/lib/features/agent/chat/ModernAgentConversation.js.map +1 -1
  37. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts +3 -1
  38. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
  39. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +11 -10
  40. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
  41. package/lib/features/agent/chat/ModernAgentOutput/Header.d.ts.map +1 -1
  42. package/lib/features/agent/chat/ModernAgentOutput/Header.js.map +1 -1
  43. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.d.ts +3 -1
  44. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.d.ts.map +1 -1
  45. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js +28 -7
  46. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -1
  47. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.d.ts.map +1 -1
  48. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.js +2 -0
  49. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.js.map +1 -1
  50. package/lib/features/agent/chat/hooks/useAgentPlans.d.ts +1 -1
  51. package/lib/features/agent/chat/hooks/useAgentPlans.d.ts.map +1 -1
  52. package/lib/features/agent/chat/hooks/useAgentPlans.js +5 -5
  53. package/lib/features/agent/chat/hooks/useAgentPlans.js.map +1 -1
  54. package/lib/features/agent/chat/index.d.ts +1 -0
  55. package/lib/features/agent/chat/index.d.ts.map +1 -1
  56. package/lib/features/agent/chat/index.js +1 -0
  57. package/lib/features/agent/chat/index.js.map +1 -1
  58. package/lib/features/facets/AgentRunnerFacetsNav.d.ts +8 -0
  59. package/lib/features/facets/AgentRunnerFacetsNav.d.ts.map +1 -1
  60. package/lib/features/facets/AgentRunnerFacetsNav.js +12 -0
  61. package/lib/features/facets/AgentRunnerFacetsNav.js.map +1 -1
  62. package/lib/features/permissions/UserPermissionsProvider.d.ts +15 -1
  63. package/lib/features/permissions/UserPermissionsProvider.d.ts.map +1 -1
  64. package/lib/features/permissions/UserPermissionsProvider.js +20 -12
  65. package/lib/features/permissions/UserPermissionsProvider.js.map +1 -1
  66. package/lib/features/store/objects/search/DocumentSearchContext.d.ts.map +1 -1
  67. package/lib/features/store/objects/search/DocumentSearchContext.js +6 -1
  68. package/lib/features/store/objects/search/DocumentSearchContext.js.map +1 -1
  69. package/lib/features/store/objects/selection/SelectionActions.js +1 -1
  70. package/lib/features/store/objects/selection/SelectionActions.js.map +1 -1
  71. package/lib/features/store/types/TypeRegistry.d.ts +130 -0
  72. package/lib/features/store/types/TypeRegistry.d.ts.map +1 -1
  73. package/lib/features/store/types/search/ObjectTypeSearchContext.d.ts +130 -0
  74. package/lib/features/store/types/search/ObjectTypeSearchContext.d.ts.map +1 -1
  75. package/lib/i18n/index.d.ts +5 -4
  76. package/lib/i18n/index.d.ts.map +1 -1
  77. package/lib/i18n/index.js +16 -2
  78. package/lib/i18n/index.js.map +1 -1
  79. package/lib/i18n/locales/ar.json +30 -0
  80. package/lib/i18n/locales/de.json +30 -0
  81. package/lib/i18n/locales/en.json +30 -0
  82. package/lib/i18n/locales/es.json +30 -0
  83. package/lib/i18n/locales/fr.json +30 -0
  84. package/lib/i18n/locales/it.json +30 -0
  85. package/lib/i18n/locales/ja.json +30 -0
  86. package/lib/i18n/locales/ko.json +30 -0
  87. package/lib/i18n/locales/pt.json +30 -0
  88. package/lib/i18n/locales/ru.json +30 -0
  89. package/lib/i18n/locales/tr.json +30 -0
  90. package/lib/i18n/locales/zh-TW.json +30 -0
  91. package/lib/i18n/locales/zh.json +30 -0
  92. package/lib/layout/ErrorPage.js +1 -1
  93. package/lib/layout/ErrorPage.js.map +1 -1
  94. package/lib/layout/Navbar.d.ts.map +1 -1
  95. package/lib/layout/Navbar.js +3 -2
  96. package/lib/layout/Navbar.js.map +1 -1
  97. package/lib/session/UserSession.d.ts.map +1 -1
  98. package/lib/session/UserSession.js +2 -3
  99. package/lib/session/UserSession.js.map +1 -1
  100. package/lib/session/UserSessionProvider.d.ts +2 -1
  101. package/lib/session/UserSessionProvider.d.ts.map +1 -1
  102. package/lib/session/UserSessionProvider.js +13 -4
  103. package/lib/session/UserSessionProvider.js.map +1 -1
  104. package/lib/session/auth/composable.d.ts.map +1 -1
  105. package/lib/session/auth/composable.js +88 -3
  106. package/lib/session/auth/composable.js.map +1 -1
  107. package/lib/session/auth/domainRouting.d.ts +22 -12
  108. package/lib/session/auth/domainRouting.d.ts.map +1 -1
  109. package/lib/session/auth/domainRouting.js +35 -21
  110. package/lib/session/auth/domainRouting.js.map +1 -1
  111. package/lib/session/auth/firebase.d.ts.map +1 -1
  112. package/lib/session/auth/firebase.js +10 -0
  113. package/lib/session/auth/firebase.js.map +1 -1
  114. package/lib/session/auth/useAuthState.d.ts +9 -4
  115. package/lib/session/auth/useAuthState.d.ts.map +1 -1
  116. package/lib/session/auth/useAuthState.js +9 -4
  117. package/lib/session/auth/useAuthState.js.map +1 -1
  118. package/lib/session/index.d.ts.map +1 -1
  119. package/lib/session/index.js +3 -1
  120. package/lib/session/index.js.map +1 -1
  121. package/lib/shell/AuthScreenPreview.d.ts +12 -0
  122. package/lib/shell/AuthScreenPreview.d.ts.map +1 -0
  123. package/lib/shell/AuthScreenPreview.js +140 -0
  124. package/lib/shell/AuthScreenPreview.js.map +1 -0
  125. package/lib/shell/BrandedAuthScreens.d.ts +19 -0
  126. package/lib/shell/BrandedAuthScreens.d.ts.map +1 -0
  127. package/lib/shell/BrandedAuthScreens.js +64 -0
  128. package/lib/shell/BrandedAuthScreens.js.map +1 -0
  129. package/lib/shell/SplashScreen.d.ts +13 -2
  130. package/lib/shell/SplashScreen.d.ts.map +1 -1
  131. package/lib/shell/SplashScreen.js +20 -19
  132. package/lib/shell/SplashScreen.js.map +1 -1
  133. package/lib/shell/VertesiaShell.d.ts +15 -4
  134. package/lib/shell/VertesiaShell.d.ts.map +1 -1
  135. package/lib/shell/VertesiaShell.js +8 -3
  136. package/lib/shell/VertesiaShell.js.map +1 -1
  137. package/lib/shell/apps/StandaloneApp.js +5 -1
  138. package/lib/shell/apps/StandaloneApp.js.map +1 -1
  139. package/lib/shell/index.d.ts +6 -0
  140. package/lib/shell/index.d.ts.map +1 -1
  141. package/lib/shell/index.js +5 -0
  142. package/lib/shell/index.js.map +1 -1
  143. package/lib/shell/login/SignInAuthPending.js +1 -1
  144. package/lib/shell/login/SignInAuthPending.js.map +1 -1
  145. package/lib/shell/login/SignInEmailStep.d.ts.map +1 -1
  146. package/lib/shell/login/SignInEmailStep.js +2 -2
  147. package/lib/shell/login/SignInEmailStep.js.map +1 -1
  148. package/lib/shell/login/SignInFlow.d.ts +68 -0
  149. package/lib/shell/login/SignInFlow.d.ts.map +1 -0
  150. package/lib/shell/login/SignInFlow.js +108 -0
  151. package/lib/shell/login/SignInFlow.js.map +1 -0
  152. package/lib/shell/login/SignInIcons.d.ts +1 -1
  153. package/lib/shell/login/SignInIcons.d.ts.map +1 -1
  154. package/lib/shell/login/SignInPageShell.d.ts +13 -0
  155. package/lib/shell/login/SignInPageShell.d.ts.map +1 -0
  156. package/lib/shell/login/SignInPageShell.js +14 -0
  157. package/lib/shell/login/SignInPageShell.js.map +1 -0
  158. package/lib/shell/login/SignInPrimitives.d.ts +3 -3
  159. package/lib/shell/login/SignInPrimitives.d.ts.map +1 -1
  160. package/lib/shell/login/SignInPrimitives.js +13 -11
  161. package/lib/shell/login/SignInPrimitives.js.map +1 -1
  162. package/lib/shell/login/SignInRestrictedEnvStep.d.ts +5 -0
  163. package/lib/shell/login/SignInRestrictedEnvStep.d.ts.map +1 -1
  164. package/lib/shell/login/SignInRestrictedEnvStep.js +8 -4
  165. package/lib/shell/login/SignInRestrictedEnvStep.js.map +1 -1
  166. package/lib/shell/login/SigninScreen.d.ts +38 -3
  167. package/lib/shell/login/SigninScreen.d.ts.map +1 -1
  168. package/lib/shell/login/SigninScreen.js +33 -86
  169. package/lib/shell/login/SigninScreen.js.map +1 -1
  170. package/lib/shell/login/SignupForm.d.ts +3 -1
  171. package/lib/shell/login/SignupForm.d.ts.map +1 -1
  172. package/lib/shell/login/SignupForm.js +7 -3
  173. package/lib/shell/login/SignupForm.js.map +1 -1
  174. package/lib/shell/login/signInUtils.d.ts +12 -1
  175. package/lib/shell/login/signInUtils.d.ts.map +1 -1
  176. package/lib/shell/login/signInUtils.js +34 -11
  177. package/lib/shell/login/signInUtils.js.map +1 -1
  178. package/lib/vertesia-ui-boot.js +237 -0
  179. package/lib/vertesia-ui-boot.js.map +1 -0
  180. package/lib/vertesia-ui-core.js +88 -46
  181. package/lib/vertesia-ui-core.js.map +1 -1
  182. package/lib/vertesia-ui-env.js +1 -1
  183. package/lib/vertesia-ui-env.js.map +1 -1
  184. package/lib/vertesia-ui-features.js +350 -317
  185. package/lib/vertesia-ui-features.js.map +1 -1
  186. package/lib/vertesia-ui-i18n.B3NFclwl.chunk.js +5 -0
  187. package/lib/vertesia-ui-i18n.B3NFclwl.chunk.js.map +1 -0
  188. package/lib/vertesia-ui-i18n.BWSrNIxc.chunk.js +5 -0
  189. package/lib/vertesia-ui-i18n.BWSrNIxc.chunk.js.map +1 -0
  190. package/lib/vertesia-ui-i18n.BWvWeB1p.chunk.js +5 -0
  191. package/lib/vertesia-ui-i18n.BWvWeB1p.chunk.js.map +1 -0
  192. package/lib/vertesia-ui-i18n.BZCXvTC1.chunk.js +5 -0
  193. package/lib/vertesia-ui-i18n.BZCXvTC1.chunk.js.map +1 -0
  194. package/lib/vertesia-ui-i18n.BbJMvFZW.chunk.js +5 -0
  195. package/lib/vertesia-ui-i18n.BbJMvFZW.chunk.js.map +1 -0
  196. package/lib/vertesia-ui-i18n.CE5ldwpt.chunk.js +5 -0
  197. package/lib/vertesia-ui-i18n.CE5ldwpt.chunk.js.map +1 -0
  198. package/lib/vertesia-ui-i18n.CMC0IShY.chunk.js +5 -0
  199. package/lib/vertesia-ui-i18n.CMC0IShY.chunk.js.map +1 -0
  200. package/lib/vertesia-ui-i18n.CkcRqBKU.chunk.js +5 -0
  201. package/lib/vertesia-ui-i18n.CkcRqBKU.chunk.js.map +1 -0
  202. package/lib/vertesia-ui-i18n.D-Mq1sw_.chunk.js +5 -0
  203. package/lib/vertesia-ui-i18n.D-Mq1sw_.chunk.js.map +1 -0
  204. package/lib/vertesia-ui-i18n.DkK68-A-.chunk.js +5 -0
  205. package/lib/vertesia-ui-i18n.DkK68-A-.chunk.js.map +1 -0
  206. package/lib/vertesia-ui-i18n.XE_dcCg6.chunk.js +5 -0
  207. package/lib/vertesia-ui-i18n.XE_dcCg6.chunk.js.map +1 -0
  208. package/lib/vertesia-ui-i18n.js +2 -2
  209. package/lib/vertesia-ui-i18n.js.map +1 -1
  210. package/lib/vertesia-ui-i18n.qgNqMPvK.chunk.js +5 -0
  211. package/lib/vertesia-ui-i18n.qgNqMPvK.chunk.js.map +1 -0
  212. package/lib/vertesia-ui-layout.js +43 -19
  213. package/lib/vertesia-ui-layout.js.map +1 -1
  214. package/lib/vertesia-ui-rich-text.js +123 -74
  215. package/lib/vertesia-ui-rich-text.js.map +1 -1
  216. package/lib/vertesia-ui-router.js.map +1 -1
  217. package/lib/vertesia-ui-session.js +1 -1
  218. package/lib/vertesia-ui-session.js.map +1 -1
  219. package/lib/vertesia-ui-shell.js +87 -33
  220. package/lib/vertesia-ui-shell.js.map +1 -1
  221. package/lib/vertesia-ui-widgets.js +154 -98
  222. package/lib/vertesia-ui-widgets.js.map +1 -1
  223. package/lib/widgets/xml-viewer/hooks/useCollapsible.d.ts +1 -1
  224. package/llms.txt +6 -2
  225. package/package.json +45 -36
  226. package/src/__tests__/a11y.test.tsx +25 -0
  227. package/src/__tests__/theme.test.ts +91 -0
  228. package/src/boot/branding.test.ts +72 -0
  229. package/src/boot/branding.ts +108 -0
  230. package/src/boot/index.test.ts +216 -0
  231. package/src/boot/index.ts +356 -0
  232. package/src/boot/vite.test.ts +93 -0
  233. package/src/boot/vite.ts +118 -0
  234. package/src/core/components/shadcn/button.tsx +1 -2
  235. package/src/core/components/shadcn/filters/filter-styles.ts +4 -4
  236. package/src/core/components/shadcn/label.tsx +1 -1
  237. package/src/env/index.test.ts +127 -0
  238. package/src/env/index.ts +73 -3
  239. package/src/features/agent/PayloadBuilder.tsx +10 -1
  240. package/src/features/agent/chat/AgentRunFeedback.test.tsx +347 -0
  241. package/src/features/agent/chat/AgentRunFeedback.tsx +465 -0
  242. package/src/features/agent/chat/ModernAgentConversation.test.tsx +1 -1
  243. package/src/features/agent/chat/ModernAgentConversation.tsx +52 -47
  244. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.test.tsx +145 -0
  245. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +42 -24
  246. package/src/features/agent/chat/ModernAgentOutput/Header.tsx +4 -0
  247. package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +38 -5
  248. package/src/features/agent/chat/ModernAgentOutput/SummaryConversation.ts +2 -0
  249. package/src/features/agent/chat/ModernAgentOutput/utils.test.ts +14 -0
  250. package/src/features/agent/chat/hooks/useAgentPlans.test.ts +52 -0
  251. package/src/features/agent/chat/hooks/useAgentPlans.ts +5 -5
  252. package/src/features/agent/chat/hooks/useFileProcessing.test.tsx +0 -5
  253. package/src/features/agent/chat/index.ts +6 -0
  254. package/src/features/facets/AgentRunnerFacetsNav.tsx +26 -0
  255. package/src/features/permissions/UserPermissionsProvider.test.tsx +50 -1
  256. package/src/features/permissions/UserPermissionsProvider.tsx +82 -44
  257. package/src/features/store/objects/search/DocumentSearchContext.ts +8 -3
  258. package/src/features/store/objects/selection/SelectionActions.tsx +4 -1
  259. package/src/i18n/index.tsx +25 -2
  260. package/src/i18n/locales/ar.json +30 -0
  261. package/src/i18n/locales/de.json +30 -0
  262. package/src/i18n/locales/en.json +30 -0
  263. package/src/i18n/locales/es.json +30 -0
  264. package/src/i18n/locales/fr.json +30 -0
  265. package/src/i18n/locales/it.json +30 -0
  266. package/src/i18n/locales/ja.json +30 -0
  267. package/src/i18n/locales/ko.json +30 -0
  268. package/src/i18n/locales/pt.json +30 -0
  269. package/src/i18n/locales/ru.json +30 -0
  270. package/src/i18n/locales/tr.json +30 -0
  271. package/src/i18n/locales/zh-TW.json +30 -0
  272. package/src/i18n/locales/zh.json +30 -0
  273. package/src/layout/ErrorPage.tsx +1 -1
  274. package/src/layout/Navbar.test.tsx +58 -0
  275. package/src/layout/Navbar.tsx +5 -2
  276. package/src/router/path.test.ts +5 -5
  277. package/src/session/UserSession.ts +2 -4
  278. package/src/session/UserSessionProvider.strict-mode.test.tsx +44 -0
  279. package/src/session/UserSessionProvider.test.ts +62 -1
  280. package/src/session/UserSessionProvider.tsx +12 -4
  281. package/src/session/auth/composable.renewal.test.ts +170 -0
  282. package/src/session/auth/composable.test.ts +23 -1
  283. package/src/session/auth/composable.ts +101 -2
  284. package/src/session/auth/domainRouting.test.ts +35 -65
  285. package/src/session/auth/domainRouting.ts +51 -34
  286. package/src/session/auth/firebase.test.ts +25 -0
  287. package/src/session/auth/firebase.ts +10 -0
  288. package/src/session/auth/useAuthState.ts +11 -4
  289. package/src/session/index.ts +3 -1
  290. package/src/shell/AuthScreenPreview.test.tsx +44 -0
  291. package/src/shell/AuthScreenPreview.tsx +228 -0
  292. package/src/shell/BrandedAuthScreens.test.tsx +181 -0
  293. package/src/shell/BrandedAuthScreens.tsx +117 -0
  294. package/src/shell/SplashScreen.test.tsx +37 -0
  295. package/src/shell/SplashScreen.tsx +44 -39
  296. package/src/shell/VertesiaShell.tsx +49 -22
  297. package/src/shell/apps/StandaloneApp.tsx +5 -1
  298. package/src/shell/index.tsx +6 -0
  299. package/src/shell/login/SignInAuthPending.tsx +3 -3
  300. package/src/shell/login/SignInEmailStep.test.tsx +32 -0
  301. package/src/shell/login/SignInEmailStep.tsx +13 -9
  302. package/src/shell/login/SignInFlow.tsx +213 -0
  303. package/src/shell/login/SignInPageShell.tsx +62 -0
  304. package/src/shell/login/SignInPrimitives.tsx +14 -11
  305. package/src/shell/login/SignInRestrictedEnvStep.tsx +19 -7
  306. package/src/shell/login/SigninScreen.test.tsx +104 -0
  307. package/src/shell/login/SigninScreen.tsx +115 -145
  308. package/src/shell/login/SignupForm.tsx +8 -3
  309. package/src/shell/login/signInUtils.ts +42 -9
  310. package/src/widgets/markdown/CollaborativeMarkdownRenderer.test.tsx +11 -3
  311. package/src/widgets/markdown/markdown.css +21 -21
  312. package/lib/vertesia-ui-i18n.BfN7iOHb.chunk.js +0 -5
  313. package/lib/vertesia-ui-i18n.BfN7iOHb.chunk.js.map +0 -1
  314. package/lib/vertesia-ui-i18n.BjH2zEZw.chunk.js +0 -5
  315. package/lib/vertesia-ui-i18n.BjH2zEZw.chunk.js.map +0 -1
  316. package/lib/vertesia-ui-i18n.BjSwAZXl.chunk.js +0 -5
  317. package/lib/vertesia-ui-i18n.BjSwAZXl.chunk.js.map +0 -1
  318. package/lib/vertesia-ui-i18n.C7PUm5Au.chunk.js +0 -5
  319. package/lib/vertesia-ui-i18n.C7PUm5Au.chunk.js.map +0 -1
  320. package/lib/vertesia-ui-i18n.CF_1mUS5.chunk.js +0 -5
  321. package/lib/vertesia-ui-i18n.CF_1mUS5.chunk.js.map +0 -1
  322. package/lib/vertesia-ui-i18n.ChfUl3_-.chunk.js +0 -5
  323. package/lib/vertesia-ui-i18n.ChfUl3_-.chunk.js.map +0 -1
  324. package/lib/vertesia-ui-i18n.D-Sk-5d1.chunk.js +0 -5
  325. package/lib/vertesia-ui-i18n.D-Sk-5d1.chunk.js.map +0 -1
  326. package/lib/vertesia-ui-i18n.D4rnu1_S.chunk.js +0 -5
  327. package/lib/vertesia-ui-i18n.D4rnu1_S.chunk.js.map +0 -1
  328. package/lib/vertesia-ui-i18n.DDf0-laK.chunk.js +0 -5
  329. package/lib/vertesia-ui-i18n.DDf0-laK.chunk.js.map +0 -1
  330. package/lib/vertesia-ui-i18n.DN79y06J.chunk.js +0 -5
  331. package/lib/vertesia-ui-i18n.DN79y06J.chunk.js.map +0 -1
  332. package/lib/vertesia-ui-i18n.DWLIciYQ.chunk.js +0 -5
  333. package/lib/vertesia-ui-i18n.DWLIciYQ.chunk.js.map +0 -1
  334. package/lib/vertesia-ui-i18n.DvF_YaAJ.chunk.js +0 -5
  335. package/lib/vertesia-ui-i18n.DvF_YaAJ.chunk.js.map +0 -1
  336. package/src/session/auth/authState.test.ts +0 -35
@@ -818,6 +818,105 @@ describe('AllMessagesMixed summary view', () => {
818
818
  expect(screen.getByText('Main agent response.')).not.toBeNull();
819
819
  });
820
820
 
821
+ it('keeps the existing back action visible for an empty selected workstream', () => {
822
+ renderSummary([
823
+ makeMessage({
824
+ timestamp: 1_000,
825
+ type: AgentMessageType.QUESTION,
826
+ message: 'Implement a type for a contract.',
827
+ }),
828
+ makeMessage({
829
+ timestamp: 2_000,
830
+ type: AgentMessageType.UPDATE,
831
+ message: 'Workstream "app_development_process" launched',
832
+ workstream_id: 'app_development_process',
833
+ details: {
834
+ event_class: 'activity',
835
+ workstream_event: 'launched',
836
+ launch_id: 'launch-process',
837
+ workstream_id: 'app_development_process',
838
+ kind: 'process',
839
+ process_run_id: 'process-run-1',
840
+ process_workflow_id: 'process-wf-1',
841
+ process_name: 'App Development Process',
842
+ },
843
+ }),
844
+ makeMessage({
845
+ timestamp: 3_000,
846
+ type: AgentMessageType.ANSWER,
847
+ message: 'Main agent response.',
848
+ }),
849
+ ]);
850
+
851
+ fireEvent.click(screen.getByRole('button', { name: /App Development Process/ }));
852
+
853
+ expect(screen.getByRole('button', { name: 'Back to main agent' })).not.toBeNull();
854
+ expect(screen.getByText('No messages in this workstream yet...')).not.toBeNull();
855
+
856
+ fireEvent.click(screen.getByRole('button', { name: 'Back to main agent' }));
857
+
858
+ expect(screen.getByText('Main agent response.')).not.toBeNull();
859
+ });
860
+
861
+ it('renders relayed Process progress in the selected workstream', () => {
862
+ renderSummary([
863
+ makeMessage({
864
+ timestamp: 1_000,
865
+ type: AgentMessageType.QUESTION,
866
+ message: 'Implement a type for a contract.',
867
+ }),
868
+ makeMessage({
869
+ timestamp: 2_000,
870
+ type: AgentMessageType.UPDATE,
871
+ message: 'Workstream "app_development_process" launched',
872
+ workstream_id: 'app_development_process',
873
+ details: {
874
+ event_class: 'activity',
875
+ workstream_event: 'launched',
876
+ launch_id: 'launch-process',
877
+ workstream_id: 'app_development_process',
878
+ kind: 'process',
879
+ process_run_id: 'process-run-1',
880
+ process_workflow_id: 'process-wf-1',
881
+ process_name: 'App Development Process',
882
+ },
883
+ }),
884
+ makeMessage({
885
+ timestamp: 3_000,
886
+ type: AgentMessageType.UPDATE,
887
+ message: 'Process running at implementation (agent, sequence 2).',
888
+ workstream_id: 'app_development_process',
889
+ details: {
890
+ event_class: 'activity',
891
+ process_event: 'progress',
892
+ launch_id: 'launch-process',
893
+ workstream_id: 'app_development_process',
894
+ kind: 'process',
895
+ process_run_id: 'process-run-1',
896
+ process_workflow_id: 'process-wf-1',
897
+ process_name: 'App Development Process',
898
+ phase: 'executing_tool',
899
+ current_step: 'implementation',
900
+ process_status: 'running',
901
+ process_current_node: 'implementation',
902
+ process_current_node_type: 'agent',
903
+ process_sequence: 2,
904
+ },
905
+ }),
906
+ makeMessage({
907
+ timestamp: 4_000,
908
+ type: AgentMessageType.ANSWER,
909
+ message: 'Main agent response.',
910
+ }),
911
+ ]);
912
+
913
+ fireEvent.click(screen.getByRole('button', { name: /App Development Process/ }));
914
+
915
+ expect(screen.getByRole('button', { name: 'Back to main agent' })).not.toBeNull();
916
+ expect(screen.getByText('Process running at implementation (agent, sequence 2).')).not.toBeNull();
917
+ expect(screen.queryByText('Main agent response.')).toBeNull();
918
+ });
919
+
821
920
  it('keeps streamed and persisted child output in the owning workstream throughout its lifecycle', () => {
822
921
  const question = makeMessage({
823
922
  timestamp: 1_000,
@@ -2782,3 +2881,49 @@ describe('AllMessagesMixed resource summary — same-timestamp cursor clipping',
2782
2881
  expect(screen.queryByText('Doc B')).toBeNull();
2783
2882
  });
2784
2883
  });
2884
+
2885
+ describe('AllMessagesMixed — answer feedback', () => {
2886
+ const answer = makeMessage({ type: AgentMessageType.ANSWER, message: 'Here is the result.', timestamp: 10 });
2887
+ const thought = makeMessage({ type: AgentMessageType.UPDATE, message: 'Working on it.', timestamp: 5 });
2888
+
2889
+ it('renders the rating control under each answer in the details view when a run id is given', () => {
2890
+ renderStacked([thought, answer], true, { agentRunId: 'agent-run-1' });
2891
+
2892
+ expect(screen.getByRole('button', { name: 'Rate this answer up' })).not.toBeNull();
2893
+ expect(screen.getByRole('button', { name: 'Rate this answer down' })).not.toBeNull();
2894
+ // Only answers are rated; the working update above it carries no control.
2895
+ expect(screen.getAllByRole('button', { name: /Rate this answer/ })).toHaveLength(2);
2896
+ });
2897
+
2898
+ it('renders the rating control under each answer in the summary view when a run id is given', () => {
2899
+ const session = new UserSession({} as unknown as VertesiaClient);
2900
+ const bottomRef = React.createRef<HTMLDivElement>() as React.RefObject<HTMLDivElement>;
2901
+ render(
2902
+ <I18nProvider lng="en">
2903
+ <ReactRouterContext.Provider value={makeRouterContext()}>
2904
+ <UserSessionContext.Provider value={session}>
2905
+ <AgentResourceResolverProvider value={testResourceResolver}>
2906
+ <AllMessagesMixed
2907
+ messages={[thought, answer]}
2908
+ bottomRef={bottomRef}
2909
+ viewMode="sliding"
2910
+ isCompleted
2911
+ artifactRunId="run-1"
2912
+ agentRunId="agent-run-1"
2913
+ />
2914
+ </AgentResourceResolverProvider>
2915
+ </UserSessionContext.Provider>
2916
+ </ReactRouterContext.Provider>
2917
+ </I18nProvider>,
2918
+ );
2919
+
2920
+ expect(screen.getByRole('button', { name: 'Rate this answer up' })).not.toBeNull();
2921
+ expect(screen.getAllByRole('button', { name: /Rate this answer/ })).toHaveLength(2);
2922
+ });
2923
+
2924
+ it('renders no rating control without a run id (fixture playback)', () => {
2925
+ renderStacked([thought, answer], true);
2926
+
2927
+ expect(screen.queryByRole('button', { name: /Rate this answer/ })).toBeNull();
2928
+ });
2929
+ });
@@ -29,6 +29,7 @@ import {
29
29
  Wrench,
30
30
  } from 'lucide-react';
31
31
  import React, { Component, type ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react';
32
+ import { AgentRunFeedback, agentMessageFeedbackId, isAgentMessageRatable } from '../AgentRunFeedback';
32
33
  import { AnimatedThinkingDots, PulsatingCircle } from '../AnimatedThinkingDots';
33
34
  import { AskUserWidget, isAskUserOptions } from '../AskUserWidget';
34
35
  import { DocumentEditingActionCard, parseMarkdownEditingAction } from '../DocumentEditingActionCard.js';
@@ -309,6 +310,8 @@ interface SummaryMessageProps {
309
310
  requestInputAnswered?: boolean;
310
311
  StoreLinkComponent?: React.ComponentType<{ href: string; documentId: string; children: React.ReactNode }>;
311
312
  CollectionLinkComponent?: React.ComponentType<{ href: string; collectionId: string; children: React.ReactNode }>;
313
+ /** When set, answers carry a thumbs up / down rating control scoped to the message. */
314
+ feedbackAgentRunId?: string;
312
315
  }
313
316
 
314
317
  function SummaryWorkstreamLaunchMessage({
@@ -677,6 +680,7 @@ function SummaryMessage({
677
680
  requestInputAnswered = false,
678
681
  StoreLinkComponent,
679
682
  CollectionLinkComponent,
683
+ feedbackAgentRunId,
680
684
  }: SummaryMessageProps) {
681
685
  const { router } = useRouterContext();
682
686
  const content =
@@ -794,7 +798,7 @@ function SummaryMessage({
794
798
  const isError = message.type === AgentMessageType.ERROR || message.type === AgentMessageType.WARNING;
795
799
 
796
800
  return (
797
- <div className="mx-auto w-full max-w-3xl px-1" data-workstream-id={workstreamId}>
801
+ <div className="group mx-auto w-full max-w-3xl px-1" data-workstream-id={workstreamId}>
798
802
  {isError && (
799
803
  <div className="mb-2 text-xs font-medium text-destructive">
800
804
  {message.type === AgentMessageType.WARNING ? 'Warning' : 'Error'}
@@ -819,6 +823,14 @@ function SummaryMessage({
819
823
  </MarkdownRenderer>
820
824
  </div>
821
825
  )}
826
+ {feedbackAgentRunId && isAgentMessageRatable(message) && (
827
+ <AgentRunFeedback
828
+ agentRunId={feedbackAgentRunId}
829
+ messageId={agentMessageFeedbackId(message)}
830
+ tone="inline"
831
+ className="mt-1 -ms-1.5 print:hidden"
832
+ />
833
+ )}
822
834
  </div>
823
835
  );
824
836
  }
@@ -2480,6 +2492,8 @@ interface AllMessagesMixedProps {
2480
2492
  batchProgressPanelClassNames?: BatchProgressPanelClassNames;
2481
2493
  /** Run ID used to resolve artifact references in streaming chart specs */
2482
2494
  artifactRunId?: string;
2495
+ /** Agent run to record answer ratings against. Omit to render answers without a rating control. */
2496
+ agentRunId?: string;
2483
2497
  /** Hide the workstream tabs entirely */
2484
2498
  hideWorkstreamTabs?: boolean;
2485
2499
  /** className override for the working indicator container */
@@ -2534,6 +2548,7 @@ function AllMessagesMixedComponent({
2534
2548
  streamingMessageClassNames,
2535
2549
  batchProgressPanelClassNames,
2536
2550
  artifactRunId,
2551
+ agentRunId,
2537
2552
  hideWorkstreamTabs,
2538
2553
  workingIndicatorClassName,
2539
2554
  messageListClassName,
@@ -3174,7 +3189,7 @@ function AllMessagesMixedComponent({
3174
3189
  padding: 0.75rem;
3175
3190
  border-radius: 0.5rem;
3176
3191
  overflow-x: auto;
3177
- background-color: var(--color-muted-background, #f3f4f6);
3192
+ background-color: var(--color-muted, #f3f4f6);
3178
3193
  color: var(--color-foreground, #1f2937);
3179
3194
  }
3180
3195
  .vprose pre code {
@@ -3269,7 +3284,7 @@ function AllMessagesMixedComponent({
3269
3284
  .agent-markdown :not(pre) > code {
3270
3285
  border: 1px solid var(--border);
3271
3286
  border-radius: 0.375rem;
3272
- background: var(--muted-background);
3287
+ background: var(--muted);
3273
3288
  color: var(--foreground);
3274
3289
  padding: 0.1rem 0.35rem;
3275
3290
  font-size: 0.8125em;
@@ -3282,7 +3297,7 @@ function AllMessagesMixedComponent({
3282
3297
  overflow: auto;
3283
3298
  border: 1px solid var(--border);
3284
3299
  border-radius: 0.75rem;
3285
- background: var(--muted-background);
3300
+ background: var(--muted);
3286
3301
  color: var(--foreground);
3287
3302
  padding: 0.875rem;
3288
3303
  font-size: 0.8125rem;
@@ -3370,6 +3385,27 @@ function AllMessagesMixedComponent({
3370
3385
  </div>
3371
3386
  )}
3372
3387
 
3388
+ {isSummaryView && activeWorkstream !== 'all' && activeWorkstreamName && (
3389
+ <div className="sticky top-0 z-20 -mx-2 bg-background/95 px-2 pb-2 pt-1 backdrop-blur sm:-mx-4 sm:px-4">
3390
+ <div className="mx-auto flex w-full max-w-3xl items-center gap-2 border-b border-border/70 pb-3">
3391
+ <Button
3392
+ type="button"
3393
+ variant="ghost"
3394
+ size="icon"
3395
+ className="size-8 shrink-0 text-muted hover:text-foreground"
3396
+ title={t('agent.backToMainAgent')}
3397
+ aria-label={t('agent.backToMainAgent')}
3398
+ onClick={handleShowMainAgentChat}
3399
+ >
3400
+ <ArrowLeft className="size-4" aria-hidden="true" />
3401
+ </Button>
3402
+ <div className="min-w-0 flex-1 truncate text-sm font-medium text-foreground">
3403
+ {activeWorkstreamName}
3404
+ </div>
3405
+ </div>
3406
+ </div>
3407
+ )}
3408
+
3373
3409
  {displayMessages.length === 0 &&
3374
3410
  incompleteStreaming.length === 0 &&
3375
3411
  !hasRenderableInitialRequest &&
@@ -3399,26 +3435,6 @@ function AllMessagesMixedComponent({
3399
3435
  messageListClassName,
3400
3436
  )}
3401
3437
  >
3402
- {isSummaryView && activeWorkstream !== 'all' && activeWorkstreamName && (
3403
- <div className="sticky top-0 z-20 -mx-2 bg-background/95 px-2 pb-2 pt-1 backdrop-blur sm:-mx-4 sm:px-4">
3404
- <div className="mx-auto flex w-full max-w-3xl items-center gap-2 border-b border-border/70 pb-3">
3405
- <Button
3406
- type="button"
3407
- variant="ghost"
3408
- size="icon"
3409
- className="size-8 shrink-0 text-muted hover:text-foreground"
3410
- title={t('agent.backToMainAgent')}
3411
- onClick={handleShowMainAgentChat}
3412
- >
3413
- <ArrowLeft className="size-4" aria-hidden="true" />
3414
- </Button>
3415
- <div className="min-w-0 flex-1 truncate text-sm font-medium text-foreground">
3416
- {activeWorkstreamName}
3417
- </div>
3418
- </div>
3419
- </div>
3420
- )}
3421
-
3422
3438
  {/* Friendly message — rendered outside the messages array to avoid memo issues/triggering autoscroll */}
3423
3439
  {shouldRenderInitialRequest && (
3424
3440
  <InitialRequestMessage
@@ -3588,6 +3604,7 @@ function AllMessagesMixedComponent({
3588
3604
  messageStyleOverrides={messageStyleOverrides}
3589
3605
  StoreLinkComponent={StoreLinkComponent}
3590
3606
  CollectionLinkComponent={CollectionLinkComponent}
3607
+ feedbackAgentRunId={agentRunId}
3591
3608
  />
3592
3609
  </MessageErrorBoundary>
3593
3610
  </TimelineEntry>
@@ -3708,6 +3725,7 @@ function AllMessagesMixedComponent({
3708
3725
  )}
3709
3726
  StoreLinkComponent={StoreLinkComponent}
3710
3727
  CollectionLinkComponent={CollectionLinkComponent}
3728
+ feedbackAgentRunId={agentRunId}
3711
3729
  />
3712
3730
  </MessageErrorBoundary>
3713
3731
  );
@@ -209,6 +209,10 @@ export default function Header({
209
209
  </Button>
210
210
  )}
211
211
 
212
+ {/* Keyed by run so a switch remounts the control. The component also resets itself —
213
+ it is exported and cannot assume a parent does this — but a remount here makes the
214
+ intent local and obvious at the one site that knows a new run is being shown. */}
215
+
212
216
  {agentRunId && (
213
217
  <Button
214
218
  type="button"
@@ -27,6 +27,7 @@ import type React from 'react';
27
27
  import { memo, useEffect, useMemo, useRef, useState } from 'react';
28
28
  import dayjs from '../../../../core/utils/dayjs.js';
29
29
  import { useDownloadFile } from '../../../store/objects/components/useDownloadFile.js';
30
+ import { AgentRunFeedback, agentMessageFeedbackId, isAgentMessageRatable } from '../AgentRunFeedback';
30
31
  import { PulsatingCircle } from '../AnimatedThinkingDots';
31
32
  import { AskUserWidget, isAskUserOptions } from '../AskUserWidget';
32
33
  import { DocumentEditingActionCard, parseMarkdownEditingAction } from '../DocumentEditingActionCard.js';
@@ -120,25 +121,42 @@ export interface MessageItemProps extends MessageItemClassNames {
120
121
  StoreLinkComponent?: React.ComponentType<{ href: string; documentId: string; children: React.ReactNode }>;
121
122
  /** Custom component to render store/collection links instead of default NavLink navigation */
122
123
  CollectionLinkComponent?: React.ComponentType<{ href: string; collectionId: string; children: React.ReactNode }>;
124
+ /** When set, answers carry a thumbs up / down rating control scoped to the message. */
125
+ feedbackAgentRunId?: string;
123
126
  }
124
127
 
125
128
  // Consolidated Studio/default message styling - single source of truth
126
129
  export const MESSAGE_STYLES: Record<AgentMessageType | 'default', MessageStyleConfig> = {
127
- [AgentMessageType.ANSWER]: { borderColor: 'border-s-info', iconColor: 'text-info', sender: 'Agent', Icon: Bot },
130
+ [AgentMessageType.ANSWER]: {
131
+ borderColor: 'border-s-info',
132
+ iconColor: 'text-info',
133
+ sender: 'Agent',
134
+ Icon: Bot,
135
+ },
128
136
  [AgentMessageType.COMPLETE]: {
129
137
  borderColor: 'border-s-success',
130
138
  iconColor: 'text-success',
131
139
  sender: 'Completed',
132
140
  Icon: CheckCircle,
133
141
  },
134
- [AgentMessageType.IDLE]: { borderColor: 'border-s-info', iconColor: 'text-info', sender: 'Ready', Icon: Clock },
142
+ [AgentMessageType.IDLE]: {
143
+ borderColor: 'border-s-info',
144
+ iconColor: 'text-info',
145
+ sender: 'Ready',
146
+ Icon: Clock,
147
+ },
135
148
  [AgentMessageType.REQUEST_INPUT]: {
136
149
  borderColor: 'border-s-attention',
137
150
  iconColor: 'text-attention',
138
151
  sender: 'Input',
139
152
  Icon: User,
140
153
  },
141
- [AgentMessageType.QUESTION]: { borderColor: 'border-s-muted', iconColor: 'text-muted', sender: 'User', Icon: User },
154
+ [AgentMessageType.QUESTION]: {
155
+ borderColor: 'border-s-muted',
156
+ iconColor: 'text-muted',
157
+ sender: 'User',
158
+ Icon: User,
159
+ },
142
160
  [AgentMessageType.THOUGHT]: {
143
161
  borderColor: 'border-s-done',
144
162
  iconColor: 'text-done',
@@ -175,7 +193,12 @@ export const MESSAGE_STYLES: Record<AgentMessageType | 'default', MessageStyleCo
175
193
  sender: 'Warning',
176
194
  Icon: AlertCircle,
177
195
  },
178
- [AgentMessageType.SYSTEM]: { borderColor: 'border-s-muted', iconColor: 'text-muted', sender: 'System', Icon: Info },
196
+ [AgentMessageType.SYSTEM]: {
197
+ borderColor: 'border-s-muted',
198
+ iconColor: 'text-muted',
199
+ sender: 'System',
200
+ Icon: Info,
201
+ },
179
202
  [AgentMessageType.STREAMING_CHUNK]: {
180
203
  borderColor: 'border-s-info',
181
204
  iconColor: 'text-info',
@@ -216,6 +239,7 @@ function MessageItemComponent({
216
239
  messageStyleOverrides,
217
240
  StoreLinkComponent,
218
241
  CollectionLinkComponent,
242
+ feedbackAgentRunId,
219
243
  }: MessageItemProps) {
220
244
  const [showDetails, setShowDetails] = useState(false);
221
245
  const { t } = useUITranslation();
@@ -549,7 +573,7 @@ function MessageItemComponent({
549
573
  <div className={cn('w-full max-w-full', resolvedStyle.className)}>
550
574
  <div
551
575
  className={cn(
552
- 'border-s-4 bg-white dark:bg-muted mb-4 w-full max-w-full overflow-hidden',
576
+ 'group border-s-4 bg-white dark:bg-muted mb-4 w-full max-w-full overflow-hidden',
553
577
  resolvedStyle.borderColor,
554
578
  resolvedStyle.cardClassName,
555
579
  )}
@@ -659,6 +683,15 @@ function MessageItemComponent({
659
683
  )
660
684
  )}
661
685
 
686
+ {feedbackAgentRunId && isAgentMessageRatable(message) && (
687
+ <AgentRunFeedback
688
+ agentRunId={feedbackAgentRunId}
689
+ messageId={agentMessageFeedbackId(message)}
690
+ tone="inline"
691
+ className="mt-2 -ms-1.5 print:hidden"
692
+ />
693
+ )}
694
+
662
695
  {messageAttachments.length > 0 && (
663
696
  <AttachmentPreviewList
664
697
  items={messageAttachments}
@@ -133,6 +133,8 @@ export function isSummaryAssistantProseMessage(message: AgentMessage): boolean {
133
133
 
134
134
  if (message.type === AgentMessageType.ANSWER) return true;
135
135
 
136
+ if (message.details?.process_event === 'progress' && message.details?.kind === 'process') return true;
137
+
136
138
  if (isToolPreambleMessage(message)) {
137
139
  // Text accompanying ask_user can be the draft the question asks the user to review.
138
140
  // Keep it visible for both persisted messages and reconstructed streaming messages.
@@ -141,6 +141,20 @@ describe('ModernAgentOutput utils - tool preamble behavior', () => {
141
141
  });
142
142
 
143
143
  describe('ModernAgentOutput summary - ask_user review content', () => {
144
+ it('preserves process progress visibility alongside tool preamble classification', () => {
145
+ const progress = makeMessage({
146
+ message: 'The process completed its review step.',
147
+ details: {
148
+ process_event: 'progress',
149
+ kind: 'process',
150
+ display_role: 'tool_preamble',
151
+ tools: ['update_plan'],
152
+ },
153
+ });
154
+
155
+ expect(buildSummaryConversationItems([progress], false)).toEqual([{ type: 'message', message: progress }]);
156
+ });
157
+
144
158
  const draft = '## Draft agenda\n9:00 Welcome\n9:15 Platform foundations';
145
159
  const tool = makeMessage({
146
160
  timestamp: 3000,
@@ -0,0 +1,52 @@
1
+ import { act, cleanup, renderHook } from '@testing-library/react';
2
+ import { type AgentMessage, AgentMessageType } from '@vertesia/common';
3
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
4
+ import { useAgentPlans } from './useAgentPlans.js';
5
+
6
+ const question: AgentMessage = {
7
+ timestamp: 1,
8
+ workflow_run_id: 'run-1',
9
+ workstream_id: 'main',
10
+ type: AgentMessageType.QUESTION,
11
+ message: 'Help with a task',
12
+ };
13
+ const plan: AgentMessage = {
14
+ ...question,
15
+ timestamp: 2,
16
+ type: AgentMessageType.PLAN,
17
+ details: { plan: [{ id: 1, goal: 'Review the task', status: 'pending' }] },
18
+ };
19
+
20
+ describe('useAgentPlans sidebar visibility', () => {
21
+ beforeEach(() => sessionStorage.clear());
22
+ afterEach(cleanup);
23
+
24
+ it('stays closed while history loads and when history has no plan', () => {
25
+ const { result, rerender } = renderHook(({ messages }) => useAgentPlans(messages, true), {
26
+ initialProps: { messages: [] as AgentMessage[] },
27
+ });
28
+ expect(result.current.showSlidingPanel).toBe(false);
29
+ rerender({ messages: [question] });
30
+ expect(result.current.showSlidingPanel).toBe(false);
31
+ });
32
+
33
+ it('opens when a plan arrives and resets for a new empty run', () => {
34
+ const { result, rerender } = renderHook(({ messages }) => useAgentPlans(messages, true), {
35
+ initialProps: { messages: [question] },
36
+ });
37
+ rerender({ messages: [question, plan] });
38
+ expect(result.current.showSlidingPanel).toBe(true);
39
+ expect(result.current.plans).toHaveLength(1);
40
+ rerender({ messages: [] });
41
+ expect(result.current.showSlidingPanel).toBe(false);
42
+ });
43
+
44
+ it('preserves manual opening when subsequent messages have no plan', () => {
45
+ const { result, rerender } = renderHook(({ messages }) => useAgentPlans(messages, true), {
46
+ initialProps: { messages: [question] },
47
+ });
48
+ act(() => result.current.setShowSlidingPanel(true));
49
+ rerender({ messages: [question, { ...question, timestamp: 3, type: AgentMessageType.ANSWER }] });
50
+ expect(result.current.showSlidingPanel).toBe(true);
51
+ });
52
+ });
@@ -18,14 +18,14 @@ export interface UseAgentPlansResult {
18
18
  * Key improvement: incremental processing. Instead of scanning ALL messages
19
19
  * on every change, tracks `lastProcessedIndex` and only scans new messages.
20
20
  */
21
- export function useAgentPlans(messages: AgentMessage[], interactive: boolean, isModal = false): UseAgentPlansResult {
21
+ export function useAgentPlans(messages: AgentMessage[], interactive: boolean): UseAgentPlansResult {
22
22
  const [plans, setPlans] = useState<Array<{ plan: Plan; timestamp: number }>>([]);
23
23
  const [activePlanIndex, setActivePlanIndex] = useState<number>(0);
24
24
  const [workstreamStatusMap, setWorkstreamStatusMap] = useState<
25
25
  Map<number, Map<string, 'pending' | 'in_progress' | 'completed' | 'skipped'>>
26
26
  >(new Map());
27
27
  const [showInput, setShowInput] = useState(interactive);
28
- const [showSlidingPanel, setShowSlidingPanel] = useState<boolean>(!isModal);
28
+ const [showSlidingPanel, setShowSlidingPanel] = useState<boolean>(false);
29
29
 
30
30
  // Incremental processing: track how far we've scanned
31
31
  const lastProcessedIndex = useRef<number>(-1);
@@ -38,12 +38,12 @@ export function useAgentPlans(messages: AgentMessage[], interactive: boolean, is
38
38
  setPlans([]);
39
39
  setActivePlanIndex(0);
40
40
  setWorkstreamStatusMap(new Map());
41
- // Keep right panel open by default on desktop sessions.
42
- setShowSlidingPanel(!isModal);
41
+ // Open automatically only once a plan is available.
42
+ setShowSlidingPanel(false);
43
43
  lastProcessedIndex.current = -1;
44
44
  knownPlanTimestamps.current.clear();
45
45
  }
46
- }, [messages.length, isModal]);
46
+ }, [messages.length]);
47
47
 
48
48
  // Helper to determine showInput from the latest message
49
49
  const updateShowInput = useCallback(
@@ -149,11 +149,6 @@ describe('useFileProcessing', () => {
149
149
 
150
150
  await act(async () => {
151
151
  resolveUpload?.({ url: 'https://example.test/upload', path: 'files/wrong.png' });
152
- // biome 2.5.6 regression: the nursery rule mis-types `await` on a `Promise | undefined`
153
- // variable assigned inside a callback, and its own fix suggests `await await`. It only
154
- // fires on Linux CI, not on macOS, so the suppression may read as unused locally.
155
- // Drop it once the rule is fixed upstream.
156
- // biome-ignore lint/nursery/noFloatingPromises: false positive — already awaited
157
152
  await uploadPromise;
158
153
  });
159
154
 
@@ -28,6 +28,12 @@ export {
28
28
  type AgentChatReplayStreamingMessage,
29
29
  } from './AgentChatFixtureReplay';
30
30
  export { AgentChatPlaybackControls, type AgentChatPlaybackControlsProps } from './AgentChatPlaybackControls';
31
+ export {
32
+ AgentRunFeedback,
33
+ type AgentRunFeedbackProps,
34
+ AgentRunFeedbackProvider,
35
+ agentRunFeedbackReasonCodes,
36
+ } from './AgentRunFeedback';
31
37
  export * from './AnimatedThinkingDots';
32
38
  // AskUser widget for displaying agent prompts/questions
33
39
  export {
@@ -30,6 +30,10 @@ export interface AgentRunnerFilterQuery {
30
30
  initiated_by?: string;
31
31
  start?: string;
32
32
  end?: string;
33
+ /** Evaluation severity (`high`, `medium`, `low`, `none`) or `unrated` for runs no detector looked at. */
34
+ evaluation?: string;
35
+ /** Last user rating on the run: `up` or `down`. */
36
+ feedback?: string;
33
37
  }
34
38
 
35
39
  const agentRunnerFilterNames = [
@@ -40,6 +44,8 @@ const agentRunnerFilterNames = [
40
44
  'initiated_by',
41
45
  'start',
42
46
  'end',
47
+ 'evaluation',
48
+ 'feedback',
43
49
  ] as const satisfies readonly (keyof AgentRunnerFilterQuery)[];
44
50
  const isAgentRunnerFilterName = createSearchQueryKeyGuard<AgentRunnerFilterQuery>(agentRunnerFilterNames);
45
51
 
@@ -50,6 +56,10 @@ interface AgentRunnerFacetsNavProps {
50
56
  interactions?: EnrichedFacetBucket[];
51
57
  /** `run_kind` buckets — `agent` (autonomous runs) and `process` (process runs). */
52
58
  kinds?: FacetBucket[];
59
+ /** Evaluation severity buckets, `unrated` standing for runs without an evaluation. */
60
+ evaluation?: FacetBucket[];
61
+ /** Last-rating buckets (`up` / `down`). */
62
+ feedback?: FacetBucket[];
53
63
  };
54
64
  search: SearchInterface<AgentRunnerFilterQuery>;
55
65
  actions?: React.ReactNode[];
@@ -108,6 +118,22 @@ export function useAgentRunnerFilterGroups(facets: AgentRunnerFacetsNavProps['fa
108
118
  }),
109
119
  );
110
120
 
121
+ customFilterGroups.push(
122
+ VStringFacet({
123
+ buckets: facets.evaluation || [],
124
+ name: 'evaluation',
125
+ placeholder: 'Evaluation',
126
+ }),
127
+ );
128
+
129
+ customFilterGroups.push(
130
+ VStringFacet({
131
+ buckets: facets.feedback || [],
132
+ name: 'feedback',
133
+ placeholder: 'Feedback',
134
+ }),
135
+ );
136
+
111
137
  customFilterGroups.push({
112
138
  name: 'start',
113
139
  placeholder: 'Started After',