@opengeni/react 1.0.1 → 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 +651 -21
  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 +6 -3
  302. package/dist/realtime.js +133 -74
  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 +133 -46
  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
@@ -45,6 +45,7 @@ import { xtermThemeFromTokens } from "../lib/xterm-theme";
45
45
  import { sandboxAcceptsLiveIo } from "../lib/sandbox-liveness";
46
46
  import type { BrowserFrameWebSocketFactory } from "../hooks/use-browser-frame-stream";
47
47
  import type { ComputerFrameWebSocketFactory } from "../hooks/use-computer-frame-stream";
48
+ import type { FileNodeVisibilityPredicate } from "../file-node-visibility";
48
49
  import { useSessionCapabilities } from "../hooks/use-session-capabilities";
49
50
  import { useSandboxFiles } from "../hooks/use-sandbox-files";
50
51
  import {
@@ -55,21 +56,49 @@ import {
55
56
  import { useSandboxTerminal } from "../hooks/use-sandbox-terminal";
56
57
  import { useWorkspaceCapture } from "../hooks/use-workspace-capture";
57
58
  import { useMachineChip, type MachineChip } from "../hooks/use-machine-chip";
58
- import { useMachines } from "../hooks/use-machines";
59
+ import { MACHINES_SESSION_POLL_MS, useMachines } from "../hooks/use-machines";
59
60
  import type { MachineView } from "../types/machines";
60
- import { SandboxFiles } from "./sandbox-files";
61
+ import type { SandboxFilesProps } from "./sandbox-files";
61
62
  import { WorkbenchChanges } from "./workbench-changes";
62
63
  import { SandboxTerminal, type XtermTheme } from "./sandbox-terminal";
63
64
  import { WorkspaceDock, type WorkspaceDockProps, type WorkspaceTab } from "./workspace-dock";
64
65
 
66
+ const LazySandboxFiles = lazy(() =>
67
+ import("./sandbox-files")
68
+ .then(({ SandboxFiles }) => ({ default: SandboxFiles }))
69
+ // A host may already have attempted stale-deployment recovery. Keep an
70
+ // optional chunk failure inside Files rather than unmounting the chat.
71
+ .catch(() => ({ default: FilesLoadFailed })),
72
+ );
73
+
74
+ function FilesLoadFailed() {
75
+ return (
76
+ <CenteredState tone="danger" icon={<TriangleAlertIcon className="size-5" aria-hidden />}>
77
+ <p className="text-og-sm font-medium text-og-fg">Files could not be loaded.</p>
78
+ <DockActionButton onClick={() => window.location.reload()}>
79
+ <RefreshCwIcon className="size-3" aria-hidden />
80
+ Reload
81
+ </DockActionButton>
82
+ </CenteredState>
83
+ );
84
+ }
85
+
86
+ function FilesTabBody(props: SandboxFilesProps) {
87
+ return (
88
+ <Suspense fallback={<WorkbenchSurfaceLoading name="Files" />}>
89
+ <LazySandboxFiles {...props} />
90
+ </Suspense>
91
+ );
92
+ }
93
+
65
94
  const LazyBrowserViewer = lazy(async () => {
66
- const viewers = await import("./interactive-workbench-viewers");
67
- return { default: viewers.BrowserViewer };
95
+ const { BrowserViewer } = await import("./browser-viewer");
96
+ return { default: BrowserViewer };
68
97
  });
69
98
 
70
99
  const LazyComputerViewer = lazy(async () => {
71
- const viewers = await import("./interactive-workbench-viewers");
72
- return { default: viewers.ComputerViewer };
100
+ const { ComputerViewer } = await import("./computer-viewer");
101
+ return { default: ComputerViewer };
73
102
  });
74
103
 
75
104
  /** A host-routed notification (replaces the app-only `sonner` toast coupling). */
@@ -101,6 +130,12 @@ function isWorkbenchSurface(value: string): value is SandboxWorkspaceSurface {
101
130
  return (WORKBENCH_SURFACES as readonly string[]).includes(value);
102
131
  }
103
132
 
133
+ function isCanonicalAbsoluteSandboxPath(value: string | null | undefined): boolean {
134
+ if (!value) return false;
135
+ const portable = value.replaceAll("\\", "/");
136
+ return portable.startsWith("/") || /^[A-Za-z]:\//u.test(portable);
137
+ }
138
+
104
139
  function sourceDrivenDefaultTab(
105
140
  hasChanges: boolean,
106
141
  changesEnabled: boolean,
@@ -112,31 +147,7 @@ function sourceDrivenDefaultTab(
112
147
  return null;
113
148
  }
114
149
 
115
- function captureDegradedMessage(reason: string): string {
116
- switch (reason) {
117
- case "repository_discovery_timed_out":
118
- return "Workspace capture is incomplete because repository discovery timed out. Live files remain authoritative.";
119
- case "repository_discovery_result_limit_exceeded":
120
- return "Workspace capture is incomplete because the repository limit was exceeded. Live files remain authoritative.";
121
- case "repository_read_unavailable":
122
- return "Workspace capture is incomplete because repository changes could not be read. Live files remain authoritative.";
123
- default:
124
- return "Workspace capture is incomplete because repository discovery failed. Live files remain authoritative.";
125
- }
126
- }
127
-
128
- function WorkbenchTabLabel({ icon, children }: { icon: ReactNode; children: ReactNode }) {
129
- return (
130
- <span className="inline-flex items-center gap-1.5">
131
- <span className="[&>svg]:size-3.5" aria-hidden>
132
- {icon}
133
- </span>
134
- <span>{children}</span>
135
- </span>
136
- );
137
- }
138
-
139
- function WorkbenchSurfaceLoading({ name }: { name: "Browser" | "Computer" }) {
150
+ function WorkbenchSurfaceLoading({ name }: { name: "Files" | "Browser" | "Desktop" }) {
140
151
  return (
141
152
  <CenteredState
142
153
  icon={
@@ -218,10 +229,51 @@ function sandboxProvisionInFlight(events: SessionEvent[]): boolean {
218
229
  return inFlight;
219
230
  }
220
231
 
232
+ /**
233
+ * Whether this session currently owns an admitted agent turn. Automatic live
234
+ * Files/Git reads pause across the whole turn: command boundaries are not a safe
235
+ * gap because the next tool can dispatch before a remote provider read releases
236
+ * its sandbox holder. Existing/captured content remains usable, and the terminal
237
+ * turn event resumes one authoritative refresh.
238
+ */
239
+ function workspaceTurnInFlight(events: SessionEvent[]): boolean {
240
+ const activeTurnIds = new Set<string>();
241
+ let anonymousTurnInFlight = false;
242
+ let sessionOwnsWorkspace = false;
243
+ for (const event of events) {
244
+ if (event.type === "session.status.changed") {
245
+ const status =
246
+ event.payload && typeof event.payload === "object" && !Array.isArray(event.payload)
247
+ ? (event.payload as Record<string, unknown>).status
248
+ : null;
249
+ sessionOwnsWorkspace = status === "running" || status === "recovering";
250
+ continue;
251
+ }
252
+ if (event.type === "turn.started") {
253
+ if (event.turnId) activeTurnIds.add(event.turnId);
254
+ else anonymousTurnInFlight = true;
255
+ continue;
256
+ }
257
+ if (
258
+ event.type !== "turn.completed" &&
259
+ event.type !== "turn.failed" &&
260
+ event.type !== "turn.cancelled" &&
261
+ event.type !== "turn.superseded"
262
+ ) {
263
+ continue;
264
+ }
265
+ if (event.turnId) activeTurnIds.delete(event.turnId);
266
+ else anonymousTurnInFlight = false;
267
+ }
268
+ // The retained event window preserves the latest status even after a very
269
+ // long turn has evicted its original turn.started event.
270
+ return sessionOwnsWorkspace || anonymousTurnInFlight || activeTurnIds.size > 0;
271
+ }
272
+
221
273
  export type WorkspaceMachine = {
222
274
  /** Whether at least one built-in workbench surface is enabled. */
223
275
  enabled: boolean;
224
- /** The derived live/waking/offline chip model. */
276
+ /** The derived live/waking/sleeping-or-offline chip model. */
225
277
  chip: MachineChip;
226
278
  /** The machine these surfaces are bound to (the Modal group box or a
227
279
  * self-hosted machine), or null while the fleet is still resolving. */
@@ -256,14 +308,27 @@ export type UseSandboxWorkspaceTabsOptions = ClientOverride & {
256
308
  browserWebSocketFactory?: BrowserFrameWebSocketFactory | undefined;
257
309
  /** Alternate Computer frame transport for non-browser runtimes and deterministic tests. */
258
310
  computerWebSocketFactory?: ComputerFrameWebSocketFactory | undefined;
311
+ /** Host-owned setup page or store listing for attaching an existing Chrome profile. */
312
+ browserExtensionSetupUrl?: string | undefined;
259
313
  /** File requested by a Changes guard. The Files surface defers the read until
260
314
  * the sandbox is live, then reveals this path. */
261
315
  requestedFilePath?: string | null | undefined;
262
316
  /** Unique identity for `requestedFilePath`, including repeated requests for the
263
317
  * same path. */
264
318
  requestedFileRequestId?: string | number | null | undefined;
319
+ /** 1-based line to reveal after `requestedFilePath` opens. */
320
+ requestedFileLine?: number | null | undefined;
265
321
  /** Route a guarded diff into the host's Files tab. */
266
322
  onOpenFile?: ((path: string) => void) | undefined;
323
+ /** Restore and report navigation inside the built-in workbench surfaces. */
324
+ initialFilePath?: string | null | undefined;
325
+ onFilePathChange?: ((path: string | null) => void) | undefined;
326
+ /** Presentation-only filter for Files tree nodes and selected-file viewing. */
327
+ isFileNodeVisible?: FileNodeVisibilityPredicate | undefined;
328
+ initialBrowserSessionId?: string | null | undefined;
329
+ onBrowserSessionIdChange?: ((browserSessionId: string | null) => void) | undefined;
330
+ initialComputerSessionId?: string | null | undefined;
331
+ onComputerSessionIdChange?: ((computerSessionId: string | null) => void) | undefined;
267
332
  /** Navigate the host dock to one exact linked ComputerSession. */
268
333
  onOpenComputerSession?: ((computerSessionId: string) => void) | undefined;
269
334
  requestedComputerSessionId?: string | null | undefined;
@@ -274,7 +339,8 @@ export type UseSandboxWorkspaceTabsResult = {
274
339
  /** Changes | Files | Terminal | Browser | Desktop (capability-gated where noted). */
275
340
  tabs: WorkspaceTab[];
276
341
  /** The source-driven default tab: Changes when the first authoritative capture
277
- * or live Git result has changes, else Files (a host `initialTab` overrides).
342
+ * has changes, else Files (a host `initialTab` overrides). Choosing a tab
343
+ * never performs hidden live workspace I/O.
278
344
  * null while that source resolves, or permanently when neither Changes nor
279
345
  * Files is enabled; the choice latches once. */
280
346
  defaultTab: string | null;
@@ -312,9 +378,18 @@ export function useSandboxWorkspaceTabs(
312
378
  onNotify,
313
379
  browserWebSocketFactory,
314
380
  computerWebSocketFactory,
381
+ browserExtensionSetupUrl,
315
382
  requestedFilePath,
316
383
  requestedFileRequestId,
384
+ requestedFileLine,
317
385
  onOpenFile,
386
+ initialFilePath,
387
+ onFilePathChange,
388
+ isFileNodeVisible,
389
+ initialBrowserSessionId,
390
+ onBrowserSessionIdChange,
391
+ initialComputerSessionId,
392
+ onComputerSessionIdChange,
318
393
  onOpenComputerSession,
319
394
  requestedComputerSessionId,
320
395
  requestedComputerRequestId,
@@ -338,7 +413,7 @@ export function useSandboxWorkspaceTabs(
338
413
  ...(placement ? { placement } : {}),
339
414
  });
340
415
  if (response.operation.state !== "completed" || response.session.lifecycle !== "active") {
341
- throw new Error(response.operation.error?.message ?? "The computer could not be opened.");
416
+ throw new Error(response.operation.error?.message ?? "The desktop could not be opened.");
342
417
  }
343
418
  return {
344
419
  id: response.session.id,
@@ -356,6 +431,7 @@ export function useSandboxWorkspaceTabs(
356
431
  const resolvedActiveTab = activeTab ?? initialTab;
357
432
  const changesActive = resolvedActiveTab === WORKBENCH_TAB_CHANGES;
358
433
  const filesActive = resolvedActiveTab === WORKBENCH_TAB_FILES;
434
+ const turnInFlight = workspaceTurnInFlight(events);
359
435
  const surfaceIdentity = WORKBENCH_SURFACES.filter((surface) => surfaceSet.has(surface)).join(",");
360
436
 
361
437
  // The two box-warming INTENTS, each off by default and each
@@ -369,6 +445,11 @@ export function useSandboxWorkspaceTabs(
369
445
  const warmIntents =
370
446
  storedWarmIntents.sessionId === sessionId ? storedWarmIntents : emptyWarmIntents(sessionId);
371
447
  const { warmTerminal, warmFiles } = warmIntents;
448
+ // A host-requested file is itself explicit live-file intent. Derive the wake
449
+ // directly from the request instead of relying on a follow-up effect to copy
450
+ // it into local state; otherwise a missing or delayed effect leaves the file
451
+ // waiting for a sandbox that this hook never asks to start.
452
+ const filesWarmRequested = warmFiles || Boolean(requestedFilePath);
372
453
  const requestWarmIntent = useCallback(
373
454
  (intent: Exclude<keyof SessionWarmIntents, "sessionId">) => {
374
455
  setStoredWarmIntents((previous) => {
@@ -378,13 +459,12 @@ export function useSandboxWorkspaceTabs(
378
459
  },
379
460
  [sessionId],
380
461
  );
381
-
382
462
  // The session's machine fleet + the active-sandbox pointer. Drives the header
383
- // chip (which machine + its connection state). Polls slowly — ambient context.
463
+ // chip (which machine + its connection state). Shares the session list poll.
384
464
  const machines = useMachines({
385
465
  workspaceId,
386
466
  sessionId,
387
- pollIntervalMs: 8000,
467
+ pollIntervalMs: MACHINES_SESSION_POLL_MS,
388
468
  enabled: machineSurfaceEnabled,
389
469
  });
390
470
  const activeMachine: MachineView | null =
@@ -399,7 +479,7 @@ export function useSandboxWorkspaceTabs(
399
479
  attachTerminal: terminalEnabled && warmTerminal,
400
480
  // Explicit live-file intent only — NOT "the Files tab is open". A cold edit
401
481
  // or guarded-file open wakes the box; a glance at the tree/diff does not.
402
- attachFiles: workspaceDataEnabled && warmFiles,
482
+ attachFiles: workspaceDataEnabled && filesWarmRequested,
403
483
  });
404
484
  const capabilities = caps.capabilities;
405
485
  const liveness = capabilities?.liveness;
@@ -409,6 +489,9 @@ export function useSandboxWorkspaceTabs(
409
489
  // is still pending.
410
490
  const liveIoLiveness = liveness ?? null;
411
491
  const fileSystemOn = capabilities?.FileSystem.available ?? false;
492
+ const fileSystemRoute = capabilities
493
+ ? { epoch: capabilities.leaseEpoch, root: capabilities.FileSystem.root }
494
+ : undefined;
412
495
  // The FS is writable only when it's live AND not read-only. A self-hosted box
413
496
  // that's offline (or any read-only advertisement) or a capture-served cold tree
414
497
  // must not offer create/rename/delete/edit affordances — you cannot mutate a
@@ -487,29 +570,22 @@ export function useSandboxWorkspaceTabs(
487
570
  if (advertised.length > 0) return advertised;
488
571
  return captureState.capture?.repos.map((repo) => repo.root) ?? [];
489
572
  }, [capabilities?.Git.repos, captureState.capture]);
490
- const notifiedCaptureDegradedReason = useRef<{
491
- sessionId: string;
492
- reason: string | null;
493
- }>({
494
- sessionId,
495
- reason: null,
496
- });
497
- if (notifiedCaptureDegradedReason.current.sessionId !== sessionId) {
498
- notifiedCaptureDegradedReason.current = { sessionId, reason: null };
499
- }
500
- useEffect(() => {
501
- const reason = captureState.degradedReason;
502
- if (!reason || notifiedCaptureDegradedReason.current.reason === reason) return;
503
- notifiedCaptureDegradedReason.current = { sessionId, reason };
504
- onNotify?.({ kind: "error", message: captureDegradedMessage(reason) });
505
- }, [sessionId, captureState.degradedReason, onNotify]);
506
-
507
573
  const files = useSandboxFiles(sessionId, {
508
574
  events,
509
575
  // No passive Channel-A reads while cold, even after a conclusive capture
510
576
  // miss. A missing capture gets an explicit "Open live workspace" gate.
511
577
  enabled: filesEnabled && (captureAvailable || (fileSystemOn && liveWorkspaceExpected)),
512
- active: filesActive,
578
+ // A cold sandbox can become warm while the first agent command still owns
579
+ // startup. Do not race that command with an automatic Files read. Keeping
580
+ // this fence at turn scope also avoids unsafe millisecond gaps between
581
+ // sequential tool calls; rendered state and explicit user actions remain.
582
+ active: filesActive && !turnInFlight,
583
+ // A deliberate canonical absolute-path open browses in the selected target's
584
+ // advertised namespace, so the authoritative tree and link share exact paths.
585
+ ...(isCanonicalAbsoluteSandboxPath(requestedFilePath) && capabilities?.FileSystem.root
586
+ ? { rootPath: capabilities.FileSystem.root }
587
+ : {}),
588
+ ...(fileSystemRoute ? { route: fileSystemRoute } : {}),
513
589
  repoPaths,
514
590
  liveness: liveIoLiveness,
515
591
  capture: captureState.capture,
@@ -550,10 +626,11 @@ export function useSandboxWorkspaceTabs(
550
626
  : changesComparison === "branch"
551
627
  ? workspaceDataEnabled && (captureSupportsBranch || (gitOn && liveWorkspaceExpected))
552
628
  : workspaceDataEnabled && gitOn && liveWorkspaceExpected,
553
- // Before the dock chooses its source-driven default, Git is the sole probe
554
- // that may need to resolve that choice on a live workspace. Files remains
555
- // dormant, avoiding the old duplicate full-tree read.
556
- active: changesActive || resolvedActiveTab === null,
629
+ // Live Git belongs to the visible Changes surface. In particular, do not
630
+ // turn an unresolved/default tab into a hidden provider read: that races the
631
+ // agent's own sandbox commands and used to refresh after every tool output
632
+ // even while Files was visibly selected.
633
+ active: changesActive && !turnInFlight,
557
634
  repoPaths,
558
635
  liveness: liveIoLiveness,
559
636
  comparison: changesComparison,
@@ -597,19 +674,17 @@ export function useSandboxWorkspaceTabs(
597
674
  capabilitiesState: caps.state,
598
675
  activeMachineState: activeMachine?.state ?? null,
599
676
  activeIsSelfhosted: activeMachine?.kind === "selfhosted",
600
- wantsWarm: (terminalEnabled && warmTerminal) || (workspaceDataEnabled && warmFiles),
677
+ wantsWarm: (terminalEnabled && warmTerminal) || (workspaceDataEnabled && filesWarmRequested),
601
678
  capturedAt: captureState.capturedAt,
602
679
  });
603
680
  const workspaceWaking = chip.state === "waking";
604
681
 
605
- // The pre-paint default tab is decided from the first AUTHORITATIVE workspace
606
- // source. A capture wins immediately on the cold/offline fast path; a warm box
607
- // waits for live Git so a prior snapshot can never outrank the current tree.
608
- // When the GET says no capture exists, `fileCount: 0` does NOT itself mean the
609
- // working tree is clean. A captured-revision announce can
610
- // resolve Changes earlier, but a pure embedder with no event preload still gets
611
- // the correct live default. The choice latches once so later edits never steal
612
- // the user's current tab.
682
+ // The pre-paint default comes only from the durable capture. Default selection
683
+ // must never dispatch live provider work: a live Git probe can overlap the
684
+ // agent's first command, and an uncontrolled dock used to keep that probe
685
+ // active forever after it visibly selected Files. A capture with reviewable
686
+ // changes opens Changes; no capture (or an empty one) opens Files. The choice
687
+ // latches once so later edits never steal the user's current tab.
613
688
  const defaultIdentity = `${sessionId}\u0000${surfaceIdentity}`;
614
689
  const defaultTabRef = useRef<{ identity: string; value: string | null }>({
615
690
  identity: defaultIdentity,
@@ -618,62 +693,32 @@ export function useSandboxWorkspaceTabs(
618
693
  if (defaultTabRef.current.identity !== defaultIdentity) {
619
694
  defaultTabRef.current = { identity: defaultIdentity, value: null };
620
695
  }
621
- const captureIsAuthoritative =
622
- !liveWorkspaceExpected && (liveness !== undefined || caps.error !== null);
623
696
  const captureHasChanges =
624
697
  (captureState.fileCount ?? 0) > 0 ||
625
698
  (captureState.capture?.repos.some((repo) => (repo.branchDiff?.length ?? 0) > 0) ?? false);
626
699
  const captureUnavailable =
627
- (captureState.fileCount === 0 && !captureHasChanges) || captureState.error !== null;
628
- const implicitBranchFallbackPending =
629
- changesComparison === "branch" &&
630
- git.error !== null &&
631
- storedChangesComparison?.sessionId !== sessionId;
700
+ !captureState.loading &&
701
+ ((captureState.fileCount === 0 && !captureHasChanges) || captureState.error !== null);
632
702
  if (defaultTabRef.current.value === null) {
633
703
  if (initialTab && (!isWorkbenchSurface(initialTab) || surfaceSet.has(initialTab))) {
634
704
  defaultTabRef.current.value = initialTab;
635
- } else if (git.source === "live") {
636
- defaultTabRef.current.value = sourceDrivenDefaultTab(
637
- git.diff.length > 0,
638
- changesEnabled,
639
- filesEnabled,
640
- );
641
- } else if (
642
- captureIsAuthoritative &&
643
- captureState.fileCount !== null &&
644
- captureState.available
645
- ) {
705
+ } else if (captureState.fileCount !== null && captureState.available) {
646
706
  defaultTabRef.current.value = sourceDrivenDefaultTab(
647
707
  captureHasChanges,
648
708
  changesEnabled,
649
709
  filesEnabled,
650
710
  );
711
+ } else if (captureUnavailable && initialWorkspaceTab(events) === WORKBENCH_TAB_CHANGES) {
712
+ defaultTabRef.current.value = sourceDrivenDefaultTab(true, changesEnabled, filesEnabled);
651
713
  } else if (
652
- captureIsAuthoritative &&
653
- captureUnavailable &&
654
- initialWorkspaceTab(events) === WORKBENCH_TAB_CHANGES
714
+ !captureState.loading &&
715
+ (captureState.fileCount !== null || captureState.error !== null)
655
716
  ) {
656
- defaultTabRef.current.value = sourceDrivenDefaultTab(true, changesEnabled, filesEnabled);
657
- } else if (captureUnavailable && caps.error) {
658
- // The Changes surface owns the truthful sandbox-unavailable state + retry.
659
- // Files would misleadingly describe this as a missing filesystem.
660
- defaultTabRef.current.value = sourceDrivenDefaultTab(true, changesEnabled, filesEnabled);
661
- } else if (captureIsAuthoritative && captureState.fileCount !== null && captureUnavailable) {
662
- // No durable review surface exists and the machine is resting. Files owns
663
- // the explicit wake gate; do not issue a live Git probe merely to choose a
664
- // tab.
665
- defaultTabRef.current.value = sourceDrivenDefaultTab(false, changesEnabled, filesEnabled);
666
- } else if (captureState.available && git.error && captureState.fileCount !== null) {
667
- // A warm live read failed but the durable capture is intact: retain an
668
- // immediate, deterministic review surface instead of hanging unresolved.
669
- defaultTabRef.current.value = sourceDrivenDefaultTab(
670
- captureHasChanges,
671
- changesEnabled,
672
- filesEnabled,
673
- );
674
- } else if (captureUnavailable && git.error && !implicitBranchFallbackPending) {
675
- // No capture and live Git failed: Files is the least surprising fallback
676
- // after the implicit branch-to-working fallback has also had its chance.
717
+ // Metadata may arrive before a signed manifest. While that manifest is
718
+ // loading, neither a positive count nor zero (committed-only changes)
719
+ // proves an unavailable capture, so leave the default unresolved.
720
+ // No durable review surface exists. Files owns the explicit live-workspace
721
+ // gate; a user can open Changes deliberately if they need a fresh Git read.
677
722
  defaultTabRef.current.value = sourceDrivenDefaultTab(false, changesEnabled, filesEnabled);
678
723
  }
679
724
  }
@@ -687,7 +732,8 @@ export function useSandboxWorkspaceTabs(
687
732
  if (changesEnabled)
688
733
  list.push({
689
734
  id: WORKBENCH_TAB_CHANGES,
690
- label: <WorkbenchTabLabel icon={<GitCompareArrowsIcon />}>Changes</WorkbenchTabLabel>,
735
+ label: "Changes",
736
+ icon: <GitCompareArrowsIcon />,
691
737
  badge: dirtyCount > 0 ? <DirtyBadge count={dirtyCount} /> : undefined,
692
738
  content: (
693
739
  <ChangesTabBody
@@ -695,6 +741,7 @@ export function useSandboxWorkspaceTabs(
695
741
  comparison={changesComparison}
696
742
  onComparisonChange={setChangesComparison}
697
743
  captureAvailable={captureAvailable}
744
+ captureDegraded={captureState.degradedReason !== null}
698
745
  captureRevision={captureState.revision}
699
746
  capturePending={capturePending}
700
747
  liveWorkspaceExpected={liveWorkspaceExpected}
@@ -719,12 +766,14 @@ export function useSandboxWorkspaceTabs(
719
766
  if (filesEnabled)
720
767
  list.push({
721
768
  id: WORKBENCH_TAB_FILES,
722
- label: <WorkbenchTabLabel icon={<FileCode2Icon />}>Files</WorkbenchTabLabel>,
769
+ label: "Files",
770
+ icon: <FileCode2Icon />,
723
771
  content: (
724
- <SandboxFiles
772
+ <FilesTabBody
725
773
  key={sessionId}
726
774
  files={files}
727
775
  git={git}
776
+ isNodeVisible={isFileNodeVisible}
728
777
  fileSystemAvailable={fileSystemOn || captureAvailable}
729
778
  editable={
730
779
  filesEditable && files.source === "live" && files.error === null && !files.loading
@@ -738,7 +787,20 @@ export function useSandboxWorkspaceTabs(
738
787
  }
739
788
  workspaceWaking={!liveWorkspaceExpected && !captureAvailable && workspaceWaking}
740
789
  liveWorkspaceReady={liveWorkspaceExpected}
741
- onWakeWorkspace={() => requestWarmIntent("warmFiles")}
790
+ workspaceError={
791
+ caps.error ??
792
+ (caps.viewerCapReached
793
+ ? new Error(
794
+ "The live workspace viewer limit has been reached. Close another viewer and retry.",
795
+ )
796
+ : filesWarmRequested && caps.state === "on-demand" && !fileSystemOn
797
+ ? new Error("This machine does not currently expose a live file system.")
798
+ : null)
799
+ }
800
+ onWakeWorkspace={() => {
801
+ if (filesWarmRequested) caps.renegotiate();
802
+ else requestWarmIntent("warmFiles");
803
+ }}
742
804
  {...(requestedFilePath
743
805
  ? {
744
806
  requestedPath: requestedFilePath,
@@ -746,11 +808,16 @@ export function useSandboxWorkspaceTabs(
746
808
  ? { requestedPathRequestId: requestedFileRequestId }
747
809
  : {}),
748
810
  requestedPathReady: sandboxAcceptsLiveIo(liveness),
811
+ ...(requestedFileLine != null && requestedFileLine > 0
812
+ ? { requestedLine: requestedFileLine }
813
+ : {}),
749
814
  }
750
815
  : {})}
751
816
  // Ordinary capture browsing does not warm a box. The first edit — or an
752
817
  // explicit guarded-file open from Changes — is deliberate live-file intent.
753
818
  onEditIntent={() => requestWarmIntent("warmFiles")}
819
+ initialSelectedPath={initialFilePath}
820
+ onSelectedPathChange={onFilePathChange}
754
821
  className="h-full"
755
822
  />
756
823
  ),
@@ -760,7 +827,8 @@ export function useSandboxWorkspaceTabs(
760
827
  if (terminalOn) {
761
828
  list.push({
762
829
  id: WORKBENCH_TAB_TERMINAL,
763
- label: <WorkbenchTabLabel icon={<SquareTerminalIcon />}>Terminal</WorkbenchTabLabel>,
830
+ label: "Terminal",
831
+ icon: <SquareTerminalIcon />,
764
832
  content: (
765
833
  <div className="h-full bg-og-bg p-1">
766
834
  <SandboxTerminal
@@ -785,7 +853,8 @@ export function useSandboxWorkspaceTabs(
785
853
  if (browserEnabled) {
786
854
  list.push({
787
855
  id: WORKBENCH_TAB_BROWSER,
788
- label: <WorkbenchTabLabel icon={<Globe2Icon />}>Browser</WorkbenchTabLabel>,
856
+ label: "Browser",
857
+ icon: <Globe2Icon />,
789
858
  content: (
790
859
  <Suspense fallback={<WorkbenchSurfaceLoading name="Browser" />}>
791
860
  <LazyBrowserViewer
@@ -802,10 +871,14 @@ export function useSandboxWorkspaceTabs(
802
871
  // start BrowserViewer—the lazy panel is still unmounted until the
803
872
  // user/agent first visits it.
804
873
  enabled={workspaceVisible}
874
+ active={resolvedActiveTab === WORKBENCH_TAB_BROWSER}
805
875
  onNotify={onNotify}
876
+ initialBrowserSessionId={initialBrowserSessionId}
877
+ onBrowserSessionIdChange={onBrowserSessionIdChange}
806
878
  {...(desktopEnabled ? { createLinkedComputer } : {})}
807
879
  {...(onOpenComputerSession ? { onOpenComputer: onOpenComputerSession } : {})}
808
880
  {...(browserWebSocketFactory ? { webSocketFactory: browserWebSocketFactory } : {})}
881
+ {...(browserExtensionSetupUrl ? { browserExtensionSetupUrl } : {})}
809
882
  className="h-full"
810
883
  />
811
884
  </Suspense>
@@ -818,9 +891,10 @@ export function useSandboxWorkspaceTabs(
818
891
  if (desktopEnabled) {
819
892
  list.push({
820
893
  id: WORKBENCH_TAB_DESKTOP,
821
- label: <WorkbenchTabLabel icon={<MonitorIcon />}>Computer</WorkbenchTabLabel>,
894
+ label: "Desktop",
895
+ icon: <MonitorIcon />,
822
896
  content: (
823
- <Suspense fallback={<WorkbenchSurfaceLoading name="Computer" />}>
897
+ <Suspense fallback={<WorkbenchSurfaceLoading name="Desktop" />}>
824
898
  <LazyComputerViewer
825
899
  key={sessionId}
826
900
  client={client}
@@ -832,6 +906,8 @@ export function useSandboxWorkspaceTabs(
832
906
  // second and later Computer opens local-machine fast.
833
907
  enabled={workspaceVisible}
834
908
  onNotify={onNotify}
909
+ initialComputerSessionId={initialComputerSessionId}
910
+ onComputerSessionIdChange={onComputerSessionIdChange}
835
911
  requestedComputerSessionId={requestedComputerSessionId}
836
912
  requestedComputerRequestId={requestedComputerRequestId}
837
913
  {...(computerWebSocketFactory ? { webSocketFactory: computerWebSocketFactory } : {})}
@@ -852,11 +928,20 @@ export function useSandboxWorkspaceTabs(
852
928
  browserEnabled,
853
929
  desktopEnabled,
854
930
  captureAvailable,
931
+ captureState.degradedReason,
855
932
  dirtyCount,
856
933
  warmTerminal,
857
934
  requestedFilePath,
858
935
  requestedFileRequestId,
936
+ requestedFileLine,
859
937
  onOpenFile,
938
+ initialFilePath,
939
+ onFilePathChange,
940
+ isFileNodeVisible,
941
+ initialBrowserSessionId,
942
+ onBrowserSessionIdChange,
943
+ initialComputerSessionId,
944
+ onComputerSessionIdChange,
860
945
  onOpenComputerSession,
861
946
  requestedComputerSessionId,
862
947
  requestedComputerRequestId,
@@ -879,6 +964,8 @@ export function useSandboxWorkspaceTabs(
879
964
  caps.state,
880
965
  caps.error,
881
966
  caps.viewerCapReached,
967
+ caps.renegotiate,
968
+ filesWarmRequested,
882
969
  requestWarmIntent,
883
970
  createLinkedComputer,
884
971
  ]);
@@ -913,14 +1000,39 @@ export type SandboxWorkspaceProps = ClientOverride & {
913
1000
  /** Host tabs injected AFTER the workbench tabs (e.g. a "Debug" tab). */
914
1001
  trailingTabs?: WorkspaceTab[] | undefined;
915
1002
  /** Override the pre-paint default tab (e.g. a host landing tab id). When
916
- * omitted the workbench decides from capture, then live Git when no capture exists. */
1003
+ * omitted the workbench decides from the durable workspace capture. */
917
1004
  initialTab?: string | undefined;
1005
+ onActiveTabChange?: ((activeTab: string) => void) | undefined;
1006
+ /** Open a built-in or host-injected tab. A new requestId reopens the same tab. */
1007
+ openTabRequest?: { tab: string; requestId: number } | null | undefined;
1008
+ initialFilePath?: string | null | undefined;
1009
+ onFilePathChange?: ((path: string | null) => void) | undefined;
1010
+ /** Presentation-only filter for Files tree nodes and selected-file viewing. */
1011
+ isFileNodeVisible?: FileNodeVisibilityPredicate | undefined;
1012
+ /**
1013
+ * Host request to open a workspace file (and optional line) in Files. A new
1014
+ * `requestId` re-opens even the same path.
1015
+ */
1016
+ openFileRequest?:
1017
+ | {
1018
+ path: string;
1019
+ line?: number | null;
1020
+ requestId: number;
1021
+ }
1022
+ | null
1023
+ | undefined;
1024
+ initialBrowserSessionId?: string | null | undefined;
1025
+ onBrowserSessionIdChange?: ((browserSessionId: string | null) => void) | undefined;
1026
+ initialComputerSessionId?: string | null | undefined;
1027
+ onComputerSessionIdChange?: ((computerSessionId: string | null) => void) | undefined;
918
1028
  /** Host-routed notifications (no toast dependency in the package). */
919
1029
  onNotify?: ((notification: WorkspaceNotification) => void) | undefined;
920
1030
  /** Alternate Browser frame transport for non-browser runtimes and deterministic tests. */
921
1031
  browserWebSocketFactory?: BrowserFrameWebSocketFactory | undefined;
922
1032
  /** Alternate Computer frame transport for non-browser runtimes and deterministic tests. */
923
1033
  computerWebSocketFactory?: ComputerFrameWebSocketFactory | undefined;
1034
+ /** Host-owned setup page or store listing for attaching an existing Chrome profile. */
1035
+ browserExtensionSetupUrl?: string | undefined;
924
1036
  /** Controlled collapsed state for hosts with their own dock toggle. */
925
1037
  collapsed?: boolean | undefined;
926
1038
  onCollapsedChange?: ((collapsed: boolean) => void) | undefined;
@@ -951,9 +1063,20 @@ export function SandboxWorkspace(props: SandboxWorkspaceProps): ReactNode {
951
1063
  leadingTabs,
952
1064
  trailingTabs,
953
1065
  initialTab,
1066
+ onActiveTabChange,
1067
+ openTabRequest,
1068
+ initialFilePath,
1069
+ onFilePathChange,
1070
+ isFileNodeVisible,
1071
+ openFileRequest,
1072
+ initialBrowserSessionId,
1073
+ onBrowserSessionIdChange,
1074
+ initialComputerSessionId,
1075
+ onComputerSessionIdChange,
954
1076
  onNotify,
955
1077
  browserWebSocketFactory,
956
1078
  computerWebSocketFactory,
1079
+ browserExtensionSetupUrl,
957
1080
  collapsed,
958
1081
  onCollapsedChange,
959
1082
  showCollapseControl,
@@ -972,6 +1095,7 @@ export function SandboxWorkspace(props: SandboxWorkspaceProps): ReactNode {
972
1095
  const [requestedFile, setRequestedFile] = useState<{
973
1096
  sessionId: string;
974
1097
  path: string;
1098
+ line: number | null;
975
1099
  requestId: number;
976
1100
  } | null>(null);
977
1101
  const [requestedComputer, setRequestedComputer] = useState<{
@@ -982,15 +1106,55 @@ export function SandboxWorkspace(props: SandboxWorkspaceProps): ReactNode {
982
1106
  const nextFileRequestId = useRef(0);
983
1107
  const nextComputerRequestId = useRef(0);
984
1108
  const selectedTab = storedSelection?.sessionId === sessionId ? storedSelection.tab : null;
1109
+ const handledTabRequest = useRef<{ sessionId: string; requestId: number } | null>(null);
1110
+ useEffect(() => {
1111
+ if (
1112
+ !openTabRequest ||
1113
+ (handledTabRequest.current?.sessionId === sessionId &&
1114
+ handledTabRequest.current.requestId === openTabRequest.requestId)
1115
+ )
1116
+ return;
1117
+ const available =
1118
+ [...(leadingTabs ?? []), ...(trailingTabs ?? [])].some(
1119
+ (tab) => tab.id === openTabRequest.tab,
1120
+ ) || (surfaces ?? WORKBENCH_SURFACES).some((tab) => tab === openTabRequest.tab);
1121
+ if (!available) return;
1122
+ handledTabRequest.current = { sessionId, requestId: openTabRequest.requestId };
1123
+ setStoredSelection({ sessionId, tab: openTabRequest.tab });
1124
+ onActiveTabChange?.(openTabRequest.tab);
1125
+ onCollapsedChange?.(false);
1126
+ }, [
1127
+ openTabRequest,
1128
+ sessionId,
1129
+ leadingTabs,
1130
+ trailingTabs,
1131
+ surfaces,
1132
+ onActiveTabChange,
1133
+ onCollapsedChange,
1134
+ ]);
985
1135
  const activeTabHint = selectedTab ?? initialTab ?? leadingTabs?.[0]?.id ?? null;
986
1136
  const openFile = useCallback(
987
- (path: string) => {
988
- nextFileRequestId.current += 1;
989
- setRequestedFile({ sessionId, path, requestId: nextFileRequestId.current });
1137
+ (path: string, line?: number | null) => {
1138
+ setRequestedFile({
1139
+ sessionId,
1140
+ path,
1141
+ line: line != null && line > 0 ? line : null,
1142
+ requestId: ++nextFileRequestId.current,
1143
+ });
990
1144
  setStoredSelection({ sessionId, tab: WORKBENCH_TAB_FILES });
1145
+ onActiveTabChange?.(WORKBENCH_TAB_FILES);
1146
+ onFilePathChange?.(path);
1147
+ onCollapsedChange?.(false);
991
1148
  },
992
- [sessionId],
1149
+ [onActiveTabChange, onCollapsedChange, onFilePathChange, sessionId],
993
1150
  );
1151
+ const handledOpenFileRequestId = useRef<number | null>(null);
1152
+ useEffect(() => {
1153
+ if (!openFileRequest) return;
1154
+ if (handledOpenFileRequestId.current === openFileRequest.requestId) return;
1155
+ handledOpenFileRequestId.current = openFileRequest.requestId;
1156
+ openFile(openFileRequest.path, openFileRequest.line);
1157
+ }, [openFile, openFileRequest]);
994
1158
  const openComputer = useCallback(
995
1159
  (computerSessionId: string) => {
996
1160
  nextComputerRequestId.current += 1;
@@ -1000,8 +1164,10 @@ export function SandboxWorkspace(props: SandboxWorkspaceProps): ReactNode {
1000
1164
  requestId: nextComputerRequestId.current,
1001
1165
  });
1002
1166
  setStoredSelection({ sessionId, tab: WORKBENCH_TAB_DESKTOP });
1167
+ onActiveTabChange?.(WORKBENCH_TAB_DESKTOP);
1168
+ onComputerSessionIdChange?.(computerSessionId);
1003
1169
  },
1004
- [sessionId],
1170
+ [onActiveTabChange, onComputerSessionIdChange, sessionId],
1005
1171
  );
1006
1172
 
1007
1173
  const {
@@ -1020,8 +1186,17 @@ export function SandboxWorkspace(props: SandboxWorkspaceProps): ReactNode {
1020
1186
  ...(onNotify ? { onNotify } : {}),
1021
1187
  ...(browserWebSocketFactory ? { browserWebSocketFactory } : {}),
1022
1188
  ...(computerWebSocketFactory ? { computerWebSocketFactory } : {}),
1189
+ ...(browserExtensionSetupUrl ? { browserExtensionSetupUrl } : {}),
1190
+ initialFilePath,
1191
+ onFilePathChange,
1192
+ isFileNodeVisible,
1193
+ initialBrowserSessionId,
1194
+ onBrowserSessionIdChange,
1195
+ initialComputerSessionId,
1196
+ onComputerSessionIdChange,
1023
1197
  requestedFilePath: requestedFile?.sessionId === sessionId ? requestedFile.path : null,
1024
1198
  requestedFileRequestId: requestedFile?.sessionId === sessionId ? requestedFile.requestId : null,
1199
+ requestedFileLine: requestedFile?.sessionId === sessionId ? requestedFile.line : null,
1025
1200
  onOpenFile: openFile,
1026
1201
  onOpenComputerSession: openComputer,
1027
1202
  requestedComputerSessionId:
@@ -1040,9 +1215,19 @@ export function SandboxWorkspace(props: SandboxWorkspaceProps): ReactNode {
1040
1215
  const activeTab =
1041
1216
  preferredTab && tabs.some((tab) => tab.id === preferredTab) ? preferredTab : tabs[0]?.id;
1042
1217
  const selectTab = useCallback(
1043
- (tab: string) => setStoredSelection({ sessionId, tab }),
1044
- [sessionId],
1218
+ (tab: string) => {
1219
+ setStoredSelection({ sessionId, tab });
1220
+ onActiveTabChange?.(tab);
1221
+ },
1222
+ [onActiveTabChange, sessionId],
1045
1223
  );
1224
+ useEffect(() => {
1225
+ if (selectedTab !== null || defaultTab === null) return;
1226
+ // Once the source-driven choice resolves, make it the real controlled
1227
+ // selection. Without this handoff the dock could visibly show Files while
1228
+ // the data hooks continued treating the selection as unresolved.
1229
+ setStoredSelection({ sessionId, tab: defaultTab });
1230
+ }, [defaultTab, selectedTab, sessionId]);
1046
1231
 
1047
1232
  return (
1048
1233
  <WorkspaceDock
@@ -1050,7 +1235,12 @@ export function SandboxWorkspace(props: SandboxWorkspaceProps): ReactNode {
1050
1235
  tabs={tabs}
1051
1236
  {...(activeTab !== undefined ? { activeTab } : {})}
1052
1237
  onActiveTabChange={selectTab}
1053
- {...(machine.enabled
1238
+ // Browser and Desktop select independent workspace resources, potentially
1239
+ // on another placement. Their own viewers report runtime status; the
1240
+ // agent-session machine chip must not describe those resources.
1241
+ {...(machine.enabled &&
1242
+ activeTab !== WORKBENCH_TAB_BROWSER &&
1243
+ activeTab !== WORKBENCH_TAB_DESKTOP
1054
1244
  ? {
1055
1245
  headerAccessory: <MachineStateChip chip={machine.chip} />,
1056
1246
  }
@@ -1086,7 +1276,7 @@ function chipDotClass(state: MachineChip["state"]): string {
1086
1276
  }
1087
1277
 
1088
1278
  /**
1089
- * The dock-header machine status: one quiet, truthful live/waking/offline
1279
+ * The dock-header machine status: one quiet, truthful live/waking/resting
1090
1280
  * indicator. It is intentionally not interactive; detailed machine controls do
1091
1281
  * not belong in a transient popover above the workspace tabs.
1092
1282
  */
@@ -1170,6 +1360,7 @@ function ChangesTabContent({
1170
1360
  git,
1171
1361
  comparison,
1172
1362
  captureAvailable,
1363
+ captureDegraded,
1173
1364
  captureRevision,
1174
1365
  capturePending,
1175
1366
  liveWorkspaceExpected,
@@ -1183,6 +1374,7 @@ function ChangesTabContent({
1183
1374
  git: UseSandboxGitResult;
1184
1375
  comparison: SandboxGitComparison;
1185
1376
  captureAvailable: boolean;
1377
+ captureDegraded: boolean;
1186
1378
  captureRevision: number | null;
1187
1379
  capturePending: boolean;
1188
1380
  liveWorkspaceExpected: boolean;
@@ -1276,6 +1468,8 @@ function ChangesTabContent({
1276
1468
  }
1277
1469
 
1278
1470
  if (!liveWorkspaceExpected && (comparison !== "working" || !captureAvailable)) {
1471
+ // Staged changes are live-only; a failed saved preview is not their blocker.
1472
+ const previewUnavailable = captureDegraded && !captureAvailable && comparison !== "staged";
1279
1473
  return (
1280
1474
  <CenteredState
1281
1475
  icon={
@@ -1284,22 +1478,30 @@ function ChangesTabContent({
1284
1478
  className="size-5 animate-spin motion-reduce:animate-none"
1285
1479
  aria-hidden
1286
1480
  />
1481
+ ) : previewUnavailable ? (
1482
+ <TriangleAlertIcon className="size-5" aria-hidden />
1287
1483
  ) : (
1288
1484
  <CpuIcon className="size-5" aria-hidden />
1289
1485
  )
1290
1486
  }
1291
1487
  >
1292
1488
  <p className="text-og-sm font-medium text-og-fg">
1293
- {workspaceWaking ? "Waking workspace" : "Workspace is resting"}
1489
+ {workspaceWaking
1490
+ ? "Waking workspace"
1491
+ : previewUnavailable
1492
+ ? "Saved changes preview is unavailable"
1493
+ : "Workspace is resting"}
1294
1494
  </p>
1295
1495
  <p className="text-og-sm leading-5 text-og-fg-subtle">
1296
1496
  {workspaceWaking
1297
1497
  ? "Connecting to the live working tree…"
1298
- : comparison === "branch"
1299
- ? "Wake the sandbox to compare this branch with the remote default branch."
1300
- : comparison === "staged"
1301
- ? "Wake the sandbox to inspect staged changes."
1302
- : "No captured revision is available yet. Wake the sandbox to inspect uncommitted changes."}
1498
+ : previewUnavailable
1499
+ ? "Open the live workspace to view current changes."
1500
+ : comparison === "branch"
1501
+ ? "Wake the sandbox to compare this branch with the remote default branch."
1502
+ : comparison === "staged"
1503
+ ? "Wake the sandbox to inspect staged changes."
1504
+ : "No captured revision is available yet. Wake the sandbox to inspect uncommitted changes."}
1303
1505
  </p>
1304
1506
  {!workspaceWaking ? (
1305
1507
  <DockActionButton onClick={onWake}>