@opengeni/react 4.4.1 → 4.5.1-canary.39832248373001

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 (654) hide show
  1. package/dist/app/app-state.js +15 -15
  2. package/dist/app/components/Composer.js +19 -19
  3. package/dist/app/components/artifacts/artifact-browse-controls.js +3 -3
  4. package/dist/app/components/artifacts/artifact-library.js +9 -9
  5. package/dist/app/components/artifacts/artifact-page-chrome.js +2 -2
  6. package/dist/app/components/artifacts/chat-interactive-block.js +14 -14
  7. package/dist/app/components/artifacts/inline-chat-image.js +22 -21
  8. package/dist/app/components/artifacts/retained-file-preview.js +24 -23
  9. package/dist/app/components/artifacts/retained-text-preview.js +2 -2
  10. package/dist/app/components/artifacts/site-audience.js +2 -2
  11. package/dist/app/components/artifacts/site-conversations.js +14 -13
  12. package/dist/app/components/artifacts/site-data.js +4 -4
  13. package/dist/app/components/artifacts/site-publishing.js +20 -20
  14. package/dist/app/components/artifacts/site-settings.js +25 -25
  15. package/dist/app/components/billing-class-mark.js +3 -3
  16. package/dist/app/components/capabilities/capability-detail-sheet.js +6 -6
  17. package/dist/app/components/capabilities/capability-logo-source.js +8 -8
  18. package/dist/app/components/capabilities/connector-tool-permissions.js +3 -3
  19. package/dist/app/components/capabilities/native-connect-setup.js +8 -8
  20. package/dist/app/components/capabilities/prepared-mcp-setup-card.js +10 -10
  21. package/dist/app/components/capabilities/session-capability-card.js +43 -41
  22. package/dist/app/components/capabilities/session-capability-card.js.map +1 -1
  23. package/dist/app/components/capabilities/session-chrome-card.js +20 -18
  24. package/dist/app/components/capabilities/session-custom-mcp-card.js +11 -11
  25. package/dist/app/components/capabilities/session-github-card.js +13 -13
  26. package/dist/app/components/capabilities/session-machine-card.js +19 -17
  27. package/dist/app/components/command-menu/chat-status.js +16 -15
  28. package/dist/app/components/command-menu/chat-switcher.js +19 -18
  29. package/dist/app/components/command-menu/chat-switcher.js.map +1 -1
  30. package/dist/app/components/command-menu/command-menu.js +29 -107
  31. package/dist/app/components/command-menu/command-menu.js.map +1 -1
  32. package/dist/app/components/command-menu/shortcut-sheet.js +9 -9
  33. package/dist/app/components/composer-mobile-plus-panel.js +9 -9
  34. package/dist/app/components/composer-mobile-plus.js +1 -1
  35. package/dist/app/components/credit-required-gate.js +1 -1
  36. package/dist/app/components/credit-required-prompt.js +5 -5
  37. package/dist/app/components/credits/coupon-redeem.js +2 -2
  38. package/dist/app/components/credits/credit-refusal-notice.js +2 -2
  39. package/dist/app/components/desktop/app-shots.js +7 -7
  40. package/dist/app/components/desktop/this-computer.js +4 -4
  41. package/dist/app/components/feedback.js +3 -3
  42. package/dist/app/components/follow-up-repository-menu-body.js +2 -2
  43. package/dist/app/components/follow-up-repository-picker.js +1 -1
  44. package/dist/app/components/github-app-connect-launcher.js +2 -2
  45. package/dist/app/components/in-app-help-link.js +2 -2
  46. package/dist/app/components/machines/connect-machine-dialog.js +3 -3
  47. package/dist/app/components/markdown.js +5 -5
  48. package/dist/app/components/models/models-ui.js +3 -3
  49. package/dist/app/components/new-session-starters.js +2 -2
  50. package/dist/app/components/pickers.js +6 -6
  51. package/dist/app/components/rail/rail-context.js +3 -3
  52. package/dist/app/components/rail/rail-sections.js +51 -48
  53. package/dist/app/components/rail/session-header.js +29 -28
  54. package/dist/app/components/rail/session-list.js +50 -47
  55. package/dist/app/components/rail/session-row-content.d.ts +6 -2
  56. package/dist/app/components/rail/session-row-content.js +1 -1
  57. package/dist/app/components/rail/session-row-hover-details.js +17 -16
  58. package/dist/app/components/rail/session-shell.js +78 -75
  59. package/dist/app/components/rail/site-session-group-heading.d.ts +7 -1
  60. package/dist/app/components/rail/site-session-group-heading.js +20 -3
  61. package/dist/app/components/repository-picker.js +2 -2
  62. package/dist/app/components/session/agent-configuration-panel.js +18 -18
  63. package/dist/app/components/session/artifact-link-boundary.js +2 -2
  64. package/dist/app/components/session/artifact-session-page.js +5 -5
  65. package/dist/app/components/session/banners.js +7 -7
  66. package/dist/app/components/session/codex-account-indicator.js +10 -10
  67. package/dist/app/components/session/editable-artifacts-workspace.js +24 -24
  68. package/dist/app/components/session/failed-session-banner.js +6 -6
  69. package/dist/app/components/session/human-input.js +41 -37
  70. package/dist/app/components/session/inspector.js +61 -57
  71. package/dist/app/components/session/inspector.js.map +1 -1
  72. package/dist/app/components/session/message-actions.js +3 -3
  73. package/dist/app/components/session/message-resource-attachments.js +12 -11
  74. package/dist/app/components/session/message-resource-attachments.js.map +1 -1
  75. package/dist/app/components/session/model-account-indicator.js +9 -9
  76. package/dist/app/components/session/model-recovery-notice.js +3 -3
  77. package/dist/app/components/session/new-session-settings-menu.js +8 -8
  78. package/dist/app/components/session/sandbox-switcher.js +12 -12
  79. package/dist/app/components/session/sandbox-workspace.js +58 -54
  80. package/dist/app/components/session/search-markdown-highlight.js +6 -6
  81. package/dist/app/components/session/search-results-view.js +7 -7
  82. package/dist/app/components/session/session-admin-access.js +3 -3
  83. package/dist/app/components/session/session-admission-notice.js +5 -5
  84. package/dist/app/components/session/session-machine-access-notice.js +5 -5
  85. package/dist/app/components/session/session-search-dialog.js +8 -8
  86. package/dist/app/components/session/session-tenancy-control.d.ts +2 -0
  87. package/dist/app/components/session/session-tenancy-control.js +26 -11
  88. package/dist/app/components/session/session-tenancy-control.js.map +1 -1
  89. package/dist/app/components/session/session-usage-limit-section.js +4 -4
  90. package/dist/app/components/session/session-wait-status.js +8 -7
  91. package/dist/app/components/session/session-wait-status.js.map +1 -1
  92. package/dist/app/components/session/site-origin-link.d.ts +1 -0
  93. package/dist/app/components/session/site-origin-link.js +2 -2
  94. package/dist/app/components/session/subagents.js +13 -12
  95. package/dist/app/components/settings/row-select.js +3 -3
  96. package/dist/app/components/transcription-settings.js +4 -4
  97. package/dist/app/components/usage/usage-entry.js +5 -5
  98. package/dist/app/components/workspace-composer-plus.js +12 -12
  99. package/dist/app/embed/memory-navigation.js +2 -2
  100. package/dist/app/embed/session-app.js +196 -190
  101. package/dist/app/lib/actions/actions-provider.js +9 -9
  102. package/dist/app/lib/actions/held-modifier.d.ts +11 -0
  103. package/dist/app/lib/app-surfaces.js +2 -2
  104. package/dist/app/lib/codex-usage-query.js +6 -6
  105. package/dist/app/lib/composer-connectors.js +9 -9
  106. package/dist/app/lib/console-site.d.ts +6 -0
  107. package/dist/app/lib/console-site.js +14 -0
  108. package/dist/app/lib/console-text.js +2 -2
  109. package/dist/app/lib/events.js +13 -12
  110. package/dist/app/lib/failed-session-copy.js +3 -3
  111. package/dist/app/lib/model-access-onboarding.js +3 -3
  112. package/dist/app/lib/move-chat-to-machine.js +3 -3
  113. package/dist/app/lib/navigation.d.ts +5 -0
  114. package/dist/app/lib/navigation.js +1 -1
  115. package/dist/app/lib/routes.d.ts +17 -0
  116. package/dist/app/lib/routes.js +9 -3
  117. package/dist/app/lib/session-branch-cache.js +12 -11
  118. package/dist/app/lib/session-create.js +2 -2
  119. package/dist/app/lib/session-deep-link.js +2 -2
  120. package/dist/app/lib/session-failure-toasts.d.ts +8 -0
  121. package/dist/app/lib/session-group-pagination.js +12 -11
  122. package/dist/app/lib/session-hover-facts.js +12 -11
  123. package/dist/app/lib/session-model.js +2 -2
  124. package/dist/app/lib/session-rail.js +8 -7
  125. package/dist/app/lib/session-rename.js +2 -2
  126. package/dist/app/lib/session-ui-features.d.ts +6 -1
  127. package/dist/app/lib/session-ui-features.js +1 -1
  128. package/dist/app/lib/sessions-group.d.ts +43 -3
  129. package/dist/app/lib/sessions-group.js +19 -12
  130. package/dist/app/lib/shared-query.js +3 -3
  131. package/dist/app/lib/site-opened.d.ts +6 -0
  132. package/dist/app/lib/site-opened.js +10 -0
  133. package/dist/app/lib/turn-failure-analytics.js +5 -5
  134. package/dist/app/lib/use-duplicate-site.js +2 -2
  135. package/dist/app/lib/use-follow-up-repositories.js +2 -2
  136. package/dist/app/lib/use-session-list-hint-refresh.d.ts +20 -2
  137. package/dist/app/lib/use-session-list-hint-refresh.js +5 -1
  138. package/dist/app/lib/use-workspace-machines.js +5 -5
  139. package/dist/app/lib/use-workspace-model-catalog.js +7 -7
  140. package/dist/app/lib/use-workspace-rigs.js +7 -7
  141. package/dist/app/lib/workspace-navigation-preference.js +4 -4
  142. package/dist/app/lib/workspace-scope-context.js +3 -3
  143. package/dist/app/routes/artifacts.js +70 -87
  144. package/dist/app/routes/artifacts.js.map +1 -1
  145. package/dist/app/routes/retained-artifact.js +36 -35
  146. package/dist/app/routes/retained-artifact.js.map +1 -1
  147. package/dist/app/routes/session-unavailable.js +6 -4
  148. package/dist/app/routes/session.js +127 -123
  149. package/dist/app/routes/sessions-index-hydration.js +3 -3
  150. package/dist/app/routes/sessions-index.js +96 -94
  151. package/dist/app/routes/site-view.d.ts +11 -0
  152. package/dist/app/routes/site-view.js +597 -0
  153. package/dist/app/routes/site-view.js.map +1 -0
  154. package/dist/artifacts-document.js +4 -4
  155. package/dist/artifacts-presentation.js +4 -4
  156. package/dist/artifacts-spreadsheet.js +4 -4
  157. package/dist/artifacts.js +13 -13
  158. package/dist/{browser-viewer-RYYQSRTC.js → browser-viewer-VPK3CV2H.js} +7 -5
  159. package/dist/{chat-interactive-block-ABCRKXJ4.js → chat-interactive-block-AMDSW656.js} +5 -5
  160. package/dist/chunk-22GTC4MZ.js +15 -0
  161. package/dist/chunk-22GTC4MZ.js.map +1 -0
  162. package/dist/{chunk-RQDFYQHA.js → chunk-25LWDG5D.js} +6 -6
  163. package/dist/{chunk-U3HSFCON.js → chunk-2CKVVAGP.js} +15 -15
  164. package/dist/{chunk-F6LBGYS6.js → chunk-2DL6NJP5.js} +15 -15
  165. package/dist/{chunk-UHFWF6ZU.js → chunk-2FPS5H2D.js} +2 -2
  166. package/dist/{chunk-NAWXARTY.js → chunk-2KO2G3RI.js} +72 -6
  167. package/dist/chunk-2KO2G3RI.js.map +1 -0
  168. package/dist/{chunk-TWXIFWBD.js → chunk-34EU25RL.js} +2 -2
  169. package/dist/{chunk-PTGRFAMH.js → chunk-3ABPIUCK.js} +2 -2
  170. package/dist/{chunk-722UO6YQ.js → chunk-3PEXVG4D.js} +2 -2
  171. package/dist/{chunk-N3ZP4IDU.js → chunk-45WYYFP6.js} +2 -2
  172. package/dist/{chunk-HOJGAJAB.js → chunk-4MQLGMV2.js} +5 -5
  173. package/dist/{chunk-L7YURQI2.js → chunk-4U4GXWXS.js} +3 -3
  174. package/dist/{chunk-63VGE4OH.js → chunk-5HIOVXOX.js} +3 -3
  175. package/dist/{chunk-GFUUFM2O.js → chunk-5M23GZA2.js} +3 -3
  176. package/dist/{chunk-PM3OSANE.js → chunk-5MJHH72T.js} +14 -3
  177. package/dist/chunk-5MJHH72T.js.map +1 -0
  178. package/dist/{chunk-RKB2Z457.js → chunk-5VGJXWQ2.js} +2 -2
  179. package/dist/{chunk-6W3LF3DB.js → chunk-5YFY4SFC.js} +2 -12
  180. package/dist/chunk-5YFY4SFC.js.map +1 -0
  181. package/dist/{chunk-I6VUUEXH.js → chunk-6AFSZKZA.js} +3 -3
  182. package/dist/{chunk-FBMU3VK5.js → chunk-6DCEDIF6.js} +2 -2
  183. package/dist/{chunk-5MZTJMZ3.js → chunk-6MRY2RUZ.js} +13 -7
  184. package/dist/chunk-6MRY2RUZ.js.map +1 -0
  185. package/dist/{chunk-4EONHNJU.js → chunk-6O4VWKSO.js} +2 -2
  186. package/dist/chunk-756MKA2J.js +45 -0
  187. package/dist/chunk-756MKA2J.js.map +1 -0
  188. package/dist/{chunk-BSX2R4CW.js → chunk-767WCGAX.js} +6 -6
  189. package/dist/{chunk-7KGKDWWR.js → chunk-7HFLYNWN.js} +2 -2
  190. package/dist/{chunk-OSVHU2WU.js → chunk-7IYAHFPE.js} +2 -2
  191. package/dist/{chunk-4EAF3HSD.js → chunk-7J7PZB4S.js} +2 -2
  192. package/dist/{chunk-ADJJQSYC.js → chunk-7PUFAH4I.js} +34 -32
  193. package/dist/chunk-7PUFAH4I.js.map +1 -0
  194. package/dist/{chunk-OR37STQZ.js → chunk-7R2JQHBX.js} +3 -3
  195. package/dist/{chunk-QM5H4FPT.js → chunk-7VN6VC3D.js} +3 -3
  196. package/dist/{chunk-HWDGJFM4.js → chunk-A2E3ZF6N.js} +4 -4
  197. package/dist/{chunk-RGW24ZZM.js → chunk-A6CK4ENG.js} +19 -17
  198. package/dist/chunk-A6CK4ENG.js.map +1 -0
  199. package/dist/{chunk-4432A3HQ.js → chunk-A6T4FGE7.js} +4 -4
  200. package/dist/{chunk-73SOCVLS.js → chunk-AIEXYO2X.js} +3 -3
  201. package/dist/{chunk-U7TC2XJQ.js → chunk-AJPW3SV4.js} +3 -3
  202. package/dist/{chunk-46VBQG2D.js → chunk-AOUCHCSB.js} +5 -5
  203. package/dist/{chunk-HDHK3SXK.js → chunk-AT4K4F6S.js} +2 -2
  204. package/dist/{chunk-TQGJN5UZ.js → chunk-AW3QEFOF.js} +140 -522
  205. package/dist/chunk-AW3QEFOF.js.map +1 -0
  206. package/dist/{chunk-HRJQAFKR.js → chunk-AX6YJA5U.js} +2 -2
  207. package/dist/{chunk-HO5Y2OOX.js → chunk-BLPXOHG6.js} +6 -6
  208. package/dist/{chunk-DT7BORXG.js → chunk-BMJTNPWK.js} +2 -2
  209. package/dist/{chunk-HIHO2QE7.js → chunk-BT2MVGHT.js} +2 -2
  210. package/dist/{chunk-AOLE4IRZ.js → chunk-C535KSTY.js} +2 -2
  211. package/dist/{chunk-IVOA3DXA.js → chunk-CB574ERL.js} +4 -4
  212. package/dist/{chunk-IBTXYLBW.js → chunk-CCFWY4GF.js} +2 -2
  213. package/dist/{chunk-ZOC3OP6F.js → chunk-CCR33J7L.js} +2 -2
  214. package/dist/{chunk-NYZQ7LO7.js → chunk-CDUDKETD.js} +2 -2
  215. package/dist/{chunk-JTN3T4QN.js → chunk-D3RK3NGM.js} +4 -4
  216. package/dist/{chunk-IOKSNX74.js → chunk-D5OWJZQR.js} +2 -2
  217. package/dist/{chunk-BJIZ7PL7.js → chunk-D64Z4V26.js} +145 -29
  218. package/dist/chunk-D64Z4V26.js.map +1 -0
  219. package/dist/{chunk-XWWXIZFP.js → chunk-DFXZYNTX.js} +7 -7
  220. package/dist/{chunk-SQGXMHJO.js → chunk-DGLRZMXL.js} +3 -3
  221. package/dist/{chunk-GNEHAPKV.js → chunk-DJFTH2DI.js} +3 -3
  222. package/dist/{chunk-KWKGBGAF.js → chunk-DKCX643S.js} +11 -11
  223. package/dist/{chunk-HQG4SLTE.js → chunk-DYJGYGPB.js} +2 -2
  224. package/dist/{chunk-GTQ3SNEI.js → chunk-E36IC3LU.js} +2 -2
  225. package/dist/{chunk-CVG4FILQ.js → chunk-ECHYJP63.js} +253 -1008
  226. package/dist/chunk-ECHYJP63.js.map +1 -0
  227. package/dist/{chunk-Q35DT6I6.js → chunk-EH7TTYE6.js} +179 -170
  228. package/dist/chunk-EH7TTYE6.js.map +1 -0
  229. package/dist/{chunk-72J6C2AJ.js → chunk-EMCB6XKU.js} +2 -2
  230. package/dist/{chunk-3AA6RNGE.js → chunk-ENS6E4RZ.js} +2 -2
  231. package/dist/{chunk-AG7VGUIW.js → chunk-ERG355NM.js} +3 -3
  232. package/dist/{chunk-TSBE4KOQ.js → chunk-EWL6NDOO.js} +3 -3
  233. package/dist/{chunk-Z5WMLJKI.js → chunk-F2RMKGDQ.js} +89 -1
  234. package/dist/chunk-F2RMKGDQ.js.map +1 -0
  235. package/dist/{chunk-X7L4H4VG.js → chunk-F33EDYS7.js} +524 -426
  236. package/dist/chunk-F33EDYS7.js.map +1 -0
  237. package/dist/{chunk-HTT3FB7T.js → chunk-F3FN6DO6.js} +2 -2
  238. package/dist/{chunk-ST22GONV.js → chunk-FB3B45FP.js} +11 -11
  239. package/dist/{chunk-P5T36BA3.js → chunk-FRP64DEK.js} +2 -2
  240. package/dist/{chunk-KBF3SE7G.js → chunk-FSP334UU.js} +2 -2
  241. package/dist/{chunk-4VKA5O7T.js → chunk-FVL4B552.js} +9 -9
  242. package/dist/{chunk-VP62LPLW.js → chunk-G2BX56CN.js} +5 -5
  243. package/dist/{chunk-CSHBR2IZ.js → chunk-GDLDBR6B.js} +2 -2
  244. package/dist/{chunk-PN66T6JA.js → chunk-GFSOXB2K.js} +2 -2
  245. package/dist/{chunk-S4EZ3JUB.js → chunk-GZGQHQI7.js} +29 -29
  246. package/dist/chunk-H4IE2PYF.js +792 -0
  247. package/dist/chunk-H4IE2PYF.js.map +1 -0
  248. package/dist/{chunk-XFNLU7EW.js → chunk-H5M33DAL.js} +15 -6
  249. package/dist/chunk-H5M33DAL.js.map +1 -0
  250. package/dist/{chunk-BXRIQZAH.js → chunk-HNNM2GDN.js} +3 -3
  251. package/dist/{chunk-EU6XSQFM.js → chunk-HPB4KSV3.js} +2 -2
  252. package/dist/{chunk-QCD5Y7K5.js → chunk-HSQRYJ4P.js} +5 -5
  253. package/dist/{chunk-YXOKAG66.js → chunk-HUXDGWAN.js} +2 -2
  254. package/dist/{chunk-VUHPA3XQ.js → chunk-I66ZB6KD.js} +3 -3
  255. package/dist/{chunk-7CZTKBTI.js → chunk-IC7KNOBB.js} +5 -5
  256. package/dist/{chunk-KF3MF6FP.js → chunk-IECRGM6K.js} +3 -2
  257. package/dist/chunk-IECRGM6K.js.map +1 -0
  258. package/dist/{chunk-HGMWMK5K.js → chunk-IIO2MR3B.js} +2 -2
  259. package/dist/chunk-IJYL5BZM.js +38 -0
  260. package/dist/chunk-IJYL5BZM.js.map +1 -0
  261. package/dist/{chunk-L6RXRRN3.js → chunk-ILDOW2IQ.js} +3 -3
  262. package/dist/{chunk-O756O2I7.js → chunk-IPPVX5GF.js} +1 -1
  263. package/dist/{chunk-X7ASQHR6.js → chunk-IUK5QGP5.js} +2 -2
  264. package/dist/{chunk-5JZYPZ72.js → chunk-JFK7NTEA.js} +4 -4
  265. package/dist/chunk-JFK7NTEA.js.map +1 -0
  266. package/dist/{chunk-PIVGX42P.js → chunk-JNY5MT3I.js} +2 -2
  267. package/dist/chunk-JRSNCSZN.js +37 -0
  268. package/dist/chunk-JRSNCSZN.js.map +1 -0
  269. package/dist/{chunk-DDK4WFJ3.js → chunk-JWN7SLTO.js} +9 -9
  270. package/dist/{chunk-Q35YZVDZ.js → chunk-KFWVBTUH.js} +3 -3
  271. package/dist/{chunk-JXT5QDJC.js → chunk-KNFDWNCH.js} +5 -5
  272. package/dist/{chunk-AZVANYMB.js → chunk-KUNFUSZ7.js} +2 -2
  273. package/dist/{chunk-DXZNDKQD.js → chunk-LEEJBZ5B.js} +2 -2
  274. package/dist/{chunk-STUCI6QA.js → chunk-LEKBNKLD.js} +1 -1
  275. package/dist/{chunk-STUCI6QA.js.map → chunk-LEKBNKLD.js.map} +1 -1
  276. package/dist/{chunk-RSNYGEVZ.js → chunk-LKJ2C7PH.js} +8 -8
  277. package/dist/{chunk-RIMKJBCD.js → chunk-LMPTC4CX.js} +2 -2
  278. package/dist/{chunk-3KVWXKD6.js → chunk-LQ47YL6E.js} +2 -2
  279. package/dist/{chunk-GAIM5RNE.js → chunk-MJQBC7C5.js} +3 -3
  280. package/dist/{chunk-NWZW2WHN.js → chunk-MM7OKOTE.js} +6 -6
  281. package/dist/{chunk-FM4OUCC2.js → chunk-MOKYT3X3.js} +3 -3
  282. package/dist/{chunk-GZ64CASI.js → chunk-MVZYNZXE.js} +5 -4
  283. package/dist/chunk-MVZYNZXE.js.map +1 -0
  284. package/dist/{chunk-XRRSFQEV.js → chunk-NAZZLAWX.js} +2 -2
  285. package/dist/{chunk-XOFUXMPP.js → chunk-ND2WCWXI.js} +4 -4
  286. package/dist/{chunk-6L7U46Y2.js → chunk-NKNVIO66.js} +2 -2
  287. package/dist/{chunk-JKUICTLM.js → chunk-NLAFNMPK.js} +2 -2
  288. package/dist/{chunk-OO2T63BY.js → chunk-NML44AW2.js} +2 -2
  289. package/dist/chunk-NQQKOJDI.js +89 -0
  290. package/dist/chunk-NQQKOJDI.js.map +1 -0
  291. package/dist/{chunk-4LKNIGHB.js → chunk-O2SBHS2N.js} +2 -2
  292. package/dist/{chunk-RA3FNMWF.js → chunk-O4DYOSOL.js} +5 -5
  293. package/dist/{chunk-ZKYYZH6L.js → chunk-OFB6TUDC.js} +4 -4
  294. package/dist/{chunk-DWPOQ3S5.js → chunk-OTMWHZBY.js} +2 -2
  295. package/dist/{chunk-VVCDB2T7.js → chunk-PCJLH45G.js} +3 -3
  296. package/dist/{chunk-WSMYOLHG.js → chunk-PEKPWK5M.js} +2 -2
  297. package/dist/{chunk-PZ24CYDO.js → chunk-PFAUGEV5.js} +2 -2
  298. package/dist/{chunk-KTRKZRID.js → chunk-PKEKZ2VA.js} +5 -5
  299. package/dist/{chunk-6JKZILLF.js → chunk-PMD7V4N7.js} +3 -3
  300. package/dist/{chunk-B74GSYR6.js → chunk-PUTS4DYW.js} +2 -2
  301. package/dist/{chunk-ZRJCGBVV.js → chunk-PVR5EELP.js} +2 -2
  302. package/dist/{chunk-JSIDLTTG.js → chunk-PZ2V2XIK.js} +2 -2
  303. package/dist/{chunk-TMEQPODK.js → chunk-PZ37VDB5.js} +2 -2
  304. package/dist/{chunk-FLGUVRR7.js → chunk-QBADR2FO.js} +6 -6
  305. package/dist/{chunk-TGVVEGZG.js → chunk-QLIDZGPV.js} +6 -6
  306. package/dist/{chunk-LVONK3YQ.js → chunk-QRKTESVE.js} +2 -2
  307. package/dist/{chunk-HT5WSUC7.js → chunk-QXEDIDBZ.js} +3 -3
  308. package/dist/{chunk-WURSS6MP.js → chunk-R66YMYJU.js} +2 -2
  309. package/dist/{chunk-6PQNLL4E.js → chunk-R7XCJWCD.js} +11 -11
  310. package/dist/{chunk-4R3JCVID.js → chunk-RAMZTZOB.js} +360 -103
  311. package/dist/chunk-RAMZTZOB.js.map +1 -0
  312. package/dist/{chunk-QRVNI5V6.js → chunk-SCNEQFIW.js} +3 -3
  313. package/dist/{chunk-BNUPYHHZ.js → chunk-SD4PPZFB.js} +4 -4
  314. package/dist/{chunk-ROQOVH4N.js → chunk-SFAU5R5S.js} +3 -3
  315. package/dist/{chunk-R63QEVPK.js → chunk-SJORXXLV.js} +6 -6
  316. package/dist/{chunk-FBE6AIIW.js → chunk-SOKNCW5U.js} +2 -2
  317. package/dist/{chunk-JRXHSVD5.js → chunk-SOXZ4LGS.js} +68 -11
  318. package/dist/chunk-SOXZ4LGS.js.map +1 -0
  319. package/dist/{chunk-EF5SYXAY.js → chunk-SQDPHCK2.js} +22 -14
  320. package/dist/chunk-SQDPHCK2.js.map +1 -0
  321. package/dist/{chunk-NDF3SH3X.js → chunk-TDIOBPLA.js} +5 -5
  322. package/dist/{chunk-EHCUFCXM.js → chunk-TEPPPAJI.js} +17 -7
  323. package/dist/chunk-TEPPPAJI.js.map +1 -0
  324. package/dist/{chunk-33TPANCR.js → chunk-TFK4KFKA.js} +4 -4
  325. package/dist/{chunk-6NIB2KGJ.js → chunk-THVIT3PW.js} +22 -22
  326. package/dist/{chunk-HPPKLBTJ.js → chunk-TJQDL3JH.js} +2 -2
  327. package/dist/{chunk-FD4Q5KFL.js → chunk-TLL22FFO.js} +2 -2
  328. package/dist/{chunk-7DU35P5J.js → chunk-TN5T5HRZ.js} +7 -7
  329. package/dist/{chunk-JK7C5A4I.js → chunk-TR4HIKJ2.js} +8 -8
  330. package/dist/{chunk-HNYJEAES.js → chunk-UGEWCWVV.js} +3 -3
  331. package/dist/chunk-ULYQEFNH.js +529 -0
  332. package/dist/chunk-ULYQEFNH.js.map +1 -0
  333. package/dist/{chunk-H5EVWF6L.js → chunk-UNNJUJVD.js} +2 -2
  334. package/dist/{chunk-AD22P5X3.js → chunk-UUSAOIJR.js} +3 -3
  335. package/dist/{chunk-Z6DKXQG7.js → chunk-UXXFMF4X.js} +2 -2
  336. package/dist/{chunk-RGPYMHKI.js → chunk-V3K4RQO7.js} +9 -3
  337. package/dist/chunk-V3K4RQO7.js.map +1 -0
  338. package/dist/{chunk-UP4BE32Y.js → chunk-VO6RVVP7.js} +5 -5
  339. package/dist/{chunk-S4SC5SSV.js → chunk-VPNXQUUS.js} +11 -11
  340. package/dist/{chunk-7BST7BA6.js → chunk-VW3BBTMA.js} +1 -1
  341. package/dist/{chunk-CBY5CXBD.js → chunk-VWSFA4LJ.js} +2 -2
  342. package/dist/{chunk-MYNUBDU7.js → chunk-VYKW6TB2.js} +1 -1
  343. package/dist/chunk-VYKW6TB2.js.map +1 -0
  344. package/dist/{chunk-QEJTQTF5.js → chunk-W6T5HR3Z.js} +3 -3
  345. package/dist/{chunk-5JEIDFPD.js → chunk-WBPQ7OPC.js} +1 -1
  346. package/dist/{chunk-GZLLDA6P.js → chunk-WEFN327U.js} +2 -2
  347. package/dist/{chunk-ANHUMDJX.js → chunk-WNDTLK44.js} +2 -2
  348. package/dist/{chunk-DLOYMWUQ.js → chunk-WSLPZ43N.js} +7 -7
  349. package/dist/{chunk-2DS4UOYQ.js → chunk-WSZQNTVN.js} +2 -2
  350. package/dist/{chunk-LE2EDBXU.js → chunk-WUHB422G.js} +5 -5
  351. package/dist/{chunk-BJW7G6EF.js → chunk-WVX5AQXS.js} +3 -3
  352. package/dist/{chunk-5POTDNQT.js → chunk-WWOHORRO.js} +3 -3
  353. package/dist/{chunk-4W7VISE7.js → chunk-WYDZP5F2.js} +93 -94
  354. package/dist/chunk-WYDZP5F2.js.map +1 -0
  355. package/dist/{chunk-KZHW27BV.js → chunk-WYEPUXGL.js} +2 -2
  356. package/dist/{chunk-GALB2G3W.js → chunk-X2AH4DRF.js} +2 -2
  357. package/dist/{chunk-NCX5SAQY.js → chunk-XN6CALYY.js} +9 -9
  358. package/dist/{chunk-SUVEDKE2.js → chunk-XNACICAB.js} +3 -3
  359. package/dist/{chunk-FDNJVZRE.js → chunk-XU4I47IP.js} +4 -4
  360. package/dist/chunk-XV6ZYRHK.js +59 -0
  361. package/dist/chunk-XV6ZYRHK.js.map +1 -0
  362. package/dist/{chunk-WRLWLGEF.js → chunk-Y5E3XQ2S.js} +25 -2
  363. package/dist/{chunk-WRLWLGEF.js.map → chunk-Y5E3XQ2S.js.map} +1 -1
  364. package/dist/{chunk-U36PO27Q.js → chunk-YG3IJCM2.js} +3 -3
  365. package/dist/{chunk-UWJ5P5CU.js → chunk-YGSJWWT3.js} +3 -3
  366. package/dist/{chunk-APU42QDI.js → chunk-YO64YVYL.js} +105 -101
  367. package/dist/chunk-YO64YVYL.js.map +1 -0
  368. package/dist/{chunk-P5WABK2H.js → chunk-Z4GJB24B.js} +2 -2
  369. package/dist/{chunk-NLMTNEWW.js → chunk-Z6E6TUAE.js} +2 -2
  370. package/dist/{chunk-OBQVTCTW.js → chunk-ZX5H7LWD.js} +2 -2
  371. package/dist/components/browser-viewer.d.ts +1 -1
  372. package/dist/composer.js +8 -8
  373. package/dist/{computer-viewer-KEDVLD42.js → computer-viewer-VA5JONUH.js} +6 -6
  374. package/dist/connect.js +7 -7
  375. package/dist/desktop.js +2 -2
  376. package/dist/editor.js +2 -2
  377. package/dist/{embedded-new-voice-LFHWWYD2.js → embedded-new-voice-6BILAOUG.js} +6 -6
  378. package/dist/{embedded-voice-6QS4ANNX.js → embedded-voice-UDE4JRKB.js} +6 -6
  379. package/dist/{fleet-decision-row-QNSTP3VX.js → fleet-decision-row-NN2HXDX3.js} +2 -2
  380. package/dist/hooks/internal.d.ts +38 -0
  381. package/dist/hooks/use-client-config-flags.d.ts +12 -0
  382. package/dist/hooks/use-workspace-sessions.d.ts +10 -1
  383. package/dist/index.js +86 -80
  384. package/dist/interaction.js +8 -6
  385. package/dist/interaction.js.map +1 -1
  386. package/dist/{latest-question-AW3PPDUM.js → latest-question-4WDBECXB.js} +4 -3
  387. package/dist/{latest-question-AW3PPDUM.js.map → latest-question-4WDBECXB.js.map} +1 -1
  388. package/dist/machines.js +4 -4
  389. package/dist/messages/en.d.ts +3 -3
  390. package/dist/messages.js +1 -1
  391. package/dist/{model-policy-picker-menu-CURJ247L.js → model-policy-picker-menu-NRTO6FRP.js} +4 -4
  392. package/dist/{platform-activity-row-BMXXNZKX.js → platform-activity-row-ENQVIFTL.js} +2 -2
  393. package/dist/{queue-surface-implementation-2X5AXB6I.js → queue-surface-implementation-H4XSNHZE.js} +8 -6
  394. package/dist/{queue-surface-implementation-2X5AXB6I.js.map → queue-surface-implementation-H4XSNHZE.js.map} +1 -1
  395. package/dist/realtime.js +5 -5
  396. package/dist/{sandbox-files-4FBG3GS2.js → sandbox-files-IEHODU35.js} +9 -9
  397. package/dist/sandbox-files-IEHODU35.js.map +1 -0
  398. package/dist/session-app.js +198 -192
  399. package/dist/session-list-model.d.ts +1 -0
  400. package/dist/session-list-model.js +7 -1
  401. package/dist/{session-realtime-2XIB254N.js → session-realtime-JNKDSGH7.js} +3 -3
  402. package/dist/session-realtime-JNKDSGH7.js.map +1 -0
  403. package/dist/session-realtime.js +2 -2
  404. package/dist/session-ui.js +48 -43
  405. package/dist/session.js +20 -18
  406. package/dist/sites.js +2 -2
  407. package/dist/terminal.js +2 -2
  408. package/dist/this-computer.js +3 -3
  409. package/dist/timeline/invoked-tool.d.ts +5 -0
  410. package/dist/timeline/tool-display-name.d.ts +2 -2
  411. package/dist/timeline/tool-icon.d.ts +14 -0
  412. package/dist/timeline/tool-presentation.d.ts +8 -3
  413. package/dist/{timeline-annotation-markers-X4K2IEOO.js → timeline-annotation-markers-ZSOFW7PG.js} +2 -2
  414. package/dist/{timeline-annotation-selection-MEHBW676.js → timeline-annotation-selection-YWV2UC34.js} +2 -2
  415. package/dist/{timeline-annotations-dialog-U2FPQ3UY.js → timeline-annotations-dialog-ZWQVX2HI.js} +3 -3
  416. package/dist/timeline-model.js +16 -14
  417. package/dist/ui/access-list.js +7 -7
  418. package/dist/ui/cadence-picker.js +2 -2
  419. package/dist/ui/list-row.js +3 -3
  420. package/dist/ui/revision-history.js +2 -2
  421. package/dist/ui/role-select.js +3 -3
  422. package/dist/ui/select-menu.js +2 -2
  423. package/dist/usage.js +3 -3
  424. package/dist/workbench.js +4 -4
  425. package/package.json +4 -4
  426. package/src/app/app-state.tsx +3 -1
  427. package/src/app/components/capabilities/session-machine-card.tsx +9 -2
  428. package/src/app/components/rail/session-list.tsx +254 -44
  429. package/src/app/components/rail/session-row-content.tsx +24 -2
  430. package/src/app/components/rail/session-shell.tsx +14 -9
  431. package/src/app/components/rail/site-session-group-heading.tsx +59 -20
  432. package/src/app/components/session/session-tenancy-control.tsx +18 -0
  433. package/src/app/components/session/site-origin-link.test.tsx +73 -0
  434. package/src/app/components/session/site-origin-link.tsx +4 -2
  435. package/src/app/embed/memory-navigation.tsx +1 -0
  436. package/src/app/lib/actions/held-modifier.test.ts +101 -0
  437. package/src/app/lib/actions/held-modifier.ts +108 -0
  438. package/src/app/lib/console-site.tsx +38 -0
  439. package/src/app/lib/navigation.tsx +4 -0
  440. package/src/app/lib/routes.tsx +42 -0
  441. package/src/app/lib/session-failure-toasts.ts +26 -0
  442. package/src/app/lib/session-ui-features.tsx +18 -4
  443. package/src/app/lib/sessions-group.tsx +219 -30
  444. package/src/app/lib/site-opened.tsx +48 -0
  445. package/src/app/lib/site-session-groups.test.ts +173 -6
  446. package/src/app/lib/site-view-routes.test.ts +55 -0
  447. package/src/app/lib/use-session-list-hint-refresh.tsx +44 -4
  448. package/src/app/routes/artifacts.tsx +2 -29
  449. package/src/app/routes/session-transient-failures.test.tsx +343 -0
  450. package/src/app/routes/session-unavailable.tsx +74 -3
  451. package/src/app/routes/session.tsx +4 -13
  452. package/src/app/routes/sessions-index.tsx +13 -9
  453. package/src/app/routes/site-view.test.tsx +476 -0
  454. package/src/app/routes/site-view.tsx +583 -0
  455. package/src/components/browser-viewer.tsx +16 -2
  456. package/src/hooks/internal.ts +129 -6
  457. package/src/hooks/use-client-config-flags.ts +8 -0
  458. package/src/hooks/use-session-events.ts +83 -9
  459. package/src/hooks/use-workspace-sessions.ts +21 -1
  460. package/src/messages/en.ts +3 -3
  461. package/src/session-list-model.ts +4 -0
  462. package/src/timeline/activity-rail.tsx +3 -2
  463. package/src/timeline/invoked-tool.ts +14 -4
  464. package/src/timeline/projection.ts +11 -6
  465. package/src/timeline/rolling-activity.tsx +6 -2
  466. package/src/timeline/tool-display-name.ts +2 -2
  467. package/src/timeline/tool-icon.tsx +165 -0
  468. package/src/timeline/tool-presentation.ts +207 -48
  469. package/src/timeline/tool-renderers.tsx +1 -70
  470. package/styles/compiled.css +38 -0
  471. package/dist/chunk-22ZBT6CN.js +0 -50
  472. package/dist/chunk-22ZBT6CN.js.map +0 -1
  473. package/dist/chunk-4R3JCVID.js.map +0 -1
  474. package/dist/chunk-4W7VISE7.js.map +0 -1
  475. package/dist/chunk-5JZYPZ72.js.map +0 -1
  476. package/dist/chunk-5MZTJMZ3.js.map +0 -1
  477. package/dist/chunk-6W3LF3DB.js.map +0 -1
  478. package/dist/chunk-ADJJQSYC.js.map +0 -1
  479. package/dist/chunk-APU42QDI.js.map +0 -1
  480. package/dist/chunk-BJIZ7PL7.js.map +0 -1
  481. package/dist/chunk-CVG4FILQ.js.map +0 -1
  482. package/dist/chunk-EF5SYXAY.js.map +0 -1
  483. package/dist/chunk-EHCUFCXM.js.map +0 -1
  484. package/dist/chunk-GZ64CASI.js.map +0 -1
  485. package/dist/chunk-JRXHSVD5.js.map +0 -1
  486. package/dist/chunk-KF3MF6FP.js.map +0 -1
  487. package/dist/chunk-MYNUBDU7.js.map +0 -1
  488. package/dist/chunk-NAWXARTY.js.map +0 -1
  489. package/dist/chunk-PM3OSANE.js.map +0 -1
  490. package/dist/chunk-Q35DT6I6.js.map +0 -1
  491. package/dist/chunk-R25ZKOZR.js +0 -24
  492. package/dist/chunk-R25ZKOZR.js.map +0 -1
  493. package/dist/chunk-RGPYMHKI.js.map +0 -1
  494. package/dist/chunk-RGW24ZZM.js.map +0 -1
  495. package/dist/chunk-TQGJN5UZ.js.map +0 -1
  496. package/dist/chunk-X7L4H4VG.js.map +0 -1
  497. package/dist/chunk-XFNLU7EW.js.map +0 -1
  498. package/dist/chunk-Z5WMLJKI.js.map +0 -1
  499. /package/dist/{browser-viewer-RYYQSRTC.js.map → app/lib/console-site.js.map} +0 -0
  500. /package/dist/{chat-interactive-block-ABCRKXJ4.js.map → app/lib/site-opened.js.map} +0 -0
  501. /package/dist/{computer-viewer-KEDVLD42.js.map → browser-viewer-VPK3CV2H.js.map} +0 -0
  502. /package/dist/{embedded-new-voice-LFHWWYD2.js.map → chat-interactive-block-AMDSW656.js.map} +0 -0
  503. /package/dist/{chunk-RQDFYQHA.js.map → chunk-25LWDG5D.js.map} +0 -0
  504. /package/dist/{chunk-U3HSFCON.js.map → chunk-2CKVVAGP.js.map} +0 -0
  505. /package/dist/{chunk-F6LBGYS6.js.map → chunk-2DL6NJP5.js.map} +0 -0
  506. /package/dist/{chunk-UHFWF6ZU.js.map → chunk-2FPS5H2D.js.map} +0 -0
  507. /package/dist/{chunk-TWXIFWBD.js.map → chunk-34EU25RL.js.map} +0 -0
  508. /package/dist/{chunk-PTGRFAMH.js.map → chunk-3ABPIUCK.js.map} +0 -0
  509. /package/dist/{chunk-722UO6YQ.js.map → chunk-3PEXVG4D.js.map} +0 -0
  510. /package/dist/{chunk-N3ZP4IDU.js.map → chunk-45WYYFP6.js.map} +0 -0
  511. /package/dist/{chunk-HOJGAJAB.js.map → chunk-4MQLGMV2.js.map} +0 -0
  512. /package/dist/{chunk-L7YURQI2.js.map → chunk-4U4GXWXS.js.map} +0 -0
  513. /package/dist/{chunk-63VGE4OH.js.map → chunk-5HIOVXOX.js.map} +0 -0
  514. /package/dist/{chunk-GFUUFM2O.js.map → chunk-5M23GZA2.js.map} +0 -0
  515. /package/dist/{chunk-RKB2Z457.js.map → chunk-5VGJXWQ2.js.map} +0 -0
  516. /package/dist/{chunk-I6VUUEXH.js.map → chunk-6AFSZKZA.js.map} +0 -0
  517. /package/dist/{chunk-FBMU3VK5.js.map → chunk-6DCEDIF6.js.map} +0 -0
  518. /package/dist/{chunk-4EONHNJU.js.map → chunk-6O4VWKSO.js.map} +0 -0
  519. /package/dist/{chunk-BSX2R4CW.js.map → chunk-767WCGAX.js.map} +0 -0
  520. /package/dist/{chunk-7KGKDWWR.js.map → chunk-7HFLYNWN.js.map} +0 -0
  521. /package/dist/{chunk-OSVHU2WU.js.map → chunk-7IYAHFPE.js.map} +0 -0
  522. /package/dist/{chunk-4EAF3HSD.js.map → chunk-7J7PZB4S.js.map} +0 -0
  523. /package/dist/{chunk-OR37STQZ.js.map → chunk-7R2JQHBX.js.map} +0 -0
  524. /package/dist/{chunk-QM5H4FPT.js.map → chunk-7VN6VC3D.js.map} +0 -0
  525. /package/dist/{chunk-HWDGJFM4.js.map → chunk-A2E3ZF6N.js.map} +0 -0
  526. /package/dist/{chunk-4432A3HQ.js.map → chunk-A6T4FGE7.js.map} +0 -0
  527. /package/dist/{chunk-73SOCVLS.js.map → chunk-AIEXYO2X.js.map} +0 -0
  528. /package/dist/{chunk-U7TC2XJQ.js.map → chunk-AJPW3SV4.js.map} +0 -0
  529. /package/dist/{chunk-46VBQG2D.js.map → chunk-AOUCHCSB.js.map} +0 -0
  530. /package/dist/{chunk-HDHK3SXK.js.map → chunk-AT4K4F6S.js.map} +0 -0
  531. /package/dist/{chunk-HRJQAFKR.js.map → chunk-AX6YJA5U.js.map} +0 -0
  532. /package/dist/{chunk-HO5Y2OOX.js.map → chunk-BLPXOHG6.js.map} +0 -0
  533. /package/dist/{chunk-DT7BORXG.js.map → chunk-BMJTNPWK.js.map} +0 -0
  534. /package/dist/{chunk-HIHO2QE7.js.map → chunk-BT2MVGHT.js.map} +0 -0
  535. /package/dist/{chunk-AOLE4IRZ.js.map → chunk-C535KSTY.js.map} +0 -0
  536. /package/dist/{chunk-IVOA3DXA.js.map → chunk-CB574ERL.js.map} +0 -0
  537. /package/dist/{chunk-IBTXYLBW.js.map → chunk-CCFWY4GF.js.map} +0 -0
  538. /package/dist/{chunk-ZOC3OP6F.js.map → chunk-CCR33J7L.js.map} +0 -0
  539. /package/dist/{chunk-NYZQ7LO7.js.map → chunk-CDUDKETD.js.map} +0 -0
  540. /package/dist/{chunk-JTN3T4QN.js.map → chunk-D3RK3NGM.js.map} +0 -0
  541. /package/dist/{chunk-IOKSNX74.js.map → chunk-D5OWJZQR.js.map} +0 -0
  542. /package/dist/{chunk-XWWXIZFP.js.map → chunk-DFXZYNTX.js.map} +0 -0
  543. /package/dist/{chunk-SQGXMHJO.js.map → chunk-DGLRZMXL.js.map} +0 -0
  544. /package/dist/{chunk-GNEHAPKV.js.map → chunk-DJFTH2DI.js.map} +0 -0
  545. /package/dist/{chunk-KWKGBGAF.js.map → chunk-DKCX643S.js.map} +0 -0
  546. /package/dist/{chunk-HQG4SLTE.js.map → chunk-DYJGYGPB.js.map} +0 -0
  547. /package/dist/{chunk-GTQ3SNEI.js.map → chunk-E36IC3LU.js.map} +0 -0
  548. /package/dist/{chunk-72J6C2AJ.js.map → chunk-EMCB6XKU.js.map} +0 -0
  549. /package/dist/{chunk-3AA6RNGE.js.map → chunk-ENS6E4RZ.js.map} +0 -0
  550. /package/dist/{chunk-AG7VGUIW.js.map → chunk-ERG355NM.js.map} +0 -0
  551. /package/dist/{chunk-TSBE4KOQ.js.map → chunk-EWL6NDOO.js.map} +0 -0
  552. /package/dist/{chunk-HTT3FB7T.js.map → chunk-F3FN6DO6.js.map} +0 -0
  553. /package/dist/{chunk-ST22GONV.js.map → chunk-FB3B45FP.js.map} +0 -0
  554. /package/dist/{chunk-P5T36BA3.js.map → chunk-FRP64DEK.js.map} +0 -0
  555. /package/dist/{chunk-KBF3SE7G.js.map → chunk-FSP334UU.js.map} +0 -0
  556. /package/dist/{chunk-4VKA5O7T.js.map → chunk-FVL4B552.js.map} +0 -0
  557. /package/dist/{chunk-VP62LPLW.js.map → chunk-G2BX56CN.js.map} +0 -0
  558. /package/dist/{chunk-CSHBR2IZ.js.map → chunk-GDLDBR6B.js.map} +0 -0
  559. /package/dist/{chunk-PN66T6JA.js.map → chunk-GFSOXB2K.js.map} +0 -0
  560. /package/dist/{chunk-S4EZ3JUB.js.map → chunk-GZGQHQI7.js.map} +0 -0
  561. /package/dist/{chunk-BXRIQZAH.js.map → chunk-HNNM2GDN.js.map} +0 -0
  562. /package/dist/{chunk-EU6XSQFM.js.map → chunk-HPB4KSV3.js.map} +0 -0
  563. /package/dist/{chunk-QCD5Y7K5.js.map → chunk-HSQRYJ4P.js.map} +0 -0
  564. /package/dist/{chunk-YXOKAG66.js.map → chunk-HUXDGWAN.js.map} +0 -0
  565. /package/dist/{chunk-VUHPA3XQ.js.map → chunk-I66ZB6KD.js.map} +0 -0
  566. /package/dist/{chunk-7CZTKBTI.js.map → chunk-IC7KNOBB.js.map} +0 -0
  567. /package/dist/{chunk-HGMWMK5K.js.map → chunk-IIO2MR3B.js.map} +0 -0
  568. /package/dist/{chunk-L6RXRRN3.js.map → chunk-ILDOW2IQ.js.map} +0 -0
  569. /package/dist/{chunk-O756O2I7.js.map → chunk-IPPVX5GF.js.map} +0 -0
  570. /package/dist/{chunk-X7ASQHR6.js.map → chunk-IUK5QGP5.js.map} +0 -0
  571. /package/dist/{chunk-PIVGX42P.js.map → chunk-JNY5MT3I.js.map} +0 -0
  572. /package/dist/{chunk-DDK4WFJ3.js.map → chunk-JWN7SLTO.js.map} +0 -0
  573. /package/dist/{chunk-Q35YZVDZ.js.map → chunk-KFWVBTUH.js.map} +0 -0
  574. /package/dist/{chunk-JXT5QDJC.js.map → chunk-KNFDWNCH.js.map} +0 -0
  575. /package/dist/{chunk-AZVANYMB.js.map → chunk-KUNFUSZ7.js.map} +0 -0
  576. /package/dist/{chunk-DXZNDKQD.js.map → chunk-LEEJBZ5B.js.map} +0 -0
  577. /package/dist/{chunk-RSNYGEVZ.js.map → chunk-LKJ2C7PH.js.map} +0 -0
  578. /package/dist/{chunk-RIMKJBCD.js.map → chunk-LMPTC4CX.js.map} +0 -0
  579. /package/dist/{chunk-3KVWXKD6.js.map → chunk-LQ47YL6E.js.map} +0 -0
  580. /package/dist/{chunk-GAIM5RNE.js.map → chunk-MJQBC7C5.js.map} +0 -0
  581. /package/dist/{chunk-NWZW2WHN.js.map → chunk-MM7OKOTE.js.map} +0 -0
  582. /package/dist/{chunk-FM4OUCC2.js.map → chunk-MOKYT3X3.js.map} +0 -0
  583. /package/dist/{chunk-XRRSFQEV.js.map → chunk-NAZZLAWX.js.map} +0 -0
  584. /package/dist/{chunk-XOFUXMPP.js.map → chunk-ND2WCWXI.js.map} +0 -0
  585. /package/dist/{chunk-6L7U46Y2.js.map → chunk-NKNVIO66.js.map} +0 -0
  586. /package/dist/{chunk-JKUICTLM.js.map → chunk-NLAFNMPK.js.map} +0 -0
  587. /package/dist/{chunk-OO2T63BY.js.map → chunk-NML44AW2.js.map} +0 -0
  588. /package/dist/{chunk-4LKNIGHB.js.map → chunk-O2SBHS2N.js.map} +0 -0
  589. /package/dist/{chunk-RA3FNMWF.js.map → chunk-O4DYOSOL.js.map} +0 -0
  590. /package/dist/{chunk-ZKYYZH6L.js.map → chunk-OFB6TUDC.js.map} +0 -0
  591. /package/dist/{chunk-DWPOQ3S5.js.map → chunk-OTMWHZBY.js.map} +0 -0
  592. /package/dist/{chunk-VVCDB2T7.js.map → chunk-PCJLH45G.js.map} +0 -0
  593. /package/dist/{chunk-WSMYOLHG.js.map → chunk-PEKPWK5M.js.map} +0 -0
  594. /package/dist/{chunk-PZ24CYDO.js.map → chunk-PFAUGEV5.js.map} +0 -0
  595. /package/dist/{chunk-KTRKZRID.js.map → chunk-PKEKZ2VA.js.map} +0 -0
  596. /package/dist/{chunk-6JKZILLF.js.map → chunk-PMD7V4N7.js.map} +0 -0
  597. /package/dist/{chunk-B74GSYR6.js.map → chunk-PUTS4DYW.js.map} +0 -0
  598. /package/dist/{chunk-ZRJCGBVV.js.map → chunk-PVR5EELP.js.map} +0 -0
  599. /package/dist/{chunk-JSIDLTTG.js.map → chunk-PZ2V2XIK.js.map} +0 -0
  600. /package/dist/{chunk-TMEQPODK.js.map → chunk-PZ37VDB5.js.map} +0 -0
  601. /package/dist/{chunk-FLGUVRR7.js.map → chunk-QBADR2FO.js.map} +0 -0
  602. /package/dist/{chunk-TGVVEGZG.js.map → chunk-QLIDZGPV.js.map} +0 -0
  603. /package/dist/{chunk-LVONK3YQ.js.map → chunk-QRKTESVE.js.map} +0 -0
  604. /package/dist/{chunk-HT5WSUC7.js.map → chunk-QXEDIDBZ.js.map} +0 -0
  605. /package/dist/{chunk-WURSS6MP.js.map → chunk-R66YMYJU.js.map} +0 -0
  606. /package/dist/{chunk-6PQNLL4E.js.map → chunk-R7XCJWCD.js.map} +0 -0
  607. /package/dist/{chunk-QRVNI5V6.js.map → chunk-SCNEQFIW.js.map} +0 -0
  608. /package/dist/{chunk-BNUPYHHZ.js.map → chunk-SD4PPZFB.js.map} +0 -0
  609. /package/dist/{chunk-ROQOVH4N.js.map → chunk-SFAU5R5S.js.map} +0 -0
  610. /package/dist/{chunk-R63QEVPK.js.map → chunk-SJORXXLV.js.map} +0 -0
  611. /package/dist/{chunk-FBE6AIIW.js.map → chunk-SOKNCW5U.js.map} +0 -0
  612. /package/dist/{chunk-NDF3SH3X.js.map → chunk-TDIOBPLA.js.map} +0 -0
  613. /package/dist/{chunk-33TPANCR.js.map → chunk-TFK4KFKA.js.map} +0 -0
  614. /package/dist/{chunk-6NIB2KGJ.js.map → chunk-THVIT3PW.js.map} +0 -0
  615. /package/dist/{chunk-HPPKLBTJ.js.map → chunk-TJQDL3JH.js.map} +0 -0
  616. /package/dist/{chunk-FD4Q5KFL.js.map → chunk-TLL22FFO.js.map} +0 -0
  617. /package/dist/{chunk-7DU35P5J.js.map → chunk-TN5T5HRZ.js.map} +0 -0
  618. /package/dist/{chunk-JK7C5A4I.js.map → chunk-TR4HIKJ2.js.map} +0 -0
  619. /package/dist/{chunk-HNYJEAES.js.map → chunk-UGEWCWVV.js.map} +0 -0
  620. /package/dist/{chunk-H5EVWF6L.js.map → chunk-UNNJUJVD.js.map} +0 -0
  621. /package/dist/{chunk-AD22P5X3.js.map → chunk-UUSAOIJR.js.map} +0 -0
  622. /package/dist/{chunk-Z6DKXQG7.js.map → chunk-UXXFMF4X.js.map} +0 -0
  623. /package/dist/{chunk-UP4BE32Y.js.map → chunk-VO6RVVP7.js.map} +0 -0
  624. /package/dist/{chunk-S4SC5SSV.js.map → chunk-VPNXQUUS.js.map} +0 -0
  625. /package/dist/{chunk-7BST7BA6.js.map → chunk-VW3BBTMA.js.map} +0 -0
  626. /package/dist/{chunk-CBY5CXBD.js.map → chunk-VWSFA4LJ.js.map} +0 -0
  627. /package/dist/{chunk-QEJTQTF5.js.map → chunk-W6T5HR3Z.js.map} +0 -0
  628. /package/dist/{chunk-5JEIDFPD.js.map → chunk-WBPQ7OPC.js.map} +0 -0
  629. /package/dist/{chunk-GZLLDA6P.js.map → chunk-WEFN327U.js.map} +0 -0
  630. /package/dist/{chunk-ANHUMDJX.js.map → chunk-WNDTLK44.js.map} +0 -0
  631. /package/dist/{chunk-DLOYMWUQ.js.map → chunk-WSLPZ43N.js.map} +0 -0
  632. /package/dist/{chunk-2DS4UOYQ.js.map → chunk-WSZQNTVN.js.map} +0 -0
  633. /package/dist/{chunk-LE2EDBXU.js.map → chunk-WUHB422G.js.map} +0 -0
  634. /package/dist/{chunk-BJW7G6EF.js.map → chunk-WVX5AQXS.js.map} +0 -0
  635. /package/dist/{chunk-5POTDNQT.js.map → chunk-WWOHORRO.js.map} +0 -0
  636. /package/dist/{chunk-KZHW27BV.js.map → chunk-WYEPUXGL.js.map} +0 -0
  637. /package/dist/{chunk-GALB2G3W.js.map → chunk-X2AH4DRF.js.map} +0 -0
  638. /package/dist/{chunk-NCX5SAQY.js.map → chunk-XN6CALYY.js.map} +0 -0
  639. /package/dist/{chunk-SUVEDKE2.js.map → chunk-XNACICAB.js.map} +0 -0
  640. /package/dist/{chunk-FDNJVZRE.js.map → chunk-XU4I47IP.js.map} +0 -0
  641. /package/dist/{chunk-U36PO27Q.js.map → chunk-YG3IJCM2.js.map} +0 -0
  642. /package/dist/{chunk-UWJ5P5CU.js.map → chunk-YGSJWWT3.js.map} +0 -0
  643. /package/dist/{chunk-P5WABK2H.js.map → chunk-Z4GJB24B.js.map} +0 -0
  644. /package/dist/{chunk-NLMTNEWW.js.map → chunk-Z6E6TUAE.js.map} +0 -0
  645. /package/dist/{chunk-OBQVTCTW.js.map → chunk-ZX5H7LWD.js.map} +0 -0
  646. /package/dist/{embedded-voice-6QS4ANNX.js.map → computer-viewer-VA5JONUH.js.map} +0 -0
  647. /package/dist/{model-policy-picker-menu-CURJ247L.js.map → embedded-new-voice-6BILAOUG.js.map} +0 -0
  648. /package/dist/{sandbox-files-4FBG3GS2.js.map → embedded-voice-UDE4JRKB.js.map} +0 -0
  649. /package/dist/{fleet-decision-row-QNSTP3VX.js.map → fleet-decision-row-NN2HXDX3.js.map} +0 -0
  650. /package/dist/{session-realtime-2XIB254N.js.map → model-policy-picker-menu-NRTO6FRP.js.map} +0 -0
  651. /package/dist/{platform-activity-row-BMXXNZKX.js.map → platform-activity-row-ENQVIFTL.js.map} +0 -0
  652. /package/dist/{timeline-annotation-markers-X4K2IEOO.js.map → timeline-annotation-markers-ZSOFW7PG.js.map} +0 -0
  653. /package/dist/{timeline-annotation-selection-MEHBW676.js.map → timeline-annotation-selection-YWV2UC34.js.map} +0 -0
  654. /package/dist/{timeline-annotations-dialog-U2FPQ3UY.js.map → timeline-annotations-dialog-ZWQVX2HI.js.map} +0 -0
