@opengeni/react 6.8.0 → 6.8.1-canary.41842879332001

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 (685) hide show
  1. package/dist/app/app-state.js +8 -8
  2. package/dist/app/components/Composer.js +18 -18
  3. package/dist/app/components/agent/agent-capability-picker.js +6 -6
  4. package/dist/app/components/artifacts/artifact-library.js +6 -6
  5. package/dist/app/components/artifacts/artifact-viewer.js +18 -18
  6. package/dist/app/components/artifacts/chat-interactive-block.js +11 -11
  7. package/dist/app/components/artifacts/file-reach-dialog.js +6 -6
  8. package/dist/app/components/artifacts/inline-chat-image.js +19 -19
  9. package/dist/app/components/artifacts/retained-file-preview.js +20 -20
  10. package/dist/app/components/artifacts/retained-text-preview.js +3 -3
  11. package/dist/app/components/artifacts/site-audience.js +3 -3
  12. package/dist/app/components/artifacts/site-conversations.js +9 -9
  13. package/dist/app/components/artifacts/site-data.js +10 -10
  14. package/dist/app/components/artifacts/site-publishing-page.js +25 -25
  15. package/dist/app/components/artifacts/site-publishing.js +22 -22
  16. package/dist/app/components/artifacts/site-settings.js +24 -24
  17. package/dist/app/components/artifacts/site-version-menu.js +3 -3
  18. package/dist/app/components/billing-class-mark.js +3 -3
  19. package/dist/app/components/bots/bot-launch-strip.js +20 -20
  20. package/dist/app/components/bots/bot-template-dialog.js +26 -26
  21. package/dist/app/components/bots/bot-template-shortcuts.js +20 -20
  22. package/dist/app/components/bots/bot-templates-page.js +30 -30
  23. package/dist/app/components/capabilities/capability-detail-sheet.js +6 -6
  24. package/dist/app/components/capabilities/capability-logo-source.js +13 -13
  25. package/dist/app/components/capabilities/connector-tool-permissions.js +4 -4
  26. package/dist/app/components/capabilities/native-connect-setup.js +13 -13
  27. package/dist/app/components/capabilities/own-logins-shared-heads-up.js +3 -3
  28. package/dist/app/components/capabilities/prepared-mcp-setup-card.js +15 -15
  29. package/dist/app/components/capabilities/session-capability-card.js +47 -47
  30. package/dist/app/components/capabilities/session-chrome-card.js +20 -20
  31. package/dist/app/components/capabilities/session-custom-mcp-card.js +16 -16
  32. package/dist/app/components/capabilities/session-github-card.js +16 -16
  33. package/dist/app/components/capabilities/session-machine-card.js +19 -19
  34. package/dist/app/components/capabilities/session-personal-github-card.js +14 -14
  35. package/dist/app/components/capabilities/session-plugin-card.js +8 -8
  36. package/dist/app/components/command-menu/chat-status.js +15 -15
  37. package/dist/app/components/command-menu/chat-switcher.js +32 -32
  38. package/dist/app/components/command-menu/command-menu.js +36 -36
  39. package/dist/app/components/command-menu/shortcut-sheet.js +8 -8
  40. package/dist/app/components/composer-capabilities-menu-body.js +4 -4
  41. package/dist/app/components/composer-mobile-plus-panel.js +8 -8
  42. package/dist/app/components/composer-mobile-plus.js +1 -1
  43. package/dist/app/components/credit-required-gate.js +1 -1
  44. package/dist/app/components/credit-required-prompt.js +3 -3
  45. package/dist/app/components/desktop/app-shots.js +6 -6
  46. package/dist/app/components/desktop/computer-use.js +2 -2
  47. package/dist/app/components/desktop/this-computer.js +5 -5
  48. package/dist/app/components/feedback.js +3 -3
  49. package/dist/app/components/github-app-connect-launcher.js +1 -1
  50. package/dist/app/components/machines/connect-machine-dialog.js +11 -11
  51. package/dist/app/components/markdown.js +6 -6
  52. package/dist/app/components/models/models-ui.js +5 -5
  53. package/dist/app/components/my-things.js +4 -4
  54. package/dist/app/components/own-where-it-works.js +3 -3
  55. package/dist/app/components/personal-resource-attachment-surface.js +4 -4
  56. package/dist/app/components/pickers.js +5 -5
  57. package/dist/app/components/rail/channel-create-dialog.js +3 -3
  58. package/dist/app/components/rail/project-glyph.js +20 -20
  59. package/dist/app/components/rail/project-profile.js +27 -27
  60. package/dist/app/components/rail/rail-context.js +1 -1
  61. package/dist/app/components/rail/rail-sections.js +55 -55
  62. package/dist/app/components/rail/session-header.js +47 -47
  63. package/dist/app/components/rail/session-list.js +53 -53
  64. package/dist/app/components/rail/session-row-content.js +4 -4
  65. package/dist/app/components/rail/session-row-hover-details.js +14 -14
  66. package/dist/app/components/rail/session-shell.js +73 -73
  67. package/dist/app/components/rail/site-session-group-heading.js +8 -8
  68. package/dist/app/components/session/agent-configuration-panel.js +12 -12
  69. package/dist/app/components/session/banners.js +8 -8
  70. package/dist/app/components/session/console-new-conversation.js +39 -39
  71. package/dist/app/components/session/descendant-requests.js +36 -36
  72. package/dist/app/components/session/editable-artifacts-workspace.js +16 -16
  73. package/dist/app/components/session/failed-session-banner.js +6 -6
  74. package/dist/app/components/session/failure-recovery-boundary.js +3 -3
  75. package/dist/app/components/session/human-input-delegation-record.js +2 -2
  76. package/dist/app/components/session/human-input.js +33 -33
  77. package/dist/app/components/session/inspector.js +43 -43
  78. package/dist/app/components/session/message-actions.js +3 -3
  79. package/dist/app/components/session/message-resource-attachments.js +10 -10
  80. package/dist/app/components/session/model-recovery-notice.js +3 -3
  81. package/dist/app/components/session/new-session-settings-menu.js +6 -6
  82. package/dist/app/components/session/new-session-setup-strip.js +21 -21
  83. package/dist/app/components/session/sandbox-recovery-actions.js +3 -3
  84. package/dist/app/components/session/sandbox-switcher.js +7 -7
  85. package/dist/app/components/session/sandbox-workspace.js +48 -48
  86. package/dist/app/components/session/search-markdown-highlight.js +7 -7
  87. package/dist/app/components/session/search-results-view.js +8 -8
  88. package/dist/app/components/session/session-admin-access.js +4 -4
  89. package/dist/app/components/session/session-admission-notice.js +4 -4
  90. package/dist/app/components/session/session-avatar-picker.js +21 -21
  91. package/dist/app/components/session/session-avatar.js +19 -19
  92. package/dist/app/components/session/session-machine-access-notice.js +4 -4
  93. package/dist/app/components/session/session-profile-dialog.js +25 -25
  94. package/dist/app/components/session/session-profile-editor.js +26 -26
  95. package/dist/app/components/session/session-retention.js +3 -3
  96. package/dist/app/components/session/session-search-dialog.js +8 -8
  97. package/dist/app/components/session/session-tenancy-control.js +2 -2
  98. package/dist/app/components/session/session-usage-limit-section.js +4 -4
  99. package/dist/app/components/session/share-chat-dialog.js +5 -5
  100. package/dist/app/components/session/subagents.js +8 -8
  101. package/dist/app/components/session/subscription-account-indicator.js +6 -6
  102. package/dist/app/components/settings/row-select.js +4 -4
  103. package/dist/app/components/transcription-settings.js +6 -6
  104. package/dist/app/components/ui/destructive-confirm.js +5 -5
  105. package/dist/app/components/usage/usage-entry.js +3 -3
  106. package/dist/app/components/window-bar.js +9 -9
  107. package/dist/app/components/workspace-composer-plus.js +16 -16
  108. package/dist/app/components/workspace-reach.js +4 -4
  109. package/dist/app/embed/session-app.js +156 -156
  110. package/dist/app/lib/actions/actions-provider.js +8 -8
  111. package/dist/app/lib/agent-capabilities.js +3 -3
  112. package/dist/app/lib/codex-usage-query.js +2 -2
  113. package/dist/app/lib/composer-connectors.js +14 -14
  114. package/dist/app/lib/console-site.js +2 -2
  115. package/dist/app/lib/console-text.js +2 -2
  116. package/dist/app/lib/events.js +12 -12
  117. package/dist/app/lib/failed-session-copy.js +3 -3
  118. package/dist/app/lib/model-access-onboarding.js +3 -3
  119. package/dist/app/lib/move-chat-to-machine.js +3 -3
  120. package/dist/app/lib/session-branch-cache.js +8 -8
  121. package/dist/app/lib/session-create.js +4 -4
  122. package/dist/app/lib/session-group-pagination.js +8 -8
  123. package/dist/app/lib/session-hover-facts.js +13 -13
  124. package/dist/app/lib/session-model.js +2 -2
  125. package/dist/app/lib/session-pins.js +1 -1
  126. package/dist/app/lib/session-rail.js +5 -5
  127. package/dist/app/lib/session-rename.js +3 -3
  128. package/dist/app/lib/sessions-group.d.ts +5 -3
  129. package/dist/app/lib/sessions-group.js +7 -7
  130. package/dist/app/lib/site-tool-consent-dialog.js +7 -7
  131. package/dist/app/lib/site-tool-consent.js +1 -1
  132. package/dist/app/lib/turn-failure-analytics.js +4 -4
  133. package/dist/app/lib/use-follow-up-repositories.js +3 -3
  134. package/dist/app/lib/use-workspace-machines.js +4 -4
  135. package/dist/app/lib/use-workspace-model-catalog.js +3 -3
  136. package/dist/app/lib/use-workspace-rigs.js +2 -2
  137. package/dist/app/lib/workspace-navigation-preference.js +4 -4
  138. package/dist/app/lib/workspace-scope-context.js +3 -3
  139. package/dist/app/routes/artifacts.js +48 -48
  140. package/dist/app/routes/retained-artifact.js +32 -32
  141. package/dist/app/routes/session.js +94 -94
  142. package/dist/app/routes/sessions-index-hydration.js +5 -5
  143. package/dist/app/routes/sessions-index.js +76 -76
  144. package/dist/app/routes/site-view.js +55 -55
  145. package/dist/artifacts-document.js +4 -4
  146. package/dist/artifacts-presentation.js +4 -4
  147. package/dist/artifacts-spreadsheet.js +4 -4
  148. package/dist/artifacts.js +10 -10
  149. package/dist/automations.js +10 -10
  150. package/dist/{browser-viewer-ZHQDVHZ2.js → browser-viewer-H7PKY67P.js} +4 -4
  151. package/dist/{chat-interactive-block-VSDD6X3M.js → chat-interactive-block-47TCT4DN.js} +5 -5
  152. package/dist/{chunk-7Z76QP64.js → chunk-2QH3Q6Z2.js} +35 -5
  153. package/dist/chunk-2QH3Q6Z2.js.map +1 -0
  154. package/dist/{chunk-5MHMCE2G.js → chunk-2X2B6D5G.js} +3 -3
  155. package/dist/{chunk-OCXEY7HE.js → chunk-3BUI5DT7.js} +2 -2
  156. package/dist/{chunk-OSJ366KR.js → chunk-3FWP3TD3.js} +29 -29
  157. package/dist/{chunk-PWUSSSSL.js → chunk-3G5IA36N.js} +2 -2
  158. package/dist/{chunk-RGR57NYY.js → chunk-3NK4JAHL.js} +2 -2
  159. package/dist/{chunk-XUOYNJPB.js → chunk-3O7UZRWM.js} +24 -24
  160. package/dist/{chunk-JV3UI7BH.js → chunk-3OR6HMA4.js} +3 -3
  161. package/dist/{chunk-MV2CLIO6.js → chunk-3PC45I5N.js} +6 -6
  162. package/dist/{chunk-SJYTQLN3.js → chunk-3PI2BYK5.js} +3 -3
  163. package/dist/{chunk-DCEQCGVN.js → chunk-3PNA2P2Z.js} +2 -2
  164. package/dist/{chunk-ESXAECZ3.js → chunk-3XBZKF3K.js} +2 -2
  165. package/dist/{chunk-SBXSKRFA.js → chunk-45OGYO3S.js} +3 -3
  166. package/dist/{chunk-M3FDGRB4.js → chunk-4A7TKVNX.js} +3 -3
  167. package/dist/{chunk-RHXYO4H2.js → chunk-4BXRGXTD.js} +2 -2
  168. package/dist/{chunk-CV4VVLPZ.js → chunk-4HQAJA3T.js} +2 -2
  169. package/dist/{chunk-VCJQQYRE.js → chunk-4X2A3KPB.js} +4 -4
  170. package/dist/{chunk-OCXTTKVA.js → chunk-555K37A7.js} +2 -2
  171. package/dist/{chunk-EBIVTDEG.js → chunk-57L5ZXDS.js} +2 -2
  172. package/dist/{chunk-3L465FBR.js → chunk-5IADORIV.js} +6 -6
  173. package/dist/{chunk-SK5S2PCK.js → chunk-5IZQT4TE.js} +14 -14
  174. package/dist/chunk-5IZQT4TE.js.map +1 -0
  175. package/dist/{chunk-ZW5YTIH3.js → chunk-5PB46DAA.js} +1 -1
  176. package/dist/{chunk-ZW5YTIH3.js.map → chunk-5PB46DAA.js.map} +1 -1
  177. package/dist/{chunk-PVB4YVDP.js → chunk-5Y2O2432.js} +2 -2
  178. package/dist/{chunk-OOOSGPJL.js → chunk-6572EFE4.js} +1 -1
  179. package/dist/{chunk-YMI27QPF.js → chunk-6BG5HCUP.js} +2 -2
  180. package/dist/{chunk-QRECBCJM.js → chunk-6EXFJWII.js} +2 -2
  181. package/dist/{chunk-74CBR5YE.js → chunk-6PNRUGOK.js} +2 -2
  182. package/dist/{chunk-PUUEI4W3.js → chunk-6RJEY6TC.js} +5 -5
  183. package/dist/{chunk-DLVIRJGK.js → chunk-727GL2YY.js} +2 -2
  184. package/dist/{chunk-J2BTILRR.js → chunk-7FGYLFW6.js} +2 -2
  185. package/dist/{chunk-MKDFYE2E.js → chunk-7IMWTFEG.js} +2 -2
  186. package/dist/{chunk-FER6EVIY.js → chunk-7POKH54R.js} +2 -2
  187. package/dist/{chunk-H6BX6WOW.js → chunk-7T26IH6W.js} +3 -3
  188. package/dist/{chunk-R33SBMB7.js → chunk-7XQRVZZQ.js} +3 -3
  189. package/dist/{chunk-NFCS5WYC.js → chunk-A3SPPXMC.js} +3 -3
  190. package/dist/{chunk-DQPIEQGP.js → chunk-A7CWPDEH.js} +2 -2
  191. package/dist/{chunk-3PM3M2Q6.js → chunk-AGOYVKTI.js} +2 -2
  192. package/dist/{chunk-OBGOLHCP.js → chunk-AIQKZUPB.js} +3 -3
  193. package/dist/{chunk-GSCGKJNK.js → chunk-AMYDHG3S.js} +2 -2
  194. package/dist/{chunk-U4LTPFD2.js → chunk-APJPB6TX.js} +2 -2
  195. package/dist/{chunk-SP44O3OU.js → chunk-APLGT5EI.js} +2 -2
  196. package/dist/{chunk-M3HGBO2Y.js → chunk-ATNKMGLO.js} +1 -1
  197. package/dist/{chunk-4O2XWOLZ.js → chunk-AVX4CZQ3.js} +3 -3
  198. package/dist/{chunk-CXAN2FHF.js → chunk-B46MK44K.js} +6 -6
  199. package/dist/{chunk-RMCLFSMX.js → chunk-BBKUPEGG.js} +2 -2
  200. package/dist/{chunk-J2WY42FA.js → chunk-BES6OQE3.js} +2 -2
  201. package/dist/{chunk-GU7T2S5N.js → chunk-BM2N26SH.js} +2 -2
  202. package/dist/{chunk-HEGV4QMS.js → chunk-C3NS74PZ.js} +2 -2
  203. package/dist/{chunk-752WXSDN.js → chunk-C56ABB5V.js} +2 -2
  204. package/dist/{chunk-77SYIH6O.js → chunk-C6MATJQ5.js} +2 -2
  205. package/dist/{chunk-KUE5BOQE.js → chunk-CRX47CO6.js} +4 -4
  206. package/dist/{chunk-QPQ7R77C.js → chunk-CUIV2XPO.js} +3 -1
  207. package/dist/chunk-CUIV2XPO.js.map +1 -0
  208. package/dist/{chunk-GTHCHCWW.js → chunk-D33KWZQJ.js} +3 -3
  209. package/dist/{chunk-AH3DGOTK.js → chunk-D7E3BSCX.js} +2 -2
  210. package/dist/{chunk-OJWDNNW3.js → chunk-DFR3TMTZ.js} +5 -5
  211. package/dist/{chunk-WYGTAQMX.js → chunk-DICC75CU.js} +2 -2
  212. package/dist/{chunk-736RUNIA.js → chunk-DJ2LMKKX.js} +4 -4
  213. package/dist/{chunk-4F3AEJI6.js → chunk-DJI4D7PM.js} +4 -4
  214. package/dist/{chunk-LVELUUK6.js → chunk-DSZUQL4W.js} +2 -2
  215. package/dist/{chunk-MT2R57SF.js → chunk-DVF246BE.js} +2 -2
  216. package/dist/{chunk-OI6VI6SU.js → chunk-DVOWBHWN.js} +8 -8
  217. package/dist/{chunk-PZKHST7A.js → chunk-E2KPRSA4.js} +2 -2
  218. package/dist/{chunk-EKJHOWTZ.js → chunk-E3LMLWEB.js} +4 -4
  219. package/dist/{chunk-QURYQFDN.js → chunk-EDC7X7PW.js} +2 -2
  220. package/dist/{chunk-HYEIA25Y.js → chunk-EDSMULHU.js} +2 -2
  221. package/dist/{chunk-U6552Q3T.js → chunk-EQQOZ6DD.js} +2 -2
  222. package/dist/{chunk-IFSXVU2S.js → chunk-ERBDQ2GY.js} +2 -2
  223. package/dist/{chunk-IZXYFWA4.js → chunk-EWI73URG.js} +13 -13
  224. package/dist/{chunk-N3FM4BNA.js → chunk-EZ6LFN33.js} +2 -2
  225. package/dist/{chunk-4K64EKM7.js → chunk-F7YL6DPR.js} +4 -4
  226. package/dist/{chunk-ICAMYP5M.js → chunk-FIGFXMUP.js} +2 -2
  227. package/dist/{chunk-54U6ZBEX.js → chunk-FJRJK67G.js} +3 -3
  228. package/dist/{chunk-E5KOWRDU.js → chunk-FLHB2NZT.js} +2 -2
  229. package/dist/{chunk-OWET7EY2.js → chunk-FRSZSL2S.js} +19 -13
  230. package/dist/{chunk-OWET7EY2.js.map → chunk-FRSZSL2S.js.map} +1 -1
  231. package/dist/{chunk-D3PTVN2I.js → chunk-FUGGM76A.js} +2 -2
  232. package/dist/{chunk-QQIZMVAJ.js → chunk-FWLLGNGP.js} +51 -49
  233. package/dist/chunk-FWLLGNGP.js.map +1 -0
  234. package/dist/{chunk-TDTD66BK.js → chunk-FXPZAZYT.js} +2 -2
  235. package/dist/{chunk-KO3OHHY2.js → chunk-GAGAM4MT.js} +2 -2
  236. package/dist/{chunk-TK5FWVZR.js → chunk-GESGH3HY.js} +3 -3
  237. package/dist/{chunk-2VJOSU4H.js → chunk-GI4PWKXI.js} +2 -2
  238. package/dist/{chunk-KFNZZ2N6.js → chunk-GJTEBAZ7.js} +2 -2
  239. package/dist/{chunk-LTJFV2JI.js → chunk-GNCGEW7F.js} +2 -2
  240. package/dist/{chunk-34NV52R3.js → chunk-GOMUNPB6.js} +4 -4
  241. package/dist/{chunk-7YTR3UFO.js → chunk-GPWE5UD7.js} +8 -5
  242. package/dist/chunk-GPWE5UD7.js.map +1 -0
  243. package/dist/{chunk-LIJNVIT3.js → chunk-GUMUILEI.js} +3 -3
  244. package/dist/{chunk-7NLF35YL.js → chunk-GVGNHBFT.js} +4 -4
  245. package/dist/{chunk-K3D7IQQP.js → chunk-GW4YI3FB.js} +6 -6
  246. package/dist/{chunk-D5TIVCXG.js → chunk-GXKCV7X7.js} +2 -2
  247. package/dist/{chunk-2J77TWGH.js → chunk-H467EQA6.js} +3 -3
  248. package/dist/{chunk-3OK7Y6ES.js → chunk-HE77VDDR.js} +2 -2
  249. package/dist/{chunk-UO35OEOX.js → chunk-HT65RGCX.js} +3 -3
  250. package/dist/{chunk-G6ICCGJ3.js → chunk-HVQSFTE7.js} +2 -2
  251. package/dist/{chunk-G5UQBTXY.js → chunk-HXJPDC76.js} +2 -2
  252. package/dist/{chunk-GIWFLWXG.js → chunk-I6LQW24C.js} +4 -4
  253. package/dist/{chunk-467WDSOK.js → chunk-I7A6S5YL.js} +2 -2
  254. package/dist/{chunk-AAS7OWV6.js → chunk-IADS4ZYD.js} +3 -3
  255. package/dist/{chunk-Y3XZEKDQ.js → chunk-IJWMWCGR.js} +2 -2
  256. package/dist/{chunk-SGH7I7OY.js → chunk-IWFO6KOU.js} +2 -2
  257. package/dist/{chunk-GMHIOYB7.js → chunk-IYC6QGV2.js} +4 -4
  258. package/dist/{chunk-2OXSB2OL.js → chunk-J2TZIFRC.js} +3 -2
  259. package/dist/chunk-J2TZIFRC.js.map +1 -0
  260. package/dist/{chunk-3NNAC43A.js → chunk-J5AODKJO.js} +2 -2
  261. package/dist/{chunk-DIP7YALH.js → chunk-JKI3LMLH.js} +2 -2
  262. package/dist/{chunk-IJR6VOLU.js → chunk-JSYRWOCE.js} +2 -2
  263. package/dist/{chunk-CEMSIU4Z.js → chunk-JTQTWO4D.js} +5 -5
  264. package/dist/{chunk-JHZRAYI4.js → chunk-JWSRFXRN.js} +2 -2
  265. package/dist/chunk-JWSRFXRN.js.map +1 -0
  266. package/dist/{chunk-BASI553K.js → chunk-KBTKAAHM.js} +4 -4
  267. package/dist/{chunk-OYOFPNLC.js → chunk-KD7VEMWY.js} +4 -4
  268. package/dist/{chunk-3DRLCX5V.js → chunk-KPGFGRSA.js} +2 -2
  269. package/dist/{chunk-PLYVGZIN.js → chunk-KWFDEJFI.js} +1 -1
  270. package/dist/{chunk-FNXCFIPW.js → chunk-KYLEH4OF.js} +2 -2
  271. package/dist/{chunk-WXF2RTS4.js → chunk-L7FJTFJN.js} +2 -2
  272. package/dist/{chunk-KI46GKMD.js → chunk-L7VVQOSY.js} +7 -7
  273. package/dist/{chunk-M5IQVMLR.js → chunk-LAZ2QZTJ.js} +11 -4
  274. package/dist/chunk-LAZ2QZTJ.js.map +1 -0
  275. package/dist/chunk-LKLQVANM.js +2 -0
  276. package/dist/{chunk-YNTLWCF4.js → chunk-LLYEAZ4E.js} +3 -3
  277. package/dist/{chunk-4Z5X7PLC.js → chunk-LWM7JUW6.js} +3 -3
  278. package/dist/{chunk-CHU3RDV4.js → chunk-LXKV4ND3.js} +3 -3
  279. package/dist/{chunk-AB5IW227.js → chunk-LYLICEQO.js} +3 -3
  280. package/dist/{chunk-PSM3CU7N.js → chunk-M3OZOCIK.js} +46 -39
  281. package/dist/chunk-M3OZOCIK.js.map +1 -0
  282. package/dist/{chunk-OTW25A6I.js → chunk-M5GRI5K4.js} +3 -3
  283. package/dist/{chunk-X2QJXDE4.js → chunk-MF65PKKF.js} +8 -8
  284. package/dist/{chunk-EDDKPIIV.js → chunk-MJ4XIOPM.js} +2 -2
  285. package/dist/{chunk-FLWQJDJ5.js → chunk-MMPJJQG3.js} +6 -6
  286. package/dist/{chunk-T67LTMSW.js → chunk-MOU54FGD.js} +10 -10
  287. package/dist/{chunk-LQKVNREV.js → chunk-NAWHQ4IL.js} +3 -3
  288. package/dist/{chunk-ZBHGNE2J.js → chunk-NBHBB2VV.js} +3 -3
  289. package/dist/{chunk-PF2WU2IL.js → chunk-ND4IQJUM.js} +120 -17
  290. package/dist/chunk-ND4IQJUM.js.map +1 -0
  291. package/dist/{chunk-U5UGM5XD.js → chunk-NMOZDAEZ.js} +5 -5
  292. package/dist/{chunk-D74Z2N4K.js → chunk-NZA4R3BE.js} +2 -2
  293. package/dist/{chunk-WRMUXZ7C.js → chunk-OB2CX7PJ.js} +3 -3
  294. package/dist/{chunk-YJSCLGAW.js → chunk-OB4I4OIT.js} +3 -3
  295. package/dist/{chunk-DWJ6J3YW.js → chunk-OKQW2FPL.js} +4 -4
  296. package/dist/{chunk-2GCHGWNE.js → chunk-ORLX6A3C.js} +3 -3
  297. package/dist/{chunk-EBTUPRRQ.js → chunk-P5N4EYFW.js} +4 -4
  298. package/dist/{chunk-JKL5S7UQ.js → chunk-PL4JE3NI.js} +6 -6
  299. package/dist/{chunk-OP2GD6QW.js → chunk-PNUHKDY2.js} +2 -2
  300. package/dist/{chunk-MZY3VKKM.js → chunk-PWJE7D6V.js} +2 -2
  301. package/dist/{chunk-RISUROBM.js → chunk-PYE27I6J.js} +4 -4
  302. package/dist/{chunk-SPD4ULVB.js → chunk-PYMROAWS.js} +2 -1
  303. package/dist/chunk-PYMROAWS.js.map +1 -0
  304. package/dist/{chunk-Q5K2J5GG.js → chunk-Q74FQK3A.js} +13 -3
  305. package/dist/chunk-Q74FQK3A.js.map +1 -0
  306. package/dist/{chunk-R5QAL43H.js → chunk-QIJHK6P4.js} +2 -2
  307. package/dist/{chunk-AJBDAVX3.js → chunk-QK3A23NP.js} +7 -7
  308. package/dist/{chunk-CYDXCILL.js → chunk-QLWDNAOV.js} +7 -7
  309. package/dist/{chunk-BQYRZIZ7.js → chunk-QS6DQBVJ.js} +2 -2
  310. package/dist/{chunk-3PZ3LRPV.js → chunk-QSUVFPG3.js} +3 -3
  311. package/dist/{chunk-PYB4BFEC.js → chunk-QUC5MLTN.js} +3 -3
  312. package/dist/{chunk-WDASYY4S.js → chunk-QVT5AWPI.js} +6 -6
  313. package/dist/{chunk-K4DQS2ML.js → chunk-QZC6WCBR.js} +4 -4
  314. package/dist/{chunk-HWVPLFIW.js → chunk-RAHNICPP.js} +2 -2
  315. package/dist/{chunk-H6MJFMHZ.js → chunk-RME6RGIW.js} +3 -3
  316. package/dist/{chunk-XMBOLFFS.js → chunk-RQIB2F53.js} +2 -2
  317. package/dist/{chunk-OXQ2SXVC.js → chunk-RUA72NQY.js} +2 -2
  318. package/dist/{chunk-UMX6DZME.js → chunk-SCJHWN4X.js} +2 -2
  319. package/dist/{chunk-HTMQGS63.js → chunk-SIXBDT5F.js} +8 -8
  320. package/dist/{chunk-ZAX4XQLN.js → chunk-SPK3T4JK.js} +2 -2
  321. package/dist/{chunk-WTSQUCHB.js → chunk-SSN2YSST.js} +3 -3
  322. package/dist/{chunk-5MIBQ4P5.js → chunk-SYJCDX5V.js} +2 -2
  323. package/dist/{chunk-NQ2CPQJF.js → chunk-SYL7LCRA.js} +26 -3
  324. package/dist/chunk-SYL7LCRA.js.map +1 -0
  325. package/dist/{chunk-ZR5EKJT6.js → chunk-T6276OXI.js} +2 -2
  326. package/dist/{chunk-DEHLWZSI.js → chunk-T7OARG4N.js} +4 -4
  327. package/dist/{chunk-77BHKC43.js → chunk-TF5L3BEV.js} +1 -1
  328. package/dist/{chunk-GOCODNQS.js → chunk-TF6Z7BOP.js} +2 -2
  329. package/dist/{chunk-WIFDNUKD.js → chunk-TJDXWZMO.js} +3 -3
  330. package/dist/{chunk-SFIXTOOJ.js → chunk-TL5ATBHZ.js} +3 -3
  331. package/dist/{chunk-XZCCEKPW.js → chunk-TMOHIOMT.js} +6 -6
  332. package/dist/{chunk-AVXDIRRW.js → chunk-UI5X63YC.js} +2 -2
  333. package/dist/{chunk-6QK65ZWM.js → chunk-UIY7BDZC.js} +3 -3
  334. package/dist/{chunk-VATYK3JQ.js → chunk-UMBFMEO7.js} +3 -3
  335. package/dist/{chunk-UU5FBVRX.js → chunk-UU5G7OA4.js} +2 -2
  336. package/dist/{chunk-EGKARC53.js → chunk-UZUCYCF4.js} +2 -2
  337. package/dist/{chunk-LPKJ77EK.js → chunk-V2A7G7S7.js} +2 -2
  338. package/dist/{chunk-CH4UQ4NO.js → chunk-V5G4TKRC.js} +5 -5
  339. package/dist/{chunk-UBRQ3PQD.js → chunk-VKAVW34W.js} +2 -2
  340. package/dist/{chunk-JV5ULONH.js → chunk-VVLEVNTQ.js} +36 -36
  341. package/dist/{chunk-44JWVYJB.js → chunk-VW7X7TWZ.js} +2 -2
  342. package/dist/{chunk-3CDJSKDW.js → chunk-VWA2CHSL.js} +3 -3
  343. package/dist/{chunk-IN3VQFKS.js → chunk-W43HZPM7.js} +2 -2
  344. package/dist/{chunk-SXGJL7UT.js → chunk-WHGD7Q2L.js} +14 -14
  345. package/dist/{chunk-XOIDUM2H.js → chunk-WNXKYEVN.js} +1 -1
  346. package/dist/{chunk-TKQL7EDB.js → chunk-WSA7UBX4.js} +2 -2
  347. package/dist/{chunk-AJDGP2N4.js → chunk-WZ5TQJ3T.js} +19 -19
  348. package/dist/{chunk-FBA2NXYH.js → chunk-X3TGNSOG.js} +3 -3
  349. package/dist/{chunk-R4JA5JFI.js → chunk-X4WXYI3N.js} +3 -3
  350. package/dist/{chunk-Q5EZNBPI.js → chunk-XIQ3AIAJ.js} +3 -3
  351. package/dist/{chunk-S27VZ5DO.js → chunk-XWYT4LEL.js} +6 -6
  352. package/dist/{chunk-477DTTMH.js → chunk-Y3PU75OC.js} +3 -3
  353. package/dist/{chunk-4JXPLTWV.js → chunk-Y5ZWX5YS.js} +2 -2
  354. package/dist/{chunk-4BWMAGJJ.js → chunk-YA5PABND.js} +3 -3
  355. package/dist/{chunk-VXORMNU4.js → chunk-YBHAAULA.js} +67 -2
  356. package/dist/chunk-YBHAAULA.js.map +1 -0
  357. package/dist/{chunk-OGU73VUN.js → chunk-YBPRR2QS.js} +2 -2
  358. package/dist/{chunk-TNSJFZ6Q.js → chunk-YDYR7XQE.js} +4 -4
  359. package/dist/{chunk-GTRAH4FG.js → chunk-YG6V2LQH.js} +2 -2
  360. package/dist/{chunk-XVLEBB4Y.js → chunk-YUXA7ALE.js} +2 -2
  361. package/dist/{chunk-SN2WENRP.js → chunk-YWHQDXPB.js} +3 -3
  362. package/dist/{chunk-BFFNINCC.js → chunk-YWRR5R7B.js} +3 -3
  363. package/dist/{chunk-FSDQQQIA.js → chunk-YYRK7A4N.js} +3 -3
  364. package/dist/{chunk-MRECRNVU.js → chunk-Z26CDLUV.js} +5 -5
  365. package/dist/{chunk-OYCK4JRS.js → chunk-Z27EXLMQ.js} +2 -2
  366. package/dist/{chunk-UTRNLNCW.js → chunk-Z7GDH7W2.js} +3 -3
  367. package/dist/{chunk-PRT4J2DL.js → chunk-ZGVLSAWL.js} +2 -2
  368. package/dist/{chunk-OK7BQMCI.js → chunk-ZM6Q5NQN.js} +9 -9
  369. package/dist/components/message-timeline.d.ts +10 -2
  370. package/dist/composer.js +8 -8
  371. package/dist/{computer-viewer-5LKRCEVQ.js → computer-viewer-SROXREYD.js} +5 -5
  372. package/dist/connect.js +12 -12
  373. package/dist/desktop-dictation.js +8 -8
  374. package/dist/desktop.js +2 -2
  375. package/dist/editor.js +2 -2
  376. package/dist/{embedded-new-voice-GHJRY3YL.js → embedded-new-voice-EIQY2VBF.js} +5 -5
  377. package/dist/{embedded-voice-ASQXBSTX.js → embedded-voice-LMWNH7F7.js} +5 -5
  378. package/dist/{fleet-decision-row-U7LDVBEM.js → fleet-decision-row-X2G56ZRA.js} +2 -2
  379. package/dist/hooks/use-recordings.d.ts +4 -2
  380. package/dist/in-chat-connect-model.js +5 -5
  381. package/dist/index.d.ts +2 -2
  382. package/dist/index.js +66 -60
  383. package/dist/interaction.js +5 -5
  384. package/dist/{latest-question-RNVF262Q.js → latest-question-KA7AQYVI.js} +2 -2
  385. package/dist/machines.js +3 -3
  386. package/dist/meetings/recorder-context.d.ts +6 -1
  387. package/dist/meetings/recorder-panel.d.ts +2 -5
  388. package/dist/meetings-recorder.js +1 -1
  389. package/dist/meetings.js +22 -21
  390. package/dist/meetings.js.map +1 -1
  391. package/dist/messages/en.d.ts +2 -0
  392. package/dist/messages.js +1 -1
  393. package/dist/{model-policy-picker-menu-E6XKMFTA.js → model-policy-picker-menu-SHWPT5VA.js} +4 -4
  394. package/dist/{payment-page-card-DJDKV2LW.js → payment-page-card-NNVUISN4.js} +4 -4
  395. package/dist/{platform-activity-row-MSDCSMET.js → platform-activity-row-7UDWSAHK.js} +2 -2
  396. package/dist/{queue-surface-implementation-GUAIG6TK.js → queue-surface-implementation-BUXSO24N.js} +5 -5
  397. package/dist/realtime.js +4 -4
  398. package/dist/{recorder-host-2MYDJPQW.js → recorder-host-POX54CFT.js} +5 -5
  399. package/dist/recordings.js +4 -4
  400. package/dist/{sandbox-files-W5W2LW4K.js → sandbox-files-33QD7DW2.js} +6 -6
  401. package/dist/session-app.js +156 -156
  402. package/dist/{session-connect-cards-HPH7JOZP.js → session-connect-cards-CXGNVA2A.js} +9 -9
  403. package/dist/session-list-model.js +2 -2
  404. package/dist/{session-realtime-SDTKFFIR.js → session-realtime-CVDSEULB.js} +3 -3
  405. package/dist/session-realtime.js +2 -2
  406. package/dist/session-ui.js +33 -33
  407. package/dist/session.d.ts +3 -2
  408. package/dist/session.js +16 -10
  409. package/dist/sites.js +2 -2
  410. package/dist/terminal.js +2 -2
  411. package/dist/this-computer.js +3 -3
  412. package/dist/timeline/index.d.ts +3 -2
  413. package/dist/timeline/projection.d.ts +52 -0
  414. package/dist/timeline/turn-summary-model.d.ts +4 -3
  415. package/dist/timeline/types.d.ts +8 -2
  416. package/dist/timeline/use-timeline-pauses.d.ts +12 -0
  417. package/dist/timeline/work-presentation.d.ts +4 -3
  418. package/dist/{timeline-annotation-markers-FNILLWNU.js → timeline-annotation-markers-5J5TM5IP.js} +2 -2
  419. package/dist/{timeline-annotation-selection-MBCIDO2Q.js → timeline-annotation-selection-WLY7FB7F.js} +2 -2
  420. package/dist/{timeline-annotations-dialog-JPNKLOTE.js → timeline-annotations-dialog-67VRFKJU.js} +3 -3
  421. package/dist/timeline-model.js +2 -2
  422. package/dist/ui/access-list.js +5 -5
  423. package/dist/ui/cadence-picker.js +4 -4
  424. package/dist/ui/choice-cards.js +3 -3
  425. package/dist/ui/confirm-dialog.js +2 -2
  426. package/dist/ui/copy-field.js +3 -3
  427. package/dist/ui/detail-page.js +2 -2
  428. package/dist/ui/detail-sheet.js +2 -2
  429. package/dist/ui/disclosure.js +3 -3
  430. package/dist/ui/email-chips-input.js +3 -3
  431. package/dist/ui/field.js +2 -2
  432. package/dist/ui/flush-form-page.js +3 -3
  433. package/dist/ui/form-dialog.js +2 -2
  434. package/dist/ui/list-row.js +3 -3
  435. package/dist/ui/relative-time.js +2 -2
  436. package/dist/ui/revision-history.js +4 -4
  437. package/dist/ui/role-select.js +5 -5
  438. package/dist/ui/select-menu.js +3 -3
  439. package/dist/ui/usage-meter.js +3 -3
  440. package/dist/usage.js +2 -2
  441. package/dist/workbench.js +4 -4
  442. package/package.json +6 -5
  443. package/src/app/components/rail/session-row-content.tsx +27 -0
  444. package/src/app/lib/session-branch-cache.tsx +1 -0
  445. package/src/app/lib/session-pins.tsx +1 -0
  446. package/src/app/lib/session-row-paused.test.tsx +183 -0
  447. package/src/app/lib/sessions-group-channels.test.ts +4 -4
  448. package/src/app/lib/sessions-group.tsx +62 -4
  449. package/src/app/routes/session.tsx +2 -0
  450. package/src/components/message-timeline.tsx +14 -2
  451. package/src/components/session-conversation.tsx +2 -1
  452. package/src/components/timeline-annotations.tsx +4 -1
  453. package/src/components/timeline-settlement.ts +1 -1
  454. package/src/hooks/use-recordings.ts +5 -0
  455. package/src/index.ts +5 -0
  456. package/src/meetings/recorder-context.tsx +28 -5
  457. package/src/meetings/recorder-panel.tsx +13 -5
  458. package/src/meetings/recorder-workspace.test.tsx +57 -8
  459. package/src/messages/en.ts +2 -0
  460. package/src/session.ts +8 -1
  461. package/src/timeline/index.ts +4 -1
  462. package/src/timeline/projection.ts +228 -16
  463. package/src/timeline/turn-summary-model.ts +4 -3
  464. package/src/timeline/turn-summary.tsx +15 -2
  465. package/src/timeline/types.ts +8 -2
  466. package/src/timeline/use-timeline-pauses.ts +105 -0
  467. package/src/timeline/work-presentation.ts +13 -4
  468. package/dist/chunk-2OXSB2OL.js.map +0 -1
  469. package/dist/chunk-7YTR3UFO.js.map +0 -1
  470. package/dist/chunk-7Z76QP64.js.map +0 -1
  471. package/dist/chunk-JHZRAYI4.js.map +0 -1
  472. package/dist/chunk-M5IQVMLR.js.map +0 -1
  473. package/dist/chunk-NQ2CPQJF.js.map +0 -1
  474. package/dist/chunk-O2UPPN5M.js +0 -2
  475. package/dist/chunk-PF2WU2IL.js.map +0 -1
  476. package/dist/chunk-PSM3CU7N.js.map +0 -1
  477. package/dist/chunk-Q5K2J5GG.js.map +0 -1
  478. package/dist/chunk-QPQ7R77C.js.map +0 -1
  479. package/dist/chunk-QQIZMVAJ.js.map +0 -1
  480. package/dist/chunk-SK5S2PCK.js.map +0 -1
  481. package/dist/chunk-SPD4ULVB.js.map +0 -1
  482. package/dist/chunk-VXORMNU4.js.map +0 -1
  483. /package/dist/{browser-viewer-ZHQDVHZ2.js.map → browser-viewer-H7PKY67P.js.map} +0 -0
  484. /package/dist/{chat-interactive-block-VSDD6X3M.js.map → chat-interactive-block-47TCT4DN.js.map} +0 -0
  485. /package/dist/{chunk-5MHMCE2G.js.map → chunk-2X2B6D5G.js.map} +0 -0
  486. /package/dist/{chunk-OCXEY7HE.js.map → chunk-3BUI5DT7.js.map} +0 -0
  487. /package/dist/{chunk-OSJ366KR.js.map → chunk-3FWP3TD3.js.map} +0 -0
  488. /package/dist/{chunk-PWUSSSSL.js.map → chunk-3G5IA36N.js.map} +0 -0
  489. /package/dist/{chunk-RGR57NYY.js.map → chunk-3NK4JAHL.js.map} +0 -0
  490. /package/dist/{chunk-XUOYNJPB.js.map → chunk-3O7UZRWM.js.map} +0 -0
  491. /package/dist/{chunk-JV3UI7BH.js.map → chunk-3OR6HMA4.js.map} +0 -0
  492. /package/dist/{chunk-MV2CLIO6.js.map → chunk-3PC45I5N.js.map} +0 -0
  493. /package/dist/{chunk-SJYTQLN3.js.map → chunk-3PI2BYK5.js.map} +0 -0
  494. /package/dist/{chunk-DCEQCGVN.js.map → chunk-3PNA2P2Z.js.map} +0 -0
  495. /package/dist/{chunk-ESXAECZ3.js.map → chunk-3XBZKF3K.js.map} +0 -0
  496. /package/dist/{chunk-SBXSKRFA.js.map → chunk-45OGYO3S.js.map} +0 -0
  497. /package/dist/{chunk-M3FDGRB4.js.map → chunk-4A7TKVNX.js.map} +0 -0
  498. /package/dist/{chunk-RHXYO4H2.js.map → chunk-4BXRGXTD.js.map} +0 -0
  499. /package/dist/{chunk-CV4VVLPZ.js.map → chunk-4HQAJA3T.js.map} +0 -0
  500. /package/dist/{chunk-VCJQQYRE.js.map → chunk-4X2A3KPB.js.map} +0 -0
  501. /package/dist/{chunk-OCXTTKVA.js.map → chunk-555K37A7.js.map} +0 -0
  502. /package/dist/{chunk-EBIVTDEG.js.map → chunk-57L5ZXDS.js.map} +0 -0
  503. /package/dist/{chunk-3L465FBR.js.map → chunk-5IADORIV.js.map} +0 -0
  504. /package/dist/{chunk-PVB4YVDP.js.map → chunk-5Y2O2432.js.map} +0 -0
  505. /package/dist/{chunk-OOOSGPJL.js.map → chunk-6572EFE4.js.map} +0 -0
  506. /package/dist/{chunk-YMI27QPF.js.map → chunk-6BG5HCUP.js.map} +0 -0
  507. /package/dist/{chunk-QRECBCJM.js.map → chunk-6EXFJWII.js.map} +0 -0
  508. /package/dist/{chunk-74CBR5YE.js.map → chunk-6PNRUGOK.js.map} +0 -0
  509. /package/dist/{chunk-PUUEI4W3.js.map → chunk-6RJEY6TC.js.map} +0 -0
  510. /package/dist/{chunk-DLVIRJGK.js.map → chunk-727GL2YY.js.map} +0 -0
  511. /package/dist/{chunk-J2BTILRR.js.map → chunk-7FGYLFW6.js.map} +0 -0
  512. /package/dist/{chunk-MKDFYE2E.js.map → chunk-7IMWTFEG.js.map} +0 -0
  513. /package/dist/{chunk-FER6EVIY.js.map → chunk-7POKH54R.js.map} +0 -0
  514. /package/dist/{chunk-H6BX6WOW.js.map → chunk-7T26IH6W.js.map} +0 -0
  515. /package/dist/{chunk-R33SBMB7.js.map → chunk-7XQRVZZQ.js.map} +0 -0
  516. /package/dist/{chunk-NFCS5WYC.js.map → chunk-A3SPPXMC.js.map} +0 -0
  517. /package/dist/{chunk-DQPIEQGP.js.map → chunk-A7CWPDEH.js.map} +0 -0
  518. /package/dist/{chunk-3PM3M2Q6.js.map → chunk-AGOYVKTI.js.map} +0 -0
  519. /package/dist/{chunk-OBGOLHCP.js.map → chunk-AIQKZUPB.js.map} +0 -0
  520. /package/dist/{chunk-GSCGKJNK.js.map → chunk-AMYDHG3S.js.map} +0 -0
  521. /package/dist/{chunk-U4LTPFD2.js.map → chunk-APJPB6TX.js.map} +0 -0
  522. /package/dist/{chunk-SP44O3OU.js.map → chunk-APLGT5EI.js.map} +0 -0
  523. /package/dist/{chunk-M3HGBO2Y.js.map → chunk-ATNKMGLO.js.map} +0 -0
  524. /package/dist/{chunk-4O2XWOLZ.js.map → chunk-AVX4CZQ3.js.map} +0 -0
  525. /package/dist/{chunk-CXAN2FHF.js.map → chunk-B46MK44K.js.map} +0 -0
  526. /package/dist/{chunk-RMCLFSMX.js.map → chunk-BBKUPEGG.js.map} +0 -0
  527. /package/dist/{chunk-J2WY42FA.js.map → chunk-BES6OQE3.js.map} +0 -0
  528. /package/dist/{chunk-GU7T2S5N.js.map → chunk-BM2N26SH.js.map} +0 -0
  529. /package/dist/{chunk-HEGV4QMS.js.map → chunk-C3NS74PZ.js.map} +0 -0
  530. /package/dist/{chunk-752WXSDN.js.map → chunk-C56ABB5V.js.map} +0 -0
  531. /package/dist/{chunk-77SYIH6O.js.map → chunk-C6MATJQ5.js.map} +0 -0
  532. /package/dist/{chunk-KUE5BOQE.js.map → chunk-CRX47CO6.js.map} +0 -0
  533. /package/dist/{chunk-GTHCHCWW.js.map → chunk-D33KWZQJ.js.map} +0 -0
  534. /package/dist/{chunk-AH3DGOTK.js.map → chunk-D7E3BSCX.js.map} +0 -0
  535. /package/dist/{chunk-OJWDNNW3.js.map → chunk-DFR3TMTZ.js.map} +0 -0
  536. /package/dist/{chunk-WYGTAQMX.js.map → chunk-DICC75CU.js.map} +0 -0
  537. /package/dist/{chunk-736RUNIA.js.map → chunk-DJ2LMKKX.js.map} +0 -0
  538. /package/dist/{chunk-4F3AEJI6.js.map → chunk-DJI4D7PM.js.map} +0 -0
  539. /package/dist/{chunk-LVELUUK6.js.map → chunk-DSZUQL4W.js.map} +0 -0
  540. /package/dist/{chunk-MT2R57SF.js.map → chunk-DVF246BE.js.map} +0 -0
  541. /package/dist/{chunk-OI6VI6SU.js.map → chunk-DVOWBHWN.js.map} +0 -0
  542. /package/dist/{chunk-PZKHST7A.js.map → chunk-E2KPRSA4.js.map} +0 -0
  543. /package/dist/{chunk-EKJHOWTZ.js.map → chunk-E3LMLWEB.js.map} +0 -0
  544. /package/dist/{chunk-QURYQFDN.js.map → chunk-EDC7X7PW.js.map} +0 -0
  545. /package/dist/{chunk-HYEIA25Y.js.map → chunk-EDSMULHU.js.map} +0 -0
  546. /package/dist/{chunk-U6552Q3T.js.map → chunk-EQQOZ6DD.js.map} +0 -0
  547. /package/dist/{chunk-IFSXVU2S.js.map → chunk-ERBDQ2GY.js.map} +0 -0
  548. /package/dist/{chunk-IZXYFWA4.js.map → chunk-EWI73URG.js.map} +0 -0
  549. /package/dist/{chunk-N3FM4BNA.js.map → chunk-EZ6LFN33.js.map} +0 -0
  550. /package/dist/{chunk-4K64EKM7.js.map → chunk-F7YL6DPR.js.map} +0 -0
  551. /package/dist/{chunk-ICAMYP5M.js.map → chunk-FIGFXMUP.js.map} +0 -0
  552. /package/dist/{chunk-54U6ZBEX.js.map → chunk-FJRJK67G.js.map} +0 -0
  553. /package/dist/{chunk-E5KOWRDU.js.map → chunk-FLHB2NZT.js.map} +0 -0
  554. /package/dist/{chunk-D3PTVN2I.js.map → chunk-FUGGM76A.js.map} +0 -0
  555. /package/dist/{chunk-TDTD66BK.js.map → chunk-FXPZAZYT.js.map} +0 -0
  556. /package/dist/{chunk-KO3OHHY2.js.map → chunk-GAGAM4MT.js.map} +0 -0
  557. /package/dist/{chunk-TK5FWVZR.js.map → chunk-GESGH3HY.js.map} +0 -0
  558. /package/dist/{chunk-2VJOSU4H.js.map → chunk-GI4PWKXI.js.map} +0 -0
  559. /package/dist/{chunk-KFNZZ2N6.js.map → chunk-GJTEBAZ7.js.map} +0 -0
  560. /package/dist/{chunk-LTJFV2JI.js.map → chunk-GNCGEW7F.js.map} +0 -0
  561. /package/dist/{chunk-34NV52R3.js.map → chunk-GOMUNPB6.js.map} +0 -0
  562. /package/dist/{chunk-LIJNVIT3.js.map → chunk-GUMUILEI.js.map} +0 -0
  563. /package/dist/{chunk-7NLF35YL.js.map → chunk-GVGNHBFT.js.map} +0 -0
  564. /package/dist/{chunk-K3D7IQQP.js.map → chunk-GW4YI3FB.js.map} +0 -0
  565. /package/dist/{chunk-D5TIVCXG.js.map → chunk-GXKCV7X7.js.map} +0 -0
  566. /package/dist/{chunk-2J77TWGH.js.map → chunk-H467EQA6.js.map} +0 -0
  567. /package/dist/{chunk-3OK7Y6ES.js.map → chunk-HE77VDDR.js.map} +0 -0
  568. /package/dist/{chunk-UO35OEOX.js.map → chunk-HT65RGCX.js.map} +0 -0
  569. /package/dist/{chunk-G6ICCGJ3.js.map → chunk-HVQSFTE7.js.map} +0 -0
  570. /package/dist/{chunk-G5UQBTXY.js.map → chunk-HXJPDC76.js.map} +0 -0
  571. /package/dist/{chunk-GIWFLWXG.js.map → chunk-I6LQW24C.js.map} +0 -0
  572. /package/dist/{chunk-467WDSOK.js.map → chunk-I7A6S5YL.js.map} +0 -0
  573. /package/dist/{chunk-AAS7OWV6.js.map → chunk-IADS4ZYD.js.map} +0 -0
  574. /package/dist/{chunk-Y3XZEKDQ.js.map → chunk-IJWMWCGR.js.map} +0 -0
  575. /package/dist/{chunk-SGH7I7OY.js.map → chunk-IWFO6KOU.js.map} +0 -0
  576. /package/dist/{chunk-GMHIOYB7.js.map → chunk-IYC6QGV2.js.map} +0 -0
  577. /package/dist/{chunk-3NNAC43A.js.map → chunk-J5AODKJO.js.map} +0 -0
  578. /package/dist/{chunk-DIP7YALH.js.map → chunk-JKI3LMLH.js.map} +0 -0
  579. /package/dist/{chunk-IJR6VOLU.js.map → chunk-JSYRWOCE.js.map} +0 -0
  580. /package/dist/{chunk-CEMSIU4Z.js.map → chunk-JTQTWO4D.js.map} +0 -0
  581. /package/dist/{chunk-BASI553K.js.map → chunk-KBTKAAHM.js.map} +0 -0
  582. /package/dist/{chunk-OYOFPNLC.js.map → chunk-KD7VEMWY.js.map} +0 -0
  583. /package/dist/{chunk-3DRLCX5V.js.map → chunk-KPGFGRSA.js.map} +0 -0
  584. /package/dist/{chunk-PLYVGZIN.js.map → chunk-KWFDEJFI.js.map} +0 -0
  585. /package/dist/{chunk-FNXCFIPW.js.map → chunk-KYLEH4OF.js.map} +0 -0
  586. /package/dist/{chunk-WXF2RTS4.js.map → chunk-L7FJTFJN.js.map} +0 -0
  587. /package/dist/{chunk-KI46GKMD.js.map → chunk-L7VVQOSY.js.map} +0 -0
  588. /package/dist/{chunk-O2UPPN5M.js.map → chunk-LKLQVANM.js.map} +0 -0
  589. /package/dist/{chunk-YNTLWCF4.js.map → chunk-LLYEAZ4E.js.map} +0 -0
  590. /package/dist/{chunk-4Z5X7PLC.js.map → chunk-LWM7JUW6.js.map} +0 -0
  591. /package/dist/{chunk-CHU3RDV4.js.map → chunk-LXKV4ND3.js.map} +0 -0
  592. /package/dist/{chunk-AB5IW227.js.map → chunk-LYLICEQO.js.map} +0 -0
  593. /package/dist/{chunk-OTW25A6I.js.map → chunk-M5GRI5K4.js.map} +0 -0
  594. /package/dist/{chunk-X2QJXDE4.js.map → chunk-MF65PKKF.js.map} +0 -0
  595. /package/dist/{chunk-EDDKPIIV.js.map → chunk-MJ4XIOPM.js.map} +0 -0
  596. /package/dist/{chunk-FLWQJDJ5.js.map → chunk-MMPJJQG3.js.map} +0 -0
  597. /package/dist/{chunk-T67LTMSW.js.map → chunk-MOU54FGD.js.map} +0 -0
  598. /package/dist/{chunk-LQKVNREV.js.map → chunk-NAWHQ4IL.js.map} +0 -0
  599. /package/dist/{chunk-ZBHGNE2J.js.map → chunk-NBHBB2VV.js.map} +0 -0
  600. /package/dist/{chunk-U5UGM5XD.js.map → chunk-NMOZDAEZ.js.map} +0 -0
  601. /package/dist/{chunk-D74Z2N4K.js.map → chunk-NZA4R3BE.js.map} +0 -0
  602. /package/dist/{chunk-WRMUXZ7C.js.map → chunk-OB2CX7PJ.js.map} +0 -0
  603. /package/dist/{chunk-YJSCLGAW.js.map → chunk-OB4I4OIT.js.map} +0 -0
  604. /package/dist/{chunk-DWJ6J3YW.js.map → chunk-OKQW2FPL.js.map} +0 -0
  605. /package/dist/{chunk-2GCHGWNE.js.map → chunk-ORLX6A3C.js.map} +0 -0
  606. /package/dist/{chunk-EBTUPRRQ.js.map → chunk-P5N4EYFW.js.map} +0 -0
  607. /package/dist/{chunk-JKL5S7UQ.js.map → chunk-PL4JE3NI.js.map} +0 -0
  608. /package/dist/{chunk-OP2GD6QW.js.map → chunk-PNUHKDY2.js.map} +0 -0
  609. /package/dist/{chunk-MZY3VKKM.js.map → chunk-PWJE7D6V.js.map} +0 -0
  610. /package/dist/{chunk-RISUROBM.js.map → chunk-PYE27I6J.js.map} +0 -0
  611. /package/dist/{chunk-R5QAL43H.js.map → chunk-QIJHK6P4.js.map} +0 -0
  612. /package/dist/{chunk-AJBDAVX3.js.map → chunk-QK3A23NP.js.map} +0 -0
  613. /package/dist/{chunk-CYDXCILL.js.map → chunk-QLWDNAOV.js.map} +0 -0
  614. /package/dist/{chunk-BQYRZIZ7.js.map → chunk-QS6DQBVJ.js.map} +0 -0
  615. /package/dist/{chunk-3PZ3LRPV.js.map → chunk-QSUVFPG3.js.map} +0 -0
  616. /package/dist/{chunk-PYB4BFEC.js.map → chunk-QUC5MLTN.js.map} +0 -0
  617. /package/dist/{chunk-WDASYY4S.js.map → chunk-QVT5AWPI.js.map} +0 -0
  618. /package/dist/{chunk-K4DQS2ML.js.map → chunk-QZC6WCBR.js.map} +0 -0
  619. /package/dist/{chunk-HWVPLFIW.js.map → chunk-RAHNICPP.js.map} +0 -0
  620. /package/dist/{chunk-H6MJFMHZ.js.map → chunk-RME6RGIW.js.map} +0 -0
  621. /package/dist/{chunk-XMBOLFFS.js.map → chunk-RQIB2F53.js.map} +0 -0
  622. /package/dist/{chunk-OXQ2SXVC.js.map → chunk-RUA72NQY.js.map} +0 -0
  623. /package/dist/{chunk-UMX6DZME.js.map → chunk-SCJHWN4X.js.map} +0 -0
  624. /package/dist/{chunk-HTMQGS63.js.map → chunk-SIXBDT5F.js.map} +0 -0
  625. /package/dist/{chunk-ZAX4XQLN.js.map → chunk-SPK3T4JK.js.map} +0 -0
  626. /package/dist/{chunk-WTSQUCHB.js.map → chunk-SSN2YSST.js.map} +0 -0
  627. /package/dist/{chunk-5MIBQ4P5.js.map → chunk-SYJCDX5V.js.map} +0 -0
  628. /package/dist/{chunk-ZR5EKJT6.js.map → chunk-T6276OXI.js.map} +0 -0
  629. /package/dist/{chunk-DEHLWZSI.js.map → chunk-T7OARG4N.js.map} +0 -0
  630. /package/dist/{chunk-77BHKC43.js.map → chunk-TF5L3BEV.js.map} +0 -0
  631. /package/dist/{chunk-GOCODNQS.js.map → chunk-TF6Z7BOP.js.map} +0 -0
  632. /package/dist/{chunk-WIFDNUKD.js.map → chunk-TJDXWZMO.js.map} +0 -0
  633. /package/dist/{chunk-SFIXTOOJ.js.map → chunk-TL5ATBHZ.js.map} +0 -0
  634. /package/dist/{chunk-XZCCEKPW.js.map → chunk-TMOHIOMT.js.map} +0 -0
  635. /package/dist/{chunk-AVXDIRRW.js.map → chunk-UI5X63YC.js.map} +0 -0
  636. /package/dist/{chunk-6QK65ZWM.js.map → chunk-UIY7BDZC.js.map} +0 -0
  637. /package/dist/{chunk-VATYK3JQ.js.map → chunk-UMBFMEO7.js.map} +0 -0
  638. /package/dist/{chunk-UU5FBVRX.js.map → chunk-UU5G7OA4.js.map} +0 -0
  639. /package/dist/{chunk-EGKARC53.js.map → chunk-UZUCYCF4.js.map} +0 -0
  640. /package/dist/{chunk-LPKJ77EK.js.map → chunk-V2A7G7S7.js.map} +0 -0
  641. /package/dist/{chunk-CH4UQ4NO.js.map → chunk-V5G4TKRC.js.map} +0 -0
  642. /package/dist/{chunk-UBRQ3PQD.js.map → chunk-VKAVW34W.js.map} +0 -0
  643. /package/dist/{chunk-JV5ULONH.js.map → chunk-VVLEVNTQ.js.map} +0 -0
  644. /package/dist/{chunk-44JWVYJB.js.map → chunk-VW7X7TWZ.js.map} +0 -0
  645. /package/dist/{chunk-3CDJSKDW.js.map → chunk-VWA2CHSL.js.map} +0 -0
  646. /package/dist/{chunk-IN3VQFKS.js.map → chunk-W43HZPM7.js.map} +0 -0
  647. /package/dist/{chunk-SXGJL7UT.js.map → chunk-WHGD7Q2L.js.map} +0 -0
  648. /package/dist/{chunk-XOIDUM2H.js.map → chunk-WNXKYEVN.js.map} +0 -0
  649. /package/dist/{chunk-TKQL7EDB.js.map → chunk-WSA7UBX4.js.map} +0 -0
  650. /package/dist/{chunk-AJDGP2N4.js.map → chunk-WZ5TQJ3T.js.map} +0 -0
  651. /package/dist/{chunk-FBA2NXYH.js.map → chunk-X3TGNSOG.js.map} +0 -0
  652. /package/dist/{chunk-R4JA5JFI.js.map → chunk-X4WXYI3N.js.map} +0 -0
  653. /package/dist/{chunk-Q5EZNBPI.js.map → chunk-XIQ3AIAJ.js.map} +0 -0
  654. /package/dist/{chunk-S27VZ5DO.js.map → chunk-XWYT4LEL.js.map} +0 -0
  655. /package/dist/{chunk-477DTTMH.js.map → chunk-Y3PU75OC.js.map} +0 -0
  656. /package/dist/{chunk-4JXPLTWV.js.map → chunk-Y5ZWX5YS.js.map} +0 -0
  657. /package/dist/{chunk-4BWMAGJJ.js.map → chunk-YA5PABND.js.map} +0 -0
  658. /package/dist/{chunk-OGU73VUN.js.map → chunk-YBPRR2QS.js.map} +0 -0
  659. /package/dist/{chunk-TNSJFZ6Q.js.map → chunk-YDYR7XQE.js.map} +0 -0
  660. /package/dist/{chunk-GTRAH4FG.js.map → chunk-YG6V2LQH.js.map} +0 -0
  661. /package/dist/{chunk-XVLEBB4Y.js.map → chunk-YUXA7ALE.js.map} +0 -0
  662. /package/dist/{chunk-SN2WENRP.js.map → chunk-YWHQDXPB.js.map} +0 -0
  663. /package/dist/{chunk-BFFNINCC.js.map → chunk-YWRR5R7B.js.map} +0 -0
  664. /package/dist/{chunk-FSDQQQIA.js.map → chunk-YYRK7A4N.js.map} +0 -0
  665. /package/dist/{chunk-MRECRNVU.js.map → chunk-Z26CDLUV.js.map} +0 -0
  666. /package/dist/{chunk-OYCK4JRS.js.map → chunk-Z27EXLMQ.js.map} +0 -0
  667. /package/dist/{chunk-UTRNLNCW.js.map → chunk-Z7GDH7W2.js.map} +0 -0
  668. /package/dist/{chunk-PRT4J2DL.js.map → chunk-ZGVLSAWL.js.map} +0 -0
  669. /package/dist/{chunk-OK7BQMCI.js.map → chunk-ZM6Q5NQN.js.map} +0 -0
  670. /package/dist/{computer-viewer-5LKRCEVQ.js.map → computer-viewer-SROXREYD.js.map} +0 -0
  671. /package/dist/{embedded-new-voice-GHJRY3YL.js.map → embedded-new-voice-EIQY2VBF.js.map} +0 -0
  672. /package/dist/{embedded-voice-ASQXBSTX.js.map → embedded-voice-LMWNH7F7.js.map} +0 -0
  673. /package/dist/{fleet-decision-row-U7LDVBEM.js.map → fleet-decision-row-X2G56ZRA.js.map} +0 -0
  674. /package/dist/{latest-question-RNVF262Q.js.map → latest-question-KA7AQYVI.js.map} +0 -0
  675. /package/dist/{model-policy-picker-menu-E6XKMFTA.js.map → model-policy-picker-menu-SHWPT5VA.js.map} +0 -0
  676. /package/dist/{payment-page-card-DJDKV2LW.js.map → payment-page-card-NNVUISN4.js.map} +0 -0
  677. /package/dist/{platform-activity-row-MSDCSMET.js.map → platform-activity-row-7UDWSAHK.js.map} +0 -0
  678. /package/dist/{queue-surface-implementation-GUAIG6TK.js.map → queue-surface-implementation-BUXSO24N.js.map} +0 -0
  679. /package/dist/{recorder-host-2MYDJPQW.js.map → recorder-host-POX54CFT.js.map} +0 -0
  680. /package/dist/{sandbox-files-W5W2LW4K.js.map → sandbox-files-33QD7DW2.js.map} +0 -0
  681. /package/dist/{session-connect-cards-HPH7JOZP.js.map → session-connect-cards-CXGNVA2A.js.map} +0 -0
  682. /package/dist/{session-realtime-SDTKFFIR.js.map → session-realtime-CVDSEULB.js.map} +0 -0
  683. /package/dist/{timeline-annotation-markers-FNILLWNU.js.map → timeline-annotation-markers-5J5TM5IP.js.map} +0 -0
  684. /package/dist/{timeline-annotation-selection-MBCIDO2Q.js.map → timeline-annotation-selection-WLY7FB7F.js.map} +0 -0
  685. /package/dist/{timeline-annotations-dialog-JPNKLOTE.js.map → timeline-annotations-dialog-67VRFKJU.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/session-auth-recommendation.ts","../src/components/session-connection-request.tsx","../src/hooks/use-video-artifact-playback.ts","../src/hooks/use-scheduled-tasks.ts","../src/hooks/use-workspace-background-commands.ts","../src/index.ts","../src/hooks/use-workspaces.ts","../src/hooks/use-billing-usage.ts","../src/hooks/use-session-capabilities.ts","../src/hooks/use-sandbox-terminal.ts","../src/hooks/use-sandbox-git.ts","../src/hooks/use-workspace-capture.ts","../src/hooks/use-workspace-edit.ts","../src/hooks/use-machine-chip.ts","../src/components/fleet-tile.tsx","../src/components/workbench-changes.tsx","../src/hooks/use-windowed-sections.ts","../src/components/diff-view.tsx","../src/components/sandbox-workspace.tsx","../src/hooks/use-supergrok-accounts.ts"],"sourcesContent":["import type { AuthNeededItem } from \"./timeline/types\";\nimport type { CapabilityCatalogItem } from \"@opengeni/sdk\";\nimport { type OpenGeniText } from \"./messages/runtime\";\n\n/** Recovery events identify runtime servers/connections, while recommendation\n * events already carry a catalog id. Never guess among same-domain accounts. */\nexport function sessionAuthRecommendation(\n t: OpenGeniText,\n item: AuthNeededItem,\n catalog: CapabilityCatalogItem[],\n): AuthNeededItem | undefined {\n if (\n item.authoritySource === \"host\" ||\n item.reason === \"unsupported_auth\" ||\n item.reason === \"resource_scope_unavailable\"\n )\n return undefined;\n if (item.capability) return item;\n const recoveryServerId = item.canonicalServerId ?? item.serverId;\n const matches = catalog.filter(\n (candidate) =>\n (recoveryServerId !== null &&\n candidate.runtime.mcpServerId === recoveryServerId &&\n recoveryServerId !== \"opengeni\") ||\n (item.connectionId !== null && candidate.connectionRef?.connectionId === item.connectionId),\n );\n if (matches.length !== 1) return undefined;\n const entry = matches[0]!;\n const personalAccess = item.reason === \"personal_authority_unavailable\";\n if (\n personalAccess &&\n ((item.connectionSubjectScope ?? entry.connectionRef?.subjectScope) !== \"subject\" ||\n entry.connectionRef?.authoritySource === \"host\")\n )\n return undefined;\n return {\n ...item,\n capability: {\n id: entry.id,\n name: entry.name,\n kind: entry.kind,\n source: entry.source,\n action: \"connect\",\n rationale: personalAccess\n ? t(\"sessionAuthRecommendation.reviewPermissionToUseYour\")\n : t(\"sessionAuthRecommendation.reconnectThisIntegrationToUse\"),\n requiredVariables: [],\n },\n };\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport type { AuthNeededItem } from \"../timeline/types\";\nimport { sessionAuthRecommendation } from \"../session-auth-recommendation\";\nimport {\n SessionMcpCapabilityCard,\n type SessionMcpCapabilityCardProps,\n} from \"./session-mcp-capability-card\";\nimport { useOpenGeniText } from \"../messages/runtime\";\n\nexport type SessionConnectionRequestProps = Omit<\n SessionMcpCapabilityCardProps,\n \"capabilityId\" | \"name\" | \"rationale\"\n> & {\n request: AuthNeededItem;\n};\n\n/** Resolve native reauthorization notices with the same exact-identity rules\n * as the console. Recommendations never supply endpoints or account authority. */\nexport function SessionConnectionRequest(props: SessionConnectionRequestProps) {\n const [client, setClient] = useState(props.client);\n const [generation, setGeneration] = useState(0);\n if (client !== props.client) {\n setClient(props.client);\n setGeneration(generation + 1);\n }\n return (\n <ScopedRequest\n key={`${generation}:${props.workspaceId}:${props.sessionId}:${props.request.id}`}\n {...props}\n />\n );\n}\n\nfunction ScopedRequest({ request, ...props }: SessionConnectionRequestProps) {\n const t = useOpenGeniText();\n const [resolved, setResolved] = useState<AuthNeededItem | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [retry, setRetry] = useState(0);\n const requestRef = useRef(request);\n requestRef.current = request;\n useEffect(() => {\n let current = true;\n const event = requestRef.current;\n setResolved(null);\n setError(null);\n void props.client\n .listCapabilities(props.workspaceId)\n .then((catalog) => {\n if (!current) return;\n const recommendation = sessionAuthRecommendation(t, event, catalog.items);\n const candidate = catalog.items.find(\n (entry) => entry.id === recommendation?.capability?.id,\n );\n if (!recommendation || candidate?.kind !== \"mcp\" || candidate.authKind !== \"oauth2\") {\n setError(t(\"sessionConnectionRequest.thisRequestCouldNotBe\"));\n return;\n }\n setResolved(recommendation);\n })\n .catch(() => {\n if (current) setError(t(\"sessionConnectionRequest.couldnTLoadConnectionDetails\"));\n });\n return () => {\n current = false;\n };\n }, [\n props.client,\n props.workspaceId,\n request.id,\n request.serverId,\n request.connectionId,\n request.authoritySource,\n request.reason,\n request.capability?.id,\n retry,\n t,\n ]);\n if (!resolved?.capability)\n return (\n <div className=\"og-session-capability-setup\">\n <p role={error ? \"alert\" : \"status\"}>\n {error ?? t(\"sessionConnectionRequest.loadingConnectionDetails\")}\n </p>\n {error ? (\n <button type=\"button\" onClick={() => setRetry((value) => value + 1)}>\n {t(\"sessionConnectionRequest.retry\")}\n </button>\n ) : null}\n </div>\n );\n return (\n <SessionMcpCapabilityCard\n {...props}\n capabilityId={resolved.capability.id}\n name={resolved.capability.name}\n rationale={resolved.capability.rationale}\n />\n );\n}\n","import { useMemo } from \"react\";\nimport type { VideoArtifactPlaybackLoader } from \"../timeline\";\nimport { useOpenGeni, type ClientOverride } from \"../session-context\";\n\n/**\n * Bind the current public SDK client/workspace to MessageTimeline's renewable\n * video-source boundary. Proxy hosts may omit the method until they support\n * retained video; the failure remains local to the player instead of loading\n * any video bytes through React.\n */\nexport function useVideoArtifactPlaybackLoader(\n options: ClientOverride = {},\n): VideoArtifactPlaybackLoader {\n const { client, workspaceId } = useOpenGeni(options);\n return useMemo(\n () => async (artifactId: string, signal?: AbortSignal) => {\n if (typeof client.createVideoArtifactPlaybackSource !== \"function\") {\n throw new Error(\"This Opengeni host does not expose retained-video playback.\");\n }\n return await client.createVideoArtifactPlaybackSource(\n workspaceId,\n artifactId,\n signal ? { signal } : {},\n );\n },\n [client, workspaceId],\n );\n}\n","import type { ScheduledTask } from \"@opengeni/sdk\";\nimport { useCallback } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { usePolledValue } from \"./internal\";\n\nexport type UseScheduledTasksOptions = ClientOverride & {\n limit?: number | undefined;\n pollIntervalMs?: number | undefined;\n enabled?: boolean | undefined;\n};\n\nexport type UseScheduledTasksResult = {\n tasks: ScheduledTask[];\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n};\n\n/** List the workspace's scheduled tasks (drift checks, sentinels, reapers, ...). */\nexport function useScheduledTasks(options: UseScheduledTasksOptions = {}): UseScheduledTasksResult {\n const { client, workspaceId } = useOpenGeni(options);\n const limit = options.limit;\n const load = useCallback(\n async () => await client.listScheduledTasks(workspaceId, limit !== undefined ? { limit } : {}),\n [client, workspaceId, limit],\n );\n const state = usePolledValue(load, {\n pollIntervalMs: options.pollIntervalMs,\n enabled: options.enabled,\n });\n return {\n tasks: state.data ?? [],\n loading: state.loading,\n error: state.error,\n refresh: state.refresh,\n };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { WorkspaceBackgroundCommand } from \"@opengeni/sdk\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { usePolledValue } from \"./internal\";\n\n/** Live workspace projection; Stop remains the existing session command action. */\nexport function useWorkspaceBackgroundCommands(\n options: ClientOverride & { enabled?: boolean; pollIntervalMs?: number } = {},\n) {\n const { client, workspaceId } = useOpenGeni(options);\n const [pages, setPages] = useState(1);\n const enabled = options.enabled ?? true;\n useEffect(() => setPages(1), [client, workspaceId]);\n const load = useCallback(\n async (signal?: AbortSignal) => {\n if (!client.listWorkspaceBackgroundCommands)\n throw new Error(\"The configured client does not support workspace commands\");\n const commands = new Map<string, WorkspaceBackgroundCommand>();\n let cursor: string | undefined;\n for (let page = 0; page < pages; page += 1) {\n signal?.throwIfAborted();\n const result = await client.listWorkspaceBackgroundCommands(workspaceId, {\n ...(cursor ? { cursor } : {}),\n ...(signal ? { signal } : {}),\n });\n for (const command of result.commands) commands.set(command.id, command);\n cursor = result.nextCursor ?? undefined;\n if (!cursor) break;\n }\n return { commands: [...commands.values()], hasMore: Boolean(cursor) };\n },\n [client, workspaceId, pages],\n );\n const state = usePolledValue(load, { enabled, pollIntervalMs: options.pollIntervalMs ?? 5_000 });\n const { data, refresh } = state;\n const generation = useRef(0);\n useEffect(() => {\n generation.current += 1;\n return () => {\n generation.current += 1;\n };\n }, [client, workspaceId, enabled]);\n const cancel = useCallback(\n async (commandId: string) => {\n const command = data?.commands.find((item) => item.id === commandId);\n if (!command || !enabled) return;\n if (!client.cancelSessionBackgroundCommand)\n throw new Error(\"The configured client does not support stopping commands\");\n const ticket = generation.current;\n await client.cancelSessionBackgroundCommand(workspaceId, command.sessionId, commandId);\n if (ticket === generation.current) await refresh();\n },\n [client, workspaceId, enabled, data, refresh],\n );\n return {\n commands: enabled && !state.error ? (state.data?.commands ?? []) : [],\n loading: enabled && state.loading,\n error: enabled ? state.error : null,\n refresh: state.refresh,\n cancel,\n hasMore: enabled && !state.error && (state.data?.hasMore ?? false),\n loadMore: () => setPages((value) => value + 1),\n };\n}\n","export { sessionAuthRecommendation } from \"./session-auth-recommendation\";\nexport {\n SessionConnectionRequest,\n type SessionConnectionRequestProps,\n} from \"./components/session-connection-request\";\nexport {\n SessionMcpCapabilityCard,\n McpConnectionCard,\n type McpConnectionCardProps,\n type SessionMcpCapabilityCardProps,\n} from \"./components/session-mcp-capability-card\";\nexport {\n SessionCapabilityFrame,\n type SessionCapabilityFrameProps,\n} from \"./components/session-capability-frame\";\nexport {\n SessionIntegrationCapabilityCard,\n supportsIntegrationCapabilityCard,\n type SessionIntegrationCapabilityCardProps,\n} from \"./components/session-integration-capability-card\";\nexport {\n attachSessionCapability,\n completeSessionCapabilityOAuth,\n prepareSessionCapabilityAccess,\n applySessionCapabilityAccess,\n type SessionCapabilityAccessPlan,\n} from \"./session-capability-policy\";\nexport { retainedImageId } from \"./components/markdown\";\n// oxlint-disable-next-line typescript/triple-slash-reference -- package consumers must load the ambient type for this optional untyped peer without emitting a runtime import.\n/// <reference path=\"./types/external.d.ts\" />\n\n// @opengeni/react — hooks + styled components on @opengeni/sdk.\n//\n// Import the ready-to-use styles once:\n// import \"@opengeni/react/compiled.css\";\n// Tailwind v4 hosts may instead use the additive styles.css + @source bridge;\n// container-responsive composers additionally import responsive.css.\n\nexport type {\n EmbeddedBrowserInteractionClientLike,\n EmbeddedComputerInteractionClientLike,\n EmbeddedFileAttachmentClientLike,\n EmbeddedGoalClientLike,\n EmbeddedHumanInputSessionClientLike,\n EmbeddedInteractionClientLike,\n EmbeddedSessionEventClientLike,\n EmbeddedSessionLineageClientLike,\n EmbeddedSessionMcpApprovalPolicyClientLike,\n EmbeddedSessionReadClientLike,\n EmbeddedSessionClientLike,\n SessionClientLike,\n} from \"./client\";\nexport { OpenGeniProvider } from \"./provider\";\nexport type { OpenGeniProviderProps, ErrorMessageFormatter } from \"./provider\";\nexport {\n createOpenGeniText,\n OpenGeniMessagesProvider,\n useOpenGeniLocale,\n useOpenGeniText,\n} from \"./messages/runtime\";\nexport type {\n MessageParamValue,\n OpenGeniMessageCatalog,\n OpenGeniMessageKey,\n OpenGeniMessageParams,\n OpenGeniMessages,\n OpenGeniMessagesProviderProps,\n OpenGeniText,\n PluralCategory,\n} from \"./messages/runtime\";\nexport { englishMessages } from \"./messages/en\";\nexport { SINGLE_SEND_WORDING, singleSendText } from \"./messages/single-send\";\nexport { SingleSendWording } from \"./messages/runtime\";\nexport { useOpenGeni, useOpenGeniClient } from \"./session-context\";\nexport { useVideoArtifactPlaybackLoader } from \"./hooks/use-video-artifact-playback\";\nexport type { ClientOverride, OpenGeniContextValue } from \"./session-context\";\nexport { createEmbeddedSessionClient } from \"./embedded-session-client\";\nexport type {\n ComposerDraftMapContext,\n CreateEmbeddedSessionClientOptions,\n} from \"./embedded-session-client\";\nexport { usePageLiveActivity } from \"./hooks/internal\";\nexport { filePathVisibility, visibleFileTree } from \"./file-node-visibility\";\nexport type {\n FileNodeVisibilityContext,\n FileNodeVisibilityPredicate,\n FilePathVisibility,\n} from \"./file-node-visibility\";\n\n// Hooks\nexport { useSession, isTitleEvent } from \"./hooks/use-session\";\nexport { useRetainedReads } from \"./hooks/shared-query\";\nexport { readClientConfig } from \"./lib/client-config-read\";\nexport type { UseSessionOptions, UseSessionResult } from \"./hooks/use-session\";\nexport {\n SESSION_EVENT_BROWSER_MAX_BYTES,\n SESSION_EVENT_BROWSER_MAX_COUNT,\n SESSION_EVENT_BROWSER_PENDING_MAX_BYTES,\n SESSION_EVENT_BROWSER_PENDING_MAX_COUNT,\n boundBrowserSessionEventWindow,\n useSessionEvents,\n} from \"./hooks/use-session-events\";\nexport { createOlderHistoryLoadReceipt } from \"./older-history\";\nexport type {\n BrowserSessionEventWindow,\n SessionEventsConnectionState,\n UseSessionEventsOptions,\n UseSessionEventsResult,\n} from \"./hooks/use-session-events\";\nexport type { OlderHistoryLoader, OlderHistoryLoadReceipt } from \"./older-history\";\nexport {\n useComposer,\n composeSendInput,\n shouldSteerOnKey,\n shouldSubmitOnKey,\n FILE_ONLY_MESSAGE_TEXT,\n} from \"./hooks/use-composer\";\nexport type {\n ComposerBusySend,\n ComposerControllerState,\n ComposerPolicy,\n InitialComposerDraft,\n ComposerSendExtras,\n ComposerState,\n UseComposerOptions,\n} from \"./hooks/use-composer\";\nexport {\n VOICE_RECORDING_CLIENT_MAX_DURATION_SECONDS,\n VOICE_RECORDING_OWNER_HEARTBEAT_MILLISECONDS,\n VOICE_RECORDING_OWNER_STALE_MILLISECONDS,\n VOICE_RECORDING_TIMESLICE_MILLISECONDS,\n useVoiceInput,\n} from \"./hooks/use-voice-input\";\nexport type {\n UseVoiceInputOptions,\n UseVoiceInputResult,\n VoiceInputStatus,\n VoiceInputRecordingsClient,\n} from \"./hooks/use-voice-input\";\nexport {\n IndexedDbVoiceRecordingStore,\n VoiceRecordingChunkConflictError,\n VoiceRecordingChunkSequenceError,\n VoiceRecordingNotFoundError,\n VoiceRecordingOwnedError,\n VoiceRecordingStorageUnavailableError,\n createVoiceRecordingManifest,\n planVoiceRecordingChunkCommit,\n prepareVoiceRecordingChunk,\n} from \"./voice-recording-store\";\nexport type {\n PersistVoiceRecordingChunkInput,\n PersistVoiceRecordingChunkResult,\n VoiceRecordingCaptureState,\n VoiceRecordingChunk,\n VoiceRecordingChunkUploadState,\n VoiceRecordingFinalizationState,\n VoiceRecordingHandoffMode,\n VoiceRecordingManifest,\n VoiceRecordingRecoveryMode,\n VoiceRecordingStore,\n VoiceRecordingTranscriptionState,\n VoiceRecordingUploadState,\n} from \"./voice-recording-store\";\nexport {\n COMPOSER_MODEL_UNAVAILABLE_MESSAGE,\n COMPOSER_PAYMENT_REQUIRED_MESSAGE,\n COMPOSER_SESSION_USAGE_LIMIT_MESSAGE,\n composerSubmissionErrorMessage,\n isModelUnavailableSubmissionError,\n isSessionUsageLimitSubmissionError,\n} from \"./lib/format\";\nexport {\n INITIAL_TRANSCRIPTION_CONTROL_STATE,\n appendFinalTranscript,\n transitionTranscriptionControl,\n useTranscription,\n} from \"./hooks/use-transcription\";\nexport type {\n TranscriptionControlAction,\n TranscriptionControlState,\n TranscriptionControlTransition,\n UseTranscriptionOptions,\n UseTranscriptionResult,\n} from \"./hooks/use-transcription\";\nexport { useFileAttachments } from \"./hooks/use-file-attachments\";\nexport type {\n FileAttachment,\n UseFileAttachmentsOptions,\n UseFileAttachmentsResult,\n} from \"./hooks/use-file-attachments\";\nexport { useTurnQueue, isTurnQueueEvent } from \"./hooks/use-turn-queue\";\nexport type {\n QueueMutationKind,\n QueueRecallResult,\n UseTurnQueueOptions,\n UseTurnQueueResult,\n} from \"./hooks/use-turn-queue\";\nexport {\n latestRecallableQueuedTurn,\n shouldRecallQueuedOnKey,\n useQueuedPromptRecall,\n} from \"./hooks/use-queued-prompt-recall\";\nexport type {\n ComposerQueuedRecall,\n QueuedPromptRecallOutcome,\n} from \"./hooks/use-queued-prompt-recall\";\nexport {\n useLastStartedTurnPolicy,\n isLastStartedTurnPolicyEvent,\n} from \"./hooks/use-last-started-turn-policy\";\nexport type {\n LastStartedTurnPolicy,\n UseLastStartedTurnPolicyOptions,\n UseLastStartedTurnPolicyResult,\n} from \"./hooks/use-last-started-turn-policy\";\nexport { QueueSurface } from \"./components/queue-surface\";\nexport type { QueueSurfaceProps } from \"./components/queue-surface\";\nexport {\n SessionChrome,\n sessionChromeGoalPillExplanation,\n sessionChromeGoalPillLabel,\n sessionChromeGoalPillState,\n} from \"./components/session-chrome\";\nexport type {\n SessionChromeAgentsSignal,\n SessionChromeProps,\n SessionChromeSignalId,\n SessionChromeSignalTone,\n SessionChromeWait,\n} from \"./components/session-chrome\";\nexport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from \"./components/tooltip\";\nexport { OPEN_WORKSTREAM_CONTROL_EVENT } from \"./workstream-control-event\";\nexport { useGoal, isGoalEvent } from \"./hooks/use-goal\";\nexport type { UseGoalOptions, UseGoalResult } from \"./hooks/use-goal\";\nexport { useSessionControl } from \"./hooks/use-session-control\";\nexport type {\n UseSessionControlOptions,\n UseSessionControlResult,\n} from \"./hooks/use-session-control\";\nexport {\n isSessionMcpApprovalPolicyEvent,\n useSessionMcpApprovalPolicy,\n} from \"./hooks/use-session-mcp-approval-policy\";\nexport type {\n UseSessionMcpApprovalPolicyOptions,\n UseSessionMcpApprovalPolicyResult,\n} from \"./hooks/use-session-mcp-approval-policy\";\nexport { useScheduledTasks } from \"./hooks/use-scheduled-tasks\";\nexport type {\n UseScheduledTasksOptions,\n UseScheduledTasksResult,\n} from \"./hooks/use-scheduled-tasks\";\nexport { useWorkspaceSessions } from \"./hooks/use-workspace-sessions\";\nexport type {\n UseWorkspaceSessionsOptions,\n UseWorkspaceSessionsResult,\n} from \"./hooks/use-workspace-sessions\";\nexport { useSessionBackgroundCommands } from \"./hooks/use-session-background-commands\";\nexport { useWorkspaceBackgroundCommands } from \"./hooks/use-workspace-background-commands\";\nexport type {\n UseSessionBackgroundCommandsOptions,\n UseSessionBackgroundCommandsResult,\n} from \"./hooks/use-session-background-commands\";\nexport { useSessionLineage, isLineageRefreshEvent } from \"./hooks/use-session-lineage\";\nexport type {\n UseSessionLineageOptions,\n UseSessionLineageResult,\n} from \"./hooks/use-session-lineage\";\nexport {\n useVaultsApi,\n useVaults,\n useVault,\n useVaultItems,\n useVaultItem,\n useVaultFieldVersions,\n useSessionSecrets,\n VAULT_ITEM_PAGE_LIMIT,\n} from \"./hooks/use-vaults\";\nexport type { UseVaultQueryOptions } from \"./hooks/use-vaults\";\nexport { asVaultClient, vaultsApi, vaultErrorCode, vaultErrorDetail } from \"@opengeni/sdk\";\nexport type { VaultClientLike, VaultsApi } from \"@opengeni/sdk\";\nexport type {\n VaultPolicy,\n VaultOwnerKind,\n VaultSource,\n VaultMode,\n VaultSyncStatus,\n VaultItemType,\n VaultFieldKind,\n VaultAvailability,\n VaultSummary,\n VaultItemReferences,\n VaultItemSummary,\n VaultItemField,\n PasskeySummary,\n VaultItem,\n VaultVersionCreatedByKind,\n VaultFieldVersionMeta,\n GeneratePasswordOptions,\n CreateVaultRequest,\n UpdateVaultRequest,\n VaultFieldInput,\n CreateVaultItemRequest,\n UpdateVaultItemRequest,\n MoveVaultItemRequest,\n RevealVaultFieldResponse,\n SecretUseGrantScope,\n SecretUseGrant,\n VaultItemApproval,\n SetVaultItemApprovalRequest,\n ListVaultItemsQuery,\n SessionSecretsVault,\n SessionSecretsView,\n OnePasswordPlanTier,\n InstallOnePasswordRequest,\n ProviderVaultMeta,\n InstallOnePasswordResponse,\n OnePasswordConnectionSummary,\n ReplaceOnePasswordTokenRequest,\n DisconnectOnePasswordResponse,\n LinkProviderVaultRequest,\n CreateManagedProviderVaultRequest,\n VaultErrorCode,\n} from \"@opengeni/sdk\";\nexport { SecretsUiProvider, useSecretsUi } from \"./secrets-ui\";\nexport {\n SecretAnswerChip,\n SecretRefChip,\n SecretRefText,\n secretReferenceLabel,\n} from \"./components/secret-ref-chip\";\nexport type {\n SecretAnswerChipProps,\n SecretRefChipProps,\n SecretRefTextProps,\n SecretReferenceLabel,\n} from \"./components/secret-ref-chip\";\nexport type {\n SecretsUi,\n SecretReferenceLike,\n SecretReferenceTargetLike,\n SecretTextTokenLike,\n PasswordStrengthLike,\n} from \"./secrets-ui\";\nexport { useChannels } from \"./hooks/use-channels\";\nexport type { UseChannelsOptions, UseChannelsResult } from \"./hooks/use-channels\";\nexport { useRigs, useRig, useRigVersions, useRigChanges } from \"./hooks/use-rigs\";\nexport type {\n UseRigsOptions,\n UseRigsResult,\n UseRigOptions,\n UseRigResult,\n UseRigVersionsOptions,\n UseRigVersionsResult,\n UseRigChangesOptions,\n UseRigChangesResult,\n} from \"./hooks/use-rigs\";\nexport { useWorkspaces } from \"./hooks/use-workspaces\";\nexport type { UseWorkspacesOptions, UseWorkspacesResult } from \"./hooks/use-workspaces\";\nexport { useBillingUsage } from \"./hooks/use-billing-usage\";\nexport type { UseBillingUsageOptions, UseBillingUsageResult } from \"./hooks/use-billing-usage\";\nexport { useAvailableModels, useWorkspaceModelCatalog } from \"./hooks/use-available-models\";\nexport type {\n UseAvailableModelsOptions,\n UseAvailableModelsResult,\n UseWorkspaceModelCatalogOptions,\n UseWorkspaceModelCatalogResult,\n} from \"./hooks/use-available-models\";\n\n// Sandbox surfacing (Phase 5): capability negotiation + terminal/files/diff/desktop\nexport { useSessionCapabilities } from \"./hooks/use-session-capabilities\";\nexport type {\n SessionCapabilitiesState,\n UseSessionCapabilitiesOptions,\n UseSessionCapabilitiesResult,\n} from \"./hooks/use-session-capabilities\";\nexport { useDesktopStream } from \"./hooks/use-desktop-stream\";\nexport type { UseDesktopStreamOptions, UseDesktopStreamResult } from \"./hooks/use-desktop-stream\";\nexport { useRelayFrameStream } from \"./hooks/use-relay-frame-stream\";\nexport type {\n DesktopWebSocketFactory,\n DesktopWebSocketLike,\n UseRelayFrameStreamOptions,\n UseRelayFrameStreamResult,\n} from \"./hooks/use-relay-frame-stream\";\nexport { useTerminalStream } from \"./hooks/use-terminal-stream\";\nexport type {\n TerminalStreamStatus,\n UseTerminalStreamOptions,\n UseTerminalStreamResult,\n} from \"./hooks/use-terminal-stream\";\nexport { useSandboxTerminal } from \"./hooks/use-sandbox-terminal\";\nexport type {\n TerminalChunk,\n UseSandboxTerminalOptions,\n UseSandboxTerminalResult,\n} from \"./hooks/use-sandbox-terminal\";\nexport {\n CapturedFileUnavailableError,\n FileWriteConflictError,\n useSandboxFiles,\n} from \"./hooks/use-sandbox-files\";\nexport type {\n CapturedFileUnavailableReason,\n FileTreeNode,\n FileTreeStatus,\n SandboxFilesGitSummary,\n SandboxWriteFileOptions,\n UseSandboxFilesOptions,\n UseSandboxFilesResult,\n} from \"./hooks/use-sandbox-files\";\nexport { useSandboxGit } from \"./hooks/use-sandbox-git\";\nexport type {\n SandboxGitComparison,\n SandboxGitFileDiff,\n UseSandboxGitOptions,\n UseSandboxGitResult,\n} from \"./hooks/use-sandbox-git\";\n\n// Workbench v2 turn-end capture (the cold-paint data layer)\nexport { useWorkspaceCapture } from \"./hooks/use-workspace-capture\";\nexport type {\n UseWorkspaceCaptureOptions,\n UseWorkspaceCaptureResult,\n} from \"./hooks/use-workspace-capture\";\nexport { useWorkspaceEdit } from \"./hooks/use-workspace-edit\";\nexport type {\n UseWorkspaceEditOptions,\n UseWorkspaceEditResult,\n WorkspaceEditConflict,\n WorkspaceEditState,\n} from \"./hooks/use-workspace-edit\";\nexport { deriveMachineChip, formatAsOf, useMachineChip } from \"./hooks/use-machine-chip\";\nexport type {\n DeriveMachineChipInput,\n MachineChip,\n MachineChipState,\n UseMachineChipOptions,\n} from \"./hooks/use-machine-chip\";\n\n// Pending-approvals projection\nexport {\n approvalsDecidable,\n approvalsFromRequiresAction,\n projectPendingApprovals,\n} from \"./approvals\";\nexport type { PendingApproval } from \"./approvals\";\nexport { ApprovalSurface, defaultApprovalSurfaceMessages } from \"./components/approval-surface\";\nexport { ToolActionReviewCard, ToolActionReviewDetails } from \"./components/tool-action-review\";\nexport type { ToolReviewDetailsLoader } from \"./components/tool-action-review\";\nexport type { ApprovalSurfaceMessages, ApprovalSurfaceProps } from \"./components/approval-surface\";\n\n// Structured human input: event projection, authoritative hook, and styled form.\nexport { humanInputRequestFromEvent, projectPendingHumanInputRequests } from \"./human-input\";\nexport type { PendingHumanInputRequest } from \"./human-input\";\nexport { isHumanInputEvent, useHumanInputRequests } from \"./hooks/use-human-input\";\nexport type {\n UseHumanInputRequestsOptions,\n UseHumanInputRequestsResult,\n} from \"./hooks/use-human-input\";\nexport {\n HumanInputForm,\n answersFromDrafts,\n defaultHumanInputFormMessages,\n} from \"./components/human-input-form\";\nexport type {\n HumanInputAnswerDraft,\n HumanInputFormMessages,\n HumanInputFormProps,\n} from \"./components/human-input-form\";\nexport { HumanInputSurface } from \"./components/human-input-surface\";\nexport type { HumanInputSurfaceProps } from \"./components/human-input-surface\";\nexport { claimHumanInputDraftOwner, forgetAllHumanInputDrafts } from \"./human-input-draft-store\";\n\n// Timeline projection\nexport {\n buildTimeline,\n creditExhaustedFromEvents,\n creditRefusalFromEvents,\n extractSessionRef,\n groupTimeline,\n sessionStatusFromEvents,\n toolDisplayName,\n} from \"./timeline\";\nexport type {\n GroupTimelineOptions,\n ActivityItem,\n AgentMessageItem,\n AuthNeededItem,\n ContextCompactionItem,\n GoalItem,\n HumanInputAnswerSummary,\n HumanInputItem,\n MachineInputBatchItem,\n MachineInputMember,\n NoticeItem,\n ReasoningItem,\n SandboxItem,\n SessionStatusItem,\n SessionUsageLimitStop,\n TimelineGroup,\n TimelineItem,\n TurnEndItem,\n TurnStepsItem,\n TurnStepsState,\n ToolCallItem,\n ToolOutputPreview,\n UserMessageItem,\n WorkerItem,\n} from \"./timeline\";\n\n// Tool-renderer registry + the per-tool renderers (the timeline's extension API)\nexport {\n createDefaultToolRegistry,\n createSessionRetainedScreenshotLoader,\n createToolRegistry,\n createWorkspaceRetainedArtifactLoader,\n createWorkspaceRetainedVideoLoader,\n defaultToolRegistry,\n rawTypeOf,\n} from \"./timeline\";\nexport type {\n CreateToolRegistryOptions,\n RetainedArtifactLoader,\n RetainedArtifactLoadOptions,\n RetainedArtifactLoaderClient,\n RetainedScreenshotLoader,\n RetainedScreenshotLoaderClient,\n RetainedVideoLoaderClient,\n VideoArtifactPlaybackLoader,\n ToolRegistry,\n ToolRegistryEntry,\n ToolRenderer,\n ToolRendererProps,\n} from \"./timeline\";\n\n// Timeline rendering primitives + the screenshot lightbox (compose custom renderers)\nexport {\n ActivityDisclosure,\n ActivityRail,\n BodyNote,\n DisclosureDefaultsProvider,\n LightboxProvider,\n MediaEmpty,\n MediaSkeleton,\n PayloadBlock,\n ScreenshotFigure,\n TermBlock,\n Thumbnail,\n TurnSummary,\n BUILT_IN_TURN_SUMMARY_FACET_IDS,\n useLightbox,\n useLightboxGalleryItem,\n useLightboxOptional,\n} from \"./timeline\";\nexport type {\n ActivityDisclosureProps,\n ActivityRailProps,\n DisclosureChip,\n BuiltInTurnSummaryFacetId,\n TurnOutcome,\n TurnSummaryContext,\n TurnSummaryFacet,\n TurnSummaryFacetConfiguration,\n TurnSummaryFacetResult,\n TurnSummaryOptions,\n TurnSummaryProps,\n TurnSummaryStatus,\n LightboxControlLabels,\n LightboxGalleryEntry,\n LightboxGalleryImage,\n} from \"./timeline\";\n\n// Pure provider-shape parsers (exec banner, V4A diff, tool arguments, …)\nexport {\n applyPatchOps,\n applyPatchOpsFromToolItem,\n controlCaret,\n execTruncated,\n isApplyPatch,\n isExecSessionLostBanner,\n looksBinary,\n parseExecBannerSessionId,\n parseFreeformApplyPatch,\n parseToolArgs,\n sandboxCommandExitCode,\n stripExecBanner,\n tailPeek,\n unwrapMcpOutput,\n v4aToGitFileDiff,\n} from \"./timeline\";\nexport type { ApplyPatchOperation } from \"./timeline\";\n\n// Slash-command palette (registry + UI + hook)\nexport {\n argHint,\n defaultCommands,\n filterCommands,\n firstMissingRequiredArg,\n hasPermission,\n matchCommand,\n parseCommandLine,\n} from \"./commands/registry\";\nexport type { ParsedCommandLine } from \"./commands/registry\";\nexport type {\n CommandContext,\n CommandResult,\n Notice,\n SlashArg,\n SlashCommand,\n} from \"./commands/types\";\nexport { useSlashCommands } from \"./hooks/use-slash-commands\";\nexport type {\n ConfirmState,\n SlashCommandContext,\n SlashCommandHandlers,\n UseSlashCommandsOptions,\n UseSlashCommandsResult,\n} from \"./hooks/use-slash-commands\";\nexport { CommandPalette } from \"./components/command-palette\";\nexport type { CommandPaletteProps } from \"./components/command-palette\";\n\n// Components\nexport { ChatComposer } from \"./components/chat-composer\";\nexport { conversationTimeline } from \"./conversation-timeline\";\nexport { SessionConversation, SessionConversationView } from \"./components/session-conversation\";\nexport { useSessionConversation } from \"./hooks/use-session-conversation\";\nexport {\n useSessionReadAcknowledgement,\n type SessionAttentionClientLike,\n type UseSessionReadAcknowledgementInput,\n} from \"./hooks/use-session-read-acknowledgement\";\nexport { useNewConversation } from \"./hooks/use-new-conversation\";\nexport type {\n NewConversationController,\n UseNewConversationOptions,\n NewConversationCreateOptions,\n CreatedConversation,\n} from \"./hooks/use-new-conversation\";\nexport { NewConversation, NewConversationView } from \"./components/new-conversation\";\nexport type {\n NewConversationProps,\n NewConversationViewProps,\n NewConversationLabels,\n} from \"./components/new-conversation\";\nexport type {\n PendingPrompt,\n SessionConversationController,\n UseSessionConversationOptions,\n} from \"./hooks/use-session-conversation\";\nexport { SessionList } from \"./components/session-list\";\nexport type { SessionListLabels, SessionListProps } from \"./components/session-list\";\nexport { OpenGeniChat } from \"./components/open-geni-chat\";\nexport type {\n OpenGeniChatCreateOptions,\n OpenGeniChatLabels,\n OpenGeniChatProps,\n} from \"./components/open-geni-chat\";\nexport type {\n SessionConversationLabels,\n SessionConversationProps,\n SessionConversationViewProps,\n} from \"./components/session-conversation\";\nexport type { ChatComposerProps } from \"./components/chat-composer\";\nexport { ComposerTranscriptionControl } from \"./components/composer-transcription-control\";\nexport type {\n ComposerTranscriptionControlProps,\n ComposerVoiceInputOptions,\n ComposerTranscriptionMessages,\n} from \"./components/composer-transcription-control\";\nexport { defaultChatComposerMessages } from \"./components/composer\";\nexport type { ChatComposerMessages, ResponsiveBasis } from \"./components/composer\";\nexport { ModelPicker } from \"./components/model-picker\";\nexport type { ModelPickerProps } from \"./components/model-picker\";\nexport {\n BillingClassMark,\n ModelPolicyPicker,\n PickerAnimatedPage,\n PickerBackHeader,\n PickerNavRow,\n defaultModelPolicyPickerMessages,\n} from \"./components/model-policy-picker\";\nexport { ModelPolicyPickerMenu } from \"./components/model-policy-picker-menu\";\nexport type {\n ModelPolicyPickerMessages,\n ModelPolicyPickerProps,\n ModelPolicyPickerGroupPresentation,\n} from \"./components/model-policy-picker\";\nexport {\n advancedSourceSummary,\n availabilityReasonLabel,\n billingClassForModel,\n billingClassLabel,\n coerceReasoningEffortForModel,\n defaultEffortForModel,\n effortOptionsForModel,\n findPickerRow,\n groupPickerRowsByBillingClass,\n labelLatencyMode,\n labelReasoningEffort,\n payerSummaryForModel,\n modelUsesCredits,\n projectClientModelRows,\n projectPickerRows,\n runnableLatencyModesForModel,\n sortPickerRows,\n} from \"./model-policy\";\nexport type {\n GroupPickerRowsOptions,\n LatencyModeId,\n PickerBillingClass,\n PickerModelRow,\n} from \"./model-policy\";\nexport { ChatGptMark, ModelMark, ModelName, modelHasMark } from \"./components/model-mark\";\nexport {\n REGION_RESTRICTED,\n inferenceFeatureRestriction,\n isRegionRestricted,\n regionRestrictedText,\n} from \"./inference-region\";\nexport {\n humanizeModelSlug,\n isRawModelLabel,\n modelDisplayName,\n modelSlug,\n modelVendor,\n} from \"@opengeni/sdk/model-display\";\nexport type { ModelDisplayInput, ModelVendor } from \"@opengeni/sdk/model-display\";\nexport { MessageTimeline, TimelineRow } from \"./components/message-timeline\";\nexport { GeneratedVideoPlayer } from \"./components/generated-video-player\";\nexport type { GeneratedVideoPlayerProps } from \"./components/generated-video-player\";\nexport type { MessageTimelineProps } from \"./components/message-timeline\";\nexport { MessageSenderLabel } from \"./timeline/message-sender\";\nexport type { RenderMessageSender } from \"./timeline/message-sender\";\nexport type { MessageSender } from \"./timeline\";\nexport type { RenderAllowanceExhausted } from \"./timeline/allowance-exhausted-row\";\nexport type { AllowanceLabels, AllowanceScope } from \"./usage/allowance-copy\";\nexport type { TimelineSearchTarget } from \"./components/timeline-search\";\nexport { UserMessageBody, userMessageLikelyNeedsDisclosure } from \"./components/user-message-body\";\nexport type {\n UserMessageBodyProps,\n UserMessageDisclosureLabels,\n} from \"./components/user-message-body\";\nexport {\n Markdown,\n sandboxFileLocationFromHref,\n sandboxFilePathFromHref,\n} from \"./components/markdown\";\nexport type {\n MarkdownProps,\n MarkdownInteractiveBlock,\n SandboxFileLocation,\n} from \"./components/markdown\";\nexport {\n OpenGeniLinkProvider,\n chainLinkRenderers,\n chainLinkResolvers,\n sessionLinkResolver,\n useOpenGeniLinkRenderer,\n useOpenGeniLinkResolver,\n viewerLinkResolver,\n} from \"./components/open-geni-links\";\nexport type {\n OpenGeniHostLink,\n OpenGeniLinkRenderer,\n OpenGeniLinkResolution,\n OpenGeniLinkResolver,\n OpenGeniLinkTarget,\n OpenGeniViewerTarget,\n} from \"./components/open-geni-links\";\nexport { parseOpenGeniLink } from \"@opengeni/sdk\";\nexport {\n ArtifactLabelsProvider,\n DEFAULT_ARTIFACT_LABELS,\n type ArtifactLabels,\n} from \"./components/artifacts/artifact-chrome\";\nexport { CopyButton, CopyHoverFrame } from \"./components/copy-button\";\nexport { copyTextToClipboard, tableElementToTsv } from \"./lib/clipboard\";\nexport { SessionStatus, StatusDot, SESSION_STATUS_META } from \"./components/session-status\";\nexport {\n promptSendDestination,\n sessionAdmissionBlocked,\n sessionDisplayStatus,\n} from \"./session-status-model\";\nexport type { SessionDisplayStatus } from \"./session-status-model\";\nexport type {\n SessionStatusProps,\n StatusDotProps,\n SessionStatusMeta,\n} from \"./components/session-status\";\nexport { FleetTile, sessionDisplayTitle } from \"./components/fleet-tile\";\nexport type { FleetTileProps } from \"./components/fleet-tile\";\n\n// Sandbox surfacing components (Phase 5)\nexport { SandboxTerminal } from \"./components/sandbox-terminal\";\nexport type { SandboxTerminalProps, XtermTheme } from \"./components/sandbox-terminal\";\nexport { FileBrowser } from \"./components/file-browser\";\nexport type { FileBrowserProps } from \"./components/file-browser\";\nexport { WorkbenchChanges } from \"./components/workbench-changes\";\nexport type { WorkbenchChangesProps } from \"./components/workbench-changes\";\nexport { DiffView } from \"./components/diff-view\";\nexport type { DiffViewProps, DiffTheme } from \"./components/diff-view\";\nexport { PierreDiff } from \"./components/pierre-diff\";\n// Opt in to the optional `@pierre/diffs` peer with `enablePierreDiffs()` from\n// `@opengeni/react/diffs`; the root entry never names the peer.\nexport { registerPierreDiffs, type PierreDiffsLoader } from \"./lib/pierre-diffs-loader\";\n// Bundler-visible optional workbench imports live only on opt-in subpaths.\nexport {\n registerSandboxTerminal,\n registerCodeEditor,\n registerDesktopViewer,\n} from \"./lib/workbench-peers\";\nexport type {\n WorkbenchPeerLoader,\n SandboxTerminalPeers,\n CodeEditorPeers,\n CodeEditorLanguage,\n CodeEditorLanguages,\n} from \"./lib/workbench-peers\";\nexport type { PierreDiffProps } from \"./components/pierre-diff\";\nexport { PierreFile } from \"./components/pierre-file\";\nexport type { PierreFileProps } from \"./components/pierre-file\";\nexport { CodeEditor, languageForPath } from \"./components/code-editor\";\nexport type { CodeEditorProps } from \"./components/code-editor\";\nexport { SandboxFiles } from \"./components/sandbox-files\";\nexport type { SandboxFilesProps } from \"./components/sandbox-files\";\nexport { DesktopViewer } from \"./components/desktop-viewer\";\nexport type { DesktopViewerProps } from \"./components/desktop-viewer\";\nexport { WorkspaceDock, useWorkspacePanelOwnsExpand } from \"./components/workspace-dock\";\nexport type { WorkspaceDockProps, WorkspaceTab } from \"./components/workspace-dock\";\n\n// The embeddable dock \"brain\" (Workbench v2, M4): the whole session workspace as\n// one component + the tab-building hook + the pre-paint default-tab helper.\nexport {\n SandboxWorkspace,\n useSandboxWorkspaceTabs,\n initialWorkspaceTab,\n WORKBENCH_TAB_CHANGES,\n WORKBENCH_TAB_FILES,\n WORKBENCH_TAB_TERMINAL,\n WORKBENCH_TAB_BROWSER,\n WORKBENCH_TAB_DESKTOP,\n WORKBENCH_SURFACES,\n} from \"./components/sandbox-workspace\";\nexport type {\n SandboxWorkspaceSurface,\n SandboxWorkspaceProps,\n UseSandboxWorkspaceTabsOptions,\n UseSandboxWorkspaceTabsResult,\n WorkspaceMachine,\n WorkspaceNotification,\n} from \"./components/sandbox-workspace\";\n\n// Connected-machine UI moved to the \"@opengeni/react/machines\" subpath; re-exported\n// here for back-compat (#144).\nexport * from \"./machines\";\n// Multi-account Codex (P1): accounts list + active-switch hook.\nexport { useCodexAccounts, isCodexAccountEvent } from \"./hooks/use-codex-accounts\";\nexport type {\n CodexAccountsClientLike,\n UseCodexAccountsOptions,\n UseCodexAccountsResult,\n} from \"./hooks/use-codex-accounts\";\n// Model-account choice for every provider on the shared subscription core.\nexport { useSessionModelAccount, isModelAccountEvent } from \"./hooks/use-session-model-account\";\nexport type {\n ModelAccountClientLike,\n UseSessionModelAccountOptions,\n UseSessionModelAccountResult,\n} from \"./hooks/use-session-model-account\";\nexport { useSuperGrokAccounts } from \"./hooks/use-supergrok-accounts\";\nexport type {\n SuperGrokAccountsClientLike,\n UseSuperGrokAccountsOptions,\n UseSuperGrokAccountsResult,\n} from \"./hooks/use-supergrok-accounts\";\n\n// Sandbox helpers\nexport { gitFileDiffToPatch } from \"./lib/git-patch\";\nexport { xtermThemeFromTokens } from \"./lib/xterm-theme\";\n\n// Utilities\nexport { cn } from \"./lib/cn\";\nexport { markClassicScrollbars } from \"./lib/scrollbars\";\nexport {\n CREDIT_EXHAUSTION_MESSAGE,\n formatBytes,\n formatClockTime,\n formatRelativeTime,\n humanizeFailureReason,\n presentFailure,\n isCreditExhaustion,\n stringifyPayload,\n truncate,\n tryParseJson,\n} from \"./lib/format\";\nexport {\n currentProviderRecovery,\n parseProviderRecovery,\n providerRecoveryExhaustedText,\n providerRecoveryRetryingText,\n providerRecoverySubject,\n type ProviderRecoveryCondition,\n type ProviderRecoveryFacts,\n} from \"./lib/provider-recovery\";\nexport {\n ProviderRecoveryNotice,\n PROVIDER_RECOVERY_NOTICE_DETAIL,\n type ProviderRecoveryNoticeProps,\n} from \"./components/provider-recovery-notice\";\nexport { SessionCommandsPanel } from \"./components/session-commands-panel\";\nexport { SessionCommands } from \"./components/session-commands\";\n\nexport { KnowledgeActivityProvider } from \"./timeline/knowledge-receipt\";\nexport {\n PaymentPageActivityProvider,\n type PaymentPageActivity,\n} from \"./timeline/payment-page-activity\";\nexport {\n LearningRefusalActionsProvider,\n type LearningRefusalActions,\n} from \"./timeline/learning-refusal-row\";\nexport type { LearningRefusalPlace } from \"./timeline/learning-refusal-copy\";\nexport type { KnowledgeActivityActions } from \"./timeline/knowledge-receipt\";\n\nexport { StartupTimings } from \"./timeline/startup-timings\";\nexport { setStartupDetails, useStartupDetails } from \"./timeline/startup-preference\";\n\nexport { ClaudeMark } from \"./components/claude-mark\";\nexport { AnthropicMark } from \"./components/anthropic-mark\";\nexport { OpenRouterMark } from \"./components/openrouter-mark\";\nexport { OpperMark } from \"./components/opper-mark\";\nexport { GrokMark } from \"./components/grok-mark\";\n\nexport { ToolReviewHistoryProvider } from \"./components/tool-review-history\";\nexport { InteractiveAnswer, type InteractiveAnswerProps } from \"./components/interactive-answer\";\nexport {\n browserInteractiveAnswerStore,\n INTERACTIVE_ANSWER_FENCE,\n InteractiveAnswerProvider,\n type InteractiveAnswerHost,\n type InteractiveAnswerStore,\n} from \"./interactive-answer-model\";\n","import type { CreateWorkspaceRequest, UpdateWorkspaceRequest, Workspace } from \"@opengeni/sdk\";\nimport { useCallback } from \"react\";\nimport { useOpenGeniClient, type ClientOverride } from \"../provider\";\nimport { useMutationRunner, usePolledValue } from \"./internal\";\n\nexport type UseWorkspacesOptions = Pick<ClientOverride, \"client\"> & {\n pollIntervalMs?: number | undefined;\n enabled?: boolean | undefined;\n};\n\nexport type UseWorkspacesResult = {\n workspaces: Workspace[];\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n create: (request: CreateWorkspaceRequest) => Promise<Workspace | null>;\n update: (workspaceId: string, request: UpdateWorkspaceRequest) => Promise<Workspace | null>;\n mutating: boolean;\n mutationError: Error | null;\n clearMutationError: () => void;\n};\n\n/**\n * The caller's workspaces (workspace switchers, onboarding). Not scoped to\n * the provider's workspace, so it only needs the client.\n */\nexport function useWorkspaces(options: UseWorkspacesOptions = {}): UseWorkspacesResult {\n const client = useOpenGeniClient(options);\n const load = useCallback(async () => await client.listWorkspaces(), [client]);\n const { data, loading, error, refresh } = usePolledValue(load, {\n pollIntervalMs: options.pollIntervalMs,\n enabled: options.enabled,\n });\n const { run, mutating, mutationError, clearMutationError } = useMutationRunner();\n\n const create = useCallback(\n async (request: CreateWorkspaceRequest): Promise<Workspace | null> => {\n const result = await run(() => client.createWorkspace(request));\n if (result) {\n await refresh();\n }\n return result;\n },\n [client, run, refresh],\n );\n\n const update = useCallback(\n async (workspaceId: string, request: UpdateWorkspaceRequest): Promise<Workspace | null> => {\n const result = await run(() => client.updateWorkspace(workspaceId, request));\n if (result) {\n await refresh();\n }\n return result;\n },\n [client, run, refresh],\n );\n\n return {\n workspaces: data ?? [],\n loading,\n error,\n refresh,\n create,\n update,\n mutating,\n mutationError,\n clearMutationError,\n };\n}\n","import type { BillingBalance, UsageEvent } from \"@opengeni/sdk\";\nimport { useCallback } from \"react\";\nimport { useOpenGeniClient, type ClientOverride } from \"../provider\";\nimport { usePolledValue } from \"./internal\";\n\nexport type UseBillingUsageOptions = Pick<ClientOverride, \"client\"> & {\n /** Account to read. Defaults to the caller's default account server-side. */\n accountId?: string | undefined;\n /** Filter usage to one workspace. */\n workspaceId?: string | undefined;\n /** Refresh interval (ms) for live billing meters. Off by default. */\n pollIntervalMs?: number | undefined;\n enabled?: boolean | undefined;\n};\n\nexport type UseBillingUsageResult = {\n /** Prepaid credit balance (micro-USD), null until loaded. */\n balance: BillingBalance | null;\n /** Recent usage events (runs, tokens, cost, uploads, ...). */\n usage: UsageEvent[];\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n};\n\n/**\n * Account billing usage: credit balance + recent usage events — the data\n * behind per-call billing meters. Account-scoped, so it only needs the\n * client; pass `workspaceId` to narrow usage to one workspace.\n */\nexport function useBillingUsage(options: UseBillingUsageOptions = {}): UseBillingUsageResult {\n const client = useOpenGeniClient(options);\n const accountId = options.accountId;\n const workspaceId = options.workspaceId;\n const load = useCallback(\n async () =>\n await client.getBillingUsage({\n ...(accountId !== undefined ? { accountId } : {}),\n ...(workspaceId !== undefined ? { workspaceId } : {}),\n }),\n [client, accountId, workspaceId],\n );\n const state = usePolledValue(load, {\n pollIntervalMs: options.pollIntervalMs,\n enabled: options.enabled,\n });\n return {\n balance: state.data?.balance ?? null,\n usage: state.data?.usage ?? [],\n loading: state.loading,\n error: state.error,\n refresh: state.refresh,\n };\n}\n","import {\n OpenGeniApiError,\n applyUrlRotation,\n type SessionCapabilities,\n type SessionEvent,\n type StreamUrlRotatedPayload,\n} from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { sandboxAcceptsLiveIo } from \"../lib/sandbox-liveness\";\nimport { terminalCanAcquirePty } from \"../lib/terminal-capability\";\nimport { normalizeError } from \"../lib/error-message\";\nimport { usePageLiveActivity } from \"./internal\";\n\n// \"on-demand\" is the boxless-benign resting state: the lease is not currently\n// holder-backed and NOTHING asked to warm a box (no viewer/consent action, no\n// files-tab warm). Under lazy\n// provisioning a chat-only turn never creates a box, so this is the correct calm\n// terminal state — NOT an error. It is distinct from \"cold\", which now means \"a\n// warm-up is genuinely in flight\" (a viewer attach was requested) and therefore\n// still polls with a patience deadline. A box appears on demand when the agent\n// first runs a sandbox tool; the workbench observes `sandbox.provision` and\n// renegotiates to pick up the freshly-warm box.\nexport type SessionCapabilitiesState =\n | \"idle\"\n | \"negotiating\"\n | \"ready\"\n | \"cold\"\n | \"on-demand\"\n | \"error\";\n\nexport type UseSessionCapabilitiesOptions = ClientOverride & {\n /**\n * Live event log to fold `stream.url.rotated` from (usually\n * `useSessionEvents().events`). When present the desktop socket stays fresh on\n * a box rollover without a round-trip; stale-epoch rotations are dropped.\n */\n events?: SessionEvent[] | undefined;\n /**\n * Whether to acquire a viewer holder for the desktop pixel plane. Requires the\n * un-redacted acknowledgment to have been recorded (else the attach 409s and\n * the hook surfaces the consent requirement). Default false: read-only\n * negotiation (no holder, no warm) — terminal/files/git work without it.\n */\n attachDesktop?: boolean | undefined;\n /**\n * Whether to acquire a viewer holder to warm the box for the REAL interactive\n * terminal (the ttyd pty-ws plane). Symmetric with `attachDesktop` and shares\n * the SAME viewer attach (one warm box serves both planes), but needs NO\n * un-redacted acknowledgment — a shell is interactive by nature, and the gate\n * is the scoped tunnel URL + stream token. Default false: the terminal stays on\n * the read-only Channel-A firehose until the user opens/focuses it. The attach\n * folds the minted `pty-ws` url+token into the `Terminal` cell.\n */\n attachTerminal?: boolean | undefined;\n /**\n * Whether to acquire a viewer holder to warm the box for a FILE WRITE — the\n * wake-on-edit INTENT (a first keystroke in the editor), NOT passive browsing.\n * Shares the SAME viewer attach as the desktop/terminal (one warm box, one\n * holder) and — like the terminal — needs NO un-redacted acknowledgment:\n * reading/writing files is the ordinary Channel-A control plane, not the pixel\n * plane. It folds NO live URL (files ride the stateless HTTP plane) — it only\n * refcounts liveness. Unlike desktop/terminal it warms even a COLD box: an edit\n * legitimately cold-creates (that IS the wake), so the write lands ~100ms warm\n * instead of paying the ~5s cold resume. Default false. IMPORTANT: merely\n * opening/reading the Files tab must NOT set this — browsing capture-served\n * trees/diffs needs no box, and warming one on a cold glance burns box-hours to\n * serve reads the capture already answers for free.\n */\n attachFiles?: boolean | undefined;\n /** Hold off negotiating (e.g. the workbench panel is collapsed). Default true. */\n enabled?: boolean | undefined;\n /** Poll cadence (ms) while the lease is cold/warming. Default 1500. */\n warmingPollMs?: number | undefined;\n /**\n * Give up waiting for `warm` after this long while polling (ms) and surface a\n * stalled error with a manual `renegotiate`. Default 30000. This is a UI\n * patience deadline, independent from the worker's sandbox warming timeout.\n * 0 disables the deadline.\n */\n warmingDeadlineMs?: number | undefined;\n};\n\nexport type UseSessionCapabilitiesResult = {\n /** The negotiated capability doc — the single source of UI truth. */\n capabilities: SessionCapabilities | null;\n state: SessionCapabilitiesState;\n error: Error | null;\n /**\n * 409 from the desktop attach: the un-redacted (or shared) plane needs explicit\n * acknowledgment before a viewer holder is granted. The workbench uses this\n * to complete acknowledgment automatically while Desktop is opening.\n */\n acknowledgmentRequired: \"unredacted\" | \"shared\" | null;\n /** 429 from the desktop attach: the per-session viewer cap is reached. */\n viewerCapReached: boolean;\n /** The viewer holder id minted on a desktop attach (for detach/heartbeat). */\n viewerId: string | null;\n /** Force a re-negotiation (after acknowledging, a resolution change, etc.). */\n renegotiate: () => void;\n};\n\n/**\n * Whether a desktop attach (POST /viewers) is worth attempting for this cell.\n * The desktop is FEASIBLE — and thus worth warming — when it already has a live\n * transport, OR when the only thing missing is a warm box (a cold/un-provisioned\n * lease). The handshake never warms a box, so a feasible-but-cold cell reports\n * transport:null with a transient reason; the viewer attach is exactly what warms\n * it. A genuinely-unsupported desktop (backend/os/policy/headless) is never\n * attachable — attaching would 409/403/no-op without ever producing a stream.\n */\nfunction desktopAttachable(cell: SessionCapabilities[\"DesktopStream\"]): boolean {\n if (cell.transport !== null) return true;\n // transport === null: attach only when the reason is a transient cold state.\n return cell.reason === \"lease_cold\" || cell.reason === \"not_provisioned\" || cell.reason === null;\n}\n\n/**\n * Whether warming the box for the interactive terminal (pty-ws) is worth it.\n * A real-PTY descriptor is attachable when already routed as `pty-ws`, or while\n * transiently cold. A firehose-only backend and policy/OS/backend degradation\n * cannot become interactive, so attaching there would only waste a holder.\n */\n/** Read `stream.url.rotated` payloads off the live event log, newest last. */\nfunction rotationsFrom(events: SessionEvent[]): StreamUrlRotatedPayload[] {\n const out: StreamUrlRotatedPayload[] = [];\n for (const event of events) {\n if (event.type === \"stream.url.rotated\" && event.payload && typeof event.payload === \"object\") {\n out.push(event.payload as StreamUrlRotatedPayload);\n }\n }\n return out;\n}\n\n/**\n * The capability-negotiation hook. Discovers what THIS session+backend+OS\n * supports (FileSystem/Terminal/Git always-ish; DesktopStream/Recording\n * sometimes), drives capability-gated rendering, and — when `attachDesktop` —\n * holds a viewer lease + heartbeats it so the box stays warm while watched.\n *\n * Degradation is a value, never a crash: an unsupported surface comes back\n * `available:false`/`transport:null` + a `reason`; the components render the\n * reason-aware empty state. 409 (acknowledgment) and 429 (viewer cap) are\n * surfaced as typed signals, not thrown.\n */\nexport function useSessionCapabilities(\n sessionId: string | null | undefined,\n options: UseSessionCapabilitiesOptions = {},\n): UseSessionCapabilitiesResult {\n const { client, workspaceId } = useOpenGeni(options);\n const enabled = (options.enabled ?? true) && Boolean(sessionId);\n const pageLive = usePageLiveActivity();\n const lifecycleEnabled = enabled && pageLive;\n const attachDesktop = options.attachDesktop ?? false;\n const attachTerminal = options.attachTerminal ?? false;\n const attachFiles = options.attachFiles ?? false;\n const warmingPollMs = options.warmingPollMs ?? 1500;\n const warmingDeadlineMs = options.warmingDeadlineMs ?? 30_000;\n const identityKey = `${workspaceId}\\u0000${sessionId ?? \"\"}\\u0000${enabled}`;\n\n const [capabilities, setCapabilities] = useState<SessionCapabilities | null>(null);\n const [state, setState] = useState<SessionCapabilitiesState>(\"idle\");\n const [error, setError] = useState<Error | null>(null);\n const [acknowledgmentRequired, setAcknowledgmentRequired] = useState<\n \"unredacted\" | \"shared\" | null\n >(null);\n const [viewerCapReached, setViewerCapReached] = useState(false);\n const [viewerId, setViewerId] = useState<string | null>(null);\n const [stateIdentity, setStateIdentity] = useState(identityKey);\n // Bumped to force a fresh negotiation cycle.\n const [nonce, setNonce] = useState(0);\n\n // The epoch the client has settled on — used to fence stale rotations folded\n // from the event log, and echoed on heartbeats.\n const epochRef = useRef(0);\n const viewerIdRef = useRef<string | null>(null);\n const previousIdentityRef = useRef(identityKey);\n\n const renegotiate = useCallback(() => {\n setNonce((n) => n + 1);\n }, []);\n\n // ── Negotiation + viewer lifecycle ──────────────────────────────────────────\n useEffect(() => {\n const identityChanged = previousIdentityRef.current !== identityKey;\n previousIdentityRef.current = identityKey;\n if (identityChanged) {\n setStateIdentity(identityKey);\n setCapabilities(null);\n setState(\"idle\");\n setError(null);\n setAcknowledgmentRequired(null);\n setViewerCapReached(false);\n setViewerId(null);\n epochRef.current = 0;\n viewerIdRef.current = null;\n }\n if (!lifecycleEnabled || !sessionId) {\n setState(\"idle\");\n setCapabilities(null);\n viewerIdRef.current = null;\n setViewerId(null);\n return;\n }\n // The preceding effect cleanup released any old holder before this fresh\n // lifecycle starts. Never project that stale id while re-negotiating or if\n // the replacement grant degrades.\n viewerIdRef.current = null;\n setViewerId(null);\n let cancelled = false;\n let pollTimer: ReturnType<typeof setTimeout> | null = null;\n let heartbeatTimer: ReturnType<typeof setTimeout> | null = null;\n let localViewerId: string | null = null;\n const requestAbort = new AbortController();\n const startedAt = Date.now();\n\n const clearTimers = () => {\n if (pollTimer !== null) clearTimeout(pollTimer);\n if (heartbeatTimer !== null) clearTimeout(heartbeatTimer);\n pollTimer = null;\n heartbeatTimer = null;\n };\n\n const settle = (caps: SessionCapabilities) => {\n if (cancelled) return;\n epochRef.current = caps.leaseEpoch;\n setCapabilities(caps);\n setError(null);\n };\n\n const startHeartbeat = (caps: SessionCapabilities) => {\n if (!localViewerId || heartbeatTimer !== null) return;\n const intervalMs =\n caps.viewerHeartbeatIntervalMs > 0 ? caps.viewerHeartbeatIntervalMs : 30_000;\n const schedule = () => {\n if (cancelled || !localViewerId) return;\n heartbeatTimer = setTimeout(() => {\n heartbeatTimer = null;\n if (cancelled || !localViewerId) return;\n void client\n .heartbeatViewer(workspaceId, sessionId, localViewerId, {\n leaseEpoch: epochRef.current,\n })\n .then((res) => {\n // alive:false ⇒ the holder was reaped or the epoch moved under us;\n // re-negotiate to re-acquire against the new owner.\n if (!res.alive && !cancelled) {\n renegotiate();\n }\n })\n .catch((cause) => {\n if (cancelled) return;\n if (\n cause instanceof OpenGeniApiError &&\n (cause.status === 409 || cause.status === 410)\n ) {\n renegotiate();\n }\n })\n .finally(schedule);\n }, intervalMs);\n };\n schedule();\n };\n\n const pollUntilWarm = () => {\n pollTimer = setTimeout(() => {\n if (cancelled) return;\n void client\n .getStreamCapabilities(workspaceId, sessionId, { signal: requestAbort.signal })\n .then((caps) => {\n if (cancelled) return;\n settle(caps);\n if (sandboxAcceptsLiveIo(caps.liveness)) {\n setState(\"ready\");\n return;\n }\n if (warmingDeadlineMs > 0 && Date.now() - startedAt > warmingDeadlineMs) {\n setState(\"error\");\n setError(new Error(\"sandbox did not warm in time — retry to re-negotiate\"));\n return;\n }\n pollUntilWarm();\n })\n .catch((cause) => {\n if (!cancelled) {\n if (isSandboxOwnershipDisabledError(cause)) {\n setState(\"on-demand\");\n setError(null);\n return;\n }\n setState(\"error\");\n setError(normalizeError(cause));\n }\n });\n }, warmingPollMs);\n };\n\n void (async () => {\n setState(\"negotiating\");\n setAcknowledgmentRequired(null);\n setViewerCapReached(false);\n try {\n const caps = await client.getStreamCapabilities(workspaceId, sessionId, {\n signal: requestAbort.signal,\n });\n if (cancelled) return;\n settle(caps);\n\n // Optional viewer attach: acquire a viewer holder (warms a cold box). ONE\n // attach serves BOTH live planes — the desktop pixel stream AND the\n // interactive terminal (ttyd pty-ws) ride the same warm box and the same\n // holder; the response folds the minted address for each requested plane.\n // The acknowledgment requirement (409) and viewer cap (429) surface as\n // typed signals rather than throwing — the tabs degrade gracefully.\n //\n // KEY: the handshake (getStreamCapabilities) NEVER spins up a cold box, so\n // on a cold/warming lease the desktop cell comes back transport:null and\n // the terminal cell comes back `sse-events` (read-only firehose) with a\n // transient reason (`lease_cold`/`not_provisioned`). Gating the attach on\n // `transport` therefore dead-ends both surfaces (forever \"Starting…\"): they\n // never warm because they never attach, and never attach because they\n // aren't warm. We attach whenever a REQUESTED plane is FEASIBLE — transport\n // already live OR cold-but-feasible — and let POST /viewers warm the box and\n // mint the URLs. Only a genuinely-unsupported reason suppresses the attach.\n const wantDesktopAttach = attachDesktop && desktopAttachable(caps.DesktopStream);\n const wantTerminalAttach = attachTerminal && terminalCanAcquirePty(caps.Terminal);\n // The Files attach warms the box for a file WRITE (wake-on-edit intent). It\n // folds no live URL (files are stateless HTTP) — the attach is purely a\n // liveness refcount. Unlike the previous \"keep the box warm while the Files\n // tab is on screen\" wiring, this fires on genuine EDIT intent only, so it\n // legitimately cold-CREATES: an edit is the wake, and the caller (the dock)\n // never sets it for passive browsing. Gate solely on the FileSystem cap\n // being advertised; liveness (cold included) does not suppress it — POST\n // /viewers warms a cold box exactly as it does for a desktop/terminal engage.\n const wantFilesAttach = attachFiles && caps.FileSystem.available;\n if (wantDesktopAttach || wantTerminalAttach || wantFilesAttach) {\n try {\n // Declare WHICH plane we're attaching for. `desktop:true` opts into the\n // un-redacted pixel plane (which carries the consent gate); a\n // terminal-only attach (`desktop:false`) warms the box + mints the\n // pty-ws terminal cell WITHOUT tripping the desktop consent 409.\n const holder = await client.attachViewer(workspaceId, sessionId, {\n desktop: wantDesktopAttach,\n terminal: wantTerminalAttach,\n files: wantFilesAttach,\n });\n if (cancelled) {\n // The attach crossed an identity/unmount boundary after the server\n // had already minted a holder. It is too late to publish the result,\n // but abandoning it would keep the old sandbox warm until the\n // reaper runs. Release that exact old-session holder immediately.\n void client.detachViewer(workspaceId, sessionId, holder.viewerId).catch(() => {});\n return;\n }\n if (\n (wantDesktopAttach &&\n (!holder.dataPlaneUrl || !holder.transport || !holder.client)) ||\n (wantTerminalAttach && (!holder.terminalUrl || !holder.terminalTransport))\n ) {\n // Nullable plane cells are valid graceful-degradation values at\n // the raw API boundary, but an explicit UI grant must not become\n // a successful holder that waits forever. Release it and surface\n // a retryable error instead of retaining stale credentials.\n await client.detachViewer(workspaceId, sessionId, holder.viewerId).catch(() => {});\n throw new Error(\"live plane unavailable\");\n }\n localViewerId = holder.viewerId;\n viewerIdRef.current = holder.viewerId;\n setViewerId(holder.viewerId);\n epochRef.current = holder.leaseEpoch;\n // Fold the freshly-minted live address(es) into the doc the components\n // read. Desktop fields fold only when a desktop attach was wanted;\n // terminal fields fold the minted ttyd pty-ws url+token when present.\n setCapabilities((prev) =>\n prev\n ? {\n ...prev,\n liveness: holder.liveness,\n leaseEpoch: holder.leaseEpoch,\n viewerHeartbeatIntervalMs: holder.viewerHeartbeatIntervalMs,\n DesktopStream: wantDesktopAttach\n ? {\n ...prev.DesktopStream,\n transport: holder.transport ?? prev.DesktopStream.transport,\n client: holder.client ?? prev.DesktopStream.client,\n url: holder.dataPlaneUrl,\n token: holder.streamToken,\n expiresAt: holder.streamExpiresAt,\n resolution: holder.resolution ?? prev.DesktopStream.resolution,\n }\n : prev.DesktopStream,\n Terminal: wantTerminalAttach\n ? {\n ...prev.Terminal,\n transport: holder.terminalTransport ?? prev.Terminal.transport,\n url: holder.terminalUrl,\n token: holder.terminalToken,\n expiresAt: holder.terminalExpiresAt,\n // A live pty-ws means the box is pty-capable for real.\n ptyCapable: holder.terminalTransport ? true : prev.Terminal.ptyCapable,\n reason: holder.terminalTransport ? null : prev.Terminal.reason,\n }\n : prev.Terminal,\n }\n : prev,\n );\n } catch (cause) {\n if (cancelled) return;\n if (cause instanceof OpenGeniApiError) {\n if (cause.status === 409) {\n // The un-redacted/shared consent gate is a DESKTOP requirement. A\n // terminal-only warm attach needs no acknowledgment, so a 409 there\n // is not a desktop-open signal — the terminal stays on the read-only\n // firehose. Only raise the consent requirement when the desktop was\n // the (or a) reason we attached.\n if (wantDesktopAttach) {\n setAcknowledgmentRequired(\n cause.message.includes(\"shared_acknowledgment\") ? \"shared\" : \"unredacted\",\n );\n }\n } else if (cause.status === 429) {\n setViewerCapReached(true);\n } else if (cause.status === 403) {\n setState(\"error\");\n setError(cause);\n return;\n } else {\n throw cause;\n }\n // 409/429 are recoverable: structured surfaces still negotiated;\n // keep going to set ready/cold below.\n } else {\n throw cause;\n }\n }\n }\n\n // Whether ANYTHING asked to warm a box this negotiation. Only then is a\n // non-warm lease \"warming in flight\" — worth polling, and worth surfacing a\n // stall as an error. With no warm-up requested a cold lease is the benign\n // boxless resting state (below), never an error.\n const warmUpRequested = wantDesktopAttach || wantTerminalAttach || wantFilesAttach;\n if (sandboxAcceptsLiveIo(caps.liveness) || localViewerId) {\n setState(\"ready\");\n startHeartbeat(caps);\n } else if (warmUpRequested) {\n // A warm-up is genuinely in flight (a viewer attach was requested) but the\n // box isn't holder-confirmed warm yet — poll until it is, with the deadline so a\n // real stall surfaces as an error.\n setState(\"cold\");\n pollUntilWarm();\n } else {\n // Boxless and nobody asked for a box: rest in the benign on-demand state.\n // NO poll, NO deadline, NO false \"sandbox offline\". The box is created on\n // demand when the agent first runs a sandbox tool; the workbench watches\n // for `sandbox.provision` and renegotiates to pick the warm box back up.\n setState(\"on-demand\");\n }\n } catch (cause) {\n if (cancelled) return;\n if (isSandboxOwnershipDisabledError(cause)) {\n setState(\"on-demand\");\n setError(null);\n return;\n }\n if (cause instanceof OpenGeniApiError && cause.status === 403) {\n setState(\"error\");\n setError(new Error(\"not permitted to view this session's sandbox\"));\n return;\n }\n setState(\"error\");\n setError(normalizeError(cause));\n }\n })();\n\n return () => {\n cancelled = true;\n requestAbort.abort();\n clearTimers();\n // Fire-and-forget detach (idempotent delete-my-row). Capture the id so a\n // re-render/unmount race still releases the right holder.\n const releaseId = localViewerId ?? viewerIdRef.current;\n if (releaseId) {\n void client.detachViewer(workspaceId, sessionId, releaseId).catch(() => {});\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n client,\n workspaceId,\n sessionId,\n lifecycleEnabled,\n attachDesktop,\n attachTerminal,\n attachFiles,\n warmingPollMs,\n warmingDeadlineMs,\n nonce,\n identityKey,\n ]);\n\n // ── Fold stream.url.rotated from the live event log (no round trip) ──────────\n const events = options.events;\n useEffect(() => {\n if (!events || events.length === 0) return;\n setCapabilities((prev) => {\n if (!prev || !prev.DesktopStream.url) return prev;\n let next = prev.DesktopStream;\n let changed = false;\n for (const rotation of rotationsFrom(events)) {\n // Only this viewer's rotations (others' are filtered by viewerId when set).\n if (rotation.viewerId && viewerIdRef.current && rotation.viewerId !== viewerIdRef.current) {\n continue;\n }\n const applied = applyUrlRotation(next, rotation, epochRef.current);\n if (applied) {\n next = { ...next, url: applied.url, token: applied.token, expiresAt: applied.expiresAt };\n epochRef.current = Math.max(epochRef.current, rotation.leaseEpoch);\n changed = true;\n }\n }\n return changed ? { ...prev, DesktopStream: next, leaseEpoch: epochRef.current } : prev;\n });\n }, [events]);\n\n const identityMatches = enabled && stateIdentity === identityKey;\n return {\n capabilities: identityMatches ? capabilities : null,\n state: identityMatches ? state : \"idle\",\n error: identityMatches ? error : null,\n acknowledgmentRequired: identityMatches ? acknowledgmentRequired : null,\n viewerCapReached: identityMatches && viewerCapReached,\n viewerId: identityMatches ? viewerId : null,\n renegotiate,\n };\n}\n\nfunction isSandboxOwnershipDisabledError(error: unknown): boolean {\n return (\n error instanceof OpenGeniApiError &&\n error.status === 404 &&\n error.message.includes(\"sandbox ownership is not enabled\")\n );\n}\n","import type {\n SandboxCommandOutputDeltaPayload,\n SessionEvent,\n SessionEventPage,\n SessionEventType,\n TerminalPtyExitedPayload,\n TerminalPtyOutputDeltaPayload,\n} from \"@opengeni/sdk\";\nimport { OpenGeniApiError } from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { SessionClientLike } from \"../client\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { sandboxAcceptsLiveIo } from \"../lib/sandbox-liveness\";\nimport { useTurnlessOutputGap } from \"./turnless-output-gaps\";\n\n/**\n * Newest terminal output rows read when the terminal opens: one page, which\n * the server also bounds to 1 MB. xterm keeps 1,000 lines of scrollback, so\n * older pages would scroll straight out of it.\n */\nexport const SANDBOX_TERMINAL_HISTORY_ROWS = 1000;\n/** Output rows the terminal keeps (history and live) for a rewrite. */\nexport const SANDBOX_TERMINAL_MAX_ROWS = 4000;\n\nexport type TerminalChunk = {\n /** Stable key (the source event id) so the xterm writer tracks a written-cursor. */\n id: string;\n /** Raw output bytes (utf-8 lossy) — written verbatim into xterm. */\n text: string;\n /** stdout vs stderr (drives optional tinting). */\n stream: \"stdout\" | \"stderr\";\n /** Global ordering: the source event sequence. */\n seq: number;\n};\n\nexport type UseSandboxTerminalOptions = ClientOverride & {\n /** The live session event log (usually `useSessionEvents().events`). */\n events: SessionEvent[];\n /** Restrict to one PTY (by ptyId). Omit to interleave the agent firehose +\n * every PTY. */\n ptyId?: string | undefined;\n /** Include the agent's command-output firehose (sandbox.command.output.delta).\n * Default true — the read-only \"terminal-as-events\" the data path settled on. */\n includeAgentFirehose?: boolean | undefined;\n /**\n * OPEN an interactive PTY against the box so the user can type, not just watch.\n * When true (and the session is live) the hook calls `terminalPtyOpen` once,\n * tracks the returned ptyId, exposes `write` immediately (bound to that ptyId),\n * and closes the PTY on unmount. The PTY's banner + every output delta ride the\n * SSE spine (`terminal.pty.*`) back into `events`, so xterm fills in. Default\n * false — a caller that only wants the read-only firehose stays projection-only.\n */\n interactive?: boolean | undefined;\n /** Lease liveness (\"cold\" | \"warm\" | \"draining\"). The interactive PTY is only\n * opened once the box is warm — opening on a cold box (ptyCapable is advertised\n * cold too) races the box and leaves a dead read-only terminal. */\n liveness?: string | undefined;\n /**\n * Read this session's terminal history when true: the newest\n * {@link SANDBOX_TERMINAL_HISTORY_ROWS} PTY output rows (and agent command\n * output rows with `includeAgentFirehose`). Conversation reads carry none of\n * these rows, so this read restores the scrollback after a reload. Default\n * true; the dock enables it when its Terminal opens.\n */\n history?: boolean | undefined;\n};\n\nexport type UseSandboxTerminalResult = {\n /** Ordered, deduped output chunks to write() into xterm.js. */\n chunks: TerminalChunk[];\n /** Whether a PTY is currently open (drives the prompt/cursor affordance). */\n running: boolean;\n /**\n * Interactive write fn when a PTY is open and the backend supports stdin\n * (`terminal.transport === \"pty-ws\"` / `PtyOpenResponse.supportsInput`). Null\n * in the read-only event-projection case (v1 default).\n */\n write: ((data: string) => void) | null;\n /** The active PTY id, if one is open. */\n activePtyId: string | null;\n /** Close the active PTY (no-op when none is open). */\n close: () => void;\n /** A PTY-open failure (interactive mode), if any. */\n error: Error | null;\n};\n\n/**\n * Project the Channel-A event log into an xterm-writable byte stream. The\n * terminal is \"terminal-as-events\": there is NO new socket in v1 — the agent's\n * command output (`sandbox.command.output.delta`) and any interactive PTY\n * (`terminal.pty.output.delta`) ride the existing SSE spine. When a PTY is open\n * and the backend accepts stdin, `write` pipes keystrokes via the SDK\n * `terminalPtyWrite` (the synchronous Channel-A control path).\n */\nexport function useSandboxTerminal(\n sessionId: string | null | undefined,\n options: UseSandboxTerminalOptions,\n): UseSandboxTerminalResult {\n const { client, workspaceId } = useOpenGeni(options);\n const includeAgentFirehose = options.includeAgentFirehose ?? true;\n const interactive = options.interactive ?? false;\n // When the caller controls a fixed ptyId we project that one; otherwise (the\n // interactive default) the hook opens its OWN PTY and tracks it here so `write`\n // is live before the `terminal.pty.started` event round-trips through SSE.\n const ptyFilter = options.ptyId;\n const liveness = options.liveness;\n const identityKey = `${workspaceId}\\u0000${sessionId ?? \"\"}\\u0000${interactive}\\u0000${ptyFilter ?? \"\"}`;\n const [openedPtyId, setOpenedPtyId] = useState<string | null>(null);\n const [openError, setOpenError] = useState<Error | null>(null);\n const [stateIdentity, setStateIdentity] = useState(identityKey);\n // Bumped to force a fresh PTY open after a write reveals the old PTY was lost\n // (a 409 \"pty session lost\" — the box rolled over since the open). This makes\n // the interactive terminal self-heal instead of dead-ending on a stale session.\n const [reopenNonce, setReopenNonce] = useState(0);\n const currentIdentityRef = useRef(identityKey);\n currentIdentityRef.current = identityKey;\n\n // Async PTY state belongs to one workspace/session/mode identity. Hide it\n // synchronously on the switching render, then clear it durably in the effect.\n useEffect(() => {\n setStateIdentity(identityKey);\n setOpenedPtyId(null);\n setOpenError(null);\n }, [identityKey]);\n\n // Open ONE interactive PTY against the box, close it on unmount/identity\n // change. The open's banner + subsequent output deltas ride A1, so xterm fills\n // from `events` — we don't thread the open's body output here (the SSE\n // projection is the single source of truth for what's written). The open is\n // gated on a WARM box: opening on a cold/warming lease races the box (the PTY\n // exec-session is created on a box that the next op may not resume), which is\n // exactly the \"session not found\" terminal failure; we wait for warm.\n const openInFlight = useRef(false);\n const boxWarm = liveness === undefined || sandboxAcceptsLiveIo(liveness);\n useEffect(() => {\n if (!interactive || !sessionId || ptyFilter || !boxWarm) {\n setOpenError(null);\n return;\n }\n let cancelled = false;\n setOpenError(null);\n openInFlight.current = true;\n let openedId: string | null = null;\n void client\n .terminalPtyOpen(workspaceId, sessionId, {})\n .then((res) => {\n if (cancelled) {\n // Raced past unmount — close the orphan we just opened.\n void client\n .terminalPtyClose(workspaceId, sessionId, { ptyId: res.ptyId })\n .catch(() => {});\n return;\n }\n openedId = res.ptyId;\n setOpenedPtyId(res.ptyId);\n })\n .catch((cause) => {\n if (!cancelled) setOpenError(cause instanceof Error ? cause : new Error(String(cause)));\n })\n .finally(() => {\n openInFlight.current = false;\n });\n return () => {\n cancelled = true;\n setOpenedPtyId(null);\n const id = openedId;\n if (id) void client.terminalPtyClose(workspaceId, sessionId, { ptyId: id }).catch(() => {});\n };\n }, [interactive, client, workspaceId, sessionId, ptyFilter, boxWarm, reopenNonce]);\n\n // Terminal history: conversation reads carry no PTY output and only the\n // turns a reader opened carry command output, so the terminal reads its own\n // newest page once it is enabled (the dock enables it when its Terminal\n // opens). Live rows keep arriving through `events`; when the live stream may\n // have skipped some (it rejoined at the head, or a burst overflowed its\n // tail), the session's gap generation moves and the newest page is read\n // again. A failed read retries with backoff while the terminal is enabled.\n const outputTypes = useMemo<SessionEventType[]>(\n () =>\n includeAgentFirehose && !ptyFilter\n ? [\"terminal.pty.output.delta\", \"sandbox.command.output.delta\"]\n : [\"terminal.pty.output.delta\"],\n [includeAgentFirehose, ptyFilter],\n );\n const historyKey = `${workspaceId}\\u0000${sessionId ?? \"\"}\\u0000${outputTypes.join(\",\")}`;\n const historyEnabled = (options.history ?? true) && Boolean(sessionId);\n const gapGeneration = useTurnlessOutputGap(workspaceId, sessionId);\n const [history, setHistory] = useState<TerminalHistory | null>(null);\n const [historyTick, setHistoryTick] = useState(0);\n const readRef = useRef<HistoryReadState>(historyReadState(historyKey));\n const mountedRef = useRef(false);\n useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n const state = readRef.current;\n if (state.timer) clearTimeout(state.timer);\n state.timer = null;\n };\n }, []);\n useEffect(() => {\n let state = readRef.current;\n // Another session (or set of types) forgets this one's page, so coming\n // back reads what was written meanwhile.\n if (state.key !== historyKey) {\n if (state.timer) clearTimeout(state.timer);\n state = historyReadState(historyKey);\n readRef.current = state;\n setHistory(null);\n }\n if (!historyEnabled || !sessionId || state.inFlight || state.timer) return;\n if (!state.failed && state.generation === gapGeneration) return;\n const now = Date.now();\n const wait = state.failed\n ? terminalHistoryRetryDelay(state.failures) - (now - state.startedAt)\n : state.generation === null\n ? 0\n : SANDBOX_TERMINAL_REREAD_MIN_MS - (now - state.startedAt);\n if (wait > 0) {\n state.timer = setTimeout(() => {\n state.timer = null;\n if (mountedRef.current) setHistoryTick((tick) => tick + 1);\n }, wait);\n return;\n }\n const generation = gapGeneration;\n state.inFlight = true;\n state.startedAt = now;\n const current = () => mountedRef.current && readRef.current === state;\n void readTerminalHistory(client, workspaceId, sessionId, outputTypes).then(\n (page) => {\n state.inFlight = false;\n if (!current()) return;\n state.failed = false;\n state.failures = 0;\n state.generation = generation;\n setHistory({ key: state.key, events: page.events, complete: page.complete });\n // A gap marked during the read is read again.\n setHistoryTick((tick) => tick + 1);\n },\n (cause: unknown) => {\n state.inFlight = false;\n if (!current()) return;\n // A refusal (another 4xx than a timeout or rate limit) will not\n // change by retrying: wait for the next gap or session instead.\n if (\n cause instanceof OpenGeniApiError &&\n cause.status >= 400 &&\n cause.status < 500 &&\n cause.status !== 408 &&\n cause.status !== 429\n ) {\n state.failed = false;\n state.failures = 0;\n state.generation = generation;\n return;\n }\n state.failed = true;\n state.failures += 1;\n setHistoryTick((tick) => tick + 1);\n },\n );\n }, [\n historyEnabled,\n historyKey,\n gapGeneration,\n historyTick,\n outputTypes,\n client,\n workspaceId,\n sessionId,\n ]);\n\n // Live output rows seen in `events`, kept after they leave it (a host's\n // event window keeps only a short tail of them).\n const liveRef = useRef<LiveTerminalRows>({ key: historyKey, rows: new Map(), below: 0 });\n\n const { chunks, openPty, supportsInput } = useMemo(() => {\n // Track PTY lifecycle so `running`/`write` reflect the latest state.\n const open = new Map<string, { supportsInput: boolean }>();\n let lastOpened: string | null = null;\n let lastSupportsInput = false;\n if (liveRef.current.key !== historyKey) {\n liveRef.current = { key: historyKey, rows: new Map(), below: 0 };\n }\n const liveRows = liveRef.current;\n const live = liveRows.rows;\n const types = new Set<string>(outputTypes);\n\n for (const event of options.events) {\n // The hook is session-scoped even if a host accidentally retains the old\n // event array for one render during navigation.\n if (event.workspaceId !== workspaceId || event.sessionId !== sessionId) continue;\n if (event.type === \"terminal.pty.started\") {\n const payload = event.payload as { ptyId?: string } | null;\n if (payload?.ptyId) {\n open.set(payload.ptyId, { supportsInput: true });\n lastOpened = payload.ptyId;\n }\n continue;\n }\n if (event.type === \"terminal.pty.exited\") {\n const payload = event.payload as TerminalPtyExitedPayload | null;\n if (payload?.ptyId) {\n open.delete(payload.ptyId);\n if (lastOpened === payload.ptyId) lastOpened = null;\n }\n continue;\n }\n // Rows below the trimmed floor stay out (an opened turn's older steps).\n if (types.has(event.type) && event.sequence >= liveRows.below && !live.has(event.id)) {\n live.set(event.id, event);\n }\n }\n trimLiveRows(liveRows);\n\n const loaded = history?.key === historyKey ? history : null;\n // Rows older than an incomplete history page are outside what the\n // terminal shows (for example the steps of an old turn a reader opened).\n const floor = loaded && !loaded.complete ? (loaded.events[0]?.sequence ?? 0) : 0;\n const seen = new Set<string>();\n const out: TerminalChunk[] = [];\n const add = (event: SessionEvent) => {\n if (seen.has(event.id) || event.sequence < floor) return;\n seen.add(event.id);\n const chunk = terminalChunk(event, ptyFilter);\n if (chunk) out.push(chunk);\n };\n loaded?.events.forEach(add);\n live.forEach(add);\n\n // Stable order: by sequence (the SSE spine guarantees per-session ordering).\n out.sort((a, b) => a.seq - b.seq);\n const activePty = ptyFilter && open.has(ptyFilter) ? ptyFilter : lastOpened;\n lastSupportsInput = activePty ? (open.get(activePty)?.supportsInput ?? false) : false;\n return {\n chunks: out.length > SANDBOX_TERMINAL_MAX_ROWS ? out.slice(-SANDBOX_TERMINAL_MAX_ROWS) : out,\n openPty: activePty,\n supportsInput: lastSupportsInput,\n };\n }, [options.events, history, historyKey, outputTypes, ptyFilter, workspaceId, sessionId]);\n\n // The PTY this hook actively drives: the one it opened (interactive) wins so\n // `write` is live the instant the open resolves — even before the\n // `terminal.pty.started` event arrives through SSE. Fall back to whatever the\n // event projection found (a PTY opened elsewhere, or a caller-pinned ptyId).\n const identityMatches = stateIdentity === identityKey;\n const activePtyId = identityMatches ? (openedPtyId ?? openPty) : null;\n // An interactively-opened PTY accepts stdin by construction (we only open it on\n // a pty-capable backend); a projected PTY uses its advertised supportsInput.\n const canWrite = openedPtyId !== null || supportsInput;\n\n const write = useMemo(() => {\n if (!activePtyId || !canWrite || !sessionId) return null;\n const writeIdentity = identityKey;\n return (data: string) => {\n void client\n .terminalPtyWrite(workspaceId, sessionId, { ptyId: activePtyId, data })\n .catch((cause) => {\n // The PTY exec-session was lost on the live box (409/404 — the box rolled\n // over since the open). Self-heal: drop the stale id and re-open a fresh\n // PTY against the current box rather than silently swallowing keystrokes.\n if (\n cause instanceof OpenGeniApiError &&\n (cause.status === 409 || cause.status === 404) &&\n activePtyId === openedPtyId &&\n currentIdentityRef.current === writeIdentity\n ) {\n setOpenedPtyId(null);\n setReopenNonce((n) => n + 1);\n }\n });\n };\n }, [client, workspaceId, sessionId, activePtyId, canWrite, openedPtyId, identityKey]);\n\n const close = useCallback(() => {\n if (!activePtyId || !sessionId) return;\n void client.terminalPtyClose(workspaceId, sessionId, { ptyId: activePtyId }).catch(() => {});\n }, [client, workspaceId, sessionId, activePtyId]);\n\n return {\n chunks,\n running: activePtyId !== null,\n write,\n activePtyId,\n close,\n error: identityMatches ? openError : null,\n };\n}\n\n/** The terminal's history page for one session and set of output types. */\ntype TerminalHistory = {\n key: string;\n /** Ascending. */\n events: SessionEvent[];\n /** No older output rows exist. */\n complete: boolean;\n};\n\ntype LiveTerminalRows = {\n key: string;\n rows: Map<string, SessionEvent>;\n /** Rows below this sequence were trimmed and are not taken again. */\n below: number;\n};\n\n/**\n * Keep the newest {@link SANDBOX_TERMINAL_MAX_ROWS} live rows, trimming in\n * batches so a long-running terminal sorts rarely.\n */\nfunction trimLiveRows(live: LiveTerminalRows): void {\n const { rows } = live;\n if (rows.size <= SANDBOX_TERMINAL_MAX_ROWS + SANDBOX_TERMINAL_MAX_ROWS / 4) return;\n const sorted = [...rows.values()].sort((left, right) => left.sequence - right.sequence);\n const drop = sorted.length - SANDBOX_TERMINAL_MAX_ROWS;\n for (const event of sorted.slice(0, drop)) rows.delete(event.id);\n live.below = Math.max(live.below, sorted[drop]!.sequence);\n}\n\n/** Where the terminal's history read stands for one session and set of types. */\ntype HistoryReadState = {\n key: string;\n /** The gap generation the last successful read started at. */\n generation: number | null;\n inFlight: boolean;\n failed: boolean;\n failures: number;\n /** When the latest read started (ms). */\n startedAt: number;\n timer: ReturnType<typeof setTimeout> | null;\n};\n\nfunction historyReadState(key: string): HistoryReadState {\n return {\n key,\n generation: null,\n inFlight: false,\n failed: false,\n failures: 0,\n startedAt: 0,\n timer: null,\n };\n}\n\n/** Re-reads after live gaps start at most this often. */\nconst SANDBOX_TERMINAL_REREAD_MIN_MS = 1000;\n\n/** Backoff after failed history reads: 1 s, doubling, at most 30 s. */\nfunction terminalHistoryRetryDelay(failures: number): number {\n return Math.min(30_000, 1000 * 2 ** Math.max(0, failures - 1));\n}\n\nfunction terminalChunk(event: SessionEvent, ptyFilter: string | undefined): TerminalChunk | null {\n if (event.type === \"terminal.pty.output.delta\") {\n const payload = event.payload as TerminalPtyOutputDeltaPayload | null;\n if (!payload || typeof payload.chunk !== \"string\") return null;\n if (ptyFilter && payload.ptyId !== ptyFilter) return null;\n return {\n id: event.id,\n text: payload.chunk,\n stream: payload.stream === \"stderr\" ? \"stderr\" : \"stdout\",\n seq: event.sequence,\n };\n }\n if (event.type === \"sandbox.command.output.delta\" && !ptyFilter) {\n const payload = event.payload as SandboxCommandOutputDeltaPayload | null;\n if (!payload?.chunk) return null;\n return {\n id: event.id,\n text: payload.chunk,\n stream: payload.stream === \"stderr\" ? \"stderr\" : \"stdout\",\n seq: event.sequence,\n };\n }\n return null;\n}\n\ntype EventPageClient = {\n listEventPage?: (\n workspaceId: string,\n sessionId: string,\n options: Parameters<SessionClientLike[\"listEvents\"]>[2],\n ) => Promise<SessionEventPage>;\n};\n\n/**\n * The newest page of terminal output rows, ascending. Uses the SDK's page read\n * when the client has it (it says whether older rows remain).\n */\nasync function readTerminalHistory(\n client: SessionClientLike,\n workspaceId: string,\n sessionId: string,\n includeTypes: SessionEventType[],\n): Promise<{ events: SessionEvent[]; complete: boolean }> {\n const options = {\n includeTypes,\n direction: \"before\" as const,\n // Explicit: a cursorless read otherwise defaults to the monitoring tail,\n // which drops raw output deltas.\n mode: \"forensic\" as const,\n payloadMode: \"full\" as const,\n limit: SANDBOX_TERMINAL_HISTORY_ROWS,\n };\n const pageClient = client as SessionClientLike & EventPageClient;\n const page =\n typeof pageClient.listEventPage === \"function\"\n ? await pageClient.listEventPage(workspaceId, sessionId, options)\n : null;\n const events = page ? page.events : await client.listEvents(workspaceId, sessionId, options);\n const sorted = [...events].sort((left, right) => left.sequence - right.sequence);\n return {\n events: sorted,\n // Without a continuation fact, only an empty read is known complete: the\n // server's byte bound can cut a page short of the row limit.\n complete: page ? !page.hasMore : sorted.length === 0,\n };\n}\n","import type {\n GitFileDiff,\n SessionCapabilities,\n SessionEvent,\n WorkspaceCaptureManifest,\n WorkspaceCaptureRepo,\n} from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { type ClientOverride, useOpenGeni } from \"../provider\";\nimport { sandboxAcceptsLiveIo } from \"../lib/sandbox-liveness\";\n\nexport type UseSandboxGitOptions = ClientOverride & {\n /** Live event log (usually `useSessionEvents().events`) — drives auto-refresh\n * on `git.changed`. */\n events?: SessionEvent[] | undefined;\n /** Repo root within the workspace (multi-repo). Default: workspace root. */\n repoPath?: string | undefined;\n /** All repository roots in the workspace. When supplied, status and diff are\n * aggregated into one workspace-wide result and paths are workspace-relative. */\n repoPaths?: readonly string[] | undefined;\n /** Diff the staged index vs HEAD (`--cached`) instead of the working tree. */\n staged?: boolean | undefined;\n /** Review scope. `branch` compares the current branch with the remote default\n * branch, `working` shows uncommitted edits, and `staged` shows the index.\n * `staged` above remains as a compatibility alias. */\n comparison?: SandboxGitComparison | undefined;\n /** Hold off the initial fetch. Default true. */\n enabled?: boolean | undefined;\n /** Pause live reads/invalidation while preserving the last rendered result. */\n active?: boolean | undefined;\n /** Lease liveness. `null` means capability negotiation is still pending and\n * blocks live I/O. When not warm, the diff is served from the capture instead\n * of a live `gitDiff` RPC. Omission preserves legacy direct-hook behavior. */\n liveness?: SessionCapabilities[\"liveness\"] | null | undefined;\n /** The latest turn-end capture (from `useWorkspaceCapture`). Seeds the diff\n * immediately; a warm box reconciles live and leaves this durable review\n * surface in place if the live request is temporarily unavailable. */\n capture?: WorkspaceCaptureManifest | null | undefined;\n};\n\nexport type SandboxGitComparison = \"branch\" | \"working\" | \"staged\";\n\n/** A Git diff qualified into workspace scope. `repoRoot` is present for the\n * workspace-wide path and lets review UI group real repositories without\n * guessing from the first path segment. */\nexport type SandboxGitFileDiff = GitFileDiff & {\n repoRoot?: string | undefined;\n};\n\nexport type UseSandboxGitResult = {\n /** Working-tree (or staged) diff vs HEAD — the structured hunks the Pierre\n * diff view renders. */\n diff: SandboxGitFileDiff[];\n branch: string | null;\n /** Whether a repo is actually mounted (drives \"no repository\" vs \"no changes\"). */\n isRepo: boolean;\n ahead: number;\n behind: number;\n /** Number and workspace-relative roots of repositories represented here. */\n repoCount: number;\n repoRoots: string[];\n refresh: () => Promise<void>;\n /** Which source the diff is served from: the live box or the turn-end capture. */\n source: \"live\" | \"capture\" | null;\n /** When the served capture was taken (ISO), when `source === \"capture\"`. */\n capturedAt: string | null;\n loading: boolean;\n error: Error | null;\n};\n\n/** Normalize a repo root for matching (\"\" and \".\" both mean the workspace root). */\nfunction normalizeRoot(root: string): string {\n const normalized = root\n .replaceAll(\"\\\\\", \"/\")\n .replace(/^\\.\\/+/, \"\")\n .replace(/\\/+$/, \"\");\n return normalized === \".\" ? \"\" : normalized;\n}\n\nfunction qualifyPath(repoRoot: string, path: string): string {\n const root = normalizeRoot(repoRoot);\n return root ? `${root}/${path}` : path;\n}\n\nfunction qualifyDiff(repoRoot: string, file: GitFileDiff): SandboxGitFileDiff {\n const root = normalizeRoot(repoRoot);\n return {\n ...file,\n path: qualifyPath(root, file.path),\n oldPath: file.oldPath === null ? null : qualifyPath(root, file.oldPath),\n repoRoot: root,\n };\n}\n\nfunction uniqueRoots(roots: readonly string[]): string[] {\n return [...new Set(roots.map(normalizeRoot))].sort((a, b) => a.localeCompare(b));\n}\n\n// GitReadBatchRequest is contract-bounded to 32 items. Keep workspace-wide\n// reads bounded without changing the wire limit; sequential chunks preserve\n// deterministic root/result mapping and cap Channel-A lease concurrency at one.\nconst GIT_READ_BATCH_REQUEST_LIMIT = 32;\n\n/** Find the capture repo matching `repoPath` (default workspace root). */\nfunction repoForPath(\n manifest: WorkspaceCaptureManifest,\n repoPath: string,\n): WorkspaceCaptureRepo | null {\n const want = normalizeRoot(repoPath);\n const exact = manifest.repos.find((r) => normalizeRoot(r.root) === want);\n if (exact) return exact;\n // Root-scoped hook against a single-repo capture whose root isn't literally \"\":\n // fall back to the sole repo so the common single-repo case just works.\n if (want === \"\" && manifest.repos.length === 1) return manifest.repos[0] ?? null;\n return null;\n}\n\n/** Full diff equality for identity preservation. Hunk count/count summaries are\n * not sufficient: an edit can replace text without changing either shape. */\nfunction sameFileDiff(a: SandboxGitFileDiff, b: SandboxGitFileDiff): boolean {\n if (\n a.path !== b.path ||\n a.oldPath !== b.oldPath ||\n a.repoRoot !== b.repoRoot ||\n a.status !== b.status ||\n a.isBinary !== b.isBinary ||\n a.isImage !== b.isImage ||\n a.additions !== b.additions ||\n a.deletions !== b.deletions ||\n a.truncated !== b.truncated ||\n a.hunks.length !== b.hunks.length\n )\n return false;\n\n return a.hunks.every((hunk, hunkIndex) => {\n const other = b.hunks[hunkIndex];\n if (\n !other ||\n hunk.oldStart !== other.oldStart ||\n hunk.oldLines !== other.oldLines ||\n hunk.newStart !== other.newStart ||\n hunk.newLines !== other.newLines ||\n hunk.header !== other.header ||\n hunk.lines.length !== other.lines.length\n )\n return false;\n return hunk.lines.every((line, lineIndex) => {\n const otherLine = other.lines[lineIndex];\n return (\n otherLine !== undefined &&\n line.type === otherLine.type &&\n line.oldNo === otherLine.oldNo &&\n line.newNo === otherLine.newNo &&\n line.text === otherLine.text\n );\n });\n });\n}\n\n/** Merge a freshly-served diff over the current one, preserving the identity of\n * genuinely unchanged per-file entries so a cold→warm reconcile does NOT\n * remount unchanged file sections — no-flicker (§12-D1). */\nfunction mergeDiffs(\n current: SandboxGitFileDiff[],\n next: SandboxGitFileDiff[],\n): SandboxGitFileDiff[] {\n if (current.length === 0) return next;\n const byPath = new Map(current.map((d) => [d.path, d] as const));\n let changed = current.length !== next.length;\n const merged = next.map((file, index) => {\n const existing = byPath.get(file.path);\n if (existing && sameFileDiff(existing, file)) {\n if (current[index] !== existing) changed = true;\n return existing;\n }\n changed = true;\n return file;\n });\n return changed ? merged : current;\n}\n\n/**\n * Project the Git service into the Pierre diff data contract: structured\n * `GitFileDiff[]` (per-file hunks with per-line old/new numbers, rename\n * detection, binary flag, add/del counts) plus branch + ahead/behind. When the\n * box is warm the `git diff` runs in-box (API-direct); when it is cold/offline the\n * diff is served from the turn-end capture instead. Refreshes on\n * `git.changed`; reconciles live in place on the cold→warm transition.\n */\nexport function useSandboxGit(\n sessionId: string | null | undefined,\n options: UseSandboxGitOptions = {},\n): UseSandboxGitResult {\n const { client, workspaceId } = useOpenGeni(options);\n const enabled = (options.enabled ?? true) && Boolean(sessionId);\n const active = options.active ?? true;\n const repoPath = options.repoPath ?? \"\";\n const workspaceWide = options.repoPaths !== undefined;\n // Serialize the caller's array so inline values do not retrigger effects. An\n // explicitly empty advertised list falls back to the legacy repoPath probe.\n const repoPathsKey = uniqueRoots(\n options.repoPaths && options.repoPaths.length > 0 ? options.repoPaths : [repoPath],\n ).join(\"\\u0000\");\n const repoPaths = useMemo(() => repoPathsKey.split(\"\\u0000\"), [repoPathsKey]);\n const comparison: SandboxGitComparison =\n options.comparison ?? (options.staged ? \"staged\" : \"working\");\n const hasAdvertisedRepoPaths = (options.repoPaths?.length ?? 0) > 0;\n // New captures retain both working-tree and branch comparisons. Staged state\n // remains live-only; legacy captures simply lack branchDiff and fall back via\n // the workspace controller without inventing an empty branch comparison.\n const capture = comparison === \"staged\" ? null : (options.capture ?? null);\n const isLive = sandboxAcceptsLiveIo(options.liveness);\n // `liveness` is optional for compatibility with direct hook consumers. Explicit\n // `null` (negotiating) and lifecycle values require authoritative warm.\n const acceptsEventReads = options.liveness === undefined || isLive;\n const acceptsEventReadsRef = useRef(acceptsEventReads);\n acceptsEventReadsRef.current = acceptsEventReads;\n const hasLiveIoFence = options.liveness !== undefined;\n const identityKey = `${workspaceId}\\u0000${sessionId ?? \"\"}\\u0000${repoPathsKey}\\u0000${workspaceWide}\\u0000${comparison}`;\n\n const [diff, setDiff] = useState<SandboxGitFileDiff[]>([]);\n const [branch, setBranch] = useState<string | null>(null);\n const [isRepo, setIsRepo] = useState(false);\n const [ahead, setAhead] = useState(0);\n const [behind, setBehind] = useState(0);\n const [repoRoots, setRepoRoots] = useState<string[]>([]);\n const [source, setSource] = useState<\"live\" | \"capture\" | null>(null);\n const sourceRef = useRef<\"live\" | \"capture\" | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [stateIdentity, setStateIdentity] = useState(identityKey);\n // Live requests and event cursors are identity-scoped. The refs deliberately\n // survive renders, so they must be fenced/reset when that identity changes.\n const refreshGenerationRef = useRef(0);\n const refreshAbortRef = useRef<AbortController | null>(null);\n const refreshInFlightRef = useRef<Promise<void> | null>(null);\n const refreshPendingRef = useRef(false);\n const refreshWorkerEpochRef = useRef(0);\n const lastChangeRef = useRef(0);\n const eventRefreshTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const performRefresh = useCallback(async () => {\n if (!sessionId) return;\n const refreshAbort = new AbortController();\n refreshAbortRef.current = refreshAbort;\n const generation = (refreshGenerationRef.current += 1);\n setLoading(true);\n setError(null);\n try {\n const diffRequest = (root: string) =>\n client.gitDiff(\n workspaceId,\n sessionId,\n {\n path: root,\n ...(comparison === \"branch\"\n ? { fromRef: \"origin/HEAD\", includeUntracked: true }\n : comparison === \"working\"\n ? { fromRef: \"HEAD\", includeUntracked: true }\n : { staged: true, includeUntracked: false }),\n },\n { signal: refreshAbort.signal },\n );\n\n // Capability-advertised roots are known repositories. Fetch status metadata\n // and diff hunks together: both are independent Channel-A reads and each can\n // take several seconds on a remote sandbox. The legacy root probe remains\n // serial so a non-repository workspace never receives a failing git diff.\n const prefetched = hasAdvertisedRepoPaths\n ? await (async () => {\n const prefetchedRepos: Array<{\n root: string;\n status: Awaited<ReturnType<typeof client.gitStatus>>;\n result: Awaited<ReturnType<typeof client.gitDiff>>;\n }> = [];\n for (\n let offset = 0;\n offset < repoPaths.length;\n offset += GIT_READ_BATCH_REQUEST_LIMIT\n ) {\n const roots = repoPaths.slice(offset, offset + GIT_READ_BATCH_REQUEST_LIMIT);\n const batch = await client.gitReadBatch(\n workspaceId,\n sessionId,\n {\n requests: roots.map((root) => ({\n status: { path: root },\n diff: {\n path: root,\n ...(comparison === \"branch\"\n ? { fromRef: \"origin/HEAD\", includeUntracked: true }\n : comparison === \"working\"\n ? { fromRef: \"HEAD\", includeUntracked: true }\n : { staged: true, includeUntracked: false }),\n },\n })),\n },\n { signal: refreshAbort.signal },\n );\n if (batch.results.length !== roots.length) {\n throw new Error(\n `Workspace Git batch returned ${batch.results.length} results for ${roots.length} repositories.`,\n );\n }\n batch.results.forEach((item, index) => {\n prefetchedRepos.push({\n root: roots[index]!,\n status: item.status,\n result: item.diff ?? {\n files: [],\n revision: item.status.revision,\n },\n });\n });\n }\n return prefetchedRepos;\n })()\n : null;\n const statuses =\n prefetched ??\n (await Promise.all(\n repoPaths.map(async (root) => ({\n root,\n status: await client.gitStatus(\n workspaceId,\n sessionId,\n { path: root },\n { signal: refreshAbort.signal },\n ),\n })),\n ));\n if (refreshGenerationRef.current !== generation) return;\n const repositories = statuses.filter(({ status }) => status.isRepo);\n const roots = repositories.map(({ root }) => root);\n setRepoRoots(roots);\n setIsRepo(repositories.length > 0);\n setBranch(repositories.length === 1 ? (repositories[0]?.status.head ?? null) : null);\n setAhead(repositories.reduce((sum, { status }) => sum + status.ahead, 0));\n setBehind(repositories.reduce((sum, { status }) => sum + status.behind, 0));\n if (repositories.length === 0) {\n setDiff([]);\n sourceRef.current = \"live\";\n setSource(\"live\");\n return;\n }\n const prefetchedByRoot = new Map(prefetched?.map(({ root, result }) => [root, result]));\n const results = await Promise.all(\n repositories.map(async ({ root }) => ({\n root,\n result: prefetchedByRoot.get(root) ?? (await diffRequest(root)),\n })),\n );\n if (refreshGenerationRef.current !== generation) return;\n // Merge in place so the cold→warm swap keeps unchanged file sections mounted.\n setDiff((prev) =>\n mergeDiffs(\n prev,\n results.flatMap(({ root, result }) =>\n workspaceWide ? result.files.map((file) => qualifyDiff(root, file)) : result.files,\n ),\n ),\n );\n sourceRef.current = \"live\";\n setSource(\"live\");\n } catch (cause) {\n if (refreshGenerationRef.current !== generation) return;\n setError(cause instanceof Error ? cause : new Error(String(cause)));\n } finally {\n if (refreshGenerationRef.current === generation) setLoading(false);\n if (refreshAbortRef.current === refreshAbort) refreshAbortRef.current = null;\n }\n }, [\n client,\n workspaceId,\n sessionId,\n repoPaths,\n hasAdvertisedRepoPaths,\n workspaceWide,\n comparison,\n ]);\n\n // Provider reads cannot be undispatched after they reach a remote sandbox.\n // Keep exactly one refresh in flight and collapse any burst of invalidations\n // into one trailing read. Aborting and replacing every tool-output refresh\n // used to leave several Modal reads contending for the same provider lock.\n const performRefreshRef = useRef(performRefresh);\n performRefreshRef.current = performRefresh;\n const refresh = useCallback(async () => {\n refreshPendingRef.current = true;\n const existing = refreshInFlightRef.current;\n if (existing) return await existing;\n\n const workerEpoch = refreshWorkerEpochRef.current;\n const run = (async () => {\n while (refreshPendingRef.current && refreshWorkerEpochRef.current === workerEpoch) {\n refreshPendingRef.current = false;\n await performRefreshRef.current();\n }\n })();\n refreshInFlightRef.current = run;\n try {\n await run;\n } finally {\n if (refreshInFlightRef.current === run) refreshInFlightRef.current = null;\n }\n }, []);\n\n // Serve the requested review scope from a capture when that scope exists.\n const seedFromCapture = useCallback(\n (manifest: WorkspaceCaptureManifest) => {\n const repositories = workspaceWide\n ? manifest.repos\n : ([repoForPath(manifest, repoPath)].filter(Boolean) as WorkspaceCaptureRepo[]);\n if (comparison === \"branch\" && repositories.some((repo) => repo.branchDiff === undefined)) {\n return;\n }\n if (repositories.length === 0) {\n setIsRepo(false);\n setBranch(null);\n setAhead(0);\n setBehind(0);\n setRepoRoots([]);\n setDiff((prev) => (prev.length === 0 ? prev : []));\n sourceRef.current = \"capture\";\n setSource(\"capture\");\n return;\n }\n setIsRepo(true);\n setBranch(repositories.length === 1 ? (repositories[0]?.head ?? null) : null);\n setAhead(repositories.reduce((sum, repo) => sum + repo.ahead, 0));\n setBehind(repositories.reduce((sum, repo) => sum + repo.behind, 0));\n setRepoRoots(repositories.map((repo) => normalizeRoot(repo.root)));\n setDiff((prev) =>\n mergeDiffs(\n prev,\n repositories.flatMap((repo) => {\n const capturedDiff = comparison === \"branch\" ? (repo.branchDiff ?? []) : repo.diff;\n return workspaceWide\n ? capturedDiff.map((file) => qualifyDiff(repo.root, file))\n : capturedDiff;\n }),\n ),\n );\n sourceRef.current = \"capture\";\n setSource(\"capture\");\n setError(null);\n },\n [comparison, repoPath, workspaceWide],\n );\n\n // Source selection on mount / liveness / capture-revision change. Key on the\n // capture REVISION (a primitive), not the manifest object, so a fresh object per\n // render can't spin the effect; the latest manifest is read from a ref.\n const captureRef = useRef<WorkspaceCaptureManifest | null>(capture);\n captureRef.current = capture;\n const captureRevision = capture?.revision ?? null;\n const previousIdentityRef = useRef(identityKey);\n useEffect(() => {\n // A liveness/capture source change supersedes any older live request. Only a\n // true data-identity change clears rendered state and the event high-water mark.\n refreshAbortRef.current?.abort();\n refreshAbortRef.current = null;\n refreshPendingRef.current = false;\n refreshGenerationRef.current += 1;\n const identityChanged = previousIdentityRef.current !== identityKey;\n previousIdentityRef.current = identityKey;\n if (identityChanged) {\n // Different sessions target different provider identities. Fence the old\n // worker and let the new session load immediately instead of waiting for a\n // stuck request that has already been aborted.\n refreshWorkerEpochRef.current += 1;\n refreshInFlightRef.current = null;\n }\n if (identityChanged || !enabled) {\n lastChangeRef.current = 0;\n setDiff([]);\n setStateIdentity(identityKey);\n setIsRepo(false);\n setBranch(null);\n setAhead(0);\n setBehind(0);\n setRepoRoots([]);\n sourceRef.current = null;\n setSource(null);\n setLoading(false);\n setError(null);\n }\n if (!enabled) {\n return;\n }\n const currentCapture = captureRevision !== null ? captureRef.current : null;\n if (currentCapture && (identityChanged || !isLive || sourceRef.current !== \"live\")) {\n seedFromCapture(currentCapture);\n }\n if (!active) {\n if (!active) setLoading(false);\n return;\n }\n if (isLive || (!hasLiveIoFence && !currentCapture)) {\n void refresh();\n }\n return () => {\n refreshAbortRef.current?.abort();\n refreshAbortRef.current = null;\n refreshPendingRef.current = false;\n refreshGenerationRef.current += 1;\n };\n }, [\n enabled,\n active,\n isLive,\n hasLiveIoFence,\n captureRevision,\n identityKey,\n refresh,\n seedFromCapture,\n ]);\n\n // Structured Git changes are debounced into one live reconcile. Generic\n // command/tool output performs no provider reads: the canonical turn-end\n // capture advances `captureRevision`, which refreshes after the burst settles.\n const events = options.events;\n useEffect(() => {\n if (!enabled || !events) {\n if (eventRefreshTimerRef.current) {\n clearTimeout(eventRefreshTimerRef.current);\n eventRefreshTimerRef.current = null;\n }\n return;\n }\n // Historical events describe the capture we already loaded. Inactive tabs\n // and holderless draining/cold leases advance the cursor without issuing\n // provider I/O; becoming warm performs one authoritative reconcile above.\n if (!active || !acceptsEventReads) {\n for (const event of events) {\n if (event.sequence > lastChangeRef.current) lastChangeRef.current = event.sequence;\n }\n if (eventRefreshTimerRef.current) {\n clearTimeout(eventRefreshTimerRef.current);\n eventRefreshTimerRef.current = null;\n }\n return;\n }\n let latest = lastChangeRef.current;\n let changed = false;\n for (const event of events) {\n if (event.sequence <= latest) continue;\n if (event.type === \"git.changed\") {\n latest = event.sequence;\n changed = true;\n }\n }\n if (latest > lastChangeRef.current) {\n lastChangeRef.current = latest;\n if (!changed) return;\n if (eventRefreshTimerRef.current) clearTimeout(eventRefreshTimerRef.current);\n eventRefreshTimerRef.current = setTimeout(() => {\n eventRefreshTimerRef.current = null;\n if (acceptsEventReadsRef.current) void refresh();\n }, 150);\n }\n }, [enabled, active, acceptsEventReads, events, refresh]);\n\n useEffect(\n () => () => {\n if (eventRefreshTimerRef.current) clearTimeout(eventRefreshTimerRef.current);\n },\n [],\n );\n\n const identityMatches = enabled && stateIdentity === identityKey;\n const visibleRepoRoots = identityMatches ? repoRoots : [];\n return {\n diff: identityMatches ? diff : [],\n branch: identityMatches ? branch : null,\n isRepo: identityMatches && isRepo,\n ahead: identityMatches ? ahead : 0,\n behind: identityMatches ? behind : 0,\n repoCount: visibleRepoRoots.length,\n repoRoots: visibleRepoRoots,\n refresh,\n source: identityMatches ? source : null,\n capturedAt: identityMatches && source === \"capture\" ? (capture?.capturedAt ?? null) : null,\n loading: identityMatches && loading,\n error: identityMatches ? error : null,\n };\n}\n","import type {\n GetWorkspaceCaptureResponse,\n SessionEvent,\n WorkspaceCaptureDegradedReason,\n WorkspaceCaptureManifest,\n WorkspaceRevisionCapturedPayload,\n WorkspaceRevisionDegradedPayload,\n} from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { isRecord } from \"@opengeni/contracts/values\";\n\n/** The announce event M1 emits at turn end (metadata only, never content). */\nconst REVISION_CAPTURED = \"workspace.revision.captured\";\nconst REVISION_DEGRADED = \"workspace.revision.degraded\";\nconst MANIFEST_FETCH_TIMEOUT_MS = 15_000;\n\ntype AvailableCaptureResponse = Extract<GetWorkspaceCaptureResponse, { available: true }>;\n\nconst CAPTURE_STATS_NUMBER_FIELDS = [\n \"repoCount\",\n \"fileCount\",\n \"additions\",\n \"deletions\",\n \"totalBytes\",\n \"tooLargeCount\",\n \"binaryCount\",\n \"treeEntryCount\",\n \"durationMs\",\n] as const;\n\n/**\n * Signed manifests bypass the authenticated JSON client's wire decoder. Treat\n * the blob as untrusted until its outer schema and exact revision identity match\n * the metadata response that minted the URL. The API performs the full contract\n * parse; this client-side boundary prevents a corrupt/mis-keyed response from\n * being presented as a different authoritative capture.\n */\nfunction captureManifestForResponse(\n value: unknown,\n response: AvailableCaptureResponse,\n): WorkspaceCaptureManifest {\n if (\n !isRecord(value) ||\n value.version !== 1 ||\n !Number.isSafeInteger(value.revision) ||\n typeof value.capturedAt !== \"string\" ||\n !(value.turnId === null || typeof value.turnId === \"string\") ||\n !Number.isSafeInteger(value.leaseEpoch) ||\n !isRecord(value.treeIndex) ||\n typeof value.treeTruncated !== \"boolean\" ||\n !Array.isArray(value.repos) ||\n !Array.isArray(value.files) ||\n !isRecord(value.stats)\n ) {\n throw new Error(\"Workspace capture manifest failed validation.\");\n }\n\n if (\n value.revision !== response.revision ||\n value.capturedAt !== response.capturedAt ||\n value.turnId !== response.turnId ||\n value.leaseEpoch !== response.leaseEpoch\n ) {\n throw new Error(\"Workspace capture manifest identity did not match its response.\");\n }\n\n for (const field of CAPTURE_STATS_NUMBER_FIELDS) {\n if (!Number.isSafeInteger(value.stats[field]) || value.stats[field] !== response.stats[field]) {\n throw new Error(\"Workspace capture manifest statistics did not match its response.\");\n }\n }\n if (\n typeof value.stats.treeTruncated !== \"boolean\" ||\n value.stats.treeTruncated !== response.stats.treeTruncated ||\n (value.stats.fingerprint ?? null) !== (response.stats.fingerprint ?? null) ||\n value.repos.length !== response.stats.repoCount ||\n value.files.length !== response.stats.fileCount ||\n value.treeTruncated !== response.stats.treeTruncated\n ) {\n throw new Error(\"Workspace capture manifest statistics did not match its response.\");\n }\n\n return value as WorkspaceCaptureManifest;\n}\n\nexport type UseWorkspaceCaptureOptions = ClientOverride & {\n /** Live event log (usually `useSessionEvents().events`) — a\n * `workspace.revision.captured` for a NEWER revision refreshes the manifest. */\n events?: SessionEvent[] | undefined;\n /** Hold off the mount fetch (e.g. the workbench panel is collapsed). Default true. */\n enabled?: boolean | undefined;\n};\n\nexport type UseWorkspaceCaptureResult = {\n /** The resolved manifest (tree index + per-repo diffs + file refs), or null when\n * no capture exists (falls back to the live/wake path — status quo). */\n capture: WorkspaceCaptureManifest | null;\n /** The loaded capture's monotonic revision, or null when unavailable. */\n revision: number | null;\n /** When the loaded capture was taken (ISO), for the \"as of <time>\" source badge. */\n capturedAt: string | null;\n /** Whether a capture is available at all (the `{available:false}` discriminator). */\n available: boolean;\n /** Why the newest durable revision is unavailable. null means no capture has\n * been attempted yet; a value means capture explicitly failed closed and\n * consumers must use the live box rather than trust an incomplete snapshot. */\n degradedReason: WorkspaceCaptureDegradedReason | null;\n /** The changed-file count from the capture's stats, resolved on the FIRST GET\n * (from the response's top-level `stats`, before any manifest-URL hop). null\n * until that first resolve; 0 when no capture exists. This is the pre-paint\n * \"changes exist?\" signal the dock uses to pick its default tab with no\n * embedder events-at-mount contract. */\n fileCount: number | null;\n /** A newer revision has been ANNOUNCED than the one currently loaded (a refresh\n * is in flight or pending). M5's source badge can show a subtle \"updating…\". */\n isStale: boolean;\n loading: boolean;\n error: Error | null;\n /** Force a re-fetch of the latest capture. */\n refresh: () => Promise<void>;\n};\n\n/**\n * The cold-paint data source: fetch the latest turn-end workspace capture with a\n * SINGLE api round-trip on mount (no machine, no Channel-A — this is the <200ms\n * first paint). The manifest is served inline in the common\n * case; a rare >2MB manifest comes back as a short-TTL signed URL we follow.\n *\n * Subscribes to the live event log: a `workspace.revision.captured` for a revision\n * newer than the one loaded triggers a background refresh (stale-while-revalidate).\n * `{available:false}` is a value, never a crash — consumers fall back to the\n * live/wake path exactly as before the capture feature existed.\n */\nexport function useWorkspaceCapture(\n sessionId: string | null | undefined,\n options: UseWorkspaceCaptureOptions = {},\n): UseWorkspaceCaptureResult {\n const { client, workspaceId } = useOpenGeni(options);\n const enabled = (options.enabled ?? true) && Boolean(sessionId);\n const identityKey = `${workspaceId}\\u0000${sessionId ?? \"\"}`;\n\n const [capture, setCapture] = useState<WorkspaceCaptureManifest | null>(null);\n const [available, setAvailable] = useState(false);\n const [degradedReason, setDegradedReason] = useState<WorkspaceCaptureDegradedReason | null>(null);\n // Resolved from the FIRST GET's top-level stats (before any manifest-URL hop),\n // so the dock can pick its default tab as early as possible. null until then.\n const [fileCount, setFileCount] = useState<number | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n // The highest revision ANNOUNCED on the event log — compared against the loaded\n // manifest's revision to compute `isStale` and to gate refreshes.\n const [announcedRevision, setAnnouncedRevision] = useState<number | null>(null);\n // State updates are asynchronous, so the previous session's capture still\n // exists during the first render after an identity switch. Tag it and hide it\n // synchronously until the new identity's request owns the state.\n const [stateIdentity, setStateIdentity] = useState(identityKey);\n\n // A generation counter fences a slow in-flight fetch against a newer one (or an\n // identity change) so a stale response can never overwrite fresher state.\n const generationRef = useRef(0);\n const requestAbortRef = useRef<AbortController | null>(null);\n // Event sequence numbers are scoped to a session. Keeping this cursor across an\n // identity switch would discard the new session's low-numbered announcements.\n const lastSeqRef = useRef(0);\n\n const refresh = useCallback(async () => {\n if (!sessionId) return;\n requestAbortRef.current?.abort();\n const requestAbort = new AbortController();\n requestAbortRef.current = requestAbort;\n const generation = (generationRef.current += 1);\n setStateIdentity(identityKey);\n setLoading(true);\n setError(null);\n try {\n // A signed URL can expire between mint and GET. Re-enter the authenticated\n // endpoint once to mint a fresh URL; never replay or log the old credential.\n for (let attempt = 0; attempt < 2; attempt += 1) {\n const res: GetWorkspaceCaptureResponse = await client.getWorkspaceCapture(\n workspaceId,\n sessionId,\n { signal: requestAbort.signal },\n );\n if (generationRef.current !== generation) return;\n if (!res.available) {\n setCapture(null);\n setAvailable(false);\n setFileCount(0);\n setDegradedReason(res.degradedReason ?? null);\n return;\n }\n setDegradedReason(null);\n // Expose metadata while a large signed manifest downloads. Consumers\n // must distinguish this pending count from a resolved capture; zero\n // working-tree files can still have committed-only branch changes.\n setFileCount(res.stats.fileCount);\n // Exactly one of manifest / manifestUrl is non-null (M2 contract). The inline\n // manifest is the <200ms common case; a >2MB manifest is a signed URL hop.\n let manifestValue: unknown = res.manifest;\n if (!manifestValue && res.manifestUrl) {\n const response = await fetch(res.manifestUrl.url, {\n signal: AbortSignal.any([\n requestAbort.signal,\n AbortSignal.timeout(MANIFEST_FETCH_TIMEOUT_MS),\n ]),\n credentials: \"omit\",\n cache: \"no-store\",\n referrerPolicy: \"no-referrer\",\n }).catch(() => null);\n if (generationRef.current !== generation) return;\n if (!response?.ok) {\n if (\n attempt === 0 &&\n (response === null || response.status === 401 || response.status === 403)\n ) {\n continue;\n }\n throw new Error(\n `Workspace capture manifest download failed${response ? ` (${response.status})` : \"\"}.`,\n );\n }\n try {\n manifestValue = await response.json();\n } catch {\n throw new Error(\"Workspace capture manifest was not valid JSON.\");\n }\n if (generationRef.current !== generation) return;\n }\n if (!manifestValue) {\n throw new Error(\"Workspace capture response did not include a manifest.\");\n }\n const manifest = captureManifestForResponse(manifestValue, res);\n setCapture(manifest);\n setAvailable(true);\n // Fold the served revision into the announced high-water mark so a capture we\n // JUST loaded is never reported stale against an older announce.\n setAnnouncedRevision((prev) =>\n prev === null || manifest.revision > prev ? manifest.revision : prev,\n );\n return;\n }\n throw new Error(\"Workspace capture manifest download failed after refreshing its URL.\");\n } catch (cause) {\n if (generationRef.current !== generation) return;\n setError(cause instanceof Error ? cause : new Error(String(cause)));\n } finally {\n if (generationRef.current === generation) setLoading(false);\n if (requestAbortRef.current === requestAbort) requestAbortRef.current = null;\n }\n }, [client, workspaceId, sessionId, identityKey]);\n\n // Mount fetch + reset on identity change.\n useEffect(() => {\n // Invalidate a request started for the previous identity before clearing its\n // state. The cleanup also fences a response that arrives after unmount.\n requestAbortRef.current?.abort();\n requestAbortRef.current = null;\n generationRef.current += 1;\n lastSeqRef.current = 0;\n setCapture(null);\n setAvailable(false);\n setDegradedReason(null);\n setFileCount(null);\n setAnnouncedRevision(null);\n setError(null);\n if (!enabled) {\n setLoading(false);\n return;\n }\n void refresh();\n return () => {\n requestAbortRef.current?.abort();\n requestAbortRef.current = null;\n generationRef.current += 1;\n };\n }, [enabled, refresh]);\n\n // Fold `workspace.revision.captured` announcements. A revision NEWER than the one\n // loaded bumps the announced high-water mark (→ isStale) and refreshes in the\n // background. The event is announce-only (metadata) — we still re-fetch the\n // manifest, since the payload carries no content.\n const events = options.events;\n useEffect(() => {\n if (!enabled || !events) return;\n let newest: number | null = null;\n for (const event of events) {\n if (event.sequence <= lastSeqRef.current) continue;\n if (event.type === REVISION_CAPTURED) {\n const payload = event.payload as WorkspaceRevisionCapturedPayload | null;\n if (payload && typeof payload === \"object\" && typeof payload.revision === \"number\") {\n newest = newest === null ? payload.revision : Math.max(newest, payload.revision);\n }\n } else if (event.type === REVISION_DEGRADED) {\n const payload = event.payload as WorkspaceRevisionDegradedPayload | null;\n if (payload && typeof payload === \"object\" && typeof payload.revision === \"number\") {\n newest = newest === null ? payload.revision : Math.max(newest, payload.revision);\n }\n }\n }\n for (const event of events)\n if (event.sequence > lastSeqRef.current) lastSeqRef.current = event.sequence;\n if (newest === null) return;\n setAnnouncedRevision((prev) => (prev === null || newest > prev ? newest : prev));\n }, [enabled, events]);\n\n // A newer announced revision than the loaded manifest → refresh in the background.\n const identityMatches = enabled && stateIdentity === identityKey;\n const visibleCapture = identityMatches ? capture : null;\n const visibleAnnouncedRevision = identityMatches ? announcedRevision : null;\n const loadedRevision = visibleCapture?.revision ?? null;\n useEffect(() => {\n if (!enabled) return;\n if (visibleAnnouncedRevision === null) return;\n if (loadedRevision !== null && visibleAnnouncedRevision <= loadedRevision) return;\n // The mount request is already resolving the latest revision. Do not abort\n // and replace that exact identity-equivalent read merely because the event\n // tail announced a revision before the response arrived. When the request\n // settles, its state update re-runs this effect and a genuinely newer\n // announcement still refreshes immediately.\n if (requestAbortRef.current) return;\n // A newer capture exists than the one we hold (or we hold none) — pull it.\n void refresh();\n }, [enabled, visibleAnnouncedRevision, loadedRevision, refresh]);\n\n const isStale =\n loadedRevision !== null &&\n visibleAnnouncedRevision !== null &&\n visibleAnnouncedRevision > loadedRevision;\n\n return {\n capture: visibleCapture,\n revision: loadedRevision,\n capturedAt: visibleCapture?.capturedAt ?? null,\n available: identityMatches && available,\n degradedReason: identityMatches ? degradedReason : null,\n fileCount: identityMatches ? fileCount : null,\n isStale,\n loading: identityMatches && loading,\n error: identityMatches ? error : null,\n refresh,\n };\n}\n","import type { FileSystemRouteIdentity } from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { sandboxAcceptsLiveIo } from \"../lib/sandbox-liveness\";\n\n/**\n * The wake-on-edit state machine. This hook owns the logic and the UI renders\n * its result. States are explicit and exhaustive:\n *\n * viewing-cold — cold snapshot open, no local edits (editable, cloud).\n * buffering — local edits buffered; the box is not warm and no warm is\n * yet in flight (the host has not attached).\n * warming — edits buffered; the box is actively coming up (the host\n * attached a viewer in response to `wantsWarm`).\n * flushing — the box is warm; the guarded write is in flight.\n * flushed — the buffer was written to the live box.\n * conflict — the live file diverged from the captured base between\n * capture and flush; NO write was issued (C2).\n * readonly-offline — a self-hosted machine that is offline; read-only, no wake.\n */\nexport type WorkspaceEditState =\n | \"viewing-cold\"\n | \"buffering\"\n | \"warming\"\n | \"flushing\"\n | \"flushed\"\n | \"conflict\"\n | \"readonly-offline\";\n\nexport type WorkspaceEditConflict = {\n path: string;\n /** The capture-served content the edit was based on. */\n base: string;\n /** The live content found on the box at flush time (what would be overwritten). */\n live: string;\n};\n\nexport type UseWorkspaceEditOptions = ClientOverride & {\n /** The file being edited (workspace-relative). null disables the machine. */\n path?: string | null | undefined;\n /** The capture-served content loaded into the editor — the flush base (C2). */\n baseContent?: string | null | undefined;\n /** Exact capability identity for the selected filesystem route. A route/root\n * change discards the buffered edit and makes stale flushes fail retryably. */\n route?: FileSystemRouteIdentity | undefined;\n /** `capabilities.liveness` — \"warm\" | \"draining\" | \"cold\". Drives the flush. */\n liveness?: string | undefined;\n /** True while the host is actively warming the box (attach in flight, not warm\n * yet) — lifts `buffering` → `warming`. The host sets this after acting on\n * `wantsWarm` (e.g. flipping `attachFiles` on `useSessionCapabilities`). */\n warming?: boolean | undefined;\n /** A self-hosted machine that is OFFLINE: read-only, no remote wake possible. */\n offline?: boolean | undefined;\n /** Called once when the first cold edit needs the box warmed — the host wires\n * this to its liveness primitive (flip `attachFiles`/`attachViewer`). */\n onWarmRequested?: (() => void) | undefined;\n};\n\nexport type UseWorkspaceEditResult = {\n state: WorkspaceEditState;\n /** The editor should be read-only (self-hosted offline). */\n readOnly: boolean;\n /** The current buffered content (null = no local edit yet). */\n buffer: string | null;\n /** The host should warm the box (flip its attach primitive). Latches true from\n * the first cold edit until the buffer flushes or is discarded. */\n wantsWarm: boolean;\n /** Record an edit from the editor (idempotent per identical content). */\n edit: (content: string) => void;\n /** The conflict detail when `state === \"conflict\"`. */\n conflict: WorkspaceEditConflict | null;\n /** Flush the buffer regardless of the base guard (the user chose \"overwrite\"\n * from the conflict bar). Writes last-writer-wins. */\n overwrite: () => Promise<void>;\n /** Drop the local buffer and return to viewing the snapshot. */\n discard: () => void;\n error: Error | null;\n};\n\nfunction isLive(liveness: string | undefined): boolean {\n return sandboxAcceptsLiveIo(liveness);\n}\n\n/**\n * Cold-editing without a spinner: the editor opens instantly from the capture,\n * the first keystroke buffers locally AND signals the host to warm the box, and on\n * warm the buffer flushes IF the live file still matches the captured base — else a\n * non-blocking conflict is surfaced and nothing is overwritten.\n *\n * The base guard compares the live content at flush time against `baseContent`\n * (the exact bytes the editor loaded). This is equivalent to the sha256 compare\n * the design specifies — M1 leaves `baseHash` null, so the loaded content IS the\n * authoritative base — and avoids async Web Crypto in the render path.\n */\nexport function useWorkspaceEdit(\n sessionId: string | null | undefined,\n options: UseWorkspaceEditOptions = {},\n): UseWorkspaceEditResult {\n const { client, workspaceId } = useOpenGeni(options);\n const path = options.path ?? null;\n const baseContent = options.baseContent ?? null;\n const routeEpoch = options.route?.epoch;\n const routeRoot = options.route?.root;\n const route = useMemo<FileSystemRouteIdentity | undefined>(\n () =>\n routeEpoch !== undefined && routeRoot !== undefined\n ? { epoch: routeEpoch, root: routeRoot }\n : undefined,\n [routeEpoch, routeRoot],\n );\n const live = isLive(options.liveness);\n const offline = options.offline === true;\n const identityKey = `${workspaceId}\\u0000${sessionId ?? \"\"}\\u0000${path ?? \"\"}\\u0000${routeEpoch ?? \"\"}\\u0000${routeRoot ?? \"\"}`;\n\n const [buffer, setBuffer] = useState<string | null>(null);\n const [wantsWarm, setWantsWarm] = useState(false);\n const [flush, setFlush] = useState<\"idle\" | \"flushing\" | \"flushed\" | \"conflict\">(\"idle\");\n const [conflict, setConflict] = useState<WorkspaceEditConflict | null>(null);\n const [error, setError] = useState<Error | null>(null);\n const [stateIdentity, setStateIdentity] = useState(identityKey);\n\n const onWarmRequested = options.onWarmRequested;\n const bufferRef = useRef<string | null>(null);\n bufferRef.current = buffer;\n // Guards a single in-flight flush against re-entry (liveness can re-render).\n const flushingRef = useRef(false);\n const identityGenerationRef = useRef(0);\n const flushAttemptRef = useRef(0);\n const readAbortRef = useRef<AbortController | null>(null);\n\n // Reset the machine when the edited file (or session) changes.\n useEffect(() => {\n identityGenerationRef.current += 1;\n flushAttemptRef.current += 1;\n readAbortRef.current?.abort();\n readAbortRef.current = null;\n setStateIdentity(identityKey);\n setBuffer(null);\n setWantsWarm(false);\n setFlush(\"idle\");\n setConflict(null);\n setError(null);\n flushingRef.current = false;\n return () => {\n identityGenerationRef.current += 1;\n flushAttemptRef.current += 1;\n readAbortRef.current?.abort();\n readAbortRef.current = null;\n };\n }, [identityKey]);\n\n const edit = useCallback(\n (content: string) => {\n if (stateIdentity !== identityKey) return;\n if (offline) return; // read-only — no buffering, no wake.\n setBuffer((prev) => (prev === content ? prev : content));\n // Any new edit invalidates a prior flushed/conflict resolution.\n setFlush((prev) => (prev === \"flushing\" ? prev : \"idle\"));\n setConflict(null);\n if (!live) {\n // First cold edit signals the host to warm the box (once).\n setWantsWarm((prev) => {\n if (!prev) onWarmRequested?.();\n return true;\n });\n }\n },\n [offline, live, onWarmRequested, stateIdentity, identityKey],\n );\n\n const doFlush = useCallback(\n async (force: boolean) => {\n if (stateIdentity !== identityKey) return;\n if (!sessionId || !path) return;\n const content = bufferRef.current;\n if (content === null) return;\n if (flushingRef.current) return;\n const identityGeneration = identityGenerationRef.current;\n const flushAttempt = (flushAttemptRef.current += 1);\n flushingRef.current = true;\n setFlush(\"flushing\");\n setError(null);\n try {\n if (!force) {\n // Base guard: re-read the live file and compare to the captured base. A\n // divergence means the box changed under us — surface a conflict, write\n // NOTHING (C2).\n const readAbort = new AbortController();\n readAbortRef.current?.abort();\n readAbortRef.current = readAbort;\n const liveRead = await client.fsRead(\n workspaceId,\n sessionId,\n { path, ...(route ? { route } : {}) },\n { signal: readAbort.signal },\n );\n if (readAbortRef.current === readAbort) readAbortRef.current = null;\n if (identityGenerationRef.current !== identityGeneration) return;\n const liveContent = liveRead.content;\n if (baseContent !== null && liveContent !== baseContent) {\n setConflict({ path, base: baseContent, live: liveContent });\n setFlush(\"conflict\");\n return;\n }\n }\n await client.fsWrite(workspaceId, sessionId, {\n path,\n content,\n overwrite: true,\n ...(route ? { route } : {}),\n });\n if (identityGenerationRef.current !== identityGeneration) return;\n setConflict(null);\n setFlush(\"flushed\");\n setWantsWarm(false);\n } catch (cause) {\n if (identityGenerationRef.current !== identityGeneration) return;\n setError(cause instanceof Error ? cause : new Error(String(cause)));\n // Leave the buffer intact so the user can retry; fall back to buffering.\n setFlush(\"idle\");\n } finally {\n if (flushAttemptRef.current === flushAttempt) {\n flushingRef.current = false;\n readAbortRef.current = null;\n }\n }\n },\n [client, workspaceId, sessionId, path, baseContent, route, stateIdentity, identityKey],\n );\n\n // Auto-flush once the box is warm and a buffer is pending (the wake completed).\n useEffect(() => {\n if (offline) return;\n if (!live) return;\n if (buffer === null) return;\n if (flush === \"flushed\" || flush === \"conflict\" || flush === \"flushing\") return;\n void doFlush(false);\n }, [offline, live, buffer, flush, doFlush]);\n\n const overwrite = useCallback(async () => {\n await doFlush(true);\n }, [doFlush]);\n\n const discard = useCallback(() => {\n setBuffer(null);\n setWantsWarm(false);\n setFlush(\"idle\");\n setConflict(null);\n setError(null);\n }, []);\n\n // Derive the exhaustive public state.\n let state: WorkspaceEditState;\n if (offline) {\n state = \"readonly-offline\";\n } else if (flush === \"flushing\") {\n state = \"flushing\";\n } else if (flush === \"flushed\") {\n state = \"flushed\";\n } else if (flush === \"conflict\") {\n state = \"conflict\";\n } else if (buffer === null) {\n state = \"viewing-cold\";\n } else if (live) {\n // Warm with a pending buffer that hasn't entered flush yet — a transient tick\n // before the auto-flush effect runs.\n state = \"flushing\";\n } else if (options.warming === true) {\n state = \"warming\";\n } else {\n state = \"buffering\";\n }\n\n const identityMatches = stateIdentity === identityKey;\n return {\n state: identityMatches ? state : offline ? \"readonly-offline\" : \"viewing-cold\",\n readOnly: offline,\n buffer: identityMatches ? buffer : null,\n wantsWarm: identityMatches && wantsWarm,\n edit,\n conflict: identityMatches ? conflict : null,\n overwrite,\n discard,\n error: identityMatches ? error : null,\n };\n}\n","import { useMemo } from \"react\";\nimport type { MachineState } from \"@opengeni/sdk\";\nimport type { SessionCapabilitiesState } from \"./use-session-capabilities\";\nimport { sandboxAcceptsLiveIo } from \"../lib/sandbox-liveness\";\nimport { connectionStatusForState } from \"../types/machines\";\nimport { useOpenGeniText, type OpenGeniText } from \"../messages/runtime\";\n\n/** The one truthful machine indicator. Managed cold compute is sleeping; a\n * Connected Machine that is genuinely unreachable remains offline. */\nexport type MachineChipState = \"live\" | \"waking\" | \"offline\";\n\nexport type MachineChip = {\n state: MachineChipState;\n /** A ready-to-render label (\"Live\" / \"Waking…\" / \"Sleeping · saved 3m ago\"). */\n label: string;\n /** The capture time backing an offline/stale label (ISO), or null. M4 may\n * reformat this; `label` already embeds a relative form. */\n asOf: string | null;\n};\n\nexport type DeriveMachineChipInput = {\n /** `capabilities.liveness` — \"warm\" | \"draining\" | \"cold\" (or null pre-negotiation). */\n liveness?: string | null | undefined;\n /** `useSessionCapabilities().state` — drives the \"waking\" (negotiating) read. */\n capabilitiesState?: SessionCapabilitiesState | null | undefined;\n /** The ACTIVE machine's connection state (from `useMachines`), when known. A\n * self-hosted machine that is `offline` cannot be remotely woken. */\n activeMachineState?: MachineState | null | undefined;\n /** Whether the active sandbox is a user-owned self-hosted machine (no remote wake). */\n activeIsSelfhosted?: boolean | undefined;\n /** An interaction (wake-on-edit, terminal focus) is actively warming the box. */\n wantsWarm?: boolean | undefined;\n /** The latest capture's `capturedAt` (ISO) — the \"as of <time>\" backing. */\n capturedAt?: string | null | undefined;\n /** Injectable clock for deterministic relative labels (defaults to Date.now). */\n now?: number | undefined;\n};\n\n/** Compact relative-time for the \"as of\" label. Pure, no Intl dependency. */\nexport function formatAsOf(t: OpenGeniText, capturedAt: string, now: number): string {\n const then = Date.parse(capturedAt);\n if (Number.isNaN(then)) return \"recently\";\n const seconds = Math.max(0, Math.round((now - then) / 1000));\n if (seconds < 45) return t(\"hooks.useMachineChip.justNow\");\n const minutes = Math.round(seconds / 60);\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.round(minutes / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.round(hours / 24);\n return `${days}d ago`;\n}\n\n/**\n * Derive the machine-state chip from the live capability/liveness surface, the\n * active machine's connection state, and the latest capture time. PURE (M4 renders\n * it; the whole point is a deterministic, testable projection).\n *\n * Precedence:\n * 1. warm lease → **live** (a holder-confirmed box always wins).\n * 2. actively warming (negotiating, wake-on-edit, or a reconnecting/enrolling\n * machine) → **waking**.\n * 3. everything else (a cold/asleep box, a self-hosted machine that's offline,\n * an error) → **offline**, labelled \"as of <capture time>\".\n */\nexport function deriveMachineChip(t: OpenGeniText, input: DeriveMachineChipInput): MachineChip {\n const now = input.now ?? Date.now();\n const asOf = input.capturedAt ?? null;\n const managedRestingLabel = asOf\n ? t(\"hooks.useMachineChip.sleepingSavedAsof\", { asOf: formatAsOf(t, asOf, now) })\n : t(\"hooks.useMachineChip.sleeping\");\n const offlineLabel = t(\"hooks.useMachineChip.offline\");\n\n // A connected machine has no Modal group lease, so capability negotiation\n // legitimately reports `cold` until a stream holder is minted. Its fleet\n // probe is the authoritative reachability signal; do not label an online Mac\n // \"Offline\" merely because there is no unrelated Modal lease.\n const selfhostedOnline =\n input.activeIsSelfhosted === true &&\n input.activeMachineState != null &&\n connectionStatusForState(input.activeMachineState) === \"online\";\n\n // 1. A holder-confirmed warm provider or online connected machine is live.\n // Draining remains teardown-owned and may already have lost its instance.\n if (sandboxAcceptsLiveIo(input.liveness) || selfhostedOnline) {\n return { state: \"live\", label: t(\"hooks.useMachineChip.live\"), asOf: null };\n }\n\n // A self-hosted machine that reports offline cannot be woken remotely — honest\n // \"offline\", never \"waking\".\n const selfhostedOffline =\n input.activeIsSelfhosted === true && input.activeMachineState === \"offline\";\n\n // Capability negotiation has definitively failed. A retained warm intent\n // must not turn that error into the optimistic Waking state.\n if (input.capabilitiesState === \"error\") {\n return {\n state: \"offline\",\n label: input.activeIsSelfhosted === true ? offlineLabel : managedRestingLabel,\n asOf,\n };\n }\n\n // 2. Actively coming up: negotiation in flight, an edit/terminal is warming, or\n // the active machine is (re)connecting. Never when self-hosted is hard-offline.\n const machineWarming =\n input.activeMachineState === \"reconnecting\" || input.activeMachineState === \"enrolling\";\n if (\n !selfhostedOffline &&\n (input.capabilitiesState === \"negotiating\" || input.wantsWarm === true || machineWarming)\n ) {\n return { state: \"waking\", label: t(\"hooks.useMachineChip.waking\"), asOf };\n }\n\n // 3. Managed cold compute is sleeping with saved-workspace freshness. A\n // Connected Machine is only described as Offline when its reachability is\n // genuinely unavailable; capture time is not a heartbeat.\n return {\n state: \"offline\",\n label: input.activeIsSelfhosted === true ? offlineLabel : managedRestingLabel,\n asOf,\n };\n}\n\nexport type UseMachineChipOptions = DeriveMachineChipInput;\n\n/**\n * Thin memoized wrapper over `deriveMachineChip` for the dock header (M4). The\n * dock already runs `useSessionCapabilities` + `useMachines` + `useWorkspace\n * capture`; it feeds their `liveness` / `state` / active-machine state /\n * `capturedAt` here. Pass a periodically-updated `now` if you want the relative\n * \"as of\" label to tick.\n */\nexport function useMachineChip(input: UseMachineChipOptions): MachineChip {\n const t = useOpenGeniText();\n const {\n liveness,\n capabilitiesState,\n activeMachineState,\n activeIsSelfhosted,\n wantsWarm,\n capturedAt,\n now,\n } = input;\n return useMemo(\n () =>\n deriveMachineChip(t, {\n liveness,\n capabilitiesState,\n activeMachineState,\n activeIsSelfhosted,\n wantsWarm,\n capturedAt,\n now,\n }),\n // Depend on the primitive fields (not the object identity) so a caller passing\n // a fresh object each render doesn't recompute needlessly.\n [\n liveness,\n capabilitiesState,\n activeMachineState,\n activeIsSelfhosted,\n wantsWarm,\n capturedAt,\n now,\n t,\n ],\n );\n}\n","import { deriveSessionDisplayTitle, type Session } from \"@opengeni/sdk\";\nimport { modelDisplayName } from \"@opengeni/sdk/model-display\";\nimport { cn } from \"../lib/cn\";\nimport { formatRelativeTime } from \"../lib/format\";\nimport { sessionAdmissionBlocked, sessionDisplayStatus } from \"../session-status-model\";\nimport { SessionStatus } from \"./session-status\";\nimport { useOpenGeniText } from \"../messages/runtime\";\n\nconst SESSION_METADATA_TITLE_KEYS = [\"title\", \"name\"] as const;\n\nexport type FleetTileProps = {\n session: Session;\n /** Overrides the derived title (durable title, metadata, prompt preview, or safe fallback). */\n title?: string | undefined;\n /** Extra line under the title — e.g. \"drift check\" or the worker's task. */\n subtitle?: string | undefined;\n onOpen?: ((session: Session) => void) | undefined;\n className?: string | undefined;\n};\n\n/** Best-effort display title for a session. */\nexport function sessionDisplayTitle(session: Session): string {\n return deriveSessionDisplayTitle(session, { metadataKeys: SESSION_METADATA_TITLE_KEYS });\n}\n\n/**\n * One session in the fleet/manager view: title, live status, model, and\n * recency — dense but calm. Running sessions carry a breathing status dot\n * and a faint accent edge so the live ones read at a glance.\n */\nexport function FleetTile({ session, title, subtitle, onOpen, className }: FleetTileProps) {\n const msg = useOpenGeniText();\n const running = session.status === \"running\" || session.status === \"queued\";\n const needsYou = session.status === \"requires_action\" && !sessionAdmissionBlocked(session);\n return (\n <button\n type=\"button\"\n data-status={session.status}\n onClick={onOpen ? () => onOpen(session) : undefined}\n disabled={!onOpen}\n className={cn(\n \"og-root group relative flex w-full flex-col gap-2.5 overflow-hidden rounded-og-lg border border-og-border\",\n \"bg-og-surface-1 p-4 text-left shadow-og-sm\",\n \"transition-[border-color,background-color,box-shadow,transform] duration-200 ease-og-out\",\n onOpen &&\n \"hover:-translate-y-px hover:border-og-border-strong hover:bg-og-surface-2 hover:shadow-og-md\",\n \"disabled:cursor-default\",\n className,\n )}\n >\n <span\n aria-hidden\n className={cn(\n \"absolute inset-y-0 left-0 w-0.5 transition-opacity duration-300\",\n running\n ? \"bg-og-accent opacity-100\"\n : needsYou\n ? \"bg-og-status-waiting opacity-100\"\n : \"opacity-0\",\n )}\n />\n <span className=\"flex w-full items-start justify-between gap-3\">\n <span className=\"line-clamp-2 min-w-0 text-og-base font-medium leading-snug text-og-fg\">\n {title ?? sessionDisplayTitle(session)}\n </span>\n <SessionStatus status={sessionDisplayStatus(session)} size=\"sm\" className=\"mt-px\" />\n </span>\n {subtitle ? (\n <span className=\"line-clamp-1 text-og-sm text-og-fg-muted\">{subtitle}</span>\n ) : null}\n <span className=\"mt-auto flex w-full items-center gap-2 text-og-xs text-og-fg-subtle\">\n <span className=\"font-og-mono\">{session.id.slice(0, 8)}</span>\n <span aria-hidden>·</span>\n <span className=\"truncate\">{modelDisplayName(session.model)}</span>\n <span className=\"ml-auto shrink-0\" title={session.updatedAt}>\n {formatRelativeTime(msg, session.updatedAt)}\n </span>\n </span>\n </button>\n );\n}\n","import type { GitFileDiff } from \"@opengeni/sdk\";\nimport { ArrowUpRightIcon, FileWarningIcon, HistoryIcon } from \"lucide-react\";\nimport {\n Component,\n type ReactNode,\n useCallback,\n useEffect,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { VList, type VListHandle } from \"virtua\";\nimport { cn } from \"../lib/cn\";\nimport { useUnicodeFallbackFonts } from \"../lib/use-unicode-fonts\";\nimport { useThemeType } from \"../lib/use-theme-type\";\nimport { formatAsOf } from \"../hooks/use-machine-chip\";\nimport type { SandboxGitFileDiff } from \"../hooks/use-sandbox-git\";\nimport { useWindowedSections } from \"../hooks/use-windowed-sections\";\nimport { PierreDiff } from \"./pierre-diff\";\nimport { useOpenGeniText, type OpenGeniText } from \"../messages/runtime\";\n\n/* ----------------------------------------------------------------------------\n Changes tab — a PR-review surface.\n\n A file rail (status glyph, ±counts, grouped by repository when metadata is\n available, otherwise by top-level directory for a large legacy input) on the\n left; a stacked, WINDOWED diff pane on the right. Only\n the file sections inside the visible window ± overscan mount a Pierre/Shiki\n highlighter (the one renderer), so a 40- or 400-file change set never mounts N\n highlighters at once (D2). A per-file size guard (binary / diff too\n large) degrades to an \"open live\" affordance instead of a diff body.\n\n Workspace-wide Git results carry an explicit `repoRoot`, so grouping never\n guesses repository ownership from a directory name. Multi-repo results group\n at every size; legacy unscoped inputs group by top-level directory only past\n the threshold.\n -------------------------------------------------------------------------- */\n\n/** Group the rail (and reorder the pane) once the change set is larger than this. */\nconst GROUP_THRESHOLD = 20;\n/** Mount this many sections beyond the visible window on each side. */\nconst OVERSCAN = 2;\nconst HEADER_PX = 30;\nconst LINE_PX = 18;\nconst GUARD_BODY_PX = 52;\nconst COMPACT_SURFACE_PX = 560;\nconst useChangesLayoutEffect = typeof window === \"undefined\" ? useEffect : useLayoutEffect;\n\nconst STATUS_TINT: Record<GitFileDiff[\"status\"], string> = {\n added: \"text-og-status-idle\",\n modified: \"text-og-status-running\",\n deleted: \"text-og-status-failed\",\n renamed: \"text-og-accent\",\n copied: \"text-og-accent\",\n untracked: \"text-og-fg-subtle\",\n ignored: \"text-og-fg-subtle\",\n conflicted: \"text-og-status-failed\",\n typechange: \"text-og-status-running\",\n};\n\nconst STATUS_LETTER: Record<GitFileDiff[\"status\"], string> = {\n added: \"A\",\n modified: \"M\",\n deleted: \"D\",\n renamed: \"R\",\n copied: \"C\",\n untracked: \"U\",\n ignored: \"I\",\n conflicted: \"!\",\n typechange: \"T\",\n};\n\nfunction compactFileLabel(file: SandboxGitFileDiff): string {\n const slash = file.path.lastIndexOf(\"/\");\n const basename = slash >= 0 ? file.path.slice(slash + 1) : file.path;\n const parent = slash >= 0 ? file.path.slice(0, slash + 1) : \"\";\n return `${STATUS_LETTER[file.status]} · ${basename}${parent ? ` — ${parent}` : \"\"}`;\n}\n\nexport type WorkbenchChangesProps = {\n /** The changed files (`useSandboxGit().diff`). Assumed non-empty by the caller. */\n diff: SandboxGitFileDiff[];\n /** Which source the diff came from — drives the \"live\" vs \"as of turn\" badge. */\n source: \"live\" | \"capture\" | null;\n /** When the served capture was taken (ISO), when `source === \"capture\"`. */\n capturedAt: string | null;\n /** The capture's turn revision, for the \"as of turn N\" badge. */\n captureRevision?: number | null | undefined;\n themeType?: \"dark\" | \"light\" | undefined;\n /** Route a guarded binary/oversize file into the live Files surface. */\n onOpenFile?: ((path: string) => void) | undefined;\n className?: string | undefined;\n};\n\ntype RailRow =\n | { kind: \"group\"; label: string; count: number }\n | { kind: \"file\"; file: SandboxGitFileDiff; index: number };\n\ntype ChangesRailVListProps = {\n children: ReactNode;\n className: string;\n coarsePointer: boolean;\n files: readonly SandboxGitFileDiff[];\n rowCount: number;\n};\n\ntype ChangesRailVListState = {\n renderedRowCount: number;\n resetVersion: number;\n};\n\ntype ChangesRailSnapshot = {\n focusedPath: string | null;\n scrollOffset: number;\n};\n\n/** Virtua must reset its cached range when the rail shrinks. Keep that remount\n * scoped to shrink transitions and preserve the reader's focus/scroll context. */\nclass ChangesRailVList extends Component<\n ChangesRailVListProps,\n ChangesRailVListState,\n ChangesRailSnapshot | null\n> {\n state: ChangesRailVListState = {\n renderedRowCount: this.props.rowCount,\n resetVersion: 0,\n };\n\n private host: HTMLDivElement | null = null;\n private listHandle: VListHandle | null = null;\n private pendingFocusedPath: string | null = null;\n private restoreFrame: number | null = null;\n\n static getDerivedStateFromProps(\n props: ChangesRailVListProps,\n state: ChangesRailVListState,\n ): ChangesRailVListState | null {\n if (props.rowCount === state.renderedRowCount) return null;\n return {\n renderedRowCount: props.rowCount,\n resetVersion:\n props.rowCount < state.renderedRowCount ? state.resetVersion + 1 : state.resetVersion,\n };\n }\n\n getSnapshotBeforeUpdate(\n _previousProps: ChangesRailVListProps,\n previousState: ChangesRailVListState,\n ): ChangesRailSnapshot | null {\n if (previousState.resetVersion === this.state.resetVersion) return null;\n const scroller = this.host?.firstElementChild;\n if (!(scroller instanceof HTMLElement)) return null;\n const active = document.activeElement;\n const focusedRow =\n active instanceof HTMLElement && scroller.contains(active)\n ? active.closest<HTMLElement>(\"[data-rail-file-path]\")\n : null;\n return {\n focusedPath: focusedRow?.dataset.railFilePath ?? this.pendingFocusedPath,\n scrollOffset: scroller.scrollTop,\n };\n }\n\n componentDidUpdate(\n _previousProps: ChangesRailVListProps,\n _previousState: ChangesRailVListState,\n snapshot: ChangesRailSnapshot | null,\n ): void {\n if (!snapshot || !this.listHandle) return;\n this.cancelRestoreFrame();\n const maxOffset = Math.max(0, this.listHandle.scrollSize - this.listHandle.viewportSize);\n this.listHandle.scrollTo(Math.min(Math.max(snapshot.scrollOffset, 0), maxOffset));\n const focusedPath = snapshot.focusedPath;\n if (!focusedPath) return;\n this.pendingFocusedPath = focusedPath;\n this.continueFocusRestore();\n }\n\n componentWillUnmount(): void {\n this.cancelRestoreFrame();\n this.pendingFocusedPath = null;\n }\n\n private cancelRestoreFrame(): void {\n if (this.restoreFrame === null) return;\n if (typeof cancelAnimationFrame === \"function\") cancelAnimationFrame(this.restoreFrame);\n this.restoreFrame = null;\n }\n\n private continueFocusRestore = (): void => {\n const path = this.pendingFocusedPath;\n if (!path) return;\n if (this.restoreFocusedPath(path)) {\n this.pendingFocusedPath = null;\n return;\n }\n if (this.restoreFrame === null && typeof requestAnimationFrame === \"function\") {\n this.restoreFrame = requestAnimationFrame(() => {\n this.restoreFrame = null;\n this.continueFocusRestore();\n });\n }\n };\n\n private restoreFocusedPath(path: string): boolean {\n const host = this.host;\n if (!host) return true;\n const active = document.activeElement;\n if (active instanceof HTMLElement && active.isConnected && active !== document.body) {\n return true;\n }\n if (!this.props.files.some((file) => file.path === path)) return true;\n const row = Array.from(host.querySelectorAll<HTMLButtonElement>(\"[data-rail-file-path]\")).find(\n (candidate) => candidate.dataset.railFilePath === path,\n );\n if (!row) return false;\n row.focus({ preventScroll: true });\n return true;\n }\n\n private setHost = (host: HTMLDivElement | null): void => {\n this.host = host;\n };\n\n private setListHandle = (handle: VListHandle | null): void => {\n this.listHandle = handle;\n };\n\n render() {\n return (\n <div ref={this.setHost} data-opengeni-changes-rail className={this.props.className}>\n <VList\n key={this.state.resetVersion}\n ref={this.setListHandle}\n className=\"h-full\"\n itemSize={this.props.coarsePointer ? 44 : 28}\n ssrCount={Math.min(30, this.props.rowCount)}\n >\n {this.props.children}\n </VList>\n </div>\n );\n }\n}\n\n/** Order the files and build the rail rows (grouped past the threshold). The\n * returned `orderedFiles` drives BOTH the rail and the diff pane so a rail row's\n * `index` addresses the matching pane section. Exported for tests. */\nexport function buildRail(\n t: OpenGeniText,\n files: SandboxGitFileDiff[],\n): {\n orderedFiles: SandboxGitFileDiff[];\n rows: RailRow[];\n grouped: boolean;\n} {\n const roots = new Set(\n files.flatMap((file) => (file.repoRoot === undefined ? [] : [file.repoRoot])),\n );\n const groupByRepo = roots.size > 1;\n if (!groupByRepo && files.length <= GROUP_THRESHOLD) {\n return {\n orderedFiles: files,\n rows: files.map((file, index) => ({ kind: \"file\", file, index })),\n grouped: false,\n };\n }\n const groups = new Map<string, SandboxGitFileDiff[]>();\n for (const file of files) {\n const slash = file.path.indexOf(\"/\");\n const key = groupByRepo\n ? file.repoRoot || t(\"workbenchChanges.workspace\")\n : slash > 0\n ? file.path.slice(0, slash)\n : t(\"workbenchChanges.root\");\n const bucket = groups.get(key);\n if (bucket) bucket.push(file);\n else groups.set(key, [file]);\n }\n const labels = [...groups.keys()].sort((a, b) => a.localeCompare(b));\n const orderedFiles: SandboxGitFileDiff[] = [];\n const rows: RailRow[] = [];\n for (const label of labels) {\n const bucket = (groups.get(label) ?? []).slice().sort((a, b) => a.path.localeCompare(b.path));\n rows.push({ kind: \"group\", label, count: bucket.length });\n for (const file of bucket) {\n rows.push({ kind: \"file\", file, index: orderedFiles.length });\n orderedFiles.push(file);\n }\n }\n return { orderedFiles, rows, grouped: true };\n}\n\n/** A file's diff body is \"too large to inline\" when it's binary or the diff guard\n * tripped (the backend omits hunks past its size cap) — open it live instead. */\nfunction isGuarded(file: GitFileDiff): boolean {\n return file.isBinary || file.truncated;\n}\n\n/** Estimate a section's rendered height for the windowing math. Line-count based,\n * so it is close enough that the first paint barely shifts as real heights land. */\nfunction estimateSectionHeight(file: GitFileDiff): number {\n if (isGuarded(file)) return HEADER_PX + GUARD_BODY_PX;\n let lines = 0;\n for (const hunk of file.hunks) lines += hunk.lines.length + 1;\n return HEADER_PX + Math.max(lines, 1) * LINE_PX + 8;\n}\n\nexport function WorkbenchChanges({\n diff,\n source,\n capturedAt,\n captureRevision,\n themeType,\n onOpenFile,\n className,\n}: WorkbenchChangesProps) {\n const t = useOpenGeniText();\n const rootRef = useRef<HTMLDivElement | null>(null);\n const [compact, setCompact] = useState(false);\n const [coarsePointer, setCoarsePointer] = useState(false);\n const resolvedTheme = useThemeType(themeType);\n const [layout, setLayout] = useState<\"unified\" | \"split\">(\"unified\");\n const [activePath, setActivePath] = useState<string | null>(null);\n const pickerId = useId();\n\n const unicodeFontPaths = useMemo(\n () => diff.flatMap((file) => (file.oldPath ? [file.path, file.oldPath] : [file.path])),\n [diff],\n );\n useUnicodeFallbackFonts(unicodeFontPaths);\n\n const { orderedFiles, rows, grouped } = useMemo(() => buildRail(t, diff), [diff, t]);\n const selectedIndex = orderedFiles.findIndex((file) => file.path === activePath);\n const activeIndex = selectedIndex >= 0 ? selectedIndex : 0;\n\n useChangesLayoutEffect(() => {\n const root = rootRef.current;\n if (!root || typeof ResizeObserver === \"undefined\") return;\n const update = (width: number) => {\n // DOM test environments report a zero geometry. Keep the deterministic\n // desktop/SSR branch until the observer has a real measurement.\n if (width > 0) setCompact(width < COMPACT_SURFACE_PX);\n };\n update(root.getBoundingClientRect().width);\n const observer = new ResizeObserver((entries) => {\n update(entries[0]?.contentRect.width ?? root.getBoundingClientRect().width);\n });\n observer.observe(root);\n return () => observer.disconnect();\n }, []);\n\n useChangesLayoutEffect(() => {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") return;\n const query = window.matchMedia(\"(pointer: coarse)\");\n const update = () => setCoarsePointer(query.matches);\n update();\n if (typeof query.addEventListener === \"function\") {\n query.addEventListener(\"change\", update);\n return () => query.removeEventListener(\"change\", update);\n }\n if (typeof query.addListener === \"function\") {\n query.addListener(update);\n return () => query.removeListener(update);\n }\n }, []);\n\n const additions = useMemo(() => diff.reduce((sum, f) => sum + f.additions, 0), [diff]);\n const deletions = useMemo(() => diff.reduce((sum, f) => sum + f.deletions, 0), [diff]);\n\n const estimateHeight = useCallback(\n (index: number) => {\n const file = orderedFiles[index];\n return file ? estimateSectionHeight(file) : HEADER_PX + LINE_PX;\n },\n [orderedFiles],\n );\n\n const windowed = useWindowedSections({\n count: orderedFiles.length,\n estimateHeight,\n overscan: OVERSCAN,\n });\n\n const jumpTo = useCallback(\n (index: number) => {\n setActivePath(orderedFiles[index]?.path ?? null);\n windowed.scrollToIndex(index);\n },\n [orderedFiles, windowed],\n );\n\n // Track which section is at the top of the pane so the rail highlights it.\n const onPaneScroll = useCallback(() => {\n const el = windowed.scrollRef.current;\n if (!el) {\n return;\n }\n const top = el.scrollTop;\n const offsets = windowed.offsets;\n let idx = 0;\n for (let i = 0; i < orderedFiles.length; i++) {\n if ((offsets[i] ?? 0) <= top + 4) idx = i;\n else break;\n }\n const nextPath = orderedFiles[idx]?.path ?? null;\n setActivePath((previous) => (previous === nextPath ? previous : nextPath));\n }, [windowed, orderedFiles]);\n\n useEffect(() => {\n const el = windowed.scrollRef.current;\n if (!el) return;\n el.addEventListener(\"scroll\", onPaneScroll, { passive: true });\n return () => el.removeEventListener(\"scroll\", onPaneScroll);\n }, [windowed.scrollRef, onPaneScroll]);\n\n const sourceBadge = describeSource(t, source, capturedAt, captureRevision ?? null);\n const activeFile = orderedFiles[activeIndex] ?? orderedFiles[0];\n\n return (\n <div\n ref={rootRef}\n className={cn(\"flex h-full min-h-0 min-w-0 flex-col\", className)}\n data-workbench-changes-layout={compact ? \"compact\" : \"rail\"}\n >\n {/* Summary + source badge + layout toggle. */}\n <div\n className={cn(\n \"flex shrink-0 items-center justify-between gap-2 border-b border-og-border px-3 py-1.5\",\n compact && source === \"capture\" && \"flex-col items-stretch gap-1.5 py-2\",\n )}\n >\n <span\n role=\"status\"\n aria-atomic=\"true\"\n aria-live=\"polite\"\n data-contrast-audited\n className=\"min-w-0 text-og-xs text-og-fg-muted\"\n >\n {t(\"workbenchChanges.filesChanged\", { count: diff.length })}\n <span data-contrast-audited className=\"ml-2 text-og-status-idle\">\n +{additions}\n </span>\n <span data-contrast-audited className=\"ml-1 text-og-status-failed\">\n −{deletions}\n </span>\n </span>\n <div\n className={cn(\n \"flex shrink-0 items-center gap-2\",\n compact && source === \"capture\" && \"self-start\",\n )}\n >\n {compact ? null : <LayoutToggle layout={layout} onChange={setLayout} />}\n <SourceBadge source={source} capturedAt={capturedAt} label={sourceBadge} />\n </div>\n </div>\n\n {compact ? (\n <div className=\"flex min-h-0 flex-1 flex-col\">\n <div className=\"shrink-0 border-b border-og-border bg-og-surface-1 p-2\">\n <label className=\"sr-only\" htmlFor={pickerId}>\n {t(\"workbenchChanges.changedFile\")}\n </label>\n <select\n id={pickerId}\n aria-label={t(\"workbenchChanges.changedFile\")}\n value={activeIndex}\n onChange={(event) => {\n const index = Number(event.currentTarget.value);\n setActivePath(orderedFiles[index]?.path ?? null);\n }}\n title={activeFile?.path}\n data-compact-file-picker\n className=\"h-11 w-full rounded-og-md border border-og-border bg-og-bg px-3 font-og-mono text-og-sm text-og-fg outline-hidden transition-colors focus:border-og-accent focus:ring-2 focus:ring-og-accent-soft\"\n >\n {orderedFiles.map((file, index) => (\n <option key={file.path} value={index}>\n {compactFileLabel(file)}\n </option>\n ))}\n </select>\n </div>\n <div\n aria-label={t(\"workbenchChanges.changedFileDiff\")}\n className=\"min-h-0 min-w-0 flex-1 overflow-auto outline-hidden focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-og-accent\"\n data-opengeni-changes-pane\n role=\"region\"\n tabIndex={0}\n >\n {activeFile ? (\n <DiffSection\n file={activeFile}\n layout=\"unified\"\n themeType={resolvedTheme}\n {...(onOpenFile ? { onOpenFile } : {})}\n />\n ) : null}\n </div>\n </div>\n ) : (\n <div className=\"flex min-h-0 flex-1\">\n {/* File rail — virtualized (virtua): a dense change set is fine. */}\n <ChangesRailVList\n rowCount={rows.length}\n coarsePointer={coarsePointer}\n files={orderedFiles}\n className=\"w-[clamp(12rem,28%,15rem)] shrink-0 border-r border-og-border bg-og-surface-1/35\"\n >\n {rows.map((row) =>\n row.kind === \"group\" ? (\n <div\n key={`g:${row.label}`}\n data-rail-group\n className=\"flex items-center gap-1.5 px-2 pb-0.5 pt-2 text-og-xs font-medium uppercase tracking-wide text-og-fg-subtle\"\n >\n <span className=\"min-w-0 truncate\">{row.label}</span>\n <span className=\"shrink-0\">{row.count}</span>\n </div>\n ) : (\n <RailFileRow\n key={row.file.path}\n file={row.file}\n grouped={grouped}\n active={row.index === activeIndex}\n onClick={() => jumpTo(row.index)}\n />\n ),\n )}\n </ChangesRailVList>\n\n {/* Diff pane — windowed file sections. Only the sections inside the\n visible window ± overscan are in the DOM; the container reserves the\n full scroll height so scrolling + the rail-jump stay accurate. */}\n <div\n ref={windowed.scrollRef}\n aria-label={t(\"workbenchChanges.changedFilesDiff\")}\n className=\"min-h-0 min-w-0 flex-1 overflow-auto outline-hidden focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-og-accent\"\n data-opengeni-changes-pane\n role=\"region\"\n tabIndex={0}\n >\n <div style={{ position: \"relative\", height: windowed.totalHeight }}>\n {orderedFiles.map((file, index) => {\n if (index < windowed.range.start || index >= windowed.range.end) return null;\n return (\n <MeasuredSection\n key={file.path}\n index={index}\n top={windowed.offsets[index] ?? 0}\n onMeasure={windowed.measure}\n >\n <DiffSection\n file={file}\n layout={layout}\n themeType={resolvedTheme}\n {...(onOpenFile ? { onOpenFile } : {})}\n />\n </MeasuredSection>\n );\n })}\n </div>\n </div>\n </div>\n )}\n </div>\n );\n}\n\n/**\n * The data-source badge. \"live\" stays understated (the header chip already\n * carries machine liveness) — but a capture-served diff is honestly labelled\n * historical: a muted clock + the \"as of turn N · <time>\" so the reviewer always\n * knows they are looking at a turn-end snapshot, not the live tree.\n */\nfunction SourceBadge({\n source,\n capturedAt,\n label,\n}: {\n source: \"live\" | \"capture\" | null;\n capturedAt: string | null;\n label: string;\n}) {\n const t = useOpenGeniText();\n if (source === \"capture\" && capturedAt) {\n return (\n <span\n className=\"inline-flex items-center gap-1 rounded-og-xs border border-og-border px-1.5 py-px text-og-xs text-og-fg-muted\"\n title={new Date(capturedAt).toLocaleString(t.locale)}\n >\n <HistoryIcon className=\"size-3 shrink-0 text-og-status-running\" aria-hidden />\n {label}\n </span>\n );\n }\n return (\n <span className=\"rounded-og-xs bg-og-surface-2 px-1.5 py-px text-og-xs text-og-fg-subtle\">\n {label}\n </span>\n );\n}\n\n/** \"Live diff\" · \"as of turn 7 · 14:32\" · \"as of 14:32\" (no revision). */\nfunction describeSource(\n t: OpenGeniText,\n source: \"live\" | \"capture\" | null,\n capturedAt: string | null,\n revision: number | null,\n): string {\n if (source !== \"capture\" || !capturedAt) return t(\"workbenchChanges.liveDiff\");\n const time = formatAsOf(t, capturedAt, Date.now());\n return revision !== null\n ? t(\"workbenchChanges.asOfTurnRevisionTime\", { revision, time })\n : `as of ${time}`;\n}\n\nfunction RailFileRow({\n file,\n grouped,\n active,\n onClick,\n}: {\n file: SandboxGitFileDiff;\n grouped: boolean;\n active: boolean;\n onClick: () => void;\n}) {\n // A real repository group strips the exact repo root. Legacy top-directory\n // grouping strips only that first segment.\n const repoPrefix = file.repoRoot ? `${file.repoRoot}/` : null;\n const shown = grouped\n ? file.repoRoot !== undefined\n ? repoPrefix && file.path.startsWith(repoPrefix)\n ? file.path.slice(repoPrefix.length)\n : file.path\n : file.path.slice(file.path.indexOf(\"/\") + 1) || file.path\n : file.path;\n return (\n <button\n type=\"button\"\n onClick={onClick}\n title={file.path}\n data-rail-file\n data-rail-file-path={file.path}\n className={cn(\n \"relative flex min-h-7 w-full items-center gap-1.5 truncate px-2 py-0.5 text-left text-og-sm transition-colors hover:bg-og-surface-2 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-og-accent pointer-coarse:min-h-11\",\n grouped && \"pl-3\",\n active &&\n \"bg-og-accent-soft text-og-fg before:absolute before:inset-y-1 before:left-0 before:w-0.5 before:rounded-r-full before:bg-og-accent\",\n )}\n >\n <span\n data-contrast-audited\n className={cn(\"w-3 shrink-0 text-center font-og-mono text-og-xs\", STATUS_TINT[file.status])}\n >\n {STATUS_LETTER[file.status]}\n </span>\n <span className=\"min-w-0 flex-1 truncate\">{shown}</span>\n <span className=\"ml-auto flex shrink-0 items-center gap-1 pl-1 font-og-mono text-og-xs\">\n <span data-contrast-audited className=\"text-og-status-idle\">\n +{file.additions}\n </span>\n <span data-contrast-audited className=\"text-og-status-failed\">\n −{file.deletions}\n </span>\n </span>\n </button>\n );\n}\n\n/** A windowed section wrapper. Absolutely positioned at `top`; a ResizeObserver\n * reports its real height back so the layout refines as Pierre's async Shiki\n * render grows (else short estimates would overlap sections). */\nfunction MeasuredSection({\n index,\n top,\n onMeasure,\n children,\n}: {\n index: number;\n top: number;\n onMeasure: (index: number, height: number) => void;\n children: ReactNode;\n}) {\n const ref = useRef<HTMLDivElement>(null);\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n const report = () => onMeasure(index, el.offsetHeight);\n report();\n const ro = typeof ResizeObserver !== \"undefined\" ? new ResizeObserver(report) : null;\n ro?.observe(el);\n return () => ro?.disconnect();\n }, [index, onMeasure]);\n return (\n <div\n ref={ref}\n data-diff-section\n data-diff-index={index}\n style={{ position: \"absolute\", top, left: 0, right: 0 }}\n >\n {children}\n </div>\n );\n}\n\nfunction DiffSection({\n file,\n layout,\n themeType,\n onOpenFile,\n}: {\n file: GitFileDiff;\n layout: \"unified\" | \"split\";\n themeType: \"dark\" | \"light\";\n onOpenFile?: ((path: string) => void) | undefined;\n}) {\n // The guard files (binary / over-cap) get a minimal header + \"open live\" body\n // since Pierre has nothing to render; real diffs use Pierre's own sticky file\n // header (one header — no redundant chrome).\n if (isGuarded(file)) {\n const renamed = file.oldPath && file.oldPath !== file.path;\n return (\n <section className=\"border-b border-og-border pb-1\">\n <header className=\"flex items-center justify-between gap-2 bg-og-surface-1 px-3 py-1.5 text-og-sm\">\n <span className=\"min-w-0 truncate font-og-mono text-og-xs\">\n {renamed ? `${file.oldPath} → ${file.path}` : file.path}\n </span>\n <span className=\"flex shrink-0 items-center gap-2 font-og-mono text-og-xs\">\n <span className=\"text-og-status-idle\">+{file.additions}</span>\n <span className=\"text-og-status-failed\">−{file.deletions}</span>\n </span>\n </header>\n <GuardBody file={file} {...(onOpenFile ? { onOpenFile } : {})} />\n </section>\n );\n }\n return (\n <section data-pierre-section className=\"border-b border-og-border pb-2\">\n <PierreDiff diff={[file]} layout={layout} themeType={themeType} className=\"px-1\" />\n </section>\n );\n}\n\n/** The per-file guard: a binary file or an over-cap diff opens live rather than\n * inlining a body we don't (fully) have. */\nfunction GuardBody({\n file,\n onOpenFile,\n}: {\n file: GitFileDiff;\n onOpenFile?: ((path: string) => void) | undefined;\n}) {\n const t = useOpenGeniText();\n const reason = file.isBinary\n ? t(\"workbenchChanges.binaryFile\")\n : t(\"workbenchChanges.diffTooLargeToShow\");\n return (\n <div className=\"flex flex-wrap items-center gap-2 px-3 py-3 text-og-sm text-og-fg-subtle\">\n <FileWarningIcon className=\"size-3.5 shrink-0\" aria-hidden />\n <span className=\"min-w-0 flex-1\">{reason}.</span>\n {onOpenFile ? (\n <button\n type=\"button\"\n onClick={() => onOpenFile(file.path)}\n className=\"inline-flex min-h-8 shrink-0 items-center gap-1.5 rounded-og-sm border border-og-border px-2 py-1 text-og-xs font-medium text-og-fg-muted transition-colors hover:border-og-border-strong hover:bg-og-surface-2 hover:text-og-fg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-og-accent pointer-coarse:min-h-11\"\n >\n {t(\"workbenchChanges.openInFiles\")}\n <ArrowUpRightIcon className=\"size-3.5\" aria-hidden />\n </button>\n ) : null}\n </div>\n );\n}\n\nfunction LayoutToggle({\n layout,\n onChange,\n}: {\n layout: \"unified\" | \"split\";\n onChange: (next: \"unified\" | \"split\") => void;\n}) {\n return (\n <div className=\"inline-flex items-center rounded-og-sm border border-og-border p-0.5\">\n {([\"unified\", \"split\"] as const).map((value) => (\n <button\n key={value}\n type=\"button\"\n onClick={() => onChange(value)}\n className={cn(\n \"min-h-7 rounded-og-xs px-1.5 py-0.5 text-og-xs capitalize focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-og-accent max-[1023px]:min-w-11 pointer-coarse:min-h-11 pointer-coarse:min-w-11\",\n layout === value\n ? \"bg-og-accent-soft text-og-fg\"\n : \"text-og-fg-subtle hover:text-og-fg\",\n )}\n >\n {value}\n </button>\n ))}\n </div>\n );\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\n\n/* ----------------------------------------------------------------------------\n Windowed sections — variable-height file-section virtualization.\n\n The Changes tab stacks N file diffs in one scroll pane. Mounting N Shiki\n highlighters (Pierre's `PatchDiff`) at once is the exact wart this replaces,\n so we mount only the sections inside the visible window ± overscan and reserve\n the rest as empty space (D2).\n\n Why NOT `virtua` here (unlike the file tree/rail): Pierre renders each diff in\n a shadow DOM with its own internal overflow/virtualization, so an outer\n measuring virtualizer can read a collapsed or fixed height and lay sections\n out wrong (known layout risk). This hook windows by mounting/unmounting whole\n file sections off a scroll offset and a per-section height ESTIMATE (refined\n by measurement when a real browser provides it), which never depends on\n Pierre reporting its own height — and the math is pure + deterministic, so\n D2 is provable in both happy-dom (drive scrollTop/clientHeight) and a real\n browser (Playwright, the verification-matrix path).\n -------------------------------------------------------------------------- */\n\nexport type WindowRange = {\n /** First mounted index (inclusive). */\n start: number;\n /** One past the last mounted index (exclusive). */\n end: number;\n};\n\n/**\n * Pure windowing math: given each section's height (px), the scroll offset, the\n * viewport height, and an overscan count, return the `[start, end)` index window\n * to mount. Robust to a zero viewport (a headless/pre-layout pass) — it then\n * mounts a small overscan window anchored at the item under `scrollTop` rather\n * than the whole list.\n */\nexport function computeWindowRange(\n heights: readonly number[],\n scrollTop: number,\n viewport: number,\n overscan: number,\n): WindowRange {\n const n = heights.length;\n if (n === 0) return { start: 0, end: 0 };\n const top = Math.max(scrollTop, 0);\n const bottom = top + Math.max(viewport, 0);\n\n let firstVisible = -1;\n let lastVisible = -1;\n let acc = 0;\n let anchor = 0; // the item containing `scrollTop` — the zero-viewport fallback\n for (let i = 0; i < n; i++) {\n const secTop = acc;\n const secBottom = secTop + Math.max(heights[i] ?? 0, 0);\n if (secTop <= top) anchor = i;\n // A section is visible when it overlaps [top, bottom); with viewport 0 the\n // half-open interval is empty, so nothing matches and we fall back to anchor.\n if (secBottom > top && secTop < bottom) {\n if (firstVisible === -1) firstVisible = i;\n lastVisible = i;\n }\n acc = secBottom;\n }\n\n if (firstVisible === -1) {\n firstVisible = anchor;\n lastVisible = anchor;\n }\n\n return {\n start: Math.max(0, firstVisible - overscan),\n end: Math.min(n, lastVisible + 1 + overscan),\n };\n}\n\nexport type WindowedSections = {\n /** Attach to the scroll container. */\n scrollRef: React.RefObject<HTMLDivElement | null>;\n /** The mounted window `[start, end)`. */\n range: WindowRange;\n /** Prefix offsets: `offsets[i]` is the top px of section `i`; `offsets[count]`\n * is the total content height. */\n offsets: number[];\n /** Total content height (px) — set on the spacer so scroll length is stable. */\n totalHeight: number;\n /** Report a MOUNTED section's real height (px) so the layout refines as async\n * content — e.g. Pierre's Shiki render — grows. Drive it from a ResizeObserver;\n * a zero/idle value is ignored so a headless pass keeps the estimate. */\n measure: (index: number, height: number) => void;\n /** Scroll section `index` to the top of the pane (the rail-jump). */\n scrollToIndex: (index: number) => void;\n};\n\n/**\n * Variable-height section windowing over a scroll container. Seeds every section\n * to `estimateHeight(i)`, mounts only `range`, and refines heights from real\n * measurements (a no-op in a zero-layout headless pass, which keeps the estimate\n * — deterministic for tests). Pass a STABLE `estimateHeight` (wrap in useCallback).\n */\nexport function useWindowedSections(opts: {\n count: number;\n estimateHeight: (index: number) => number;\n overscan?: number | undefined;\n}): WindowedSections {\n const { count, estimateHeight, overscan = 3 } = opts;\n const scrollRef = useRef<HTMLDivElement | null>(null);\n\n const [heights, setHeights] = useState<number[]>(() =>\n Array.from({ length: count }, (_, i) => estimateHeight(i)),\n );\n\n // Re-seed when the estimate function changes as well as when the count changes.\n // A replacement diff can contain the same number of files but radically\n // different section sizes; retaining measurements by index would then place\n // every unvisited section at an offset belonging to the previous diff.\n useEffect(() => {\n setHeights((prev) => {\n const next = Array.from({ length: count }, (_, i) => estimateHeight(i));\n return prev.length === next.length && prev.every((height, index) => height === next[index])\n ? prev\n : next;\n });\n }, [count, estimateHeight]);\n\n const heightsRef = useRef(heights);\n heightsRef.current = heights;\n\n const [range, setRange] = useState<WindowRange>(() => ({\n start: 0,\n end: Math.min(count, overscan + 1),\n }));\n\n const recompute = useCallback(() => {\n const el = scrollRef.current;\n if (!el) return;\n const next = computeWindowRange(heightsRef.current, el.scrollTop, el.clientHeight, overscan);\n setRange((prev) => (prev.start === next.start && prev.end === next.end ? prev : next));\n }, [overscan]);\n\n // Recompute on scroll (rAF-coalesced) and on container resize.\n useEffect(() => {\n const el = scrollRef.current;\n if (!el) return;\n let raf = 0;\n const onScroll = () => {\n if (raf) return;\n raf =\n typeof requestAnimationFrame === \"function\"\n ? requestAnimationFrame(() => {\n raf = 0;\n recompute();\n })\n : (recompute(), 0);\n };\n el.addEventListener(\"scroll\", onScroll, { passive: true });\n const ro = typeof ResizeObserver !== \"undefined\" ? new ResizeObserver(() => recompute()) : null;\n ro?.observe(el);\n recompute();\n return () => {\n el.removeEventListener(\"scroll\", onScroll);\n ro?.disconnect();\n if (raf && typeof cancelAnimationFrame === \"function\") cancelAnimationFrame(raf);\n };\n }, [recompute, count]);\n\n const measure = useCallback((index: number, height: number) => {\n if (height <= 0) return; // zero-layout pass — keep the estimate\n setHeights((prev) => {\n if (Math.abs((prev[index] ?? 0) - height) < 1) return prev;\n const next = prev.slice();\n next[index] = height;\n return next;\n });\n }, []);\n\n const offsets = useMemo(() => {\n const out = new Array<number>(count + 1);\n out[0] = 0;\n for (let i = 0; i < count; i++) out[i + 1] = (out[i] ?? 0) + Math.max(heights[i] ?? 0, 0);\n return out;\n }, [heights, count]);\n\n // A measured height can shift the window (e.g. estimates were short) — keep the\n // mounted set in sync without waiting for the next scroll.\n useEffect(() => {\n recompute();\n }, [offsets, recompute]);\n\n const scrollToIndex = useCallback(\n (index: number) => {\n const el = scrollRef.current;\n if (!el) return;\n const clamped = Math.max(0, Math.min(count - 1, index));\n el.scrollTop = offsets[clamped] ?? 0;\n },\n [offsets, count],\n );\n\n return {\n scrollRef,\n range,\n offsets,\n totalHeight: offsets[count] ?? 0,\n measure,\n scrollToIndex,\n };\n}\n","import type { GitFileDiff } from \"@opengeni/sdk\";\nimport { type ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { PierreDiff } from \"./pierre-diff\";\nimport { useOpenGeniText } from \"../messages/runtime\";\n\n/**\n * @deprecated Use {@link PierreDiff} directly. Retained only as a thin,\n * back-compat alias that renders the Pierre (Shiki) renderer with a plain-text\n * degrade. The old hand-rolled hunk renderer was removed in Workbench v2 — the\n * workbench keeps exactly ONE diff renderer. This alias is removed next major.\n */\nexport type DiffTheme = {\n addBackground?: string;\n delBackground?: string;\n contextBackground?: string;\n metaForeground?: string;\n};\n\n/**\n * @deprecated Use {@link PierreDiff}. `theme`/`onSelectFile`/`emptyState` from the\n * removed hand-rolled renderer are accepted for source compatibility and ignored;\n * `fallback` still overrides the plain-text degrade.\n */\nexport type DiffViewProps = {\n diff: GitFileDiff[];\n fallback?: ReactNode | undefined;\n layout?: \"unified\" | \"split\" | undefined;\n themeType?: \"dark\" | \"light\" | undefined;\n /** @deprecated line-background theming was part of the removed renderer. */\n theme?: DiffTheme | undefined;\n /** @deprecated the alias no longer renders a clickable file header. */\n onSelectFile?: ((path: string) => void) | undefined;\n isRepo?: boolean | undefined;\n emptyState?: ReactNode | undefined;\n className?: string | undefined;\n};\n\n/**\n * @deprecated Use {@link PierreDiff} directly. Thin alias: renders `PierreDiff`\n * (Shiki-highlighted, unified/split) with a plain-text fallback for a host\n * without `@pierre/diffs`. Removed next major.\n */\nexport function DiffView({\n diff,\n fallback,\n layout = \"unified\",\n themeType,\n isRepo = true,\n emptyState,\n className,\n}: DiffViewProps) {\n const t = useOpenGeniText();\n if (diff.length === 0) {\n return (\n <div className={cn(\"p-3 text-og-sm text-og-fg-subtle\", className)}>\n {emptyState ?? (isRepo ? t(\"diffView.noChanges\") : t(\"diffView.noRepositoryMounted\"))}\n </div>\n );\n }\n return (\n <PierreDiff\n diff={diff}\n layout={layout}\n themeType={themeType}\n {...(fallback !== undefined ? { fallback } : {})}\n className={className}\n />\n );\n}\n","// The sandbox workbench — the SDK-embeddable dock \"brain\" (Workbench v2, M4).\n//\n// This module owns the whole session workspace surface an embedder mounts:\n// Changes — review-first git: turn-end capture (cold) or live diff (warm)\n// Files — tree + inline editor (capture-backed cold, live warm)\n// Terminal — interactive xterm wired to the box PTY (Channel-A projection)\n// Browser — workspace-wide BrowserSessions, tabs, live frames, and input\n// Computer — workspace ComputerSessions: native targets, frames, and input\n// plus a machine-state chip in the dock header (the one truthful live/waking/\n// offline indicator) and any host-injected extra tabs (Run/Debug in apps/web).\n//\n// It is decoupled from the host app: the client comes from <OpenGeniProvider>\n// (never an app context), notifications flow through an optional `onNotify` prop\n// (no `sonner` import), and every surface renders with package primitives + og\n// tokens only. `apps/web` consumes this through the exact public surface an\n// external embedder uses — that is criterion F1.\nimport {\n lazy,\n type ReactNode,\n Suspense,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type { SessionEvent } from \"@opengeni/sdk\";\nimport type { InteractionPlacement } from \"@opengeni/sdk/interaction\";\nimport {\n CircleCheckIcon,\n CpuIcon,\n FileCode2Icon,\n GitCompareArrowsIcon,\n Globe2Icon,\n LoaderCircleIcon,\n MonitorIcon,\n RefreshCwIcon,\n SquareTerminalIcon,\n TriangleAlertIcon,\n} from \"lucide-react\";\n\nimport { type ClientOverride, useOpenGeni } from \"../provider\";\nimport { cn } from \"../lib/cn\";\nimport { xtermThemeFromTokens } from \"../lib/xterm-theme\";\nimport { sandboxAcceptsLiveIo } from \"../lib/sandbox-liveness\";\nimport type { BrowserFrameWebSocketFactory } from \"../hooks/use-browser-frame-stream\";\nimport type { ComputerFrameWebSocketFactory } from \"../hooks/use-computer-frame-stream\";\nimport type { FileNodeVisibilityPredicate } from \"../file-node-visibility\";\nimport { useSessionCapabilities } from \"../hooks/use-session-capabilities\";\nimport { useSandboxFiles } from \"../hooks/use-sandbox-files\";\nimport {\n useSandboxGit,\n type SandboxGitComparison,\n type UseSandboxGitResult,\n} from \"../hooks/use-sandbox-git\";\nimport { useSandboxTerminal } from \"../hooks/use-sandbox-terminal\";\nimport { useWorkspaceCapture } from \"../hooks/use-workspace-capture\";\nimport { useMachineChip, type MachineChip } from \"../hooks/use-machine-chip\";\nimport { MACHINES_SESSION_POLL_MS, useMachines } from \"../hooks/use-machines\";\nimport type { MachineView } from \"../types/machines\";\nimport type { SandboxFilesProps } from \"./sandbox-files\";\nimport { WorkbenchChanges } from \"./workbench-changes\";\nimport { SandboxTerminal, type XtermTheme } from \"./sandbox-terminal\";\nimport { WorkspaceDock, type WorkspaceDockProps, type WorkspaceTab } from \"./workspace-dock\";\nimport { useOpenGeniText } from \"../messages/runtime\";\n\nconst LazySandboxFiles = lazy(() =>\n import(\"./sandbox-files\")\n .then(({ SandboxFiles }) => ({ default: SandboxFiles }))\n // A host may already have attempted stale-deployment recovery. Keep an\n // optional chunk failure inside Files rather than unmounting the chat.\n .catch(() => ({ default: FilesLoadFailed })),\n);\n\nfunction FilesLoadFailed() {\n const t = useOpenGeniText();\n return (\n <CenteredState tone=\"danger\" icon={<TriangleAlertIcon className=\"size-5\" aria-hidden />}>\n <p className=\"text-og-sm font-medium text-og-fg\">\n {t(\"sandboxWorkspace.filesCouldNotBeLoaded\")}\n </p>\n <DockActionButton onClick={() => window.location.reload()}>\n <RefreshCwIcon className=\"size-3\" aria-hidden />\n {t(\"sandboxWorkspace.reload\")}\n </DockActionButton>\n </CenteredState>\n );\n}\n\nfunction FilesTabBody(props: SandboxFilesProps) {\n return (\n <Suspense fallback={<WorkbenchSurfaceLoading name=\"Files\" />}>\n <LazySandboxFiles {...props} />\n </Suspense>\n );\n}\n\nconst LazyBrowserViewer = lazy(async () => {\n const { BrowserViewer } = await import(\"./browser-viewer\");\n return { default: BrowserViewer };\n});\n\nconst LazyComputerViewer = lazy(async () => {\n const { ComputerViewer } = await import(\"./computer-viewer\");\n return { default: ComputerViewer };\n});\n\n/** A host-routed notification (replaces the app-only `sonner` toast coupling). */\nexport type WorkspaceNotification = { kind: \"error\" | \"info\"; message: string };\n\n/** The workbench's canonical tab ids (a host injects extras around these). */\nexport const WORKBENCH_TAB_CHANGES = \"changes\";\nexport const WORKBENCH_TAB_FILES = \"files\";\nexport const WORKBENCH_TAB_TERMINAL = \"terminal\";\nexport const WORKBENCH_TAB_BROWSER = \"browser\";\nexport const WORKBENCH_TAB_DESKTOP = \"desktop\";\n\n/**\n * The built-in workbench surfaces in their canonical display order. Hosts can\n * pass a subset through `surfaces`; omission preserves the complete standalone\n * workbench.\n */\nexport const WORKBENCH_SURFACES = [\n WORKBENCH_TAB_CHANGES,\n WORKBENCH_TAB_FILES,\n WORKBENCH_TAB_TERMINAL,\n WORKBENCH_TAB_BROWSER,\n WORKBENCH_TAB_DESKTOP,\n] as const;\n\nexport type SandboxWorkspaceSurface = (typeof WORKBENCH_SURFACES)[number];\n\nfunction isWorkbenchSurface(value: string): value is SandboxWorkspaceSurface {\n return (WORKBENCH_SURFACES as readonly string[]).includes(value);\n}\n\nfunction isCanonicalAbsoluteSandboxPath(value: string | null | undefined): boolean {\n if (!value) return false;\n const portable = value.replaceAll(\"\\\\\", \"/\");\n return portable.startsWith(\"/\") || /^[A-Za-z]:\\//u.test(portable);\n}\n\nfunction sourceDrivenDefaultTab(\n hasChanges: boolean,\n changesEnabled: boolean,\n filesEnabled: boolean,\n): string | null {\n if (hasChanges && changesEnabled) return WORKBENCH_TAB_CHANGES;\n if (filesEnabled) return WORKBENCH_TAB_FILES;\n if (changesEnabled) return WORKBENCH_TAB_CHANGES;\n return null;\n}\n\nfunction WorkbenchSurfaceLoading({ name }: { name: \"Files\" | \"Browser\" | \"Desktop\" }) {\n const t = useOpenGeniText();\n return (\n <CenteredState\n icon={\n <LoaderCircleIcon className=\"size-5 animate-spin motion-reduce:animate-none\" aria-hidden />\n }\n >\n <p className=\"text-og-sm font-medium text-og-fg\">\n {t(\"sandboxWorkspace.openingName\", { name })}\n </p>\n </CenteredState>\n );\n}\n\n/**\n * Decide a workspace tab from an already-local event log: the newest\n * `workspace.revision.captured` announce carries the change surface stats, so\n * \"changes exist → Changes, else Files\" needs zero machine round-trips. A host\n * `override` (e.g. a landing \"run\" tab) wins when supplied.\n *\n * `<SandboxWorkspace>` uses this only as an optional early hint after its own\n * capture GET reports no durable capture. A pure embedder needs no events-at-mount\n * contract: it falls through to authoritative live Git instead.\n */\nexport function initialWorkspaceTab(\n events: SessionEvent[] | undefined,\n override?: string | null,\n): string {\n if (override) return override;\n let bestSeq = -1;\n let bestFileCount = 0;\n for (const event of events ?? []) {\n if (event.type !== \"workspace.revision.captured\") continue;\n if (event.sequence <= bestSeq) continue;\n const stats = (event.payload as { stats?: { fileCount?: number } } | null)?.stats;\n bestSeq = event.sequence;\n bestFileCount = typeof stats?.fileCount === \"number\" ? stats.fileCount : 0;\n }\n if (bestFileCount > 0) return WORKBENCH_TAB_CHANGES;\n\n let latestGitSeq = -1;\n let committedOnly = false;\n for (const event of events ?? []) {\n if (event.type !== \"git.changed\" || event.sequence > bestSeq) continue;\n if (event.sequence <= latestGitSeq) continue;\n const payload = event.payload as { ahead?: number; reason?: string } | null;\n latestGitSeq = event.sequence;\n committedOnly =\n (typeof payload?.ahead === \"number\" && payload.ahead > 0) || payload?.reason === \"commit\";\n }\n return committedOnly ? WORKBENCH_TAB_CHANGES : WORKBENCH_TAB_FILES;\n}\n\n/**\n * Whether a lazy sandbox provision is in flight on this event stream: the latest\n * `sandbox.provision` operation event is a `.started` not yet closed by a\n * `.completed`/`.failed`. Package-local twin of apps/web's events helper so the\n * dock brain can wake its on-demand capability negotiation when the box warms.\n */\nfunction sandboxProvisionInFlight(events: SessionEvent[]): boolean {\n let inFlight = false;\n for (const event of events) {\n if (\n event.type !== \"sandbox.operation.started\" &&\n event.type !== \"sandbox.operation.completed\" &&\n event.type !== \"sandbox.operation.failed\"\n ) {\n continue;\n }\n const payload = event.payload;\n const name =\n payload && typeof payload === \"object\" && !Array.isArray(payload)\n ? (payload as Record<string, unknown>).name\n : null;\n if (name !== \"sandbox.provision\") continue;\n if (event.type === \"sandbox.operation.started\") {\n inFlight = true;\n } else {\n inFlight = false;\n }\n }\n return inFlight;\n}\n\n/**\n * Whether this session currently owns an admitted agent turn. Automatic live\n * Files/Git reads pause across the whole turn: command boundaries are not a safe\n * gap because the next tool can dispatch before a remote provider read releases\n * its sandbox holder. Existing/captured content remains usable, and the terminal\n * turn event resumes one authoritative refresh.\n */\nfunction workspaceTurnInFlight(events: SessionEvent[]): boolean {\n const activeTurnIds = new Set<string>();\n let anonymousTurnInFlight = false;\n let sessionOwnsWorkspace = false;\n for (const event of events) {\n if (event.type === \"session.status.changed\") {\n const status =\n event.payload && typeof event.payload === \"object\" && !Array.isArray(event.payload)\n ? (event.payload as Record<string, unknown>).status\n : null;\n sessionOwnsWorkspace = status === \"running\" || status === \"recovering\";\n continue;\n }\n if (event.type === \"turn.started\") {\n if (event.turnId) activeTurnIds.add(event.turnId);\n else anonymousTurnInFlight = true;\n continue;\n }\n if (\n event.type !== \"turn.completed\" &&\n event.type !== \"turn.failed\" &&\n event.type !== \"turn.cancelled\" &&\n event.type !== \"turn.superseded\"\n ) {\n continue;\n }\n if (event.turnId) activeTurnIds.delete(event.turnId);\n else anonymousTurnInFlight = false;\n }\n // The retained event window preserves the latest status even after a very\n // long turn has evicted its original turn.started event.\n return sessionOwnsWorkspace || anonymousTurnInFlight || activeTurnIds.size > 0;\n}\n\nexport type WorkspaceMachine = {\n /** Whether at least one built-in workbench surface is enabled. */\n enabled: boolean;\n /** The derived live/waking/sleeping-or-offline chip model. */\n chip: MachineChip;\n /** The machine these surfaces are bound to (the Modal group box or a\n * self-hosted machine), or null while the fleet is still resolving. */\n activeMachine: MachineView | null;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n};\n\nexport type UseSandboxWorkspaceTabsOptions = ClientOverride & {\n sessionId: string;\n /** Live event log (usually `useSessionEvents().events`). */\n events: SessionEvent[];\n /**\n * Built-in surfaces this host wants to expose. Omit for all five. A disabled\n * surface is behaviorally dormant: its data hooks, warm intents, stream\n * attachment, and navigation callbacks are not activated.\n */\n surfaces?: readonly SandboxWorkspaceSurface[] | undefined;\n /**\n * Whether this viewer may read the workspace machine fleet\n * (`GET /machines`, permission `enrollments:read`). Defaults to true. Pass\n * false for a viewer without it: the dock then never requests the fleet and\n * the machine chip derives from the session's own capabilities alone.\n */\n machinesEnabled?: boolean | undefined;\n /** Override the source-driven default tab (e.g. a host landing tab id). When\n * omitted the workbench picks Changes-vs-Files from capture or live Git. */\n initialTab?: string | null | undefined;\n /** Actually selected dock tab. Inactive data surfaces retain cache but issue no live reads. */\n activeTab?: string | null | undefined;\n /** Whether the dock is visible. Hidden docks retain UI state but must not keep\n * expensive browser/computer media streams alive. */\n workspaceVisible?: boolean | undefined;\n /** Host-routed notifications (mutation errors, desktop-consent failures). The\n * package never imports a toast library — the host decides how to surface. */\n onNotify?: ((notification: WorkspaceNotification) => void) | undefined;\n /** Alternate frame transport for non-browser runtimes and deterministic tests. */\n browserWebSocketFactory?: BrowserFrameWebSocketFactory | undefined;\n /** Alternate Computer frame transport for non-browser runtimes and deterministic tests. */\n computerWebSocketFactory?: ComputerFrameWebSocketFactory | undefined;\n /** Host-owned setup page or store listing for attaching an existing Chrome profile. */\n browserExtensionSetupUrl?: string | undefined;\n /** File requested by a Changes guard. The Files surface defers the read until\n * the sandbox is live, then reveals this path. */\n requestedFilePath?: string | null | undefined;\n /** Unique identity for `requestedFilePath`, including repeated requests for the\n * same path. */\n requestedFileRequestId?: string | number | null | undefined;\n /** 1-based line to reveal after `requestedFilePath` opens. */\n requestedFileLine?: number | null | undefined;\n /** Route a guarded diff into the host's Files tab. */\n onOpenFile?: ((path: string) => void) | undefined;\n /** Restore and report navigation inside the built-in workbench surfaces. */\n initialFilePath?: string | null | undefined;\n onFilePathChange?: ((path: string | null) => void) | undefined;\n /** Presentation-only filter for Files tree nodes and selected-file viewing. */\n isFileNodeVisible?: FileNodeVisibilityPredicate | undefined;\n initialBrowserSessionId?: string | null | undefined;\n onBrowserSessionIdChange?: ((browserSessionId: string | null) => void) | undefined;\n initialComputerSessionId?: string | null | undefined;\n onComputerSessionIdChange?: ((computerSessionId: string | null) => void) | undefined;\n /** Navigate the host dock to one exact linked ComputerSession. */\n onOpenComputerSession?: ((computerSessionId: string) => void) | undefined;\n requestedComputerSessionId?: string | null | undefined;\n requestedComputerRequestId?: string | number | null | undefined;\n};\n\nexport type UseSandboxWorkspaceTabsResult = {\n /** Changes | Files | Terminal | Browser | Desktop (capability-gated where noted). */\n tabs: WorkspaceTab[];\n /** The source-driven default tab: Changes when the first authoritative capture\n * has changes, else Files (a host `initialTab` overrides). Choosing a tab\n * never performs hidden live workspace I/O.\n * null while that source resolves, or permanently when neither Changes nor\n * Files is enabled; the choice latches once. */\n defaultTab: string | null;\n /** The machine-state model for the dock-header chip. */\n machine: WorkspaceMachine;\n};\n\ntype SessionWarmIntents = {\n sessionId: string;\n warmTerminal: boolean;\n warmFiles: boolean;\n};\n\nfunction emptyWarmIntents(sessionId: string): SessionWarmIntents {\n return {\n sessionId,\n warmTerminal: false,\n warmFiles: false,\n };\n}\n\n/**\n * Build the workbench tabs + the machine-chip model for one session. This is the\n * dock \"brain\": capability negotiation, capture-backed cold reads, prewarm\n * flags, automatic desktop acknowledgment, and the xterm theme observer — all\n * package-local.\n */\nexport function useSandboxWorkspaceTabs(\n options: UseSandboxWorkspaceTabsOptions,\n): UseSandboxWorkspaceTabsResult {\n const t = useOpenGeniText();\n const { client, workspaceId, workspaceInteractionEvent } = useOpenGeni(options);\n const {\n sessionId,\n events,\n onNotify,\n browserWebSocketFactory,\n computerWebSocketFactory,\n browserExtensionSetupUrl,\n requestedFilePath,\n requestedFileRequestId,\n requestedFileLine,\n onOpenFile,\n initialFilePath,\n onFilePathChange,\n isFileNodeVisible,\n initialBrowserSessionId,\n onBrowserSessionIdChange,\n initialComputerSessionId,\n onComputerSessionIdChange,\n onOpenComputerSession,\n requestedComputerSessionId,\n requestedComputerRequestId,\n } = options;\n const initialTab = options.initialTab ?? null;\n const activeTab = options.activeTab ?? initialTab;\n const workspaceVisible = options.workspaceVisible ?? true;\n const machinesEnabled = options.machinesEnabled ?? true;\n const requestedSurfaces = options.surfaces ?? WORKBENCH_SURFACES;\n const surfaceSet = new Set<SandboxWorkspaceSurface>(requestedSurfaces);\n const changesEnabled = surfaceSet.has(WORKBENCH_TAB_CHANGES);\n const filesEnabled = surfaceSet.has(WORKBENCH_TAB_FILES);\n const terminalEnabled = surfaceSet.has(WORKBENCH_TAB_TERMINAL);\n const browserEnabled = surfaceSet.has(WORKBENCH_TAB_BROWSER);\n const desktopEnabled = surfaceSet.has(WORKBENCH_TAB_DESKTOP);\n const createLinkedComputer = useCallback(\n async (name: string, placement?: InteractionPlacement) => {\n const response = await client.createComputerSession(workspaceId, {\n operationId: crypto.randomUUID(),\n sessionId,\n name,\n ...(placement ? { placement } : {}),\n });\n if (response.operation.state !== \"completed\" || response.session.lifecycle !== \"active\") {\n throw new Error(\n response.operation.error?.message ?? t(\"sandboxWorkspace.theDesktopCouldNotBe\"),\n );\n }\n return {\n id: response.session.id,\n placement: response.session.placement,\n };\n },\n [client, sessionId, workspaceId, t],\n );\n const workspaceDataEnabled = changesEnabled || filesEnabled;\n const machineSurfaceEnabled = workspaceDataEnabled || terminalEnabled || desktopEnabled;\n // Do not speculatively activate both remote workspace surfaces while the dock\n // is still resolving its selected tab. Modal calls cannot be cancelled after\n // dispatch, so that transient state otherwise creates an aborted duplicate\n // batch immediately before the real selected-tab request.\n const resolvedActiveTab = activeTab ?? initialTab;\n const changesActive = resolvedActiveTab === WORKBENCH_TAB_CHANGES;\n const filesActive = resolvedActiveTab === WORKBENCH_TAB_FILES;\n const turnInFlight = workspaceTurnInFlight(events);\n const surfaceIdentity = WORKBENCH_SURFACES.filter((surface) => surfaceSet.has(surface)).join(\",\");\n\n // The two box-warming INTENTS, each off by default and each\n // flipped true by a genuine user action (never on mount, never on a passive\n // capture glance): terminal engagement (`onActivate`) and a deliberate\n // live-file open/edit in Files. Browsing capture-served\n // Changes/Files warms nothing — that is the whole point of Refinement 1.\n const [storedWarmIntents, setStoredWarmIntents] = useState<SessionWarmIntents>(() =>\n emptyWarmIntents(sessionId),\n );\n const warmIntents =\n storedWarmIntents.sessionId === sessionId ? storedWarmIntents : emptyWarmIntents(sessionId);\n const { warmTerminal, warmFiles } = warmIntents;\n // A host-requested file is itself explicit live-file intent. Derive the wake\n // directly from the request instead of relying on a follow-up effect to copy\n // it into local state; otherwise a missing or delayed effect leaves the file\n // waiting for a sandbox that this hook never asks to start.\n const filesWarmRequested = warmFiles || Boolean(requestedFilePath);\n const requestWarmIntent = useCallback(\n (intent: Exclude<keyof SessionWarmIntents, \"sessionId\">) => {\n setStoredWarmIntents((previous) => {\n const current = previous.sessionId === sessionId ? previous : emptyWarmIntents(sessionId);\n return current[intent] ? current : { ...current, [intent]: true };\n });\n },\n [sessionId],\n );\n // The session's machine fleet + the active-sandbox pointer. Drives the header\n // chip (which machine + its connection state). Shares the session list poll.\n const machines = useMachines({\n workspaceId,\n sessionId,\n pollIntervalMs: MACHINES_SESSION_POLL_MS,\n enabled: machineSurfaceEnabled && machinesEnabled,\n });\n const activeMachine: MachineView | null =\n machines.machines.find((m) => m.sandboxId === machines.activeSandboxId) ??\n machines.machines.find((m) => m.active) ??\n null;\n\n const caps = useSessionCapabilities(sessionId, {\n events,\n enabled: machineSurfaceEnabled,\n attachDesktop: false,\n attachTerminal: terminalEnabled && warmTerminal,\n // Explicit live-file intent only — NOT \"the Files tab is open\". A cold edit\n // or guarded-file open wakes the box; a glance at the tree/diff does not.\n attachFiles: workspaceDataEnabled && filesWarmRequested,\n });\n const capabilities = caps.capabilities;\n const liveness = capabilities?.liveness;\n // A missing capability document is not evidence that the sandbox is live.\n // Pass explicit null to live-I/O hooks so fast capture/event hydration cannot\n // exploit their legacy \"liveness omitted\" compatibility path while negotiation\n // is still pending.\n const liveIoLiveness = liveness ?? null;\n const fileSystemOn = capabilities?.FileSystem.available ?? false;\n const fileSystemRoute = capabilities\n ? { epoch: capabilities.leaseEpoch, root: capabilities.FileSystem.root }\n : undefined;\n // The FS is writable only when it's live AND not read-only. A self-hosted box\n // that's offline (or any read-only advertisement) or a capture-served cold tree\n // must not offer create/rename/delete/edit affordances — you cannot mutate a\n // machine you can't reach (C3). Tree-structure ops need a warm\n // writable box; content editing on a cold CLOUD box is the wake-on-edit path in\n // the editor, not tree mutation.\n const fsReadOnly = capabilities?.FileSystem.readOnly ?? false;\n // Mutations are live-only. A capture is a review artifact, never a writable\n // surrogate for a sleeping machine; the user must deliberately open the live\n // workspace before create/rename/delete/edit controls appear.\n const filesEditable = fileSystemOn && !fsReadOnly && sandboxAcceptsLiveIo(liveness);\n const gitOn = capabilities?.Git.available ?? false;\n const terminalOn = terminalEnabled && (capabilities?.Terminal.transport ?? null) !== null;\n // A descriptor-only pty-ws cell intentionally has no short-lived URL until\n // terminal intent acquires one. Do not mistake that grant boundary for a\n // legacy HTTP PTY and eagerly open a second terminal. The fallback exists only\n // for a genuinely firehose-transport backend with no typed degradation.\n const ptyCapable =\n warmTerminal &&\n (capabilities?.Terminal.ptyCapable ?? false) &&\n capabilities?.Terminal.transport === \"sse-events\" &&\n capabilities?.Terminal.reason === null;\n // The terminal reads its own history (PTY and agent command output) the\n // first time its tab shows in a visible dock, and keeps it for the session.\n const terminalShown =\n terminalOn && workspaceVisible && resolvedActiveTab === WORKBENCH_TAB_TERMINAL;\n const [terminalOpenedSession, setTerminalOpenedSession] = useState<string | null>(null);\n useEffect(() => {\n if (terminalShown) setTerminalOpenedSession(sessionId);\n }, [terminalShown, sessionId]);\n const terminal = useSandboxTerminal(sessionId, {\n events: terminalEnabled ? events : [],\n interactive: terminalEnabled && ptyCapable,\n liveness,\n history: terminalShown || terminalOpenedSession === sessionId,\n });\n // Lazy provisioning (#315) creates the box mid-turn on the first sandbox tool\n // call, emitting sandbox.provision started→completed/failed on the live stream.\n // The on-demand resting hook rests without polling, so when the box warms the\n // cold capability doc never refreshes on its own — Terminal/Desktop would stay\n // hidden. Watch the provision edge and renegotiate when it settles so the\n // freshly-warm box's surfaces fill in.\n const provisioning = sandboxProvisionInFlight(events);\n const renegotiate = caps.renegotiate;\n const provisioningRef = useRef({ sessionId, provisioning });\n useEffect(() => {\n const previous = provisioningRef.current;\n if (previous.sessionId === sessionId && previous.provisioning && !provisioning) {\n renegotiate();\n }\n provisioningRef.current = { sessionId, provisioning };\n }, [sessionId, provisioning, renegotiate]);\n\n // BrowserSession and ComputerSession lifecycles use the same placement lease\n // as files/terminal/desktop, but are workspace resources rather than session\n // events. Re-read the capability document on their canonical workspace\n // invalidation so the one machine chip cannot remain \"Offline\" beside a live\n // browser/computer (or remain \"Live\" after the final interaction holder ends).\n // This is a read-only negotiation: it never acquires a holder or wakes a box.\n useEffect(() => {\n if (workspaceInteractionEvent?.workspaceId !== workspaceId) return;\n renegotiate();\n }, [workspaceId, workspaceInteractionEvent, renegotiate]);\n\n // The cold-paint data source: the latest turn-end capture, fetched with a single\n // api round-trip on mount (no machine). Feeds the Files tree + the Changes/Git\n // diff immediately; a warm box reconciles live without discarding the capture\n // when that provider read is temporarily unavailable.\n const captureState = useWorkspaceCapture(sessionId, {\n events,\n enabled: workspaceDataEnabled,\n });\n const captureAvailable = captureState.available;\n const liveWorkspaceExpected = sandboxAcceptsLiveIo(liveness);\n // Capability negotiation and capture resolution are independent requests. A\n // cold capability document can win that race by a few milliseconds; enabling\n // the leaf hooks in that window would make them interpret `capture: null` as a\n // real miss and issue Channel-A reads, waking the very box the capture exists\n // to avoid. Wait until the capture request has conclusively resolved. A warm\n // workspace never waits on this server-side snapshot.\n const capturePending =\n !liveWorkspaceExpected && (captureState.fileCount === null || captureState.loading);\n const repoPaths = useMemo(() => {\n const advertised = capabilities?.Git.repos ?? [];\n if (advertised.length > 0) return advertised;\n return captureState.capture?.repos.map((repo) => repo.root) ?? [];\n }, [capabilities?.Git.repos, captureState.capture]);\n const files = useSandboxFiles(sessionId, {\n events,\n // No passive Channel-A reads while cold, even after a conclusive capture\n // miss. A missing capture gets an explicit \"Open live workspace\" gate.\n enabled: filesEnabled && (captureAvailable || (fileSystemOn && liveWorkspaceExpected)),\n // A cold sandbox can become warm while the first agent command still owns\n // startup. Do not race that command with an automatic Files read. Keeping\n // this fence at turn scope also avoids unsafe millisecond gaps between\n // sequential tool calls; rendered state and explicit user actions remain.\n active: filesActive && !turnInFlight,\n // A deliberate canonical absolute-path open browses in the selected target's\n // advertised namespace, so the authoritative tree and link share exact paths.\n ...(isCanonicalAbsoluteSandboxPath(requestedFilePath) && capabilities?.FileSystem.root\n ? { rootPath: capabilities.FileSystem.root }\n : {}),\n ...(fileSystemRoute ? { route: fileSystemRoute } : {}),\n repoPaths,\n liveness: liveIoLiveness,\n capture: captureState.capture,\n // A reverted optimistic mutation (e.g. a 409 rename collision) surfaces as a\n // host notification — the tree silently rolls back, the user sees why.\n onMutationError: (error, op) =>\n onNotify?.({\n kind: \"error\",\n message: t(\"sandboxWorkspace.couldNotOpMessage\", { op, message: error.message }),\n }),\n });\n const [storedChangesComparison, setStoredChangesComparison] = useState<{\n sessionId: string;\n value: SandboxGitComparison;\n } | null>(null);\n const captureSupportsBranch =\n captureState.capture !== null &&\n captureState.capture.repos.length > 0 &&\n captureState.capture.repos.every((repo) => repo.branchDiff !== undefined);\n // A sleeping workspace can truthfully serve only the captured working-tree\n // comparison. A live workspace defaults to the branch comparison so committed\n // agent work remains visible. Explicit user selection is scoped per session.\n const changesComparison =\n storedChangesComparison?.sessionId === sessionId\n ? storedChangesComparison.value\n : liveWorkspaceExpected || captureSupportsBranch\n ? \"branch\"\n : \"working\";\n const setChangesComparison = useCallback(\n (value: SandboxGitComparison) => setStoredChangesComparison({ sessionId, value }),\n [sessionId],\n );\n const git = useSandboxGit(sessionId, {\n events,\n enabled:\n changesComparison === \"working\"\n ? workspaceDataEnabled && (captureAvailable || (gitOn && liveWorkspaceExpected))\n : changesComparison === \"branch\"\n ? workspaceDataEnabled && (captureSupportsBranch || (gitOn && liveWorkspaceExpected))\n : workspaceDataEnabled && gitOn && liveWorkspaceExpected,\n // Live Git belongs to the visible Changes surface. In particular, do not\n // turn an unresolved/default tab into a hidden provider read: that races the\n // agent's own sandbox commands and used to refresh after every tool output\n // even while Files was visibly selected.\n active: changesActive && !turnInFlight,\n repoPaths,\n liveness: liveIoLiveness,\n comparison: changesComparison,\n capture: changesComparison === \"staged\" ? null : captureState.capture,\n });\n useEffect(() => {\n if (\n changesComparison === \"branch\" &&\n git.error &&\n storedChangesComparison?.sessionId !== sessionId\n ) {\n // `origin/HEAD` is not guaranteed on a newly initialized repository, a\n // connected machine, or a clone whose remote was renamed. The implicit\n // live default must not strand the whole Changes surface when its ordinary\n // working-tree comparison is still valid. Fall back once; an explicit\n // user-selected Branch view remains selected and surfaces its real error.\n setStoredChangesComparison({ sessionId, value: \"working\" });\n }\n }, [changesComparison, git.error, sessionId, storedChangesComparison?.sessionId]);\n // Token-derived xterm theme; re-derive on a `data-og-theme` flip. Generic — it\n // belongs in the package (an embedder's theme toggle drives it too).\n const [xtermTheme, setXtermTheme] = useState<XtermTheme | undefined>(undefined);\n useEffect(() => {\n if (!terminalEnabled || typeof document === \"undefined\") return;\n const derive = () => setXtermTheme(xtermThemeFromTokens());\n derive();\n const observer = new MutationObserver(derive);\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"data-og-theme\", \"class\"],\n });\n return () => observer.disconnect();\n }, [terminalEnabled]);\n\n const dirtyCount = git.diff.length;\n\n // The one truthful machine indicator, derived from the live capability/liveness\n // surface + the active machine's connection state + the latest capture time.\n const chip = useMachineChip({\n liveness,\n capabilitiesState: caps.state,\n activeMachineState: activeMachine?.state ?? null,\n activeIsSelfhosted: activeMachine?.kind === \"selfhosted\",\n wantsWarm: (terminalEnabled && warmTerminal) || (workspaceDataEnabled && filesWarmRequested),\n capturedAt: captureState.capturedAt,\n });\n const workspaceWaking = chip.state === \"waking\";\n\n // The pre-paint default comes only from the durable capture. Default selection\n // must never dispatch live provider work: a live Git probe can overlap the\n // agent's first command, and an uncontrolled dock used to keep that probe\n // active forever after it visibly selected Files. A capture with reviewable\n // changes opens Changes; no capture (or an empty one) opens Files. The choice\n // latches once so later edits never steal the user's current tab.\n const defaultIdentity = `${sessionId}\\u0000${surfaceIdentity}`;\n const defaultTabRef = useRef<{ identity: string; value: string | null }>({\n identity: defaultIdentity,\n value: null,\n });\n if (defaultTabRef.current.identity !== defaultIdentity) {\n defaultTabRef.current = { identity: defaultIdentity, value: null };\n }\n const captureHasChanges =\n (captureState.fileCount ?? 0) > 0 ||\n (captureState.capture?.repos.some((repo) => (repo.branchDiff?.length ?? 0) > 0) ?? false);\n const captureUnavailable =\n !captureState.loading &&\n ((captureState.fileCount === 0 && !captureHasChanges) || captureState.error !== null);\n if (defaultTabRef.current.value === null) {\n if (initialTab && (!isWorkbenchSurface(initialTab) || surfaceSet.has(initialTab))) {\n defaultTabRef.current.value = initialTab;\n } else if (captureState.fileCount !== null && captureState.available) {\n defaultTabRef.current.value = sourceDrivenDefaultTab(\n captureHasChanges,\n changesEnabled,\n filesEnabled,\n );\n } else if (captureUnavailable && initialWorkspaceTab(events) === WORKBENCH_TAB_CHANGES) {\n defaultTabRef.current.value = sourceDrivenDefaultTab(true, changesEnabled, filesEnabled);\n } else if (\n !captureState.loading &&\n (captureState.fileCount !== null || captureState.error !== null)\n ) {\n // Metadata may arrive before a signed manifest. While that manifest is\n // loading, neither a positive count nor zero (committed-only changes)\n // proves an unavailable capture, so leave the default unresolved.\n // No durable review surface exists. Files owns the explicit live-workspace\n // gate; a user can open Changes deliberately if they need a fresh Git read.\n defaultTabRef.current.value = sourceDrivenDefaultTab(false, changesEnabled, filesEnabled);\n }\n }\n // null only during the brief pre-first-resolve window (no host override yet).\n const defaultTab = defaultTabRef.current.value;\n\n const tabs = useMemo(() => {\n const list: WorkspaceTab[] = [];\n\n // Changes — capture-backed and usable cold/offline when the host enables it.\n if (changesEnabled)\n list.push({\n id: WORKBENCH_TAB_CHANGES,\n label: t(\"sandboxWorkspace.changes\"),\n icon: <GitCompareArrowsIcon />,\n badge: dirtyCount > 0 ? <DirtyBadge count={dirtyCount} /> : undefined,\n content: (\n <ChangesTabBody\n git={git}\n comparison={changesComparison}\n onComparisonChange={setChangesComparison}\n captureAvailable={captureAvailable}\n captureDegraded={captureState.degradedReason !== null}\n captureRevision={captureState.revision}\n capturePending={capturePending}\n liveWorkspaceExpected={liveWorkspaceExpected}\n workspaceWaking={workspaceWaking}\n capabilitiesState={caps.state}\n capabilitiesError={caps.error}\n onRetry={caps.renegotiate}\n onWake={() => requestWarmIntent(\"warmFiles\")}\n {...(filesEnabled && onOpenFile\n ? {\n onOpenFile: (path: string) => {\n requestWarmIntent(\"warmFiles\");\n onOpenFile(path);\n },\n }\n : {})}\n />\n ),\n });\n\n // Files — capture-backed cold tree; live warm when the host enables it.\n if (filesEnabled)\n list.push({\n id: WORKBENCH_TAB_FILES,\n label: t(\"sandboxWorkspace.files\"),\n icon: <FileCode2Icon />,\n content: (\n <FilesTabBody\n key={sessionId}\n files={files}\n git={git}\n isNodeVisible={isFileNodeVisible}\n fileSystemAvailable={fileSystemOn || captureAvailable}\n editable={\n filesEditable && files.source === \"live\" && files.error === null && !files.loading\n }\n workspaceResting={\n !liveWorkspaceExpected &&\n liveness !== undefined &&\n !capturePending &&\n !captureAvailable &&\n !workspaceWaking\n }\n workspaceWaking={!liveWorkspaceExpected && !captureAvailable && workspaceWaking}\n liveWorkspaceReady={liveWorkspaceExpected}\n workspaceError={\n caps.error ??\n (caps.viewerCapReached\n ? new Error(t(\"sandboxWorkspace.theLiveWorkspaceViewerLimit\"))\n : filesWarmRequested && caps.state === \"on-demand\" && !fileSystemOn\n ? new Error(t(\"sandboxWorkspace.thisMachineDoesNotCurrently\"))\n : null)\n }\n onWakeWorkspace={() => {\n if (filesWarmRequested) caps.renegotiate();\n else requestWarmIntent(\"warmFiles\");\n }}\n {...(requestedFilePath\n ? {\n requestedPath: requestedFilePath,\n ...(requestedFileRequestId !== null && requestedFileRequestId !== undefined\n ? { requestedPathRequestId: requestedFileRequestId }\n : {}),\n requestedPathReady: sandboxAcceptsLiveIo(liveness),\n ...(requestedFileLine != null && requestedFileLine > 0\n ? { requestedLine: requestedFileLine }\n : {}),\n }\n : {})}\n // Ordinary capture browsing does not warm a box. The first edit — or an\n // explicit guarded-file open from Changes — is deliberate live-file intent.\n onEditIntent={() => requestWarmIntent(\"warmFiles\")}\n initialSelectedPath={initialFilePath}\n onSelectedPathChange={onFilePathChange}\n className=\"h-full\"\n />\n ),\n });\n\n // Terminal — capability-gated (appears after negotiation; never the default).\n if (terminalOn) {\n list.push({\n id: WORKBENCH_TAB_TERMINAL,\n label: t(\"sandboxWorkspace.terminal\"),\n icon: <SquareTerminalIcon />,\n content: (\n <div className=\"h-full bg-og-bg p-1\">\n <SandboxTerminal\n key={sessionId}\n result={terminal}\n terminalCapability={capabilities?.Terminal ?? null}\n onActivate={() => requestWarmIntent(\"warmTerminal\")}\n onReconnectNeeded={caps.renegotiate}\n showHeader\n shell={capabilities?.Terminal.shell ?? undefined}\n liveness={liveness}\n {...(xtermTheme ? { theme: xtermTheme } : {})}\n />\n </div>\n ),\n });\n }\n\n // Browser — independent from sandbox capability negotiation. BrowserSessions\n // are workspace resources and may live in this agent's sandbox, a peer's\n // sandbox, a connected machine, or an external browser placement.\n if (browserEnabled) {\n list.push({\n id: WORKBENCH_TAB_BROWSER,\n label: t(\"sandboxWorkspace.browser\"),\n icon: <Globe2Icon />,\n content: (\n <Suspense fallback={<WorkbenchSurfaceLoading name=\"Browser\" />}>\n <LazyBrowserViewer\n key={sessionId}\n client={client}\n workspaceId={workspaceId}\n sessionId={sessionId}\n // WorkspaceDock mounts a heavy surface only after its first visit,\n // then keeps it mounted behind `hidden` when another tab is\n // selected. Keep that already-visited surface enabled while the\n // dock itself remains open: tearing down its controller + media\n // socket on every Browser↔Computer tab switch turned an ordinary\n // click into a multi-second cold reconnect. This does not eagerly\n // start BrowserViewer—the lazy panel is still unmounted until the\n // user/agent first visits it.\n enabled={workspaceVisible}\n active={resolvedActiveTab === WORKBENCH_TAB_BROWSER}\n onNotify={onNotify}\n initialBrowserSessionId={initialBrowserSessionId}\n onBrowserSessionIdChange={onBrowserSessionIdChange}\n {...(desktopEnabled ? { createLinkedComputer } : {})}\n {...(onOpenComputerSession ? { onOpenComputer: onOpenComputerSession } : {})}\n {...(browserWebSocketFactory ? { webSocketFactory: browserWebSocketFactory } : {})}\n {...(browserExtensionSetupUrl ? { browserExtensionSetupUrl } : {})}\n className=\"h-full\"\n />\n </Suspense>\n ),\n });\n }\n\n // Computer — stable legacy tab id, new workspace resource body. Like Browser,\n // it is independent from the selected agent's sandbox capability document.\n if (desktopEnabled) {\n list.push({\n id: WORKBENCH_TAB_DESKTOP,\n label: t(\"sandboxWorkspace.desktop\"),\n icon: <MonitorIcon />,\n content: (\n <Suspense fallback={<WorkbenchSurfaceLoading name=\"Desktop\" />}>\n <LazyComputerViewer\n key={sessionId}\n client={client}\n workspaceId={workspaceId}\n sessionId={sessionId}\n // Same visited-surface lifetime as Browser above. A live noVNC\n // connection survives tab switches and ResizeObserver re-fits its\n // canvas when this hidden panel becomes visible again, making the\n // second and later Computer opens local-machine fast.\n enabled={workspaceVisible}\n onNotify={onNotify}\n initialComputerSessionId={initialComputerSessionId}\n onComputerSessionIdChange={onComputerSessionIdChange}\n requestedComputerSessionId={requestedComputerSessionId}\n requestedComputerRequestId={requestedComputerRequestId}\n {...(computerWebSocketFactory ? { webSocketFactory: computerWebSocketFactory } : {})}\n className=\"h-full\"\n />\n </Suspense>\n ),\n });\n }\n\n return list;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n fileSystemOn,\n changesEnabled,\n filesEnabled,\n terminalOn,\n browserEnabled,\n desktopEnabled,\n captureAvailable,\n captureState.degradedReason,\n dirtyCount,\n warmTerminal,\n requestedFilePath,\n requestedFileRequestId,\n requestedFileLine,\n onOpenFile,\n initialFilePath,\n onFilePathChange,\n isFileNodeVisible,\n initialBrowserSessionId,\n onBrowserSessionIdChange,\n initialComputerSessionId,\n onComputerSessionIdChange,\n onOpenComputerSession,\n requestedComputerSessionId,\n requestedComputerRequestId,\n onNotify,\n browserWebSocketFactory,\n computerWebSocketFactory,\n workspaceVisible,\n resolvedActiveTab,\n client,\n workspaceId,\n liveness,\n sessionId,\n files,\n git,\n changesComparison,\n terminal,\n xtermTheme,\n capabilities,\n workspaceWaking,\n caps.state,\n caps.error,\n caps.viewerCapReached,\n caps.renegotiate,\n filesWarmRequested,\n requestWarmIntent,\n createLinkedComputer,\n t,\n ]);\n\n return {\n tabs,\n defaultTab,\n machine: {\n enabled: machineSurfaceEnabled,\n chip,\n activeMachine,\n loading: machines.loading,\n error: machines.error,\n refresh: machines.refresh,\n },\n };\n}\n\nexport type SandboxWorkspaceProps = ClientOverride & {\n sessionId: string;\n /** Live event log (usually `useSessionEvents().events`). */\n events: SessionEvent[];\n /** The chat / primary pane shown beside the dock. */\n primary: ReactNode;\n /**\n * Built-in surfaces this host wants to expose. Omit for Changes, Files,\n * Terminal, Browser, and Desktop. Disabled surfaces remain behaviorally dormant.\n */\n surfaces?: readonly SandboxWorkspaceSurface[] | undefined;\n /**\n * Whether this viewer may read the workspace machine fleet\n * (`GET /machines`, permission `enrollments:read`). Defaults to true. Pass\n * false for a viewer without it so the dock never requests the fleet.\n */\n machinesEnabled?: boolean | undefined;\n /** Host tabs injected BEFORE the workbench tabs (e.g. a \"Run\" landing tab). */\n leadingTabs?: WorkspaceTab[] | undefined;\n /** Host tabs injected AFTER the workbench tabs (e.g. a \"Debug\" tab). */\n trailingTabs?: WorkspaceTab[] | undefined;\n /** Override the pre-paint default tab (e.g. a host landing tab id). When\n * omitted the workbench decides from the durable workspace capture. */\n initialTab?: string | undefined;\n onActiveTabChange?: ((activeTab: string) => void) | undefined;\n /** Open a built-in or host-injected tab. A new requestId reopens the same tab. */\n openTabRequest?: { tab: string; requestId: number } | null | undefined;\n initialFilePath?: string | null | undefined;\n onFilePathChange?: ((path: string | null) => void) | undefined;\n /** Presentation-only filter for Files tree nodes and selected-file viewing. */\n isFileNodeVisible?: FileNodeVisibilityPredicate | undefined;\n /**\n * Host request to open a workspace file (and optional line) in Files. A new\n * `requestId` re-opens even the same path.\n */\n openFileRequest?:\n | {\n path: string;\n line?: number | null | undefined;\n requestId: number;\n }\n | null\n | undefined;\n initialBrowserSessionId?: string | null | undefined;\n onBrowserSessionIdChange?: ((browserSessionId: string | null) => void) | undefined;\n initialComputerSessionId?: string | null | undefined;\n onComputerSessionIdChange?: ((computerSessionId: string | null) => void) | undefined;\n /** Host-routed notifications (no toast dependency in the package). */\n onNotify?: ((notification: WorkspaceNotification) => void) | undefined;\n /** Alternate Browser frame transport for non-browser runtimes and deterministic tests. */\n browserWebSocketFactory?: BrowserFrameWebSocketFactory | undefined;\n /** Alternate Computer frame transport for non-browser runtimes and deterministic tests. */\n computerWebSocketFactory?: ComputerFrameWebSocketFactory | undefined;\n /** Host-owned setup page or store listing for attaching an existing Chrome profile. */\n browserExtensionSetupUrl?: string | undefined;\n /** Controlled collapsed state for hosts with their own dock toggle. */\n collapsed?: boolean | undefined;\n onCollapsedChange?: ((collapsed: boolean) => void) | undefined;\n /** Keep the dock's built-in collapse control with controlled collapsed state. */\n showCollapseControl?: boolean | undefined;\n /** Host navigation shown only in the phone workspace overlay header. */\n mobileLeadingControl?: ReactNode | undefined;\n autoSaveId?: string | undefined;\n defaultSize?: number | undefined;\n minSize?: number | undefined;\n maxSize?: number | undefined;\n className?: string | undefined;\n};\n\n/**\n * The whole session workspace, ready to mount: `<SandboxWorkspace>` assembles the\n * capability-gated tabs, pins the machine-state chip in the dock header, and\n * renders the resizable `<WorkspaceDock>`. Wrap the tree in `<OpenGeniProvider>`\n * (client + workspaceId) and import `@opengeni/react/compiled.css`; that is the\n * entire integration (see `docs/embedding-workbench.md`).\n */\nexport function SandboxWorkspace(props: SandboxWorkspaceProps): ReactNode {\n const {\n sessionId,\n events,\n primary,\n surfaces,\n machinesEnabled,\n leadingTabs,\n trailingTabs,\n initialTab,\n onActiveTabChange,\n openTabRequest,\n initialFilePath,\n onFilePathChange,\n isFileNodeVisible,\n openFileRequest,\n initialBrowserSessionId,\n onBrowserSessionIdChange,\n initialComputerSessionId,\n onComputerSessionIdChange,\n onNotify,\n browserWebSocketFactory,\n computerWebSocketFactory,\n browserExtensionSetupUrl,\n collapsed,\n onCollapsedChange,\n showCollapseControl,\n mobileLeadingControl,\n autoSaveId,\n defaultSize,\n minSize,\n maxSize,\n className,\n } = props;\n\n const [storedSelection, setStoredSelection] = useState<{\n sessionId: string;\n tab: string;\n } | null>(null);\n const [requestedFile, setRequestedFile] = useState<{\n sessionId: string;\n path: string;\n line: number | null;\n requestId: number;\n } | null>(null);\n const [requestedComputer, setRequestedComputer] = useState<{\n sessionId: string;\n computerSessionId: string;\n requestId: number;\n } | null>(null);\n const nextFileRequestId = useRef(0);\n const nextComputerRequestId = useRef(0);\n const selectedTab = storedSelection?.sessionId === sessionId ? storedSelection.tab : null;\n const handledTabRequest = useRef<{ sessionId: string; requestId: number } | null>(null);\n useEffect(() => {\n if (\n !openTabRequest ||\n (handledTabRequest.current?.sessionId === sessionId &&\n handledTabRequest.current.requestId === openTabRequest.requestId)\n )\n return;\n const available =\n [...(leadingTabs ?? []), ...(trailingTabs ?? [])].some(\n (tab) => tab.id === openTabRequest.tab,\n ) || (surfaces ?? WORKBENCH_SURFACES).some((tab) => tab === openTabRequest.tab);\n if (!available) return;\n handledTabRequest.current = { sessionId, requestId: openTabRequest.requestId };\n setStoredSelection({ sessionId, tab: openTabRequest.tab });\n onActiveTabChange?.(openTabRequest.tab);\n onCollapsedChange?.(false);\n }, [\n openTabRequest,\n sessionId,\n leadingTabs,\n trailingTabs,\n surfaces,\n onActiveTabChange,\n onCollapsedChange,\n ]);\n const activeTabHint = selectedTab ?? initialTab ?? leadingTabs?.[0]?.id ?? null;\n const openFile = useCallback(\n (path: string, line?: number | null) => {\n setRequestedFile({\n sessionId,\n path,\n line: line != null && line > 0 ? line : null,\n requestId: ++nextFileRequestId.current,\n });\n setStoredSelection({ sessionId, tab: WORKBENCH_TAB_FILES });\n onActiveTabChange?.(WORKBENCH_TAB_FILES);\n onFilePathChange?.(path);\n onCollapsedChange?.(false);\n },\n [onActiveTabChange, onCollapsedChange, onFilePathChange, sessionId],\n );\n const handledOpenFileRequestId = useRef<number | null>(null);\n useEffect(() => {\n if (!openFileRequest) return;\n if (handledOpenFileRequestId.current === openFileRequest.requestId) return;\n handledOpenFileRequestId.current = openFileRequest.requestId;\n openFile(openFileRequest.path, openFileRequest.line);\n }, [openFile, openFileRequest]);\n const openComputer = useCallback(\n (computerSessionId: string) => {\n nextComputerRequestId.current += 1;\n setRequestedComputer({\n sessionId,\n computerSessionId,\n requestId: nextComputerRequestId.current,\n });\n setStoredSelection({ sessionId, tab: WORKBENCH_TAB_DESKTOP });\n onActiveTabChange?.(WORKBENCH_TAB_DESKTOP);\n onComputerSessionIdChange?.(computerSessionId);\n },\n [onActiveTabChange, onComputerSessionIdChange, sessionId],\n );\n\n const {\n tabs: workbenchTabs,\n machine,\n defaultTab,\n } = useSandboxWorkspaceTabs({\n ...(props.client ? { client: props.client } : {}),\n ...(props.workspaceId ? { workspaceId: props.workspaceId } : {}),\n sessionId,\n events,\n ...(surfaces ? { surfaces } : {}),\n ...(machinesEnabled !== undefined ? { machinesEnabled } : {}),\n ...(initialTab ? { initialTab } : {}),\n activeTab: activeTabHint,\n workspaceVisible: collapsed !== true,\n ...(onNotify ? { onNotify } : {}),\n ...(browserWebSocketFactory ? { browserWebSocketFactory } : {}),\n ...(computerWebSocketFactory ? { computerWebSocketFactory } : {}),\n ...(browserExtensionSetupUrl ? { browserExtensionSetupUrl } : {}),\n initialFilePath,\n onFilePathChange,\n isFileNodeVisible,\n initialBrowserSessionId,\n onBrowserSessionIdChange,\n initialComputerSessionId,\n onComputerSessionIdChange,\n requestedFilePath: requestedFile?.sessionId === sessionId ? requestedFile.path : null,\n requestedFileRequestId: requestedFile?.sessionId === sessionId ? requestedFile.requestId : null,\n requestedFileLine: requestedFile?.sessionId === sessionId ? requestedFile.line : null,\n onOpenFile: openFile,\n onOpenComputerSession: openComputer,\n requestedComputerSessionId:\n requestedComputer?.sessionId === sessionId ? requestedComputer.computerSessionId : null,\n requestedComputerRequestId:\n requestedComputer?.sessionId === sessionId ? requestedComputer.requestId : null,\n });\n\n // A user's tab click wins forever; before that we follow the source-driven\n // default. While it is still resolving (null, pure-embedder pre-first-resolve)\n // we pass no controlled tab, so the dock renders its own first-tab fallback\n // (Changes) — whose body is a connecting/loading state until the capture lands,\n // so committing the real default at first-resolve produces no CONTENT switch.\n const tabs: WorkspaceTab[] = [...(leadingTabs ?? []), ...workbenchTabs, ...(trailingTabs ?? [])];\n const preferredTab = selectedTab ?? defaultTab;\n const activeTab =\n preferredTab && tabs.some((tab) => tab.id === preferredTab) ? preferredTab : tabs[0]?.id;\n const selectTab = useCallback(\n (tab: string) => {\n setStoredSelection({ sessionId, tab });\n onActiveTabChange?.(tab);\n },\n [onActiveTabChange, sessionId],\n );\n useEffect(() => {\n if (selectedTab !== null || defaultTab === null) return;\n // Once the source-driven choice resolves, make it the real controlled\n // selection. Without this handoff the dock could visibly show Files while\n // the data hooks continued treating the selection as unresolved.\n setStoredSelection({ sessionId, tab: defaultTab });\n }, [defaultTab, selectedTab, sessionId]);\n\n return (\n <WorkspaceDock\n primary={primary}\n tabs={tabs}\n {...(activeTab !== undefined ? { activeTab } : {})}\n onActiveTabChange={selectTab}\n // Browser and Desktop select independent workspace resources, potentially\n // on another placement. Their own viewers report runtime status; the\n // agent-session machine chip must not describe those resources.\n {...(machine.enabled &&\n activeTab !== WORKBENCH_TAB_BROWSER &&\n activeTab !== WORKBENCH_TAB_DESKTOP\n ? {\n headerAccessory: <MachineStateChip chip={machine.chip} />,\n }\n : {})}\n {...(mobileLeadingControl !== undefined ? { mobileLeadingControl } : {})}\n {...(collapsed !== undefined ? { collapsed } : {})}\n {...(onCollapsedChange ? { onCollapsedChange } : {})}\n {...(showCollapseControl !== undefined ? { showCollapseControl } : {})}\n {...(autoSaveId !== undefined ? { autoSaveId } : {})}\n {...(defaultSize !== undefined ? { defaultSize } : {})}\n {...(minSize !== undefined ? { minSize } : {})}\n {...(maxSize !== undefined ? { maxSize } : {})}\n {...(className !== undefined ? { className } : {})}\n />\n );\n}\n\n// Re-export the dock so an embedder can grab the shell type off one import.\nexport type { WorkspaceDockProps };\n\nfunction DirtyBadge({ count }: { count: number }) {\n return (\n <span className=\"rounded-og-xs bg-og-accent-soft px-1 text-og-xs text-og-fg-muted\">\n {count}\n </span>\n );\n}\n\nfunction chipDotClass(state: MachineChip[\"state\"]): string {\n if (state === \"live\") return \"bg-og-status-running\";\n if (state === \"waking\") return \"bg-og-status-idle animate-pulse motion-reduce:animate-none\";\n return \"bg-og-fg-subtle\";\n}\n\n/**\n * The dock-header machine status: one quiet, truthful live/waking/resting\n * indicator. It is intentionally not interactive; detailed machine controls do\n * not belong in a transient popover above the workspace tabs.\n */\nfunction MachineStateChip({ chip }: { chip: MachineChip }) {\n const t = useOpenGeniText();\n return (\n <div\n role=\"status\"\n aria-label={t(\"sandboxWorkspace.machineLabel\", { label: chip.label })}\n title={chip.label}\n className=\"inline-flex min-h-7 min-w-0 max-w-full items-center gap-1.5 px-2 py-1 text-og-xs font-medium text-og-fg-muted max-[1023px]:min-h-11 pointer-coarse:min-h-11\"\n >\n <span\n className={cn(\"size-1.5 shrink-0 rounded-full\", chipDotClass(chip.state))}\n aria-hidden\n />\n <span className=\"min-w-0 max-w-[11rem] truncate\">{chip.label}</span>\n </div>\n );\n}\n\n/** A minimal token-styled action button (the package has no app Button import). */\nfunction DockActionButton({ onClick, children }: { onClick: () => void; children: ReactNode }) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className=\"inline-flex items-center gap-1.5 rounded-og-sm border border-og-border px-2 py-1 text-og-xs font-medium text-og-fg-muted transition-colors hover:border-og-border-strong hover:text-og-fg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-og-accent max-[1023px]:min-h-11 pointer-coarse:min-h-11\"\n >\n {children}\n </button>\n );\n}\n\n/**\n * The Changes tab body: the real PR-review surface (`WorkbenchChanges` — file\n * rail + windowed Pierre diff pane) when there are changes, wrapped in the honest\n * connecting/offline/empty states so the default tab is never a blank surface.\n * The dock frame is untouched; this is the M5 seam.\n */\nfunction ChangesTabBody({\n comparison,\n onComparisonChange,\n ...props\n}: {\n comparison: SandboxGitComparison;\n onComparisonChange: (comparison: SandboxGitComparison) => void;\n} & Parameters<typeof ChangesTabContent>[0]) {\n const t = useOpenGeniText();\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n <div className=\"flex shrink-0 items-center gap-1 border-b border-og-border bg-og-surface-1 px-2 py-1.5\">\n {(\n [\n [\"branch\", t(\"sandboxWorkspace.branch\")],\n [\"working\", t(\"sandboxWorkspace.uncommitted\")],\n [\"staged\", t(\"sandboxWorkspace.staged\")],\n ] as const\n ).map(([value, label]) => (\n <button\n key={value}\n type=\"button\"\n aria-pressed={comparison === value}\n onClick={() => onComparisonChange(value)}\n className={cn(\n \"rounded-og-sm px-2 py-1 text-og-xs font-medium transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-og-accent max-[1023px]:min-h-11 pointer-coarse:min-h-11\",\n comparison === value\n ? \"bg-og-surface-2 text-og-fg shadow-sm\"\n : \"text-og-fg-muted hover:bg-og-surface-2 hover:text-og-fg\",\n )}\n >\n {label}\n </button>\n ))}\n </div>\n <div className=\"min-h-0 flex-1\">\n <ChangesTabContent comparison={comparison} {...props} />\n </div>\n </div>\n );\n}\n\nfunction ChangesTabContent({\n git,\n comparison,\n captureAvailable,\n captureDegraded,\n captureRevision,\n capturePending,\n liveWorkspaceExpected,\n workspaceWaking,\n capabilitiesState,\n capabilitiesError,\n onRetry,\n onWake,\n onOpenFile,\n}: {\n git: UseSandboxGitResult;\n comparison: SandboxGitComparison;\n captureAvailable: boolean;\n captureDegraded: boolean;\n captureRevision: number | null;\n capturePending: boolean;\n liveWorkspaceExpected: boolean;\n workspaceWaking: boolean;\n capabilitiesState: string;\n capabilitiesError: Error | null;\n onRetry: () => void;\n onWake: () => void;\n onOpenFile?: ((path: string) => void) | undefined;\n}) {\n const t = useOpenGeniText();\n const diff = git.diff;\n\n if (diff.length > 0) {\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n {git.error ? (\n <div\n role=\"status\"\n aria-live=\"polite\"\n data-opengeni-changes-degraded\n className=\"flex shrink-0 items-center gap-2 border-b border-og-status-running/30 bg-og-status-running/10 px-2 py-1.5 text-og-xs text-og-fg-muted\"\n >\n <TriangleAlertIcon className=\"size-3.5 shrink-0 text-og-status-running\" aria-hidden />\n <span className=\"min-w-0 flex-1\">\n {git.source === \"capture\"\n ? t(\"sandboxWorkspace.liveChangesAreTemporarilyUnavailable\")\n : t(\"sandboxWorkspace.liveRefreshFailedShowingThe\")}\n </span>\n <button\n type=\"button\"\n onClick={() => void git.refresh()}\n disabled={git.loading}\n className=\"inline-flex min-h-7 shrink-0 items-center gap-1 rounded-og-sm border border-og-border bg-og-surface-1 px-2 font-medium text-og-fg transition-colors hover:border-og-border-strong focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-og-accent disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:min-h-11\"\n >\n <RefreshCwIcon\n className={cn(\"size-3\", git.loading && \"animate-spin motion-reduce:animate-none\")}\n aria-hidden\n />\n {t(\"sandboxWorkspace.retry\")}\n </button>\n </div>\n ) : null}\n <div className=\"min-h-0 flex-1\">\n <WorkbenchChanges\n diff={diff}\n source={git.source}\n capturedAt={git.capturedAt}\n captureRevision={captureRevision}\n {...(onOpenFile ? { onOpenFile } : {})}\n />\n </div>\n </div>\n );\n }\n\n if (capabilitiesError && !captureAvailable) {\n return (\n <CenteredState icon={<TriangleAlertIcon className=\"size-5\" aria-hidden />} tone=\"danger\">\n <p className=\"text-og-sm font-medium text-og-fg\">\n {t(\"sandboxWorkspace.sandboxUnavailable\")}\n </p>\n <p data-contrast-audited className=\"text-og-sm leading-5 text-og-fg-muted\">\n {capabilitiesError.message || t(\"sandboxWorkspace.couldnTReachTheSandbox\")}\n </p>\n <DockActionButton onClick={onRetry}>\n <RefreshCwIcon className=\"size-3\" />\n {t(\"sandboxWorkspace.retry\")}\n </DockActionButton>\n </CenteredState>\n );\n }\n\n if (\n (capturePending || capabilitiesState === \"negotiating\") &&\n !captureAvailable &&\n !workspaceWaking\n ) {\n return (\n <CenteredState\n icon={\n <LoaderCircleIcon\n className=\"size-5 animate-spin motion-reduce:animate-none\"\n aria-hidden\n />\n }\n >\n <p className=\"text-og-sm font-medium text-og-fg\">\n {t(\"sandboxWorkspace.connectingWorkspace\")}\n </p>\n <p className=\"text-og-sm leading-5 text-og-fg-subtle\">\n {t(\"sandboxWorkspace.lookingForTheLatestFiles\")}\n </p>\n </CenteredState>\n );\n }\n\n if (!liveWorkspaceExpected && (comparison !== \"working\" || !captureAvailable)) {\n // Staged changes are live-only; a failed saved preview is not their blocker.\n const previewUnavailable = captureDegraded && !captureAvailable && comparison !== \"staged\";\n return (\n <CenteredState\n icon={\n workspaceWaking ? (\n <LoaderCircleIcon\n className=\"size-5 animate-spin motion-reduce:animate-none\"\n aria-hidden\n />\n ) : previewUnavailable ? (\n <TriangleAlertIcon className=\"size-5\" aria-hidden />\n ) : (\n <CpuIcon className=\"size-5\" aria-hidden />\n )\n }\n >\n <p className=\"text-og-sm font-medium text-og-fg\">\n {workspaceWaking\n ? t(\"sandboxWorkspace.wakingWorkspace\")\n : previewUnavailable\n ? t(\"sandboxWorkspace.savedChangesPreviewIsUnavailable\")\n : t(\"sandboxWorkspace.workspaceIsResting\")}\n </p>\n <p className=\"text-og-sm leading-5 text-og-fg-subtle\">\n {workspaceWaking\n ? t(\"sandboxWorkspace.connectingToTheLiveWorking\")\n : previewUnavailable\n ? t(\"sandboxWorkspace.openTheLiveWorkspaceTo\")\n : comparison === \"branch\"\n ? t(\"sandboxWorkspace.wakeTheSandboxToCompare\")\n : comparison === \"staged\"\n ? t(\"sandboxWorkspace.wakeTheSandboxToInspect\")\n : t(\"sandboxWorkspace.noCapturedRevisionIsAvailable\")}\n </p>\n {!workspaceWaking ? (\n <DockActionButton onClick={onWake}>\n <CpuIcon className=\"size-3\" />\n {t(\"sandboxWorkspace.openLiveWorkspace\")}\n </DockActionButton>\n ) : null}\n </CenteredState>\n );\n }\n\n if (git.loading && git.source === null) {\n return (\n <CenteredState\n icon={\n <LoaderCircleIcon\n className=\"size-5 animate-spin motion-reduce:animate-none\"\n aria-hidden\n />\n }\n >\n <p className=\"text-og-sm font-medium text-og-fg\">\n {t(\"sandboxWorkspace.loadingWorkspace\")}\n </p>\n <p className=\"text-og-sm leading-5 text-og-fg-subtle\">\n {t(\"sandboxWorkspace.readingTheCurrentWorkingTree\")}\n </p>\n </CenteredState>\n );\n }\n\n return (\n <CenteredState icon={<CircleCheckIcon className=\"size-5\" aria-hidden />} tone=\"success\">\n <p className=\"text-og-sm font-medium text-og-fg\">\n {comparison === \"branch\"\n ? t(\"sandboxWorkspace.noBranchChanges\")\n : comparison === \"staged\"\n ? t(\"sandboxWorkspace.noStagedChanges\")\n : t(\"sandboxWorkspace.noUncommittedChanges\")}\n </p>\n <p className=\"text-og-sm leading-5 text-og-fg-subtle\">\n {comparison === \"branch\"\n ? t(\"sandboxWorkspace.thisBranchMatchesTheRemote\")\n : comparison === \"staged\"\n ? t(\"sandboxWorkspace.stageFilesToReviewThe\")\n : t(\"sandboxWorkspace.localEditsNotYetCommitted\")}\n </p>\n </CenteredState>\n );\n}\n\nfunction CenteredState({\n children,\n icon,\n tone = \"neutral\",\n}: {\n children: ReactNode;\n icon?: ReactNode | undefined;\n tone?: \"neutral\" | \"success\" | \"danger\";\n}) {\n return (\n <div\n role={tone === \"danger\" ? \"alert\" : \"status\"}\n aria-atomic=\"true\"\n aria-live={tone === \"danger\" ? \"assertive\" : \"polite\"}\n className=\"grid h-full place-items-center p-6 text-center\"\n >\n <div className=\"flex max-w-sm flex-col items-center gap-2.5\">\n {icon ? (\n <span\n className={cn(\n \"grid size-10 place-items-center rounded-og-lg border bg-og-surface-1 shadow-sm\",\n tone === \"success\" && \"border-og-status-idle/30 text-og-status-idle\",\n tone === \"danger\" && \"border-og-status-failed/30 text-og-status-failed\",\n tone === \"neutral\" && \"border-og-border text-og-fg-muted\",\n )}\n >\n {icon}\n </span>\n ) : null}\n {children}\n </div>\n </div>\n );\n}\n","import type { SuperGrokAccount, SuperGrokAccountsResponse } from \"@opengeni/sdk\";\nimport { useCallback } from \"react\";\n\nimport { useOpenGeni, type ClientOverride } from \"../provider\";\nimport { useMutationRunner } from \"./internal\";\nimport { invalidateSharedQueries, useSharedQuery, type SharedQueryKey } from \"./shared-query\";\n\n/** Shared-cache key for a workspace's SuperGrok accounts (internal; see `useSharedQuery`). */\nexport const superGrokAccountsQueryKey = (workspaceId: string) =>\n [\"supergrok-accounts\", workspaceId] as SharedQueryKey;\n\nexport type SuperGrokAccountsClientLike = {\n listSuperGrokAccounts: (workspaceId: string) => Promise<SuperGrokAccountsResponse>;\n activateSuperGrokAccount?: (\n workspaceId: string,\n accountId: string,\n ) => Promise<{ activated: boolean; accountId: string }>;\n};\n\nexport type UseSuperGrokAccountsOptions = ClientOverride & {\n enabled?: boolean | undefined;\n pollIntervalMs?: number | undefined;\n supergrokClient?: SuperGrokAccountsClientLike | undefined;\n};\n\nexport type UseSuperGrokAccountsResult = {\n accounts: SuperGrokAccount[];\n activeAccountId: string | null;\n settings: SuperGrokAccountsResponse[\"settings\"];\n loading: boolean;\n refresh: () => Promise<void>;\n activate: (accountId: string) => Promise<boolean>;\n activating: boolean;\n mutationError: Error | null;\n};\n\nconst EMPTY: SuperGrokAccountsResponse = {\n accounts: [],\n activeAccountId: null,\n settings: {\n rotationEnabled: false,\n rotationStrategy: \"sharded\",\n activeCredentialId: null,\n },\n};\n\n/**\n * Workspace-visible xAI accounts. Workspace scope is the connection default.\n * Reads share the client-scoped cache, so a remount renders retained rows at once.\n */\nexport function useSuperGrokAccounts(\n options: UseSuperGrokAccountsOptions = {},\n): UseSuperGrokAccountsResult {\n const { client, workspaceId } = useOpenGeni(options);\n const supergrokClient =\n options.supergrokClient ?? (client as unknown as SuperGrokAccountsClientLike);\n const load = useCallback(\n async () => await supergrokClient.listSuperGrokAccounts(workspaceId),\n [supergrokClient, workspaceId],\n );\n const { data, loading, refresh } = useSharedQuery(\n supergrokClient,\n superGrokAccountsQueryKey(workspaceId),\n load,\n { enabled: options.enabled, pollIntervalMs: options.pollIntervalMs },\n );\n const { run, mutating: activating, mutationError } = useMutationRunner();\n const activate = useCallback(\n async (accountId: string): Promise<boolean> => {\n if (!supergrokClient.activateSuperGrokAccount) return false;\n const invalidated: { current: Promise<void> | null } = { current: null };\n const result = await run(async () => {\n await supergrokClient.activateSuperGrokAccount!(workspaceId, accountId);\n // Invalidate even if this component unmounted meanwhile (the runner\n // then resolves null): other surfaces must not keep the old primary.\n invalidated.current = invalidateSharedQueries(supergrokClient, [\"supergrok-accounts\"]);\n return true;\n });\n if (result) await invalidated.current;\n return result === true;\n },\n [run, supergrokClient, workspaceId],\n );\n const state = data ?? EMPTY;\n return {\n accounts: state.accounts,\n activeAccountId: state.activeAccountId,\n settings: state.settings,\n loading,\n refresh,\n activate,\n activating,\n mutationError,\n };\n}\n"],"mappings":"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","names":["useCallback","useEffect","useRef","useState","useState","useEffect","useCallback","useRef","useCallback","useCallback","useCallback","useCallback","useCallback","useEffect","useRef","useState","useState","useRef","useCallback","useEffect","OpenGeniApiError","useCallback","useEffect","useMemo","useRef","useState","useState","useRef","useEffect","useMemo","OpenGeniApiError","useCallback","useCallback","useEffect","useMemo","useRef","useState","useMemo","isLive","useRef","useState","useCallback","roots","useEffect","useCallback","useEffect","useRef","useState","useState","useRef","useCallback","useEffect","useCallback","useEffect","useMemo","useRef","useState","useMemo","useState","useRef","useEffect","useCallback","useMemo","useMemo","modelDisplayName","jsx","jsxs","useCallback","useEffect","useMemo","useRef","useState","useCallback","useEffect","useMemo","useRef","useState","jsx","jsxs","useEffect","useRef","useState","useMemo","useCallback","jsx","useCallback","useEffect","useMemo","useRef","useState","jsx","jsxs","SandboxFiles","useCallback","useState","useEffect","useRef","useMemo","useCallback","useCallback"]}