@opengeni/react 4.3.3-canary.39786771332001 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (710) hide show
  1. package/dist/app/app-state.js +29 -29
  2. package/dist/app/components/Composer.js +27 -27
  3. package/dist/app/components/agent/agent-capability-picker.js +4 -4
  4. package/dist/app/components/artifacts/artifact-browse-controls.js +2 -2
  5. package/dist/app/components/artifacts/artifact-library.js +19 -19
  6. package/dist/app/components/artifacts/artifact-page-chrome.js +2 -2
  7. package/dist/app/components/artifacts/chat-interactive-block.js +16 -16
  8. package/dist/app/components/artifacts/inline-chat-image.js +31 -30
  9. package/dist/app/components/artifacts/retained-file-preview.js +35 -34
  10. package/dist/app/components/artifacts/retained-text-preview.js +5 -5
  11. package/dist/app/components/artifacts/site-audience.js +4 -4
  12. package/dist/app/components/artifacts/site-conversations.js +22 -21
  13. package/dist/app/components/artifacts/site-data.js +19 -19
  14. package/dist/app/components/artifacts/site-publishing.js +41 -41
  15. package/dist/app/components/artifacts/site-settings.js +50 -50
  16. package/dist/app/components/billing-class-mark.js +5 -5
  17. package/dist/app/components/capabilities/capability-detail-sheet.js +9 -9
  18. package/dist/app/components/capabilities/capability-logo-source.js +12 -12
  19. package/dist/app/components/capabilities/connector-tool-permissions.js +3 -3
  20. package/dist/app/components/capabilities/native-connect-setup.js +14 -14
  21. package/dist/app/components/capabilities/perform-capability-action.js +1 -1
  22. package/dist/app/components/capabilities/prepared-mcp-setup-card.js +16 -16
  23. package/dist/app/components/capabilities/session-capability-card.js +94 -76
  24. package/dist/app/components/capabilities/session-capability-card.js.map +1 -1
  25. package/dist/app/components/capabilities/session-chrome-card.css +1023 -0
  26. package/dist/app/components/capabilities/session-chrome-card.css.map +1 -0
  27. package/dist/app/components/capabilities/session-chrome-card.d.ts +18 -0
  28. package/dist/app/components/capabilities/session-chrome-card.js +72 -0
  29. package/dist/app/components/capabilities/session-custom-mcp-card.js +20 -20
  30. package/dist/app/components/capabilities/session-github-card.js +24 -24
  31. package/dist/app/components/capabilities/session-machine-card.d.ts +27 -1
  32. package/dist/app/components/capabilities/session-machine-card.js +40 -36
  33. package/dist/app/components/capabilities/use-capabilities-catalog.js +3 -3
  34. package/dist/app/components/capabilities/use-connection-accounts.js +1 -1
  35. package/dist/app/components/command-menu/chat-status.js +18 -17
  36. package/dist/app/components/command-menu/chat-switcher.js +19 -18
  37. package/dist/app/components/command-menu/chat-switcher.js.map +1 -1
  38. package/dist/app/components/command-menu/command-menu.js +36 -114
  39. package/dist/app/components/command-menu/command-menu.js.map +1 -1
  40. package/dist/app/components/command-menu/shortcut-sheet.js +17 -17
  41. package/dist/app/components/composer-capabilities-menu-body.js +3 -3
  42. package/dist/app/components/composer-mobile-plus-panel.js +20 -20
  43. package/dist/app/components/composer-mobile-plus.js +1 -1
  44. package/dist/app/components/credit-required-gate.js +1 -1
  45. package/dist/app/components/credit-required-prompt.js +12 -12
  46. package/dist/app/components/credits/coupon-redeem.js +2 -2
  47. package/dist/app/components/credits/credit-refusal-notice.js +2 -2
  48. package/dist/app/components/desktop/app-shots.js +7 -7
  49. package/dist/app/components/desktop/this-computer.js +4 -4
  50. package/dist/app/components/feedback.js +4 -4
  51. package/dist/app/components/follow-up-repository-menu-body.js +5 -5
  52. package/dist/app/components/follow-up-repository-picker.js +1 -1
  53. package/dist/app/components/github-app-connect-launcher.js +2 -2
  54. package/dist/app/components/in-app-help-link.js +2 -2
  55. package/dist/app/components/knowledge/agent-learning-settings.js +3 -3
  56. package/dist/app/components/machines/connect-machine-dialog.js +18 -18
  57. package/dist/app/components/markdown.js +9 -9
  58. package/dist/app/components/message-context-pills.js +2 -2
  59. package/dist/app/components/models/models-ui.js +8 -8
  60. package/dist/app/components/new-session-starters.js +2 -2
  61. package/dist/app/components/pickers.js +9 -9
  62. package/dist/app/components/rail/rail-context.js +2 -2
  63. package/dist/app/components/rail/rail-sections.js +69 -66
  64. package/dist/app/components/rail/session-header.js +49 -48
  65. package/dist/app/components/rail/session-list.js +68 -65
  66. package/dist/app/components/rail/session-row-content.d.ts +6 -2
  67. package/dist/app/components/rail/session-row-content.js +1 -1
  68. package/dist/app/components/rail/session-row-hover-details.js +24 -23
  69. package/dist/app/components/rail/session-shell.js +107 -104
  70. package/dist/app/components/rail/site-session-group-heading.d.ts +7 -1
  71. package/dist/app/components/rail/site-session-group-heading.js +20 -3
  72. package/dist/app/components/repository-picker.js +5 -5
  73. package/dist/app/components/secrets/session-secrets-panel.js +3 -3
  74. package/dist/app/components/session/agent-configuration-panel.js +38 -38
  75. package/dist/app/components/session/artifact-link-boundary.js +2 -2
  76. package/dist/app/components/session/artifact-session-page.js +4 -4
  77. package/dist/app/components/session/banners.js +11 -11
  78. package/dist/app/components/session/codex-account-indicator.js +12 -12
  79. package/dist/app/components/session/editable-artifacts-workspace.js +45 -45
  80. package/dist/app/components/session/failed-session-banner.js +11 -11
  81. package/dist/app/components/session/human-input.js +59 -55
  82. package/dist/app/components/session/inspector.js +91 -87
  83. package/dist/app/components/session/inspector.js.map +1 -1
  84. package/dist/app/components/session/message-actions.js +4 -4
  85. package/dist/app/components/session/message-resource-attachments.js +21 -20
  86. package/dist/app/components/session/message-resource-attachments.js.map +1 -1
  87. package/dist/app/components/session/model-account-indicator.js +11 -11
  88. package/dist/app/components/session/model-context-inspector.js +2 -2
  89. package/dist/app/components/session/model-recovery-notice.js +3 -3
  90. package/dist/app/components/session/new-session-settings-menu.js +12 -12
  91. package/dist/app/components/session/sandbox-switcher.js +16 -16
  92. package/dist/app/components/session/sandbox-workspace.js +83 -79
  93. package/dist/app/components/session/search-markdown-highlight.js +10 -10
  94. package/dist/app/components/session/search-results-view.js +11 -11
  95. package/dist/app/components/session/session-admin-access.js +9 -9
  96. package/dist/app/components/session/session-admission-notice.js +6 -6
  97. package/dist/app/components/session/session-machine-access-notice.js +6 -6
  98. package/dist/app/components/session/session-retention.js +4 -4
  99. package/dist/app/components/session/session-search-dialog.js +12 -12
  100. package/dist/app/components/session/session-skill-reviews.js +1 -1
  101. package/dist/app/components/session/session-tenancy-control.d.ts +2 -0
  102. package/dist/app/components/session/session-tenancy-control.js +41 -26
  103. package/dist/app/components/session/session-tenancy-control.js.map +1 -1
  104. package/dist/app/components/session/session-usage-limit-section.js +11 -11
  105. package/dist/app/components/session/session-wait-status.js +10 -9
  106. package/dist/app/components/session/session-wait-status.js.map +1 -1
  107. package/dist/app/components/session/site-origin-link.d.ts +1 -0
  108. package/dist/app/components/session/site-origin-link.js +2 -2
  109. package/dist/app/components/session/subagents.js +17 -16
  110. package/dist/app/components/session-connectors-menu-body.js +5 -5
  111. package/dist/app/components/settings/row-select.js +1 -1
  112. package/dist/app/components/transcription-settings.js +2 -2
  113. package/dist/app/components/ui/destructive-confirm.js +6 -6
  114. package/dist/app/components/usage/usage-entry.js +8 -8
  115. package/dist/app/components/workspace-composer-plus.js +22 -22
  116. package/dist/app/embed/memory-navigation.js +2 -2
  117. package/dist/app/embed/session-app.js +275 -269
  118. package/dist/app/lib/actions/actions-provider.js +14 -14
  119. package/dist/app/lib/actions/held-modifier.d.ts +11 -0
  120. package/dist/app/lib/app-surfaces.js +2 -2
  121. package/dist/app/lib/codex-usage-query.js +6 -6
  122. package/dist/app/lib/composer-connectors.js +13 -13
  123. package/dist/app/lib/console-site.d.ts +6 -0
  124. package/dist/app/lib/console-site.js +14 -0
  125. package/dist/app/lib/console-text.js +2 -2
  126. package/dist/app/lib/events.js +18 -17
  127. package/dist/app/lib/failed-session-copy.js +3 -3
  128. package/dist/app/lib/model-access-onboarding.js +3 -3
  129. package/dist/app/lib/move-chat-to-machine.js +3 -3
  130. package/dist/app/lib/navigation.d.ts +5 -0
  131. package/dist/app/lib/navigation.js +1 -1
  132. package/dist/app/lib/routes.d.ts +17 -0
  133. package/dist/app/lib/routes.js +9 -3
  134. package/dist/app/lib/session-branch-cache.js +14 -13
  135. package/dist/app/lib/session-create.js +2 -2
  136. package/dist/app/lib/session-deep-link.js +2 -2
  137. package/dist/app/lib/session-failure-toasts.d.ts +8 -0
  138. package/dist/app/lib/session-group-pagination.js +14 -13
  139. package/dist/app/lib/session-hover-facts.js +15 -14
  140. package/dist/app/lib/session-model.js +3 -3
  141. package/dist/app/lib/session-rail.js +10 -9
  142. package/dist/app/lib/session-rename.js +3 -3
  143. package/dist/app/lib/session-ui-features.d.ts +6 -1
  144. package/dist/app/lib/session-ui-features.js +1 -1
  145. package/dist/app/lib/sessions-group.d.ts +43 -3
  146. package/dist/app/lib/sessions-group.js +22 -15
  147. package/dist/app/lib/shared-query.js +3 -3
  148. package/dist/app/lib/site-opened.d.ts +6 -0
  149. package/dist/app/lib/site-opened.js +10 -0
  150. package/dist/app/lib/turn-failure-analytics.js +5 -5
  151. package/dist/app/lib/use-duplicate-site.js +3 -3
  152. package/dist/app/lib/use-follow-up-repositories.js +4 -4
  153. package/dist/app/lib/use-session-list-hint-refresh.d.ts +20 -2
  154. package/dist/app/lib/use-session-list-hint-refresh.js +5 -1
  155. package/dist/app/lib/use-workspace-machines.js +6 -6
  156. package/dist/app/lib/use-workspace-model-catalog.js +8 -8
  157. package/dist/app/lib/use-workspace-rigs.js +8 -8
  158. package/dist/app/lib/workspace-navigation-preference.js +5 -5
  159. package/dist/app/lib/workspace-scope-context.js +4 -4
  160. package/dist/app/routes/artifacts.js +136 -153
  161. package/dist/app/routes/artifacts.js.map +1 -1
  162. package/dist/app/routes/retained-artifact.js +63 -62
  163. package/dist/app/routes/retained-artifact.js.map +1 -1
  164. package/dist/app/routes/session-unavailable.js +7 -5
  165. package/dist/app/routes/session.js +177 -173
  166. package/dist/app/routes/sessions-index-hydration.js +3 -3
  167. package/dist/app/routes/sessions-index.js +123 -121
  168. package/dist/app/routes/site-view.d.ts +11 -0
  169. package/dist/app/routes/site-view.js +597 -0
  170. package/dist/app/routes/site-view.js.map +1 -0
  171. package/dist/artifacts-document.js +4 -4
  172. package/dist/artifacts-presentation.js +4 -4
  173. package/dist/artifacts-spreadsheet.js +4 -4
  174. package/dist/artifacts.js +39 -39
  175. package/dist/{browser-viewer-RYYQSRTC.js → browser-viewer-QMCNV4RI.js} +9 -7
  176. package/dist/{chat-interactive-block-ABCRKXJ4.js → chat-interactive-block-PMIAUXSO.js} +6 -6
  177. package/dist/{chunk-GIZGNFIX.js → chunk-22FFOHPT.js} +11 -11
  178. package/dist/chunk-22GTC4MZ.js +15 -0
  179. package/dist/chunk-22GTC4MZ.js.map +1 -0
  180. package/dist/{chunk-Z5WMLJKI.js → chunk-22JFMNMF.js} +92 -4
  181. package/dist/chunk-22JFMNMF.js.map +1 -0
  182. package/dist/{chunk-UHFWF6ZU.js → chunk-2FPS5H2D.js} +2 -2
  183. package/dist/{chunk-NAWXARTY.js → chunk-2KO2G3RI.js} +72 -6
  184. package/dist/chunk-2KO2G3RI.js.map +1 -0
  185. package/dist/{chunk-5POTDNQT.js → chunk-2NC7NZCE.js} +6 -6
  186. package/dist/{chunk-ZKYYZH6L.js → chunk-2QBYDGWO.js} +9 -9
  187. package/dist/{chunk-TWXIFWBD.js → chunk-34EU25RL.js} +2 -2
  188. package/dist/{chunk-LQKKSUCR.js → chunk-35BC2FU2.js} +19 -19
  189. package/dist/{chunk-PTGRFAMH.js → chunk-3ABPIUCK.js} +2 -2
  190. package/dist/{chunk-S4SC5SSV.js → chunk-3GU7AWG7.js} +18 -18
  191. package/dist/{chunk-722UO6YQ.js → chunk-3PEXVG4D.js} +2 -2
  192. package/dist/{chunk-OQAAI33Y.js → chunk-3RMKPHBL.js} +3 -3
  193. package/dist/{chunk-6JKZILLF.js → chunk-3RQUWFZT.js} +67 -67
  194. package/dist/{chunk-6JKZILLF.js.map → chunk-3RQUWFZT.js.map} +1 -1
  195. package/dist/{chunk-GCGTYXJJ.js → chunk-3STBLX4O.js} +9 -9
  196. package/dist/{chunk-YXIW7H4N.js → chunk-3X5FKDYQ.js} +28 -28
  197. package/dist/{chunk-KTRKZRID.js → chunk-4GLLWX33.js} +11 -11
  198. package/dist/{chunk-ROQOVH4N.js → chunk-4HEXNAFI.js} +20 -20
  199. package/dist/chunk-4HEXNAFI.js.map +1 -0
  200. package/dist/{chunk-SD2K5ZN5.js → chunk-4LPA25NQ.js} +4 -4
  201. package/dist/{chunk-DKCX643S.js → chunk-4RMN4E2Y.js} +13 -13
  202. package/dist/{chunk-E5FCEDMU.js → chunk-4SAGYEVB.js} +2 -2
  203. package/dist/{chunk-HTT3FB7T.js → chunk-4VK2R5QC.js} +3 -3
  204. package/dist/{chunk-CKG2EG62.js → chunk-4XQC7VLT.js} +14 -14
  205. package/dist/{chunk-IVOA3DXA.js → chunk-4YXAQMTD.js} +12 -12
  206. package/dist/{chunk-HOJGAJAB.js → chunk-52WK2GGK.js} +8 -8
  207. package/dist/{chunk-NYZQ7LO7.js → chunk-552UYIQ7.js} +20 -20
  208. package/dist/{chunk-LEXPBQ56.js → chunk-5DSKMG2I.js} +4 -4
  209. package/dist/{chunk-WNG757ID.js → chunk-5FA455GR.js} +4 -4
  210. package/dist/{chunk-MNWQAYY3.js → chunk-5FEN3KYH.js} +11 -11
  211. package/dist/{chunk-OSVHU2WU.js → chunk-5JHRMUAZ.js} +12 -12
  212. package/dist/{chunk-PM3OSANE.js → chunk-5MJHH72T.js} +14 -3
  213. package/dist/chunk-5MJHH72T.js.map +1 -0
  214. package/dist/{chunk-RKB2Z457.js → chunk-5VGJXWQ2.js} +2 -2
  215. package/dist/{chunk-GFUUFM2O.js → chunk-5W6ZDKRR.js} +6 -6
  216. package/dist/{chunk-NDETTZQA.js → chunk-5W7KJ5NQ.js} +37 -37
  217. package/dist/{chunk-Q35YZVDZ.js → chunk-5Y2FPLZE.js} +9 -9
  218. package/dist/{chunk-6W3LF3DB.js → chunk-5YFY4SFC.js} +2 -12
  219. package/dist/chunk-5YFY4SFC.js.map +1 -0
  220. package/dist/{chunk-F3NERYBQ.js → chunk-62VER7O4.js} +6 -6
  221. package/dist/{chunk-FBMU3VK5.js → chunk-6DCEDIF6.js} +2 -2
  222. package/dist/{chunk-WUHB422G.js → chunk-73WI7FL2.js} +18 -18
  223. package/dist/chunk-756MKA2J.js +45 -0
  224. package/dist/chunk-756MKA2J.js.map +1 -0
  225. package/dist/{chunk-QECZVL7S.js → chunk-7FJMRJDG.js} +2 -2
  226. package/dist/{chunk-7KGKDWWR.js → chunk-7HFLYNWN.js} +2 -2
  227. package/dist/{chunk-XVM566II.js → chunk-7KIENXRE.js} +2 -2
  228. package/dist/{chunk-CBY5CXBD.js → chunk-7NPCEBZE.js} +5 -5
  229. package/dist/{chunk-46VBQG2D.js → chunk-7P4AQMGA.js} +13 -13
  230. package/dist/{chunk-CKZW7A5S.js → chunk-7TCT7KPQ.js} +742 -644
  231. package/dist/chunk-7TCT7KPQ.js.map +1 -0
  232. package/dist/{chunk-O77Q4NG2.js → chunk-7XO7YKPC.js} +283 -1038
  233. package/dist/chunk-7XO7YKPC.js.map +1 -0
  234. package/dist/{chunk-S7PVL7XH.js → chunk-A4BD4ZVB.js} +4 -4
  235. package/dist/{chunk-VSQHDBHU.js → chunk-ACL2V2KE.js} +68 -35
  236. package/dist/chunk-ACL2V2KE.js.map +1 -0
  237. package/dist/{chunk-73SOCVLS.js → chunk-AIEXYO2X.js} +3 -3
  238. package/dist/{chunk-U7TC2XJQ.js → chunk-AJPW3SV4.js} +3 -3
  239. package/dist/{chunk-HRJQAFKR.js → chunk-AX6YJA5U.js} +2 -2
  240. package/dist/{chunk-P5WABK2H.js → chunk-BCM7C3MJ.js} +9 -9
  241. package/dist/{chunk-DT7BORXG.js → chunk-BMJTNPWK.js} +2 -2
  242. package/dist/{chunk-HIHO2QE7.js → chunk-BT2MVGHT.js} +2 -2
  243. package/dist/{chunk-3XOISKZC.js → chunk-BXQYAAVE.js} +4 -4
  244. package/dist/{chunk-IBTXYLBW.js → chunk-CCFWY4GF.js} +2 -2
  245. package/dist/{chunk-ZOC3OP6F.js → chunk-CCR33J7L.js} +2 -2
  246. package/dist/{chunk-GTQ3SNEI.js → chunk-CD3MO3IC.js} +2 -2
  247. package/dist/{chunk-WSMYOLHG.js → chunk-CDEXRJB6.js} +5 -5
  248. package/dist/{chunk-3GLAPCVI.js → chunk-CFFNT2OY.js} +8 -8
  249. package/dist/{chunk-FUSFVUIJ.js → chunk-CMLJSF2F.js} +12 -12
  250. package/dist/{chunk-O4DYOSOL.js → chunk-CP7ZQHBW.js} +13 -13
  251. package/dist/{chunk-IOKSNX74.js → chunk-D5OWJZQR.js} +2 -2
  252. package/dist/{chunk-SQGXMHJO.js → chunk-DGLRZMXL.js} +3 -3
  253. package/dist/{chunk-GNEHAPKV.js → chunk-DJFTH2DI.js} +3 -3
  254. package/dist/{chunk-HQG4SLTE.js → chunk-DYJGYGPB.js} +2 -2
  255. package/dist/{chunk-4EAF3HSD.js → chunk-EJ7WARW7.js} +2 -2
  256. package/dist/{chunk-3AA6RNGE.js → chunk-ENS6E4RZ.js} +2 -2
  257. package/dist/{chunk-OOEO4MKY.js → chunk-EPWD4KRA.js} +2 -2
  258. package/dist/{chunk-V5RJAWRP.js → chunk-EQE3MNQN.js} +5 -5
  259. package/dist/{chunk-TSBE4KOQ.js → chunk-EWL6NDOO.js} +3 -3
  260. package/dist/{chunk-OO2T63BY.js → chunk-EYS4ZOF5.js} +2 -2
  261. package/dist/{chunk-IC7KNOBB.js → chunk-FDAV72IX.js} +7 -7
  262. package/dist/{chunk-AG7VGUIW.js → chunk-FFNPUSVO.js} +7 -7
  263. package/dist/{chunk-P5T36BA3.js → chunk-FRP64DEK.js} +2 -2
  264. package/dist/{chunk-KBF3SE7G.js → chunk-FSP334UU.js} +2 -2
  265. package/dist/{chunk-ZHFKMMOT.js → chunk-FTX5CNHA.js} +6 -6
  266. package/dist/{chunk-KYBALSWW.js → chunk-FWOBNL2A.js} +1 -1
  267. package/dist/{chunk-HJ5XWW62.js → chunk-FWYEZ3LE.js} +34 -34
  268. package/dist/{chunk-WSLPZ43N.js → chunk-G4HQUBO4.js} +12 -12
  269. package/dist/{chunk-CSHBR2IZ.js → chunk-GDLDBR6B.js} +2 -2
  270. package/dist/chunk-GGV4NSG3.js +792 -0
  271. package/dist/chunk-GGV4NSG3.js.map +1 -0
  272. package/dist/{chunk-G3S2F35T.js → chunk-GHHM6WN4.js} +3 -3
  273. package/dist/{chunk-OANSIX34.js → chunk-GRSODLVO.js} +4 -4
  274. package/dist/{chunk-DDIBZA4X.js → chunk-GT7JFQ4E.js} +405 -148
  275. package/dist/chunk-GT7JFQ4E.js.map +1 -0
  276. package/dist/{chunk-EU6XSQFM.js → chunk-GXW2I2M2.js} +2 -2
  277. package/dist/{chunk-4246UYVG.js → chunk-GZS37O3G.js} +1 -1
  278. package/dist/{chunk-XFNLU7EW.js → chunk-H5M33DAL.js} +15 -6
  279. package/dist/chunk-H5M33DAL.js.map +1 -0
  280. package/dist/{chunk-Y7WMW74G.js → chunk-HQWVDQXW.js} +7 -7
  281. package/dist/{chunk-YTZQV2DD.js → chunk-HU6JTNWF.js} +2 -2
  282. package/dist/{chunk-QRVNI5V6.js → chunk-I6KIQKU6.js} +3 -3
  283. package/dist/{chunk-Q262Y2YX.js → chunk-IBA5FMRE.js} +141 -137
  284. package/dist/chunk-IBA5FMRE.js.map +1 -0
  285. package/dist/{chunk-BNUPYHHZ.js → chunk-IDXTASGN.js} +4 -4
  286. package/dist/{chunk-KF3MF6FP.js → chunk-IECRGM6K.js} +3 -2
  287. package/dist/chunk-IECRGM6K.js.map +1 -0
  288. package/dist/chunk-IJYL5BZM.js +38 -0
  289. package/dist/chunk-IJYL5BZM.js.map +1 -0
  290. package/dist/{chunk-L6RXRRN3.js → chunk-ILDOW2IQ.js} +3 -3
  291. package/dist/{chunk-VUHPA3XQ.js → chunk-ITX2TB4K.js} +6 -6
  292. package/dist/{chunk-ETCB6SUJ.js → chunk-J22HD2PB.js} +6 -6
  293. package/dist/{chunk-U47YDYLQ.js → chunk-J5MEDX7C.js} +8 -8
  294. package/dist/{chunk-6VQTHC4W.js → chunk-J7FBBLHF.js} +36 -36
  295. package/dist/{chunk-5JZYPZ72.js → chunk-JFK7NTEA.js} +4 -4
  296. package/dist/chunk-JFK7NTEA.js.map +1 -0
  297. package/dist/{chunk-QZRDCFHI.js → chunk-JM4HQPAI.js} +5 -5
  298. package/dist/{chunk-PIVGX42P.js → chunk-JNY5MT3I.js} +2 -2
  299. package/dist/{chunk-XWWXIZFP.js → chunk-JO6R5EXF.js} +7 -7
  300. package/dist/{chunk-MM7OKOTE.js → chunk-JQCGPTZ6.js} +9 -9
  301. package/dist/chunk-JRSNCSZN.js +37 -0
  302. package/dist/chunk-JRSNCSZN.js.map +1 -0
  303. package/dist/{chunk-KNFDWNCH.js → chunk-JXT5QDJC.js} +5 -5
  304. package/dist/{chunk-OR37STQZ.js → chunk-KEXYBG7Q.js} +3 -3
  305. package/dist/{chunk-AZVANYMB.js → chunk-KUNFUSZ7.js} +2 -2
  306. package/dist/{chunk-DXZNDKQD.js → chunk-LEEJBZ5B.js} +2 -2
  307. package/dist/{chunk-STUCI6QA.js → chunk-LEKBNKLD.js} +1 -1
  308. package/dist/{chunk-STUCI6QA.js.map → chunk-LEKBNKLD.js.map} +1 -1
  309. package/dist/{chunk-C535KSTY.js → chunk-LF5CBAOS.js} +4 -4
  310. package/dist/{chunk-BJIZ7PL7.js → chunk-LHLK7FUA.js} +145 -29
  311. package/dist/chunk-LHLK7FUA.js.map +1 -0
  312. package/dist/{chunk-RIMKJBCD.js → chunk-LMPTC4CX.js} +2 -2
  313. package/dist/{chunk-3KVWXKD6.js → chunk-LQ47YL6E.js} +2 -2
  314. package/dist/{chunk-H5WGWAYX.js → chunk-LT4J7RHI.js} +13 -13
  315. package/dist/{chunk-DSGMYES6.js → chunk-MCTTONOW.js} +28 -28
  316. package/dist/{chunk-IGHELZI7.js → chunk-MIECLOQC.js} +9 -9
  317. package/dist/{chunk-FM4OUCC2.js → chunk-MOKYT3X3.js} +3 -3
  318. package/dist/{chunk-GZ64CASI.js → chunk-MVZYNZXE.js} +5 -4
  319. package/dist/chunk-MVZYNZXE.js.map +1 -0
  320. package/dist/{chunk-RKILMLA7.js → chunk-MXLKI7BI.js} +3 -3
  321. package/dist/{chunk-45WYYFP6.js → chunk-N3ZP4IDU.js} +2 -2
  322. package/dist/{chunk-XRRSFQEV.js → chunk-NAZZLAWX.js} +2 -2
  323. package/dist/{chunk-UWJ5P5CU.js → chunk-NEK4WB5P.js} +3 -3
  324. package/dist/{chunk-6L7U46Y2.js → chunk-NKNVIO66.js} +2 -2
  325. package/dist/{chunk-JKUICTLM.js → chunk-NLAFNMPK.js} +2 -2
  326. package/dist/{chunk-4LKNIGHB.js → chunk-O2SBHS2N.js} +2 -2
  327. package/dist/{chunk-D3RK3NGM.js → chunk-PCFK7HKD.js} +17 -17
  328. package/dist/{chunk-VVCDB2T7.js → chunk-PCJLH45G.js} +3 -3
  329. package/dist/{chunk-PZ24CYDO.js → chunk-PFAUGEV5.js} +2 -2
  330. package/dist/{chunk-HGMWMK5K.js → chunk-PO3BH3KQ.js} +2 -2
  331. package/dist/{chunk-B74GSYR6.js → chunk-PUTS4DYW.js} +2 -2
  332. package/dist/{chunk-JSIDLTTG.js → chunk-PZ2V2XIK.js} +2 -2
  333. package/dist/{chunk-TMEQPODK.js → chunk-PZ37VDB5.js} +2 -2
  334. package/dist/{chunk-QIYBOFUV.js → chunk-QFMLAT7L.js} +246 -237
  335. package/dist/chunk-QFMLAT7L.js.map +1 -0
  336. package/dist/{chunk-LVONK3YQ.js → chunk-QRKTESVE.js} +2 -2
  337. package/dist/{chunk-HT5WSUC7.js → chunk-QXEDIDBZ.js} +3 -3
  338. package/dist/{chunk-WURSS6MP.js → chunk-R66YMYJU.js} +2 -2
  339. package/dist/{chunk-HDHK3SXK.js → chunk-RFLYID6H.js} +5 -5
  340. package/dist/{chunk-V77JK73U.js → chunk-RIYZFKIM.js} +37 -35
  341. package/dist/chunk-RIYZFKIM.js.map +1 -0
  342. package/dist/{chunk-VMFID36H.js → chunk-RQNZDTKT.js} +19 -19
  343. package/dist/{chunk-EHCUFCXM.js → chunk-RYSRFAHN.js} +32 -22
  344. package/dist/chunk-RYSRFAHN.js.map +1 -0
  345. package/dist/{chunk-I6VUUEXH.js → chunk-S2U4CDAC.js} +150 -150
  346. package/dist/chunk-S2U4CDAC.js.map +1 -0
  347. package/dist/chunk-S37GP7LX.js +204 -0
  348. package/dist/chunk-S37GP7LX.js.map +1 -0
  349. package/dist/{chunk-A2EWJQXX.js → chunk-SM5QX6UK.js} +4 -4
  350. package/dist/{chunk-FBE6AIIW.js → chunk-SOKNCW5U.js} +2 -2
  351. package/dist/{chunk-Q4NM77K7.js → chunk-SSOO4GWN.js} +193 -194
  352. package/dist/chunk-SSOO4GWN.js.map +1 -0
  353. package/dist/{chunk-PFKTGZKE.js → chunk-SY2AAZNB.js} +2 -2
  354. package/dist/{chunk-DFZMKCVP.js → chunk-TIQPKOFW.js} +4 -4
  355. package/dist/{chunk-HPPKLBTJ.js → chunk-TJQDL3JH.js} +2 -2
  356. package/dist/chunk-TL7BOFFL.js +89 -0
  357. package/dist/chunk-TL7BOFFL.js.map +1 -0
  358. package/dist/{chunk-FD4Q5KFL.js → chunk-TLL22FFO.js} +2 -2
  359. package/dist/{chunk-QM5H4FPT.js → chunk-TV6BWONY.js} +3 -3
  360. package/dist/{chunk-EDFJBX3V.js → chunk-U6MPB3K6.js} +9 -9
  361. package/dist/{chunk-TZD3U2S5.js → chunk-ULJAOMJA.js} +4 -4
  362. package/dist/chunk-ULYQEFNH.js +529 -0
  363. package/dist/chunk-ULYQEFNH.js.map +1 -0
  364. package/dist/{chunk-H5EVWF6L.js → chunk-UNNJUJVD.js} +2 -2
  365. package/dist/{chunk-324X6T6G.js → chunk-UP7I3W6O.js} +57 -55
  366. package/dist/chunk-UP7I3W6O.js.map +1 -0
  367. package/dist/{chunk-VU2EWALC.js → chunk-UUGR3X5I.js} +19 -12
  368. package/dist/chunk-UUGR3X5I.js.map +1 -0
  369. package/dist/{chunk-Z6DKXQG7.js → chunk-UXXFMF4X.js} +2 -2
  370. package/dist/{chunk-OBQVTCTW.js → chunk-UYNCMZX5.js} +4 -4
  371. package/dist/{chunk-RGPYMHKI.js → chunk-V3K4RQO7.js} +9 -3
  372. package/dist/chunk-V3K4RQO7.js.map +1 -0
  373. package/dist/{chunk-KZHW27BV.js → chunk-V4QZ7UBK.js} +2 -2
  374. package/dist/{chunk-NEVRLD77.js → chunk-VH5EGTH2.js} +3 -3
  375. package/dist/{chunk-MYNUBDU7.js → chunk-VYKW6TB2.js} +1 -1
  376. package/dist/chunk-VYKW6TB2.js.map +1 -0
  377. package/dist/{chunk-QEJTQTF5.js → chunk-W6T5HR3Z.js} +3 -3
  378. package/dist/{chunk-H6WWEKEV.js → chunk-WCMG4HYI.js} +10 -10
  379. package/dist/{chunk-GZLLDA6P.js → chunk-WEFN327U.js} +2 -2
  380. package/dist/{chunk-VW3BBTMA.js → chunk-WKHUZIOW.js} +1 -1
  381. package/dist/{chunk-ANHUMDJX.js → chunk-WNDTLK44.js} +2 -2
  382. package/dist/{chunk-2DS4UOYQ.js → chunk-WSZQNTVN.js} +2 -2
  383. package/dist/{chunk-Z2DAWUO3.js → chunk-XMNUZUUA.js} +6 -6
  384. package/dist/{chunk-GAIM5RNE.js → chunk-XN7NSPE6.js} +3 -3
  385. package/dist/chunk-XV6ZYRHK.js +59 -0
  386. package/dist/chunk-XV6ZYRHK.js.map +1 -0
  387. package/dist/{chunk-FLGUVRR7.js → chunk-Y5BSA3I7.js} +5 -5
  388. package/dist/{chunk-WRLWLGEF.js → chunk-Y5E3XQ2S.js} +25 -2
  389. package/dist/{chunk-WRLWLGEF.js.map → chunk-Y5E3XQ2S.js.map} +1 -1
  390. package/dist/{chunk-QILLL4JE.js → chunk-YEROLKOA.js} +16 -16
  391. package/dist/{chunk-NDF3SH3X.js → chunk-YJPKDRI2.js} +15 -15
  392. package/dist/{chunk-TQGJN5UZ.js → chunk-YV56F4UP.js} +318 -700
  393. package/dist/chunk-YV56F4UP.js.map +1 -0
  394. package/dist/{chunk-VAIESMPY.js → chunk-YVBHGMKC.js} +4 -4
  395. package/dist/{chunk-AD22P5X3.js → chunk-YXA2EKV3.js} +3 -3
  396. package/dist/{chunk-FDNJVZRE.js → chunk-YYCOSTUU.js} +17 -17
  397. package/dist/{chunk-NLMTNEWW.js → chunk-Z6E6TUAE.js} +2 -2
  398. package/dist/{chunk-BJW7G6EF.js → chunk-Z7IGO5EA.js} +3 -3
  399. package/dist/{chunk-N7JKT4ZU.js → chunk-ZEIFJ6PX.js} +7 -7
  400. package/dist/{chunk-Q4OHNGGB.js → chunk-ZS2UQ3DV.js} +68 -11
  401. package/dist/chunk-ZS2UQ3DV.js.map +1 -0
  402. package/dist/{chunk-VRGOOVDB.js → chunk-ZVVT72MT.js} +2 -2
  403. package/dist/components/browser-viewer.d.ts +1 -1
  404. package/dist/composer.js +14 -14
  405. package/dist/{computer-viewer-KEDVLD42.js → computer-viewer-25AJIDYA.js} +9 -9
  406. package/dist/connect.js +11 -11
  407. package/dist/desktop.js +2 -2
  408. package/dist/editor.js +2 -2
  409. package/dist/{embedded-new-voice-5PYRDZ6T.js → embedded-new-voice-RZZEJT6M.js} +8 -8
  410. package/dist/{embedded-voice-PABC5NBD.js → embedded-voice-6OKSSPLW.js} +8 -8
  411. package/dist/{fleet-decision-row-QNSTP3VX.js → fleet-decision-row-NN2HXDX3.js} +2 -2
  412. package/dist/hooks/internal.d.ts +38 -0
  413. package/dist/hooks/use-client-config-flags.d.ts +12 -0
  414. package/dist/hooks/use-workspace-sessions.d.ts +10 -1
  415. package/dist/index.js +233 -227
  416. package/dist/interaction.js +11 -9
  417. package/dist/interaction.js.map +1 -1
  418. package/dist/{latest-question-5LIRVG4G.js → latest-question-2PFWQSSG.js} +4 -3
  419. package/dist/{latest-question-5LIRVG4G.js.map → latest-question-2PFWQSSG.js.map} +1 -1
  420. package/dist/machines.js +5 -5
  421. package/dist/messages/en.d.ts +3 -3
  422. package/dist/messages.js +1 -1
  423. package/dist/{model-policy-picker-menu-CURJ247L.js → model-policy-picker-menu-VVFGGAI6.js} +6 -6
  424. package/dist/model-policy-picker-menu-VVFGGAI6.js.map +1 -0
  425. package/dist/native-previews.js +3 -3
  426. package/dist/{platform-activity-row-BMXXNZKX.js → platform-activity-row-ENQVIFTL.js} +2 -2
  427. package/dist/{queue-surface-implementation-2X5AXB6I.js → queue-surface-implementation-4SHOQPQQ.js} +10 -8
  428. package/dist/{queue-surface-implementation-2X5AXB6I.js.map → queue-surface-implementation-4SHOQPQQ.js.map} +1 -1
  429. package/dist/realtime.js +7 -7
  430. package/dist/{sandbox-files-4FBG3GS2.js → sandbox-files-CCOTGXXA.js} +11 -11
  431. package/dist/sandbox-files-CCOTGXXA.js.map +1 -0
  432. package/dist/session-app.js +277 -271
  433. package/dist/session-list-model.d.ts +1 -0
  434. package/dist/session-list-model.js +8 -2
  435. package/dist/{session-realtime-2XIB254N.js → session-realtime-JNKDSGH7.js} +3 -3
  436. package/dist/session-realtime-JNKDSGH7.js.map +1 -0
  437. package/dist/session-realtime.js +2 -2
  438. package/dist/session-ui.js +77 -72
  439. package/dist/session.js +27 -25
  440. package/dist/sites.js +2 -2
  441. package/dist/terminal.js +2 -2
  442. package/dist/this-computer.js +3 -3
  443. package/dist/timeline/invoked-tool.d.ts +5 -0
  444. package/dist/timeline/tool-display-name.d.ts +2 -2
  445. package/dist/timeline/tool-icon.d.ts +14 -0
  446. package/dist/timeline/tool-presentation.d.ts +8 -3
  447. package/dist/timeline/types.d.ts +2 -0
  448. package/dist/{timeline-annotation-markers-X4K2IEOO.js → timeline-annotation-markers-KHNYNY2J.js} +5 -5
  449. package/dist/{timeline-annotation-selection-MEHBW676.js → timeline-annotation-selection-AXEDJHBP.js} +7 -7
  450. package/dist/{timeline-annotations-dialog-U2FPQ3UY.js → timeline-annotations-dialog-AV4ZBXRC.js} +9 -9
  451. package/dist/timeline-model.js +28 -26
  452. package/dist/ui/access-list.js +20 -20
  453. package/dist/ui/choice-cards.js +2 -2
  454. package/dist/ui/detail-page.js +2 -2
  455. package/dist/ui/detail-sheet.js +2 -2
  456. package/dist/ui/diff-view.js +2 -2
  457. package/dist/ui/disclosure.js +4 -4
  458. package/dist/ui/flush-form-page.js +3 -3
  459. package/dist/ui/form-dialog.js +2 -2
  460. package/dist/ui/list-row.js +5 -5
  461. package/dist/ui/revision-history.js +11 -11
  462. package/dist/ui/role-select.js +6 -6
  463. package/dist/ui/settings-nav.js +3 -3
  464. package/dist/usage.js +3 -3
  465. package/dist/workbench.js +11 -11
  466. package/package.json +4 -4
  467. package/src/app/app-state.tsx +3 -1
  468. package/src/app/components/capabilities/session-capability-card.tsx +14 -1
  469. package/src/app/components/capabilities/session-chrome-card.dom-fixture.tsx +377 -0
  470. package/src/app/components/capabilities/session-chrome-card.test.tsx +18 -0
  471. package/src/app/components/capabilities/session-chrome-card.tsx +243 -0
  472. package/src/app/components/capabilities/session-machine-card.dom-fixture.tsx +2 -0
  473. package/src/app/components/capabilities/session-machine-card.tsx +74 -16
  474. package/src/app/components/rail/session-list.tsx +254 -44
  475. package/src/app/components/rail/session-row-content.tsx +24 -2
  476. package/src/app/components/rail/session-shell.tsx +14 -9
  477. package/src/app/components/rail/site-session-group-heading.tsx +59 -20
  478. package/src/app/components/session/session-tenancy-control.tsx +18 -0
  479. package/src/app/components/session/site-origin-link.test.tsx +73 -0
  480. package/src/app/components/session/site-origin-link.tsx +4 -2
  481. package/src/app/embed/memory-navigation.tsx +1 -0
  482. package/src/app/lib/actions/held-modifier.test.ts +101 -0
  483. package/src/app/lib/actions/held-modifier.ts +108 -0
  484. package/src/app/lib/console-site.tsx +38 -0
  485. package/src/app/lib/navigation.tsx +4 -0
  486. package/src/app/lib/routes.tsx +42 -0
  487. package/src/app/lib/session-failure-toasts.ts +26 -0
  488. package/src/app/lib/session-ui-features.tsx +18 -4
  489. package/src/app/lib/sessions-group.tsx +219 -30
  490. package/src/app/lib/site-opened.tsx +48 -0
  491. package/src/app/lib/site-session-groups.test.ts +173 -6
  492. package/src/app/lib/site-view-routes.test.ts +55 -0
  493. package/src/app/lib/use-session-list-hint-refresh.tsx +44 -4
  494. package/src/app/routes/artifacts.tsx +2 -29
  495. package/src/app/routes/session-transient-failures.test.tsx +343 -0
  496. package/src/app/routes/session-unavailable.tsx +74 -3
  497. package/src/app/routes/session.tsx +4 -13
  498. package/src/app/routes/sessions-index.tsx +13 -9
  499. package/src/app/routes/site-view.test.tsx +476 -0
  500. package/src/app/routes/site-view.tsx +583 -0
  501. package/src/components/browser-viewer.tsx +16 -2
  502. package/src/hooks/internal.ts +129 -6
  503. package/src/hooks/use-client-config-flags.ts +8 -0
  504. package/src/hooks/use-session-events.ts +83 -9
  505. package/src/hooks/use-workspace-sessions.ts +21 -1
  506. package/src/messages/en.ts +3 -3
  507. package/src/session-list-model.ts +4 -0
  508. package/src/timeline/activity-rail.tsx +3 -2
  509. package/src/timeline/invoked-tool.ts +14 -4
  510. package/src/timeline/projection.ts +15 -8
  511. package/src/timeline/rolling-activity.tsx +6 -2
  512. package/src/timeline/tool-display-name.ts +2 -2
  513. package/src/timeline/tool-icon.tsx +165 -0
  514. package/src/timeline/tool-presentation.ts +207 -48
  515. package/src/timeline/tool-renderers.tsx +1 -70
  516. package/src/timeline/types.ts +2 -0
  517. package/styles/compiled.css +38 -0
  518. package/dist/chunk-22ZBT6CN.js +0 -50
  519. package/dist/chunk-22ZBT6CN.js.map +0 -1
  520. package/dist/chunk-324X6T6G.js.map +0 -1
  521. package/dist/chunk-5JZYPZ72.js.map +0 -1
  522. package/dist/chunk-6W3LF3DB.js.map +0 -1
  523. package/dist/chunk-BJIZ7PL7.js.map +0 -1
  524. package/dist/chunk-CKZW7A5S.js.map +0 -1
  525. package/dist/chunk-DDIBZA4X.js.map +0 -1
  526. package/dist/chunk-EHCUFCXM.js.map +0 -1
  527. package/dist/chunk-GZ64CASI.js.map +0 -1
  528. package/dist/chunk-I6VUUEXH.js.map +0 -1
  529. package/dist/chunk-KF3MF6FP.js.map +0 -1
  530. package/dist/chunk-MYNUBDU7.js.map +0 -1
  531. package/dist/chunk-NAWXARTY.js.map +0 -1
  532. package/dist/chunk-O77Q4NG2.js.map +0 -1
  533. package/dist/chunk-PM3OSANE.js.map +0 -1
  534. package/dist/chunk-Q262Y2YX.js.map +0 -1
  535. package/dist/chunk-Q4NM77K7.js.map +0 -1
  536. package/dist/chunk-Q4OHNGGB.js.map +0 -1
  537. package/dist/chunk-QIYBOFUV.js.map +0 -1
  538. package/dist/chunk-R25ZKOZR.js +0 -24
  539. package/dist/chunk-R25ZKOZR.js.map +0 -1
  540. package/dist/chunk-RGPYMHKI.js.map +0 -1
  541. package/dist/chunk-ROQOVH4N.js.map +0 -1
  542. package/dist/chunk-TQGJN5UZ.js.map +0 -1
  543. package/dist/chunk-V77JK73U.js.map +0 -1
  544. package/dist/chunk-VSQHDBHU.js.map +0 -1
  545. package/dist/chunk-VU2EWALC.js.map +0 -1
  546. package/dist/chunk-XFNLU7EW.js.map +0 -1
  547. package/dist/chunk-Z5WMLJKI.js.map +0 -1
  548. /package/dist/{browser-viewer-RYYQSRTC.js.map → app/components/capabilities/session-chrome-card.js.map} +0 -0
  549. /package/dist/{chat-interactive-block-ABCRKXJ4.js.map → app/lib/console-site.js.map} +0 -0
  550. /package/dist/{computer-viewer-KEDVLD42.js.map → app/lib/site-opened.js.map} +0 -0
  551. /package/dist/{embedded-new-voice-5PYRDZ6T.js.map → browser-viewer-QMCNV4RI.js.map} +0 -0
  552. /package/dist/{embedded-voice-PABC5NBD.js.map → chat-interactive-block-PMIAUXSO.js.map} +0 -0
  553. /package/dist/{chunk-GIZGNFIX.js.map → chunk-22FFOHPT.js.map} +0 -0
  554. /package/dist/{chunk-UHFWF6ZU.js.map → chunk-2FPS5H2D.js.map} +0 -0
  555. /package/dist/{chunk-5POTDNQT.js.map → chunk-2NC7NZCE.js.map} +0 -0
  556. /package/dist/{chunk-ZKYYZH6L.js.map → chunk-2QBYDGWO.js.map} +0 -0
  557. /package/dist/{chunk-TWXIFWBD.js.map → chunk-34EU25RL.js.map} +0 -0
  558. /package/dist/{chunk-LQKKSUCR.js.map → chunk-35BC2FU2.js.map} +0 -0
  559. /package/dist/{chunk-PTGRFAMH.js.map → chunk-3ABPIUCK.js.map} +0 -0
  560. /package/dist/{chunk-S4SC5SSV.js.map → chunk-3GU7AWG7.js.map} +0 -0
  561. /package/dist/{chunk-722UO6YQ.js.map → chunk-3PEXVG4D.js.map} +0 -0
  562. /package/dist/{chunk-OQAAI33Y.js.map → chunk-3RMKPHBL.js.map} +0 -0
  563. /package/dist/{chunk-GCGTYXJJ.js.map → chunk-3STBLX4O.js.map} +0 -0
  564. /package/dist/{chunk-YXIW7H4N.js.map → chunk-3X5FKDYQ.js.map} +0 -0
  565. /package/dist/{chunk-KTRKZRID.js.map → chunk-4GLLWX33.js.map} +0 -0
  566. /package/dist/{chunk-SD2K5ZN5.js.map → chunk-4LPA25NQ.js.map} +0 -0
  567. /package/dist/{chunk-DKCX643S.js.map → chunk-4RMN4E2Y.js.map} +0 -0
  568. /package/dist/{chunk-E5FCEDMU.js.map → chunk-4SAGYEVB.js.map} +0 -0
  569. /package/dist/{chunk-HTT3FB7T.js.map → chunk-4VK2R5QC.js.map} +0 -0
  570. /package/dist/{chunk-CKG2EG62.js.map → chunk-4XQC7VLT.js.map} +0 -0
  571. /package/dist/{chunk-IVOA3DXA.js.map → chunk-4YXAQMTD.js.map} +0 -0
  572. /package/dist/{chunk-HOJGAJAB.js.map → chunk-52WK2GGK.js.map} +0 -0
  573. /package/dist/{chunk-NYZQ7LO7.js.map → chunk-552UYIQ7.js.map} +0 -0
  574. /package/dist/{chunk-LEXPBQ56.js.map → chunk-5DSKMG2I.js.map} +0 -0
  575. /package/dist/{chunk-WNG757ID.js.map → chunk-5FA455GR.js.map} +0 -0
  576. /package/dist/{chunk-MNWQAYY3.js.map → chunk-5FEN3KYH.js.map} +0 -0
  577. /package/dist/{chunk-OSVHU2WU.js.map → chunk-5JHRMUAZ.js.map} +0 -0
  578. /package/dist/{chunk-RKB2Z457.js.map → chunk-5VGJXWQ2.js.map} +0 -0
  579. /package/dist/{chunk-GFUUFM2O.js.map → chunk-5W6ZDKRR.js.map} +0 -0
  580. /package/dist/{chunk-NDETTZQA.js.map → chunk-5W7KJ5NQ.js.map} +0 -0
  581. /package/dist/{chunk-Q35YZVDZ.js.map → chunk-5Y2FPLZE.js.map} +0 -0
  582. /package/dist/{chunk-F3NERYBQ.js.map → chunk-62VER7O4.js.map} +0 -0
  583. /package/dist/{chunk-FBMU3VK5.js.map → chunk-6DCEDIF6.js.map} +0 -0
  584. /package/dist/{chunk-WUHB422G.js.map → chunk-73WI7FL2.js.map} +0 -0
  585. /package/dist/{chunk-QECZVL7S.js.map → chunk-7FJMRJDG.js.map} +0 -0
  586. /package/dist/{chunk-7KGKDWWR.js.map → chunk-7HFLYNWN.js.map} +0 -0
  587. /package/dist/{chunk-XVM566II.js.map → chunk-7KIENXRE.js.map} +0 -0
  588. /package/dist/{chunk-CBY5CXBD.js.map → chunk-7NPCEBZE.js.map} +0 -0
  589. /package/dist/{chunk-46VBQG2D.js.map → chunk-7P4AQMGA.js.map} +0 -0
  590. /package/dist/{chunk-S7PVL7XH.js.map → chunk-A4BD4ZVB.js.map} +0 -0
  591. /package/dist/{chunk-73SOCVLS.js.map → chunk-AIEXYO2X.js.map} +0 -0
  592. /package/dist/{chunk-U7TC2XJQ.js.map → chunk-AJPW3SV4.js.map} +0 -0
  593. /package/dist/{chunk-HRJQAFKR.js.map → chunk-AX6YJA5U.js.map} +0 -0
  594. /package/dist/{chunk-P5WABK2H.js.map → chunk-BCM7C3MJ.js.map} +0 -0
  595. /package/dist/{chunk-DT7BORXG.js.map → chunk-BMJTNPWK.js.map} +0 -0
  596. /package/dist/{chunk-HIHO2QE7.js.map → chunk-BT2MVGHT.js.map} +0 -0
  597. /package/dist/{chunk-3XOISKZC.js.map → chunk-BXQYAAVE.js.map} +0 -0
  598. /package/dist/{chunk-IBTXYLBW.js.map → chunk-CCFWY4GF.js.map} +0 -0
  599. /package/dist/{chunk-ZOC3OP6F.js.map → chunk-CCR33J7L.js.map} +0 -0
  600. /package/dist/{chunk-GTQ3SNEI.js.map → chunk-CD3MO3IC.js.map} +0 -0
  601. /package/dist/{chunk-WSMYOLHG.js.map → chunk-CDEXRJB6.js.map} +0 -0
  602. /package/dist/{chunk-3GLAPCVI.js.map → chunk-CFFNT2OY.js.map} +0 -0
  603. /package/dist/{chunk-FUSFVUIJ.js.map → chunk-CMLJSF2F.js.map} +0 -0
  604. /package/dist/{chunk-O4DYOSOL.js.map → chunk-CP7ZQHBW.js.map} +0 -0
  605. /package/dist/{chunk-IOKSNX74.js.map → chunk-D5OWJZQR.js.map} +0 -0
  606. /package/dist/{chunk-SQGXMHJO.js.map → chunk-DGLRZMXL.js.map} +0 -0
  607. /package/dist/{chunk-GNEHAPKV.js.map → chunk-DJFTH2DI.js.map} +0 -0
  608. /package/dist/{chunk-HQG4SLTE.js.map → chunk-DYJGYGPB.js.map} +0 -0
  609. /package/dist/{chunk-4EAF3HSD.js.map → chunk-EJ7WARW7.js.map} +0 -0
  610. /package/dist/{chunk-3AA6RNGE.js.map → chunk-ENS6E4RZ.js.map} +0 -0
  611. /package/dist/{chunk-OOEO4MKY.js.map → chunk-EPWD4KRA.js.map} +0 -0
  612. /package/dist/{chunk-V5RJAWRP.js.map → chunk-EQE3MNQN.js.map} +0 -0
  613. /package/dist/{chunk-TSBE4KOQ.js.map → chunk-EWL6NDOO.js.map} +0 -0
  614. /package/dist/{chunk-OO2T63BY.js.map → chunk-EYS4ZOF5.js.map} +0 -0
  615. /package/dist/{chunk-IC7KNOBB.js.map → chunk-FDAV72IX.js.map} +0 -0
  616. /package/dist/{chunk-AG7VGUIW.js.map → chunk-FFNPUSVO.js.map} +0 -0
  617. /package/dist/{chunk-P5T36BA3.js.map → chunk-FRP64DEK.js.map} +0 -0
  618. /package/dist/{chunk-KBF3SE7G.js.map → chunk-FSP334UU.js.map} +0 -0
  619. /package/dist/{chunk-ZHFKMMOT.js.map → chunk-FTX5CNHA.js.map} +0 -0
  620. /package/dist/{chunk-KYBALSWW.js.map → chunk-FWOBNL2A.js.map} +0 -0
  621. /package/dist/{chunk-HJ5XWW62.js.map → chunk-FWYEZ3LE.js.map} +0 -0
  622. /package/dist/{chunk-WSLPZ43N.js.map → chunk-G4HQUBO4.js.map} +0 -0
  623. /package/dist/{chunk-CSHBR2IZ.js.map → chunk-GDLDBR6B.js.map} +0 -0
  624. /package/dist/{chunk-G3S2F35T.js.map → chunk-GHHM6WN4.js.map} +0 -0
  625. /package/dist/{chunk-OANSIX34.js.map → chunk-GRSODLVO.js.map} +0 -0
  626. /package/dist/{chunk-EU6XSQFM.js.map → chunk-GXW2I2M2.js.map} +0 -0
  627. /package/dist/{chunk-4246UYVG.js.map → chunk-GZS37O3G.js.map} +0 -0
  628. /package/dist/{chunk-Y7WMW74G.js.map → chunk-HQWVDQXW.js.map} +0 -0
  629. /package/dist/{chunk-YTZQV2DD.js.map → chunk-HU6JTNWF.js.map} +0 -0
  630. /package/dist/{chunk-QRVNI5V6.js.map → chunk-I6KIQKU6.js.map} +0 -0
  631. /package/dist/{chunk-BNUPYHHZ.js.map → chunk-IDXTASGN.js.map} +0 -0
  632. /package/dist/{chunk-L6RXRRN3.js.map → chunk-ILDOW2IQ.js.map} +0 -0
  633. /package/dist/{chunk-VUHPA3XQ.js.map → chunk-ITX2TB4K.js.map} +0 -0
  634. /package/dist/{chunk-ETCB6SUJ.js.map → chunk-J22HD2PB.js.map} +0 -0
  635. /package/dist/{chunk-U47YDYLQ.js.map → chunk-J5MEDX7C.js.map} +0 -0
  636. /package/dist/{chunk-6VQTHC4W.js.map → chunk-J7FBBLHF.js.map} +0 -0
  637. /package/dist/{chunk-QZRDCFHI.js.map → chunk-JM4HQPAI.js.map} +0 -0
  638. /package/dist/{chunk-PIVGX42P.js.map → chunk-JNY5MT3I.js.map} +0 -0
  639. /package/dist/{chunk-XWWXIZFP.js.map → chunk-JO6R5EXF.js.map} +0 -0
  640. /package/dist/{chunk-MM7OKOTE.js.map → chunk-JQCGPTZ6.js.map} +0 -0
  641. /package/dist/{chunk-KNFDWNCH.js.map → chunk-JXT5QDJC.js.map} +0 -0
  642. /package/dist/{chunk-OR37STQZ.js.map → chunk-KEXYBG7Q.js.map} +0 -0
  643. /package/dist/{chunk-AZVANYMB.js.map → chunk-KUNFUSZ7.js.map} +0 -0
  644. /package/dist/{chunk-DXZNDKQD.js.map → chunk-LEEJBZ5B.js.map} +0 -0
  645. /package/dist/{chunk-C535KSTY.js.map → chunk-LF5CBAOS.js.map} +0 -0
  646. /package/dist/{chunk-RIMKJBCD.js.map → chunk-LMPTC4CX.js.map} +0 -0
  647. /package/dist/{chunk-3KVWXKD6.js.map → chunk-LQ47YL6E.js.map} +0 -0
  648. /package/dist/{chunk-H5WGWAYX.js.map → chunk-LT4J7RHI.js.map} +0 -0
  649. /package/dist/{chunk-DSGMYES6.js.map → chunk-MCTTONOW.js.map} +0 -0
  650. /package/dist/{chunk-IGHELZI7.js.map → chunk-MIECLOQC.js.map} +0 -0
  651. /package/dist/{chunk-FM4OUCC2.js.map → chunk-MOKYT3X3.js.map} +0 -0
  652. /package/dist/{chunk-RKILMLA7.js.map → chunk-MXLKI7BI.js.map} +0 -0
  653. /package/dist/{chunk-45WYYFP6.js.map → chunk-N3ZP4IDU.js.map} +0 -0
  654. /package/dist/{chunk-XRRSFQEV.js.map → chunk-NAZZLAWX.js.map} +0 -0
  655. /package/dist/{chunk-UWJ5P5CU.js.map → chunk-NEK4WB5P.js.map} +0 -0
  656. /package/dist/{chunk-6L7U46Y2.js.map → chunk-NKNVIO66.js.map} +0 -0
  657. /package/dist/{chunk-JKUICTLM.js.map → chunk-NLAFNMPK.js.map} +0 -0
  658. /package/dist/{chunk-4LKNIGHB.js.map → chunk-O2SBHS2N.js.map} +0 -0
  659. /package/dist/{chunk-D3RK3NGM.js.map → chunk-PCFK7HKD.js.map} +0 -0
  660. /package/dist/{chunk-VVCDB2T7.js.map → chunk-PCJLH45G.js.map} +0 -0
  661. /package/dist/{chunk-PZ24CYDO.js.map → chunk-PFAUGEV5.js.map} +0 -0
  662. /package/dist/{chunk-HGMWMK5K.js.map → chunk-PO3BH3KQ.js.map} +0 -0
  663. /package/dist/{chunk-B74GSYR6.js.map → chunk-PUTS4DYW.js.map} +0 -0
  664. /package/dist/{chunk-JSIDLTTG.js.map → chunk-PZ2V2XIK.js.map} +0 -0
  665. /package/dist/{chunk-TMEQPODK.js.map → chunk-PZ37VDB5.js.map} +0 -0
  666. /package/dist/{chunk-LVONK3YQ.js.map → chunk-QRKTESVE.js.map} +0 -0
  667. /package/dist/{chunk-HT5WSUC7.js.map → chunk-QXEDIDBZ.js.map} +0 -0
  668. /package/dist/{chunk-WURSS6MP.js.map → chunk-R66YMYJU.js.map} +0 -0
  669. /package/dist/{chunk-HDHK3SXK.js.map → chunk-RFLYID6H.js.map} +0 -0
  670. /package/dist/{chunk-VMFID36H.js.map → chunk-RQNZDTKT.js.map} +0 -0
  671. /package/dist/{chunk-A2EWJQXX.js.map → chunk-SM5QX6UK.js.map} +0 -0
  672. /package/dist/{chunk-FBE6AIIW.js.map → chunk-SOKNCW5U.js.map} +0 -0
  673. /package/dist/{chunk-PFKTGZKE.js.map → chunk-SY2AAZNB.js.map} +0 -0
  674. /package/dist/{chunk-DFZMKCVP.js.map → chunk-TIQPKOFW.js.map} +0 -0
  675. /package/dist/{chunk-HPPKLBTJ.js.map → chunk-TJQDL3JH.js.map} +0 -0
  676. /package/dist/{chunk-FD4Q5KFL.js.map → chunk-TLL22FFO.js.map} +0 -0
  677. /package/dist/{chunk-QM5H4FPT.js.map → chunk-TV6BWONY.js.map} +0 -0
  678. /package/dist/{chunk-EDFJBX3V.js.map → chunk-U6MPB3K6.js.map} +0 -0
  679. /package/dist/{chunk-TZD3U2S5.js.map → chunk-ULJAOMJA.js.map} +0 -0
  680. /package/dist/{chunk-H5EVWF6L.js.map → chunk-UNNJUJVD.js.map} +0 -0
  681. /package/dist/{chunk-Z6DKXQG7.js.map → chunk-UXXFMF4X.js.map} +0 -0
  682. /package/dist/{chunk-OBQVTCTW.js.map → chunk-UYNCMZX5.js.map} +0 -0
  683. /package/dist/{chunk-KZHW27BV.js.map → chunk-V4QZ7UBK.js.map} +0 -0
  684. /package/dist/{chunk-NEVRLD77.js.map → chunk-VH5EGTH2.js.map} +0 -0
  685. /package/dist/{chunk-QEJTQTF5.js.map → chunk-W6T5HR3Z.js.map} +0 -0
  686. /package/dist/{chunk-H6WWEKEV.js.map → chunk-WCMG4HYI.js.map} +0 -0
  687. /package/dist/{chunk-GZLLDA6P.js.map → chunk-WEFN327U.js.map} +0 -0
  688. /package/dist/{chunk-VW3BBTMA.js.map → chunk-WKHUZIOW.js.map} +0 -0
  689. /package/dist/{chunk-ANHUMDJX.js.map → chunk-WNDTLK44.js.map} +0 -0
  690. /package/dist/{chunk-2DS4UOYQ.js.map → chunk-WSZQNTVN.js.map} +0 -0
  691. /package/dist/{chunk-Z2DAWUO3.js.map → chunk-XMNUZUUA.js.map} +0 -0
  692. /package/dist/{chunk-GAIM5RNE.js.map → chunk-XN7NSPE6.js.map} +0 -0
  693. /package/dist/{chunk-FLGUVRR7.js.map → chunk-Y5BSA3I7.js.map} +0 -0
  694. /package/dist/{chunk-QILLL4JE.js.map → chunk-YEROLKOA.js.map} +0 -0
  695. /package/dist/{chunk-NDF3SH3X.js.map → chunk-YJPKDRI2.js.map} +0 -0
  696. /package/dist/{chunk-VAIESMPY.js.map → chunk-YVBHGMKC.js.map} +0 -0
  697. /package/dist/{chunk-AD22P5X3.js.map → chunk-YXA2EKV3.js.map} +0 -0
  698. /package/dist/{chunk-FDNJVZRE.js.map → chunk-YYCOSTUU.js.map} +0 -0
  699. /package/dist/{chunk-NLMTNEWW.js.map → chunk-Z6E6TUAE.js.map} +0 -0
  700. /package/dist/{chunk-BJW7G6EF.js.map → chunk-Z7IGO5EA.js.map} +0 -0
  701. /package/dist/{chunk-N7JKT4ZU.js.map → chunk-ZEIFJ6PX.js.map} +0 -0
  702. /package/dist/{chunk-VRGOOVDB.js.map → chunk-ZVVT72MT.js.map} +0 -0
  703. /package/dist/{model-policy-picker-menu-CURJ247L.js.map → computer-viewer-25AJIDYA.js.map} +0 -0
  704. /package/dist/{sandbox-files-4FBG3GS2.js.map → embedded-new-voice-RZZEJT6M.js.map} +0 -0
  705. /package/dist/{session-realtime-2XIB254N.js.map → embedded-voice-6OKSSPLW.js.map} +0 -0
  706. /package/dist/{fleet-decision-row-QNSTP3VX.js.map → fleet-decision-row-NN2HXDX3.js.map} +0 -0
  707. /package/dist/{platform-activity-row-BMXXNZKX.js.map → platform-activity-row-ENQVIFTL.js.map} +0 -0
  708. /package/dist/{timeline-annotation-markers-X4K2IEOO.js.map → timeline-annotation-markers-KHNYNY2J.js.map} +0 -0
  709. /package/dist/{timeline-annotation-selection-MEHBW676.js.map → timeline-annotation-selection-AXEDJHBP.js.map} +0 -0
  710. /package/dist/{timeline-annotations-dialog-U2FPQ3UY.js.map → timeline-annotations-dialog-AV4ZBXRC.js.map} +0 -0
