@opengeni/react 4.3.3-canary.39786771332001 → 4.5.0

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 (710) hide show
  1. package/dist/app/app-state.js +29 -29
  2. package/dist/app/components/Composer.js +27 -27
  3. package/dist/app/components/agent/agent-capability-picker.js +4 -4
  4. package/dist/app/components/artifacts/artifact-browse-controls.js +2 -2
  5. package/dist/app/components/artifacts/artifact-library.js +19 -19
  6. package/dist/app/components/artifacts/artifact-page-chrome.js +2 -2
  7. package/dist/app/components/artifacts/chat-interactive-block.js +16 -16
  8. package/dist/app/components/artifacts/inline-chat-image.js +31 -30
  9. package/dist/app/components/artifacts/retained-file-preview.js +35 -34
  10. package/dist/app/components/artifacts/retained-text-preview.js +5 -5
  11. package/dist/app/components/artifacts/site-audience.js +4 -4
  12. package/dist/app/components/artifacts/site-conversations.js +22 -21
  13. package/dist/app/components/artifacts/site-data.js +19 -19
  14. package/dist/app/components/artifacts/site-publishing.js +41 -41
  15. package/dist/app/components/artifacts/site-settings.js +50 -50
  16. package/dist/app/components/billing-class-mark.js +5 -5
  17. package/dist/app/components/capabilities/capability-detail-sheet.js +9 -9
  18. package/dist/app/components/capabilities/capability-logo-source.js +12 -12
  19. package/dist/app/components/capabilities/connector-tool-permissions.js +3 -3
  20. package/dist/app/components/capabilities/native-connect-setup.js +14 -14
  21. package/dist/app/components/capabilities/perform-capability-action.js +1 -1
  22. package/dist/app/components/capabilities/prepared-mcp-setup-card.js +16 -16
  23. package/dist/app/components/capabilities/session-capability-card.js +94 -76
  24. package/dist/app/components/capabilities/session-capability-card.js.map +1 -1
  25. package/dist/app/components/capabilities/session-chrome-card.css +1023 -0
  26. package/dist/app/components/capabilities/session-chrome-card.css.map +1 -0
  27. package/dist/app/components/capabilities/session-chrome-card.d.ts +18 -0
  28. package/dist/app/components/capabilities/session-chrome-card.js +72 -0
  29. package/dist/app/components/capabilities/session-custom-mcp-card.js +20 -20
  30. package/dist/app/components/capabilities/session-github-card.js +24 -24
  31. package/dist/app/components/capabilities/session-machine-card.d.ts +27 -1
  32. package/dist/app/components/capabilities/session-machine-card.js +40 -36
  33. package/dist/app/components/capabilities/use-capabilities-catalog.js +3 -3
  34. package/dist/app/components/capabilities/use-connection-accounts.js +1 -1
  35. package/dist/app/components/command-menu/chat-status.js +18 -17
  36. package/dist/app/components/command-menu/chat-switcher.js +19 -18
  37. package/dist/app/components/command-menu/chat-switcher.js.map +1 -1
  38. package/dist/app/components/command-menu/command-menu.js +36 -114
  39. package/dist/app/components/command-menu/command-menu.js.map +1 -1
  40. package/dist/app/components/command-menu/shortcut-sheet.js +17 -17
  41. package/dist/app/components/composer-capabilities-menu-body.js +3 -3
  42. package/dist/app/components/composer-mobile-plus-panel.js +20 -20
  43. package/dist/app/components/composer-mobile-plus.js +1 -1
  44. package/dist/app/components/credit-required-gate.js +1 -1
  45. package/dist/app/components/credit-required-prompt.js +12 -12
  46. package/dist/app/components/credits/coupon-redeem.js +2 -2
  47. package/dist/app/components/credits/credit-refusal-notice.js +2 -2
  48. package/dist/app/components/desktop/app-shots.js +7 -7
  49. package/dist/app/components/desktop/this-computer.js +4 -4
  50. package/dist/app/components/feedback.js +4 -4
  51. package/dist/app/components/follow-up-repository-menu-body.js +5 -5
  52. package/dist/app/components/follow-up-repository-picker.js +1 -1
  53. package/dist/app/components/github-app-connect-launcher.js +2 -2
  54. package/dist/app/components/in-app-help-link.js +2 -2
  55. package/dist/app/components/knowledge/agent-learning-settings.js +3 -3
  56. package/dist/app/components/machines/connect-machine-dialog.js +18 -18
  57. package/dist/app/components/markdown.js +9 -9
  58. package/dist/app/components/message-context-pills.js +2 -2
  59. package/dist/app/components/models/models-ui.js +8 -8
  60. package/dist/app/components/new-session-starters.js +2 -2
  61. package/dist/app/components/pickers.js +9 -9
  62. package/dist/app/components/rail/rail-context.js +2 -2
  63. package/dist/app/components/rail/rail-sections.js +69 -66
  64. package/dist/app/components/rail/session-header.js +49 -48
  65. package/dist/app/components/rail/session-list.js +68 -65
  66. package/dist/app/components/rail/session-row-content.d.ts +6 -2
  67. package/dist/app/components/rail/session-row-content.js +1 -1
  68. package/dist/app/components/rail/session-row-hover-details.js +24 -23
  69. package/dist/app/components/rail/session-shell.js +107 -104
  70. package/dist/app/components/rail/site-session-group-heading.d.ts +7 -1
  71. package/dist/app/components/rail/site-session-group-heading.js +20 -3
  72. package/dist/app/components/repository-picker.js +5 -5
  73. package/dist/app/components/secrets/session-secrets-panel.js +3 -3
  74. package/dist/app/components/session/agent-configuration-panel.js +38 -38
  75. package/dist/app/components/session/artifact-link-boundary.js +2 -2
  76. package/dist/app/components/session/artifact-session-page.js +4 -4
  77. package/dist/app/components/session/banners.js +11 -11
  78. package/dist/app/components/session/codex-account-indicator.js +12 -12
  79. package/dist/app/components/session/editable-artifacts-workspace.js +45 -45
  80. package/dist/app/components/session/failed-session-banner.js +11 -11
  81. package/dist/app/components/session/human-input.js +59 -55
  82. package/dist/app/components/session/inspector.js +91 -87
  83. package/dist/app/components/session/inspector.js.map +1 -1
  84. package/dist/app/components/session/message-actions.js +4 -4
  85. package/dist/app/components/session/message-resource-attachments.js +21 -20
  86. package/dist/app/components/session/message-resource-attachments.js.map +1 -1
  87. package/dist/app/components/session/model-account-indicator.js +11 -11
  88. package/dist/app/components/session/model-context-inspector.js +2 -2
  89. package/dist/app/components/session/model-recovery-notice.js +3 -3
  90. package/dist/app/components/session/new-session-settings-menu.js +12 -12
  91. package/dist/app/components/session/sandbox-switcher.js +16 -16
  92. package/dist/app/components/session/sandbox-workspace.js +83 -79
  93. package/dist/app/components/session/search-markdown-highlight.js +10 -10
  94. package/dist/app/components/session/search-results-view.js +11 -11
  95. package/dist/app/components/session/session-admin-access.js +9 -9
  96. package/dist/app/components/session/session-admission-notice.js +6 -6
  97. package/dist/app/components/session/session-machine-access-notice.js +6 -6
  98. package/dist/app/components/session/session-retention.js +4 -4
  99. package/dist/app/components/session/session-search-dialog.js +12 -12
  100. package/dist/app/components/session/session-skill-reviews.js +1 -1
  101. package/dist/app/components/session/session-tenancy-control.d.ts +2 -0
  102. package/dist/app/components/session/session-tenancy-control.js +41 -26
  103. package/dist/app/components/session/session-tenancy-control.js.map +1 -1
  104. package/dist/app/components/session/session-usage-limit-section.js +11 -11
  105. package/dist/app/components/session/session-wait-status.js +10 -9
  106. package/dist/app/components/session/session-wait-status.js.map +1 -1
  107. package/dist/app/components/session/site-origin-link.d.ts +1 -0
  108. package/dist/app/components/session/site-origin-link.js +2 -2
  109. package/dist/app/components/session/subagents.js +17 -16
  110. package/dist/app/components/session-connectors-menu-body.js +5 -5
  111. package/dist/app/components/settings/row-select.js +1 -1
  112. package/dist/app/components/transcription-settings.js +2 -2
  113. package/dist/app/components/ui/destructive-confirm.js +6 -6
  114. package/dist/app/components/usage/usage-entry.js +8 -8
  115. package/dist/app/components/workspace-composer-plus.js +22 -22
  116. package/dist/app/embed/memory-navigation.js +2 -2
  117. package/dist/app/embed/session-app.js +275 -269
  118. package/dist/app/lib/actions/actions-provider.js +14 -14
  119. package/dist/app/lib/actions/held-modifier.d.ts +11 -0
  120. package/dist/app/lib/app-surfaces.js +2 -2
  121. package/dist/app/lib/codex-usage-query.js +6 -6
  122. package/dist/app/lib/composer-connectors.js +13 -13
  123. package/dist/app/lib/console-site.d.ts +6 -0
  124. package/dist/app/lib/console-site.js +14 -0
  125. package/dist/app/lib/console-text.js +2 -2
  126. package/dist/app/lib/events.js +18 -17
  127. package/dist/app/lib/failed-session-copy.js +3 -3
  128. package/dist/app/lib/model-access-onboarding.js +3 -3
  129. package/dist/app/lib/move-chat-to-machine.js +3 -3
  130. package/dist/app/lib/navigation.d.ts +5 -0
  131. package/dist/app/lib/navigation.js +1 -1
  132. package/dist/app/lib/routes.d.ts +17 -0
  133. package/dist/app/lib/routes.js +9 -3
  134. package/dist/app/lib/session-branch-cache.js +14 -13
  135. package/dist/app/lib/session-create.js +2 -2
  136. package/dist/app/lib/session-deep-link.js +2 -2
  137. package/dist/app/lib/session-failure-toasts.d.ts +8 -0
  138. package/dist/app/lib/session-group-pagination.js +14 -13
  139. package/dist/app/lib/session-hover-facts.js +15 -14
  140. package/dist/app/lib/session-model.js +3 -3
  141. package/dist/app/lib/session-rail.js +10 -9
  142. package/dist/app/lib/session-rename.js +3 -3
  143. package/dist/app/lib/session-ui-features.d.ts +6 -1
  144. package/dist/app/lib/session-ui-features.js +1 -1
  145. package/dist/app/lib/sessions-group.d.ts +43 -3
  146. package/dist/app/lib/sessions-group.js +22 -15
  147. package/dist/app/lib/shared-query.js +3 -3
  148. package/dist/app/lib/site-opened.d.ts +6 -0
  149. package/dist/app/lib/site-opened.js +10 -0
  150. package/dist/app/lib/turn-failure-analytics.js +5 -5
  151. package/dist/app/lib/use-duplicate-site.js +3 -3
  152. package/dist/app/lib/use-follow-up-repositories.js +4 -4
  153. package/dist/app/lib/use-session-list-hint-refresh.d.ts +20 -2
  154. package/dist/app/lib/use-session-list-hint-refresh.js +5 -1
  155. package/dist/app/lib/use-workspace-machines.js +6 -6
  156. package/dist/app/lib/use-workspace-model-catalog.js +8 -8
  157. package/dist/app/lib/use-workspace-rigs.js +8 -8
  158. package/dist/app/lib/workspace-navigation-preference.js +5 -5
  159. package/dist/app/lib/workspace-scope-context.js +4 -4
  160. package/dist/app/routes/artifacts.js +136 -153
  161. package/dist/app/routes/artifacts.js.map +1 -1
  162. package/dist/app/routes/retained-artifact.js +63 -62
  163. package/dist/app/routes/retained-artifact.js.map +1 -1
  164. package/dist/app/routes/session-unavailable.js +7 -5
  165. package/dist/app/routes/session.js +177 -173
  166. package/dist/app/routes/sessions-index-hydration.js +3 -3
  167. package/dist/app/routes/sessions-index.js +123 -121
  168. package/dist/app/routes/site-view.d.ts +11 -0
  169. package/dist/app/routes/site-view.js +597 -0
  170. package/dist/app/routes/site-view.js.map +1 -0
  171. package/dist/artifacts-document.js +4 -4
  172. package/dist/artifacts-presentation.js +4 -4
  173. package/dist/artifacts-spreadsheet.js +4 -4
  174. package/dist/artifacts.js +39 -39
  175. package/dist/{browser-viewer-RYYQSRTC.js → browser-viewer-QMCNV4RI.js} +9 -7
  176. package/dist/{chat-interactive-block-ABCRKXJ4.js → chat-interactive-block-PMIAUXSO.js} +6 -6
  177. package/dist/{chunk-GIZGNFIX.js → chunk-22FFOHPT.js} +11 -11
  178. package/dist/chunk-22GTC4MZ.js +15 -0
  179. package/dist/chunk-22GTC4MZ.js.map +1 -0
  180. package/dist/{chunk-Z5WMLJKI.js → chunk-22JFMNMF.js} +92 -4
  181. package/dist/chunk-22JFMNMF.js.map +1 -0
  182. package/dist/{chunk-UHFWF6ZU.js → chunk-2FPS5H2D.js} +2 -2
  183. package/dist/{chunk-NAWXARTY.js → chunk-2KO2G3RI.js} +72 -6
  184. package/dist/chunk-2KO2G3RI.js.map +1 -0
  185. package/dist/{chunk-5POTDNQT.js → chunk-2NC7NZCE.js} +6 -6
  186. package/dist/{chunk-ZKYYZH6L.js → chunk-2QBYDGWO.js} +9 -9
  187. package/dist/{chunk-TWXIFWBD.js → chunk-34EU25RL.js} +2 -2
  188. package/dist/{chunk-LQKKSUCR.js → chunk-35BC2FU2.js} +19 -19
  189. package/dist/{chunk-PTGRFAMH.js → chunk-3ABPIUCK.js} +2 -2
  190. package/dist/{chunk-S4SC5SSV.js → chunk-3GU7AWG7.js} +18 -18
  191. package/dist/{chunk-722UO6YQ.js → chunk-3PEXVG4D.js} +2 -2
  192. package/dist/{chunk-OQAAI33Y.js → chunk-3RMKPHBL.js} +3 -3
  193. package/dist/{chunk-6JKZILLF.js → chunk-3RQUWFZT.js} +67 -67
  194. package/dist/{chunk-6JKZILLF.js.map → chunk-3RQUWFZT.js.map} +1 -1
  195. package/dist/{chunk-GCGTYXJJ.js → chunk-3STBLX4O.js} +9 -9
  196. package/dist/{chunk-YXIW7H4N.js → chunk-3X5FKDYQ.js} +28 -28
  197. package/dist/{chunk-KTRKZRID.js → chunk-4GLLWX33.js} +11 -11
  198. package/dist/{chunk-ROQOVH4N.js → chunk-4HEXNAFI.js} +20 -20
  199. package/dist/chunk-4HEXNAFI.js.map +1 -0
  200. package/dist/{chunk-SD2K5ZN5.js → chunk-4LPA25NQ.js} +4 -4
  201. package/dist/{chunk-DKCX643S.js → chunk-4RMN4E2Y.js} +13 -13
  202. package/dist/{chunk-E5FCEDMU.js → chunk-4SAGYEVB.js} +2 -2
  203. package/dist/{chunk-HTT3FB7T.js → chunk-4VK2R5QC.js} +3 -3
  204. package/dist/{chunk-CKG2EG62.js → chunk-4XQC7VLT.js} +14 -14
  205. package/dist/{chunk-IVOA3DXA.js → chunk-4YXAQMTD.js} +12 -12
  206. package/dist/{chunk-HOJGAJAB.js → chunk-52WK2GGK.js} +8 -8
  207. package/dist/{chunk-NYZQ7LO7.js → chunk-552UYIQ7.js} +20 -20
  208. package/dist/{chunk-LEXPBQ56.js → chunk-5DSKMG2I.js} +4 -4
  209. package/dist/{chunk-WNG757ID.js → chunk-5FA455GR.js} +4 -4
  210. package/dist/{chunk-MNWQAYY3.js → chunk-5FEN3KYH.js} +11 -11
  211. package/dist/{chunk-OSVHU2WU.js → chunk-5JHRMUAZ.js} +12 -12
  212. package/dist/{chunk-PM3OSANE.js → chunk-5MJHH72T.js} +14 -3
  213. package/dist/chunk-5MJHH72T.js.map +1 -0
  214. package/dist/{chunk-RKB2Z457.js → chunk-5VGJXWQ2.js} +2 -2
  215. package/dist/{chunk-GFUUFM2O.js → chunk-5W6ZDKRR.js} +6 -6
  216. package/dist/{chunk-NDETTZQA.js → chunk-5W7KJ5NQ.js} +37 -37
  217. package/dist/{chunk-Q35YZVDZ.js → chunk-5Y2FPLZE.js} +9 -9
  218. package/dist/{chunk-6W3LF3DB.js → chunk-5YFY4SFC.js} +2 -12
  219. package/dist/chunk-5YFY4SFC.js.map +1 -0
  220. package/dist/{chunk-F3NERYBQ.js → chunk-62VER7O4.js} +6 -6
  221. package/dist/{chunk-FBMU3VK5.js → chunk-6DCEDIF6.js} +2 -2
  222. package/dist/{chunk-WUHB422G.js → chunk-73WI7FL2.js} +18 -18
  223. package/dist/chunk-756MKA2J.js +45 -0
  224. package/dist/chunk-756MKA2J.js.map +1 -0
  225. package/dist/{chunk-QECZVL7S.js → chunk-7FJMRJDG.js} +2 -2
  226. package/dist/{chunk-7KGKDWWR.js → chunk-7HFLYNWN.js} +2 -2
  227. package/dist/{chunk-XVM566II.js → chunk-7KIENXRE.js} +2 -2
  228. package/dist/{chunk-CBY5CXBD.js → chunk-7NPCEBZE.js} +5 -5
  229. package/dist/{chunk-46VBQG2D.js → chunk-7P4AQMGA.js} +13 -13
  230. package/dist/{chunk-CKZW7A5S.js → chunk-7TCT7KPQ.js} +742 -644
  231. package/dist/chunk-7TCT7KPQ.js.map +1 -0
  232. package/dist/{chunk-O77Q4NG2.js → chunk-7XO7YKPC.js} +283 -1038
  233. package/dist/chunk-7XO7YKPC.js.map +1 -0
  234. package/dist/{chunk-S7PVL7XH.js → chunk-A4BD4ZVB.js} +4 -4
  235. package/dist/{chunk-VSQHDBHU.js → chunk-ACL2V2KE.js} +68 -35
  236. package/dist/chunk-ACL2V2KE.js.map +1 -0
  237. package/dist/{chunk-73SOCVLS.js → chunk-AIEXYO2X.js} +3 -3
  238. package/dist/{chunk-U7TC2XJQ.js → chunk-AJPW3SV4.js} +3 -3
  239. package/dist/{chunk-HRJQAFKR.js → chunk-AX6YJA5U.js} +2 -2
  240. package/dist/{chunk-P5WABK2H.js → chunk-BCM7C3MJ.js} +9 -9
  241. package/dist/{chunk-DT7BORXG.js → chunk-BMJTNPWK.js} +2 -2
  242. package/dist/{chunk-HIHO2QE7.js → chunk-BT2MVGHT.js} +2 -2
  243. package/dist/{chunk-3XOISKZC.js → chunk-BXQYAAVE.js} +4 -4
  244. package/dist/{chunk-IBTXYLBW.js → chunk-CCFWY4GF.js} +2 -2
  245. package/dist/{chunk-ZOC3OP6F.js → chunk-CCR33J7L.js} +2 -2
  246. package/dist/{chunk-GTQ3SNEI.js → chunk-CD3MO3IC.js} +2 -2
  247. package/dist/{chunk-WSMYOLHG.js → chunk-CDEXRJB6.js} +5 -5
  248. package/dist/{chunk-3GLAPCVI.js → chunk-CFFNT2OY.js} +8 -8
  249. package/dist/{chunk-FUSFVUIJ.js → chunk-CMLJSF2F.js} +12 -12
  250. package/dist/{chunk-O4DYOSOL.js → chunk-CP7ZQHBW.js} +13 -13
  251. package/dist/{chunk-IOKSNX74.js → chunk-D5OWJZQR.js} +2 -2
  252. package/dist/{chunk-SQGXMHJO.js → chunk-DGLRZMXL.js} +3 -3
  253. package/dist/{chunk-GNEHAPKV.js → chunk-DJFTH2DI.js} +3 -3
  254. package/dist/{chunk-HQG4SLTE.js → chunk-DYJGYGPB.js} +2 -2
  255. package/dist/{chunk-4EAF3HSD.js → chunk-EJ7WARW7.js} +2 -2
  256. package/dist/{chunk-3AA6RNGE.js → chunk-ENS6E4RZ.js} +2 -2
  257. package/dist/{chunk-OOEO4MKY.js → chunk-EPWD4KRA.js} +2 -2
  258. package/dist/{chunk-V5RJAWRP.js → chunk-EQE3MNQN.js} +5 -5
  259. package/dist/{chunk-TSBE4KOQ.js → chunk-EWL6NDOO.js} +3 -3
  260. package/dist/{chunk-OO2T63BY.js → chunk-EYS4ZOF5.js} +2 -2
  261. package/dist/{chunk-IC7KNOBB.js → chunk-FDAV72IX.js} +7 -7
  262. package/dist/{chunk-AG7VGUIW.js → chunk-FFNPUSVO.js} +7 -7
  263. package/dist/{chunk-P5T36BA3.js → chunk-FRP64DEK.js} +2 -2
  264. package/dist/{chunk-KBF3SE7G.js → chunk-FSP334UU.js} +2 -2
  265. package/dist/{chunk-ZHFKMMOT.js → chunk-FTX5CNHA.js} +6 -6
  266. package/dist/{chunk-KYBALSWW.js → chunk-FWOBNL2A.js} +1 -1
  267. package/dist/{chunk-HJ5XWW62.js → chunk-FWYEZ3LE.js} +34 -34
  268. package/dist/{chunk-WSLPZ43N.js → chunk-G4HQUBO4.js} +12 -12
  269. package/dist/{chunk-CSHBR2IZ.js → chunk-GDLDBR6B.js} +2 -2
  270. package/dist/chunk-GGV4NSG3.js +792 -0
  271. package/dist/chunk-GGV4NSG3.js.map +1 -0
  272. package/dist/{chunk-G3S2F35T.js → chunk-GHHM6WN4.js} +3 -3
  273. package/dist/{chunk-OANSIX34.js → chunk-GRSODLVO.js} +4 -4
  274. package/dist/{chunk-DDIBZA4X.js → chunk-GT7JFQ4E.js} +405 -148
  275. package/dist/chunk-GT7JFQ4E.js.map +1 -0
  276. package/dist/{chunk-EU6XSQFM.js → chunk-GXW2I2M2.js} +2 -2
  277. package/dist/{chunk-4246UYVG.js → chunk-GZS37O3G.js} +1 -1
  278. package/dist/{chunk-XFNLU7EW.js → chunk-H5M33DAL.js} +15 -6
  279. package/dist/chunk-H5M33DAL.js.map +1 -0
  280. package/dist/{chunk-Y7WMW74G.js → chunk-HQWVDQXW.js} +7 -7
  281. package/dist/{chunk-YTZQV2DD.js → chunk-HU6JTNWF.js} +2 -2
  282. package/dist/{chunk-QRVNI5V6.js → chunk-I6KIQKU6.js} +3 -3
  283. package/dist/{chunk-Q262Y2YX.js → chunk-IBA5FMRE.js} +141 -137
  284. package/dist/chunk-IBA5FMRE.js.map +1 -0
  285. package/dist/{chunk-BNUPYHHZ.js → chunk-IDXTASGN.js} +4 -4
  286. package/dist/{chunk-KF3MF6FP.js → chunk-IECRGM6K.js} +3 -2
  287. package/dist/chunk-IECRGM6K.js.map +1 -0
  288. package/dist/chunk-IJYL5BZM.js +38 -0
  289. package/dist/chunk-IJYL5BZM.js.map +1 -0
  290. package/dist/{chunk-L6RXRRN3.js → chunk-ILDOW2IQ.js} +3 -3
  291. package/dist/{chunk-VUHPA3XQ.js → chunk-ITX2TB4K.js} +6 -6
  292. package/dist/{chunk-ETCB6SUJ.js → chunk-J22HD2PB.js} +6 -6
  293. package/dist/{chunk-U47YDYLQ.js → chunk-J5MEDX7C.js} +8 -8
  294. package/dist/{chunk-6VQTHC4W.js → chunk-J7FBBLHF.js} +36 -36
  295. package/dist/{chunk-5JZYPZ72.js → chunk-JFK7NTEA.js} +4 -4
  296. package/dist/chunk-JFK7NTEA.js.map +1 -0
  297. package/dist/{chunk-QZRDCFHI.js → chunk-JM4HQPAI.js} +5 -5
  298. package/dist/{chunk-PIVGX42P.js → chunk-JNY5MT3I.js} +2 -2
  299. package/dist/{chunk-XWWXIZFP.js → chunk-JO6R5EXF.js} +7 -7
  300. package/dist/{chunk-MM7OKOTE.js → chunk-JQCGPTZ6.js} +9 -9
  301. package/dist/chunk-JRSNCSZN.js +37 -0
  302. package/dist/chunk-JRSNCSZN.js.map +1 -0
  303. package/dist/{chunk-KNFDWNCH.js → chunk-JXT5QDJC.js} +5 -5
  304. package/dist/{chunk-OR37STQZ.js → chunk-KEXYBG7Q.js} +3 -3
  305. package/dist/{chunk-AZVANYMB.js → chunk-KUNFUSZ7.js} +2 -2
  306. package/dist/{chunk-DXZNDKQD.js → chunk-LEEJBZ5B.js} +2 -2
  307. package/dist/{chunk-STUCI6QA.js → chunk-LEKBNKLD.js} +1 -1
  308. package/dist/{chunk-STUCI6QA.js.map → chunk-LEKBNKLD.js.map} +1 -1
  309. package/dist/{chunk-C535KSTY.js → chunk-LF5CBAOS.js} +4 -4
  310. package/dist/{chunk-BJIZ7PL7.js → chunk-LHLK7FUA.js} +145 -29
  311. package/dist/chunk-LHLK7FUA.js.map +1 -0
  312. package/dist/{chunk-RIMKJBCD.js → chunk-LMPTC4CX.js} +2 -2
  313. package/dist/{chunk-3KVWXKD6.js → chunk-LQ47YL6E.js} +2 -2
  314. package/dist/{chunk-H5WGWAYX.js → chunk-LT4J7RHI.js} +13 -13
  315. package/dist/{chunk-DSGMYES6.js → chunk-MCTTONOW.js} +28 -28
  316. package/dist/{chunk-IGHELZI7.js → chunk-MIECLOQC.js} +9 -9
  317. package/dist/{chunk-FM4OUCC2.js → chunk-MOKYT3X3.js} +3 -3
  318. package/dist/{chunk-GZ64CASI.js → chunk-MVZYNZXE.js} +5 -4
  319. package/dist/chunk-MVZYNZXE.js.map +1 -0
  320. package/dist/{chunk-RKILMLA7.js → chunk-MXLKI7BI.js} +3 -3
  321. package/dist/{chunk-45WYYFP6.js → chunk-N3ZP4IDU.js} +2 -2
  322. package/dist/{chunk-XRRSFQEV.js → chunk-NAZZLAWX.js} +2 -2
  323. package/dist/{chunk-UWJ5P5CU.js → chunk-NEK4WB5P.js} +3 -3
  324. package/dist/{chunk-6L7U46Y2.js → chunk-NKNVIO66.js} +2 -2
  325. package/dist/{chunk-JKUICTLM.js → chunk-NLAFNMPK.js} +2 -2
  326. package/dist/{chunk-4LKNIGHB.js → chunk-O2SBHS2N.js} +2 -2
  327. package/dist/{chunk-D3RK3NGM.js → chunk-PCFK7HKD.js} +17 -17
  328. package/dist/{chunk-VVCDB2T7.js → chunk-PCJLH45G.js} +3 -3
  329. package/dist/{chunk-PZ24CYDO.js → chunk-PFAUGEV5.js} +2 -2
  330. package/dist/{chunk-HGMWMK5K.js → chunk-PO3BH3KQ.js} +2 -2
  331. package/dist/{chunk-B74GSYR6.js → chunk-PUTS4DYW.js} +2 -2
  332. package/dist/{chunk-JSIDLTTG.js → chunk-PZ2V2XIK.js} +2 -2
  333. package/dist/{chunk-TMEQPODK.js → chunk-PZ37VDB5.js} +2 -2
  334. package/dist/{chunk-QIYBOFUV.js → chunk-QFMLAT7L.js} +246 -237
  335. package/dist/chunk-QFMLAT7L.js.map +1 -0
  336. package/dist/{chunk-LVONK3YQ.js → chunk-QRKTESVE.js} +2 -2
  337. package/dist/{chunk-HT5WSUC7.js → chunk-QXEDIDBZ.js} +3 -3
  338. package/dist/{chunk-WURSS6MP.js → chunk-R66YMYJU.js} +2 -2
  339. package/dist/{chunk-HDHK3SXK.js → chunk-RFLYID6H.js} +5 -5
  340. package/dist/{chunk-V77JK73U.js → chunk-RIYZFKIM.js} +37 -35
  341. package/dist/chunk-RIYZFKIM.js.map +1 -0
  342. package/dist/{chunk-VMFID36H.js → chunk-RQNZDTKT.js} +19 -19
  343. package/dist/{chunk-EHCUFCXM.js → chunk-RYSRFAHN.js} +32 -22
  344. package/dist/chunk-RYSRFAHN.js.map +1 -0
  345. package/dist/{chunk-I6VUUEXH.js → chunk-S2U4CDAC.js} +150 -150
  346. package/dist/chunk-S2U4CDAC.js.map +1 -0
  347. package/dist/chunk-S37GP7LX.js +204 -0
  348. package/dist/chunk-S37GP7LX.js.map +1 -0
  349. package/dist/{chunk-A2EWJQXX.js → chunk-SM5QX6UK.js} +4 -4
  350. package/dist/{chunk-FBE6AIIW.js → chunk-SOKNCW5U.js} +2 -2
  351. package/dist/{chunk-Q4NM77K7.js → chunk-SSOO4GWN.js} +193 -194
  352. package/dist/chunk-SSOO4GWN.js.map +1 -0
  353. package/dist/{chunk-PFKTGZKE.js → chunk-SY2AAZNB.js} +2 -2
  354. package/dist/{chunk-DFZMKCVP.js → chunk-TIQPKOFW.js} +4 -4
  355. package/dist/{chunk-HPPKLBTJ.js → chunk-TJQDL3JH.js} +2 -2
  356. package/dist/chunk-TL7BOFFL.js +89 -0
  357. package/dist/chunk-TL7BOFFL.js.map +1 -0
  358. package/dist/{chunk-FD4Q5KFL.js → chunk-TLL22FFO.js} +2 -2
  359. package/dist/{chunk-QM5H4FPT.js → chunk-TV6BWONY.js} +3 -3
  360. package/dist/{chunk-EDFJBX3V.js → chunk-U6MPB3K6.js} +9 -9
  361. package/dist/{chunk-TZD3U2S5.js → chunk-ULJAOMJA.js} +4 -4
  362. package/dist/chunk-ULYQEFNH.js +529 -0
  363. package/dist/chunk-ULYQEFNH.js.map +1 -0
  364. package/dist/{chunk-H5EVWF6L.js → chunk-UNNJUJVD.js} +2 -2
  365. package/dist/{chunk-324X6T6G.js → chunk-UP7I3W6O.js} +57 -55
  366. package/dist/chunk-UP7I3W6O.js.map +1 -0
  367. package/dist/{chunk-VU2EWALC.js → chunk-UUGR3X5I.js} +19 -12
  368. package/dist/chunk-UUGR3X5I.js.map +1 -0
  369. package/dist/{chunk-Z6DKXQG7.js → chunk-UXXFMF4X.js} +2 -2
  370. package/dist/{chunk-OBQVTCTW.js → chunk-UYNCMZX5.js} +4 -4
  371. package/dist/{chunk-RGPYMHKI.js → chunk-V3K4RQO7.js} +9 -3
  372. package/dist/chunk-V3K4RQO7.js.map +1 -0
  373. package/dist/{chunk-KZHW27BV.js → chunk-V4QZ7UBK.js} +2 -2
  374. package/dist/{chunk-NEVRLD77.js → chunk-VH5EGTH2.js} +3 -3
  375. package/dist/{chunk-MYNUBDU7.js → chunk-VYKW6TB2.js} +1 -1
  376. package/dist/chunk-VYKW6TB2.js.map +1 -0
  377. package/dist/{chunk-QEJTQTF5.js → chunk-W6T5HR3Z.js} +3 -3
  378. package/dist/{chunk-H6WWEKEV.js → chunk-WCMG4HYI.js} +10 -10
  379. package/dist/{chunk-GZLLDA6P.js → chunk-WEFN327U.js} +2 -2
  380. package/dist/{chunk-VW3BBTMA.js → chunk-WKHUZIOW.js} +1 -1
  381. package/dist/{chunk-ANHUMDJX.js → chunk-WNDTLK44.js} +2 -2
  382. package/dist/{chunk-2DS4UOYQ.js → chunk-WSZQNTVN.js} +2 -2
  383. package/dist/{chunk-Z2DAWUO3.js → chunk-XMNUZUUA.js} +6 -6
  384. package/dist/{chunk-GAIM5RNE.js → chunk-XN7NSPE6.js} +3 -3
  385. package/dist/chunk-XV6ZYRHK.js +59 -0
  386. package/dist/chunk-XV6ZYRHK.js.map +1 -0
  387. package/dist/{chunk-FLGUVRR7.js → chunk-Y5BSA3I7.js} +5 -5
  388. package/dist/{chunk-WRLWLGEF.js → chunk-Y5E3XQ2S.js} +25 -2
  389. package/dist/{chunk-WRLWLGEF.js.map → chunk-Y5E3XQ2S.js.map} +1 -1
  390. package/dist/{chunk-QILLL4JE.js → chunk-YEROLKOA.js} +16 -16
  391. package/dist/{chunk-NDF3SH3X.js → chunk-YJPKDRI2.js} +15 -15
  392. package/dist/{chunk-TQGJN5UZ.js → chunk-YV56F4UP.js} +318 -700
  393. package/dist/chunk-YV56F4UP.js.map +1 -0
  394. package/dist/{chunk-VAIESMPY.js → chunk-YVBHGMKC.js} +4 -4
  395. package/dist/{chunk-AD22P5X3.js → chunk-YXA2EKV3.js} +3 -3
  396. package/dist/{chunk-FDNJVZRE.js → chunk-YYCOSTUU.js} +17 -17
  397. package/dist/{chunk-NLMTNEWW.js → chunk-Z6E6TUAE.js} +2 -2
  398. package/dist/{chunk-BJW7G6EF.js → chunk-Z7IGO5EA.js} +3 -3
  399. package/dist/{chunk-N7JKT4ZU.js → chunk-ZEIFJ6PX.js} +7 -7
  400. package/dist/{chunk-Q4OHNGGB.js → chunk-ZS2UQ3DV.js} +68 -11
  401. package/dist/chunk-ZS2UQ3DV.js.map +1 -0
  402. package/dist/{chunk-VRGOOVDB.js → chunk-ZVVT72MT.js} +2 -2
  403. package/dist/components/browser-viewer.d.ts +1 -1
  404. package/dist/composer.js +14 -14
  405. package/dist/{computer-viewer-KEDVLD42.js → computer-viewer-25AJIDYA.js} +9 -9
  406. package/dist/connect.js +11 -11
  407. package/dist/desktop.js +2 -2
  408. package/dist/editor.js +2 -2
  409. package/dist/{embedded-new-voice-5PYRDZ6T.js → embedded-new-voice-RZZEJT6M.js} +8 -8
  410. package/dist/{embedded-voice-PABC5NBD.js → embedded-voice-6OKSSPLW.js} +8 -8
  411. package/dist/{fleet-decision-row-QNSTP3VX.js → fleet-decision-row-NN2HXDX3.js} +2 -2
  412. package/dist/hooks/internal.d.ts +38 -0
  413. package/dist/hooks/use-client-config-flags.d.ts +12 -0
  414. package/dist/hooks/use-workspace-sessions.d.ts +10 -1
  415. package/dist/index.js +233 -227
  416. package/dist/interaction.js +11 -9
  417. package/dist/interaction.js.map +1 -1
  418. package/dist/{latest-question-5LIRVG4G.js → latest-question-2PFWQSSG.js} +4 -3
  419. package/dist/{latest-question-5LIRVG4G.js.map → latest-question-2PFWQSSG.js.map} +1 -1
  420. package/dist/machines.js +5 -5
  421. package/dist/messages/en.d.ts +3 -3
  422. package/dist/messages.js +1 -1
  423. package/dist/{model-policy-picker-menu-CURJ247L.js → model-policy-picker-menu-VVFGGAI6.js} +6 -6
  424. package/dist/model-policy-picker-menu-VVFGGAI6.js.map +1 -0
  425. package/dist/native-previews.js +3 -3
  426. package/dist/{platform-activity-row-BMXXNZKX.js → platform-activity-row-ENQVIFTL.js} +2 -2
  427. package/dist/{queue-surface-implementation-2X5AXB6I.js → queue-surface-implementation-4SHOQPQQ.js} +10 -8
  428. package/dist/{queue-surface-implementation-2X5AXB6I.js.map → queue-surface-implementation-4SHOQPQQ.js.map} +1 -1
  429. package/dist/realtime.js +7 -7
  430. package/dist/{sandbox-files-4FBG3GS2.js → sandbox-files-CCOTGXXA.js} +11 -11
  431. package/dist/sandbox-files-CCOTGXXA.js.map +1 -0
  432. package/dist/session-app.js +277 -271
  433. package/dist/session-list-model.d.ts +1 -0
  434. package/dist/session-list-model.js +8 -2
  435. package/dist/{session-realtime-2XIB254N.js → session-realtime-JNKDSGH7.js} +3 -3
  436. package/dist/session-realtime-JNKDSGH7.js.map +1 -0
  437. package/dist/session-realtime.js +2 -2
  438. package/dist/session-ui.js +77 -72
  439. package/dist/session.js +27 -25
  440. package/dist/sites.js +2 -2
  441. package/dist/terminal.js +2 -2
  442. package/dist/this-computer.js +3 -3
  443. package/dist/timeline/invoked-tool.d.ts +5 -0
  444. package/dist/timeline/tool-display-name.d.ts +2 -2
  445. package/dist/timeline/tool-icon.d.ts +14 -0
  446. package/dist/timeline/tool-presentation.d.ts +8 -3
  447. package/dist/timeline/types.d.ts +2 -0
  448. package/dist/{timeline-annotation-markers-X4K2IEOO.js → timeline-annotation-markers-KHNYNY2J.js} +5 -5
  449. package/dist/{timeline-annotation-selection-MEHBW676.js → timeline-annotation-selection-AXEDJHBP.js} +7 -7
  450. package/dist/{timeline-annotations-dialog-U2FPQ3UY.js → timeline-annotations-dialog-AV4ZBXRC.js} +9 -9
  451. package/dist/timeline-model.js +28 -26
  452. package/dist/ui/access-list.js +20 -20
  453. package/dist/ui/choice-cards.js +2 -2
  454. package/dist/ui/detail-page.js +2 -2
  455. package/dist/ui/detail-sheet.js +2 -2
  456. package/dist/ui/diff-view.js +2 -2
  457. package/dist/ui/disclosure.js +4 -4
  458. package/dist/ui/flush-form-page.js +3 -3
  459. package/dist/ui/form-dialog.js +2 -2
  460. package/dist/ui/list-row.js +5 -5
  461. package/dist/ui/revision-history.js +11 -11
  462. package/dist/ui/role-select.js +6 -6
  463. package/dist/ui/settings-nav.js +3 -3
  464. package/dist/usage.js +3 -3
  465. package/dist/workbench.js +11 -11
  466. package/package.json +4 -4
  467. package/src/app/app-state.tsx +3 -1
  468. package/src/app/components/capabilities/session-capability-card.tsx +14 -1
  469. package/src/app/components/capabilities/session-chrome-card.dom-fixture.tsx +377 -0
  470. package/src/app/components/capabilities/session-chrome-card.test.tsx +18 -0
  471. package/src/app/components/capabilities/session-chrome-card.tsx +243 -0
  472. package/src/app/components/capabilities/session-machine-card.dom-fixture.tsx +2 -0
  473. package/src/app/components/capabilities/session-machine-card.tsx +74 -16
  474. package/src/app/components/rail/session-list.tsx +254 -44
  475. package/src/app/components/rail/session-row-content.tsx +24 -2
  476. package/src/app/components/rail/session-shell.tsx +14 -9
  477. package/src/app/components/rail/site-session-group-heading.tsx +59 -20
  478. package/src/app/components/session/session-tenancy-control.tsx +18 -0
  479. package/src/app/components/session/site-origin-link.test.tsx +73 -0
  480. package/src/app/components/session/site-origin-link.tsx +4 -2
  481. package/src/app/embed/memory-navigation.tsx +1 -0
  482. package/src/app/lib/actions/held-modifier.test.ts +101 -0
  483. package/src/app/lib/actions/held-modifier.ts +108 -0
  484. package/src/app/lib/console-site.tsx +38 -0
  485. package/src/app/lib/navigation.tsx +4 -0
  486. package/src/app/lib/routes.tsx +42 -0
  487. package/src/app/lib/session-failure-toasts.ts +26 -0
  488. package/src/app/lib/session-ui-features.tsx +18 -4
  489. package/src/app/lib/sessions-group.tsx +219 -30
  490. package/src/app/lib/site-opened.tsx +48 -0
  491. package/src/app/lib/site-session-groups.test.ts +173 -6
  492. package/src/app/lib/site-view-routes.test.ts +55 -0
  493. package/src/app/lib/use-session-list-hint-refresh.tsx +44 -4
  494. package/src/app/routes/artifacts.tsx +2 -29
  495. package/src/app/routes/session-transient-failures.test.tsx +343 -0
  496. package/src/app/routes/session-unavailable.tsx +74 -3
  497. package/src/app/routes/session.tsx +4 -13
  498. package/src/app/routes/sessions-index.tsx +13 -9
  499. package/src/app/routes/site-view.test.tsx +476 -0
  500. package/src/app/routes/site-view.tsx +583 -0
  501. package/src/components/browser-viewer.tsx +16 -2
  502. package/src/hooks/internal.ts +129 -6
  503. package/src/hooks/use-client-config-flags.ts +8 -0
  504. package/src/hooks/use-session-events.ts +83 -9
  505. package/src/hooks/use-workspace-sessions.ts +21 -1
  506. package/src/messages/en.ts +3 -3
  507. package/src/session-list-model.ts +4 -0
  508. package/src/timeline/activity-rail.tsx +3 -2
  509. package/src/timeline/invoked-tool.ts +14 -4
  510. package/src/timeline/projection.ts +15 -8
  511. package/src/timeline/rolling-activity.tsx +6 -2
  512. package/src/timeline/tool-display-name.ts +2 -2
  513. package/src/timeline/tool-icon.tsx +165 -0
  514. package/src/timeline/tool-presentation.ts +207 -48
  515. package/src/timeline/tool-renderers.tsx +1 -70
  516. package/src/timeline/types.ts +2 -0
  517. package/styles/compiled.css +38 -0
  518. package/dist/chunk-22ZBT6CN.js +0 -50
  519. package/dist/chunk-22ZBT6CN.js.map +0 -1
  520. package/dist/chunk-324X6T6G.js.map +0 -1
  521. package/dist/chunk-5JZYPZ72.js.map +0 -1
  522. package/dist/chunk-6W3LF3DB.js.map +0 -1
  523. package/dist/chunk-BJIZ7PL7.js.map +0 -1
  524. package/dist/chunk-CKZW7A5S.js.map +0 -1
  525. package/dist/chunk-DDIBZA4X.js.map +0 -1
  526. package/dist/chunk-EHCUFCXM.js.map +0 -1
  527. package/dist/chunk-GZ64CASI.js.map +0 -1
  528. package/dist/chunk-I6VUUEXH.js.map +0 -1
  529. package/dist/chunk-KF3MF6FP.js.map +0 -1
  530. package/dist/chunk-MYNUBDU7.js.map +0 -1
  531. package/dist/chunk-NAWXARTY.js.map +0 -1
  532. package/dist/chunk-O77Q4NG2.js.map +0 -1
  533. package/dist/chunk-PM3OSANE.js.map +0 -1
  534. package/dist/chunk-Q262Y2YX.js.map +0 -1
  535. package/dist/chunk-Q4NM77K7.js.map +0 -1
  536. package/dist/chunk-Q4OHNGGB.js.map +0 -1
  537. package/dist/chunk-QIYBOFUV.js.map +0 -1
  538. package/dist/chunk-R25ZKOZR.js +0 -24
  539. package/dist/chunk-R25ZKOZR.js.map +0 -1
  540. package/dist/chunk-RGPYMHKI.js.map +0 -1
  541. package/dist/chunk-ROQOVH4N.js.map +0 -1
  542. package/dist/chunk-TQGJN5UZ.js.map +0 -1
  543. package/dist/chunk-V77JK73U.js.map +0 -1
  544. package/dist/chunk-VSQHDBHU.js.map +0 -1
  545. package/dist/chunk-VU2EWALC.js.map +0 -1
  546. package/dist/chunk-XFNLU7EW.js.map +0 -1
  547. package/dist/chunk-Z5WMLJKI.js.map +0 -1
  548. /package/dist/{browser-viewer-RYYQSRTC.js.map → app/components/capabilities/session-chrome-card.js.map} +0 -0
  549. /package/dist/{chat-interactive-block-ABCRKXJ4.js.map → app/lib/console-site.js.map} +0 -0
  550. /package/dist/{computer-viewer-KEDVLD42.js.map → app/lib/site-opened.js.map} +0 -0
  551. /package/dist/{embedded-new-voice-5PYRDZ6T.js.map → browser-viewer-QMCNV4RI.js.map} +0 -0
  552. /package/dist/{embedded-voice-PABC5NBD.js.map → chat-interactive-block-PMIAUXSO.js.map} +0 -0
  553. /package/dist/{chunk-GIZGNFIX.js.map → chunk-22FFOHPT.js.map} +0 -0
  554. /package/dist/{chunk-UHFWF6ZU.js.map → chunk-2FPS5H2D.js.map} +0 -0
  555. /package/dist/{chunk-5POTDNQT.js.map → chunk-2NC7NZCE.js.map} +0 -0
  556. /package/dist/{chunk-ZKYYZH6L.js.map → chunk-2QBYDGWO.js.map} +0 -0
  557. /package/dist/{chunk-TWXIFWBD.js.map → chunk-34EU25RL.js.map} +0 -0
  558. /package/dist/{chunk-LQKKSUCR.js.map → chunk-35BC2FU2.js.map} +0 -0
  559. /package/dist/{chunk-PTGRFAMH.js.map → chunk-3ABPIUCK.js.map} +0 -0
  560. /package/dist/{chunk-S4SC5SSV.js.map → chunk-3GU7AWG7.js.map} +0 -0
  561. /package/dist/{chunk-722UO6YQ.js.map → chunk-3PEXVG4D.js.map} +0 -0
  562. /package/dist/{chunk-OQAAI33Y.js.map → chunk-3RMKPHBL.js.map} +0 -0
  563. /package/dist/{chunk-GCGTYXJJ.js.map → chunk-3STBLX4O.js.map} +0 -0
  564. /package/dist/{chunk-YXIW7H4N.js.map → chunk-3X5FKDYQ.js.map} +0 -0
  565. /package/dist/{chunk-KTRKZRID.js.map → chunk-4GLLWX33.js.map} +0 -0
  566. /package/dist/{chunk-SD2K5ZN5.js.map → chunk-4LPA25NQ.js.map} +0 -0
  567. /package/dist/{chunk-DKCX643S.js.map → chunk-4RMN4E2Y.js.map} +0 -0
  568. /package/dist/{chunk-E5FCEDMU.js.map → chunk-4SAGYEVB.js.map} +0 -0
  569. /package/dist/{chunk-HTT3FB7T.js.map → chunk-4VK2R5QC.js.map} +0 -0
  570. /package/dist/{chunk-CKG2EG62.js.map → chunk-4XQC7VLT.js.map} +0 -0
  571. /package/dist/{chunk-IVOA3DXA.js.map → chunk-4YXAQMTD.js.map} +0 -0
  572. /package/dist/{chunk-HOJGAJAB.js.map → chunk-52WK2GGK.js.map} +0 -0
  573. /package/dist/{chunk-NYZQ7LO7.js.map → chunk-552UYIQ7.js.map} +0 -0
  574. /package/dist/{chunk-LEXPBQ56.js.map → chunk-5DSKMG2I.js.map} +0 -0
  575. /package/dist/{chunk-WNG757ID.js.map → chunk-5FA455GR.js.map} +0 -0
  576. /package/dist/{chunk-MNWQAYY3.js.map → chunk-5FEN3KYH.js.map} +0 -0
  577. /package/dist/{chunk-OSVHU2WU.js.map → chunk-5JHRMUAZ.js.map} +0 -0
  578. /package/dist/{chunk-RKB2Z457.js.map → chunk-5VGJXWQ2.js.map} +0 -0
  579. /package/dist/{chunk-GFUUFM2O.js.map → chunk-5W6ZDKRR.js.map} +0 -0
  580. /package/dist/{chunk-NDETTZQA.js.map → chunk-5W7KJ5NQ.js.map} +0 -0
  581. /package/dist/{chunk-Q35YZVDZ.js.map → chunk-5Y2FPLZE.js.map} +0 -0
  582. /package/dist/{chunk-F3NERYBQ.js.map → chunk-62VER7O4.js.map} +0 -0
  583. /package/dist/{chunk-FBMU3VK5.js.map → chunk-6DCEDIF6.js.map} +0 -0
  584. /package/dist/{chunk-WUHB422G.js.map → chunk-73WI7FL2.js.map} +0 -0
  585. /package/dist/{chunk-QECZVL7S.js.map → chunk-7FJMRJDG.js.map} +0 -0
  586. /package/dist/{chunk-7KGKDWWR.js.map → chunk-7HFLYNWN.js.map} +0 -0
  587. /package/dist/{chunk-XVM566II.js.map → chunk-7KIENXRE.js.map} +0 -0
  588. /package/dist/{chunk-CBY5CXBD.js.map → chunk-7NPCEBZE.js.map} +0 -0
  589. /package/dist/{chunk-46VBQG2D.js.map → chunk-7P4AQMGA.js.map} +0 -0
  590. /package/dist/{chunk-S7PVL7XH.js.map → chunk-A4BD4ZVB.js.map} +0 -0
  591. /package/dist/{chunk-73SOCVLS.js.map → chunk-AIEXYO2X.js.map} +0 -0
  592. /package/dist/{chunk-U7TC2XJQ.js.map → chunk-AJPW3SV4.js.map} +0 -0
  593. /package/dist/{chunk-HRJQAFKR.js.map → chunk-AX6YJA5U.js.map} +0 -0
  594. /package/dist/{chunk-P5WABK2H.js.map → chunk-BCM7C3MJ.js.map} +0 -0
  595. /package/dist/{chunk-DT7BORXG.js.map → chunk-BMJTNPWK.js.map} +0 -0
  596. /package/dist/{chunk-HIHO2QE7.js.map → chunk-BT2MVGHT.js.map} +0 -0
  597. /package/dist/{chunk-3XOISKZC.js.map → chunk-BXQYAAVE.js.map} +0 -0
  598. /package/dist/{chunk-IBTXYLBW.js.map → chunk-CCFWY4GF.js.map} +0 -0
  599. /package/dist/{chunk-ZOC3OP6F.js.map → chunk-CCR33J7L.js.map} +0 -0
  600. /package/dist/{chunk-GTQ3SNEI.js.map → chunk-CD3MO3IC.js.map} +0 -0
  601. /package/dist/{chunk-WSMYOLHG.js.map → chunk-CDEXRJB6.js.map} +0 -0
  602. /package/dist/{chunk-3GLAPCVI.js.map → chunk-CFFNT2OY.js.map} +0 -0
  603. /package/dist/{chunk-FUSFVUIJ.js.map → chunk-CMLJSF2F.js.map} +0 -0
  604. /package/dist/{chunk-O4DYOSOL.js.map → chunk-CP7ZQHBW.js.map} +0 -0
  605. /package/dist/{chunk-IOKSNX74.js.map → chunk-D5OWJZQR.js.map} +0 -0
  606. /package/dist/{chunk-SQGXMHJO.js.map → chunk-DGLRZMXL.js.map} +0 -0
  607. /package/dist/{chunk-GNEHAPKV.js.map → chunk-DJFTH2DI.js.map} +0 -0
  608. /package/dist/{chunk-HQG4SLTE.js.map → chunk-DYJGYGPB.js.map} +0 -0
  609. /package/dist/{chunk-4EAF3HSD.js.map → chunk-EJ7WARW7.js.map} +0 -0
  610. /package/dist/{chunk-3AA6RNGE.js.map → chunk-ENS6E4RZ.js.map} +0 -0
  611. /package/dist/{chunk-OOEO4MKY.js.map → chunk-EPWD4KRA.js.map} +0 -0
  612. /package/dist/{chunk-V5RJAWRP.js.map → chunk-EQE3MNQN.js.map} +0 -0
  613. /package/dist/{chunk-TSBE4KOQ.js.map → chunk-EWL6NDOO.js.map} +0 -0
  614. /package/dist/{chunk-OO2T63BY.js.map → chunk-EYS4ZOF5.js.map} +0 -0
  615. /package/dist/{chunk-IC7KNOBB.js.map → chunk-FDAV72IX.js.map} +0 -0
  616. /package/dist/{chunk-AG7VGUIW.js.map → chunk-FFNPUSVO.js.map} +0 -0
  617. /package/dist/{chunk-P5T36BA3.js.map → chunk-FRP64DEK.js.map} +0 -0
  618. /package/dist/{chunk-KBF3SE7G.js.map → chunk-FSP334UU.js.map} +0 -0
  619. /package/dist/{chunk-ZHFKMMOT.js.map → chunk-FTX5CNHA.js.map} +0 -0
  620. /package/dist/{chunk-KYBALSWW.js.map → chunk-FWOBNL2A.js.map} +0 -0
  621. /package/dist/{chunk-HJ5XWW62.js.map → chunk-FWYEZ3LE.js.map} +0 -0
  622. /package/dist/{chunk-WSLPZ43N.js.map → chunk-G4HQUBO4.js.map} +0 -0
  623. /package/dist/{chunk-CSHBR2IZ.js.map → chunk-GDLDBR6B.js.map} +0 -0
  624. /package/dist/{chunk-G3S2F35T.js.map → chunk-GHHM6WN4.js.map} +0 -0
  625. /package/dist/{chunk-OANSIX34.js.map → chunk-GRSODLVO.js.map} +0 -0
  626. /package/dist/{chunk-EU6XSQFM.js.map → chunk-GXW2I2M2.js.map} +0 -0
  627. /package/dist/{chunk-4246UYVG.js.map → chunk-GZS37O3G.js.map} +0 -0
  628. /package/dist/{chunk-Y7WMW74G.js.map → chunk-HQWVDQXW.js.map} +0 -0
  629. /package/dist/{chunk-YTZQV2DD.js.map → chunk-HU6JTNWF.js.map} +0 -0
  630. /package/dist/{chunk-QRVNI5V6.js.map → chunk-I6KIQKU6.js.map} +0 -0
  631. /package/dist/{chunk-BNUPYHHZ.js.map → chunk-IDXTASGN.js.map} +0 -0
  632. /package/dist/{chunk-L6RXRRN3.js.map → chunk-ILDOW2IQ.js.map} +0 -0
  633. /package/dist/{chunk-VUHPA3XQ.js.map → chunk-ITX2TB4K.js.map} +0 -0
  634. /package/dist/{chunk-ETCB6SUJ.js.map → chunk-J22HD2PB.js.map} +0 -0
  635. /package/dist/{chunk-U47YDYLQ.js.map → chunk-J5MEDX7C.js.map} +0 -0
  636. /package/dist/{chunk-6VQTHC4W.js.map → chunk-J7FBBLHF.js.map} +0 -0
  637. /package/dist/{chunk-QZRDCFHI.js.map → chunk-JM4HQPAI.js.map} +0 -0
  638. /package/dist/{chunk-PIVGX42P.js.map → chunk-JNY5MT3I.js.map} +0 -0
  639. /package/dist/{chunk-XWWXIZFP.js.map → chunk-JO6R5EXF.js.map} +0 -0
  640. /package/dist/{chunk-MM7OKOTE.js.map → chunk-JQCGPTZ6.js.map} +0 -0
  641. /package/dist/{chunk-KNFDWNCH.js.map → chunk-JXT5QDJC.js.map} +0 -0
  642. /package/dist/{chunk-OR37STQZ.js.map → chunk-KEXYBG7Q.js.map} +0 -0
  643. /package/dist/{chunk-AZVANYMB.js.map → chunk-KUNFUSZ7.js.map} +0 -0
  644. /package/dist/{chunk-DXZNDKQD.js.map → chunk-LEEJBZ5B.js.map} +0 -0
  645. /package/dist/{chunk-C535KSTY.js.map → chunk-LF5CBAOS.js.map} +0 -0
  646. /package/dist/{chunk-RIMKJBCD.js.map → chunk-LMPTC4CX.js.map} +0 -0
  647. /package/dist/{chunk-3KVWXKD6.js.map → chunk-LQ47YL6E.js.map} +0 -0
  648. /package/dist/{chunk-H5WGWAYX.js.map → chunk-LT4J7RHI.js.map} +0 -0
  649. /package/dist/{chunk-DSGMYES6.js.map → chunk-MCTTONOW.js.map} +0 -0
  650. /package/dist/{chunk-IGHELZI7.js.map → chunk-MIECLOQC.js.map} +0 -0
  651. /package/dist/{chunk-FM4OUCC2.js.map → chunk-MOKYT3X3.js.map} +0 -0
  652. /package/dist/{chunk-RKILMLA7.js.map → chunk-MXLKI7BI.js.map} +0 -0
  653. /package/dist/{chunk-45WYYFP6.js.map → chunk-N3ZP4IDU.js.map} +0 -0
  654. /package/dist/{chunk-XRRSFQEV.js.map → chunk-NAZZLAWX.js.map} +0 -0
  655. /package/dist/{chunk-UWJ5P5CU.js.map → chunk-NEK4WB5P.js.map} +0 -0
  656. /package/dist/{chunk-6L7U46Y2.js.map → chunk-NKNVIO66.js.map} +0 -0
  657. /package/dist/{chunk-JKUICTLM.js.map → chunk-NLAFNMPK.js.map} +0 -0
  658. /package/dist/{chunk-4LKNIGHB.js.map → chunk-O2SBHS2N.js.map} +0 -0
  659. /package/dist/{chunk-D3RK3NGM.js.map → chunk-PCFK7HKD.js.map} +0 -0
  660. /package/dist/{chunk-VVCDB2T7.js.map → chunk-PCJLH45G.js.map} +0 -0
  661. /package/dist/{chunk-PZ24CYDO.js.map → chunk-PFAUGEV5.js.map} +0 -0
  662. /package/dist/{chunk-HGMWMK5K.js.map → chunk-PO3BH3KQ.js.map} +0 -0
  663. /package/dist/{chunk-B74GSYR6.js.map → chunk-PUTS4DYW.js.map} +0 -0
  664. /package/dist/{chunk-JSIDLTTG.js.map → chunk-PZ2V2XIK.js.map} +0 -0
  665. /package/dist/{chunk-TMEQPODK.js.map → chunk-PZ37VDB5.js.map} +0 -0
  666. /package/dist/{chunk-LVONK3YQ.js.map → chunk-QRKTESVE.js.map} +0 -0
  667. /package/dist/{chunk-HT5WSUC7.js.map → chunk-QXEDIDBZ.js.map} +0 -0
  668. /package/dist/{chunk-WURSS6MP.js.map → chunk-R66YMYJU.js.map} +0 -0
  669. /package/dist/{chunk-HDHK3SXK.js.map → chunk-RFLYID6H.js.map} +0 -0
  670. /package/dist/{chunk-VMFID36H.js.map → chunk-RQNZDTKT.js.map} +0 -0
  671. /package/dist/{chunk-A2EWJQXX.js.map → chunk-SM5QX6UK.js.map} +0 -0
  672. /package/dist/{chunk-FBE6AIIW.js.map → chunk-SOKNCW5U.js.map} +0 -0
  673. /package/dist/{chunk-PFKTGZKE.js.map → chunk-SY2AAZNB.js.map} +0 -0
  674. /package/dist/{chunk-DFZMKCVP.js.map → chunk-TIQPKOFW.js.map} +0 -0
  675. /package/dist/{chunk-HPPKLBTJ.js.map → chunk-TJQDL3JH.js.map} +0 -0
  676. /package/dist/{chunk-FD4Q5KFL.js.map → chunk-TLL22FFO.js.map} +0 -0
  677. /package/dist/{chunk-QM5H4FPT.js.map → chunk-TV6BWONY.js.map} +0 -0
  678. /package/dist/{chunk-EDFJBX3V.js.map → chunk-U6MPB3K6.js.map} +0 -0
  679. /package/dist/{chunk-TZD3U2S5.js.map → chunk-ULJAOMJA.js.map} +0 -0
  680. /package/dist/{chunk-H5EVWF6L.js.map → chunk-UNNJUJVD.js.map} +0 -0
  681. /package/dist/{chunk-Z6DKXQG7.js.map → chunk-UXXFMF4X.js.map} +0 -0
  682. /package/dist/{chunk-OBQVTCTW.js.map → chunk-UYNCMZX5.js.map} +0 -0
  683. /package/dist/{chunk-KZHW27BV.js.map → chunk-V4QZ7UBK.js.map} +0 -0
  684. /package/dist/{chunk-NEVRLD77.js.map → chunk-VH5EGTH2.js.map} +0 -0
  685. /package/dist/{chunk-QEJTQTF5.js.map → chunk-W6T5HR3Z.js.map} +0 -0
  686. /package/dist/{chunk-H6WWEKEV.js.map → chunk-WCMG4HYI.js.map} +0 -0
  687. /package/dist/{chunk-GZLLDA6P.js.map → chunk-WEFN327U.js.map} +0 -0
  688. /package/dist/{chunk-VW3BBTMA.js.map → chunk-WKHUZIOW.js.map} +0 -0
  689. /package/dist/{chunk-ANHUMDJX.js.map → chunk-WNDTLK44.js.map} +0 -0
  690. /package/dist/{chunk-2DS4UOYQ.js.map → chunk-WSZQNTVN.js.map} +0 -0
  691. /package/dist/{chunk-Z2DAWUO3.js.map → chunk-XMNUZUUA.js.map} +0 -0
  692. /package/dist/{chunk-GAIM5RNE.js.map → chunk-XN7NSPE6.js.map} +0 -0
  693. /package/dist/{chunk-FLGUVRR7.js.map → chunk-Y5BSA3I7.js.map} +0 -0
  694. /package/dist/{chunk-QILLL4JE.js.map → chunk-YEROLKOA.js.map} +0 -0
  695. /package/dist/{chunk-NDF3SH3X.js.map → chunk-YJPKDRI2.js.map} +0 -0
  696. /package/dist/{chunk-VAIESMPY.js.map → chunk-YVBHGMKC.js.map} +0 -0
  697. /package/dist/{chunk-AD22P5X3.js.map → chunk-YXA2EKV3.js.map} +0 -0
  698. /package/dist/{chunk-FDNJVZRE.js.map → chunk-YYCOSTUU.js.map} +0 -0
  699. /package/dist/{chunk-NLMTNEWW.js.map → chunk-Z6E6TUAE.js.map} +0 -0
  700. /package/dist/{chunk-BJW7G6EF.js.map → chunk-Z7IGO5EA.js.map} +0 -0
  701. /package/dist/{chunk-N7JKT4ZU.js.map → chunk-ZEIFJ6PX.js.map} +0 -0
  702. /package/dist/{chunk-VRGOOVDB.js.map → chunk-ZVVT72MT.js.map} +0 -0
  703. /package/dist/{model-policy-picker-menu-CURJ247L.js.map → computer-viewer-25AJIDYA.js.map} +0 -0
  704. /package/dist/{sandbox-files-4FBG3GS2.js.map → embedded-new-voice-RZZEJT6M.js.map} +0 -0
  705. /package/dist/{session-realtime-2XIB254N.js.map → embedded-voice-6OKSSPLW.js.map} +0 -0
  706. /package/dist/{fleet-decision-row-QNSTP3VX.js.map → fleet-decision-row-NN2HXDX3.js.map} +0 -0
  707. /package/dist/{platform-activity-row-BMXXNZKX.js.map → platform-activity-row-ENQVIFTL.js.map} +0 -0
  708. /package/dist/{timeline-annotation-markers-X4K2IEOO.js.map → timeline-annotation-markers-KHNYNY2J.js.map} +0 -0
  709. /package/dist/{timeline-annotation-selection-MEHBW676.js.map → timeline-annotation-selection-AXEDJHBP.js.map} +0 -0
  710. /package/dist/{timeline-annotations-dialog-U2FPQ3UY.js.map → timeline-annotations-dialog-AV4ZBXRC.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- import { observedSessionSequence, type SessionEvent } from "@opengeni/sdk";
1
+ import { isTransientRequestError, observedSessionSequence, type SessionEvent } from "@opengeni/sdk";
2
2
  import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
3
3
  import type { EmbeddedSessionEventClientLike } from "../client";
4
4
  import { normalizeError } from "../lib/error-message";
@@ -55,16 +55,88 @@ export type AsyncListState<T> = {
55
55
  refresh: () => Promise<void>;
56
56
  };
57
57
 
58
+ /**
59
+ * How a read hook rides out transient failures (a transport error or a
60
+ * 502/503/504, as during an API rolling deploy). While the failures last less
61
+ * than `quietWindowMs`, the hook keeps its loading state or its last data and
62
+ * retries with backoff; after that it surfaces the error but keeps retrying
63
+ * every `backgroundDelayMs`, and clears the error when a read succeeds.
64
+ * Definitive errors (401, 403, 404, other statuses) surface immediately.
65
+ */
66
+ export type TransientReadRetryOptions = {
67
+ quietWindowMs?: number | undefined;
68
+ initialDelayMs?: number | undefined;
69
+ maxDelayMs?: number | undefined;
70
+ backgroundDelayMs?: number | undefined;
71
+ };
72
+
73
+ export type TransientReadRetryPolicy = {
74
+ quietWindowMs: number;
75
+ initialDelayMs: number;
76
+ maxDelayMs: number;
77
+ backgroundDelayMs: number;
78
+ };
79
+
80
+ export const DEFAULT_TRANSIENT_READ_RETRY: Readonly<TransientReadRetryPolicy> = Object.freeze({
81
+ quietWindowMs: 20_000,
82
+ initialDelayMs: 1_000,
83
+ maxDelayMs: 4_000,
84
+ backgroundDelayMs: 15_000,
85
+ });
86
+
87
+ type TransientReadStreak = { since: number; attempts: number; surfaced: boolean };
88
+
89
+ function jittered(delayMs: number): number {
90
+ return Math.round(delayMs * (0.8 + Math.random() * 0.4));
91
+ }
92
+
93
+ /**
94
+ * The decision for one transient read failure: stay quiet and retry soon, or
95
+ * surface the error (once per streak) and keep retrying in the background.
96
+ */
97
+ export function transientReadRetryStep(
98
+ streak: TransientReadStreak,
99
+ now: number,
100
+ policy: TransientReadRetryPolicy,
101
+ ): { quiet: boolean; delayMs: number } {
102
+ streak.attempts += 1;
103
+ const quiet = now - streak.since < policy.quietWindowMs;
104
+ const delayMs = quiet
105
+ ? Math.min(policy.maxDelayMs, policy.initialDelayMs * 2 ** (streak.attempts - 1))
106
+ : policy.backgroundDelayMs;
107
+ return { quiet, delayMs: Math.max(0, jittered(delayMs)) };
108
+ }
109
+
58
110
  /**
59
111
  * Shared fetch + optional polling loop for the list/read hooks. Stale
60
112
  * responses (superseded by a newer load or an unmount) are dropped.
113
+ * Transient failures are retried quietly (see {@link TransientReadRetryOptions}).
61
114
  */
62
115
  export function usePolledValue<T>(
63
116
  load: (signal?: AbortSignal) => Promise<T>,
64
- options: { pollIntervalMs?: number | undefined; enabled?: boolean | undefined } = {},
117
+ options: {
118
+ pollIntervalMs?: number | undefined;
119
+ enabled?: boolean | undefined;
120
+ /** Quiet retry of transient failures; on by default, `false` surfaces them at once. */
121
+ transientRetry?: TransientReadRetryOptions | false | undefined;
122
+ } = {},
65
123
  ): AsyncListState<T> {
66
124
  const enabled = options.enabled ?? true;
67
125
  const pollIntervalMs = options.pollIntervalMs;
126
+ const transientRetryRef = useRef<TransientReadRetryPolicy | null>(null);
127
+ transientRetryRef.current =
128
+ options.transientRetry === false
129
+ ? null
130
+ : {
131
+ quietWindowMs:
132
+ options.transientRetry?.quietWindowMs ?? DEFAULT_TRANSIENT_READ_RETRY.quietWindowMs,
133
+ initialDelayMs:
134
+ options.transientRetry?.initialDelayMs ?? DEFAULT_TRANSIENT_READ_RETRY.initialDelayMs,
135
+ maxDelayMs: options.transientRetry?.maxDelayMs ?? DEFAULT_TRANSIENT_READ_RETRY.maxDelayMs,
136
+ backgroundDelayMs:
137
+ options.transientRetry?.backgroundDelayMs ??
138
+ DEFAULT_TRANSIENT_READ_RETRY.backgroundDelayMs,
139
+ };
68
140
  const pageLive = usePageLiveActivity();
69
141
  const [data, setData] = useState<T | null>(null);
70
142
  const [loading, setLoading] = useState(enabled);
@@ -77,6 +149,17 @@ export function usePolledValue<T>(
77
149
  const requestAbortRef = useRef<AbortController | null>(null);
78
150
  const inFlightRef = useRef<{ load: typeof load; promise: Promise<void> } | null>(null);
79
151
  const trailingRefreshRef = useRef<{ load: typeof load; promise: Promise<void> } | null>(null);
152
+ // The current run of consecutive transient failures, and its pending retry.
153
+ const transientStreakRef = useRef<TransientReadStreak | null>(null);
154
+ const transientRetryTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
155
+ // Retries run only while the query is enabled and the page is live.
156
+ const retryLiveRef = useRef(false);
157
+ const cancelTransientRetry = useCallback(() => {
158
+ if (transientRetryTimerRef.current !== null) {
159
+ clearTimeout(transientRetryTimerRef.current);
160
+ transientRetryTimerRef.current = null;
161
+ }
162
+ }, []);
80
163
  const [stateIdentity, setStateIdentity] = useState<{ load: typeof load }>(() => ({ load }));
81
164
 
82
165
  // A new loader identity means a new query (different session/workspace/...):
@@ -107,6 +190,8 @@ export function usePolledValue<T>(
107
190
  activeLoadRef.current === load &&
108
191
  !requestAbort.signal.aborted
109
192
  ) {
193
+ transientStreakRef.current = null;
194
+ cancelTransientRetry();
110
195
  setData(result);
111
196
  setError(null);
112
197
  setLoading(false);
@@ -117,8 +202,36 @@ export function usePolledValue<T>(
117
202
  activeLoadRef.current === load &&
118
203
  !requestAbort.signal.aborted
119
204
  ) {
120
- setError(normalizeError(cause));
121
- setLoading(false);
205
+ const policy = transientRetryRef.current;
206
+ if (policy && retryLiveRef.current && isTransientRequestError(cause)) {
207
+ // Keep the loading state or the last data on screen while a
208
+ // deploy or network blip passes; retry, and surface the error
209
+ // only once it outlasts the quiet window.
210
+ const now = Date.now();
211
+ const streak = (transientStreakRef.current ??= {
212
+ since: now,
213
+ attempts: 0,
214
+ surfaced: false,
215
+ });
216
+ const step = transientReadRetryStep(streak, now, policy);
217
+ if (!step.quiet) {
218
+ // One stable error per streak: background retries that fail
219
+ // the same way must not re-announce it.
220
+ if (!streak.surfaced) setError(normalizeError(cause));
221
+ streak.surfaced = true;
222
+ setLoading(false);
223
+ }
224
+ cancelTransientRetry();
225
+ transientRetryTimerRef.current = setTimeout(() => {
226
+ transientRetryTimerRef.current = null;
227
+ if (retryLiveRef.current) void run();
228
+ }, step.delayMs);
229
+ } else {
230
+ transientStreakRef.current = null;
231
+ cancelTransientRetry();
232
+ setError(normalizeError(cause));
233
+ setLoading(false);
234
+ }
122
235
  }
123
236
  } finally {
124
237
  if (requestAbortRef.current === requestAbort) requestAbortRef.current = null;
@@ -127,7 +240,7 @@ export function usePolledValue<T>(
127
240
  })();
128
241
  inFlightRef.current = { load, promise };
129
242
  return promise;
130
- }, [load]);
243
+ }, [cancelTransientRetry, load]);
131
244
 
