@opengeni/react 0.57.0 → 1.0.2-canary.37191796234001

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 (629) hide show
  1. package/README.md +654 -22
  2. package/dist/accounts.d.ts +64 -0
  3. package/dist/accounts.js +822 -0
  4. package/dist/accounts.js.map +1 -0
  5. package/dist/approvals.d.ts +2 -1
  6. package/dist/artifacts-document.js +3 -2
  7. package/dist/artifacts-presentation.js +3 -2
  8. package/dist/artifacts-spreadsheet.js +2 -2
  9. package/dist/artifacts.d.ts +4 -1
  10. package/dist/artifacts.js +518 -42
  11. package/dist/artifacts.js.map +1 -1
  12. package/dist/browser-viewer-GTR5XQ7X.js +16 -0
  13. package/dist/capability-catalog-row.d.ts +20 -0
  14. package/dist/capability-logo-fallback.d.ts +3 -0
  15. package/dist/chat-interactive-block-UGBTNB3L.js +11 -0
  16. package/dist/chat-interactive-block-UGBTNB3L.js.map +1 -0
  17. package/dist/{chunk-5UQPNLIO.js → chunk-23J2ZNXT.js} +4117 -3896
  18. package/dist/chunk-23J2ZNXT.js.map +1 -0
  19. package/dist/chunk-447JLCBU.js +209 -0
  20. package/dist/chunk-447JLCBU.js.map +1 -0
  21. package/dist/chunk-4RVYOY4O.js +379 -0
  22. package/dist/chunk-4RVYOY4O.js.map +1 -0
  23. package/dist/chunk-5CVXZA3Y.js +292 -0
  24. package/dist/chunk-5CVXZA3Y.js.map +1 -0
  25. package/dist/chunk-5J4FOW6Q.js +108 -0
  26. package/dist/chunk-5J4FOW6Q.js.map +1 -0
  27. package/dist/chunk-A2PI6UMY.js +41 -0
  28. package/dist/chunk-A2PI6UMY.js.map +1 -0
  29. package/dist/{chunk-7WCLAEFV.js → chunk-A4UJB2MM.js} +37 -27
  30. package/dist/chunk-A4UJB2MM.js.map +1 -0
  31. package/dist/chunk-B3V6TG77.js +41 -0
  32. package/dist/chunk-B3V6TG77.js.map +1 -0
  33. package/dist/chunk-BRM6FVZA.js +302 -0
  34. package/dist/chunk-BRM6FVZA.js.map +1 -0
  35. package/dist/chunk-C5X5AJXK.js +182 -0
  36. package/dist/chunk-C5X5AJXK.js.map +1 -0
  37. package/dist/chunk-CR7U7HAR.js +453 -0
  38. package/dist/chunk-CR7U7HAR.js.map +1 -0
  39. package/dist/{chunk-R3AZOAB5.js → chunk-DYWBUX5Q.js} +29 -123
  40. package/dist/chunk-DYWBUX5Q.js.map +1 -0
  41. package/dist/chunk-E3G7SAYZ.js +3124 -0
  42. package/dist/chunk-E3G7SAYZ.js.map +1 -0
  43. package/dist/chunk-ELCE5SXV.js +359 -0
  44. package/dist/chunk-ELCE5SXV.js.map +1 -0
  45. package/dist/chunk-ERGYJIBB.js +21 -0
  46. package/dist/chunk-ERGYJIBB.js.map +1 -0
  47. package/dist/chunk-FFA2OVOV.js +319 -0
  48. package/dist/chunk-FFA2OVOV.js.map +1 -0
  49. package/dist/chunk-FZCP527Y.js +116 -0
  50. package/dist/chunk-FZCP527Y.js.map +1 -0
  51. package/dist/chunk-GIMRELBW.js +14 -0
  52. package/dist/chunk-GIMRELBW.js.map +1 -0
  53. package/dist/{chunk-6KLX2RH5.js → chunk-H2NJQORO.js} +1069 -79
  54. package/dist/chunk-H2NJQORO.js.map +1 -0
  55. package/dist/chunk-I7IWRQLN.js +1608 -0
  56. package/dist/chunk-I7IWRQLN.js.map +1 -0
  57. package/dist/{chunk-HA46CYQK.js → chunk-IQUCRAT7.js} +792 -537
  58. package/dist/chunk-IQUCRAT7.js.map +1 -0
  59. package/dist/chunk-IWIDV7SB.js +1 -0
  60. package/dist/chunk-IWIDV7SB.js.map +1 -0
  61. package/dist/chunk-J2QWVSQY.js +312 -0
  62. package/dist/chunk-J2QWVSQY.js.map +1 -0
  63. package/dist/chunk-JFNEV4LU.js +2733 -0
  64. package/dist/chunk-JFNEV4LU.js.map +1 -0
  65. package/dist/chunk-JT4JW7BC.js +54 -0
  66. package/dist/chunk-JT4JW7BC.js.map +1 -0
  67. package/dist/chunk-K3HQAKQX.js +24 -0
  68. package/dist/chunk-K3HQAKQX.js.map +1 -0
  69. package/dist/{chunk-C5ZPSSS5.js → chunk-NEXLLTP4.js} +2 -1
  70. package/dist/{chunk-C5ZPSSS5.js.map → chunk-NEXLLTP4.js.map} +1 -1
  71. package/dist/chunk-NZUI76EM.js +371 -0
  72. package/dist/chunk-NZUI76EM.js.map +1 -0
  73. package/dist/{chunk-PEI6RANI.js → chunk-PNY3JKBJ.js} +309 -74
  74. package/dist/chunk-PNY3JKBJ.js.map +1 -0
  75. package/dist/{chunk-IGC6A2ZI.js → chunk-Q5QBEZIQ.js} +777 -246
  76. package/dist/chunk-Q5QBEZIQ.js.map +1 -0
  77. package/dist/chunk-RHREZ7BO.js +11 -0
  78. package/dist/chunk-RHREZ7BO.js.map +1 -0
  79. package/dist/chunk-SCOTPE2I.js +589 -0
  80. package/dist/chunk-SCOTPE2I.js.map +1 -0
  81. package/dist/{chunk-B6WPZSTT.js → chunk-SJZDKVW2.js} +1331 -1163
  82. package/dist/chunk-SJZDKVW2.js.map +1 -0
  83. package/dist/chunk-TMJRG4YC.js +12803 -0
  84. package/dist/chunk-TMJRG4YC.js.map +1 -0
  85. package/dist/chunk-TMYGL6X5.js +742 -0
  86. package/dist/chunk-TMYGL6X5.js.map +1 -0
  87. package/dist/chunk-UGLEYEMP.js +33 -0
  88. package/dist/chunk-UGLEYEMP.js.map +1 -0
  89. package/dist/chunk-UK4TINKT.js +27 -0
  90. package/dist/chunk-UK4TINKT.js.map +1 -0
  91. package/dist/chunk-UTRTG6LH.js +220 -0
  92. package/dist/chunk-UTRTG6LH.js.map +1 -0
  93. package/dist/chunk-WEHMPOXK.js +39 -0
  94. package/dist/chunk-WEHMPOXK.js.map +1 -0
  95. package/dist/chunk-WRHIZYZF.js +988 -0
  96. package/dist/chunk-WRHIZYZF.js.map +1 -0
  97. package/dist/{chunk-HUIKIDM5.js → chunk-WUISZ3WU.js} +223 -115
  98. package/dist/chunk-WUISZ3WU.js.map +1 -0
  99. package/dist/chunk-XCHWDJ22.js +107 -0
  100. package/dist/chunk-XCHWDJ22.js.map +1 -0
  101. package/dist/chunk-XOAMRDDK.js +481 -0
  102. package/dist/chunk-XOAMRDDK.js.map +1 -0
  103. package/dist/chunk-XUW2UWQM.js +299 -0
  104. package/dist/chunk-XUW2UWQM.js.map +1 -0
  105. package/dist/{chunk-KCGXPP5V.js → chunk-Y2PRMYLC.js} +11 -6
  106. package/dist/chunk-Y2PRMYLC.js.map +1 -0
  107. package/dist/chunk-YBXQDQFX.js +1772 -0
  108. package/dist/chunk-YBXQDQFX.js.map +1 -0
  109. package/dist/{chunk-KZ73RL76.js → chunk-YQEAA6LT.js} +7 -3
  110. package/dist/chunk-YQEAA6LT.js.map +1 -0
  111. package/dist/chunk-YV4L3ILF.js +9 -0
  112. package/dist/chunk-YV4L3ILF.js.map +1 -0
  113. package/dist/{chunk-LLOLUHVG.js → chunk-YWFG7ZX7.js} +1358 -2746
  114. package/dist/chunk-YWFG7ZX7.js.map +1 -0
  115. package/dist/chunk-ZYRGEKWS.js +216 -0
  116. package/dist/chunk-ZYRGEKWS.js.map +1 -0
  117. package/dist/client.d.ts +7 -4
  118. package/dist/clipboard.js +1 -0
  119. package/dist/commands/types.d.ts +2 -0
  120. package/dist/components/anthropic-mark.d.ts +3 -0
  121. package/dist/components/approval-surface.d.ts +15 -0
  122. package/dist/components/artifacts/artifact-chrome.d.ts +120 -0
  123. package/dist/components/artifacts/artifact-sandbox.d.ts +27 -0
  124. package/dist/components/artifacts/artifact-surface.d.ts +3 -1
  125. package/dist/components/artifacts/chat-interactive-block.d.ts +29 -0
  126. package/dist/components/artifacts/deferred-chat-media.d.ts +15 -0
  127. package/dist/components/artifacts/document-editor.d.ts +4 -2
  128. package/dist/components/artifacts/editable-artifact-ui.d.ts +2 -1
  129. package/dist/components/artifacts/editable-artifact-view.d.ts +46 -0
  130. package/dist/components/artifacts/editable-document.d.ts +1 -1
  131. package/dist/components/artifacts/editable-presentation.d.ts +2 -2
  132. package/dist/components/artifacts/editable-spreadsheet.d.ts +2 -1
  133. package/dist/components/artifacts/index.d.ts +8 -1
  134. package/dist/components/artifacts/inline-html-document.d.ts +2 -0
  135. package/dist/components/artifacts/latest-task-runner.d.ts +15 -0
  136. package/dist/components/artifacts/presentation-editor.d.ts +6 -2
  137. package/dist/components/artifacts/published-html-artifact-frame.d.ts +48 -3
  138. package/dist/components/artifacts/session-artifact-viewer.d.ts +39 -0
  139. package/dist/components/artifacts/site-view.d.ts +23 -0
  140. package/dist/components/artifacts/spreadsheet-general-display.d.ts +24 -0
  141. package/dist/components/artifacts/visualization-assets.gen.d.ts +2 -0
  142. package/dist/components/browser-select-control.d.ts +16 -0
  143. package/dist/components/browser-viewer.d.ts +10 -1
  144. package/dist/components/chat-composer.d.ts +21 -3
  145. package/dist/components/child-session-link.d.ts +5 -0
  146. package/dist/components/claude-mark.d.ts +3 -0
  147. package/dist/components/code-editor.d.ts +1 -4
  148. package/dist/components/composer.d.ts +45 -4
  149. package/dist/components/computer-viewer.d.ts +4 -1
  150. package/dist/components/copy-button.d.ts +3 -1
  151. package/dist/components/desktop-viewer.d.ts +1 -1
  152. package/dist/components/enrollment-consent.d.ts +6 -3
  153. package/dist/components/file-browser.d.ts +10 -1
  154. package/dist/components/fleet-tile.d.ts +2 -2
  155. package/dist/components/grok-mark.d.ts +26 -0
  156. package/dist/components/human-input-form.d.ts +21 -2
  157. package/dist/components/human-input-surface.d.ts +6 -3
  158. package/dist/components/machine-card.d.ts +4 -1
  159. package/dist/components/machines/machine-detail.d.ts +4 -1
  160. package/dist/components/machines/machine-operation-policy.d.ts +11 -0
  161. package/dist/components/machines-dashboard.d.ts +3 -1
  162. package/dist/components/markdown-table-layout.d.ts +12 -0
  163. package/dist/components/markdown.d.ts +47 -3
  164. package/dist/components/message-timeline.d.ts +72 -9
  165. package/dist/components/model-mark.d.ts +29 -0
  166. package/dist/components/model-policy-picker-menu.d.ts +9 -0
  167. package/dist/components/model-policy-picker.d.ts +62 -13
  168. package/dist/components/open-geni-chat.d.ts +55 -0
  169. package/dist/components/open-geni-links.d.ts +68 -0
  170. package/dist/components/openrouter-mark.d.ts +6 -0
  171. package/dist/components/pierre-file.d.ts +1 -1
  172. package/dist/components/preview-loading.d.ts +2 -0
  173. package/dist/components/queue-item-content.d.ts +9 -0
  174. package/dist/components/sandbox-files.d.ts +13 -2
  175. package/dist/components/sandbox-workspace.d.ts +43 -3
  176. package/dist/components/session-capability-frame.d.ts +35 -0
  177. package/dist/components/session-chrome.d.ts +66 -8
  178. package/dist/components/session-commands-panel.d.ts +6 -0
  179. package/dist/components/session-commands.d.ts +6 -0
  180. package/dist/components/session-connection-request.d.ts +8 -0
  181. package/dist/components/session-conversation.d.ts +86 -0
  182. package/dist/components/session-list.d.ts +36 -0
  183. package/dist/components/session-mcp-capability-card.d.ts +41 -0
  184. package/dist/components/timeline-anchor.d.ts +24 -0
  185. package/dist/components/timeline-annotation-chrome.d.ts +25 -0
  186. package/dist/components/timeline-annotation-layout.d.ts +42 -0
  187. package/dist/components/timeline-annotation-markers.d.ts +8 -0
  188. package/dist/components/timeline-annotation-reveal-context.d.ts +4 -0
  189. package/dist/components/timeline-annotation-shared.d.ts +31 -0
  190. package/dist/components/timeline-annotations-dialog.d.ts +3 -2
  191. package/dist/components/timeline-annotations.d.ts +13 -3
  192. package/dist/components/timeline-reading-progress.d.ts +11 -0
  193. package/dist/components/timeline-search.d.ts +34 -0
  194. package/dist/components/timeline-settlement.d.ts +16 -0
  195. package/dist/components/tip-follow.d.ts +16 -0
  196. package/dist/components/usage-limit-notice.d.ts +49 -0
  197. package/dist/components/usage-member-list.d.ts +91 -0
  198. package/dist/components/usage-meter.d.ts +73 -0
  199. package/dist/components/use-viewer-menu-dismiss.d.ts +2 -0
  200. package/dist/components/user-message-body.d.ts +10 -1
  201. package/dist/components/workspace-dock.d.ts +6 -2
  202. package/dist/composer.d.ts +5 -4
  203. package/dist/composer.js +15 -9
  204. package/dist/computer-viewer-ENHVAZ2Q.js +19 -0
  205. package/dist/computer-viewer-ENHVAZ2Q.js.map +1 -0
  206. package/dist/connect-account-identity.d.ts +8 -0
  207. package/dist/connect-accounts.d.ts +15 -0
  208. package/dist/connect-chooser.d.ts +18 -0
  209. package/dist/connect-panel.d.ts +18 -0
  210. package/dist/connect-setup.d.ts +16 -0
  211. package/dist/connect.d.ts +21 -0
  212. package/dist/connect.js +2129 -0
  213. package/dist/connect.js.map +1 -0
  214. package/dist/connection-catalog.d.ts +38 -0
  215. package/dist/connection-discovery.d.ts +12 -0
  216. package/dist/connection-installed.d.ts +17 -0
  217. package/dist/connection-logo.d.ts +9 -0
  218. package/dist/connection-service-logo.d.ts +8 -0
  219. package/dist/connection-service-presentation.d.ts +13 -0
  220. package/dist/connection-skeleton.d.ts +5 -0
  221. package/dist/connection-type-picker.d.ts +6 -0
  222. package/dist/conversation-timeline.d.ts +5 -0
  223. package/dist/desktop.d.ts +7 -0
  224. package/dist/desktop.js +26 -0
  225. package/dist/desktop.js.map +1 -0
  226. package/dist/device-authorization.d.ts +23 -0
  227. package/dist/diffs.d.ts +8 -0
  228. package/dist/diffs.js +14 -0
  229. package/dist/diffs.js.map +1 -0
  230. package/dist/discovery-cache.d.ts +5 -0
  231. package/dist/editor.d.ts +7 -0
  232. package/dist/editor.js +21 -0
  233. package/dist/editor.js.map +1 -0
  234. package/dist/embedded-session-client.d.ts +23 -0
  235. package/dist/file-node-visibility.d.ts +15 -0
  236. package/dist/{fleet-decision-row-GGCAT4E4.js → fleet-decision-row-YZ3ZKWMM.js} +2 -1
  237. package/dist/fleet-decision-row-YZ3ZKWMM.js.map +1 -0
  238. package/dist/hooks/channel-cache.d.ts +23 -0
  239. package/dist/hooks/latest-question.d.ts +25 -0
  240. package/dist/hooks/shared-machines-list.d.ts +14 -0
  241. package/dist/hooks/use-attached-browsers.d.ts +2 -1
  242. package/dist/hooks/use-browser-frame-stream.d.ts +1 -1
  243. package/dist/hooks/use-browser-session.d.ts +12 -1
  244. package/dist/hooks/use-channels.d.ts +1 -0
  245. package/dist/hooks/use-codex-accounts.d.ts +25 -7
  246. package/dist/hooks/use-composer.d.ts +45 -9
  247. package/dist/hooks/use-computer-frame-stream.d.ts +1 -1
  248. package/dist/hooks/use-computer-input-posture.d.ts +13 -0
  249. package/dist/hooks/use-computer-session.d.ts +2 -0
  250. package/dist/hooks/use-connect.d.ts +22 -0
  251. package/dist/hooks/use-desktop-stream.d.ts +1 -1
  252. package/dist/hooks/use-file-attachments.d.ts +21 -2
  253. package/dist/hooks/use-machine-chip.d.ts +3 -3
  254. package/dist/hooks/use-machines.d.ts +19 -1
  255. package/dist/hooks/use-sandbox-files.d.ts +5 -1
  256. package/dist/hooks/use-session-background-commands.d.ts +14 -0
  257. package/dist/hooks/use-session-events.d.ts +30 -8
  258. package/dist/hooks/use-session-lineage.d.ts +4 -0
  259. package/dist/hooks/use-session-mcp-approval-policy.d.ts +2 -2
  260. package/dist/hooks/use-session.d.ts +6 -0
  261. package/dist/hooks/use-turn-queue.d.ts +12 -0
  262. package/dist/hooks/use-usage.d.ts +40 -0
  263. package/dist/hooks/use-workspace-edit.d.ts +4 -0
  264. package/dist/hooks/use-workspace-sessions.d.ts +27 -5
  265. package/dist/human-input.d.ts +3 -1
  266. package/dist/identity-link-accounts.d.ts +11 -0
  267. package/dist/identity-link-consent.d.ts +18 -0
  268. package/dist/index.d.ts +60 -17
  269. package/dist/index.js +2237 -6200
  270. package/dist/index.js.map +1 -1
  271. package/dist/interaction.d.ts +1 -1
  272. package/dist/interaction.js +35 -184
  273. package/dist/interaction.js.map +1 -1
  274. package/dist/latest-question-755OW5DS.js +117 -0
  275. package/dist/latest-question-755OW5DS.js.map +1 -0
  276. package/dist/lib/error-message.d.ts +7 -0
  277. package/dist/lib/format.d.ts +36 -2
  278. package/dist/lib/host-theme.d.ts +70 -0
  279. package/dist/lib/interaction-errors.d.ts +6 -0
  280. package/dist/lib/menu-styles.d.ts +22 -0
  281. package/dist/lib/pierre-diffs-loader.d.ts +20 -0
  282. package/dist/lib/workbench-peers.d.ts +36 -0
  283. package/dist/lib/xterm-theme.d.ts +7 -5
  284. package/dist/machines.d.ts +4 -2
  285. package/dist/machines.js +14 -4
  286. package/dist/markdown-table-layout-QXSLK4BY.js +106 -0
  287. package/dist/markdown-table-layout-QXSLK4BY.js.map +1 -0
  288. package/dist/mcp-connection-status.d.ts +14 -0
  289. package/dist/model-policy-picker-menu-PWRI7R2X.js +14 -0
  290. package/dist/model-policy-picker-menu-PWRI7R2X.js.map +1 -0
  291. package/dist/model-policy.d.ts +19 -3
  292. package/dist/model-policy.js +9 -1
  293. package/dist/older-history.d.ts +30 -0
  294. package/dist/platform-activity-row-627BFZ46.js +182 -0
  295. package/dist/platform-activity-row-627BFZ46.js.map +1 -0
  296. package/dist/plugin-details.d.ts +14 -0
  297. package/dist/plugin-discovery.d.ts +25 -0
  298. package/dist/provider.d.ts +13 -1
  299. package/dist/{queue-surface-implementation-2KVJTYXH.js → queue-surface-implementation-ZHFI5JBP.js} +131 -44
  300. package/dist/queue-surface-implementation-ZHFI5JBP.js.map +1 -0
  301. package/dist/realtime/realtime-control.d.ts +10 -3
  302. package/dist/realtime.js +229 -83
  303. package/dist/realtime.js.map +1 -1
  304. package/dist/sandbox-files-BBC47SLD.js +20 -0
  305. package/dist/sandbox-files-BBC47SLD.js.map +1 -0
  306. package/dist/session-auth-recommendation.d.ts +5 -0
  307. package/dist/session-capability-policy.d.ts +12 -0
  308. package/dist/session-ui.d.ts +30 -2
  309. package/dist/session-ui.js +85 -7
  310. package/dist/session-ui.js.map +1 -1
  311. package/dist/session.d.ts +8 -2
  312. package/dist/session.js +30 -19
  313. package/dist/sites-ui.d.ts +34 -0
  314. package/dist/sites.d.ts +3 -0
  315. package/dist/sites.js +11 -0
  316. package/dist/sites.js.map +1 -0
  317. package/dist/skill-discovery.d.ts +47 -0
  318. package/dist/terminal.d.ts +8 -0
  319. package/dist/terminal.js +31 -0
  320. package/dist/terminal.js.map +1 -0
  321. package/dist/timeline/activity-rail.d.ts +11 -2
  322. package/dist/timeline/allowance-exhausted-row.d.ts +24 -0
  323. package/dist/timeline/compaction-copy.d.ts +10 -0
  324. package/dist/timeline/entrance.d.ts +13 -1
  325. package/dist/timeline/genie-loading.d.ts +34 -0
  326. package/dist/timeline/index.d.ts +6 -2
  327. package/dist/timeline/knowledge-receipt.d.ts +17 -0
  328. package/dist/timeline/platform-activity-row.d.ts +14 -0
  329. package/dist/timeline/presented-image.d.ts +6 -0
  330. package/dist/timeline/projection.d.ts +31 -2
  331. package/dist/timeline/registry.d.ts +2 -0
  332. package/dist/timeline/retained-image.d.ts +18 -0
  333. package/dist/timeline/rolling-activity.d.ts +11 -0
  334. package/dist/timeline/screenshot-lightbox.d.ts +16 -1
  335. package/dist/timeline/shared.d.ts +8 -3
  336. package/dist/timeline/startup-preference.d.ts +3 -0
  337. package/dist/timeline/startup-timings.d.ts +4 -0
  338. package/dist/timeline/tool-display-name.d.ts +2 -1
  339. package/dist/timeline/turn-summary.d.ts +32 -3
  340. package/dist/timeline/types.d.ts +141 -7
  341. package/dist/timeline-annotation-markers-GNDHTGBD.js +165 -0
  342. package/dist/timeline-annotation-markers-GNDHTGBD.js.map +1 -0
  343. package/dist/timeline-annotation-selection-DMLMM2TX.js +241 -0
  344. package/dist/timeline-annotation-selection-DMLMM2TX.js.map +1 -0
  345. package/dist/timeline-annotations-dialog-ELRDBHTS.js +273 -0
  346. package/dist/timeline-annotations-dialog-ELRDBHTS.js.map +1 -0
  347. package/dist/types/machines.d.ts +2 -2
  348. package/dist/usage/allowance-copy.d.ts +25 -0
  349. package/dist/usage/summary.d.ts +35 -0
  350. package/dist/usage.d.ts +13 -0
  351. package/dist/usage.js +1074 -0
  352. package/dist/usage.js.map +1 -0
  353. package/package.json +44 -4
  354. package/src/accounts.tsx +1072 -0
  355. package/src/approvals.ts +8 -1
  356. package/src/artifacts.ts +42 -0
  357. package/src/assets/README.md +8 -0
  358. package/src/assets/gmail.ico +0 -0
  359. package/src/assets/outlook.ico +0 -0
  360. package/src/capability-catalog-row.tsx +94 -0
  361. package/src/capability-logo-fallback.ts +22 -0
  362. package/src/client.ts +22 -13
  363. package/src/commands/registry.ts +18 -15
  364. package/src/commands/types.ts +2 -0
  365. package/src/components/anthropic-mark.tsx +10 -0
  366. package/src/components/approval-surface.tsx +171 -37
  367. package/src/components/artifacts/artifact-chrome.tsx +413 -0
  368. package/src/components/artifacts/artifact-sandbox.tsx +185 -0
  369. package/src/components/artifacts/artifact-surface.tsx +39 -19
  370. package/src/components/artifacts/chat-interactive-block.tsx +260 -0
  371. package/src/components/artifacts/deferred-chat-media.tsx +67 -0
  372. package/src/components/artifacts/document-editor.tsx +141 -16
  373. package/src/components/artifacts/editable-artifact-ui.tsx +4 -2
  374. package/src/components/artifacts/editable-artifact-view.tsx +187 -0
  375. package/src/components/artifacts/editable-artifact-workbench.tsx +5 -2
  376. package/src/components/artifacts/editable-document.tsx +37 -36
  377. package/src/components/artifacts/editable-presentation.tsx +36 -18
  378. package/src/components/artifacts/editable-spreadsheet.tsx +5 -2
  379. package/src/components/artifacts/index.ts +44 -0
  380. package/src/components/artifacts/inline-html-document.ts +24 -0
  381. package/src/components/artifacts/latest-task-runner.ts +49 -0
  382. package/src/components/artifacts/presentation-editor.tsx +323 -67
  383. package/src/components/artifacts/published-html-artifact-frame.tsx +338 -5
  384. package/src/components/artifacts/session-artifact-viewer.tsx +376 -0
  385. package/src/components/artifacts/site-view.tsx +116 -0
  386. package/src/components/artifacts/spreadsheet-canvas.ts +5 -10
  387. package/src/components/artifacts/spreadsheet-general-display.ts +43 -0
  388. package/src/components/artifacts/spreadsheet-grid.tsx +12 -13
  389. package/src/components/artifacts/visualization-assets/base.css +1015 -0
  390. package/src/components/artifacts/visualization-assets/helpers.html +349 -0
  391. package/src/components/artifacts/visualization-assets.gen.ts +3 -0
  392. package/src/components/browser-select-control.tsx +312 -0
  393. package/src/components/browser-viewer.tsx +1054 -314
  394. package/src/components/chat-composer.tsx +131 -85
  395. package/src/components/child-session-link.tsx +27 -0
  396. package/src/components/claude-mark.tsx +10 -0
  397. package/src/components/code-editor.tsx +13 -16
  398. package/src/components/composer-transcription-control.tsx +7 -5
  399. package/src/components/composer.tsx +376 -49
  400. package/src/components/computer-viewer.tsx +1041 -329
  401. package/src/components/copy-button.tsx +13 -5
  402. package/src/components/desktop-viewer.tsx +1 -1
  403. package/src/components/enrollment-consent.tsx +65 -7
  404. package/src/components/enrollment-device-flow.tsx +1 -1
  405. package/src/components/file-browser.tsx +158 -34
  406. package/src/components/fleet-tile.tsx +8 -16
  407. package/src/components/generated-video-player.tsx +4 -2
  408. package/src/components/grok-mark.tsx +33 -0
  409. package/src/components/human-input-form.tsx +455 -114
  410. package/src/components/human-input-surface.tsx +18 -7
  411. package/src/components/interaction-intervention-banner.tsx +2 -2
  412. package/src/components/machine-card.tsx +119 -4
  413. package/src/components/machine-dock-bar.tsx +1 -1
  414. package/src/components/machine-input-display.ts +23 -2
  415. package/src/components/machines/machine-detail.tsx +52 -2
  416. package/src/components/machines/machine-operation-policy.tsx +179 -0
  417. package/src/components/machines-dashboard.tsx +8 -17
  418. package/src/components/markdown-table-layout.ts +132 -0
  419. package/src/components/markdown.tsx +473 -44
  420. package/src/components/message-timeline.tsx +2498 -663
  421. package/src/components/model-mark.tsx +90 -0
  422. package/src/components/model-picker.tsx +15 -4
  423. package/src/components/model-policy-picker-menu.tsx +424 -0
  424. package/src/components/model-policy-picker.tsx +337 -381
  425. package/src/components/open-geni-chat.tsx +319 -0
  426. package/src/components/open-geni-links.tsx +179 -0
  427. package/src/components/openrouter-mark.tsx +13 -0
  428. package/src/components/pierre-diff.tsx +41 -16
  429. package/src/components/pierre-file.tsx +36 -11
  430. package/src/components/preview-loading.tsx +154 -0
  431. package/src/components/queue-item-content.ts +14 -0
  432. package/src/components/queue-surface-implementation.tsx +132 -42
  433. package/src/components/queue-surface-state.tsx +3 -1
  434. package/src/components/sandbox-files.tsx +267 -35
  435. package/src/components/sandbox-terminal.tsx +48 -11
  436. package/src/components/sandbox-workspace.tsx +337 -135
  437. package/src/components/session-capability-frame.tsx +192 -0
  438. package/src/components/session-chrome.tsx +1027 -328
  439. package/src/components/session-commands-panel.tsx +126 -0
  440. package/src/components/session-commands.tsx +18 -0
  441. package/src/components/session-connection-request.tsx +97 -0
  442. package/src/components/session-conversation.tsx +512 -0
  443. package/src/components/session-list.tsx +250 -0
  444. package/src/components/session-mcp-capability-card.tsx +680 -0
  445. package/src/components/session-status.tsx +1 -1
  446. package/src/components/timeline-anchor.tsx +119 -0
  447. package/src/components/timeline-annotation-chrome.tsx +196 -0
  448. package/src/components/timeline-annotation-layout.ts +268 -0
  449. package/src/components/timeline-annotation-markers.tsx +185 -0
  450. package/src/components/timeline-annotation-reveal-context.ts +9 -0
  451. package/src/components/timeline-annotation-selection.tsx +106 -54
  452. package/src/components/timeline-annotation-shared.ts +245 -0
  453. package/src/components/timeline-annotations-dialog.tsx +185 -128
  454. package/src/components/timeline-annotations.tsx +189 -45
  455. package/src/components/timeline-reading-progress.ts +80 -0
  456. package/src/components/timeline-search.tsx +168 -0
  457. package/src/components/timeline-settlement.ts +60 -0
  458. package/src/components/tip-follow.ts +70 -7
  459. package/src/components/tooltip.tsx +38 -5
  460. package/src/components/usage-limit-notice.tsx +179 -0
  461. package/src/components/usage-member-list.tsx +792 -0
  462. package/src/components/usage-meter.tsx +382 -0
  463. package/src/components/use-viewer-menu-dismiss.ts +33 -0
  464. package/src/components/user-message-body.tsx +194 -49
  465. package/src/components/workspace-dock.tsx +141 -175
  466. package/src/composer.ts +6 -1
  467. package/src/connect-account-identity.tsx +34 -0
  468. package/src/connect-accounts.tsx +233 -0
  469. package/src/connect-chooser.tsx +336 -0
  470. package/src/connect-panel.tsx +99 -0
  471. package/src/connect-setup.tsx +307 -0
  472. package/src/connect.ts +60 -0
  473. package/src/connection-assets.d.ts +4 -0
  474. package/src/connection-catalog.tsx +162 -0
  475. package/src/connection-discovery.tsx +235 -0
  476. package/src/connection-installed.tsx +51 -0
  477. package/src/connection-logo.tsx +37 -0
  478. package/src/connection-service-logo.tsx +55 -0
  479. package/src/connection-service-presentation.ts +46 -0
  480. package/src/connection-skeleton.tsx +16 -0
  481. package/src/connection-type-picker.tsx +36 -0
  482. package/src/conversation-timeline.ts +92 -0
  483. package/src/desktop.ts +24 -0
  484. package/src/device-authorization.tsx +98 -0
  485. package/src/diffs.ts +16 -0
  486. package/src/discovery-cache.ts +42 -0
  487. package/src/editor.ts +13 -0
  488. package/src/embedded-session-client.ts +104 -0
  489. package/src/file-node-visibility.ts +66 -0
  490. package/src/hooks/channel-cache.ts +104 -0
  491. package/src/hooks/internal.ts +3 -2
  492. package/src/hooks/latest-question.ts +164 -0
  493. package/src/hooks/shared-machines-list.ts +239 -0
  494. package/src/hooks/use-attached-browsers.ts +5 -1
  495. package/src/hooks/use-available-models.ts +20 -14
  496. package/src/hooks/use-browser-frame-stream.ts +25 -3
  497. package/src/hooks/use-browser-session.ts +271 -71
  498. package/src/hooks/use-browser-sessions.ts +7 -1
  499. package/src/hooks/use-channels.ts +32 -10
  500. package/src/hooks/use-codex-accounts.ts +78 -21
  501. package/src/hooks/use-composer.ts +1034 -320
  502. package/src/hooks/use-computer-frame-stream.ts +39 -16
  503. package/src/hooks/use-computer-input-posture.ts +94 -0
  504. package/src/hooks/use-computer-session.ts +110 -32
  505. package/src/hooks/use-computer-sessions.ts +8 -1
  506. package/src/hooks/use-connect.ts +23 -0
  507. package/src/hooks/use-desktop-stream.ts +19 -28
  508. package/src/hooks/use-file-attachments.ts +118 -10
  509. package/src/hooks/use-goal.ts +36 -9
  510. package/src/hooks/use-human-input.ts +31 -4
  511. package/src/hooks/use-last-started-turn-policy.ts +15 -13
  512. package/src/hooks/use-machine-chip.ts +23 -6
  513. package/src/hooks/use-machines.ts +104 -6
  514. package/src/hooks/use-sandbox-files.ts +253 -150
  515. package/src/hooks/use-sandbox-git.ts +58 -29
  516. package/src/hooks/use-session-background-commands.ts +67 -0
  517. package/src/hooks/use-session-capabilities.ts +21 -2
  518. package/src/hooks/use-session-events.ts +759 -433
  519. package/src/hooks/use-session-lineage.ts +28 -6
  520. package/src/hooks/use-session-mcp-approval-policy.ts +13 -5
  521. package/src/hooks/use-session.ts +75 -16
  522. package/src/hooks/use-slash-commands.ts +6 -11
  523. package/src/hooks/use-turn-queue.ts +113 -13
  524. package/src/hooks/use-usage.ts +100 -0
  525. package/src/hooks/use-voice-input.ts +12 -1
  526. package/src/hooks/use-workspace-capture.ts +3 -2
  527. package/src/hooks/use-workspace-edit.ts +23 -5
  528. package/src/hooks/use-workspace-sessions.ts +99 -11
  529. package/src/human-input.ts +12 -1
  530. package/src/identity-link-accounts.tsx +148 -0
  531. package/src/identity-link-consent.tsx +192 -0
  532. package/src/index.ts +157 -12
  533. package/src/interaction.ts +1 -0
  534. package/src/lib/error-message.ts +37 -0
  535. package/src/lib/format.ts +150 -14
  536. package/src/lib/host-theme.ts +511 -0
  537. package/src/lib/interaction-errors.ts +33 -0
  538. package/src/lib/menu-styles.ts +44 -0
  539. package/src/lib/pierre-diffs-loader.ts +53 -0
  540. package/src/lib/workbench-peers.ts +62 -0
  541. package/src/lib/xterm-theme.ts +23 -21
  542. package/src/machines.ts +9 -1
  543. package/src/mcp-connection-status.ts +35 -0
  544. package/src/model-policy.ts +223 -69
  545. package/src/older-history.ts +87 -0
  546. package/src/plugin-details.tsx +185 -0
  547. package/src/plugin-discovery.tsx +196 -0
  548. package/src/provider.tsx +55 -14
  549. package/src/realtime/dropdown-menu.tsx +19 -12
  550. package/src/realtime/realtime-control.tsx +274 -60
  551. package/src/session-auth-recommendation.ts +48 -0
  552. package/src/session-capability-policy.ts +83 -0
  553. package/src/session-context.ts +1 -0
  554. package/src/session-ui.ts +66 -2
  555. package/src/session.ts +18 -1
  556. package/src/sites-ui.tsx +402 -0
  557. package/src/sites.ts +3 -0
  558. package/src/skill-discovery.tsx +208 -0
  559. package/src/terminal.ts +26 -0
  560. package/src/timeline/activity-rail.tsx +171 -80
  561. package/src/timeline/allowance-exhausted-row.tsx +86 -0
  562. package/src/timeline/compaction-copy.ts +42 -0
  563. package/src/timeline/entrance.tsx +28 -3
  564. package/src/timeline/fleet-decision-projection.ts +2 -1
  565. package/src/timeline/fleet-decision-row.tsx +1 -0
  566. package/src/timeline/genie-loading.tsx +136 -0
  567. package/src/timeline/index.ts +11 -0
  568. package/src/timeline/knowledge-receipt.tsx +100 -0
  569. package/src/timeline/parsers.ts +2 -2
  570. package/src/timeline/platform-activity-row.tsx +216 -0
  571. package/src/timeline/presented-image.ts +49 -0
  572. package/src/timeline/projection.ts +1600 -84
  573. package/src/timeline/registry.ts +15 -3
  574. package/src/timeline/retained-image.ts +97 -0
  575. package/src/timeline/rolling-activity.tsx +92 -0
  576. package/src/timeline/screenshot-lightbox.tsx +115 -17
  577. package/src/timeline/shared.tsx +47 -15
  578. package/src/timeline/startup-preference.ts +33 -0
  579. package/src/timeline/startup-timings.tsx +145 -0
  580. package/src/timeline/tool-display-name.ts +8 -6
  581. package/src/timeline/tool-renderers.tsx +497 -128
  582. package/src/timeline/turn-summary.tsx +208 -44
  583. package/src/timeline/types.ts +186 -7
  584. package/src/types/machines.ts +10 -0
  585. package/src/usage/allowance-copy.ts +64 -0
  586. package/src/usage/summary.ts +93 -0
  587. package/src/usage.ts +50 -0
  588. package/styles/compiled.css +2098 -757
  589. package/styles/connect.css +284 -0
  590. package/styles/connect.d.ts +1 -0
  591. package/styles/effective-tokens.css +1 -0
  592. package/styles/index.css +201 -9
  593. package/styles/responsive.css +27 -1
  594. package/styles/session-capability.css +44 -0
  595. package/styles/tokens.css +135 -65
  596. package/dist/chunk-5UQPNLIO.js.map +0 -1
  597. package/dist/chunk-6KLX2RH5.js.map +0 -1
  598. package/dist/chunk-7WCLAEFV.js.map +0 -1
  599. package/dist/chunk-B6WPZSTT.js.map +0 -1
  600. package/dist/chunk-FK6VG4LL.js +0 -90
  601. package/dist/chunk-FK6VG4LL.js.map +0 -1
  602. package/dist/chunk-HA46CYQK.js.map +0 -1
  603. package/dist/chunk-HUIKIDM5.js.map +0 -1
  604. package/dist/chunk-IGC6A2ZI.js.map +0 -1
  605. package/dist/chunk-KCGXPP5V.js.map +0 -1
  606. package/dist/chunk-KZ73RL76.js.map +0 -1
  607. package/dist/chunk-LAKLF4PA.js +0 -141
  608. package/dist/chunk-LAKLF4PA.js.map +0 -1
  609. package/dist/chunk-LLOLUHVG.js.map +0 -1
  610. package/dist/chunk-MKPIAGVL.js +0 -465
  611. package/dist/chunk-MKPIAGVL.js.map +0 -1
  612. package/dist/chunk-PEI6RANI.js.map +0 -1
  613. package/dist/chunk-R3AZOAB5.js.map +0 -1
  614. package/dist/chunk-WSK7G5LE.js +0 -170
  615. package/dist/chunk-WSK7G5LE.js.map +0 -1
  616. package/dist/chunk-XBZWOM2K.js +0 -218
  617. package/dist/chunk-XBZWOM2K.js.map +0 -1
  618. package/dist/chunk-Y7OEDUJ5.js +0 -8810
  619. package/dist/chunk-Y7OEDUJ5.js.map +0 -1
  620. package/dist/fleet-decision-row-GGCAT4E4.js.map +0 -1
  621. package/dist/hooks/use-packs.d.ts +0 -32
  622. package/dist/interactive-workbench-viewers-TOHBXJEE.js +0 -15
  623. package/dist/queue-surface-implementation-2KVJTYXH.js.map +0 -1
  624. package/dist/timeline-annotation-selection-3L7LHGG2.js +0 -187
  625. package/dist/timeline-annotation-selection-3L7LHGG2.js.map +0 -1
  626. package/dist/timeline-annotations-dialog-U7EVLR75.js +0 -196
  627. package/dist/timeline-annotations-dialog-U7EVLR75.js.map +0 -1
  628. package/src/hooks/use-packs.ts +0 -157
  629. /package/dist/{interactive-workbench-viewers-TOHBXJEE.js.map → browser-viewer-GTR5XQ7X.js.map} +0 -0