@@ -1,13 +1,53 @@
1
- import { useEffect } from "react";
1
+ import { useEffect, useRef } from "react";
2
+ import type { WorkspaceSessionListEvent } from "@opengeni/sdk";
2
3
  import { useOpenGeni } from "../../session-context";
3
4
 
4
- /** Small unpaged lists reconcile on any authorized hint; the rail scopes its own pages. */
5
- export function useSessionListHintRefresh(refresh: () => Promise<void>, error: Error | null) {
5
+ /**
6
+ * Whether a hint can change an ordinary (non-Site-row) list. A hint with an
7
+ * empty `sessionIds` only carries Site conversations, which those lists omit.
8
+ */
9
+ export function hintChangesOrdinaryLists(hint: WorkspaceSessionListEvent): boolean {
10
+ return hint.sessionIds === null || hint.sessionIds.length > 0;
11
+ }
12
+
13
+ /**
14
+ * Whether a hint can change a list of Site conversations: a workspace-wide
15
+ * hint, or one naming Site conversations (`siteSessionIds`).
16
+ */
17
+ export function hintChangesSiteConversationLists(hint: WorkspaceSessionListEvent): boolean {
18
+ return hint.sessionIds === null || (hint.siteSessionIds?.length ?? 0) > 0;
19
+ }
20
+
21
+ /**
22
+ * Small unpaged lists reconcile on any authorized hint; the rail scopes its own
23
+ * pages. A list of ordinary sessions skips hints that only name Site
24
+ * conversations; a list of Site conversations (`siteConversations`) skips
25
+ * hints that name none.
26
+ */
27
+ export function useSessionListHintRefresh(
28
+ refresh: () => Promise<void>,
29
+ error: Error | null,
30
+ options: { siteConversations?: boolean | undefined } = {},
31
+ ) {
6
32
  const { workspaceId, workspaceSessionListEvent: hint, workspaceControlEvent } = useOpenGeni();
7
33
  const available = hint?.workspaceId === workspaceId && hint.available;
34
+ const seen = useRef({ hint, workspaceControlEvent });
35
+ const siteConversations = options.siteConversations === true;
8
36
  useEffect(() => {
37
+ const previous = seen.current;
38
+ seen.current = { hint, workspaceControlEvent };
39
+ // A new hint that names nothing this list shows changes nothing here.
40
+ const irrelevant =
41
+ hint !== previous.hint &&
42
+ workspaceControlEvent === previous.workspaceControlEvent &&
43
+ hint !== null &&
44
+ hint !== undefined &&
45
+ !(siteConversations
46
+ ? hintChangesSiteConversationLists(hint)
47
+ : hintChangesOrdinaryLists(hint));
48
+ if (irrelevant) return;
9
49
  if (available && document.visibilityState !== "hidden") void refresh();
10
- }, [available, hint, workspaceControlEvent, refresh]);
50
+ }, [available, hint, workspaceControlEvent, refresh, siteConversations]);
11
51
  useEffect(() => {
12
52
  if (!available || !error || document.visibilityState === "hidden") return;
13
53
  const timer = window.setTimeout(() => void refresh(), 15_000);
@@ -1,7 +1,6 @@
1
1
  import { t } from "../lib/console-text";
2
2
  import { ArtifactSessionPage } from "../components/session/artifact-session-page";
3
3
  import type {
4
- SiteViewer,
5
4
  ToolGatewayIdentity,
6
5
  WorkspaceArtifactContentResponse,
7
6
  WorkspaceArtifactDetailResponse,
@@ -12,7 +11,6 @@ import {
12
11
  artifactLoadErrorMessage,
13
12
  artifactLoadErrorView,
14
13
  type PublishedHtmlArtifactToolBridge,
15
- type SiteToolBridgeFactory,
16
14
  } from "../../artifacts";
17
15
  import { loadSiteSnapshot } from "../../sites";
18
16
  import { SiteConversations } from "../components/artifacts/site-conversations";
@@ -62,6 +60,7 @@ import { useAppContext } from "../app-context";
62
60
  import { ARTIFACT_ACCESS_REQUIRED, isArtifactReadDenied } from "../lib/artifact-access";
63
61
  import { useAppApi } from "../lib/app-api";
64
62
  import { createSiteToolBridge } from "../lib/site-tool-bridge";
63
+ import { useConsoleSiteToolBridge, useConsoleSiteViewer } from "../lib/console-site";
65
64
  import { readyNewChat } from "../lib/ready-new-chat";
66
65
  import { userErrorText } from "../../ui/api-error";
67
66
  import { newArtifactPrompt, siteEditPrompt } from "../lib/site-edit-prompt";
@@ -78,18 +77,6 @@ import type { ArtifactReturnSearch, SiteDetailTab } from "../lib/routes";
78
77
 
79
78
  const NO_SITE_TOOLS: readonly ToolGatewayIdentity[] = [];
80
79
 
81
- /** The signed-in member as Site code sees them (`site.viewer`) in the console. */
82
- function useConsoleSiteViewer(): SiteViewer {
83
- const { accessContext, authSession } = useAppContext();
84
- const subjectId = accessContext.subjectId;
85
- const name = authSession?.user?.name ?? null;
86
- const email = authSession?.user?.email ?? null;
87
- return useMemo(
88
- () => ({ kind: "member", id: `user:${subjectId}`, name, email, signedIn: true }),
89
- [email, name, subjectId],
90
- );
91
- }
92
-
93
80
  function formatSize(bytes: number): string {
94
81
  if (bytes < 1024) return `${bytes} B`;
95
82
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
@@ -420,22 +407,8 @@ function EmbeddedSiteDetail({
420
407
  controls?: EmbeddedSiteControls | undefined;
421
408
  }) {
422
409
  const { client } = useAppContext();
423
- const api = useAppApi();
424
410
  const viewer = useConsoleSiteViewer();
425
- const toolBridge = useCallback<SiteToolBridgeFactory>(
426
- (site) => {
427
- const scope = { workspaceTools: client.tools.forWorkspace(workspaceId), workspaceId };
428
- return site
429
- ? createSiteToolBridge(api, {
430
- ...scope,
431
- artifactId: site.artifactId,
432
- siteVersionId: site.siteVersionId,
433
- requestedTools: site.requestedTools,
434
- })
435
- : createSiteToolBridge(api, scope);
436
- },
437
- [api, client, workspaceId],
438
- );
411
+ const toolBridge = useConsoleSiteToolBridge(workspaceId);
439
412
  return (
440
413
  <SiteView
441
414
  client={client}
@@ -0,0 +1,343 @@
1
+ /* ----------------------------------------------------------------------------
2
+ The session page during an API rolling deploy or a network blip: no
3
+ "Failed to load session" / "Event stream disconnected" toast and no failure
4
+ panel while transient failures are retried quietly; one toast and a
5
+ "Try again" panel only when the failure persists; recovery on its own.
6
+ Definitive errors stay exactly as visible as before.
7
+ -------------------------------------------------------------------------- */
8
+ import { describe, expect, mock, test } from "bun:test";
9
+ import { OpenGeniApiError, type AccessContext, type Session } from "@opengeni/sdk";
10
+ import { act, type ReactNode } from "react";
11
+ import * as SonnerPackage from "sonner";
12
+
13
+ import { flush, registerDom, renderComponent } from "../../../test/render-hook";
14
+ import { fakeClient, SESSION_ID, WORKSPACE_ID } from "../../../test/fake-client";
15
+ import { DEFAULT_TRANSIENT_READ_RETRY } from "../../hooks/internal";
16
+ import { useSession } from "../../hooks/use-session";
17
+ import { useSessionEvents } from "../../hooks/use-session-events";
18
+ import { AppContext, type AppContextValue } from "../app-context";
19
+ import { AppHostProvider, type AppHost } from "../lib/app-host";
20
+ import type { PageHost } from "../lib/navigation";
21
+
22
+ const toastError = mock((_message: string, _data?: unknown) => undefined);
23
+ mock.module("sonner", () => ({
24
+ ...SonnerPackage,
25
+ toast: Object.assign(
26
+ mock((_message: string) => undefined),
27
+ { ...SonnerPackage.toast, error: toastError },
28
+ ),
29
+ }));
30
+
31
+ const { useSessionFailureToasts } = await import("../lib/session-failure-toasts");
32
+ const { SessionUnavailableRoute } = await import("./session-unavailable");
33
+ const { default: SessionRouteAuxiliary } =
34
+ await import("../components/session/session-tenancy-control");
35
+
36
+ registerDom({ clock: "virtual" });
37
+
38
+ const session = {
39
+ id: SESSION_ID,
40
+ workspaceId: WORKSPACE_ID,
41
+ lastSequence: 0,
42
+ title: "Deploy-safe",
43
+ titleSource: "user",
44
+ } as Session;
45
+
46
+ const unavailable = () => new OpenGeniApiError(503, "", { mutation: false });
47
+
48
+ function toastTitles(): string[] {
49
+ return toastError.mock.calls.map(([message]) => message);
50
+ }
51
+
52
+ /** The session page's read hooks plus its failure toasts. */
53
+ function SessionPageReads(props: { client: ReturnType<typeof fakeClient> }) {
54
+ const events = useSessionEvents(SESSION_ID, { client: props.client, workspaceId: WORKSPACE_ID });
55
+ const detail = useSession(SESSION_ID, {
56
+ client: props.client,
57
+ workspaceId: WORKSPACE_ID,
58
+ events: events.events,
59
+ });
60
+ useSessionFailureToasts(detail.error, events.error);
61
+ return <p>{detail.session?.title ?? (detail.error ? "failed" : "loading")}</p>;
62
+ }
63
+
64
+ function RouteProviders(props: { host: AppHost; value: AppContextValue; children: ReactNode }) {
65
+ return (
66
+ <AppHostProvider host={props.host}>
67
+ <AppContext.Provider value={props.value}>{props.children}</AppContext.Provider>
68
+ </AppHostProvider>
69
+ );
70
+ }
71
+
72
+ function liveStream(): ReturnType<typeof fakeClient>["streamEvents"] {
73
+ return (_workspaceId, _sessionId, options = {}) =>
74
+ (async function* () {
75
+ options.onOpen?.();
76
+ await new Promise<void>((resolve) =>
77
+ options.signal?.addEventListener("abort", () => resolve(), { once: true }),
78
+ );
79
+ yield* [];
80
+ })();
81
+ }
82
+
83
+ describe("session page failure toasts", () => {
84
+ test("a transient outage that recovers raises no toast", async () => {
85
+ toastError.mockClear();
86
+ let failing = true;
87
+ const client = fakeClient({
88
+ getSession: async () => {
89
+ if (failing) throw new TypeError("Failed to fetch");
90
+ return session;
91
+ },
92
+ listEvents: async () => {
93
+ if (failing) throw unavailable();
94
+ return [];
95
+ },
96
+ streamEvents: liveStream(),
97
+ });
98
+ const rendered = await renderComponent(<SessionPageReads client={client} />);
99
+ try {
100
+ await flush(8_000);
101
+ expect(rendered.container.textContent).toBe("loading");
102
+ failing = false;
103
+ await flush(8_000);
104
+ expect(rendered.container.textContent).toBe("Deploy-safe");
105
+ expect(toastTitles()).toEqual([]);
106
+ } finally {
107
+ await rendered.unmount();
108
+ }
109
+ });
110
+
111
+ test("a persistent transient outage toasts each failure once, despite background retries", async () => {
112
+ toastError.mockClear();
113
+ const client = fakeClient({
114
+ getSession: async () => {
115
+ throw unavailable();
116
+ },
117
+ listEvents: async () => {
118
+ throw new TypeError("Failed to fetch");
119
+ },
120
+ streamEvents: liveStream(),
121
+ });
122
+ const rendered = await renderComponent(<SessionPageReads client={client} />);
123
+ try {
124
+ await flush(DEFAULT_TRANSIENT_READ_RETRY.quietWindowMs - 3_000);
125
+ expect(toastTitles()).toEqual([]);
126
+ await flush(DEFAULT_TRANSIENT_READ_RETRY.backgroundDelayMs * 4);
127
+ expect(toastTitles().sort()).toEqual(["Event stream disconnected", "Failed to load session"]);
128
+ } finally {
129
+ await rendered.unmount();
130
+ }
131
+ });
132
+
133
+ test("a definitive error toasts at once, and a 404 does not toast", async () => {
134
+ toastError.mockClear();
135
+ const forbidden = fakeClient({
136
+ getSession: async () => {
137
+ throw new OpenGeniApiError(403, "", { mutation: false });
138
+ },
139
+ listEvents: async () => [],
140
+ streamEvents: liveStream(),
141
+ });
142
+ const first = await renderComponent(<SessionPageReads client={forbidden} />);
143
+ await flush(10);
144
+ expect(toastTitles()).toEqual(["Failed to load session"]);
145
+ await first.unmount();
146
+
147
+ toastError.mockClear();
148
+ const missing = fakeClient({
149
+ getSession: async () => {
150
+ throw new OpenGeniApiError(404, "", { mutation: false });
151
+ },
152
+ listEvents: async () => [],
153
+ streamEvents: liveStream(),
154
+ });
155
+ const second = await renderComponent(<SessionPageReads client={missing} />);
156
+ await flush(10);
157
+ expect(toastTitles()).toEqual([]);
158
+ await second.unmount();
159
+ });
160
+ });
161
+
162
+ describe("session load failure panel", () => {
163
+ test("a persistent transient failure offers Try again instead of a dead end", async () => {
164
+ const onRetry = mock(() => undefined);
165
+ const rendered = await renderComponent(
166
+ <SessionRouteAuxiliary
167
+ workspaceId={WORKSPACE_ID}
168
+ sessionId={SESSION_ID}
169
+ loadError={unavailable()}
170
+ onRetry={onRetry}
171
+ />,
172
+ );
173
+ try {
174
+ expect(rendered.container.textContent).toContain("Temporarily unavailable");
175
+ expect(rendered.container.textContent).toContain("Retrying automatically.");
176
+ expect(rendered.container.textContent).not.toContain("Unable to open session");
177
+ const button = [...rendered.container.querySelectorAll("button")].find(
178
+ (candidate) => candidate.textContent === "Try again",
179
+ );
180
+ await act(async () => button?.click());
181
+ expect(onRetry).toHaveBeenCalledTimes(1);
182
+ } finally {
183
+ await rendered.unmount();
184
+ }
185
+ });
186
+
187
+ test("a definitive failure keeps the existing panel", async () => {
188
+ const rendered = await renderComponent(
189
+ <SessionRouteAuxiliary
190
+ workspaceId={WORKSPACE_ID}
191
+ sessionId={SESSION_ID}
192
+ loadError={new OpenGeniApiError(403, "", { mutation: false })}
193
+ onRetry={() => undefined}
194
+ />,
195
+ );
196
+ try {
197
+ expect(rendered.container.textContent).toContain("Unable to open session");
198
+ expect(rendered.container.querySelector("a")?.textContent).toBe("Back to sessions");
199
+ expect(rendered.container.textContent).not.toContain("Try again");
200
+ } finally {
201
+ await rendered.unmount();
202
+ }
203
+ });
204
+ });
205
+
206
+ describe("SessionUnavailableRoute", () => {
207
+ const otherWorkspaceId = "33333333-3333-4333-8333-333333333333";
208
+ const accessContext = {
209
+ subjectId: "subject-a",
210
+ defaultWorkspaceId: WORKSPACE_ID,
211
+ accountGrants: [],
212
+ workspaceGrants: [WORKSPACE_ID, otherWorkspaceId].map((workspaceId) => ({
213
+ workspaceId,
214
+ accountId: "account-a",
215
+ subjectId: "subject-a",
216
+ permissions: ["sessions:read"],
217
+ })),
218
+ } as unknown as AccessContext;
219
+ const workspaces = [
220
+ { id: WORKSPACE_ID, accountId: "account-a" },
221
+ { id: otherWorkspaceId, accountId: "account-a" },
222
+ ];
223
+
224
+ function renderRoute(getSession: () => Promise<Session>) {
225
+ const assigned: string[] = [];
226
+ const page = {
227
+ href: () => `https://app.example.test/workspaces/${WORKSPACE_ID}/sessions/${SESSION_ID}`,
228
+ origin: () => "https://app.example.test",
229
+ readQuery: () => new URLSearchParams(),
230
+ replaceQuery: () => undefined,
231
+ assign: (url: string) => void assigned.push(url),
232
+ opensBeside: false,
233
+ } as unknown as PageHost;
234
+ const value = {
235
+ accessContext,
236
+ workspaces,
237
+ client: { getSession },
238
+ } as unknown as AppContextValue;
239
+ const host = { navigation: { page } } as unknown as AppHost;
240
+ const tree = (node: ReactNode) => (
241
+ <RouteProviders host={host} value={value}>
242
+ {node}
243
+ </RouteProviders>
244
+ );
245
+ return { assigned, tree };
246
+ }
247
+
248
+ test("keeps looking through a transient failure, then shows Try again, then recovers", async () => {
249
+ let failing = true;
250
+ let reads = 0;
251
+ const route = renderRoute(async () => {
252
+ reads += 1;
253
+ if (failing) throw unavailable();
254
+ return session;
255
+ });
256
+ const rendered = await renderComponent(
257
+ route.tree(<SessionUnavailableRoute workspaceId={WORKSPACE_ID} sessionId={SESSION_ID} />),
258
+ );
259
+ try {
260
+ await flush(DEFAULT_TRANSIENT_READ_RETRY.quietWindowMs - 3_000);
261
+ expect(reads).toBeGreaterThan(2);
262
+ expect(rendered.container.textContent).toContain("Looking for this session");
263
+ expect(rendered.container.textContent).not.toContain("Session unavailable");
264
+
265
+ await flush(8_000);
266
+ expect(rendered.container.textContent).toContain("Temporarily unavailable");
267
+ const tryAgain = [...rendered.container.querySelectorAll("button")].find(
268
+ (candidate) => candidate.textContent === "Try again",
269
+ );
270
+ expect(tryAgain).toBeDefined();
271
+
272
+ failing = false;
273
+ await act(async () => tryAgain?.click());
274
+ await flush(10);
275
+ expect(route.assigned).toEqual([`/workspaces/${otherWorkspaceId}/sessions/${SESSION_ID}`]);
276
+ } finally {
277
+ await rendered.unmount();
278
+ }
279
+ });
280
+
281
+ test("a definitive server error keeps the existing Session unavailable panel", async () => {
282
+ let reads = 0;
283
+ const route = renderRoute(async () => {
284
+ reads += 1;
285
+ throw new OpenGeniApiError(500, "", { mutation: false });
286
+ });
287
+ const rendered = await renderComponent(
288
+ route.tree(<SessionUnavailableRoute workspaceId={WORKSPACE_ID} sessionId={SESSION_ID} />),
289
+ );
290
+ try {
291
+ await flush(10);
292
+ expect(rendered.container.textContent).toContain("Session unavailable");
293
+ await flush(60_000);
294
+ expect(reads).toBe(1);
295
+ } finally {
296
+ await rendered.unmount();
297
+ }
298
+ });
299
+
300
+ test("a hidden page defers its retries and looks again when it returns", async () => {
301
+ const originalVisibility = Object.getOwnPropertyDescriptor(document, "visibilityState");
302
+ let visibility: DocumentVisibilityState = "visible";
303
+ Object.defineProperty(document, "visibilityState", {
304
+ configurable: true,
305
+ get: () => visibility,
306
+ });
307
+ const setVisibility = async (next: DocumentVisibilityState) => {
308
+ visibility = next;
309
+ await act(async () => document.dispatchEvent(new Event("visibilitychange")));
310
+ };
311
+ let failing = true;
312
+ let reads = 0;
313
+ const route = renderRoute(async () => {
314
+ reads += 1;
315
+ if (failing) throw unavailable();
316
+ return session;
317
+ });
318
+ const rendered = await renderComponent(
319
+ route.tree(<SessionUnavailableRoute workspaceId={WORKSPACE_ID} sessionId={SESSION_ID} />),
320
+ );
321
+ try {
322
+ await flush(5_000);
323
+ await setVisibility("hidden");
324
+ await flush(10_000);
325
+ const hiddenReads = reads;
326
+ await flush(120_000);
327
+ expect(reads).toBe(hiddenReads);
328
+
329
+ failing = false;
330
+ await setVisibility("visible");
331
+ await flush(10);
332
+ expect(reads).toBe(hiddenReads + 1);
333
+ expect(route.assigned).toEqual([`/workspaces/${otherWorkspaceId}/sessions/${SESSION_ID}`]);
334
+ } finally {
335
+ await rendered.unmount();
336
+ if (originalVisibility) {
337
+ Object.defineProperty(document, "visibilityState", originalVisibility);
338
+ } else {
339
+ Reflect.deleteProperty(document, "visibilityState");
340
+ }
341
+ }
342
+ });
343
+ });
@@ -1,9 +1,15 @@
1
- import { useEffect, useMemo, useState } from "react";
1
+ import { isTransientRequestError } from "@opengeni/sdk";
2
+ import { useEffect, useMemo, useRef, useState } from "react";
2
3
 
3
4
  import { LoadingPanel, ProblemPanel } from "../components/common";
4
5
  import { Button } from "../../ui/button";
5
6
  import { CrossSlotDeepLinkRecovery } from "../components/cross-slot-deep-link-recovery";
6
7
  import { useAppContext } from "../app-context";
8
+ import {
9
+ DEFAULT_TRANSIENT_READ_RETRY,
10
+ transientReadRetryStep,
11
+ usePageLiveActivity,
12
+ } from "../../hooks/internal";
7
13
  import {
8
14
  authorizedSessionReadWorkspaceIds,
9
15
  canonicalSessionDeepLinkTarget,
@@ -15,7 +21,29 @@ import { usePage } from "../lib/navigation";
15
21
  export function SessionUnavailableRoute(props: { workspaceId: string; sessionId: string }) {
16
22
  const page = usePage();
17
23
  const context = useAppContext();
18
- const [state, setState] = useState<"resolving" | "not-found" | "error">("resolving");
24
+ const [state, setState] = useState<"resolving" | "not-found" | "error" | "transient">(
25
+ "resolving",
26
+ );
27
+ // Each attempt re-runs the lookup; transient failures schedule the next one.
28
+ const [attempt, setAttempt] = useState(0);
29
+ const transientStreakRef = useRef<{
30
+ key: string;
31
+ since: number;
32
+ attempts: number;
33
+ surfaced: boolean;
34
+ } | null>(null);
35
+ // A hidden page defers its next retry until it is visible again, and then
36
+ // looks with a fresh quiet window.
37
+ const pageLive = usePageLiveActivity();
38
+ const pageLiveRef = useRef(pageLive);
39
+ pageLiveRef.current = pageLive;
40
+ const deferredRetryRef = useRef(false);
41
+ useEffect(() => {
42
+ if (!pageLive || !deferredRetryRef.current) return;
43
+ deferredRetryRef.current = false;
44
+ transientStreakRef.current = null;
45
+ setAttempt((value) => value + 1);
46
+ }, [pageLive]);
19
47
  const sessionWorkspaceIds = useMemo(
20
48
  () => authorizedSessionReadWorkspaceIds(context.accessContext, context.workspaces),
21
49
  [context.accessContext, context.workspaces],
@@ -30,7 +58,14 @@ export function SessionUnavailableRoute(props: { workspaceId: string; sessionId:
30
58
 
31
59
  useEffect(() => {
32
60
  let cancelled = false;
33
- setState("resolving");
61
+ let retryTimer: ReturnType<typeof setTimeout> | null = null;
62
+ deferredRetryRef.current = false;
63
+ const key = `${props.workspaceId}\u0000${props.sessionId}`;
64
+ if (transientStreakRef.current?.key !== key) transientStreakRef.current = null;
65
+ // While a transient failure is already shown, background retries keep it.
66
+ setState((current) =>
67
+ current === "transient" && transientStreakRef.current ? current : "resolving",
68
+ );
34
69
  void resolveAuthorizedSessionWorkspace(
35
70
  context.client,
36
71
  context.accessContext.workspaceGrants,
@@ -42,6 +77,7 @@ export function SessionUnavailableRoute(props: { workspaceId: string; sessionId:
42
77
  ).then((resolution) => {
43
78
  if (cancelled) return;
44
79
  if (resolution.status === "resolved") {
80
+ transientStreakRef.current = null;
45
81
  page.assign(
46
82
  canonicalSessionDeepLinkTarget(
47
83
  resolution.workspaceId,
@@ -52,10 +88,31 @@ export function SessionUnavailableRoute(props: { workspaceId: string; sessionId:
52
88
  );
53
89
  return;
54
90
  }
91
+ if (resolution.status === "error" && isTransientRequestError(resolution.error)) {
92
+ // A deploy or network blip: keep looking quietly, and show the problem
93
+ // only if it outlasts the quiet window. Keep retrying afterwards.
94
+ const now = Date.now();
95
+ const streak = (transientStreakRef.current ??= {
96
+ key,
97
+ since: now,
98
+ attempts: 0,
99
+ surfaced: false,
100
+ });
101
+ const step = transientReadRetryStep(streak, now, DEFAULT_TRANSIENT_READ_RETRY);
102
+ if (!step.quiet) setState("transient");
103
+ retryTimer = setTimeout(() => {
104
+ retryTimer = null;
105
+ if (pageLiveRef.current) setAttempt((value) => value + 1);
106
+ else deferredRetryRef.current = true;
107
+ }, step.delayMs);
108
+ return;
109
+ }
110
+ transientStreakRef.current = null;
55
111
  setState(resolution.status === "error" ? "error" : "not-found");
56
112
  });
57
113
  return () => {
58
114
  cancelled = true;
115
+ if (retryTimer !== null) clearTimeout(retryTimer);
59
116
  };
60
117
  }, [
61
118
  page,
@@ -64,9 +121,23 @@ export function SessionUnavailableRoute(props: { workspaceId: string; sessionId:
64
121
  sessionWorkspaceIds,
65
122
  props.sessionId,
66
123
  props.workspaceId,
124
+ attempt,
67
125
  ]);
68
126
 
69
127
  if (state === "resolving") return <LoadingPanel label="Looking for this session" />;
128
+ if (state === "transient") {
129
+ return (
130
+ <ProblemPanel
131
+ title="Temporarily unavailable"
132
+ description="Retrying automatically."
133
+ action={
134
+ <Button type="button" variant="outline" onClick={() => setAttempt((value) => value + 1)}>
135
+ Try again
136
+ </Button>
137
+ }
138
+ />
139
+ );
140
+ }
70
141
  const unavailable = (
71
142
  <ProblemPanel
72
143
  title={state === "error" ? "Session unavailable" : "Session not found"}
@@ -134,7 +134,8 @@ import {
134
134
  } from "react";
135
135
  import { toast } from "../lib/toast";
136
136
 
137
- import { isApiErrorStatus, useAppApi } from "../lib/app-api";
137
+ import { useAppApi } from "../lib/app-api";
138
+ import { useSessionFailureToasts } from "../lib/session-failure-toasts";
138
139
  import { apiErrorFacts, userErrorText } from "../../ui/api-error";
139
140
  import { ConsoleComposer } from "../components/Composer";
140
141
  import { CONSOLE_TIMELINE_ALLOWANCE_LABELS } from "../lib/allowance-labels";
@@ -858,18 +859,7 @@ export function SessionRoute({
858
859
  },
859
860
  [sessionId, sessionEventFeedStore, setContextConnectionState, setContextSession],
860
861
  );
861
- useEffect(() => {
862
- if (streamError && !isApiErrorStatus(streamError, 404)) {
863
- toast.error("Event stream disconnected", {
864
- description: streamError.message,
865
- });
866
- }
867
- }, [streamError]);
868
- useEffect(() => {
869
- if (loadError && !isApiErrorStatus(loadError, 404)) {
870
- toast.error("Failed to load session", { description: String(loadError) });
871
- }
872
- }, [loadError]);
862
+ useSessionFailureToasts(loadError, streamError);
873
863
  // A reconnect OAuth round-trip lands back here (the reconnect card set
874
864
  // returnPath to this session). The connection is refreshed server-side, but
875
865
  // the original tool call was settled as an error and is never replayed. Strip
@@ -1277,6 +1267,7 @@ export function SessionRoute({
1277
1267
  workspaceId={workspaceId}
1278
1268
  sessionId={sessionId}
1279
1269
  loadError={loadError}
1270
+ onRetry={() => void refreshSession()}
1280
1271
  />
1281
1272
  </Suspense>
1282
1273
  );
@@ -1,4 +1,5 @@
1
1
  import { useAppApi } from "../lib/app-api";
2
+ import { useSessionUiFeature } from "../lib/session-ui-features";
2
3
  import { initialWorkspaceMachineCompute } from "../lib/workspace-default-machine";
3
4
  import { t } from "../lib/console-text";
4
5
  import { ANALYTICS_COLLECTION_ENABLED_EVENT } from "../lib/analytics-consent";
@@ -259,6 +260,7 @@ function SessionsIndexRouteContent({
259
260
  const context = useAppContext();
260
261
  const api = useAppApi();
261
262
  const page = usePage();
263
+ const starters = useSessionUiFeature("starters");
262
264
  const connectionAccounts = useConnectionAccounts(
263
265
  context.client,
264
266
  {
@@ -2020,15 +2022,17 @@ function SessionsIndexRouteContent({
2020
2022
  </div>
2021
2023
 
2022
2024
  <RecentSessions workspaceId={workspaceId} />
2023
- <NewSessionStarters
2024
- workspaceId={workspaceId}
2025
- set={signupStarterSet(context.authSession?.user.email, workspace?.accountId)}
2026
- disabled={busy || newSessionDraft.loading}
2027
- onSelect={(prompt) => {
2028
- setMessage(prompt);
2029
- composerRegionRef.current?.querySelector("textarea")?.focus({ preventScroll: true });
2030
- }}
2031
- />
2025
+ {starters ? (
2026
+ <NewSessionStarters
2027
+ workspaceId={workspaceId}
2028
+ set={signupStarterSet(context.authSession?.user.email, workspace?.accountId)}
2029
+ disabled={busy || newSessionDraft.loading}
2030
+ onSelect={(prompt) => {
2031
+ setMessage(prompt);
2032
+ composerRegionRef.current?.querySelector("textarea")?.focus({ preventScroll: true });
2033
+ }}
2034
+ />
2035
+ ) : null}
2032
2036
  </div>
2033
2037
  <ChannelCreateDialog
2034
2038
  open={projectDialogOpen}