132
245
  const refresh = useCallback((): Promise<void> => {
133
246
  const existing = inFlightRef.current;
@@ -146,7 +259,12 @@ export function usePolledValue<T>(
146
259
  }, [load, run]);
147
260
 
148
261
  useEffect(() => {
262
+ // Every (re)start begins a fresh streak; a pending retry belongs to the
263
+ // previous query or visibility period.
264
+ transientStreakRef.current = null;
265
+ cancelTransientRetry();
149
266
  if (!enabled || !pageLive) {
267
+ retryLiveRef.current = false;
150
268
  setLoading(false);
151
269
  generation.current += 1;
152
270
  requestAbortRef.current?.abort();
@@ -154,6 +272,7 @@ export function usePolledValue<T>(
154
272
  trailingRefreshRef.current = null;
155
273
  return;
156
274
  }
275
+ retryLiveRef.current = true;
157
276
  setLoading(true);
158
277
  let cancelled = false;
159
278
  let timer: ReturnType<typeof setTimeout> | null = null;
@@ -168,6 +287,8 @@ export function usePolledValue<T>(
168
287
  if (pollIntervalMs === undefined || pollIntervalMs <= 0) {
169
288
  return () => {
170
289
  cancelled = true;
290
+ retryLiveRef.current = false;
291
+ cancelTransientRetry();
171
292
  generation.current += 1;
172
293
  requestAbortRef.current?.abort();
173
294
  inFlightRef.current = null;
@@ -177,12 +298,14 @@ export function usePolledValue<T>(
177
298
  return () => {
178
299
  cancelled = true;
179
300
  if (timer !== null) clearTimeout(timer);
301
+ retryLiveRef.current = false;
302
+ cancelTransientRetry();
180
303
  generation.current += 1;
181
304
  requestAbortRef.current?.abort();
182
305
  inFlightRef.current = null;
183
306
  trailingRefreshRef.current = null;
184
307
  };
185
- }, [run, enabled, pageLive, pollIntervalMs]);
308
+ }, [run, enabled, pageLive, pollIntervalMs, cancelTransientRetry]);
186
309
 
187
310
  const identityMatches = stateIdentity.load === load;
188
311
  return {
@@ -14,6 +14,7 @@ export type ClientConfigFlagsSource = {
14
14
  archive?: boolean | undefined;
15
15
  voiceInput?: ClientVoiceInputConfig | undefined;
16
16
  realtimeVoice?: boolean | undefined;
17
+ browserExtension?: { name: string; installUrl: string } | undefined;
17
18
  }>;
18
19
  };
19
20
 
@@ -46,6 +47,11 @@ export type ClientConfigFlags = {
46
47
  * then or when their `realtimeVoice` prop is `true`.
47
48
  */
48
49
  realtimeVoiceOffered: boolean;
50
+ /**
51
+ * The Chrome extension the deployment offers for people's own Chrome, or
52
+ * null until the config loads or when the server doesn't say (Opengeni Browser).
53
+ */
54
+ browserExtension: { name: string; installUrl: string } | null;
49
55
  };
50
56
 
51
57
  const INITIAL_FLAGS: ClientConfigFlags = {
@@ -60,6 +66,7 @@ const INITIAL_FLAGS: ClientConfigFlags = {
60
66
  voiceInput: null,
61
67
  realtimeVoice: false,
62
68
  realtimeVoiceOffered: false,
69
+ browserExtension: null,
63
70
  };
64
71
 
65
72
  /** Deployment and session-proxy capabilities from the client config. */
@@ -89,6 +96,7 @@ export function useClientConfigFlags(
89
96
  voiceInput: config.voiceInput?.available === true ? config.voiceInput : null,
90
97
  realtimeVoice: config.realtimeVoice !== false,
91
98
  realtimeVoiceOffered: config.realtimeVoice === true,
99
+ browserExtension: config.browserExtension ?? null,
92
100
  });
93
101
  }
94
102
  },
@@ -2,6 +2,7 @@ import {
2
2
  isPresentedSessionToolName,
3
3
  isRetryableStreamError,
4
4
  isSessionModelResponsePhase,
5
+ isTransientRequestError,
5
6
  SESSION_EVENT_COMPAT_EXCLUDED_STEP_TYPES,
6
7
  SESSION_EVENT_CONTENT_STEP_TYPES,
7
8
  SESSION_EVENT_CONVERSATION_FILTER_VERSION,
@@ -22,7 +23,11 @@ import type { TimelineItem, TurnStepsItem } from "../timeline/types";
22
23
  import type { EmbeddedSessionClientLike } from "../client";
23
24
  import { normalizeError } from "../lib/error-message";
24
25
  import { joinSessionDetailRead, sessionDetailReadMark } from "../lib/session-detail-read";
25
- import { usePageLiveActivity } from "./internal";
26
+ import {
27
+ DEFAULT_TRANSIENT_READ_RETRY,
28
+ transientReadRetryStep,
29
+ usePageLiveActivity,
30
+ } from "./internal";
26
31
  import { subscribePageWake } from "./page-wake";
27
32
  import { deniesRetainedView, useRetainedSessionView } from "./session-view-cache";
28
33
  import { markTurnlessOutputGap } from "./turnless-output-gaps";
@@ -311,6 +316,13 @@ export function useSessionEvents(
311
316
  const [presentedPass, setPresentedPass] = useState(0);
312
317
  // A return to the live tip from history: catch up without replaying steps.
313
318
  const rejoinPendingRef = useRef(false);
319
+ // Consecutive transient failures to open this stream (a deploy or network
320
+ // blip): they restart it quietly before an error is shown.
321
+ const streamTransientStreakRef = useRef<{
322
+ since: number;
323
+ attempts: number;
324
+ surfaced: boolean;
325
+ } | null>(null);
314
326
 
315
327
  const commitStepStores = useCallback((next: TurnStepStores) => {
316
328
  stepStoresRef.current = next;
@@ -659,6 +671,7 @@ export function useSessionEvents(
659
671
  initialWindowLoadedRef.current = false;
660
672
  reconcileAfterPageResumeRef.current = false;
661
673
  rejoinPendingRef.current = false;
674
+ streamTransientStreakRef.current = null;
662
675
  stepGenerationRef.current += 1;
663
676
  stepStoresRef.current = EMPTY_STEP_STORES;
664
677
  setStepStores(EMPTY_STEP_STORES);
@@ -678,6 +691,9 @@ export function useSessionEvents(
678
691
  const generation = generationRef.current + 1;
679
692
  generationRef.current = generation;
680
693
  if (!sessionId || !streamEnabled) {
694
+ // A suspended stream starts a fresh transient streak when it resumes: a
695
+ // failure right after a wake must not count the hidden time.
696
+ streamTransientStreakRef.current = null;
681
697
  // A page that stayed hidden beyond the live-activity grace deliberately
682
698
  // closed its SSE connection. Replaying from the old cursor on return can
683
699
  // drip a large background backlog through React in many fast batches and
@@ -717,6 +733,15 @@ export function useSessionEvents(
717
733
  navigationIdentityRef.current.streamKey === streamKey &&
718
734
  navigationIdentityRef.current.enabled === enabled;
719
735
  streamAbortRef.current = controller;
736
+ // A quiet restart or reconciliation retry scheduled by this effect instance.
737
+ let transientRetryTimer: ReturnType<typeof setTimeout> | null = null;
738
+ const scheduleTransientRetry = (delayMs: number, retry: () => void) => {
739
+ if (transientRetryTimer !== null) clearTimeout(transientRetryTimer);
740
+ transientRetryTimer = setTimeout(() => {
741
+ transientRetryTimer = null;
742
+ if (isCurrent()) retry();
743
+ }, delayMs);
744
+ };
720
745
  // Batch yielded events into one React update per flush window so a long
721
746
  // replay (thousands of events) does not render per event. Project every
722
747
  // event before retaining it here and synchronously flush at independent
@@ -962,6 +987,7 @@ export function useSessionEvents(
962
987
  skippedStepsThroughRef.current =
963
988
  retained.events.length === 0 && window.newestSequence > 0 ? window.newestSequence : null;
964
989
  initialWindowLoadedRef.current = true;
990
+ streamTransientStreakRef.current = null;
965
991
  setInitialHistoryReady(true);
966
992
  setError(null);
967
993
  if (status !== undefined) {
@@ -984,6 +1010,31 @@ export function useSessionEvents(
984
1010
  liveThroughRef.current = Math.max(liveThroughRef.current, streamResumeSequenceRef.current);
985
1011
  };
986
1012
 
1013
+ // Reconciliation after an open re-reads the API contract and projections.
1014
+ // A transient failure (a reconnect during an API rollout often lands on a
1015
+ // pod that is still starting) retries quietly; the error is shown only
1016
+ // when it is definitive or outlasts the quiet window.
1017
+ const reconcileAfterOpen = (
1018
+ initialOpen: boolean,
1019
+ streak: { since: number; attempts: number; surfaced: boolean } | null = null,
1020
+ ) => {
1021
+ void Promise.resolve()
1022
+ .then(() => reconcileSession(sessionId, { initialOpen }))
1023
+ .catch((cause) => {
1024
+ if (!isCurrent()) return;
1025
+ if (isTransientRequestError(cause)) {
1026
+ const now = Date.now();
1027
+ const current = streak ?? { since: now, attempts: 0, surfaced: false };
1028
+ const step = transientReadRetryStep(current, now, DEFAULT_TRANSIENT_READ_RETRY);
1029
+ if (step.quiet) {
1030
+ scheduleTransientRetry(step.delayMs, () => reconcileAfterOpen(initialOpen, current));
1031
+ return;
1032
+ }
1033
+ }
1034
+ setError(normalizeError(cause));
1035
+ });
1036
+ };
1037
+
987
1038
  // One bounded rejoin attempt: it is abandoned once no read completes for
988
1039
  // REJOIN_STALL_TIMEOUT_MS, and a late result is fenced out of the view
989
1040
  // (reads without a signal can only be outwaited). A `strict` attempt
@@ -1179,16 +1230,13 @@ export function useSessionEvents(
1179
1230
  const initialOpen = openedStreamKeyRef.current !== streamKey;
1180
1231
  openedStreamKeyRef.current = streamKey;
1181
1232
  strictFailures = 0;
1233
+ // The outage is over: drop an error a long transient streak surfaced.
1234
+ if (streamTransientStreakRef.current?.surfaced) setError(null);
1235
+ streamTransientStreakRef.current = null;
1182
1236
  // Reconciliation repairs projections, but it must not block reading
1183
1237
  // the already-open SSE body. Otherwise live events accumulate in the
1184
1238
  // browser and appear as one delayed burst after every reconciler ends.
1185
- void Promise.resolve()
1186
- .then(() => reconcileSession(sessionId, { initialOpen }))
1187
- .catch((cause) => {
1188
- if (isCurrent()) {
1189
- setError(normalizeError(cause));
1190
- }
1191
- });
1239
+ reconcileAfterOpen(initialOpen);
1192
1240
  },
1193
1241
  onStateChange: (state) => {
1194
1242
  if (isCurrent()) {
@@ -1227,7 +1275,32 @@ export function useSessionEvents(
1227
1275
  } catch (cause) {
1228
1276
  if (isCurrent()) {
1229
1277
  flush();
1230
- setError(normalizeError(cause));
1278
+ let announce = true;
1279
+ if (isTransientRequestError(cause)) {
1280
+ // The tail read or the stream failed transiently (an API rollout
1281
+ // or a network blip). Restart quietly, keeping the loading state
1282
+ // or the current view, and show the error only if it outlasts the
1283
+ // quiet window. Afterwards keep retrying in the background.
1284
+ const now = Date.now();
1285
+ const streak = (streamTransientStreakRef.current ??= {
1286
+ since: now,
1287
+ attempts: 0,
1288
+ surfaced: false,
1289
+ });
1290
+ const step = transientReadRetryStep(streak, now, DEFAULT_TRANSIENT_READ_RETRY);
1291
+ scheduleTransientRetry(step.delayMs, () => setStreamEpoch((epoch) => epoch + 1));
1292
+ if (step.quiet) {
1293
+ setConnectionState("connecting");
1294
+ return;
1295
+ }
1296
+ // One stable error per streak: background retries that fail the
1297
+ // same way must not re-announce it.
1298
+ announce = !streak.surfaced;
1299
+ streak.surfaced = true;
1300
+ } else {
1301
+ streamTransientStreakRef.current = null;
1302
+ }
1303
+ if (announce) setError(normalizeError(cause));
1231
1304
  setConnectionState("error");
1232
1305
  // A failed first compact-tail request has no later success path in
1233
1306
  // this effect instance. End the loading gate so hosts can render the
@@ -1239,6 +1312,7 @@ export function useSessionEvents(
1239
1312
 
1240
1313
  return () => {
1241
1314
  controller.abort();
1315
+ if (transientRetryTimer !== null) clearTimeout(transientRetryTimer);
1242
1316
  if (generationRef.current === generation) {
1243
1317
  generationRef.current = generation + 1;
1244
1318
  }
@@ -1,4 +1,9 @@
1
- import type { Session, SessionListEntry, SessionListTotals } from "@opengeni/sdk";
1
+ import type {
2
+ Session,
3
+ SessionListEntry,
4
+ SessionListTotals,
5
+ SiteConversationGroup,
6
+ } from "@opengeni/sdk";
2
7
  import { useCallback, useEffect, useRef } from "react";
3
8
  import { useOpenGeni, type ClientOverride } from "../provider";
4
9
  import { usePolledValue } from "./internal";
@@ -23,6 +28,11 @@ export type UseWorkspaceSessionsOptions = ClientOverride & {
23
28
  archivedOnly?: boolean | undefined;
24
29
  sortBy?: "updatedAt" | "createdAt" | "name" | undefined;
25
30
  archiveStatus?: "active" | "archived" | "all" | undefined;
31
+ /**
32
+ * Conversations that run inside a Site: `include` lists them as rows,
33
+ * `group` (root pages) returns them as `siteGroups` instead.
34
+ */
35
+ siteConversations?: "include" | "group" | undefined;
26
36
  /** Refresh interval (ms) for fleet/manager views. Off by default. */
27
37
  pollIntervalMs?: number | undefined;
28
38
  enabled?: boolean | undefined;
@@ -41,6 +51,10 @@ export type UseWorkspaceSessionsResult<T extends Session | SessionListEntry = Se
41
51
  /** True when the server omitted older pins from its bounded pinned section. */
42
52
  pinnedTruncated: boolean;
43
53
  totals: SessionListTotals | null;
54
+ /** Complete Site rows for a `group` page; null when not requested or unsupported. */
55
+ siteGroups: SiteConversationGroup[] | null;
56
+ /** True when the server omitted Site rows beyond its bound. */
57
+ siteGroupsTruncated: boolean;
44
58
  nextCursor: string | null;
45
59
  loading: boolean;
46
60
  error: Error | null;
@@ -79,6 +93,7 @@ export function useWorkspaceSessions(
79
93
  const archivedOnly = options.archivedOnly;
80
94
  const sortBy = options.sortBy;
81
95
  const archiveStatus = options.archiveStatus;
96
+ const siteConversations = options.siteConversations;
82
97
  const enabled = options.enabled ?? true;
83
98
  const nextReadRevision = useRef(0);
84
99
  const nextReadGeneration = useRef(0);
@@ -99,6 +114,7 @@ export function useWorkspaceSessions(
99
114
  archivedOnly ? "archived" : "active",
100
115
  sortBy ?? "",
101
116
  archiveStatus ?? "",
117
+ siteConversations ?? "",
102
118
  ].join("\u0000");
103
119
  const previousQueryKey = useRef(queryKey);
104
120
  const queryKeyTransition = previousQueryKey.current !== queryKey;
@@ -122,6 +138,7 @@ export function useWorkspaceSessions(
122
138
  ...(archivedOnly ? { archivedOnly: true } : {}),
123
139
  ...(sortBy ? { sortBy } : {}),
124
140
  ...(archiveStatus ? { archiveStatus } : {}),
141
+ ...(siteConversations ? { siteConversations } : {}),
125
142
  signal,
126
143
  };
127
144
  const page =
@@ -162,6 +179,7 @@ export function useWorkspaceSessions(
162
179
  archivedOnly,
163
180
  sortBy,
164
181
  archiveStatus,
182
+ siteConversations,
165
183
  queryKey,
166
184
  ],
167
185
  );
@@ -183,6 +201,8 @@ export function useWorkspaceSessions(
183
201
  pinned,
184
202
  pinnedTruncated: page?.pinnedTruncated ?? false,
185
203
  totals: page?.totals ?? null,
204
+ siteGroups: page?.siteGroups ?? null,
205
+ siteGroupsTruncated: page?.siteGroupsTruncated === true,
186
206
  nextCursor: page?.nextCursor ?? null,
187
207
  // `usePolledValue` clears the old data and starts the new request in an
188
208
  // effect. During that query-key transition render, its old loading flag
@@ -383,7 +383,7 @@ export const englishMessages = {
383
383
  "browserViewer.inputResultUnknown": "Input result unknown",
384
384
  "browserViewer.inspectThePageBeforeContinuing": "Inspect the page before continuing.",
385
385
  "browserViewer.installTheOpengeniBrowserExtension":
386
- "Install the Opengeni Browser extension in the profile you want to use.",
386
+ "Install the {extensionName} extension in the profile you want to use.",
387
387
  "browserViewer.interactiveBrowserPage": "Interactive browser page",
388
388
  "browserViewer.itsPrivateStateIsSaved":
389
389
  "Its private state is saved. Opening it creates a fresh, isolated browser process.",
@@ -3992,8 +3992,8 @@ export const englishMessages = {
3992
3992
  "timeline.toolStep.shareFile.running": "Sharing a file",
3993
3993
  "timeline.toolStep.signIn.done": "Signed in",
3994
3994
  "timeline.toolStep.signIn.running": "Signing in",
3995
- "timeline.toolStep.startHelper.done": "Got help from another assistant",
3996
- "timeline.toolStep.startHelper.running": "Getting help from another assistant",
3995
+ "timeline.toolStep.startHelper.done": "Started a worker",
3996
+ "timeline.toolStep.startHelper.running": "Starting a worker",
3997
3997
  "timeline.toolStep.switchComputer.done": "Switched computers",
3998
3998
  "timeline.toolStep.switchComputer.running": "Switching computers",
3999
3999
  "timeline.toolStep.syncPosts.done": "Synced posts",
@@ -16,6 +16,10 @@ import { findPickerRow, type PickerModelRow } from "./model-policy";
16
16
  import { sessionDisplayStatus, type SessionDisplayStatus } from "./session-status-model";
17
17
  import { type OpenGeniText } from "./messages/runtime";
18
18
 
19
+ // Title ranking shared with the web command menu, so chat search on every
20
+ // surface orders matches the same way.
21
+ export { foldForSearch, LOOSE_MATCH_BELOW, rankLabel } from "./app/lib/actions/rank";
22
+
19
23
  /** A list row may be a compact page entry or a complete session response. */
20
24
  export type SessionListRow = Session | SessionListEntry;
21
25
 
@@ -12,7 +12,6 @@ import {
12
12
  BrainCircuitIcon,
13
13
  MessageSquareTextIcon,
14
14
  SendIcon,
15
- WrenchIcon,
16
15
  } from "lucide-react";
17
16
  import {
18
17
  Component,
@@ -43,6 +42,8 @@ import {
43
42
  } from "./shared";
44
43
  import { invokedToolCall } from "./invoked-tool";
45
44
  import { toolDisplayName } from "./tool-display-name";
45
+ import { ToolKindIcon } from "./tool-icon";
46
+ import { genericToolIconKind } from "./tool-presentation";
46
47
  import type { ActivityItem, AgentMessageItem, MemoryItem, ToolCallItem, WorkerItem } from "./types";
47
48
  import { useOpenGeniText, type OpenGeniText } from "../messages/runtime";
48
49
 
@@ -405,7 +406,7 @@ function ToolOutputExactRow({
405
406
  return (
406
407
  <div data-og-tool-output-loading="" aria-busy="true">
407
408
  <ActivityDisclosure
408
- icon={<WrenchIcon className="size-3.5" />}
409
+ icon={<ToolKindIcon kind={genericToolIconKind(item.name)} className="size-3.5" />}
409
410
  title={toolDisplayName(msg, item.name, item.display)}
410
411
  preview={msg("timeline.toolRenderers.loadingOutput")}
411
412
  expandable={false}
@@ -2,14 +2,24 @@ import { parseToolArgs } from "./parsers";
2
2
  import { mcpToolLeaf } from "./tool-display-name";
3
3
  import type { ToolCallItem } from "./types";
4
4
 
5
+ /** The tool a `tool_invoke` call ran, or null for any other call. */
6
+ export function invokedTool(
7
+ name: string,
8
+ rawArguments: unknown,
9
+ ): { name: string; arguments: unknown } | null {
10
+ if (mcpToolLeaf(name) !== "tool_invoke") return null;
11
+ const args = parseToolArgs(rawArguments);
12
+ if (typeof args.name !== "string" || !args.name.trim()) return null;
13
+ return { name: args.name, arguments: args.arguments ?? {} };
14
+ }
15
+
5
16
  /**
6
17
  * A `tool_invoke` call shown as the tool it ran, so the row reads "Run on …"
7
18
  * instead of "Tool invoke". Any other call comes back unchanged.
8
19
  */
9
20
  export function invokedToolCall(item: ToolCallItem): ToolCallItem {
10
- if (mcpToolLeaf(item.name) !== "tool_invoke") return item;
11
- const args = parseToolArgs(item.arguments);
12
- if (typeof args.name !== "string" || !args.name.trim()) return item;
21
+ const invoked = invokedTool(item.name, item.arguments);
22
+ if (!invoked) return item;
13
23
  const { display: _display, ...rest } = item;
14
- return { ...rest, name: args.name, arguments: args.arguments ?? {} };
24
+ return { ...rest, ...invoked };
15
25
  }
@@ -33,6 +33,7 @@ import {
33
33
  tryParseJson,
34
34
  } from "../lib/format";
35
35
  import { mcpToolLeaf, toolMatchesLeaf } from "./tool-display-name";
36
+ import { invokedTool } from "./invoked-tool";
36
37
  import { presentTurnFailureText } from "./compaction-copy";
37
38
  import { toolOutputPreviewFact, type ToolOutputReader } from "../hooks/tool-output-reads";
38
39
  import type {
@@ -894,21 +895,25 @@ export function buildTimeline(
894
895
  // decision behind a duplicate generic "Ask" step.
895
896
  break;
896
897
  }
898
+ // A worker started or messaged through tool_invoke is the same worker.
899
+ const invoked = invokedTool(name, args);
900
+ const workerName = invoked?.name ?? name;
901
+ const workerArgs = invoked ? invoked.arguments : args;
897
902
  if (
898
- toolMatchesLeaf(name, WORKER_SPAWN_TOOL) ||
899
- toolMatchesLeaf(name, WORKER_MESSAGE_TOOL)
903
+ toolMatchesLeaf(workerName, WORKER_SPAWN_TOOL) ||
904
+ toolMatchesLeaf(workerName, WORKER_MESSAGE_TOOL)
900
905
  ) {
901
- const spawn = toolMatchesLeaf(name, WORKER_SPAWN_TOOL);
902
- const title = spawn ? workerTitle(args) : null;
906
+ const spawn = toolMatchesLeaf(workerName, WORKER_SPAWN_TOOL);
907
+ const title = spawn ? workerTitle(workerArgs) : null;
903
908
  const item: WorkerItem = {
904
909
  kind: "worker",
905
910
  id: event.id,
906
911
  turnId,
907
912
  callId,
908
913
  action: spawn ? "spawn" : "message",
909
- prompt: workerPrompt(args),
914
+ prompt: workerPrompt(workerArgs),
910
915
  ...(title ? { title } : {}),
911
- workerSessionId: extractSessionRef(args),
916
+ workerSessionId: extractSessionRef(workerArgs),
912
917
  failure: null,
913
918
  status: "running",
914
919
  occurredAt: event.occurredAt,
@@ -1498,6 +1503,7 @@ export function buildTimeline(
1498
1503
  capability,
1499
1504
  setupRequest,
1500
1505
  requestedSandboxId: stringValue(payload.requestedSandboxId) || null,
1506
+ ...(payload.purpose === "chrome" ? { purpose: "chrome" as const } : {}),
1501
1507
  occurredAt: event.occurredAt,
1502
1508
  });
1503
1509
  break;
@@ -2197,14 +2203,15 @@ const CONNECTED_MACHINE_CARD_ID = "api:connected-machine";
2197
2203
  * An agent that is refused a machine often asks again in later turns. Only the
2198
2204
  * newest Connected Machine card for the same request stays a full card; earlier
2199
2205
  * ones become a short note, so a chat never piles up copies of the same card.
2200
- * Cards that name different machines are separate requests.
2206
+ * Cards that name different machines, or ask for Chrome rather than a machine,
2207
+ * are separate requests.
2201
2208
  */
2202
2209
  function markRepeatedMachineRequests(items: TimelineItem[]): void {
2203
2210
  const seen = new Set<string>();
2204
2211
  for (let index = items.length - 1; index >= 0; index -= 1) {
2205
2212
  const item = items[index]!;
2206
2213
  if (item.kind !== "auth-needed" || item.capability?.id !== CONNECTED_MACHINE_CARD_ID) continue;
2207
- const key = item.requestedSandboxId ?? "";
2214
+ const key = `${item.purpose ?? ""}:${item.requestedSandboxId ?? ""}`;
2208
2215
  if (seen.has(key)) item.askedAgainLater = true;
2209
2216
  else seen.add(key);
2210
2217
  }
@@ -1,11 +1,12 @@
1
1
  import { renderActivity } from "./activity-rail";
2
2
  import { AnimatePresence, motion, useReducedMotion } from "motion/react";
3
- import { WrenchIcon } from "lucide-react";
4
3
  import { Suspense, useEffect, useState } from "react";
5
4
  import { CompactActivityContext } from "./shared";
6
5
  import { defaultToolRegistry } from "./tool-renderers";
7
6
  import type { ToolRegistry } from "./registry";
8
7
  import { toolDisplayName } from "./tool-display-name";
8
+ import { ToolKindIcon } from "./tool-icon";
9
+ import { genericToolIconKind } from "./tool-presentation";
9
10
  import { toolStepPhase } from "./tool-steps";
10
11
  import type { ActivityItem } from "./types";
11
12
  import { rollingActivityItem } from "./work-presentation";
@@ -36,7 +37,10 @@ export function RollingActivity({
36
37
  const { item, earlierCount } = selected;
37
38
  const fallback = (
38
39
  <span className="og-rolling-label">
39
- <WrenchIcon className="size-3.5" />
40
+ <ToolKindIcon
41
+ kind={item.kind === "tool-call" ? genericToolIconKind(item.name) : "wrench"}
42
+ className="size-3.5"
43
+ />
40
44
  <span>
41
45
  {item.kind === "tool-call"
42
46
  ? toolDisplayName(t, item.name, item.display, toolStepPhase(item.status))