@@ -7,7 +7,7 @@ import { formatWaitingSince } from "./format";
7
7
  import { awaitsPerson } from "./needs-you";
8
8
  import { sessionInputWait } from "./session-rail";
9
9
  import { sessionSiteOrigin, type SessionSiteOrigin } from "./session-site-origin";
10
- import type { SessionListTotals } from "@opengeni/sdk";
10
+ import type { SessionListTotals, SiteConversationGroup } from "@opengeni/sdk";
11
11
  import type { RailSession as Session } from "./session-list-entry";
12
12
 
13
13
  // The flat list rules are shared with native renderers through the pure
@@ -54,6 +54,11 @@ export {
54
54
  export type SessionTreeNode = {
55
55
  /** Presentation-only group; never persisted or used for session actions. */
56
56
  siteGroup?: SessionSiteOrigin | undefined;
57
+ /**
58
+ * A Site row's complete server counts, independent of which conversations
59
+ * are loaded. Absent when the row was built from loaded conversations only.
60
+ */
61
+ siteSummary?: SiteRowSummary | undefined;
57
62
  session: Session;
58
63
  children: SessionTreeNode[];
59
64
  /** A descendant (any depth, not the node itself) is running/queued/awaiting action. */
@@ -189,6 +194,26 @@ function railStatusCounts(
189
194
  node: SessionTreeNode,
190
195
  localDeliveryAttention: ReadonlyMap<string, number>,
191
196
  ): RailStatusCounts {
197
+ if (node.siteGroup && node.siteSummary) {
198
+ // Complete server counts; loaded rows add only browser-local send failures.
199
+ const summary = node.siteSummary;
200
+ const waiting = Math.min(summary.waiting, summary.active);
201
+ return {
202
+ total: summary.total,
203
+ sendFailed: node.children.reduce(
204
+ (total, child) => total + loadedLocalDeliveryFailureCount(child, localDeliveryAttention),
205
+ 0,
206
+ ),
207
+ attention: summary.attention,
208
+ attentionSince: summary.attentionSince,
209
+ failed: summary.failed,
210
+ active: summary.active - waiting,
211
+ queued: summary.queued,
212
+ waiting,
213
+ unread: summary.unread,
214
+ activeWork: summary.activeWork,
215
+ };
216
+ }
192
217
  if (node.siteGroup) {
193
218
  const counts = ownRailStatusCounts(node.session, localDeliveryAttention);
194
219
  for (const key of [
@@ -773,37 +798,188 @@ export function groupScheduledRuns(roots: SessionTreeNode[]): SessionTreeNode[]
773
798
  return grouped;
774
799
  }
775
800
 
776
- /** Explicit project placement wins; pins have already been split out. */
777
- export function groupSiteConversations(roots: SessionTreeNode[]): SessionTreeNode[] {
778
- const groups = new Map<string, SessionTreeNode[]>();
801
+ export type SiteRowSummary = Omit<SiteConversationGroup, "siteId" | "channelId" | "title">;
802
+
803
+ /**
804
+ * A Site row's stable id. Rows are per project when the rail shows projects,
805
+ * so a Site used from two projects appears in each; otherwise one per Site.
806
+ */
807
+ export function siteRowKey(siteId: string, channelId?: string | null): string {
808
+ return channelId === undefined ? `site:${siteId}` : `site:${siteId}:${channelId ?? "default"}`;
809
+ }
810
+
811
+ /** The Site and project a Site row stands for, or null for an ordinary id. */
812
+ export function parseSiteRowKey(
813
+ key: string,
814
+ ): { siteId: string; channelId?: string | null | undefined } | null {
815
+ const match = /^site:([0-9a-f-]{36})(?::(.+))?$/iu.exec(key);
816
+ if (!match) return null;
817
+ const channel = match[2];
818
+ return channel === undefined
819
+ ? { siteId: match[1]! }
820
+ : { siteId: match[1]!, channelId: channel === "default" ? null : channel };
821
+ }
822
+
823
+ function laterIso(a: string, b: string | undefined): string {
824
+ if (!b) return a;
825
+ return Date.parse(b) > Date.parse(a) ? b : a;
826
+ }
827
+
828
+ /** Merge per-project server groups into one per Site for rails without projects. */
829
+ function siteRowSummaries(
830
+ groups: readonly SiteConversationGroup[],
831
+ byProject: boolean,
832
+ ): Map<string, { origin: SessionSiteOrigin; channelId: string | null; summary: SiteRowSummary }> {
833
+ const rows = new Map<
834
+ string,
835
+ { origin: SessionSiteOrigin; channelId: string | null; summary: SiteRowSummary }
836
+ >();
837
+ for (const group of groups) {
838
+ const key = siteRowKey(group.siteId, byProject ? group.channelId : undefined);
839
+ const { siteId, channelId, title, ...summary } = group;
840
+ const current = rows.get(key);
841
+ if (!current) {
842
+ // A Site this viewer cannot read and that kept no label still needs a name.
843
+ const origin = { siteId, title: title.trim() || "Untitled Site" };
844
+ rows.set(key, { origin, channelId, summary: { ...summary } });
845
+ continue;
846
+ }
847
+ const merged = current.summary;
848
+ for (const field of [
849
+ "conversations",
850
+ "total",
851
+ "attention",
852
+ "failed",
853
+ "active",
854
+ "queued",
855
+ "waiting",
856
+ "unread",
857
+ "activeWork",
858
+ ] as const)
859
+ merged[field] += summary[field];
860
+ merged.attentionSince = earliestIso(merged.attentionSince, summary.attentionSince);
861
+ merged.updatedAt = laterIso(merged.updatedAt, summary.updatedAt);
862
+ merged.createdAt = laterIso(merged.createdAt, summary.createdAt);
863
+ }
864
+ return rows;
865
+ }
866
+
867
+ /** The presentation-only row a Site's conversations nest under. */
868
+ function siteRowSession(
869
+ key: string,
870
+ origin: SessionSiteOrigin,
871
+ channelId: string | null,
872
+ latest: Session | undefined,
873
+ summary: SiteRowSummary | undefined,
874
+ options: { workspaceId?: string | undefined; creator?: Session["createdBy"] | undefined },
875
+ ): Session {
876
+ const updatedAt = laterIso(summary?.updatedAt ?? latest?.updatedAt ?? "", latest?.updatedAt);
877
+ const createdAt = laterIso(summary?.createdAt ?? latest?.createdAt ?? "", latest?.createdAt);
878
+ // Only the fields the rail reads for ordering, grouping and links. It is
879
+ // never sent to the server or used for a session action.
880
+ return {
881
+ id: key,
882
+ workspaceId: latest?.workspaceId ?? options.workspaceId ?? "",
883
+ accountId: latest?.accountId ?? "",
884
+ rootSessionId: key,
885
+ parentSessionId: null,
886
+ channelId,
887
+ status: "idle",
888
+ title: origin.title,
889
+ displayTitle: origin.title,
890
+ renameSeed: origin.title,
891
+ titleSource: "user",
892
+ createdBy: latest?.createdBy ?? options.creator ?? { kind: "subject", subjectId: "" },
893
+ effectiveControl: { state: "active" },
894
+ inputWait: null,
895
+ pinned: false,
896
+ pinnedAt: null,
897
+ archived: false,
898
+ archivedAt: null,
899
+ unread: false,
900
+ activelyWorking: false,
901
+ lastSequence: 0,
902
+ treeStats: undefined,
903
+ scheduledTaskId: null,
904
+ siteOrigin: origin,
905
+ metadata: { _opengeniSiteOrigin: origin },
906
+ createdAt,
907
+ updatedAt,
908
+ } as unknown as Session;
909
+ }
910
+
911
+ /**
912
+ * Fold Site conversations into stable Site rows. `groups` are the complete
913
+ * rows from the server; loaded conversations (an expanded Site, the open
914
+ * session, a legacy labelled chat) join their row, so which session is
915
+ * selected never decides whether a Site or its conversations are listed.
916
+ * Pins have already been split out.
917
+ */
918
+ export function attachSiteRows(
919
+ roots: SessionTreeNode[],
920
+ options: {
921
+ groups?: readonly SiteConversationGroup[] | undefined;
922
+ /** Rows per project when the rail shows projects. */
923
+ byProject?: boolean | undefined;
924
+ workspaceId?: string | undefined;
925
+ creator?: Session["createdBy"] | undefined;
926
+ } = {},
927
+ ): SessionTreeNode[] {
928
+ const byProject = options.byProject ?? false;
929
+ const rows = new Map<
930
+ string,
931
+ {
932
+ origin: SessionSiteOrigin;
933
+ channelId: string | null;
934
+ summary?: SiteRowSummary | undefined;
935
+ members: SessionTreeNode[];
936
+ }
937
+ >();
938
+ for (const [key, row] of siteRowSummaries(options.groups ?? [], byProject))
939
+ rows.set(key, { ...row, members: [] });
940
+ const rest: SessionTreeNode[] = [];
779
941
  for (const node of roots) {
780
942
  const origin = sessionSiteOrigin(node.session);
781
- if (!origin || node.session.channelId || node.session.parentSessionId) continue;
782
- const members = groups.get(origin.siteId) ?? [];
783
- members.push(node);
784
- groups.set(origin.siteId, members);
943
+ if (!origin || node.session.parentSessionId) {
944
+ rest.push(node);
945
+ continue;
946
+ }
947
+ const channelId = node.session.channelId ?? null;
948
+ const key = siteRowKey(origin.siteId, byProject ? channelId : undefined);
949
+ const row = rows.get(key) ?? { origin, channelId, members: [] };
950
+ row.members.push(node);
951
+ rows.set(key, row);
785
952
  }
786
- const emitted = new Set<string>();
787
- return roots.flatMap((node) => {
788
- const origin = sessionSiteOrigin(node.session);
789
- const members =
790
- origin && !node.session.channelId && !node.session.parentSessionId
791
- ? groups.get(origin.siteId)
792
- : undefined;
793
- if (!members || !origin) return [node];
794
- if (emitted.has(origin.siteId)) return [];
795
- emitted.add(origin.siteId);
796
- members.sort((a, b) => compareSessionActivity(a.session, b.session));
797
- const latest = members[0]!;
798
- return [
799
- {
800
- siteGroup: origin,
801
- session: { ...latest.session, id: `site:${origin.siteId}`, treeStats: undefined },
802
- children: members,
803
- hasActiveDescendant: members.some(nodeIsActive),
804
- },
805
- ];
953
+ const siteRows = [...rows].map(([key, row]): SessionTreeNode => {
954
+ const members = row.members.sort((a, b) => compareSessionActivity(a.session, b.session));
955
+ const summary = row.summary;
956
+ return {
957
+ siteGroup: row.origin,
958
+ ...(summary ? { siteSummary: summary } : {}),
959
+ session: siteRowSession(
960
+ key,
961
+ row.origin,
962
+ row.channelId,
963
+ members[0]?.session,
964
+ summary,
965
+ options,
966
+ ),
967
+ children: members,
968
+ hasActiveDescendant:
969
+ members.some(nodeIsActive) ||
970
+ Boolean(summary && summary.active + summary.queued + summary.attention > 0),
971
+ };
806
972
  });
973
+ return [...rest, ...siteRows];
974
+ }
975
+
976
+ /**
977
+ * How many conversations a Site row stands for, loaded or not. The server
978
+ * counts Site conversations; an older chat that only carries a Site label
979
+ * joins the row when loaded, so the count can grow by those on expansion.
980
+ */
981
+ export function siteRowConversationCount(node: SessionTreeNode): number {
982
+ return Math.max(node.siteSummary?.conversations ?? 0, node.children.length);
807
983
  }
808
984
 
809
985
  export function categorizeRailRoots(
@@ -1076,7 +1252,15 @@ export function projectRailSessions<T extends Session>(sessions: T[], hierarchyM
1076
1252
  export function buildPinnedRailSections(
1077
1253
  sessions: Session[],
1078
1254
  now: Date = new Date(),
1079
- options: { groupSites?: boolean | undefined } = {},
1255
+ options: {
1256
+ groupSites?: boolean | undefined;
1257
+ /** Complete Site rows from a grouped root page. */
1258
+ siteGroups?: readonly SiteConversationGroup[] | undefined;
1259
+ /** Split Site rows by project (the rail's project view). */
1260
+ siteRowsByProject?: boolean | undefined;
1261
+ workspaceId?: string | undefined;
1262
+ creator?: Session["createdBy"] | undefined;
1263
+ } = {},
1080
1264
  ): PinnedRailSections {
1081
1265
  const complete = buildRailForest(sessions, now);
1082
1266
  const roots = forestRoots(complete);
@@ -1109,7 +1293,12 @@ export function buildPinnedRailSections(
1109
1293
  ordinary: categorizeRailRoots(
1110
1294
  options.groupSites === false
1111
1295
  ? groupScheduledRuns(ordinaryRoots)
1112
- : groupSiteConversations(groupScheduledRuns(ordinaryRoots)),
1296
+ : attachSiteRows(groupScheduledRuns(ordinaryRoots), {
1297
+ groups: options.siteGroups,
1298
+ byProject: options.siteRowsByProject,
1299
+ workspaceId: options.workspaceId,
1300
+ creator: options.creator,
1301
+ }),
1113
1302
  now,
1114
1303
  ),
1115
1304
  };
@@ -0,0 +1,48 @@
1
+ import { useEffect } from "react";
2
+
3
+ const SITE_OPENED_EVENT = "opengeni:site-opened";
4
+
5
+ type SiteOpenedDetail = { workspaceId: string; siteId: string };
6
+
7
+ /** Opening a Site in the app counts as activity on its sidebar row. */
8
+ export function useRecordSiteOpened(
9
+ client: { recordSiteOpened?: (workspaceId: string, siteId: string) => Promise<unknown> },
10
+ workspaceId: string,
11
+ siteId: string,
12
+ ): void {
13
+ useEffect(() => {
14
+ if (typeof client.recordSiteOpened !== "function") return;
15
+ let current = true;
16
+ client
17
+ .recordSiteOpened(workspaceId, siteId)
18
+ .then(() => {
19
+ if (!current) return;
20
+ window.dispatchEvent(
21
+ new CustomEvent<SiteOpenedDetail>(SITE_OPENED_EVENT, { detail: { workspaceId, siteId } }),
22
+ );
23
+ })
24
+ // Ordering is a convenience: a server without it, or a failed write,
25
+ // leaves the Site and its row as they were.
26
+ .catch(() => undefined);
27
+ return () => {
28
+ current = false;
29
+ };
30
+ }, [client, workspaceId, siteId]);
31
+ }
32
+
33
+ /** Calls `onOpened` after this workspace records a Site open. */
34
+ export function useSiteOpenedListener(
35
+ workspaceId: string,
36
+ onOpened: () => void,
37
+ enabled = true,
38
+ ): void {
39
+ useEffect(() => {
40
+ if (!enabled) return;
41
+ const listener = (event: Event) => {
42
+ const detail = (event as CustomEvent<SiteOpenedDetail>).detail;
43
+ if (detail?.workspaceId === workspaceId) onOpened();
44
+ };
45
+ window.addEventListener(SITE_OPENED_EVENT, listener);
46
+ return () => window.removeEventListener(SITE_OPENED_EVENT, listener);
47
+ }, [workspaceId, onOpened, enabled]);
48
+ }
@@ -1,8 +1,19 @@
1
1
  import { expect, test } from "bun:test";
2
- import { buildPinnedRailSections, summarizeRailNodes, visibleTreeRows } from "./sessions-group";
2
+ import type { SiteConversationGroup } from "@opengeni/sdk";
3
+ import {
4
+ buildPinnedRailSections,
5
+ channelRailSections,
6
+ parseSiteRowKey,
7
+ siteRowConversationCount,
8
+ siteRowKey,
9
+ summarizeRailNodes,
10
+ visibleTreeRows,
11
+ type SessionTreeNode,
12
+ } from "./sessions-group";
3
13
  import type { Session } from "../types";
4
14
 
5
15
  const siteId = "11111111-1111-4111-8111-111111111111";
16
+ const otherSiteId = "22222222-2222-4222-8222-222222222222";
6
17
  function session(id: string, patch: Partial<Session> = {}): Session {
7
18
  return {
8
19
  id,
@@ -36,17 +47,173 @@ test("Site group has stable identity, real children, aggregate activity and no d
36
47
  ).toEqual(["newer", "older"]);
37
48
  expect(running.parentSessionId).toBeNull();
38
49
  });
39
- test("projects and pins win, while Site origin survives and a single unfiled chat still groups", () => {
50
+ function siteGroup(patch: Partial<SiteConversationGroup> = {}): SiteConversationGroup {
51
+ return {
52
+ siteId,
53
+ channelId: null,
54
+ title: "Analytics",
55
+ conversations: 3,
56
+ updatedAt: "2026-09-08T09:00:00.000Z",
57
+ createdAt: "2026-09-08T09:00:00.000Z",
58
+ total: 3,
59
+ attention: 0,
60
+ attentionSince: null,
61
+ failed: 0,
62
+ active: 0,
63
+ queued: 0,
64
+ waiting: 0,
65
+ unread: 0,
66
+ activeWork: 0,
67
+ ...patch,
68
+ };
69
+ }
70
+
71
+ function railRoots(result: ReturnType<typeof buildPinnedRailSections>): SessionTreeNode[] {
72
+ return [...result.ordinary.running, ...result.ordinary.grouped.flatMap((g) => g.sessions)];
73
+ }
74
+
75
+ test("pins win; projects split Site rows only when the rail shows projects", () => {
40
76
  const placed = session("project", { channelId: "project-id" });
41
77
  const pinned = session("pin", { pinned: true, pinnedAt: "2026-09-08T10:00:00Z" });
42
- const result = buildPinnedRailSections([placed, pinned, session("unfiled")]);
78
+ const sessions = [placed, pinned, session("unfiled")];
79
+ const result = buildPinnedRailSections(sessions);
43
80
  expect(result.pinned.map((n) => n.session.id)).toEqual(["pin"]);
44
- const roots = [...result.ordinary.running, ...result.ordinary.grouped.flatMap((g) => g.sessions)];
45
- expect(roots.find((n) => n.session.id === "project")?.siteGroup).toBeUndefined();
46
- expect(roots.find((n) => n.siteGroup)?.children.map((n) => n.session.id)).toEqual(["unfiled"]);
81
+ expect(
82
+ railRoots(result).map((n) => [n.session.id, n.children.map((c) => c.session.id).sort()]),
83
+ ).toEqual([[`site:${siteId}`, ["project", "unfiled"]]]);
84
+ const byProject = buildPinnedRailSections(sessions, new Date(), { siteRowsByProject: true });
85
+ const sections = channelRailSections(byProject.ordinary, [
86
+ { id: "project-id", name: "Project" } as never,
87
+ ]);
88
+ expect(
89
+ sections.map((section) => [
90
+ section.channelId,
91
+ section.sessions.map((n) => [n.session.id, n.children.map((c) => c.session.id)]),
92
+ ]),
93
+ ).toEqual(
94
+ expect.arrayContaining([
95
+ ["project-id", [[siteRowKey(siteId, "project-id"), ["project"]]]],
96
+ [null, [[siteRowKey(siteId, null), ["unfiled"]]]],
97
+ ]),
98
+ );
47
99
  expect(placed.metadata._opengeniSiteOrigin).toBeDefined();
48
100
  });
49
101
 
102
+ test("Site rows are complete from the server and never depend on the open session", () => {
103
+ const ordinary = session("ordinary", {
104
+ metadata: {},
105
+ updatedAt: "2026-09-08T08:00:00Z",
106
+ });
107
+ const nested = session("nested", { updatedAt: "2026-09-08T09:00:00Z" });
108
+ const groups = [
109
+ siteGroup(),
110
+ siteGroup({ siteId: otherSiteId, title: "Budget", conversations: 1 }),
111
+ ];
112
+ const build = (loaded: Session[]) =>
113
+ railRoots(buildPinnedRailSections(loaded, new Date(), { siteGroups: groups }));
114
+ // The nested conversation is open: the route injects it into the rail.
115
+ const whileOpen = build([ordinary, nested]);
116
+ const site = whileOpen.find((n) => n.session.id === `site:${siteId}`)!;
117
+ expect(site.children.map((n) => n.session.id)).toEqual(["nested"]);
118
+ expect(siteRowConversationCount(site)).toBe(3);
119
+ expect(visibleTreeRows(whileOpen, new Set(), "nested").map((r) => r.node.session.id)).toContain(
120
+ "nested",
121
+ );
122
+ // Another session is selected, so the conversation is no longer injected.
123
+ // Both Sites keep their rows and counts; nothing appears at the top level.
124
+ const afterSelectingAnother = build([ordinary]);
125
+ expect(afterSelectingAnother.map((n) => n.session.id).sort()).toEqual(
126
+ ["ordinary", `site:${otherSiteId}`, `site:${siteId}`].sort(),
127
+ );
128
+ const stable = afterSelectingAnother.find((n) => n.session.id === `site:${siteId}`)!;
129
+ expect(stable.siteGroup).toEqual({ siteId, title: "Analytics" });
130
+ expect(siteRowConversationCount(stable)).toBe(3);
131
+ expect(
132
+ visibleTreeRows(afterSelectingAnother, new Set(), "ordinary").map((r) => r.node.session.id),
133
+ ).toEqual(["ordinary"]);
134
+ // Expanding lists the Site's loaded conversations under the same row.
135
+ const expanded = build([
136
+ ordinary,
137
+ nested,
138
+ session("older", { updatedAt: "2026-09-08T07:00:00Z" }),
139
+ ]);
140
+ expect(
141
+ visibleTreeRows(expanded, new Set([`site:${siteId}`]), "ordinary")
142
+ .map((r) => r.node.session.id)
143
+ .filter((id) => id !== "ordinary"),
144
+ ).toEqual(["nested", "older"]);
145
+ });
146
+
147
+ test("Site rows sort by activity among ordinary rows and summarize complete counts", () => {
148
+ const recent = session("recent", { metadata: {}, updatedAt: "2026-09-08T12:00:00Z" });
149
+ const old = session("old", { metadata: {}, updatedAt: "2026-09-08T06:00:00Z" });
150
+ const result = buildPinnedRailSections([recent, old], new Date("2026-09-08T13:00:00Z"), {
151
+ siteGroups: [siteGroup({ total: 4, unread: 2 })],
152
+ });
153
+ expect(railRoots(result).map((n) => n.session.id)).toEqual(["recent", `site:${siteId}`, "old"]);
154
+ const site = railRoots(result)[1]!;
155
+ expect(summarizeRailNodes([site])).toMatchObject({ kind: "unread", count: 2, total: 4 });
156
+ // Live or waiting conversations float their Site row with the running rows.
157
+ for (const live of [{ active: 1 }, { attention: 1, attentionSince: "2026-09-08T08:30:00Z" }]) {
158
+ const running = buildPinnedRailSections([recent], new Date(), {
159
+ siteGroups: [siteGroup(live)],
160
+ });
161
+ expect(running.ordinary.running.map((n) => n.session.id)).toEqual([`site:${siteId}`]);
162
+ }
163
+ });
164
+
165
+ test("a Site without conversations is a plain row in its creating chat's project", () => {
166
+ const chat = session("chat", {
167
+ metadata: {},
168
+ channelId: "project-id",
169
+ updatedAt: "2026-09-08T11:00:00Z",
170
+ });
171
+ const older = session("older", { metadata: {}, updatedAt: "2026-09-08T06:00:00Z" });
172
+ const created = siteGroup({
173
+ channelId: "project-id",
174
+ conversations: 0,
175
+ total: 0,
176
+ updatedAt: "2026-09-08T10:00:00Z",
177
+ });
178
+ const result = buildPinnedRailSections([chat, older], new Date("2026-09-08T13:00:00Z"), {
179
+ siteGroups: [created],
180
+ siteRowsByProject: true,
181
+ });
182
+ const sections = channelRailSections(result.ordinary, [
183
+ { id: "project-id", name: "Project" } as never,
184
+ ]);
185
+ const project = sections.find((section) => section.channelId === "project-id")!;
186
+ // Top-level beside the chat that made it, ordered by its own activity.
187
+ expect(project.sessions.map((n) => n.session.id)).toEqual([
188
+ "chat",
189
+ siteRowKey(siteId, "project-id"),
190
+ ]);
191
+ const site = project.sessions[1]!;
192
+ expect(site.children).toEqual([]);
193
+ expect(siteRowConversationCount(site)).toBe(0);
194
+ expect(summarizeRailNodes([site])).toMatchObject({ total: 0 });
195
+ // Opening it later is newer activity, so it moves above the chat.
196
+ const opened = buildPinnedRailSections([chat, older], new Date("2026-09-08T13:00:00Z"), {
197
+ siteGroups: [{ ...created, updatedAt: "2026-09-08T12:30:00Z" }],
198
+ siteRowsByProject: true,
199
+ });
200
+ expect(
201
+ channelRailSections(opened.ordinary, [{ id: "project-id", name: "Project" } as never])
202
+ .find((section) => section.channelId === "project-id")!
203
+ .sessions.map((n) => n.session.id),
204
+ ).toEqual([siteRowKey(siteId, "project-id"), "chat"]);
205
+ });
206
+
207
+ test("Site row keys round-trip their Site and project", () => {
208
+ expect(parseSiteRowKey(siteRowKey(siteId))).toEqual({ siteId });
209
+ expect(parseSiteRowKey(siteRowKey(siteId, null))).toEqual({ siteId, channelId: null });
210
+ expect(parseSiteRowKey(siteRowKey(siteId, "project-id"))).toEqual({
211
+ siteId,
212
+ channelId: "project-id",
213
+ });
214
+ expect(parseSiteRowKey(siteId)).toBeNull();
215
+ });
216
+
50
217
  test("search and custom browse can keep matched conversations flat", () => {
51
218
  const result = buildPinnedRailSections([session("one"), session("two")], new Date(), {
52
219
  groupSites: false,
@@ -0,0 +1,55 @@
1
+ import { expect, test } from "bun:test";
2
+ import { railRouteSelection, siteViewSearch, workspaceSitePath } from "./routes";
3
+
4
+ const workspaceId = "11111111-1111-4111-8111-111111111111";
5
+ const siteId = "22222222-2222-4222-8222-222222222222";
6
+ const sessionId = "33333333-3333-4333-8333-333333333333";
7
+
8
+ test("the rail marks a session page's session", () => {
9
+ expect(
10
+ railRouteSelection({
11
+ pathname: `/workspaces/${workspaceId}/sessions/${sessionId}`,
12
+ search: {},
13
+ }),
14
+ ).toEqual({ sessionId, siteId: null });
15
+ });
16
+
17
+ test("the rail marks a Site view's Site, and its selected conversation", () => {
18
+ const pathname = `/workspaces/${workspaceId}/sites/${siteId}`;
19
+ expect(railRouteSelection({ pathname, search: {} })).toEqual({ sessionId: null, siteId });
20
+ expect(railRouteSelection({ pathname, search: { conversation: sessionId } })).toEqual({
21
+ sessionId,
22
+ siteId,
23
+ });
24
+ // A malformed conversation selects nothing rather than an arbitrary row.
25
+ expect(railRouteSelection({ pathname, search: { conversation: "../x" } })).toEqual({
26
+ sessionId: null,
27
+ siteId,
28
+ });
29
+ });
30
+
31
+ test("other pages mark nothing", () => {
32
+ for (const pathname of [
33
+ `/workspaces/${workspaceId}/artifacts/${siteId}`,
34
+ `/workspaces/${workspaceId}/sites`,
35
+ `/workspaces/${workspaceId}/sites/${siteId}/extra`,
36
+ // Not a Site id, including a malformed escape that can't be decoded.
37
+ `/workspaces/${workspaceId}/sites/%E0`,
38
+ `/workspaces/${workspaceId}/sites/not-a-site`,
39
+ ])
40
+ expect(railRouteSelection({ pathname, search: { conversation: sessionId } })).toEqual({
41
+ sessionId: null,
42
+ siteId: null,
43
+ });
44
+ });
45
+
46
+ test("Site view links and search", () => {
47
+ expect(workspaceSitePath(workspaceId, siteId)).toBe(`/workspaces/${workspaceId}/sites/${siteId}`);
48
+ expect(workspaceSitePath(workspaceId, siteId, sessionId)).toBe(
49
+ `/workspaces/${workspaceId}/sites/${siteId}?conversation=${sessionId}`,
50
+ );
51
+ expect(siteViewSearch({ conversation: sessionId, other: 1 })).toEqual({
52
+ conversation: sessionId,
53
+ });
54
+ expect(siteViewSearch({ conversation: 42 })).toEqual({ conversation: undefined });
55
+ });
@@ -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);