@@ -2,6 +2,7 @@ import { FileCode2Icon, FileWarningIcon, LoaderCircleIcon } from "lucide-react";
2
2
  import { type ReactNode, useCallback, useEffect, useRef, useState } from "react";
3
3
  import { Group, Panel, Separator } from "react-resizable-panels";
4
4
  import { cn } from "../lib/cn";
5
+ import { prefersReducedMotion } from "../lib/motion";
5
6
  import { useThemeType } from "../lib/use-theme-type";
6
7
  import {
7
8
  CapturedFileUnavailableError,
@@ -9,6 +10,7 @@ import {
9
10
  type UseSandboxFilesResult,
10
11
  } from "../hooks/use-sandbox-files";
11
12
  import type { UseSandboxGitResult } from "../hooks/use-sandbox-git";
13
+ import { filePathVisibility, type FileNodeVisibilityPredicate } from "../file-node-visibility";
12
14
  import { CodeEditor } from "./code-editor";
13
15
  import { FileBrowser } from "./file-browser";
14
16
  import { PierreFile } from "./pierre-file";
@@ -32,8 +34,16 @@ export type SandboxFilesProps = {
32
34
  * dock warms the box on this so the save lands fast; opening/reading never fires
33
35
  * it. Browsing the tree/diff must not warm a box. */
34
36
  onEditIntent?: (() => void) | undefined;
35
- /** A guarded diff path routed here by the parent workspace. */
37
+ /** Restore the file last viewed in this task. Invalid/missing paths still
38
+ * surface the ordinary file-view error instead of changing files silently. */
39
+ initialSelectedPath?: string | null | undefined;
40
+ onSelectedPathChange?: ((path: string | null) => void) | undefined;
41
+ /** Presentation-only node filter shared with the tree and selected-file view. */
42
+ isNodeVisible?: FileNodeVisibilityPredicate | undefined;
43
+ /** A deliberate file-open path routed here by the parent workspace. */
36
44
  requestedPath?: string | undefined;
45
+ /** 1-based line to reveal after `requestedPath` opens. */
46
+ requestedLine?: number | null | undefined;
37
47
  /** Identity for one guarded-file request. Increment this when the same path is
38
48
  * deliberately requested again; it also lets a pending request be consumed
39
49
  * without overriding later manual tree navigation. Defaults to the path. */
@@ -47,6 +57,8 @@ export type SandboxFilesProps = {
47
57
  workspaceWaking?: boolean | undefined;
48
58
  /** Whether live reads are currently authoritative. */
49
59
  liveWorkspaceReady?: boolean | undefined;
60
+ /** Failed live negotiation; never present a failure as an ongoing wake. */
61
+ workspaceError?: Error | null | undefined;
50
62
  /** Deliberately wake the machine to read content absent from the capture. */
51
63
  onWakeWorkspace?: (() => void) | undefined;
52
64
  themeType?: "dark" | "light" | undefined;
@@ -67,22 +79,33 @@ export function SandboxFiles({
67
79
  usePierre = true,
68
80
  editable = true,
69
81
  onEditIntent,
82
+ initialSelectedPath,
83
+ onSelectedPathChange,
84
+ isNodeVisible,
70
85
  requestedPath,
86
+ requestedLine,
71
87
  requestedPathRequestId,
72
88
  requestedPathReady = true,
73
89
  workspaceResting = false,
74
90
  workspaceWaking = false,
75
91
  liveWorkspaceReady = true,
92
+ workspaceError = null,
76
93
  onWakeWorkspace,
77
94
  themeType,
78
95
  className,
79
96
  }: SandboxFilesProps) {
80
- const [selected, setSelected] = useState<string | null>(null);
97
+ const [selected, setSelected] = useState<string | null>(() => initialSelectedPath ?? null);
81
98
  // View vs Edit for the selected file. Resets to View on every new selection so
82
99
  // opening a file never lands you in a stale dirty editor for a different path.
83
100
  const [editMode, setEditMode] = useState(false);
101
+ const [focusLine, setFocusLine] = useState<number | null>(null);
102
+ const [treeRevealRequest, setTreeRevealRequest] = useState<{
103
+ path: string;
104
+ requestId: string | number;
105
+ } | null>(null);
84
106
  const [liveRequestedPath, setLiveRequestedPath] = useState<string | null>(null);
85
107
  const [viewReloadRevision, setViewReloadRevision] = useState(0);
108
+ const viewerScrollRef = useRef<HTMLDivElement | null>(null);
86
109
  const pendingRequestRef = useRef<string | number | null>(null);
87
110
  const handledRequestRef = useRef<string | number | null>(null);
88
111
  const requestKey = requestedPath ? (requestedPathRequestId ?? requestedPath) : null;
@@ -91,6 +114,7 @@ export function SandboxFiles({
91
114
  if (!requestedPath || requestKey === null) {
92
115
  pendingRequestRef.current = null;
93
116
  handledRequestRef.current = null;
117
+ setTreeRevealRequest(null);
94
118
  return;
95
119
  }
96
120
  if (handledRequestRef.current === requestKey) {
@@ -98,13 +122,40 @@ export function SandboxFiles({
98
122
  }
99
123
  if (!requestedPathReady) {
100
124
  pendingRequestRef.current = requestKey;
125
+ setTreeRevealRequest(null);
126
+ return;
127
+ }
128
+ if (isNodeVisible && files.loading && files.tree.length === 0) return;
129
+ if (isNodeVisible && !files.loading && files.tree.length === 0) {
130
+ handledRequestRef.current = requestKey;
131
+ pendingRequestRef.current = null;
132
+ setTreeRevealRequest(null);
133
+ return;
134
+ }
135
+ if (filePathVisibility(files.tree, requestedPath, isNodeVisible) === "hidden") {
136
+ handledRequestRef.current = requestKey;
137
+ pendingRequestRef.current = null;
138
+ setTreeRevealRequest(null);
101
139
  return;
102
140
  }
103
141
  handledRequestRef.current = requestKey;
104
142
  pendingRequestRef.current = null;
105
143
  setSelected(requestedPath);
144
+ onSelectedPathChange?.(requestedPath);
106
145
  setEditMode(false);
107
- }, [requestKey, requestedPath, requestedPathReady]);
146
+ setFocusLine(requestedLine != null && requestedLine > 0 ? requestedLine : null);
147
+ setTreeRevealRequest({ path: requestedPath, requestId: requestKey });
148
+ setViewReloadRevision((revision) => revision + 1);
149
+ }, [
150
+ files.loading,
151
+ files.tree,
152
+ isNodeVisible,
153
+ onSelectedPathChange,
154
+ requestKey,
155
+ requestedLine,
156
+ requestedPath,
157
+ requestedPathReady,
158
+ ]);
108
159
 
109
160
  // Side-by-side (tree left, viewer right) once the surface is wide enough;
110
161
  // stacked (tree over viewer) on a narrow dock. Tracked off the container so it
@@ -143,27 +194,52 @@ export function SandboxFiles({
143
194
  // The selected tree file opens in the viewer (read-only) or the editor (when
144
195
  // writable). Nothing is auto-selected — the pane waits for a tree click, so the
145
196
  // Files tab opens as a calm browser, not a diff.
146
- const viewPath = selected;
197
+ const selectedVisibility = selected
198
+ ? filePathVisibility(files.tree, selected, isNodeVisible)
199
+ : "unknown";
200
+ const visibilityPending = Boolean(isNodeVisible && files.loading && files.tree.length === 0);
201
+ const viewPath = selectedVisibility === "hidden" || visibilityPending ? null : selected;
202
+ useEffect(() => {
203
+ if (selected === null || selectedVisibility !== "hidden") return;
204
+ setSelected(null);
205
+ onSelectedPathChange?.(null);
206
+ setEditMode(false);
207
+ setFocusLine(null);
208
+ setTreeRevealRequest(null);
209
+ setLiveRequestedPath(null);
210
+ }, [onSelectedPathChange, selected, selectedVisibility]);
147
211
  const fileView = useFileView(
148
212
  viewPath,
149
213
  files.readFile,
150
- (files.contentRevision ?? 0) + viewReloadRevision,
214
+ `${files.contentRevision ?? 0}:${viewReloadRevision}`,
151
215
  );
152
216
 
217
+ useEffect(() => {
218
+ if (focusLine === null && viewReloadRevision > 0 && viewerScrollRef.current) {
219
+ viewerScrollRef.current.scrollTop = 0;
220
+ }
221
+ }, [focusLine, viewReloadRevision]);
222
+
153
223
  // Selecting a (different) file always returns to View — never drop the user into
154
224
  // an editor whose buffer belongs to the previously-selected path. Manual
155
225
  // navigation also consumes a pending guarded-file request: a late cold→warm
156
226
  // transition must never pull the user away from the file they chose meanwhile.
157
- const selectFile = useCallback((path: string) => {
158
- if (pendingRequestRef.current !== null) {
159
- handledRequestRef.current = pendingRequestRef.current;
160
- pendingRequestRef.current = null;
161
- }
162
- setSelected(path);
163
- setEditMode(false);
164
- setLiveRequestedPath(null);
165
- setViewReloadRevision(0);
166
- }, []);
227
+ const selectFile = useCallback(
228
+ (path: string) => {
229
+ if (pendingRequestRef.current !== null) {
230
+ handledRequestRef.current = pendingRequestRef.current;
231
+ pendingRequestRef.current = null;
232
+ }
233
+ setSelected(path);
234
+ onSelectedPathChange?.(path);
235
+ setEditMode(false);
236
+ setFocusLine(null);
237
+ setTreeRevealRequest(null);
238
+ setLiveRequestedPath(null);
239
+ setViewReloadRevision(0);
240
+ },
241
+ [onSelectedPathChange],
242
+ );
167
243
 
168
244
  // A tree file is editable only when it is a real, fully-loaded text file: not
169
245
  // binary (would corrupt on save) and not truncated (we only hold a PREFIX). The
@@ -181,10 +257,22 @@ export function SandboxFiles({
181
257
  const captureFileUnavailable =
182
258
  fileView.error instanceof CapturedFileUnavailableError ? fileView.error : null;
183
259
  const waitingForSelectedFile =
260
+ !workspaceError &&
184
261
  liveRequestedPath === viewPath &&
185
262
  (!liveWorkspaceReady || files.loading) &&
186
263
  captureFileUnavailable !== null;
187
264
 
265
+ if (workspaceError && !liveWorkspaceReady && files.source !== "capture") {
266
+ return (
267
+ <Notice className={className} title="Could not open live workspace" announce="alert">
268
+ <p>{workspaceError.message}</p>
269
+ {onWakeWorkspace ? (
270
+ <WakeButton onClick={onWakeWorkspace}>Retry live workspace</WakeButton>
271
+ ) : null}
272
+ </Notice>
273
+ );
274
+ }
275
+
188
276
  if (workspaceResting || workspaceWaking) {
189
277
  return (
190
278
  <div className={cn("h-full", className)} data-opengeni-workspace-resting>
@@ -263,7 +351,14 @@ export function SandboxFiles({
263
351
  >
264
352
  <FileBrowser
265
353
  result={files}
354
+ isNodeVisible={isNodeVisible}
266
355
  selectedPath={selected ?? undefined}
356
+ {...(treeRevealRequest
357
+ ? {
358
+ revealPath: treeRevealRequest.path,
359
+ revealPathRequestId: treeRevealRequest.requestId,
360
+ }
361
+ : {})}
267
362
  onSelectFile={selectFile}
268
363
  editable={editable}
269
364
  emptyState="This directory is empty"
@@ -295,7 +390,11 @@ export function SandboxFiles({
295
390
  data-opengeni-selected-file
296
391
  className="min-w-0 truncate font-og-mono text-og-xs text-og-fg-muted"
297
392
  >
298
- {selected ?? "No file selected"}
393
+ {selected
394
+ ? focusLine !== null
395
+ ? `${selected}:${focusLine}`
396
+ : selected
397
+ : "No file selected"}
299
398
  </span>
300
399
  {/* View/Edit toggle — only for a real, fully-loaded text file the editor
301
400
  can safely round-trip. Binary/truncated/read-only files never get an
@@ -311,7 +410,11 @@ export function SandboxFiles({
311
410
  />
312
411
  )}
313
412
  </div>
314
- <div className="min-h-0 flex-1 overflow-auto">
413
+ <div
414
+ ref={viewerScrollRef}
415
+ className="min-h-0 flex-1 overflow-auto"
416
+ data-opengeni-file-viewer-scroll
417
+ >
315
418
  {viewPath ? (
316
419
  showEditor && fileView.content !== null ? (
317
420
  <CodeEditor
@@ -327,6 +430,15 @@ export function SandboxFiles({
327
430
  {...(onEditIntent ? { onEditIntent } : {})}
328
431
  className="h-full"
329
432
  />
433
+ ) : workspaceError &&
434
+ (liveRequestedPath === viewPath || requestedPath === viewPath) &&
435
+ !liveWorkspaceReady ? (
436
+ <Notice title="Could not open live file" announce="alert">
437
+ <p>{workspaceError.message}</p>
438
+ {onWakeWorkspace ? (
439
+ <WakeButton onClick={onWakeWorkspace}>Retry live file</WakeButton>
440
+ ) : null}
441
+ </Notice>
330
442
  ) : waitingForSelectedFile ? (
331
443
  <Notice
332
444
  icon={
@@ -367,6 +479,12 @@ export function SandboxFiles({
367
479
  </Notice>
368
480
  ) : fileView.loading ? (
369
481
  <Notice announce="status">Loading {viewPath}…</Notice>
482
+ ) : fileView.imageUrl ? (
483
+ <RasterFilePreview
484
+ key={fileView.imageUrl}
485
+ src={fileView.imageUrl}
486
+ path={viewPath}
487
+ />
370
488
  ) : fileView.isBinary ? (
371
489
  <Notice>
372
490
  {viewPath} is a binary file ({fileView.sizeBytes ?? 0} bytes).
@@ -379,8 +497,9 @@ export function SandboxFiles({
379
497
  loaded). Editing is disabled to avoid corrupting the file.
380
498
  </div>
381
499
  )}
382
- {usePierre ? (
500
+ {usePierre && focusLine === null ? (
383
501
  <PierreFile
502
+ key={`${viewPath}:${viewReloadRevision}`}
384
503
  path={viewPath}
385
504
  contents={fileView.content}
386
505
  themeType={resolvedTheme}
@@ -391,6 +510,12 @@ export function SandboxFiles({
391
510
  }
392
511
  className="p-1"
393
512
  />
513
+ ) : focusLine !== null ? (
514
+ <LineNumberedFile
515
+ path={viewPath}
516
+ contents={fileView.content}
517
+ focusLine={focusLine}
518
+ />
394
519
  ) : (
395
520
  <pre className="overflow-auto whitespace-pre p-2 font-og-mono text-og-sm text-og-fg">
396
521
  {fileView.content}
@@ -402,18 +527,27 @@ export function SandboxFiles({
402
527
  )
403
528
  ) : // Nothing selected — the tree shows the whole workspace; pick a file.
404
529
  requestedPath && !requestedPathReady ? (
405
- <Notice
406
- icon={
407
- <LoaderCircleIcon
408
- className="size-5 animate-spin motion-reduce:animate-none"
409
- aria-hidden
410
- />
411
- }
412
- title="Waking sandbox"
413
- announce="status"
414
- >
415
- Opening {requestedPath} when the live workspace is ready…
416
- </Notice>
530
+ workspaceError ? (
531
+ <Notice title="Could not open live file" announce="alert">
532
+ <p>{workspaceError.message}</p>
533
+ {onWakeWorkspace ? (
534
+ <WakeButton onClick={onWakeWorkspace}>Retry live file</WakeButton>
535
+ ) : null}
536
+ </Notice>
537
+ ) : (
538
+ <Notice
539
+ icon={
540
+ <LoaderCircleIcon
541
+ className="size-5 animate-spin motion-reduce:animate-none"
542
+ aria-hidden
543
+ />
544
+ }
545
+ title="Waking sandbox"
546
+ announce="status"
547
+ >
548
+ Opening {requestedPath} when the live workspace is ready…
549
+ </Notice>
550
+ )
417
551
  ) : (
418
552
  <Notice icon={<FileCode2Icon className="size-5" aria-hidden />} title="Choose a file">
419
553
  Select a file in the tree to preview it.
@@ -431,13 +565,72 @@ function WakeButton({ children, onClick }: { children: ReactNode; onClick: () =>
431
565
  <button
432
566
  type="button"
433
567
  onClick={onClick}
434
- className="mt-1 inline-flex min-h-11 items-center justify-center rounded-og-md bg-og-accent-deep px-3 py-2 text-og-sm font-medium text-og-accent-fg shadow-sm transition-opacity hover:opacity-90 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-og-accent focus-visible:ring-offset-2 focus-visible:ring-offset-og-bg"
568
+ className="mt-1 inline-flex min-h-11 items-center justify-center rounded-og-md border border-og-primary-border bg-og-primary text-og-primary-fg px-3 py-2 text-og-sm font-medium transition-colors hover:bg-og-primary-hover focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-og-accent focus-visible:ring-offset-2 focus-visible:ring-offset-og-bg"
435
569
  >
436
570
  {children}
437
571
  </button>
438
572
  );
439
573
  }
440
574
 
575
+ function LineNumberedFile({
576
+ path,
577
+ contents,
578
+ focusLine,
579
+ }: {
580
+ path: string;
581
+ contents: string;
582
+ focusLine: number;
583
+ }) {
584
+ const lines = contents.split("\n");
585
+ const inRange = focusLine >= 1 && focusLine <= lines.length;
586
+ const targetRef = useRef<HTMLDivElement | null>(null);
587
+
588
+ useEffect(() => {
589
+ targetRef.current?.scrollIntoView({
590
+ block: "center",
591
+ behavior: prefersReducedMotion() ? "auto" : "smooth",
592
+ });
593
+ }, [path, focusLine, contents]);
594
+
595
+ return (
596
+ <div
597
+ className="h-full min-h-0 overflow-auto font-og-mono text-og-sm text-og-fg"
598
+ role="region"
599
+ aria-label={inRange ? `${path} at line ${focusLine}` : path}
600
+ >
601
+ {!inRange ? (
602
+ <p
603
+ className="border-b border-og-border bg-og-surface-1 px-2 py-1 text-og-xs text-og-fg-muted"
604
+ role="status"
605
+ >
606
+ Line {focusLine} is past the end of this file.
607
+ </p>
608
+ ) : null}
609
+ <div>
610
+ {lines.map((text, index) => {
611
+ const lineNumber = index + 1;
612
+ const focused = inRange && lineNumber === focusLine;
613
+ return (
614
+ <div
615
+ key={lineNumber}
616
+ ref={focused ? targetRef : undefined}
617
+ data-opengeni-file-line={lineNumber}
618
+ {...(focused ? { "data-opengeni-focus-line": "" } : {})}
619
+ aria-current={focused ? "location" : undefined}
620
+ className={cn("flex gap-3 px-2 py-0.5 leading-6", focused && "bg-og-accent-soft")}
621
+ >
622
+ <span className="w-11 shrink-0 select-none text-right tabular-nums text-og-fg-subtle">
623
+ {lineNumber}
624
+ </span>
625
+ <pre className="min-w-0 flex-1 whitespace-pre-wrap break-words">{text || " "}</pre>
626
+ </div>
627
+ );
628
+ })}
629
+ </div>
630
+ </div>
631
+ );
632
+ }
633
+
441
634
  function GitHeader({ git, loading }: { git: SandboxFilesGitSummary; loading: boolean }) {
442
635
  if (loading) {
443
636
  return (
@@ -474,8 +667,10 @@ function GitHeader({ git, loading }: { git: SandboxFilesGitSummary; loading: boo
474
667
  </span>
475
668
  {(git.ahead > 0 || git.behind > 0) && (
476
669
  <span className="flex shrink-0 items-center gap-1.5 text-og-xs text-og-fg-subtle">
477
- {git.ahead > 0 && <span>↑{git.ahead}</span>}
478
- {git.behind > 0 && <span>↓{git.behind}</span>}
670
+ {/* Small arrow glyphs can make axe's pixel overlap heuristic inconclusive.
671
+ Keep both counters in the same computed-contrast audit as the dirty count. */}
672
+ {git.ahead > 0 && <span data-contrast-audited>↑{git.ahead}</span>}
673
+ {git.behind > 0 && <span data-contrast-audited>↓{git.behind}</span>}
479
674
  </span>
480
675
  )}
481
676
  {dirty && (
@@ -523,6 +718,7 @@ function Segmented({
523
718
 
524
719
  type FileViewState = {
525
720
  content: string | null;
721
+ imageUrl?: string | null;
526
722
  isBinary: boolean;
527
723
  /** The backend truncated the read (size cap hit) — content is a PREFIX only.
528
724
  * Editing+saving such a file would write the prefix back and corrupt it, so
@@ -542,7 +738,7 @@ type FileViewState = {
542
738
  function useFileView(
543
739
  path: string | null,
544
740
  readFile: UseSandboxFilesResult["readFile"],
545
- reloadRevision = 0,
741
+ reloadRevision: string | number = 0,
546
742
  ): FileViewState {
547
743
  const previousPathRef = useRef<string | null>(null);
548
744
  const [state, setState] = useState<FileViewState>({
@@ -595,6 +791,8 @@ function useFileView(
595
791
  : res.content;
596
792
  setState({
597
793
  content,
794
+ imageUrl:
795
+ !res.truncated && res.encoding === "base64" ? rasterImageUrl(path, res.content) : null,
598
796
  isBinary: res.isBinary,
599
797
  truncated: res.truncated,
600
798
  sizeBytes: res.sizeBytes,
@@ -626,6 +824,38 @@ function useFileView(
626
824
  return state;
627
825
  }
628
826
 
827
+ /** Only raster formats belong in this preview; never interpret SVG/HTML as a document. */
828
+ function rasterImageUrl(path: string, content: string): string | null {
829
+ const extension = path.split(".").pop()?.toLowerCase();
830
+ const mime =
831
+ extension === "png"
832
+ ? "image/png"
833
+ : extension === "jpg" || extension === "jpeg"
834
+ ? "image/jpeg"
835
+ : extension === "gif"
836
+ ? "image/gif"
837
+ : extension === "webp"
838
+ ? "image/webp"
839
+ : null;
840
+ return mime ? `data:${mime};base64,${content}` : null;
841
+ }
842
+
843
+ function RasterFilePreview({ src, path }: { src: string; path: string }) {
844
+ const [failed, setFailed] = useState(false);
845
+ return failed ? (
846
+ <Notice title="Image preview unavailable" announce="alert">
847
+ Could not decode {path} as an image.
848
+ </Notice>
849
+ ) : (
850
+ <img
851
+ src={src}
852
+ alt={path}
853
+ onError={() => setFailed(true)}
854
+ className="max-w-full object-contain"
855
+ />
856
+ );
857
+ }
858
+
629
859
  /** Decode a base64 payload to a UTF-8 string (browser `atob` + TextDecoder). */
630
860
  function decodeBase64Utf8(b64: string): string {
631
861
  try {
@@ -671,7 +901,9 @@ function Notice({
671
901
  </span>
672
902
  ) : null}
673
903
  {title ? <p className="font-medium text-og-fg">{title}</p> : null}
674
- <div className="leading-5">{children}</div>
904
+ <div data-contrast-audited className="leading-5">
905
+ {children}
906
+ </div>
675
907
  </div>
676
908
  </div>
677
909
  );
@@ -1,5 +1,12 @@
1
1
  import type { TerminalCapability } from "@opengeni/sdk";
2
- import { type ReactNode, useEffect, useLayoutEffect, useRef, useState } from "react";
2
+ import {
3
+ type ReactNode,
4
+ useEffect,
5
+ useLayoutEffect,
6
+ useRef,
7
+ useState,
8
+ useSyncExternalStore,
9
+ } from "react";
3
10
  import { cn } from "../lib/cn";
4
11
  import { type TerminalStreamStatus, useTerminalStream } from "../hooks/use-terminal-stream";
5
12
  import type { UseSandboxTerminalResult } from "../hooks/use-sandbox-terminal";
@@ -7,6 +14,7 @@ import { resolveTerminalFont, xtermThemeFromTokens } from "../lib/xterm-theme";
7
14
  import { sandboxAcceptsLiveIo } from "../lib/sandbox-liveness";
8
15
  import { terminalCanAcquirePty } from "../lib/terminal-capability";
9
16
  import { attachRenderer, type RendererLoaders, type RendererTier } from "../lib/xterm-renderer";
17
+ import { sandboxTerminalPeers } from "../lib/workbench-peers";
10
18
 
11
19
  /**
12
20
  * A COMPLETE xterm `ITheme` (subset by intent, but every field xterm colors a
@@ -114,6 +122,19 @@ type XtermLike = {
114
122
  };
115
123
  };
116
124
  type FitAddonLike = { fit: () => void };
125
+ type TerminalPeerBundle = {
126
+ Terminal: new (options: Record<string, unknown>) => XtermLike;
127
+ FitAddon: new () => FitAddonLike;
128
+ WebLinksAddon: new (handler: (event: MouseEvent, uri: string) => void) => unknown;
129
+ loadWebgl?:
130
+ | (() => Promise<{
131
+ WebglAddon: new () => {
132
+ dispose: () => void;
133
+ onContextLoss?: (callback: () => void) => void;
134
+ };
135
+ }>)
136
+ | undefined;
137
+ };
117
138
 
118
139
  export type TerminalSurfaceState =
119
140
  | "loading"
@@ -237,6 +258,12 @@ export function SandboxTerminal({
237
258
  const wroteFirehoseRef = useRef(false);
238
259
  const bootActiveRef = useRef(false);
239
260
  const [ready, setReady] = useState(false);
261
+ const [loadError, setLoadError] = useState<Error | null>(null);
262
+ const peerRevision = useSyncExternalStore(
263
+ sandboxTerminalPeers.subscribe,
264
+ sandboxTerminalPeers.revision,
265
+ sandboxTerminalPeers.revision,
266
+ );
240
267
  const [inputReady, setInputReady] = useState(false);
241
268
  const [activated, setActivated] = useState(false);
242
269
 
@@ -353,12 +380,10 @@ export function SandboxTerminal({
353
380
 
354
381
  ensureXtermBaseCss();
355
382
 
383
+ setLoadError(null);
356
384
  void (async () => {
357
- const [{ Terminal }, { FitAddon }, { WebLinksAddon }] = await Promise.all([
358
- import("@xterm/xterm"),
359
- import("@xterm/addon-fit"),
360
- import("@xterm/addon-web-links"),
361
- ]);
385
+ const { Terminal, FitAddon, WebLinksAddon, loadWebgl } =
386
+ (await sandboxTerminalPeers.load()) as TerminalPeerBundle;
362
387
  if (disposed) return;
363
388
  await waitForSize(el);
364
389
  if (disposed) return;
@@ -397,13 +422,17 @@ export function SandboxTerminal({
397
422
  const failSet = forcedRendererFailures();
398
423
  const loaders: RendererLoaders = {
399
424
  webgl: async (onLoss) => {
425
+ if (disposed) throw new Error("Terminal was disposed");
400
426
  if (failSet.has("webgl")) throw new Error("forced webgl failure");
401
- const { WebglAddon } = await import("@xterm/addon-webgl");
427
+ if (!loadWebgl) throw new Error("WebGL terminal renderer is not enabled");
428
+ const { WebglAddon } = await loadWebgl();
429
+ if (disposed) throw new Error("Terminal was disposed");
402
430
  const addon = new WebglAddon() as unknown as {
403
431
  dispose: () => void;
404
432
  onContextLoss?: (cb: () => void) => void;
405
433
  };
406
434
  addon.onContextLoss?.(() => {
435
+ if (disposed) return;
407
436
  try {
408
437
  addon.dispose();
409
438
  } catch {
@@ -416,6 +445,7 @@ export function SandboxTerminal({
416
445
  },
417
446
  };
418
447
  await attachRenderer("webgl", loaders, (tier) => {
448
+ if (disposed) return;
419
449
  rendererRef.current = tier;
420
450
  el.setAttribute("data-og-term-renderer", tier);
421
451
  });
@@ -448,7 +478,9 @@ export function SandboxTerminal({
448
478
  }
449
479
  setReady(true);
450
480
  });
451
- })();
481
+ })().catch((cause: unknown) => {
482
+ if (!disposed) setLoadError(cause instanceof Error ? cause : new Error(String(cause)));
483
+ });
452
484
 
453
485
  return () => {
454
486
  disposed = true;
@@ -461,9 +493,9 @@ export function SandboxTerminal({
461
493
  bootActiveRef.current = false;
462
494
  setReady(false);
463
495
  };
464
- // Mount ONCE — see the effects below for the runtime option syncs.
496
+ // Mount once per peer registration; runtime options sync without a remount.
465
497
  // eslint-disable-next-line react-hooks/exhaustive-deps
466
- }, []);
498
+ }, [peerRevision]);
467
499
 
468
500
  // Sync stdin/cursor at runtime (NOT a remount) when interactivity flips, so the
469
501
  // projection→PTY handoff keeps the single Terminal instance + its scrollback.
@@ -621,7 +653,12 @@ export function SandboxTerminal({
621
653
  onPointerDownCapture={handleActivate}
622
654
  onFocusCapture={handleActivate}
623
655
  >
624
- {!ready && (placeholder ?? <TerminalPlaceholder />)}
656
+ {!ready &&
657
+ (loadError ? (
658
+ <p role="alert">{loadError.message}</p>
659
+ ) : (
660
+ (placeholder ?? <TerminalPlaceholder />)
661
+ ))}
625
662
  {/* Kept `visibility:hidden` until the first successful fit so the first
626
663
  VISIBLE frame is already correctly sized (no 80×24 flash — E4). */}
627
664
  <div