@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
@@ -110,12 +110,15 @@ export function RailTrailingMetadata({
110
110
  summary,
111
111
  scheduled = false,
112
112
  relativeTime,
113
+ jumpKey,
113
114
  creator,
114
115
  quickActionSlots = 0,
115
116
  }: {
116
117
  summary: RailAggregateStatus;
117
118
  scheduled?: boolean | undefined;
118
119
  relativeTime?: string | undefined;
120
+ /** The key that opens this row ("⌘3"), shown in place of the time while ⌘ is held. */
121
+ jumpKey?: string | undefined;
119
122
  /** Rightmost items replaced in place by the row's desktop quick actions. */
120
123
  quickActionSlots?: number | undefined;
121
124
  /**
@@ -135,7 +138,14 @@ export function RailTrailingMetadata({
135
138
  summary.kind === "needs_attention" && summary.attentionSince
136
139
  ? formatWaitingSince(summary.attentionSince)
137
140
  : "";
138
- if (!scheduled && !hasStatusMarker && !hasRelativeTime && !hasMonogram && !quickActionSlots)
141
+ if (
142
+ !scheduled &&
143
+ !hasStatusMarker &&
144
+ !hasRelativeTime &&
145
+ !jumpKey &&
146
+ !hasMonogram &&
147
+ !quickActionSlots
148
+ )
139
149
  return null;
140
150
  const items = Children.toArray([
141
151
  scheduled ? (
@@ -163,7 +173,15 @@ export function RailTrailingMetadata({
163
173
  <RailAggregateDot summary={summary} />
164
174
  </span>
165
175
  ) : null,
166
- hasRelativeTime ? (
176
+ jumpKey ? (
177
+ <kbd
178
+ key="time"
179
+ data-session-row-jump-key
180
+ className="inline-flex h-4.5 min-w-9 shrink-0 items-center justify-center rounded-[4px] border border-border bg-surface-2 px-1 font-sans text-2xs leading-none font-medium whitespace-nowrap text-fg-muted"
181
+ >
182
+ {jumpKey}
183
+ </kbd>
184
+ ) : hasRelativeTime ? (
167
185
  <span
168
186
  key="time"
169
187
  className="min-w-9 shrink-0 whitespace-nowrap text-right text-2xs tabular-nums text-fg"
@@ -213,6 +231,7 @@ export function SessionRowContent({
213
231
  summary,
214
232
  scheduled = false,
215
233
  relativeTime,
234
+ jumpKey,
216
235
  creator,
217
236
  quickActionSlots = 0,
218
237
  }: {
@@ -224,6 +243,8 @@ export function SessionRowContent({
224
243
  summary: RailAggregateStatus;
225
244
  scheduled?: boolean | undefined;
226
245
  relativeTime?: string | undefined;
246
+ /** See RailTrailingMetadata. */
247
+ jumpKey?: string | undefined;
227
248
  quickActionSlots?: number | undefined;
228
249
  /** Session creator for a top-level row, else null. See RailTrailingMetadata. */
229
250
  creator?: CreatorRef | null | undefined;
@@ -251,6 +272,7 @@ export function SessionRowContent({
251
272
  summary={summary}
252
273
  scheduled={scheduled}
253
274
  relativeTime={relativeTime}
275
+ jumpKey={jumpKey}
254
276
  creator={creator}
255
277
  />
256
278
  </>
@@ -415,6 +415,7 @@ function SessionShellFrame({ children }: { children: ReactNode }) {
415
415
  function CanvasTopStrip({ hamburgerRef }: { hamburgerRef: RefObject<HTMLButtonElement | null> }) {
416
416
  const rail = useRail();
417
417
  const chatList = useSessionUiFeature("chatList");
418
+ const brand = useSessionUiFeature("brand");
418
419
  const context = useAppContext();
419
420
  const pathname = useRouterState({
420
421
  select: (state) => state.location.pathname,
@@ -490,18 +491,22 @@ function CanvasTopStrip({ hamburgerRef }: { hamburgerRef: RefObject<HTMLButtonEl
490
491
  );
491
492
  }
492
493
 
493
- // Mobile, off a session route: the slim brand strip.
494
+ // Mobile, off a session route: the slim brand strip. A host without
495
+ // Opengeni's brand keeps only the menu button, or no strip at all.
496
+ if (!brand && !hamburger) return null;
494
497
  return (
495
498
  <header className="flex h-12 shrink-0 items-center gap-3 border-b border-border bg-canvas/75 px-3 backdrop-blur sm:px-4">
496
499
  {hamburger}
497
- <Link
498
- to="/workspaces/$workspaceId/sessions"
499
- params={{ workspaceId: rail.workspaceId }}
500
- className="flex items-center gap-2 text-fg"
501
- >
502
- <BrandMark className="w-5" />
503
- <Wordmark className="text-[17px]" />
504
- </Link>
500
+ {brand ? (
501
+ <Link
502
+ to="/workspaces/$workspaceId/sessions"
503
+ params={{ workspaceId: rail.workspaceId }}
504
+ className="flex items-center gap-2 text-fg"
505
+ >
506
+ <BrandMark className="w-5" />
507
+ <Wordmark className="text-[17px]" />
508
+ </Link>
509
+ ) : null}
505
510
  </header>
506
511
  );
507
512
  }
@@ -1,46 +1,85 @@
1
1
  import { Link } from "../../lib/navigation";
2
- import { ChevronDownIcon, ChevronRightIcon, PanelsTopLeftIcon } from "lucide-react";
2
+ import { ChevronRightIcon, PanelsTopLeftIcon } from "lucide-react";
3
3
  import { RailTrailingMetadata } from "./session-row-content";
4
+ import { cn } from "../../lib/utils";
5
+ import { visualTreeDepth } from "../../lib/session-rail";
4
6
  import type { RailAggregateStatus } from "../../lib/sessions-group";
5
7
  import type { SessionSiteOrigin } from "../../lib/session-site-origin";
6
8
 
9
+ /** A Site's row in the rail: open the Site view, or disclose its conversations. */
7
10
  export function SiteSessionGroupHeading({
8
11
  origin,
9
12
  workspaceId,
10
13
  expanded,
11
14
  onToggle,
12
15
  summary,
16
+ count,
17
+ relativeTime,
18
+ depth = 0,
19
+ active = false,
13
20
  }: {
14
21
  origin: SessionSiteOrigin;
15
22
  workspaceId: string;
16
23
  expanded: boolean;
17
24
  onToggle: () => void;
18
25
  summary: RailAggregateStatus;
26
+ /** Conversations behind the row, loaded or not. */
27
+ count: number;
28
+ relativeTime?: string | undefined;
29
+ depth?: number | undefined;
30
+ active?: boolean | undefined;
19
31
  }) {
32
+ const conversations = `${count} ${count === 1 ? "conversation" : "conversations"}`;
33
+ // A Site without conversations is a plain row: nothing to disclose.
34
+ const disclosable = count > 0 || expanded;
20
35
  return (
21
- <div className="flex min-h-8 items-center gap-1 rounded-md px-1 hover:bg-hover">
22
- <button
23
- type="button"
24
- aria-label={`${expanded ? "Collapse" : "Expand"} conversations from ${origin.title}`}
25
- aria-expanded={expanded}
26
- onClick={onToggle}
27
- className="flex size-7 shrink-0 items-center justify-center rounded focus-visible:ring-2 focus-visible:ring-accent"
36
+ <div
37
+ data-site-row={origin.siteId}
38
+ className={cn(
39
+ "group relative flex h-8 w-full items-center gap-1.5 rounded-md border py-1 pr-1 pl-1.5 text-left text-sm pointer-coarse:h-11 pointer-coarse:py-0",
40
+ active
41
+ ? "border-brand/20 bg-selection text-fg"
42
+ : "border-transparent text-fg-label hover:bg-hover hover:text-fg",
43
+ )}
44
+ >
45
+ <span
46
+ className="flex w-4 shrink-0 items-center"
47
+ style={depth > 0 ? { marginLeft: visualTreeDepth(depth) * 12 } : undefined}
28
48
  >
29
- {expanded ? (
30
- <ChevronDownIcon className="size-3" />
31
- ) : (
32
- <ChevronRightIcon className="size-3" />
33
- )}
34
- </button>
49
+ {disclosable ? (
50
+ <button
51
+ type="button"
52
+ aria-label={`${expanded ? "Collapse" : "Expand"} ${conversations} from ${origin.title}`}
53
+ aria-expanded={expanded}
54
+ onClick={onToggle}
55
+ className="flex h-4 w-4 shrink-0 items-center justify-center rounded text-fg-muted outline-hidden hover:text-fg focus-visible:ring-1 focus-visible:ring-ring pointer-coarse:h-11 pointer-coarse:w-11"
56
+ >
57
+ <ChevronRightIcon
58
+ className={cn("size-3 shrink-0 transition-transform", expanded && "rotate-90")}
59
+ />
60
+ </button>
61
+ ) : null}
62
+ </span>
35
63
  <Link
36
- className="flex min-w-0 flex-1 items-center gap-1.5 text-sm focus-visible:ring-2 focus-visible:ring-accent"
37
- to="/workspaces/$workspaceId/artifacts/$artifactId"
38
- params={{ workspaceId, artifactId: origin.siteId }}
64
+ to="/workspaces/$workspaceId/sites/$siteId"
65
+ params={{ workspaceId, siteId: origin.siteId }}
66
+ // The Site is the open page only while none of its conversations is.
67
+ activeOptions={{ exact: true, includeSearch: true }}
68
+ aria-current={active ? "page" : undefined}
69
+ // Without conversations there is no status to announce.
70
+ aria-label={`Open ${origin.title}. Site${count > 0 ? `, ${conversations}. ${summary.label}` : ""}`}
71
+ className="flex h-full min-w-0 flex-1 items-center gap-1.5 rounded-sm outline-hidden focus-visible:ring-2 focus-visible:ring-ring/40 focus-visible:ring-offset-1 focus-visible:ring-offset-surface"
39
72
  >
40
- <PanelsTopLeftIcon className="size-3.5 shrink-0" aria-hidden="true" />
41
- <span className="truncate">{origin.title}</span>
73
+ <PanelsTopLeftIcon aria-hidden="true" className="size-3.5 shrink-0 text-fg-muted" />
74
+ <span className="min-w-0 truncate">{origin.title}</span>
75
+ {count > 0 ? (
76
+ <span aria-hidden="true" className="shrink-0 text-xs tabular-nums text-fg-subtle">
77
+ {count}
78
+ </span>
79
+ ) : null}
80
+ <span className="min-w-0 flex-1" />
81
+ <RailTrailingMetadata summary={summary} relativeTime={relativeTime} />
42
82
  </Link>
43
- <RailTrailingMetadata summary={summary} />
44
83
  </div>
45
84
  );
46
85
  }
@@ -1,4 +1,5 @@
1
1
  import type { OpenGeniBrowserClient } from "@opengeni/sdk/browser";
2
+ import { isTransientRequestError } from "@opengeni/sdk";
2
3
  import type {
3
4
  Session,
4
5
  SessionEvent,
@@ -85,12 +86,29 @@ export default function SessionRouteAuxiliary(
85
86
  workspaceId: string;
86
87
  sessionId: string;
87
88
  loadError: unknown;
89
+ /** Retry the session read now (it also keeps retrying in the background). */
90
+ onRetry?: (() => void) | undefined;
88
91
  session?: never | undefined;
89
92
  events?: never | undefined;
90
93
  },
91
94
  ) {
92
95
  return props.session ? (
93
96
  <SessionTenancyRouteControl session={props.session} events={props.events} />
97
+ ) : isTransientRequestError(props.loadError) ? (
98
+ // The session read has failed transiently for a while (an outage outlasting
99
+ // a rolling deploy). The read keeps retrying and the page opens the session
100
+ // on its own when it succeeds.
101
+ <ProblemPanel
102
+ title="Temporarily unavailable"
103
+ description="Retrying automatically."
104
+ action={
105
+ props.onRetry ? (
106
+ <Button type="button" variant="outline" onClick={props.onRetry}>
107
+ Try again
108
+ </Button>
109
+ ) : undefined
110
+ }
111
+ />
94
112
  ) : !isApiErrorStatus(props.loadError, 404) ? (
95
113
  <ProblemPanel
96
114
  title="Unable to open session"
@@ -0,0 +1,73 @@
1
+ import { afterAll, beforeAll, expect, mock, test } from "bun:test";
2
+ import { GlobalRegistrator } from "@happy-dom/global-registrator";
3
+ import type { ReactNode } from "react";
4
+ import { renderToStaticMarkup } from "react-dom/server";
5
+ import type { Session } from "../../types";
6
+
7
+ const workspaceId = "11111111-1111-4111-8111-111111111111";
8
+ const siteId = "22222222-2222-4222-8222-222222222222";
9
+ const sessionId = "33333333-3333-4333-8333-333333333333";
10
+
11
+ mock.module("../../lib/navigation", () => ({
12
+ Link: ({
13
+ children,
14
+ to,
15
+ params,
16
+ search,
17
+ }: {
18
+ children: ReactNode;
19
+ to: string;
20
+ params: Record<string, string>;
21
+ search?: Record<string, string>;
22
+ }) => <a href={JSON.stringify({ to, params, search: search ?? null })}>{children}</a>,
23
+ }));
24
+
25
+ let module: typeof import("./site-origin-link");
26
+ let ownsDom = false;
27
+ beforeAll(async () => {
28
+ ownsDom = !GlobalRegistrator.isRegistered;
29
+ if (ownsDom) GlobalRegistrator.register({ url: "https://example.test" });
30
+ module = await import("./site-origin-link");
31
+ });
32
+ afterAll(async () => {
33
+ if (ownsDom) await GlobalRegistrator.unregister();
34
+ });
35
+
36
+ const session = (parentSessionId: string | null) =>
37
+ ({
38
+ id: sessionId,
39
+ workspaceId,
40
+ parentSessionId,
41
+ metadata: { _opengeniSiteOrigin: { siteId, title: "Opengeni usage" } },
42
+ }) as unknown as Session;
43
+ const target = (markup: string) => {
44
+ const container = document.createElement("div");
45
+ container.innerHTML = markup;
46
+ return JSON.parse(container.querySelector("a")!.getAttribute("href")!);
47
+ };
48
+
49
+ test("a Site's own conversation opens the Site with it selected", () => {
50
+ expect(target(renderToStaticMarkup(<module.SiteOriginLink session={session(null)} />))).toEqual({
51
+ to: "/workspaces/$workspaceId/sites/$siteId",
52
+ params: { workspaceId, siteId },
53
+ search: { conversation: sessionId },
54
+ });
55
+ });
56
+
57
+ test("a session spawned inside one opens the Site without selecting it", () => {
58
+ expect(
59
+ target(renderToStaticMarkup(<module.SiteOriginLink session={session(sessionId)} />)),
60
+ ).toEqual({
61
+ to: "/workspaces/$workspaceId/sites/$siteId",
62
+ params: { workspaceId, siteId },
63
+ search: null,
64
+ });
65
+ });
66
+
67
+ test("a session that didn't start in a Site has no link", () => {
68
+ expect(
69
+ renderToStaticMarkup(
70
+ <module.SiteOriginLink session={{ ...session(null), metadata: {} } as Session} />,
71
+ ),
72
+ ).toBe("");
73
+ });
@@ -2,6 +2,7 @@ import { Link } from "../../lib/navigation";
2
2
  import { PanelsTopLeftIcon } from "lucide-react";
3
3
  import { sessionSiteOrigin } from "../../lib/session-site-origin";
4
4
  import type { RailSession as Session } from "../../lib/session-list-entry";
5
+ /** Where a session came from: opens its Site view with this conversation selected. */
5
6
  export function SiteOriginLink({
6
7
  session,
7
8
  compact = false,
@@ -13,8 +14,9 @@ export function SiteOriginLink({
13
14
  if (!origin) return null;
14
15
  return (
15
16
  <Link
16
- to="/workspaces/$workspaceId/artifacts/$artifactId"
17
- params={{ workspaceId: session.workspaceId, artifactId: origin.siteId }}
17
+ to="/workspaces/$workspaceId/sites/$siteId"
18
+ params={{ workspaceId: session.workspaceId, siteId: origin.siteId }}
19
+ search={session.parentSessionId === null ? { conversation: session.id } : undefined}
18
20
  title={`Created through ${origin.title}`}
19
21
  aria-label={`Created through ${origin.title}. Open Site`}
20
22
  className="inline-flex shrink-0 items-center gap-1 rounded px-1 py-1 text-xs text-fg-muted hover:bg-surface-2 hover:text-fg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent"
@@ -177,6 +177,7 @@ function createMemoryNavigation(options: MemoryNavigationOptions): NavigationHos
177
177
  reloadDocument: _reloadDocument,
178
178
  href: hrefOption,
179
179
  preload: _preload,
180
+ activeOptions: _activeOptions,
180
181
  disabled,
181
182
  children,
182
183
  onClick,
@@ -0,0 +1,101 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import { createHeldModifierTracker } from "./held-modifier";
4
+
5
+ function harness(platform: "mac" | "other" = "mac") {
6
+ const listeners = new Map<string, Set<(event: Event) => void>>();
7
+ const target = {
8
+ addEventListener: (type: string, listener: (event: Event) => void) => {
9
+ if (!listeners.has(type)) listeners.set(type, new Set());
10
+ listeners.get(type)!.add(listener);
11
+ },
12
+ removeEventListener: (type: string, listener: (event: Event) => void) => {
13
+ listeners.get(type)?.delete(listener);
14
+ },
15
+ } as unknown as Pick<Window, "addEventListener" | "removeEventListener">;
16
+ let pending: (() => void) | null = null;
17
+ const timers = {
18
+ setTimeout: ((callback: () => void) => {
19
+ pending = callback;
20
+ return 1;
21
+ }) as unknown as typeof setTimeout,
22
+ clearTimeout: (() => {
23
+ pending = null;
24
+ }) as unknown as typeof clearTimeout,
25
+ };
26
+ const tracker = createHeldModifierTracker(target, platform, timers);
27
+ let changes = 0;
28
+ const unsubscribe = tracker.subscribe(() => changes++);
29
+ const fire = (type: string, init: Partial<KeyboardEvent> = {}) => {
30
+ for (const listener of listeners.get(type) ?? []) listener(init as unknown as Event);
31
+ };
32
+ return {
33
+ tracker,
34
+ fire,
35
+ elapse: () => {
36
+ const callback = pending;
37
+ pending = null;
38
+ callback?.();
39
+ },
40
+ changes: () => changes,
41
+ unsubscribe,
42
+ listenerCount: () => [...listeners.values()].reduce((sum, set) => sum + set.size, 0),
43
+ };
44
+ }
45
+
46
+ describe("held modifier", () => {
47
+ test("shows after ⌘ is held alone, hides on release", () => {
48
+ const h = harness();
49
+ h.fire("keydown", { key: "Meta", metaKey: true });
50
+ expect(h.tracker.held()).toBe(false);
51
+ h.elapse();
52
+ expect(h.tracker.held()).toBe(true);
53
+ h.fire("keyup", { key: "Meta" });
54
+ expect(h.tracker.held()).toBe(false);
55
+ expect(h.changes()).toBe(2);
56
+ });
57
+
58
+ test("a quick ⌘ shortcut never shows the hint", () => {
59
+ const h = harness();
60
+ h.fire("keydown", { key: "Meta", metaKey: true });
61
+ h.fire("keydown", { key: "c", code: "KeyC", metaKey: true });
62
+ h.elapse();
63
+ expect(h.tracker.held()).toBe(false);
64
+ });
65
+
66
+ test("another key or leaving the window hides it", () => {
67
+ const h = harness();
68
+ h.fire("keydown", { key: "Meta", metaKey: true });
69
+ h.elapse();
70
+ h.fire("keydown", { key: "1", code: "Digit1", metaKey: true });
71
+ expect(h.tracker.held()).toBe(false);
72
+ h.fire("keydown", { key: "Meta", metaKey: true });
73
+ h.elapse();
74
+ h.fire("blur");
75
+ expect(h.tracker.held()).toBe(false);
76
+ });
77
+
78
+ test("⌘ with other modifiers is not the hint", () => {
79
+ const h = harness();
80
+ h.fire("keydown", { key: "Meta", metaKey: true, shiftKey: true });
81
+ h.elapse();
82
+ expect(h.tracker.held()).toBe(false);
83
+ });
84
+
85
+ test("Ctrl is the key on Windows and Linux", () => {
86
+ const h = harness("other");
87
+ h.fire("keydown", { key: "Meta", metaKey: true });
88
+ h.elapse();
89
+ expect(h.tracker.held()).toBe(false);
90
+ h.fire("keydown", { key: "Control", ctrlKey: true });
91
+ h.elapse();
92
+ expect(h.tracker.held()).toBe(true);
93
+ });
94
+
95
+ test("stops listening when the last row goes away", () => {
96
+ const h = harness();
97
+ expect(h.listenerCount()).toBeGreaterThan(0);
98
+ h.unsubscribe();
99
+ expect(h.listenerCount()).toBe(0);
100
+ });
101
+ });
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Whether ⌘ (Mac) or Ctrl (elsewhere) is being held on its own, so the page
3
+ * can show which keys it unlocks: the pinned chats show ⌘1 to ⌘9.
4
+ *
5
+ * The hint waits a moment before appearing, so a quick ⌘C or ⌘K never flashes
6
+ * it, and it goes away on release, on any other key, and when the window loses
7
+ * focus (⌘Tab to another app releases the key where the page can't see it).
8
+ */
9
+ import { useSyncExternalStore } from "react";
10
+
11
+ import type { ChordPlatform } from "./chords";
12
+
13
+ export const HELD_MODIFIER_DELAY_MS = 350;
14
+
15
+ type HeldModifierTracker = {
16
+ subscribe(listener: () => void): () => void;
17
+ held(): boolean;
18
+ };
19
+
20
+ /** One tracker per window and platform; every row reads the same state. */
21
+ export function createHeldModifierTracker(
22
+ target: Pick<Window, "addEventListener" | "removeEventListener">,
23
+ platform: ChordPlatform,
24
+ timers: Pick<typeof globalThis, "setTimeout" | "clearTimeout"> = globalThis,
25
+ ): HeldModifierTracker {
26
+ const modifierKey = platform === "mac" ? "Meta" : "Control";
27
+ const listeners = new Set<() => void>();
28
+ let held = false;
29
+ let timer: ReturnType<typeof setTimeout> | null = null;
30
+
31
+ const set = (next: boolean) => {
32
+ if (held === next) return;
33
+ held = next;
34
+ for (const listener of listeners) listener();
35
+ };
36
+ const reset = () => {
37
+ if (timer !== null) timers.clearTimeout(timer);
38
+ timer = null;
39
+ set(false);
40
+ };
41
+ const onKeyDown = (event: Event) => {
42
+ const keyEvent = event as KeyboardEvent;
43
+ const alone =
44
+ keyEvent.key === modifierKey &&
45
+ !keyEvent.shiftKey &&
46
+ !keyEvent.altKey &&
47
+ (platform === "mac" ? !keyEvent.ctrlKey : !keyEvent.metaKey);
48
+ if (!alone) {
49
+ reset();
50
+ return;
51
+ }
52
+ if (keyEvent.repeat || held || timer !== null) return;
53
+ timer = timers.setTimeout(() => {
54
+ timer = null;
55
+ set(true);
56
+ }, HELD_MODIFIER_DELAY_MS);
57
+ };
58
+ const onKeyUp = (event: Event) => {
59
+ if ((event as KeyboardEvent).key === modifierKey) reset();
60
+ };
61
+ const onVisibility = () => reset();
62
+
63
+ return {
64
+ subscribe(listener) {
65
+ listeners.add(listener);
66
+ if (listeners.size === 1) {
67
+ target.addEventListener("keydown", onKeyDown, true);
68
+ target.addEventListener("keyup", onKeyUp, true);
69
+ target.addEventListener("blur", reset);
70
+ target.addEventListener("visibilitychange", onVisibility);
71
+ target.addEventListener("pointerdown", reset, true);
72
+ }
73
+ return () => {
74
+ listeners.delete(listener);
75
+ if (listeners.size > 0) return;
76
+ target.removeEventListener("keydown", onKeyDown, true);
77
+ target.removeEventListener("keyup", onKeyUp, true);
78
+ target.removeEventListener("blur", reset);
79
+ target.removeEventListener("visibilitychange", onVisibility);
80
+ target.removeEventListener("pointerdown", reset, true);
81
+ if (timer !== null) timers.clearTimeout(timer);
82
+ timer = null;
83
+ held = false;
84
+ };
85
+ },
86
+ held: () => held,
87
+ };
88
+ }
89
+
90
+ const trackers = new Map<ChordPlatform, HeldModifierTracker>();
91
+
92
+ function windowTracker(platform: ChordPlatform): HeldModifierTracker | null {
93
+ if (typeof window === "undefined") return null;
94
+ let tracker = trackers.get(platform);
95
+ if (!tracker) {
96
+ tracker = createHeldModifierTracker(window, platform);
97
+ trackers.set(platform, tracker);
98
+ }
99
+ return tracker;
100
+ }
101
+
102
+ const NEVER: HeldModifierTracker = { subscribe: () => () => {}, held: () => false };
103
+
104
+ /** True while ⌘ (Ctrl elsewhere) is held alone; `enabled: false` never listens. */
105
+ export function useHeldModifier(platform: ChordPlatform, enabled: boolean): boolean {
106
+ const tracker = (enabled ? windowTracker(platform) : null) ?? NEVER;
107
+ return useSyncExternalStore(tracker.subscribe, tracker.held, () => false);
108
+ }
@@ -0,0 +1,38 @@
1
+ import type { SiteViewer } from "@opengeni/sdk";
2
+ import { useCallback, useMemo } from "react";
3
+ import type { SiteToolBridgeFactory } from "../../artifacts";
4
+ import { useAppContext } from "../app-context";
5
+ import { useAppApi } from "./app-api";
6
+ import { createSiteToolBridge } from "./site-tool-bridge";
7
+
8
+ /** The signed-in member as Site code sees them (`site.viewer`) in the console. */
9
+ export function useConsoleSiteViewer(): SiteViewer {
10
+ const { accessContext, authSession } = useAppContext();
11
+ const subjectId = accessContext.subjectId;
12
+ const name = authSession?.user?.name ?? null;
13
+ const email = authSession?.user?.email ?? null;
14
+ return useMemo(
15
+ () => ({ kind: "member", id: `user:${subjectId}`, name, email, signedIn: true }),
16
+ [email, name, subjectId],
17
+ );
18
+ }
19
+
20
+ /** Console tool access for a `SiteView`, pinned to the loaded Site version. */
21
+ export function useConsoleSiteToolBridge(workspaceId: string): SiteToolBridgeFactory {
22
+ const { client } = useAppContext();
23
+ const api = useAppApi();
24
+ return useCallback<SiteToolBridgeFactory>(
25
+ (site) => {
26
+ const scope = { workspaceTools: client.tools.forWorkspace(workspaceId), workspaceId };
27
+ return site
28
+ ? createSiteToolBridge(api, {
29
+ ...scope,
30
+ artifactId: site.artifactId,
31
+ siteVersionId: site.siteVersionId,
32
+ requestedTools: site.requestedTools,
33
+ })
34
+ : createSiteToolBridge(api, scope);
35
+ },
36
+ [api, client, workspaceId],
37
+ );
38
+ }
@@ -55,6 +55,10 @@ export type LinkProps = NavigateOptions &
55
55
  | undefined;
56
56
  preload?: false | "intent" | "viewport" | "render" | undefined;
57
57
  disabled?: boolean | undefined;
58
+ /** When the link counts as the current page (`aria-current`); the router's default otherwise. */
59
+ activeOptions?:
60
+ | { exact?: boolean | undefined; includeSearch?: boolean | undefined }
61
+ | undefined;
58
62
  ref?: Ref<HTMLAnchorElement> | undefined;
59
63
  };
60
64
 
@@ -106,3 +106,45 @@ export function artifactReturnSearch(search: Record<string, unknown>): ArtifactR
106
106
  : undefined,
107
107
  };
108
108
  }
109
+
110
+ const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu;
111
+
112
+ /** The Site view: the Site with its conversations beside it, one of them open. */
113
+ export type SiteViewSearch = { conversation?: string | undefined };
114
+
115
+ export function siteViewSearch(search: Record<string, unknown>): SiteViewSearch {
116
+ return {
117
+ conversation:
118
+ typeof search.conversation === "string" && UUID.test(search.conversation)
119
+ ? search.conversation
120
+ : undefined,
121
+ };
122
+ }
123
+
124
+ export function workspaceSitePath(
125
+ workspaceId: string,
126
+ siteId: string,
127
+ conversation?: string | undefined,
128
+ ): string {
129
+ const path = `${workspacePath(workspaceId)}/sites/${encodeURIComponent(siteId)}`;
130
+ return conversation ? `${path}?conversation=${encodeURIComponent(conversation)}` : path;
131
+ }
132
+
133
+ /**
134
+ * What the rail marks as open for a location: a session page's session, or a
135
+ * Site view's Site and its selected conversation.
136
+ */
137
+ export function railRouteSelection(location: {
138
+ pathname: string;
139
+ search: Record<string, unknown>;
140
+ }): { sessionId: string | null; siteId: string | null } {
141
+ const session = /\/sessions\/([^/]+)/u.exec(location.pathname);
142
+ if (session) return { sessionId: session[1] ?? null, siteId: null };
143
+ const site = /^\/workspaces\/[^/]+\/sites\/([^/]+)\/?$/u.exec(location.pathname);
144
+ // Site ids are UUIDs; anything else (including a malformed escape) is no Site.
145
+ if (!site || !UUID.test(site[1] ?? "")) return { sessionId: null, siteId: null };
146
+ return {
147
+ sessionId: siteViewSearch(location.search).conversation ?? null,
148
+ siteId: site[1]!.toLowerCase(),
149
+ };
150
+ }