@opengeni/react 1.0.1 → 1.0.2-canary.37202341988001

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 (632) hide show
  1. package/README.md +660 -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-SHYKQRNX.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-26ZNDDLZ.js +453 -0
  18. package/dist/chunk-26ZNDDLZ.js.map +1 -0
  19. package/dist/chunk-3CTRFMAK.js +359 -0
  20. package/dist/chunk-3CTRFMAK.js.map +1 -0
  21. package/dist/chunk-447JLCBU.js +209 -0
  22. package/dist/chunk-447JLCBU.js.map +1 -0
  23. package/dist/chunk-4RVYOY4O.js +379 -0
  24. package/dist/chunk-4RVYOY4O.js.map +1 -0
  25. package/dist/chunk-5CVXZA3Y.js +292 -0
  26. package/dist/chunk-5CVXZA3Y.js.map +1 -0
  27. package/dist/chunk-5J4FOW6Q.js +108 -0
  28. package/dist/chunk-5J4FOW6Q.js.map +1 -0
  29. package/dist/chunk-742CZ3L3.js +481 -0
  30. package/dist/chunk-742CZ3L3.js.map +1 -0
  31. package/dist/chunk-A2PI6UMY.js +41 -0
  32. package/dist/chunk-A2PI6UMY.js.map +1 -0
  33. package/dist/{chunk-7WCLAEFV.js → chunk-A4UJB2MM.js} +37 -27
  34. package/dist/chunk-A4UJB2MM.js.map +1 -0
  35. package/dist/chunk-B3V6TG77.js +41 -0
  36. package/dist/chunk-B3V6TG77.js.map +1 -0
  37. package/dist/chunk-BRM6FVZA.js +302 -0
  38. package/dist/chunk-BRM6FVZA.js.map +1 -0
  39. package/dist/chunk-C5X5AJXK.js +182 -0
  40. package/dist/chunk-C5X5AJXK.js.map +1 -0
  41. package/dist/{chunk-6KLX2RH5.js → chunk-DO544OSV.js} +1075 -79
  42. package/dist/chunk-DO544OSV.js.map +1 -0
  43. package/dist/{chunk-R3AZOAB5.js → chunk-DYWBUX5Q.js} +29 -123
  44. package/dist/chunk-DYWBUX5Q.js.map +1 -0
  45. package/dist/{chunk-HA46CYQK.js → chunk-EESD3PY3.js} +792 -537
  46. package/dist/chunk-EESD3PY3.js.map +1 -0
  47. package/dist/{chunk-5UQPNLIO.js → chunk-EN3YTHKR.js} +4117 -3896
  48. package/dist/chunk-EN3YTHKR.js.map +1 -0
  49. package/dist/chunk-ERGYJIBB.js +21 -0
  50. package/dist/chunk-ERGYJIBB.js.map +1 -0
  51. package/dist/chunk-FZCP527Y.js +116 -0
  52. package/dist/chunk-FZCP527Y.js.map +1 -0
  53. package/dist/chunk-GIMRELBW.js +14 -0
  54. package/dist/chunk-GIMRELBW.js.map +1 -0
  55. package/dist/chunk-GYVRFZDY.js +2733 -0
  56. package/dist/chunk-GYVRFZDY.js.map +1 -0
  57. package/dist/{chunk-LLOLUHVG.js → chunk-HDJWDK7W.js} +1358 -2746
  58. package/dist/chunk-HDJWDK7W.js.map +1 -0
  59. package/dist/chunk-I7IWRQLN.js +1608 -0
  60. package/dist/chunk-I7IWRQLN.js.map +1 -0
  61. package/dist/chunk-IT4BJUGF.js +13055 -0
  62. package/dist/chunk-IT4BJUGF.js.map +1 -0
  63. package/dist/chunk-IWIDV7SB.js +1 -0
  64. package/dist/chunk-IWIDV7SB.js.map +1 -0
  65. package/dist/chunk-J2QWVSQY.js +312 -0
  66. package/dist/chunk-J2QWVSQY.js.map +1 -0
  67. package/dist/chunk-J6DBS4T3.js +371 -0
  68. package/dist/chunk-J6DBS4T3.js.map +1 -0
  69. package/dist/{chunk-B6WPZSTT.js → chunk-JIQYUGVL.js} +1331 -1163
  70. package/dist/chunk-JIQYUGVL.js.map +1 -0
  71. package/dist/chunk-JT4JW7BC.js +54 -0
  72. package/dist/chunk-JT4JW7BC.js.map +1 -0
  73. package/dist/chunk-K3HQAKQX.js +24 -0
  74. package/dist/chunk-K3HQAKQX.js.map +1 -0
  75. package/dist/{chunk-PEI6RANI.js → chunk-PNY3JKBJ.js} +309 -74
  76. package/dist/chunk-PNY3JKBJ.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-RLUSC2WA.js +299 -0
  80. package/dist/chunk-RLUSC2WA.js.map +1 -0
  81. package/dist/{chunk-IGC6A2ZI.js → chunk-RSI7XYXL.js} +777 -246
  82. package/dist/chunk-RSI7XYXL.js.map +1 -0
  83. package/dist/chunk-SCOTPE2I.js +589 -0
  84. package/dist/chunk-SCOTPE2I.js.map +1 -0
  85. package/dist/{chunk-C5ZPSSS5.js → chunk-TKOTKRWY.js} +5 -4
  86. package/dist/{chunk-C5ZPSSS5.js.map → chunk-TKOTKRWY.js.map} +1 -1
  87. package/dist/chunk-TMYGL6X5.js +742 -0
  88. package/dist/chunk-TMYGL6X5.js.map +1 -0
  89. package/dist/chunk-UGLEYEMP.js +33 -0
  90. package/dist/chunk-UGLEYEMP.js.map +1 -0
  91. package/dist/chunk-UK4TINKT.js +27 -0
  92. package/dist/chunk-UK4TINKT.js.map +1 -0
  93. package/dist/chunk-UTRTG6LH.js +220 -0
  94. package/dist/chunk-UTRTG6LH.js.map +1 -0
  95. package/dist/chunk-WEHMPOXK.js +39 -0
  96. package/dist/chunk-WEHMPOXK.js.map +1 -0
  97. package/dist/chunk-WGXVEJO5.js +319 -0
  98. package/dist/chunk-WGXVEJO5.js.map +1 -0
  99. package/dist/chunk-WRHIZYZF.js +988 -0
  100. package/dist/chunk-WRHIZYZF.js.map +1 -0
  101. package/dist/{chunk-HUIKIDM5.js → chunk-WUISZ3WU.js} +223 -115
  102. package/dist/chunk-WUISZ3WU.js.map +1 -0
  103. package/dist/chunk-XCHWDJ22.js +107 -0
  104. package/dist/chunk-XCHWDJ22.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-YM2DE7BQ.js +3124 -0
  110. package/dist/chunk-YM2DE7BQ.js.map +1 -0
  111. package/dist/{chunk-KZ73RL76.js → chunk-YQEAA6LT.js} +7 -3
  112. package/dist/chunk-YQEAA6LT.js.map +1 -0
  113. package/dist/chunk-YV4L3ILF.js +9 -0
  114. package/dist/chunk-YV4L3ILF.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 +58 -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 +89 -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/session-proxy-scope.d.ts +21 -0
  185. package/dist/components/timeline-anchor.d.ts +24 -0
  186. package/dist/components/timeline-annotation-chrome.d.ts +25 -0
  187. package/dist/components/timeline-annotation-layout.d.ts +42 -0
  188. package/dist/components/timeline-annotation-markers.d.ts +8 -0
  189. package/dist/components/timeline-annotation-reveal-context.d.ts +4 -0
  190. package/dist/components/timeline-annotation-shared.d.ts +31 -0
  191. package/dist/components/timeline-annotations-dialog.d.ts +3 -2
  192. package/dist/components/timeline-annotations.d.ts +13 -3
  193. package/dist/components/timeline-reading-progress.d.ts +11 -0
  194. package/dist/components/timeline-search.d.ts +34 -0
  195. package/dist/components/timeline-settlement.d.ts +16 -0
  196. package/dist/components/tip-follow.d.ts +16 -0
  197. package/dist/components/usage-limit-notice.d.ts +49 -0
  198. package/dist/components/usage-member-list.d.ts +91 -0
  199. package/dist/components/usage-meter.d.ts +73 -0
  200. package/dist/components/use-viewer-menu-dismiss.d.ts +2 -0
  201. package/dist/components/user-message-body.d.ts +10 -1
  202. package/dist/components/workspace-dock.d.ts +6 -2
  203. package/dist/composer.d.ts +5 -4
  204. package/dist/composer.js +15 -9
  205. package/dist/computer-viewer-6SRGWRUX.js +19 -0
  206. package/dist/computer-viewer-6SRGWRUX.js.map +1 -0
  207. package/dist/connect-account-identity.d.ts +8 -0
  208. package/dist/connect-accounts.d.ts +15 -0
  209. package/dist/connect-chooser.d.ts +18 -0
  210. package/dist/connect-panel.d.ts +18 -0
  211. package/dist/connect-setup.d.ts +16 -0
  212. package/dist/connect.d.ts +21 -0
  213. package/dist/connect.js +2129 -0
  214. package/dist/connect.js.map +1 -0
  215. package/dist/connection-catalog.d.ts +38 -0
  216. package/dist/connection-discovery.d.ts +12 -0
  217. package/dist/connection-installed.d.ts +17 -0
  218. package/dist/connection-logo.d.ts +9 -0
  219. package/dist/connection-service-logo.d.ts +8 -0
  220. package/dist/connection-service-presentation.d.ts +13 -0
  221. package/dist/connection-skeleton.d.ts +5 -0
  222. package/dist/connection-type-picker.d.ts +6 -0
  223. package/dist/conversation-timeline.d.ts +5 -0
  224. package/dist/desktop.d.ts +7 -0
  225. package/dist/desktop.js +26 -0
  226. package/dist/desktop.js.map +1 -0
  227. package/dist/device-authorization.d.ts +23 -0
  228. package/dist/diffs.d.ts +8 -0
  229. package/dist/diffs.js +14 -0
  230. package/dist/diffs.js.map +1 -0
  231. package/dist/discovery-cache.d.ts +5 -0
  232. package/dist/editor.d.ts +7 -0
  233. package/dist/editor.js +21 -0
  234. package/dist/editor.js.map +1 -0
  235. package/dist/embedded-session-client.d.ts +23 -0
  236. package/dist/file-node-visibility.d.ts +15 -0
  237. package/dist/{fleet-decision-row-GGCAT4E4.js → fleet-decision-row-YZ3ZKWMM.js} +2 -1
  238. package/dist/fleet-decision-row-YZ3ZKWMM.js.map +1 -0
  239. package/dist/hooks/channel-cache.d.ts +23 -0
  240. package/dist/hooks/latest-question.d.ts +25 -0
  241. package/dist/hooks/shared-machines-list.d.ts +14 -0
  242. package/dist/hooks/use-attached-browsers.d.ts +2 -1
  243. package/dist/hooks/use-browser-frame-stream.d.ts +1 -1
  244. package/dist/hooks/use-browser-session.d.ts +12 -1
  245. package/dist/hooks/use-channels.d.ts +1 -0
  246. package/dist/hooks/use-codex-accounts.d.ts +25 -7
  247. package/dist/hooks/use-composer.d.ts +45 -9
  248. package/dist/hooks/use-computer-frame-stream.d.ts +1 -1
  249. package/dist/hooks/use-computer-input-posture.d.ts +13 -0
  250. package/dist/hooks/use-computer-session.d.ts +2 -0
  251. package/dist/hooks/use-connect.d.ts +22 -0
  252. package/dist/hooks/use-desktop-stream.d.ts +1 -1
  253. package/dist/hooks/use-file-attachments.d.ts +21 -2
  254. package/dist/hooks/use-machine-chip.d.ts +3 -3
  255. package/dist/hooks/use-machines.d.ts +19 -1
  256. package/dist/hooks/use-sandbox-files.d.ts +5 -1
  257. package/dist/hooks/use-session-background-commands.d.ts +14 -0
  258. package/dist/hooks/use-session-events.d.ts +30 -8
  259. package/dist/hooks/use-session-lineage.d.ts +4 -0
  260. package/dist/hooks/use-session-mcp-approval-policy.d.ts +2 -2
  261. package/dist/hooks/use-session.d.ts +6 -0
  262. package/dist/hooks/use-turn-queue.d.ts +12 -0
  263. package/dist/hooks/use-usage.d.ts +40 -0
  264. package/dist/hooks/use-workspace-edit.d.ts +4 -0
  265. package/dist/hooks/use-workspace-sessions.d.ts +27 -5
  266. package/dist/human-input.d.ts +3 -1
  267. package/dist/identity-link-accounts.d.ts +11 -0
  268. package/dist/identity-link-consent.d.ts +18 -0
  269. package/dist/index.d.ts +60 -17
  270. package/dist/index.js +2238 -6201
  271. package/dist/index.js.map +1 -1
  272. package/dist/interaction.d.ts +1 -1
  273. package/dist/interaction.js +35 -184
  274. package/dist/interaction.js.map +1 -1
  275. package/dist/latest-question-HTRIS4KJ.js +117 -0
  276. package/dist/latest-question-HTRIS4KJ.js.map +1 -0
  277. package/dist/lib/error-message.d.ts +7 -0
  278. package/dist/lib/format.d.ts +36 -2
  279. package/dist/lib/host-theme.d.ts +70 -0
  280. package/dist/lib/interaction-errors.d.ts +6 -0
  281. package/dist/lib/menu-styles.d.ts +22 -0
  282. package/dist/lib/pierre-diffs-loader.d.ts +20 -0
  283. package/dist/lib/workbench-peers.d.ts +36 -0
  284. package/dist/lib/xterm-theme.d.ts +7 -5
  285. package/dist/machines.d.ts +4 -2
  286. package/dist/machines.js +14 -4
  287. package/dist/markdown-table-layout-QXSLK4BY.js +106 -0
  288. package/dist/markdown-table-layout-QXSLK4BY.js.map +1 -0
  289. package/dist/mcp-connection-status.d.ts +14 -0
  290. package/dist/model-policy-picker-menu-M54ISBMN.js +14 -0
  291. package/dist/model-policy-picker-menu-M54ISBMN.js.map +1 -0
  292. package/dist/model-policy.d.ts +19 -3
  293. package/dist/model-policy.js +9 -1
  294. package/dist/older-history.d.ts +30 -0
  295. package/dist/platform-activity-row-627BFZ46.js +182 -0
  296. package/dist/platform-activity-row-627BFZ46.js.map +1 -0
  297. package/dist/plugin-details.d.ts +14 -0
  298. package/dist/plugin-discovery.d.ts +25 -0
  299. package/dist/provider.d.ts +13 -1
  300. package/dist/{queue-surface-implementation-2KVJTYXH.js → queue-surface-implementation-ZHFI5JBP.js} +131 -44
  301. package/dist/queue-surface-implementation-ZHFI5JBP.js.map +1 -0
  302. package/dist/realtime/realtime-control.d.ts +6 -3
  303. package/dist/realtime.js +133 -74
  304. package/dist/realtime.js.map +1 -1
  305. package/dist/sandbox-files-GORZOUUJ.js +20 -0
  306. package/dist/sandbox-files-GORZOUUJ.js.map +1 -0
  307. package/dist/session-auth-recommendation.d.ts +5 -0
  308. package/dist/session-capability-policy.d.ts +12 -0
  309. package/dist/session-ui.d.ts +30 -2
  310. package/dist/session-ui.js +85 -7
  311. package/dist/session-ui.js.map +1 -1
  312. package/dist/session.d.ts +8 -2
  313. package/dist/session.js +30 -19
  314. package/dist/sites-ui.d.ts +34 -0
  315. package/dist/sites.d.ts +3 -0
  316. package/dist/sites.js +11 -0
  317. package/dist/sites.js.map +1 -0
  318. package/dist/skill-discovery.d.ts +47 -0
  319. package/dist/terminal.d.ts +8 -0
  320. package/dist/terminal.js +31 -0
  321. package/dist/terminal.js.map +1 -0
  322. package/dist/timeline/activity-rail.d.ts +11 -2
  323. package/dist/timeline/allowance-exhausted-row.d.ts +24 -0
  324. package/dist/timeline/compaction-copy.d.ts +10 -0
  325. package/dist/timeline/entrance.d.ts +13 -1
  326. package/dist/timeline/genie-loading.d.ts +34 -0
  327. package/dist/timeline/index.d.ts +6 -2
  328. package/dist/timeline/knowledge-receipt.d.ts +17 -0
  329. package/dist/timeline/platform-activity-row.d.ts +14 -0
  330. package/dist/timeline/presented-image.d.ts +6 -0
  331. package/dist/timeline/projection.d.ts +31 -2
  332. package/dist/timeline/registry.d.ts +2 -0
  333. package/dist/timeline/retained-image.d.ts +18 -0
  334. package/dist/timeline/rolling-activity.d.ts +11 -0
  335. package/dist/timeline/screenshot-lightbox.d.ts +16 -1
  336. package/dist/timeline/shared.d.ts +8 -3
  337. package/dist/timeline/startup-preference.d.ts +3 -0
  338. package/dist/timeline/startup-timings.d.ts +4 -0
  339. package/dist/timeline/tool-display-name.d.ts +2 -1
  340. package/dist/timeline/turn-summary.d.ts +34 -3
  341. package/dist/timeline/types.d.ts +147 -7
  342. package/dist/timeline-annotation-markers-GNDHTGBD.js +165 -0
  343. package/dist/timeline-annotation-markers-GNDHTGBD.js.map +1 -0
  344. package/dist/timeline-annotation-selection-DMLMM2TX.js +241 -0
  345. package/dist/timeline-annotation-selection-DMLMM2TX.js.map +1 -0
  346. package/dist/timeline-annotations-dialog-ELRDBHTS.js +273 -0
  347. package/dist/timeline-annotations-dialog-ELRDBHTS.js.map +1 -0
  348. package/dist/types/machines.d.ts +2 -2
  349. package/dist/usage/allowance-copy.d.ts +25 -0
  350. package/dist/usage/summary.d.ts +35 -0
  351. package/dist/usage.d.ts +13 -0
  352. package/dist/usage.js +1074 -0
  353. package/dist/usage.js.map +1 -0
  354. package/package.json +44 -4
  355. package/src/accounts.tsx +1072 -0
  356. package/src/approvals.ts +8 -1
  357. package/src/artifacts.ts +42 -0
  358. package/src/assets/README.md +8 -0
  359. package/src/assets/gmail.ico +0 -0
  360. package/src/assets/outlook.ico +0 -0
  361. package/src/capability-catalog-row.tsx +94 -0
  362. package/src/capability-logo-fallback.ts +22 -0
  363. package/src/client.ts +22 -13
  364. package/src/commands/registry.ts +18 -15
  365. package/src/commands/types.ts +2 -0
  366. package/src/components/anthropic-mark.tsx +10 -0
  367. package/src/components/approval-surface.tsx +171 -37
  368. package/src/components/artifacts/artifact-chrome.tsx +413 -0
  369. package/src/components/artifacts/artifact-sandbox.tsx +185 -0
  370. package/src/components/artifacts/artifact-surface.tsx +39 -19
  371. package/src/components/artifacts/chat-interactive-block.tsx +260 -0
  372. package/src/components/artifacts/deferred-chat-media.tsx +67 -0
  373. package/src/components/artifacts/document-editor.tsx +141 -16
  374. package/src/components/artifacts/editable-artifact-ui.tsx +4 -2
  375. package/src/components/artifacts/editable-artifact-view.tsx +187 -0
  376. package/src/components/artifacts/editable-artifact-workbench.tsx +5 -2
  377. package/src/components/artifacts/editable-document.tsx +37 -36
  378. package/src/components/artifacts/editable-presentation.tsx +36 -18
  379. package/src/components/artifacts/editable-spreadsheet.tsx +5 -2
  380. package/src/components/artifacts/index.ts +44 -0
  381. package/src/components/artifacts/inline-html-document.ts +24 -0
  382. package/src/components/artifacts/latest-task-runner.ts +49 -0
  383. package/src/components/artifacts/presentation-editor.tsx +323 -67
  384. package/src/components/artifacts/published-html-artifact-frame.tsx +338 -5
  385. package/src/components/artifacts/session-artifact-viewer.tsx +376 -0
  386. package/src/components/artifacts/site-view.tsx +116 -0
  387. package/src/components/artifacts/spreadsheet-canvas.ts +5 -10
  388. package/src/components/artifacts/spreadsheet-general-display.ts +43 -0
  389. package/src/components/artifacts/spreadsheet-grid.tsx +12 -13
  390. package/src/components/artifacts/visualization-assets/base.css +1015 -0
  391. package/src/components/artifacts/visualization-assets/helpers.html +349 -0
  392. package/src/components/artifacts/visualization-assets.gen.ts +3 -0
  393. package/src/components/browser-select-control.tsx +312 -0
  394. package/src/components/browser-viewer.tsx +1054 -314
  395. package/src/components/chat-composer.tsx +131 -85
  396. package/src/components/child-session-link.tsx +27 -0
  397. package/src/components/claude-mark.tsx +10 -0
  398. package/src/components/code-editor.tsx +13 -16
  399. package/src/components/composer-transcription-control.tsx +7 -5
  400. package/src/components/composer.tsx +376 -49
  401. package/src/components/computer-viewer.tsx +1041 -329
  402. package/src/components/copy-button.tsx +13 -5
  403. package/src/components/desktop-viewer.tsx +1 -1
  404. package/src/components/enrollment-consent.tsx +65 -7
  405. package/src/components/enrollment-device-flow.tsx +1 -1
  406. package/src/components/file-browser.tsx +158 -34
  407. package/src/components/fleet-tile.tsx +8 -16
  408. package/src/components/generated-video-player.tsx +4 -2
  409. package/src/components/grok-mark.tsx +33 -0
  410. package/src/components/human-input-form.tsx +455 -114
  411. package/src/components/human-input-surface.tsx +18 -7
  412. package/src/components/interaction-intervention-banner.tsx +2 -2
  413. package/src/components/machine-card.tsx +119 -4
  414. package/src/components/machine-dock-bar.tsx +1 -1
  415. package/src/components/machine-input-display.ts +23 -2
  416. package/src/components/machines/machine-detail.tsx +52 -2
  417. package/src/components/machines/machine-operation-policy.tsx +179 -0
  418. package/src/components/machines-dashboard.tsx +8 -17
  419. package/src/components/markdown-table-layout.ts +132 -0
  420. package/src/components/markdown.tsx +473 -44
  421. package/src/components/message-timeline.tsx +2754 -665
  422. package/src/components/model-mark.tsx +90 -0
  423. package/src/components/model-picker.tsx +15 -4
  424. package/src/components/model-policy-picker-menu.tsx +424 -0
  425. package/src/components/model-policy-picker.tsx +337 -381
  426. package/src/components/open-geni-chat.tsx +338 -0
  427. package/src/components/open-geni-links.tsx +179 -0
  428. package/src/components/openrouter-mark.tsx +13 -0
  429. package/src/components/pierre-diff.tsx +41 -16
  430. package/src/components/pierre-file.tsx +36 -11
  431. package/src/components/preview-loading.tsx +154 -0
  432. package/src/components/queue-item-content.ts +14 -0
  433. package/src/components/queue-surface-implementation.tsx +132 -42
  434. package/src/components/queue-surface-state.tsx +3 -1
  435. package/src/components/sandbox-files.tsx +267 -35
  436. package/src/components/sandbox-terminal.tsx +48 -11
  437. package/src/components/sandbox-workspace.tsx +337 -135
  438. package/src/components/session-capability-frame.tsx +192 -0
  439. package/src/components/session-chrome.tsx +1027 -328
  440. package/src/components/session-commands-panel.tsx +126 -0
  441. package/src/components/session-commands.tsx +18 -0
  442. package/src/components/session-connection-request.tsx +97 -0
  443. package/src/components/session-conversation.tsx +526 -0
  444. package/src/components/session-list.tsx +250 -0
  445. package/src/components/session-mcp-capability-card.tsx +680 -0
  446. package/src/components/session-proxy-scope.tsx +92 -0
  447. package/src/components/session-status.tsx +1 -1
  448. package/src/components/timeline-anchor.tsx +119 -0
  449. package/src/components/timeline-annotation-chrome.tsx +196 -0
  450. package/src/components/timeline-annotation-layout.ts +268 -0
  451. package/src/components/timeline-annotation-markers.tsx +185 -0
  452. package/src/components/timeline-annotation-reveal-context.ts +9 -0
  453. package/src/components/timeline-annotation-selection.tsx +106 -54
  454. package/src/components/timeline-annotation-shared.ts +245 -0
  455. package/src/components/timeline-annotations-dialog.tsx +185 -128
  456. package/src/components/timeline-annotations.tsx +189 -45
  457. package/src/components/timeline-reading-progress.ts +80 -0
  458. package/src/components/timeline-search.tsx +168 -0
  459. package/src/components/timeline-settlement.ts +60 -0
  460. package/src/components/tip-follow.ts +70 -7
  461. package/src/components/tooltip.tsx +38 -5
  462. package/src/components/usage-limit-notice.tsx +179 -0
  463. package/src/components/usage-member-list.tsx +792 -0
  464. package/src/components/usage-meter.tsx +382 -0
  465. package/src/components/use-viewer-menu-dismiss.ts +33 -0
  466. package/src/components/user-message-body.tsx +194 -49
  467. package/src/components/workspace-dock.tsx +141 -175
  468. package/src/composer.ts +6 -1
  469. package/src/connect-account-identity.tsx +34 -0
  470. package/src/connect-accounts.tsx +233 -0
  471. package/src/connect-chooser.tsx +336 -0
  472. package/src/connect-panel.tsx +99 -0
  473. package/src/connect-setup.tsx +307 -0
  474. package/src/connect.ts +60 -0
  475. package/src/connection-assets.d.ts +4 -0
  476. package/src/connection-catalog.tsx +162 -0
  477. package/src/connection-discovery.tsx +235 -0
  478. package/src/connection-installed.tsx +51 -0
  479. package/src/connection-logo.tsx +37 -0
  480. package/src/connection-service-logo.tsx +55 -0
  481. package/src/connection-service-presentation.ts +46 -0
  482. package/src/connection-skeleton.tsx +16 -0
  483. package/src/connection-type-picker.tsx +36 -0
  484. package/src/conversation-timeline.ts +92 -0
  485. package/src/desktop.ts +24 -0
  486. package/src/device-authorization.tsx +98 -0
  487. package/src/diffs.ts +16 -0
  488. package/src/discovery-cache.ts +42 -0
  489. package/src/editor.ts +13 -0
  490. package/src/embedded-session-client.ts +104 -0
  491. package/src/file-node-visibility.ts +66 -0
  492. package/src/hooks/channel-cache.ts +104 -0
  493. package/src/hooks/internal.ts +3 -2
  494. package/src/hooks/latest-question.ts +164 -0
  495. package/src/hooks/shared-machines-list.ts +239 -0
  496. package/src/hooks/use-attached-browsers.ts +5 -1
  497. package/src/hooks/use-available-models.ts +20 -14
  498. package/src/hooks/use-browser-frame-stream.ts +25 -3
  499. package/src/hooks/use-browser-session.ts +271 -71
  500. package/src/hooks/use-browser-sessions.ts +7 -1
  501. package/src/hooks/use-channels.ts +32 -10
  502. package/src/hooks/use-codex-accounts.ts +78 -21
  503. package/src/hooks/use-composer.ts +1034 -320
  504. package/src/hooks/use-computer-frame-stream.ts +39 -16
  505. package/src/hooks/use-computer-input-posture.ts +94 -0
  506. package/src/hooks/use-computer-session.ts +110 -32
  507. package/src/hooks/use-computer-sessions.ts +8 -1
  508. package/src/hooks/use-connect.ts +23 -0
  509. package/src/hooks/use-desktop-stream.ts +19 -28
  510. package/src/hooks/use-file-attachments.ts +118 -10
  511. package/src/hooks/use-goal.ts +36 -9
  512. package/src/hooks/use-human-input.ts +31 -4
  513. package/src/hooks/use-last-started-turn-policy.ts +15 -13
  514. package/src/hooks/use-machine-chip.ts +23 -6
  515. package/src/hooks/use-machines.ts +104 -6
  516. package/src/hooks/use-sandbox-files.ts +253 -150
  517. package/src/hooks/use-sandbox-git.ts +58 -29
  518. package/src/hooks/use-session-background-commands.ts +67 -0
  519. package/src/hooks/use-session-capabilities.ts +21 -2
  520. package/src/hooks/use-session-events.ts +759 -433
  521. package/src/hooks/use-session-lineage.ts +28 -6
  522. package/src/hooks/use-session-mcp-approval-policy.ts +13 -5
  523. package/src/hooks/use-session.ts +75 -16
  524. package/src/hooks/use-slash-commands.ts +6 -11
  525. package/src/hooks/use-turn-queue.ts +113 -13
  526. package/src/hooks/use-usage.ts +100 -0
  527. package/src/hooks/use-video-artifact-playback.ts +1 -1
  528. package/src/hooks/use-voice-input.ts +12 -1
  529. package/src/hooks/use-workspace-capture.ts +3 -2
  530. package/src/hooks/use-workspace-edit.ts +23 -5
  531. package/src/hooks/use-workspace-sessions.ts +99 -11
  532. package/src/human-input.ts +12 -1
  533. package/src/identity-link-accounts.tsx +148 -0
  534. package/src/identity-link-consent.tsx +192 -0
  535. package/src/index.ts +157 -12
  536. package/src/interaction.ts +1 -0
  537. package/src/lib/error-message.ts +37 -0
  538. package/src/lib/format.ts +150 -14
  539. package/src/lib/host-theme.ts +511 -0
  540. package/src/lib/interaction-errors.ts +33 -0
  541. package/src/lib/menu-styles.ts +44 -0
  542. package/src/lib/pierre-diffs-loader.ts +53 -0
  543. package/src/lib/workbench-peers.ts +62 -0
  544. package/src/lib/xterm-theme.ts +23 -21
  545. package/src/machines.ts +9 -1
  546. package/src/mcp-connection-status.ts +35 -0
  547. package/src/model-policy.ts +223 -69
  548. package/src/older-history.ts +87 -0
  549. package/src/plugin-details.tsx +185 -0
  550. package/src/plugin-discovery.tsx +196 -0
  551. package/src/provider.tsx +55 -14
  552. package/src/realtime/dropdown-menu.tsx +19 -12
  553. package/src/realtime/realtime-control.tsx +133 -46
  554. package/src/session-auth-recommendation.ts +48 -0
  555. package/src/session-capability-policy.ts +83 -0
  556. package/src/session-context.ts +4 -3
  557. package/src/session-ui.ts +66 -2
  558. package/src/session.ts +18 -1
  559. package/src/sites-ui.tsx +402 -0
  560. package/src/sites.ts +3 -0
  561. package/src/skill-discovery.tsx +208 -0
  562. package/src/terminal.ts +26 -0
  563. package/src/timeline/activity-rail.tsx +171 -80
  564. package/src/timeline/allowance-exhausted-row.tsx +86 -0
  565. package/src/timeline/compaction-copy.ts +42 -0
  566. package/src/timeline/entrance.tsx +28 -3
  567. package/src/timeline/fleet-decision-projection.ts +2 -1
  568. package/src/timeline/fleet-decision-row.tsx +1 -0
  569. package/src/timeline/genie-loading.tsx +136 -0
  570. package/src/timeline/index.ts +11 -0
  571. package/src/timeline/knowledge-receipt.tsx +100 -0
  572. package/src/timeline/parsers.ts +2 -2
  573. package/src/timeline/platform-activity-row.tsx +216 -0
  574. package/src/timeline/presented-image.ts +49 -0
  575. package/src/timeline/projection.ts +1609 -84
  576. package/src/timeline/registry.ts +15 -3
  577. package/src/timeline/retained-image.ts +97 -0
  578. package/src/timeline/rolling-activity.tsx +92 -0
  579. package/src/timeline/screenshot-lightbox.tsx +115 -17
  580. package/src/timeline/shared.tsx +47 -15
  581. package/src/timeline/startup-preference.ts +33 -0
  582. package/src/timeline/startup-timings.tsx +145 -0
  583. package/src/timeline/tool-display-name.ts +8 -6
  584. package/src/timeline/tool-renderers.tsx +497 -128
  585. package/src/timeline/turn-summary.tsx +218 -44
  586. package/src/timeline/types.ts +192 -7
  587. package/src/types/machines.ts +10 -0
  588. package/src/usage/allowance-copy.ts +64 -0
  589. package/src/usage/summary.ts +93 -0
  590. package/src/usage.ts +50 -0
  591. package/styles/compiled.css +2098 -757
  592. package/styles/connect.css +284 -0
  593. package/styles/connect.d.ts +1 -0
  594. package/styles/effective-tokens.css +1 -0
  595. package/styles/index.css +201 -9
  596. package/styles/responsive.css +27 -1
  597. package/styles/session-capability.css +44 -0
  598. package/styles/tokens.css +135 -65
  599. package/dist/chunk-5UQPNLIO.js.map +0 -1
  600. package/dist/chunk-6KLX2RH5.js.map +0 -1
  601. package/dist/chunk-7WCLAEFV.js.map +0 -1
  602. package/dist/chunk-B6WPZSTT.js.map +0 -1
  603. package/dist/chunk-FK6VG4LL.js +0 -90
  604. package/dist/chunk-FK6VG4LL.js.map +0 -1
  605. package/dist/chunk-HA46CYQK.js.map +0 -1
  606. package/dist/chunk-HUIKIDM5.js.map +0 -1
  607. package/dist/chunk-IGC6A2ZI.js.map +0 -1
  608. package/dist/chunk-KCGXPP5V.js.map +0 -1
  609. package/dist/chunk-KZ73RL76.js.map +0 -1
  610. package/dist/chunk-LAKLF4PA.js +0 -141
  611. package/dist/chunk-LAKLF4PA.js.map +0 -1
  612. package/dist/chunk-LLOLUHVG.js.map +0 -1
  613. package/dist/chunk-MKPIAGVL.js +0 -465
  614. package/dist/chunk-MKPIAGVL.js.map +0 -1
  615. package/dist/chunk-PEI6RANI.js.map +0 -1
  616. package/dist/chunk-R3AZOAB5.js.map +0 -1
  617. package/dist/chunk-WSK7G5LE.js +0 -170
  618. package/dist/chunk-WSK7G5LE.js.map +0 -1
  619. package/dist/chunk-XBZWOM2K.js +0 -218
  620. package/dist/chunk-XBZWOM2K.js.map +0 -1
  621. package/dist/chunk-Y7OEDUJ5.js +0 -8810
  622. package/dist/chunk-Y7OEDUJ5.js.map +0 -1
  623. package/dist/fleet-decision-row-GGCAT4E4.js.map +0 -1
  624. package/dist/hooks/use-packs.d.ts +0 -32
  625. package/dist/interactive-workbench-viewers-TOHBXJEE.js +0 -15
  626. package/dist/queue-surface-implementation-2KVJTYXH.js.map +0 -1
  627. package/dist/timeline-annotation-selection-3L7LHGG2.js +0 -187
  628. package/dist/timeline-annotation-selection-3L7LHGG2.js.map +0 -1
  629. package/dist/timeline-annotations-dialog-U7EVLR75.js +0 -196
  630. package/dist/timeline-annotations-dialog-U7EVLR75.js.map +0 -1
  631. package/src/hooks/use-packs.ts +0 -157
  632. /package/dist/{interactive-workbench-viewers-TOHBXJEE.js.map → browser-viewer-SHYKQRNX.js.map} +0 -0
@@ -1,16 +1,14 @@
1
+ import {
2
+ formatBytes,
3
+ formatRelativeTime
4
+ } from "./chunk-UTRTG6LH.js";
1
5
  import {
2
6
  useMutationRunner,
3
- usePageLiveActivity,
4
- usePolledValue
5
- } from "./chunk-KZ73RL76.js";
7
+ usePageLiveActivity
8
+ } from "./chunk-YQEAA6LT.js";
6
9
  import {
7
- OpenGeniContext,
8
10
  useOpenGeni
9
- } from "./chunk-C5ZPSSS5.js";
10
- import {
11
- formatBytes,
12
- formatRelativeTime
13
- } from "./chunk-LAKLF4PA.js";
11
+ } from "./chunk-TKOTKRWY.js";
14
12
  import {
15
13
  cn
16
14
  } from "./chunk-22KP6LR5.js";
@@ -284,11 +282,15 @@ function MachineMetrics({ metrics, density = "compact", className }) {
284
282
 
285
283
  // src/components/machine-card.tsx
286
284
  import {
285
+ AlertTriangleIcon,
287
286
  ArrowRightIcon,
288
287
  CpuIcon,
288
+ CircleCheckIcon,
289
+ DownloadIcon,
289
290
  LaptopIcon,
290
291
  MonitorIcon,
291
292
  MonitorOffIcon,
293
+ LoaderCircleIcon,
292
294
  ServerIcon,
293
295
  UsersIcon
294
296
  } from "lucide-react";
@@ -496,15 +498,19 @@ function MetricSparkline({
496
498
  // src/components/machine-card.tsx
497
499
  import { Fragment, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
498
500
  function KindIcon({ machine }) {
499
- if (machine.isSessionGroup)
501
+ if (machine.kind === "local" || machine.kind === "selfhosted")
502
+ return /* @__PURE__ */ jsx5(LaptopIcon, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
503
+ if (machine.kind === "docker" || machine.isSessionGroup)
500
504
  return /* @__PURE__ */ jsx5(ServerIcon, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
501
505
  if (machine.kind === "modal") return /* @__PURE__ */ jsx5(CpuIcon, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
502
- return /* @__PURE__ */ jsx5(LaptopIcon, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
506
+ return /* @__PURE__ */ jsx5(ServerIcon, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
503
507
  }
504
508
  function MachineCard({
505
509
  machine,
506
510
  onAttach,
507
511
  attaching,
512
+ onUpdateAgent,
513
+ updatingAgent,
508
514
  series,
509
515
  onOpenDetail,
510
516
  now,
@@ -517,6 +523,34 @@ function MachineCard({
517
523
  const sampledAgo = machine.metrics ? formatRelativeTime(machine.metrics.sampledAt, new Date(clockNow)) : null;
518
524
  const cpuPts = (series ?? []).map((s) => ({ t: new Date(s.sampledAt).getTime(), v: s.cpuPct }));
519
525
  const openable = Boolean(onOpenDetail);
526
+ const runtime = machine.runtime;
527
+ const updateRunning = runtime?.versionState === "updating";
528
+ const dispatchConfirmationStalled = runtime?.update?.status === "requested" && clockNow - new Date(runtime.update.updatedAt).getTime() >= 3e4;
529
+ const canUpdate = Boolean(machine.enrollmentId && onUpdateAgent) && !offline && !runtime?.updateBlockedReason && (runtime?.versionState === "outdated" || runtime?.versionState === "update_failed" || dispatchConfirmationStalled);
530
+ const updateLabel = (() => {
531
+ const update = runtime?.update;
532
+ if (!update) return null;
533
+ switch (update.status) {
534
+ case "requested":
535
+ return dispatchConfirmationStalled ? "Agent confirmation delayed" : "Confirming with agent";
536
+ case "accepted":
537
+ return "Update accepted";
538
+ case "waiting_for_idle":
539
+ return "Waiting for current work";
540
+ case "downloading":
541
+ case "verifying":
542
+ case "applying":
543
+ return `${update.status}\u2026`;
544
+ case "restarting":
545
+ return "Restarting agent";
546
+ case "succeeded":
547
+ return `Updated \xB7 v${update.targetVersion}`;
548
+ case "failed": {
549
+ const detail = update.errorCode?.replaceAll("_", " ");
550
+ return update.rolledBack ? `Update rolled back safely${detail ? ` \xB7 ${detail}` : ""}` : `Update failed${detail ? ` \xB7 ${detail}` : ""}`;
551
+ }
552
+ }
553
+ })();
520
554
  return /* @__PURE__ */ jsxs5(
521
555
  "div",
522
556
  {
@@ -556,7 +590,9 @@ function MachineCard({
556
590
  ) : null
557
591
  ] }),
558
592
  /* @__PURE__ */ jsxs5("div", { className: "mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-og-xs text-og-fg-subtle", children: [
559
- /* @__PURE__ */ jsx5("span", { className: "capitalize", children: machine.isSessionGroup ? "session sandbox" : machine.kind }),
593
+ /* @__PURE__ */ jsx5("span", { "data-machine-scope": machine.scope, className: "capitalize", children: machine.scope === "user" ? "personal" : machine.scope }),
594
+ /* @__PURE__ */ jsx5("span", { "aria-hidden": true, children: "\xB7" }),
595
+ /* @__PURE__ */ jsx5("span", { className: "capitalize", children: machine.kind }),
560
596
  /* @__PURE__ */ jsx5("span", { "aria-hidden": true, children: "\xB7" }),
561
597
  /* @__PURE__ */ jsxs5("span", { className: "font-og-mono", children: [
562
598
  machine.os,
@@ -595,6 +631,52 @@ function MachineCard({
595
631
  ]
596
632
  }
597
633
  ) : null,
634
+ machine.connectionAuthority.duplicateRunnerDeniedCount > 0 ? /* @__PURE__ */ jsxs5(
635
+ "p",
636
+ {
637
+ "data-runner-conflict": true,
638
+ className: "flex items-center gap-1.5 rounded-og-md border border-og-status-failed/30 bg-og-status-failed/5 px-2.5 py-1.5 text-og-xs text-og-status-failed",
639
+ children: [
640
+ /* @__PURE__ */ jsx5(AlertTriangleIcon, { className: "size-3.5 shrink-0", "aria-hidden": true }),
641
+ "Competing agent process blocked. Open diagnostics for details."
642
+ ]
643
+ }
644
+ ) : null,
645
+ runtime ? /* @__PURE__ */ jsxs5(
646
+ "div",
647
+ {
648
+ "data-agent-runtime": true,
649
+ className: "flex items-center justify-between gap-3 rounded-og-md border border-og-border/70 bg-og-surface-2/35 px-2.5 py-2 text-og-xs",
650
+ children: [
651
+ /* @__PURE__ */ jsxs5("div", { className: "min-w-0", children: [
652
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-1.5 text-og-fg-muted", children: [
653
+ runtime.versionState === "current" ? /* @__PURE__ */ jsx5(CircleCheckIcon, { className: "size-3.5 text-og-status-idle", "aria-hidden": true }) : updateRunning ? /* @__PURE__ */ jsx5(LoaderCircleIcon, { className: "size-3.5 animate-og-spin text-og-accent", "aria-hidden": true }) : /* @__PURE__ */ jsx5(DownloadIcon, { className: "size-3.5", "aria-hidden": true }),
654
+ /* @__PURE__ */ jsxs5("span", { className: "truncate", children: [
655
+ "Agent",
656
+ " ",
657
+ runtime.installedVersion ? `v${runtime.installedVersion}` : "version unknown"
658
+ ] })
659
+ ] }),
660
+ /* @__PURE__ */ jsx5("p", { className: "mt-0.5 truncate text-og-fg-subtle", children: updateLabel ?? (runtime.versionState === "current" ? `Current \xB7 ${runtime.updateChannel ?? "channel unknown"}` : runtime.desiredVersion ? `Promoted v${runtime.desiredVersion}` : "No promoted version configured") }),
661
+ runtime.updateBlockedReason ? /* @__PURE__ */ jsx5("p", { className: "mt-1 text-og-fg-muted", children: runtime.updateBlockedReason }) : null
662
+ ] }),
663
+ canUpdate ? /* @__PURE__ */ jsx5(
664
+ "button",
665
+ {
666
+ type: "button",
667
+ "data-update-agent": true,
668
+ disabled: updatingAgent,
669
+ onClick: (event) => {
670
+ event.stopPropagation();
671
+ onUpdateAgent?.(machine);
672
+ },
673
+ className: "shrink-0 rounded-og-sm border border-og-border px-2 py-1 font-medium text-og-fg-muted transition-colors hover:border-og-border-strong hover:text-og-fg disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:min-h-11",
674
+ children: updatingAgent ? "Starting\u2026" : dispatchConfirmationStalled ? "Retry delivery" : runtime.versionState === "update_failed" ? "Retry" : "Update"
675
+ }
676
+ ) : null
677
+ ]
678
+ }
679
+ ) : null,
598
680
  /* @__PURE__ */ jsx5(MachineMetrics, { metrics: machine.metrics }),
599
681
  cpuPts.length > 1 ? /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-1 rounded-og-md bg-og-surface-2/40 p-2.5", children: [
600
682
  /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between text-[10px] font-medium uppercase tracking-wide text-og-fg-subtle", children: [
@@ -888,6 +970,7 @@ function MetricHistoryChart({
888
970
 
889
971
  // src/components/machines/machine-detail.tsx
890
972
  import {
973
+ AlertTriangleIcon as AlertTriangleIcon3,
891
974
  ArrowLeftIcon,
892
975
  CpuIcon as CpuIcon2,
893
976
  LaptopIcon as LaptopIcon2,
@@ -979,21 +1062,191 @@ function pointsFor(def, samples) {
979
1062
  return ptsFrom(samples, def.pick);
980
1063
  }
981
1064
 
982
- // src/components/machines/machine-detail.tsx
1065
+ // src/components/machines/machine-operation-policy.tsx
1066
+ import { AlertTriangleIcon as AlertTriangleIcon2, Loader2Icon } from "lucide-react";
1067
+ import { useEffect, useState as useState2 } from "react";
983
1068
  import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1069
+ function fieldValue(value) {
1070
+ return value === null ? "" : String(value);
1071
+ }
1072
+ function parseByteCount(label, value) {
1073
+ const trimmed = value.trim();
1074
+ if (!trimmed) return null;
1075
+ if (!/^\d+$/.test(trimmed)) {
1076
+ throw new Error(`${label} must be a whole number of bytes or blank`);
1077
+ }
1078
+ const parsed = Number(trimmed);
1079
+ if (!Number.isSafeInteger(parsed) || parsed <= 0) {
1080
+ throw new Error(`${label} must be a positive safe-integer byte count or blank`);
1081
+ }
1082
+ return parsed;
1083
+ }
1084
+ function parseCpuMillicores(value) {
1085
+ const trimmed = value.trim();
1086
+ if (!trimmed) return null;
1087
+ if (!/^\d+$/.test(trimmed)) {
1088
+ throw new Error("CPU maximum must be a whole number of millicores or blank");
1089
+ }
1090
+ const parsed = Number(trimmed);
1091
+ if (!Number.isSafeInteger(parsed) || parsed <= 0 || parsed > 4294967295) {
1092
+ throw new Error("CPU maximum must be between 1 and 4294967295 millicores or blank");
1093
+ }
1094
+ return parsed;
1095
+ }
1096
+ function MachineOperationPolicyEditor({
1097
+ policy,
1098
+ memorySupported,
1099
+ cpuSupported,
1100
+ saving = false,
1101
+ onSave
1102
+ }) {
1103
+ const [memoryMaxBytes, setMemoryMaxBytes] = useState2(fieldValue(policy.memoryMaxBytes));
1104
+ const [memoryHighBytes, setMemoryHighBytes] = useState2(fieldValue(policy.memoryHighBytes));
1105
+ const [cpuMaxMillicores, setCpuMaxMillicores] = useState2(fieldValue(policy.cpuMaxMillicores));
1106
+ const [validationError, setValidationError] = useState2(null);
1107
+ useEffect(() => {
1108
+ setMemoryMaxBytes(fieldValue(policy.memoryMaxBytes));
1109
+ setMemoryHighBytes(fieldValue(policy.memoryHighBytes));
1110
+ setCpuMaxMillicores(fieldValue(policy.cpuMaxMillicores));
1111
+ setValidationError(null);
1112
+ }, [policy.memoryMaxBytes, policy.memoryHighBytes, policy.cpuMaxMillicores, policy.revision]);
1113
+ const submit = async (event) => {
1114
+ event.preventDefault();
1115
+ try {
1116
+ const max = parseByteCount("Hard ceiling", memoryMaxBytes);
1117
+ const high = parseByteCount("Reclaim threshold", memoryHighBytes);
1118
+ if (max !== null && high !== null && high > max) {
1119
+ throw new Error("Reclaim threshold cannot exceed the hard ceiling");
1120
+ }
1121
+ const cpuMax = parseCpuMillicores(cpuMaxMillicores);
1122
+ setValidationError(null);
1123
+ await onSave({
1124
+ memoryMaxBytes: max,
1125
+ memoryHighBytes: high,
1126
+ cpuMaxMillicores: cpuMax,
1127
+ expectedRevision: policy.revision
1128
+ });
1129
+ } catch (error) {
1130
+ setValidationError(error instanceof Error ? error.message : String(error));
1131
+ }
1132
+ };
1133
+ const configured = policy.memoryMaxBytes !== null || policy.memoryHighBytes !== null || policy.cpuMaxMillicores !== null;
1134
+ const memoryConfigured = policy.memoryMaxBytes !== null || policy.memoryHighBytes !== null;
1135
+ const unsupportedMemory = memoryConfigured && !memorySupported;
1136
+ const unsupportedCpu = policy.cpuMaxMillicores !== null && (!memorySupported || !cpuSupported);
1137
+ return /* @__PURE__ */ jsxs7(
1138
+ "section",
1139
+ {
1140
+ "data-machine-operation-policy": true,
1141
+ className: "rounded-og-lg border border-og-border bg-og-surface-1 p-4 shadow-og-sm",
1142
+ children: [
1143
+ /* @__PURE__ */ jsxs7("div", { className: "flex flex-col gap-1", children: [
1144
+ /* @__PURE__ */ jsx7("h2", { className: "text-og-sm font-semibold text-og-fg", children: "Per-command resource policy" }),
1145
+ /* @__PURE__ */ jsx7("p", { className: "text-og-xs leading-relaxed text-og-fg-muted", children: "Optional limits applied separately to each newly admitted exec and Git command. Running commands keep their admitted policy. Blank means unrestricted. The runner or host may apply a stricter explicit policy; browser, computer-use, and terminal capabilities remain unchanged." })
1146
+ ] }),
1147
+ configured && (unsupportedMemory || unsupportedCpu) ? /* @__PURE__ */ jsxs7("div", { className: "mt-3 flex gap-2 rounded-og-md border border-og-status-failed/40 bg-og-status-failed/5 p-3 text-og-xs text-og-status-failed", children: [
1148
+ /* @__PURE__ */ jsx7(AlertTriangleIcon2, { className: "mt-0.5 size-3.5 shrink-0", "aria-hidden": true }),
1149
+ /* @__PURE__ */ jsxs7("span", { children: [
1150
+ unsupportedCpu ? "This runner cannot enforce the configured CPU limit." : "This runner cannot enforce the configured memory limit.",
1151
+ " ",
1152
+ "Command execution fails closed until the current runner, OS, and service configuration can enforce it, or the unsupported limit is cleared. You can still save limits now for later enforcement."
1153
+ ] })
1154
+ ] }) : null,
1155
+ /* @__PURE__ */ jsxs7("form", { className: "mt-4 grid gap-3 sm:grid-cols-2", onSubmit: submit, children: [
1156
+ /* @__PURE__ */ jsxs7("label", { className: "flex flex-col gap-1.5 text-og-xs text-og-fg-muted", children: [
1157
+ "Hard ceiling (bytes)",
1158
+ /* @__PURE__ */ jsx7(
1159
+ "input",
1160
+ {
1161
+ inputMode: "numeric",
1162
+ pattern: "[0-9]*",
1163
+ value: memoryMaxBytes,
1164
+ onChange: (event) => setMemoryMaxBytes(event.target.value),
1165
+ placeholder: "Unlimited",
1166
+ disabled: saving,
1167
+ className: "min-h-9 rounded-og-sm border border-og-border bg-og-bg px-2.5 font-og-mono text-og-sm text-og-fg outline-hidden focus-visible:ring-2 focus-visible:ring-og-accent/50 disabled:opacity-60"
1168
+ }
1169
+ )
1170
+ ] }),
1171
+ /* @__PURE__ */ jsxs7("label", { className: "flex flex-col gap-1.5 text-og-xs text-og-fg-muted", children: [
1172
+ "Reclaim threshold (bytes)",
1173
+ /* @__PURE__ */ jsx7(
1174
+ "input",
1175
+ {
1176
+ inputMode: "numeric",
1177
+ pattern: "[0-9]*",
1178
+ value: memoryHighBytes,
1179
+ onChange: (event) => setMemoryHighBytes(event.target.value),
1180
+ placeholder: "Unlimited",
1181
+ disabled: saving,
1182
+ className: "min-h-9 rounded-og-sm border border-og-border bg-og-bg px-2.5 font-og-mono text-og-sm text-og-fg outline-hidden focus-visible:ring-2 focus-visible:ring-og-accent/50 disabled:opacity-60"
1183
+ }
1184
+ )
1185
+ ] }),
1186
+ /* @__PURE__ */ jsxs7("label", { className: "flex flex-col gap-1.5 text-og-xs text-og-fg-muted", children: [
1187
+ "CPU maximum (millicores)",
1188
+ /* @__PURE__ */ jsx7(
1189
+ "input",
1190
+ {
1191
+ inputMode: "numeric",
1192
+ pattern: "[0-9]*",
1193
+ value: cpuMaxMillicores,
1194
+ onChange: (event) => setCpuMaxMillicores(event.target.value),
1195
+ placeholder: "Unlimited",
1196
+ disabled: saving,
1197
+ className: "min-h-9 rounded-og-sm border border-og-border bg-og-bg px-2.5 font-og-mono text-og-sm text-og-fg outline-hidden focus-visible:ring-2 focus-visible:ring-og-accent/50 disabled:opacity-60"
1198
+ }
1199
+ ),
1200
+ /* @__PURE__ */ jsx7("span", { children: "1000 millicores = one CPU core. Blank is unlimited." })
1201
+ ] }),
1202
+ /* @__PURE__ */ jsxs7("div", { className: "flex min-h-9 items-center justify-between gap-3 sm:col-span-2", children: [
1203
+ /* @__PURE__ */ jsx7(
1204
+ "span",
1205
+ {
1206
+ role: validationError ? "alert" : void 0,
1207
+ className: "text-og-xs text-og-status-failed",
1208
+ children: validationError
1209
+ }
1210
+ ),
1211
+ /* @__PURE__ */ jsxs7(
1212
+ "button",
1213
+ {
1214
+ type: "submit",
1215
+ disabled: saving,
1216
+ className: "inline-flex min-h-9 items-center gap-1.5 rounded-og-sm border border-og-primary-border bg-og-primary text-og-primary-fg px-3 py-1.5 text-og-xs font-medium transition-colors hover:bg-og-primary-hover disabled:cursor-not-allowed disabled:opacity-60",
1217
+ children: [
1218
+ saving ? /* @__PURE__ */ jsx7(Loader2Icon, { className: "size-3.5 animate-spin", "aria-hidden": true }) : null,
1219
+ "Save policy"
1220
+ ]
1221
+ }
1222
+ )
1223
+ ] })
1224
+ ] })
1225
+ ]
1226
+ }
1227
+ );
1228
+ }
1229
+
1230
+ // src/components/machines/machine-detail.tsx
1231
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
984
1232
  function KindIcon2({ kind, session }) {
985
- if (session) return /* @__PURE__ */ jsx7(ServerIcon2, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
986
- if (kind === "modal") return /* @__PURE__ */ jsx7(CpuIcon2, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
987
- return /* @__PURE__ */ jsx7(LaptopIcon2, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
1233
+ if (kind === "local" || kind === "selfhosted")
1234
+ return /* @__PURE__ */ jsx8(LaptopIcon2, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
1235
+ if (kind === "docker" || session)
1236
+ return /* @__PURE__ */ jsx8(ServerIcon2, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
1237
+ if (kind === "modal") return /* @__PURE__ */ jsx8(CpuIcon2, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
1238
+ return /* @__PURE__ */ jsx8(ServerIcon2, { className: "size-4 text-og-fg-subtle", "aria-hidden": true });
988
1239
  }
989
1240
  function MachineDetail({
990
1241
  machine,
991
1242
  series,
992
- window: window2,
1243
+ window,
993
1244
  onWindowChange,
994
1245
  loadingSeries,
995
1246
  onBack,
996
1247
  onRemove,
1248
+ onUpdateOperationPolicy,
1249
+ updatingOperationPolicy,
997
1250
  now = Date.now(),
998
1251
  className
999
1252
  }) {
@@ -1001,31 +1254,33 @@ function MachineDetail({
1001
1254
  const tone = HEALTH_TOKEN[health.level];
1002
1255
  const latest = machine.metrics;
1003
1256
  const sampledAgo = latest ? formatRelativeTime(latest.sampledAt, new Date(now)) : null;
1257
+ const authority = machine.connectionAuthority;
1258
+ const duplicateDeniedAgo = authority.duplicateRunnerDeniedAt ? formatRelativeTime(authority.duplicateRunnerDeniedAt, new Date(now)) : null;
1004
1259
  const visible = METRICS.filter((m) => !(m.key === "gpu" && latest?.gpuUtilPct == null));
1005
1260
  const tileCols = visible.length >= 5 ? "grid-cols-2 sm:grid-cols-3 lg:grid-cols-5" : "grid-cols-2 sm:grid-cols-4";
1006
- return /* @__PURE__ */ jsxs7("div", { className: cn("og-root mx-auto flex w-full max-w-5xl flex-col gap-5", className), children: [
1007
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between gap-3", children: [
1008
- /* @__PURE__ */ jsxs7("div", { className: "flex min-w-0 items-center gap-2.5", children: [
1009
- onBack && /* @__PURE__ */ jsx7(
1261
+ return /* @__PURE__ */ jsxs8("div", { className: cn("og-root mx-auto flex w-full max-w-5xl flex-col gap-5", className), children: [
1262
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between gap-3", children: [
1263
+ /* @__PURE__ */ jsxs8("div", { className: "flex min-w-0 items-center gap-2.5", children: [
1264
+ onBack && /* @__PURE__ */ jsx8(
1010
1265
  "button",
1011
1266
  {
1012
1267
  type: "button",
1013
1268
  onClick: onBack,
1014
1269
  className: "flex size-7 shrink-0 items-center justify-center rounded-og-sm border border-og-border bg-og-surface-1 text-og-fg-muted transition-colors hover:bg-og-surface-2 hover:text-og-fg",
1015
1270
  "aria-label": "Back to machines",
1016
- children: /* @__PURE__ */ jsx7(ArrowLeftIcon, { className: "size-3.5", "aria-hidden": true })
1271
+ children: /* @__PURE__ */ jsx8(ArrowLeftIcon, { className: "size-3.5", "aria-hidden": true })
1017
1272
  }
1018
1273
  ),
1019
- /* @__PURE__ */ jsx7(KindIcon2, { kind: machine.kind, session: machine.isSessionGroup }),
1020
- /* @__PURE__ */ jsx7("h1", { className: "truncate text-og-md font-semibold text-og-fg", children: machine.name }),
1021
- /* @__PURE__ */ jsxs7("span", { className: "hidden shrink-0 rounded-og-sm border border-og-border bg-og-surface-1 px-1.5 py-0.5 font-og-mono text-og-xs text-og-fg-subtle sm:inline", children: [
1274
+ /* @__PURE__ */ jsx8(KindIcon2, { kind: machine.kind, session: machine.isSessionGroup }),
1275
+ /* @__PURE__ */ jsx8("h1", { className: "truncate text-og-md font-semibold text-og-fg", children: machine.name }),
1276
+ /* @__PURE__ */ jsxs8("span", { className: "hidden shrink-0 rounded-og-sm border border-og-border bg-og-surface-1 px-1.5 py-0.5 font-og-mono text-og-xs text-og-fg-subtle sm:inline", children: [
1022
1277
  machine.os,
1023
1278
  " \xB7 ",
1024
1279
  machine.arch
1025
1280
  ] })
1026
1281
  ] }),
1027
- /* @__PURE__ */ jsxs7("div", { className: "flex shrink-0 items-center gap-2", children: [
1028
- onRemove && machine.enrollmentId && !machine.isSessionGroup ? /* @__PURE__ */ jsxs7(
1282
+ /* @__PURE__ */ jsxs8("div", { className: "flex shrink-0 items-center gap-2", children: [
1283
+ onRemove && machine.enrollmentId && !machine.isSessionGroup ? /* @__PURE__ */ jsxs8(
1029
1284
  "button",
1030
1285
  {
1031
1286
  type: "button",
@@ -1034,20 +1289,20 @@ function MachineDetail({
1034
1289
  onClick: () => onRemove(machine),
1035
1290
  className: "inline-flex min-h-9 items-center gap-1.5 rounded-og-sm border border-og-status-failed/40 px-2.5 py-1 font-medium text-og-xs text-og-status-failed transition-colors hover:bg-og-status-failed/10 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-og-status-failed/50 pointer-coarse:min-h-11",
1036
1291
  children: [
1037
- /* @__PURE__ */ jsx7(Trash2Icon, { className: "size-3.5", "aria-hidden": true }),
1038
- /* @__PURE__ */ jsx7("span", { className: "hidden sm:inline", children: "Remove machine" })
1292
+ /* @__PURE__ */ jsx8(Trash2Icon, { className: "size-3.5", "aria-hidden": true }),
1293
+ /* @__PURE__ */ jsx8("span", { className: "hidden sm:inline", children: "Remove machine" })
1039
1294
  ]
1040
1295
  }
1041
1296
  ) : null,
1042
- /* @__PURE__ */ jsx7("div", { className: "flex items-center gap-0.5 rounded-og-md border border-og-border bg-og-surface-1 p-0.5", children: METRIC_WINDOWS.map((w) => /* @__PURE__ */ jsx7(
1297
+ /* @__PURE__ */ jsx8("div", { className: "flex items-center gap-0.5 rounded-og-md border border-og-border bg-og-surface-1 p-0.5", children: METRIC_WINDOWS.map((w) => /* @__PURE__ */ jsx8(
1043
1298
  "button",
1044
1299
  {
1045
1300
  type: "button",
1046
1301
  onClick: () => onWindowChange(w),
1047
- "data-active": w === window2,
1302
+ "data-active": w === window,
1048
1303
  className: cn(
1049
1304
  "rounded-og-sm px-2 py-1 font-og-mono text-og-xs transition-colors",
1050
- w === window2 ? "bg-og-surface-3 text-og-fg shadow-og-sm" : "text-og-fg-subtle hover:text-og-fg-muted"
1305
+ w === window ? "bg-og-surface-3 text-og-fg shadow-og-sm" : "text-og-fg-subtle hover:text-og-fg-muted"
1051
1306
  ),
1052
1307
  children: w
1053
1308
  },
@@ -1055,7 +1310,7 @@ function MachineDetail({
1055
1310
  )) })
1056
1311
  ] })
1057
1312
  ] }),
1058
- /* @__PURE__ */ jsxs7(
1313
+ /* @__PURE__ */ jsxs8(
1059
1314
  "div",
1060
1315
  {
1061
1316
  className: cn(
@@ -1063,11 +1318,11 @@ function MachineDetail({
1063
1318
  tone.soft
1064
1319
  ),
1065
1320
  children: [
1066
- /* @__PURE__ */ jsx7("span", { "aria-hidden": true, className: cn("absolute inset-y-0 left-0 w-1", tone.dot) }),
1067
- /* @__PURE__ */ jsxs7("div", { className: "flex flex-wrap items-center justify-between gap-3 pl-1", children: [
1068
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-3", children: [
1069
- /* @__PURE__ */ jsxs7("span", { className: "relative flex size-3", children: [
1070
- healthPulses(health.level) && /* @__PURE__ */ jsx7(
1321
+ /* @__PURE__ */ jsx8("span", { "aria-hidden": true, className: cn("absolute inset-y-0 left-0 w-1", tone.dot) }),
1322
+ /* @__PURE__ */ jsxs8("div", { className: "flex flex-wrap items-center justify-between gap-3 pl-1", children: [
1323
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3", children: [
1324
+ /* @__PURE__ */ jsxs8("span", { className: "relative flex size-3", children: [
1325
+ healthPulses(health.level) && /* @__PURE__ */ jsx8(
1071
1326
  "span",
1072
1327
  {
1073
1328
  className: cn(
@@ -1076,18 +1331,18 @@ function MachineDetail({
1076
1331
  )
1077
1332
  }
1078
1333
  ),
1079
- /* @__PURE__ */ jsx7("span", { className: cn("relative inline-flex size-3 rounded-full", tone.dot) })
1334
+ /* @__PURE__ */ jsx8("span", { className: cn("relative inline-flex size-3 rounded-full", tone.dot) })
1080
1335
  ] }),
1081
- /* @__PURE__ */ jsxs7("div", { className: "flex flex-col", children: [
1082
- /* @__PURE__ */ jsx7("span", { className: cn("text-og-md font-semibold", tone.text), children: health.label }),
1083
- /* @__PURE__ */ jsx7("span", { className: "text-og-sm text-og-fg-muted", children: health.reason })
1336
+ /* @__PURE__ */ jsxs8("div", { className: "flex flex-col", children: [
1337
+ /* @__PURE__ */ jsx8("span", { className: cn("text-og-md font-semibold", tone.text), children: health.label }),
1338
+ /* @__PURE__ */ jsx8("span", { className: "text-og-sm text-og-fg-muted", children: health.reason })
1084
1339
  ] })
1085
1340
  ] }),
1086
- /* @__PURE__ */ jsxs7("div", { className: "flex items-start gap-5 pr-1", children: [
1087
- sampledAgo && /* @__PURE__ */ jsxs7("div", { className: "flex flex-col items-end gap-0.5", children: [
1088
- /* @__PURE__ */ jsx7("span", { className: "text-[10px] font-medium uppercase tracking-wide text-og-fg-subtle", children: "Sampled" }),
1089
- /* @__PURE__ */ jsxs7("span", { className: "flex items-center gap-1 font-og-mono text-og-sm tabular-nums text-og-fg", children: [
1090
- /* @__PURE__ */ jsx7(
1341
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-start gap-5 pr-1", children: [
1342
+ sampledAgo && /* @__PURE__ */ jsxs8("div", { className: "flex flex-col items-end gap-0.5", children: [
1343
+ /* @__PURE__ */ jsx8("span", { className: "text-[10px] font-medium uppercase tracking-wide text-og-fg-subtle", children: "Sampled" }),
1344
+ /* @__PURE__ */ jsxs8("span", { className: "flex items-center gap-1 font-og-mono text-og-sm tabular-nums text-og-fg", children: [
1345
+ /* @__PURE__ */ jsx8(
1091
1346
  RadioIcon,
1092
1347
  {
1093
1348
  className: cn("size-3", health.stale ? "text-og-fg-subtle" : tone.text),
@@ -1097,13 +1352,13 @@ function MachineDetail({
1097
1352
  sampledAgo === "now" ? "live" : `${sampledAgo} ago`
1098
1353
  ] })
1099
1354
  ] }),
1100
- machine.lastSeenAt && /* @__PURE__ */ jsxs7("div", { className: "hidden flex-col items-end gap-0.5 sm:flex", children: [
1101
- /* @__PURE__ */ jsx7("span", { className: "text-[10px] font-medium uppercase tracking-wide text-og-fg-subtle", children: "Last seen" }),
1102
- /* @__PURE__ */ jsx7("span", { className: "font-og-mono text-og-sm tabular-nums text-og-fg-muted", children: formatRelativeTime(machine.lastSeenAt, new Date(now)) })
1355
+ machine.lastSeenAt && /* @__PURE__ */ jsxs8("div", { className: "hidden flex-col items-end gap-0.5 sm:flex", children: [
1356
+ /* @__PURE__ */ jsx8("span", { className: "text-[10px] font-medium uppercase tracking-wide text-og-fg-subtle", children: "Last seen" }),
1357
+ /* @__PURE__ */ jsx8("span", { className: "font-og-mono text-og-sm tabular-nums text-og-fg-muted", children: formatRelativeTime(machine.lastSeenAt, new Date(now)) })
1103
1358
  ] })
1104
1359
  ] })
1105
1360
  ] }),
1106
- latest && /* @__PURE__ */ jsx7(
1361
+ latest && /* @__PURE__ */ jsx8(
1107
1362
  "div",
1108
1363
  {
1109
1364
  className: cn(
@@ -1112,30 +1367,64 @@ function MachineDetail({
1112
1367
  ),
1113
1368
  children: visible.map((m) => {
1114
1369
  const pts = pointsFor(m, series);
1115
- return /* @__PURE__ */ jsxs7("div", { className: "flex flex-col gap-1.5 bg-og-surface-1 p-3", children: [
1116
- /* @__PURE__ */ jsx7("span", { className: "text-[10px] font-medium uppercase tracking-wide text-og-fg-subtle", children: m.title }),
1117
- /* @__PURE__ */ jsx7("span", { className: "font-og-mono text-og-md font-medium tabular-nums text-og-fg", children: m.current(latest) }),
1118
- /* @__PURE__ */ jsx7(MetricSparkline, { points: pts, color: m.color, yMax: m.yMax, height: 22 }),
1119
- m.sub && /* @__PURE__ */ jsx7("span", { className: "truncate font-og-mono text-[10px] text-og-fg-subtle", children: m.sub(latest) })
1370
+ return /* @__PURE__ */ jsxs8("div", { className: "flex flex-col gap-1.5 bg-og-surface-1 p-3", children: [
1371
+ /* @__PURE__ */ jsx8("span", { className: "text-[10px] font-medium uppercase tracking-wide text-og-fg-subtle", children: m.title }),
1372
+ /* @__PURE__ */ jsx8("span", { className: "font-og-mono text-og-md font-medium tabular-nums text-og-fg", children: m.current(latest) }),
1373
+ /* @__PURE__ */ jsx8(MetricSparkline, { points: pts, color: m.color, yMax: m.yMax, height: 22 }),
1374
+ m.sub && /* @__PURE__ */ jsx8("span", { className: "truncate font-og-mono text-[10px] text-og-fg-subtle", children: m.sub(latest) })
1120
1375
  ] }, m.key);
1121
1376
  })
1122
1377
  }
1123
- )
1378
+ ),
1379
+ authority.state !== "not_applicable" ? /* @__PURE__ */ jsxs8(
1380
+ "div",
1381
+ {
1382
+ "data-connection-authority": authority.state,
1383
+ className: "flex flex-wrap items-center justify-between gap-2 rounded-og-md border border-og-border bg-og-surface-1/75 px-3 py-2 text-og-xs",
1384
+ children: [
1385
+ /* @__PURE__ */ jsxs8("span", { className: "text-og-fg-muted", children: [
1386
+ "Runner ",
1387
+ authority.state.replace("_", " "),
1388
+ " \xB7 generation ",
1389
+ authority.generation,
1390
+ authority.supersededCount > 0 ? ` \xB7 ${authority.supersededCount} earlier ${authority.supersededCount === 1 ? "runner" : "runners"} fenced` : ""
1391
+ ] }),
1392
+ authority.duplicateRunnerDeniedCount > 0 ? /* @__PURE__ */ jsxs8("span", { className: "inline-flex items-center gap-1.5 text-og-status-failed", children: [
1393
+ /* @__PURE__ */ jsx8(AlertTriangleIcon3, { className: "size-3.5", "aria-hidden": true }),
1394
+ "Blocked ",
1395
+ authority.duplicateRunnerDeniedCount,
1396
+ " competing runner",
1397
+ authority.duplicateRunnerDeniedCount === 1 ? "" : "s",
1398
+ duplicateDeniedAgo ? ` \xB7 ${duplicateDeniedAgo === "now" ? "now" : `${duplicateDeniedAgo} ago`}` : ""
1399
+ ] }) : null
1400
+ ]
1401
+ }
1402
+ ) : null
1124
1403
  ]
1125
1404
  }
1126
1405
  ),
1127
- /* @__PURE__ */ jsx7("div", { className: "grid grid-cols-1 gap-3 lg:grid-cols-2", children: visible.map((m) => {
1406
+ onUpdateOperationPolicy && machine.enrollmentId && machine.operationPolicy ? /* @__PURE__ */ jsx8(
1407
+ MachineOperationPolicyEditor,
1408
+ {
1409
+ policy: machine.operationPolicy,
1410
+ memorySupported: machine.runtime?.capabilities.operationResourcePolicy === true,
1411
+ cpuSupported: machine.runtime?.capabilities.operationCpuQuota === true,
1412
+ saving: updatingOperationPolicy,
1413
+ onSave: (request) => onUpdateOperationPolicy(machine, request)
1414
+ }
1415
+ ) : null,
1416
+ /* @__PURE__ */ jsx8("div", { className: "grid grid-cols-1 gap-3 lg:grid-cols-2", children: visible.map((m) => {
1128
1417
  const pts = pointsFor(m, series);
1129
- return /* @__PURE__ */ jsxs7(
1418
+ return /* @__PURE__ */ jsxs8(
1130
1419
  "div",
1131
1420
  {
1132
1421
  className: "flex flex-col gap-3 rounded-og-lg border border-og-border bg-og-surface-1 p-4 shadow-og-sm",
1133
1422
  children: [
1134
- /* @__PURE__ */ jsxs7("div", { className: "flex items-baseline justify-between", children: [
1135
- /* @__PURE__ */ jsx7("span", { className: "text-og-sm font-medium text-og-fg", children: m.title }),
1136
- latest && /* @__PURE__ */ jsx7("span", { className: "font-og-mono text-og-sm tabular-nums text-og-fg-muted", children: m.current(latest) })
1423
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-baseline justify-between", children: [
1424
+ /* @__PURE__ */ jsx8("span", { className: "text-og-sm font-medium text-og-fg", children: m.title }),
1425
+ latest && /* @__PURE__ */ jsx8("span", { className: "font-og-mono text-og-sm tabular-nums text-og-fg-muted", children: m.current(latest) })
1137
1426
  ] }),
1138
- /* @__PURE__ */ jsx7(
1427
+ /* @__PURE__ */ jsx8(
1139
1428
  MetricHistoryChart,
1140
1429
  {
1141
1430
  points: pts,
@@ -1143,7 +1432,7 @@ function MachineDetail({
1143
1432
  unit: m.unit,
1144
1433
  color: m.color,
1145
1434
  thresholds: m.thresholds,
1146
- rangeLabel: WINDOW_LABEL[window2],
1435
+ rangeLabel: WINDOW_LABEL[window],
1147
1436
  height: 128,
1148
1437
  className: cn(loadingSeries && "opacity-50 transition-opacity")
1149
1438
  }
@@ -1158,28 +1447,28 @@ function MachineDetail({
1158
1447
 
1159
1448
  // src/components/machines-dashboard.tsx
1160
1449
  import { LaptopIcon as LaptopIcon3, PlusIcon, RefreshCwIcon } from "lucide-react";
1161
- import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1450
+ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
1162
1451
  function EmptyState({ onEnroll }) {
1163
- return /* @__PURE__ */ jsxs8(
1452
+ return /* @__PURE__ */ jsxs9(
1164
1453
  "div",
1165
1454
  {
1166
1455
  "data-machines-empty": true,
1167
1456
  className: "flex flex-col items-center justify-center gap-3 rounded-og-lg border border-dashed border-og-border bg-og-surface-1 px-6 py-12 text-center",
1168
1457
  children: [
1169
- /* @__PURE__ */ jsx8("span", { className: "flex size-10 items-center justify-center rounded-full bg-og-surface-2 text-og-fg-subtle", children: /* @__PURE__ */ jsx8(LaptopIcon3, { className: "size-5", "aria-hidden": true }) }),
1170
- /* @__PURE__ */ jsxs8("div", { className: "space-y-1", children: [
1171
- /* @__PURE__ */ jsx8("p", { className: "text-og-base font-medium text-og-fg", children: "No machines yet" }),
1172
- /* @__PURE__ */ jsx8("p", { className: "max-w-xs text-og-sm text-og-fg-muted", children: "Connect your own computer to run the agent on it \u2014 your files, your terminal, your desktop." })
1458
+ /* @__PURE__ */ jsx9("span", { className: "flex size-10 items-center justify-center rounded-full bg-og-surface-2 text-og-fg-subtle", children: /* @__PURE__ */ jsx9(LaptopIcon3, { className: "size-5", "aria-hidden": true }) }),
1459
+ /* @__PURE__ */ jsxs9("div", { className: "space-y-1", children: [
1460
+ /* @__PURE__ */ jsx9("p", { className: "text-og-base font-medium text-og-fg", children: "No machines yet" }),
1461
+ /* @__PURE__ */ jsx9("p", { className: "max-w-xs text-og-sm text-og-fg-muted", children: "Connect your own computer to run the agent on it \u2014 your files, your terminal, your desktop." })
1173
1462
  ] }),
1174
- onEnroll ? /* @__PURE__ */ jsxs8(
1463
+ onEnroll ? /* @__PURE__ */ jsxs9(
1175
1464
  "button",
1176
1465
  {
1177
1466
  type: "button",
1178
1467
  "data-enroll-cta": true,
1179
1468
  onClick: onEnroll,
1180
- className: "inline-flex items-center gap-1.5 rounded-og-sm bg-og-accent px-3 py-1.5 text-og-sm font-medium text-og-accent-fg transition-colors hover:bg-og-accent-strong pointer-coarse:min-h-11",
1469
+ className: "inline-flex items-center gap-1.5 rounded-og-sm border border-og-primary-border bg-og-primary text-og-primary-fg px-3 py-1.5 text-og-sm font-medium transition-colors hover:bg-og-primary-hover pointer-coarse:min-h-11",
1181
1470
  children: [
1182
- /* @__PURE__ */ jsx8(PlusIcon, { className: "size-3.5", "aria-hidden": true }),
1471
+ /* @__PURE__ */ jsx9(PlusIcon, { className: "size-3.5", "aria-hidden": true }),
1183
1472
  "Connect a machine"
1184
1473
  ]
1185
1474
  }
@@ -1190,41 +1479,26 @@ function EmptyState({ onEnroll }) {
1190
1479
  }
1191
1480
  function Header({
1192
1481
  count,
1193
- onEnroll,
1194
- onRefresh,
1195
- loading
1482
+ onEnroll
1196
1483
  }) {
1197
- return /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between gap-3", children: [
1198
- /* @__PURE__ */ jsxs8("div", { className: "flex items-baseline gap-2", children: [
1199
- /* @__PURE__ */ jsx8("h2", { className: "text-og-base font-semibold text-og-fg", children: "Machines" }),
1200
- /* @__PURE__ */ jsx8("span", { className: "font-og-mono text-og-xs text-og-fg-subtle", children: count })
1484
+ return /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between gap-3", children: [
1485
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-baseline gap-2", children: [
1486
+ /* @__PURE__ */ jsx9("h2", { className: "text-og-base font-semibold text-og-fg", children: "Machines" }),
1487
+ /* @__PURE__ */ jsx9("span", { className: "font-og-mono text-og-xs text-og-fg-subtle", children: count })
1201
1488
  ] }),
1202
- /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-1.5", children: [
1203
- onRefresh ? /* @__PURE__ */ jsx8(
1204
- "button",
1205
- {
1206
- type: "button",
1207
- "data-refresh": true,
1208
- onClick: onRefresh,
1209
- title: "Refresh",
1210
- className: "rounded-og-sm p-1.5 text-og-fg-subtle transition-colors hover:bg-og-surface-2 hover:text-og-fg",
1211
- children: /* @__PURE__ */ jsx8(RefreshCwIcon, { className: cn("size-3.5", loading && "animate-og-spin"), "aria-hidden": true })
1212
- }
1213
- ) : null,
1214
- onEnroll ? /* @__PURE__ */ jsxs8(
1215
- "button",
1216
- {
1217
- type: "button",
1218
- "data-enroll-cta": true,
1219
- onClick: onEnroll,
1220
- className: "inline-flex items-center gap-1.5 rounded-og-sm border border-og-border px-2.5 py-1 text-og-sm font-medium text-og-fg-muted transition-colors hover:border-og-border-strong hover:text-og-fg pointer-coarse:min-h-11",
1221
- children: [
1222
- /* @__PURE__ */ jsx8(PlusIcon, { className: "size-3.5", "aria-hidden": true }),
1223
- "Connect a machine"
1224
- ]
1225
- }
1226
- ) : null
1227
- ] })
1489
+ /* @__PURE__ */ jsx9("div", { className: "flex items-center gap-1.5", children: onEnroll ? /* @__PURE__ */ jsxs9(
1490
+ "button",
1491
+ {
1492
+ type: "button",
1493
+ "data-enroll-cta": true,
1494
+ onClick: onEnroll,
1495
+ className: "inline-flex items-center gap-1.5 rounded-og-sm border border-og-border px-2.5 py-1 text-og-sm font-medium text-og-fg-muted transition-colors hover:border-og-border-strong hover:text-og-fg pointer-coarse:min-h-11",
1496
+ children: [
1497
+ /* @__PURE__ */ jsx9(PlusIcon, { className: "size-3.5", "aria-hidden": true }),
1498
+ "Connect a machine"
1499
+ ]
1500
+ }
1501
+ ) : null })
1228
1502
  ] });
1229
1503
  }
1230
1504
  function MachinesDashboard({
@@ -1234,6 +1508,8 @@ function MachinesDashboard({
1234
1508
  error,
1235
1509
  onAttach,
1236
1510
  attachingSandboxId,
1511
+ onUpdateAgent,
1512
+ updatingEnrollmentId,
1237
1513
  seriesByMachine,
1238
1514
  onOpenDetail,
1239
1515
  now,
@@ -1242,19 +1518,19 @@ function MachinesDashboard({
1242
1518
  className
1243
1519
  }) {
1244
1520
  const isEmpty = !loading && !error && machines.length === 0;
1245
- return /* @__PURE__ */ jsxs8("section", { "data-machines-dashboard": true, className: cn("og-root flex flex-col gap-3", className), children: [
1246
- /* @__PURE__ */ jsx8(Header, { count: machines.length, onEnroll, onRefresh, loading }),
1247
- error ? /* @__PURE__ */ jsxs8(
1521
+ return /* @__PURE__ */ jsxs9("section", { "data-machines-dashboard": true, className: cn("og-root flex flex-col gap-3", className), children: [
1522
+ /* @__PURE__ */ jsx9(Header, { count: machines.length, onEnroll }),
1523
+ error ? /* @__PURE__ */ jsxs9(
1248
1524
  "div",
1249
1525
  {
1250
1526
  "data-machines-error": true,
1251
1527
  className: "flex flex-wrap items-center justify-between gap-2 rounded-og-md border border-og-status-failed/30 bg-og-status-failed/10 px-3 py-2 text-og-sm text-og-status-failed",
1252
1528
  children: [
1253
- /* @__PURE__ */ jsxs8("span", { children: [
1529
+ /* @__PURE__ */ jsxs9("span", { children: [
1254
1530
  "Could not load machines: ",
1255
1531
  error.message
1256
1532
  ] }),
1257
- onRefresh ? /* @__PURE__ */ jsxs8(
1533
+ onRefresh ? /* @__PURE__ */ jsxs9(
1258
1534
  "button",
1259
1535
  {
1260
1536
  type: "button",
@@ -1263,7 +1539,7 @@ function MachinesDashboard({
1263
1539
  disabled: loading,
1264
1540
  className: "inline-flex items-center gap-1.5 rounded-og-sm border border-og-status-failed/30 px-2 py-1 text-og-xs font-medium transition-colors hover:border-og-status-failed/50 disabled:cursor-not-allowed disabled:opacity-60 pointer-coarse:min-h-11",
1265
1541
  children: [
1266
- /* @__PURE__ */ jsx8(RefreshCwIcon, { className: cn("size-3.5", loading && "animate-og-spin"), "aria-hidden": true }),
1542
+ /* @__PURE__ */ jsx9(RefreshCwIcon, { className: cn("size-3.5", loading && "animate-og-spin"), "aria-hidden": true }),
1267
1543
  loading ? "Retrying\u2026" : "Retry"
1268
1544
  ]
1269
1545
  }
@@ -1271,13 +1547,13 @@ function MachinesDashboard({
1271
1547
  ]
1272
1548
  }
1273
1549
  ) : null,
1274
- loading && machines.length === 0 ? /* @__PURE__ */ jsx8("div", { "data-machines-loading": true, className: "grid gap-3 sm:grid-cols-2", children: [0, 1].map((i) => /* @__PURE__ */ jsx8(
1550
+ loading && machines.length === 0 ? /* @__PURE__ */ jsx9("div", { "data-machines-loading": true, className: "grid gap-3 sm:grid-cols-2", children: [0, 1].map((i) => /* @__PURE__ */ jsx9(
1275
1551
  "div",
1276
1552
  {
1277
1553
  className: "h-36 animate-og-pulse rounded-og-lg border border-og-border bg-og-surface-1"
1278
1554
  },
1279
1555
  i
1280
- )) }) : isEmpty ? /* @__PURE__ */ jsx8(EmptyState, { onEnroll }) : /* @__PURE__ */ jsx8("div", { className: "grid gap-3 sm:grid-cols-2 xl:grid-cols-3", "data-machines-grid": true, children: machines.map((machine) => /* @__PURE__ */ jsx8(
1556
+ )) }) : isEmpty ? /* @__PURE__ */ jsx9(EmptyState, { onEnroll }) : /* @__PURE__ */ jsx9("div", { className: "grid gap-3 sm:grid-cols-2 xl:grid-cols-3", "data-machines-grid": true, children: machines.map((machine) => /* @__PURE__ */ jsx9(
1281
1557
  MachineCard,
1282
1558
  {
1283
1559
  machine: {
@@ -1286,6 +1562,8 @@ function MachinesDashboard({
1286
1562
  },
1287
1563
  onAttach,
1288
1564
  attaching: attachingSandboxId === machine.sandboxId,
1565
+ onUpdateAgent,
1566
+ updatingAgent: updatingEnrollmentId === machine.enrollmentId,
1289
1567
  series: seriesByMachine?.[machine.sandboxId],
1290
1568
  onOpenDetail,
1291
1569
  now
@@ -1297,11 +1575,11 @@ function MachinesDashboard({
1297
1575
 
1298
1576
  // src/components/machine-dock-bar.tsx
1299
1577
  import { LaptopIcon as LaptopIcon4, CpuIcon as CpuIcon3, UsersIcon as UsersIcon2 } from "lucide-react";
1300
- import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
1578
+ import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
1301
1579
  function MachineDockBar({ name, kind, state, className }) {
1302
- const Icon = kind === "selfhosted" ? LaptopIcon4 : CpuIcon3;
1580
+ const Icon = kind === "selfhosted" || kind === "local" ? LaptopIcon4 : CpuIcon3;
1303
1581
  const stateBadge = MACHINE_STATE_BADGE_META[state];
1304
- return /* @__PURE__ */ jsxs9(
1582
+ return /* @__PURE__ */ jsxs10(
1305
1583
  "div",
1306
1584
  {
1307
1585
  "data-machine-dock-bar": true,
@@ -1310,10 +1588,10 @@ function MachineDockBar({ name, kind, state, className }) {
1310
1588
  className
1311
1589
  ),
1312
1590
  children: [
1313
- /* @__PURE__ */ jsxs9("div", { className: "flex min-w-0 items-center gap-1.5", children: [
1314
- /* @__PURE__ */ jsx9(Icon, { className: "size-3.5 shrink-0 text-og-fg-subtle", "aria-hidden": true }),
1315
- /* @__PURE__ */ jsx9("span", { className: "truncate text-[11px] font-medium text-og-fg", children: name }),
1316
- stateBadge ? /* @__PURE__ */ jsx9(
1591
+ /* @__PURE__ */ jsxs10("div", { className: "flex min-w-0 items-center gap-1.5", children: [
1592
+ /* @__PURE__ */ jsx10(Icon, { className: "size-3.5 shrink-0 text-og-fg-subtle", "aria-hidden": true }),
1593
+ /* @__PURE__ */ jsx10("span", { className: "truncate text-[11px] font-medium text-og-fg", children: name }),
1594
+ stateBadge ? /* @__PURE__ */ jsx10(
1317
1595
  "span",
1318
1596
  {
1319
1597
  "data-state-badge": state,
@@ -1325,7 +1603,7 @@ function MachineDockBar({ name, kind, state, className }) {
1325
1603
  }
1326
1604
  ) : null
1327
1605
  ] }),
1328
- /* @__PURE__ */ jsx9(
1606
+ /* @__PURE__ */ jsx10(
1329
1607
  ConnectionStatusPill,
1330
1608
  {
1331
1609
  status: connectionStatusForState(state),
@@ -1343,7 +1621,7 @@ function SharedMachineDisclosure({
1343
1621
  className
1344
1622
  }) {
1345
1623
  const others = Math.max(0, sharedSessionCount - 1);
1346
- return /* @__PURE__ */ jsxs9(
1624
+ return /* @__PURE__ */ jsxs10(
1347
1625
  "div",
1348
1626
  {
1349
1627
  "data-shared-disclosure": true,
@@ -1353,8 +1631,8 @@ function SharedMachineDisclosure({
1353
1631
  className
1354
1632
  ),
1355
1633
  children: [
1356
- /* @__PURE__ */ jsx9(UsersIcon2, { className: "size-3.5 shrink-0 text-og-accent", "aria-hidden": true }),
1357
- /* @__PURE__ */ jsxs9("span", { children: [
1634
+ /* @__PURE__ */ jsx10(UsersIcon2, { className: "size-3.5 shrink-0 text-og-accent", "aria-hidden": true }),
1635
+ /* @__PURE__ */ jsxs10("span", { children: [
1358
1636
  "Shared \u2014 ",
1359
1637
  others === 1 ? "another session is" : `${others} other sessions are`,
1360
1638
  " on this machine. They see the same terminal, files, and desktop."
@@ -1366,7 +1644,7 @@ function SharedMachineDisclosure({
1366
1644
 
1367
1645
  // src/components/enrollment-device-flow.tsx
1368
1646
  import { CopyIcon, ExternalLinkIcon, LaptopIcon as LaptopIcon5, TerminalIcon } from "lucide-react";
1369
- import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
1647
+ import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
1370
1648
  var PHASE_TO_STATE = {
1371
1649
  pending: "enrolling",
1372
1650
  authorized: "online",
@@ -1382,7 +1660,7 @@ function PhaseLabel({ phase }) {
1382
1660
  expired: "Code expired",
1383
1661
  disabled: "Enrollment disabled"
1384
1662
  };
1385
- return /* @__PURE__ */ jsx10("span", { children: text[phase] });
1663
+ return /* @__PURE__ */ jsx11("span", { children: text[phase] });
1386
1664
  }
1387
1665
  function EnrollmentDeviceFlow({
1388
1666
  userCode,
@@ -1399,7 +1677,7 @@ function EnrollmentDeviceFlow({
1399
1677
  const href = verificationUriComplete ?? verificationUri;
1400
1678
  const codeIsPlaceholder = !/[A-Za-z0-9]/.test(userCode);
1401
1679
  const awaitingCode = phase === "pending" && codeIsPlaceholder;
1402
- return /* @__PURE__ */ jsxs10(
1680
+ return /* @__PURE__ */ jsxs11(
1403
1681
  "div",
1404
1682
  {
1405
1683
  "data-enrollment-device-flow": true,
@@ -1408,28 +1686,28 @@ function EnrollmentDeviceFlow({
1408
1686
  className
1409
1687
  ),
1410
1688
  children: [
1411
- /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between gap-3", children: [
1412
- /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2", children: [
1413
- /* @__PURE__ */ jsx10("span", { className: "flex size-7 items-center justify-center rounded-full bg-og-surface-2 text-og-fg-muted", children: /* @__PURE__ */ jsx10(LaptopIcon5, { className: "size-4", "aria-hidden": true }) }),
1414
- /* @__PURE__ */ jsx10("h2", { className: "text-og-menu font-semibold text-og-fg", children: "Connect a machine" })
1689
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between gap-3", children: [
1690
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
1691
+ /* @__PURE__ */ jsx11("span", { className: "flex size-7 items-center justify-center rounded-full bg-og-surface-2 text-og-fg-muted", children: /* @__PURE__ */ jsx11(LaptopIcon5, { className: "size-4", "aria-hidden": true }) }),
1692
+ /* @__PURE__ */ jsx11("h2", { className: "text-og-menu font-semibold text-og-fg", children: "Connect a machine" })
1415
1693
  ] }),
1416
- /* @__PURE__ */ jsx10(
1694
+ /* @__PURE__ */ jsx11(
1417
1695
  ConnectionStatusPill,
1418
1696
  {
1419
1697
  status: PHASE_TO_STATE[phase] === "online" ? "online" : PHASE_TO_STATE[phase] === "offline" ? "offline" : "reconnecting",
1420
- label: /* @__PURE__ */ jsx10(PhaseLabel, { phase }),
1698
+ label: /* @__PURE__ */ jsx11(PhaseLabel, { phase }),
1421
1699
  size: "sm"
1422
1700
  }
1423
1701
  )
1424
1702
  ] }),
1425
- installCommand ? /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-1.5", children: [
1426
- /* @__PURE__ */ jsx10("span", { className: "text-[11px] font-medium uppercase tracking-wide text-og-fg-subtle", children: "1 \xB7 Run on the machine" }),
1427
- /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between gap-2 overflow-hidden rounded-og-md border border-og-border bg-og-bg px-2.5 py-1.5", children: [
1428
- /* @__PURE__ */ jsxs10("code", { className: "flex min-w-0 items-center gap-2 overflow-x-auto font-og-mono text-[12px] text-og-fg", children: [
1429
- /* @__PURE__ */ jsx10(TerminalIcon, { className: "size-3.5 shrink-0 text-og-fg-subtle", "aria-hidden": true }),
1703
+ installCommand ? /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-1.5", children: [
1704
+ /* @__PURE__ */ jsx11("span", { className: "text-[11px] font-medium uppercase tracking-wide text-og-fg-subtle", children: "1 \xB7 Run on the machine" }),
1705
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between gap-2 overflow-hidden rounded-og-md border border-og-border bg-og-bg px-2.5 py-1.5", children: [
1706
+ /* @__PURE__ */ jsxs11("code", { className: "flex min-w-0 items-center gap-2 overflow-x-auto font-og-mono text-[12px] text-og-fg", children: [
1707
+ /* @__PURE__ */ jsx11(TerminalIcon, { className: "size-3.5 shrink-0 text-og-fg-subtle", "aria-hidden": true }),
1430
1708
  installCommand
1431
1709
  ] }),
1432
- /* @__PURE__ */ jsx10(
1710
+ /* @__PURE__ */ jsx11(
1433
1711
  "button",
1434
1712
  {
1435
1713
  type: "button",
@@ -1437,15 +1715,15 @@ function EnrollmentDeviceFlow({
1437
1715
  onClick: onCopyInstall,
1438
1716
  title: "Copy command",
1439
1717
  className: "shrink-0 rounded-og-sm p-1.5 text-og-fg-subtle transition-colors hover:bg-og-surface-2 hover:text-og-fg",
1440
- children: /* @__PURE__ */ jsx10(CopyIcon, { className: "size-4", "aria-hidden": true })
1718
+ children: /* @__PURE__ */ jsx11(CopyIcon, { className: "size-4", "aria-hidden": true })
1441
1719
  }
1442
1720
  )
1443
1721
  ] })
1444
1722
  ] }) : null,
1445
- /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-1.5", children: [
1446
- /* @__PURE__ */ jsx10("span", { className: "text-[11px] font-medium uppercase tracking-wide text-og-fg-subtle", children: installCommand ? "2 \xB7 Approve the machine" : "Approve the machine" }),
1447
- /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between gap-3 rounded-og-md border border-og-border bg-og-bg px-3 py-2.5", children: [
1448
- awaitingCode ? /* @__PURE__ */ jsx10("span", { "data-user-code": true, className: "font-og-mono text-[13px] text-og-fg-subtle", children: "Run the command above \u2014 your code appears here" }) : /* @__PURE__ */ jsx10(
1723
+ /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-1.5", children: [
1724
+ /* @__PURE__ */ jsx11("span", { className: "text-[11px] font-medium uppercase tracking-wide text-og-fg-subtle", children: installCommand ? "2 \xB7 Approve the machine" : "Approve the machine" }),
1725
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between gap-3 rounded-og-md border border-og-border bg-og-bg px-3 py-2.5", children: [
1726
+ awaitingCode ? /* @__PURE__ */ jsx11("span", { "data-user-code": true, className: "font-og-mono text-[13px] text-og-fg-subtle", children: "Run the command above \u2014 your code appears here" }) : /* @__PURE__ */ jsx11(
1449
1727
  "span",
1450
1728
  {
1451
1729
  "data-user-code": true,
@@ -1453,7 +1731,7 @@ function EnrollmentDeviceFlow({
1453
1731
  children: userCode
1454
1732
  }
1455
1733
  ),
1456
- /* @__PURE__ */ jsx10(
1734
+ /* @__PURE__ */ jsx11(
1457
1735
  "button",
1458
1736
  {
1459
1737
  type: "button",
@@ -1462,12 +1740,12 @@ function EnrollmentDeviceFlow({
1462
1740
  disabled: awaitingCode,
1463
1741
  title: "Copy code",
1464
1742
  className: "shrink-0 rounded-og-sm p-1.5 text-og-fg-subtle transition-colors hover:bg-og-surface-2 hover:text-og-fg disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-og-fg-subtle",
1465
- children: /* @__PURE__ */ jsx10(CopyIcon, { className: "size-4", "aria-hidden": true })
1743
+ children: /* @__PURE__ */ jsx11(CopyIcon, { className: "size-4", "aria-hidden": true })
1466
1744
  }
1467
1745
  )
1468
1746
  ] })
1469
1747
  ] }),
1470
- /* @__PURE__ */ jsxs10(
1748
+ /* @__PURE__ */ jsxs11(
1471
1749
  "a",
1472
1750
  {
1473
1751
  href,
@@ -1475,26 +1753,26 @@ function EnrollmentDeviceFlow({
1475
1753
  target: "_blank",
1476
1754
  rel: "noreferrer",
1477
1755
  onClick: onOpenVerification,
1478
- className: "inline-flex items-center justify-center gap-1.5 rounded-og-sm bg-og-accent px-3 py-2 text-og-menu font-medium text-og-accent-fg transition-colors hover:bg-og-accent-strong",
1756
+ className: "inline-flex items-center justify-center gap-1.5 rounded-og-sm border border-og-primary-border bg-og-primary text-og-primary-fg px-3 py-2 text-og-menu font-medium transition-colors hover:bg-og-primary-hover",
1479
1757
  children: [
1480
1758
  "Open approval page",
1481
- /* @__PURE__ */ jsx10(ExternalLinkIcon, { className: "size-3.5", "aria-hidden": true })
1759
+ /* @__PURE__ */ jsx11(ExternalLinkIcon, { className: "size-3.5", "aria-hidden": true })
1482
1760
  ]
1483
1761
  }
1484
1762
  ),
1485
- /* @__PURE__ */ jsx10("p", { className: "text-center text-[11px] text-og-fg-subtle", children: awaitingCode ? /* @__PURE__ */ jsxs10(Fragment2, { children: [
1763
+ /* @__PURE__ */ jsx11("p", { className: "text-center text-[11px] text-og-fg-subtle", children: awaitingCode ? /* @__PURE__ */ jsxs11(Fragment2, { children: [
1486
1764
  "The one-liner prints a short code. Open",
1487
1765
  " ",
1488
- /* @__PURE__ */ jsx10("span", { className: "font-og-mono text-og-fg-muted", children: verificationUri }),
1766
+ /* @__PURE__ */ jsx11("span", { className: "font-og-mono text-og-fg-muted", children: verificationUri }),
1489
1767
  " and confirm the code shown there matches."
1490
- ] }) : /* @__PURE__ */ jsxs10(Fragment2, { children: [
1768
+ ] }) : /* @__PURE__ */ jsxs11(Fragment2, { children: [
1491
1769
  "Confirm code ",
1492
- /* @__PURE__ */ jsx10("span", { className: "font-og-mono text-og-fg-muted", children: userCode }),
1770
+ /* @__PURE__ */ jsx11("span", { className: "font-og-mono text-og-fg-muted", children: userCode }),
1493
1771
  " \u2014 the one printed by the one-liner \u2014 at",
1494
1772
  " ",
1495
- /* @__PURE__ */ jsx10("span", { className: "font-og-mono text-og-fg-muted", children: verificationUri }),
1773
+ /* @__PURE__ */ jsx11("span", { className: "font-og-mono text-og-fg-muted", children: verificationUri }),
1496
1774
  ".",
1497
- typeof expiresInSeconds === "number" ? /* @__PURE__ */ jsxs10(Fragment2, { children: [
1775
+ typeof expiresInSeconds === "number" ? /* @__PURE__ */ jsxs11(Fragment2, { children: [
1498
1776
  " Expires in ",
1499
1777
  Math.max(0, Math.round(expiresInSeconds / 60)),
1500
1778
  " min."
@@ -1506,7 +1784,7 @@ function EnrollmentDeviceFlow({
1506
1784
  }
1507
1785
 
1508
1786
  // src/components/enrollment-consent.tsx
1509
- import { useState as useState2 } from "react";
1787
+ import { useState as useState3 } from "react";
1510
1788
  import {
1511
1789
  CircleAlertIcon,
1512
1790
  LaptopIcon as LaptopIcon6,
@@ -1516,13 +1794,13 @@ import {
1516
1794
  TerminalIcon as TerminalIcon2,
1517
1795
  UsersIcon as UsersIcon3
1518
1796
  } from "lucide-react";
1519
- import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
1797
+ import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
1520
1798
  function Capability({ icon, title, body }) {
1521
- return /* @__PURE__ */ jsxs11("li", { className: "flex items-start gap-2.5", children: [
1522
- /* @__PURE__ */ jsx11("span", { className: "mt-0.5 shrink-0 text-og-status-failed", children: icon }),
1523
- /* @__PURE__ */ jsxs11("span", { className: "min-w-0", children: [
1524
- /* @__PURE__ */ jsx11("span", { className: "block text-og-base font-medium text-og-fg", children: title }),
1525
- /* @__PURE__ */ jsx11("span", { className: "block text-og-sm text-og-fg-muted", children: body })
1799
+ return /* @__PURE__ */ jsxs12("li", { className: "flex items-start gap-2.5", children: [
1800
+ /* @__PURE__ */ jsx12("span", { className: "mt-0.5 shrink-0 text-og-status-failed", children: icon }),
1801
+ /* @__PURE__ */ jsxs12("span", { className: "min-w-0", children: [
1802
+ /* @__PURE__ */ jsx12("span", { className: "block text-og-base font-medium text-og-fg", children: title }),
1803
+ /* @__PURE__ */ jsx12("span", { className: "block text-og-sm text-og-fg-muted", children: body })
1526
1804
  ] })
1527
1805
  ] });
1528
1806
  }
@@ -1530,26 +1808,42 @@ function EnrollmentConsent({
1530
1808
  userCode,
1531
1809
  machine,
1532
1810
  phase = "review",
1811
+ allowOrganizationScope = false,
1533
1812
  onApprove,
1534
1813
  onDeny,
1535
1814
  errorMessage,
1536
1815
  className
1537
1816
  }) {
1538
- const [allowScreenControl, setAllowScreenControl] = useState2(machine.requestsScreenControl);
1817
+ const [allowScreenControl, setAllowScreenControl] = useState3(machine.requestsScreenControl);
1818
+ const [scope, setScope] = useState3("user");
1539
1819
  const busy = phase === "approving";
1820
+ const scopeCopy = {
1821
+ user: {
1822
+ label: "Personal",
1823
+ body: "Only you can use this machine, from any workspace you can access in this organization."
1824
+ },
1825
+ workspace: {
1826
+ label: "Workspace",
1827
+ body: "Everyone with access to this workspace can use this machine."
1828
+ },
1829
+ organization: {
1830
+ label: "Organization",
1831
+ body: "Members of this organization can use this machine from their workspaces."
1832
+ }
1833
+ };
1540
1834
  if (phase === "approved") {
1541
- return /* @__PURE__ */ jsx11(
1835
+ return /* @__PURE__ */ jsx12(
1542
1836
  ConsentResult,
1543
1837
  {
1544
1838
  className,
1545
1839
  tone: "ok",
1546
1840
  title: "Machine connected",
1547
- body: `${machine.machineName} is now enrolled in this workspace. You can close this page \u2014 it will appear in your Machines dashboard.`
1841
+ body: `${machine.machineName} is now connected with ${scopeCopy[scope].label.toLowerCase()} access. You can close this page \u2014 it will appear in your Machines dashboard.`
1548
1842
  }
1549
1843
  );
1550
1844
  }
1551
1845
  if (phase === "denied") {
1552
- return /* @__PURE__ */ jsx11(
1846
+ return /* @__PURE__ */ jsx12(
1553
1847
  ConsentResult,
1554
1848
  {
1555
1849
  className,
@@ -1560,7 +1854,7 @@ function EnrollmentConsent({
1560
1854
  );
1561
1855
  }
1562
1856
  if (phase === "error") {
1563
- return /* @__PURE__ */ jsx11(
1857
+ return /* @__PURE__ */ jsx12(
1564
1858
  ConsentResult,
1565
1859
  {
1566
1860
  className,
@@ -1570,7 +1864,7 @@ function EnrollmentConsent({
1570
1864
  }
1571
1865
  );
1572
1866
  }
1573
- return /* @__PURE__ */ jsxs11(
1867
+ return /* @__PURE__ */ jsxs12(
1574
1868
  "div",
1575
1869
  {
1576
1870
  "data-enrollment-consent": true,
@@ -1579,65 +1873,104 @@ function EnrollmentConsent({
1579
1873
  className
1580
1874
  ),
1581
1875
  children: [
1582
- /* @__PURE__ */ jsxs11("div", { className: "flex items-start gap-3", children: [
1583
- /* @__PURE__ */ jsx11("span", { className: "flex size-9 shrink-0 items-center justify-center rounded-full bg-og-status-failed/15 text-og-status-failed", children: /* @__PURE__ */ jsx11(ShieldAlertIcon, { className: "size-5", "aria-hidden": true }) }),
1584
- /* @__PURE__ */ jsxs11("div", { className: "min-w-0", children: [
1585
- /* @__PURE__ */ jsx11("h1", { className: "text-og-md font-semibold text-og-fg", children: "Give the agent your whole machine?" }),
1586
- /* @__PURE__ */ jsxs11("p", { className: "mt-1 text-og-base text-og-fg-muted", children: [
1587
- "Approving lets the OpenGeni agent run on",
1876
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-start gap-3", children: [
1877
+ /* @__PURE__ */ jsx12("span", { className: "flex size-9 shrink-0 items-center justify-center rounded-full bg-og-status-failed/15 text-og-status-failed", children: /* @__PURE__ */ jsx12(ShieldAlertIcon, { className: "size-5", "aria-hidden": true }) }),
1878
+ /* @__PURE__ */ jsxs12("div", { className: "min-w-0", children: [
1879
+ /* @__PURE__ */ jsx12("h1", { className: "text-og-md font-semibold text-og-fg", children: "Give the agent your whole machine?" }),
1880
+ /* @__PURE__ */ jsxs12("p", { className: "mt-1 text-og-base text-og-fg-muted", children: [
1881
+ "Approving lets the Opengeni agent run on",
1588
1882
  " ",
1589
- /* @__PURE__ */ jsx11("span", { className: "font-medium text-og-fg", children: machine.machineName }),
1883
+ /* @__PURE__ */ jsx12("span", { className: "font-medium text-og-fg", children: machine.machineName }),
1590
1884
  " with full access. This is your real computer \u2014 not a sandbox."
1591
1885
  ] })
1592
1886
  ] })
1593
1887
  ] }),
1594
- /* @__PURE__ */ jsxs11("div", { className: "flex flex-wrap items-center gap-2 rounded-og-md border border-og-border bg-og-surface-2 px-3 py-2 text-og-sm", children: [
1595
- /* @__PURE__ */ jsx11(LaptopIcon6, { className: "size-4 text-og-fg-subtle", "aria-hidden": true }),
1596
- /* @__PURE__ */ jsx11("span", { className: "font-medium text-og-fg", children: machine.machineName }),
1597
- /* @__PURE__ */ jsxs11("span", { className: "font-og-mono text-og-fg-subtle", children: [
1888
+ /* @__PURE__ */ jsxs12("div", { className: "flex flex-wrap items-center gap-2 rounded-og-md border border-og-border bg-og-surface-2 px-3 py-2 text-og-sm", children: [
1889
+ /* @__PURE__ */ jsx12(LaptopIcon6, { className: "size-4 text-og-fg-subtle", "aria-hidden": true }),
1890
+ /* @__PURE__ */ jsx12("span", { className: "font-medium text-og-fg", children: machine.machineName }),
1891
+ /* @__PURE__ */ jsxs12("span", { className: "font-og-mono text-og-fg-subtle", children: [
1598
1892
  machine.os,
1599
1893
  "/",
1600
1894
  machine.arch
1601
1895
  ] }),
1602
- /* @__PURE__ */ jsx11("span", { "aria-hidden": true, className: "text-og-fg-subtle", children: "\xB7" }),
1603
- /* @__PURE__ */ jsxs11("span", { className: "text-og-fg-subtle", children: [
1896
+ /* @__PURE__ */ jsx12("span", { "aria-hidden": true, className: "text-og-fg-subtle", children: "\xB7" }),
1897
+ /* @__PURE__ */ jsxs12("span", { className: "text-og-fg-subtle", children: [
1604
1898
  "code ",
1605
- /* @__PURE__ */ jsx11("span", { className: "font-og-mono font-medium text-og-fg", children: userCode })
1899
+ /* @__PURE__ */ jsx12("span", { className: "font-og-mono font-medium text-og-fg", children: userCode })
1606
1900
  ] })
1607
1901
  ] }),
1608
- /* @__PURE__ */ jsxs11("ul", { className: "flex flex-col gap-3", children: [
1609
- /* @__PURE__ */ jsx11(
1902
+ /* @__PURE__ */ jsxs12("ul", { className: "flex flex-col gap-3", children: [
1903
+ /* @__PURE__ */ jsx12(
1610
1904
  Capability,
1611
1905
  {
1612
- icon: /* @__PURE__ */ jsx11(TerminalIcon2, { className: "size-4", "aria-hidden": true }),
1906
+ icon: /* @__PURE__ */ jsx12(TerminalIcon2, { className: "size-4", "aria-hidden": true }),
1613
1907
  title: "Read, write & run anything",
1614
1908
  body: "The agent can read and modify any file, run any command, and use your git credentials \u2014 as if it were you at the keyboard."
1615
1909
  }
1616
1910
  ),
1617
- machine.canOfferDisplay ? /* @__PURE__ */ jsx11(
1911
+ machine.canOfferDisplay ? /* @__PURE__ */ jsx12(
1618
1912
  Capability,
1619
1913
  {
1620
- icon: /* @__PURE__ */ jsx11(MonitorIcon2, { className: "size-4", "aria-hidden": true }),
1914
+ icon: /* @__PURE__ */ jsx12(MonitorIcon2, { className: "size-4", "aria-hidden": true }),
1621
1915
  title: "See your screen",
1622
1916
  body: "The agent can capture this machine's display to watch what it is doing."
1623
1917
  }
1624
1918
  ) : null,
1625
- /* @__PURE__ */ jsx11(
1919
+ /* @__PURE__ */ jsx12(
1626
1920
  Capability,
1627
1921
  {
1628
- icon: /* @__PURE__ */ jsx11(UsersIcon3, { className: "size-4", "aria-hidden": true }),
1629
- title: "Shared while connected",
1630
- body: "Any session in this workspace can use this machine while it is online. Disconnect the agent to revoke access instantly."
1922
+ icon: /* @__PURE__ */ jsx12(UsersIcon3, { className: "size-4", "aria-hidden": true }),
1923
+ title: `${scopeCopy[scope].label} access while connected`,
1924
+ body: `${scopeCopy[scope].body} Disconnect the agent to revoke access instantly.`
1631
1925
  }
1632
1926
  )
1633
1927
  ] }),
1634
- machine.canOfferDisplay ? /* @__PURE__ */ jsxs11(
1928
+ /* @__PURE__ */ jsxs12("fieldset", { className: "flex flex-col gap-2", disabled: busy, children: [
1929
+ /* @__PURE__ */ jsx12("legend", { className: "mb-1 text-og-sm font-medium text-og-fg", children: "Who can use this machine?" }),
1930
+ ["user", "workspace", "organization"].map((candidate) => {
1931
+ const disabled = candidate === "organization" && !allowOrganizationScope;
1932
+ return /* @__PURE__ */ jsxs12(
1933
+ "label",
1934
+ {
1935
+ "data-enrollment-scope": candidate,
1936
+ "data-disabled": disabled ? "true" : "false",
1937
+ className: cn(
1938
+ "flex items-start gap-2.5 rounded-og-md border border-og-border bg-og-bg px-3 py-2.5",
1939
+ disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer"
1940
+ ),
1941
+ children: [
1942
+ /* @__PURE__ */ jsx12(
1943
+ "input",
1944
+ {
1945
+ type: "radio",
1946
+ name: "enrollment-scope",
1947
+ value: candidate,
1948
+ checked: scope === candidate,
1949
+ disabled: disabled || busy,
1950
+ onChange: () => setScope(candidate),
1951
+ className: "mt-0.5 size-4 accent-og-accent"
1952
+ }
1953
+ ),
1954
+ /* @__PURE__ */ jsxs12("span", { className: "min-w-0", children: [
1955
+ /* @__PURE__ */ jsxs12("span", { className: "block text-og-base font-medium text-og-fg", children: [
1956
+ scopeCopy[candidate].label,
1957
+ disabled ? " \xB7 organization admin required" : ""
1958
+ ] }),
1959
+ /* @__PURE__ */ jsx12("span", { className: "block text-og-sm text-og-fg-muted", children: scopeCopy[candidate].body })
1960
+ ] })
1961
+ ]
1962
+ },
1963
+ candidate
1964
+ );
1965
+ })
1966
+ ] }),
1967
+ machine.canOfferDisplay ? /* @__PURE__ */ jsxs12(
1635
1968
  "label",
1636
1969
  {
1637
1970
  "data-screen-control-toggle": true,
1638
1971
  className: "flex cursor-pointer items-start gap-3 rounded-og-md border border-og-border bg-og-bg px-3 py-2.5",
1639
1972
  children: [
1640
- /* @__PURE__ */ jsx11(
1973
+ /* @__PURE__ */ jsx12(
1641
1974
  "input",
1642
1975
  {
1643
1976
  type: "checkbox",
@@ -1647,21 +1980,21 @@ function EnrollmentConsent({
1647
1980
  className: "mt-0.5 size-4 accent-og-accent"
1648
1981
  }
1649
1982
  ),
1650
- /* @__PURE__ */ jsxs11("span", { className: "min-w-0", children: [
1651
- /* @__PURE__ */ jsxs11("span", { className: "flex items-center gap-1.5 text-og-base font-medium text-og-fg", children: [
1652
- /* @__PURE__ */ jsx11(ScreenShareIcon, { className: "size-3.5 text-og-fg-muted", "aria-hidden": true }),
1983
+ /* @__PURE__ */ jsxs12("span", { className: "min-w-0", children: [
1984
+ /* @__PURE__ */ jsxs12("span", { className: "flex items-center gap-1.5 text-og-base font-medium text-og-fg", children: [
1985
+ /* @__PURE__ */ jsx12(ScreenShareIcon, { className: "size-3.5 text-og-fg-muted", "aria-hidden": true }),
1653
1986
  "Also let the agent control my mouse & keyboard"
1654
1987
  ] }),
1655
- /* @__PURE__ */ jsx11("span", { className: "mt-0.5 block text-og-sm text-og-fg-muted", children: "Optional. Enables computer-use \u2014 the agent can move the pointer, type, and click on this machine's desktop. Leave off to let it only watch." })
1988
+ /* @__PURE__ */ jsx12("span", { className: "mt-0.5 block text-og-sm text-og-fg-muted", children: "Optional. Enables computer-use \u2014 the agent can move the pointer, type, and click on this machine's desktop. Leave off to let it only watch." })
1656
1989
  ] })
1657
1990
  ]
1658
1991
  }
1659
- ) : /* @__PURE__ */ jsxs11("p", { className: "flex items-start gap-2 rounded-og-md border border-og-border bg-og-bg px-3 py-2 text-og-sm text-og-fg-muted", children: [
1660
- /* @__PURE__ */ jsx11(CircleAlertIcon, { className: "mt-px size-3.5 shrink-0 text-og-fg-subtle", "aria-hidden": true }),
1992
+ ) : /* @__PURE__ */ jsxs12("p", { className: "flex items-start gap-2 rounded-og-md border border-og-border bg-og-bg px-3 py-2 text-og-sm text-og-fg-muted", children: [
1993
+ /* @__PURE__ */ jsx12(CircleAlertIcon, { className: "mt-px size-3.5 shrink-0 text-og-fg-subtle", "aria-hidden": true }),
1661
1994
  "This machine has no display, so screen control isn't available \u2014 files, terminal, and git only."
1662
1995
  ] }),
1663
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
1664
- /* @__PURE__ */ jsx11(
1996
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
1997
+ /* @__PURE__ */ jsx12(
1665
1998
  "button",
1666
1999
  {
1667
2000
  type: "button",
@@ -1672,13 +2005,13 @@ function EnrollmentConsent({
1672
2005
  children: "Cancel"
1673
2006
  }
1674
2007
  ),
1675
- /* @__PURE__ */ jsx11(
2008
+ /* @__PURE__ */ jsx12(
1676
2009
  "button",
1677
2010
  {
1678
2011
  type: "button",
1679
2012
  "data-approve": true,
1680
2013
  disabled: busy,
1681
- onClick: () => onApprove?.(allowScreenControl),
2014
+ onClick: () => onApprove?.(allowScreenControl, scope),
1682
2015
  className: "flex-1 rounded-og-sm bg-og-status-failed px-3 py-2 text-og-sm font-semibold text-og-accent-fg transition-colors hover:opacity-90 disabled:opacity-50 pointer-coarse:min-h-11",
1683
2016
  children: busy ? "Connecting\u2026" : "Grant full access"
1684
2017
  }
@@ -1696,7 +2029,7 @@ function ConsentResult({
1696
2029
  }) {
1697
2030
  const ring = tone === "ok" ? "border-og-status-running/30" : tone === "danger" ? "border-og-status-failed/30" : "border-og-border";
1698
2031
  const iconClass = tone === "ok" ? "text-og-status-running" : tone === "danger" ? "text-og-status-failed" : "text-og-fg-subtle";
1699
- return /* @__PURE__ */ jsxs11(
2032
+ return /* @__PURE__ */ jsxs12(
1700
2033
  "div",
1701
2034
  {
1702
2035
  "data-enrollment-result": tone,
@@ -1706,348 +2039,225 @@ function ConsentResult({
1706
2039
  className
1707
2040
  ),
1708
2041
  children: [
1709
- /* @__PURE__ */ jsx11(
2042
+ /* @__PURE__ */ jsx12(
1710
2043
  "span",
1711
2044
  {
1712
2045
  className: cn(
1713
2046
  "flex size-10 items-center justify-center rounded-full bg-og-surface-2",
1714
2047
  iconClass
1715
2048
  ),
1716
- children: /* @__PURE__ */ jsx11(LaptopIcon6, { className: "size-5", "aria-hidden": true })
2049
+ children: /* @__PURE__ */ jsx12(LaptopIcon6, { className: "size-5", "aria-hidden": true })
1717
2050
  }
1718
2051
  ),
1719
- /* @__PURE__ */ jsx11("h1", { className: "text-og-md font-semibold text-og-fg", children: title }),
1720
- /* @__PURE__ */ jsx11("p", { className: "max-w-sm text-og-base text-og-fg-muted", children: body })
2052
+ /* @__PURE__ */ jsx12("h1", { className: "text-og-md font-semibold text-og-fg", children: title }),
2053
+ /* @__PURE__ */ jsx12("p", { className: "max-w-sm text-og-base text-og-fg-muted", children: body })
1721
2054
  ]
1722
2055
  }
1723
2056
  );
1724
2057
  }
1725
2058
 
1726
2059
  // src/hooks/use-machines.ts
1727
- import { useCallback as useCallback2, useRef as useRef3, useState as useState4 } from "react";
2060
+ import { useCallback as useCallback2, useRef as useRef2, useState as useState5 } from "react";
1728
2061
 
1729
- // src/provider.tsx
1730
- import {
1731
- OpenGeniApiContractMismatchError,
1732
- OPENGENI_API_CONTRACT_REVISION
1733
- } from "@opengeni/sdk";
1734
- import { useCallback, useEffect, useMemo, useRef as useRef2, useState as useState3 } from "react";
1735
- import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
1736
- var CONTRACT_RELOAD_STORAGE_PREFIX = "opengeni.reloadForApiContract:";
1737
- function OpenGeniProvider({
1738
- client,
1739
- workspaceId,
1740
- onWorkspaceControlEvent,
1741
- onWorkspaceInteractionEvent,
1742
- children
1743
- }) {
1744
- const [workspaceControlEvent, setWorkspaceControlEvent] = useState3(
1745
- null
1746
- );
1747
- const [workspaceControlConnectionState, setWorkspaceControlConnectionState] = useState3("idle");
1748
- const [workspaceInteractionEvent, setWorkspaceInteractionEvent] = useState3(null);
1749
- const [workspaceInteractionConnectionState, setWorkspaceInteractionConnectionState] = useState3("idle");
1750
- const [contractMismatch, setContractMismatch] = useState3(
1751
- null
1752
- );
1753
- const callbackRef = useRef2(onWorkspaceControlEvent);
1754
- const interactionCallbackRef = useRef2(onWorkspaceInteractionEvent);
1755
- const reconcilersRef = useRef2(/* @__PURE__ */ new Map());
1756
- const reconcileInFlightRef = useRef2(/* @__PURE__ */ new Map());
1757
- const workspaceControlSequencesRef = useRef2(/* @__PURE__ */ new Map());
1758
- const workspaceInteractionSequencesRef = useRef2(/* @__PURE__ */ new Map());
1759
- const pageLive = usePageLiveActivity();
1760
- const supportsWorkspaceLiveStream = "streamWorkspaceLiveEvents" in client && typeof client.streamWorkspaceLiveEvents === "function";
1761
- callbackRef.current = onWorkspaceControlEvent;
1762
- interactionCallbackRef.current = onWorkspaceInteractionEvent;
1763
- const verifyApiContract = useCallback(async () => {
1764
- try {
1765
- const config = await client.getClientConfig();
1766
- if (config.apiContractRevision !== OPENGENI_API_CONTRACT_REVISION) {
1767
- throw new OpenGeniApiContractMismatchError(
1768
- OPENGENI_API_CONTRACT_REVISION,
1769
- String(config.apiContractRevision || "(missing)")
1770
- );
1771
- }
1772
- } catch (error) {
1773
- if (error instanceof OpenGeniApiContractMismatchError) {
1774
- setContractMismatch(error);
1775
- reloadForContractMismatchOnce(error);
1776
- }
1777
- throw error;
1778
- }
1779
- }, [client]);
1780
- const registerSessionReconciler = useMemo(
1781
- () => (sessionId, key, reconcile) => {
1782
- const sessionReconcilers = reconcilersRef.current.get(sessionId) ?? /* @__PURE__ */ new Map();
1783
- sessionReconcilers.set(key, reconcile);
1784
- reconcilersRef.current.set(sessionId, sessionReconcilers);
1785
- return () => {
1786
- const current = reconcilersRef.current.get(sessionId);
1787
- current?.delete(key);
1788
- if (current?.size === 0) reconcilersRef.current.delete(sessionId);
1789
- };
1790
- },
1791
- []
1792
- );
1793
- const reconcileSession = useMemo(
1794
- () => (sessionId) => {
1795
- const existing = reconcileInFlightRef.current.get(sessionId);
1796
- if (existing) return existing;
1797
- const promise = (async () => {
1798
- await withTimeout(verifyApiContract(), 1e4, "API contract reconciliation");
1799
- const callbacks = [...reconcilersRef.current.get(sessionId)?.values() ?? []];
1800
- await withTimeout(
1801
- Promise.all(callbacks.map((reconcile) => reconcile())).then(() => void 0),
1802
- 15e3,
1803
- "session reconciliation"
1804
- );
1805
- })().finally(() => {
1806
- if (reconcileInFlightRef.current.get(sessionId) === promise) {
1807
- reconcileInFlightRef.current.delete(sessionId);
1808
- }
1809
- });
1810
- reconcileInFlightRef.current.set(sessionId, promise);
1811
- return promise;
1812
- },
1813
- [verifyApiContract]
1814
- );
1815
- useEffect(() => {
1816
- if (!supportsWorkspaceLiveStream) return;
1817
- const openLiveStream = client.streamWorkspaceLiveEvents;
1818
- setWorkspaceControlEvent(null);
1819
- setWorkspaceInteractionEvent(null);
1820
- if (!pageLive) {
1821
- setWorkspaceControlConnectionState("idle");
1822
- setWorkspaceInteractionConnectionState("idle");
1823
- return;
2062
+ // src/hooks/shared-machines-list.ts
2063
+ import { useCallback, useEffect as useEffect2, useState as useState4 } from "react";
2064
+ var EMPTY_MACHINES = {
2065
+ activeSandboxId: null,
2066
+ activeEpoch: 0,
2067
+ machines: []
2068
+ };
2069
+ var shares = /* @__PURE__ */ new Map();
2070
+ function emit(share) {
2071
+ for (const subscriber of share.subscribers) {
2072
+ subscriber.onChange();
2073
+ }
2074
+ }
2075
+ function effective(share) {
2076
+ let enabled = false;
2077
+ let pollIntervalMs;
2078
+ for (const subscriber of share.subscribers) {
2079
+ if (!subscriber.enabled || !subscriber.pageLive) continue;
2080
+ enabled = true;
2081
+ if (subscriber.pollIntervalMs !== void 0 && subscriber.pollIntervalMs > 0) {
2082
+ pollIntervalMs = pollIntervalMs === void 0 ? subscriber.pollIntervalMs : Math.min(pollIntervalMs, subscriber.pollIntervalMs);
1824
2083
  }
1825
- const controller = new AbortController();
1826
- const setConnectionState = (state) => {
1827
- setWorkspaceControlConnectionState(state);
1828
- setWorkspaceInteractionConnectionState(state);
2084
+ }
2085
+ return { enabled, pollIntervalMs };
2086
+ }
2087
+ function latestLoad(share) {
2088
+ let load = null;
2089
+ for (const subscriber of share.subscribers) {
2090
+ if (subscriber.enabled && subscriber.pageLive) load = subscriber.load;
2091
+ }
2092
+ return load;
2093
+ }
2094
+ function stopTimer(share) {
2095
+ if (share.timer !== null) {
2096
+ clearTimeout(share.timer);
2097
+ share.timer = null;
2098
+ }
2099
+ }
2100
+ function cancelDispose(share) {
2101
+ if (share.disposeTimer !== null) {
2102
+ clearTimeout(share.disposeTimer);
2103
+ share.disposeTimer = null;
2104
+ }
2105
+ }
2106
+ function arm(share) {
2107
+ stopTimer(share);
2108
+ const { enabled, pollIntervalMs } = effective(share);
2109
+ if (!enabled || pollIntervalMs === void 0) return;
2110
+ share.timer = setTimeout(() => {
2111
+ share.timer = null;
2112
+ void run(share).finally(() => arm(share));
2113
+ }, pollIntervalMs);
2114
+ }
2115
+ async function runFresh(share) {
2116
+ const load = latestLoad(share);
2117
+ if (!load) return;
2118
+ const ticket = ++share.generation;
2119
+ const abort = new AbortController();
2120
+ share.abort = abort;
2121
+ try {
2122
+ const data = await load(abort.signal);
2123
+ if (ticket !== share.generation || abort.signal.aborted) return;
2124
+ share.snapshot = { data, loading: false, error: null };
2125
+ emit(share);
2126
+ } catch (cause) {
2127
+ if (ticket !== share.generation || abort.signal.aborted) return;
2128
+ share.snapshot = {
2129
+ data: share.snapshot.data,
2130
+ loading: false,
2131
+ error: cause instanceof Error ? cause : new Error(String(cause))
1829
2132
  };
1830
- setConnectionState("connecting");
1831
- void (async () => {
1832
- try {
1833
- await verifyApiContract();
1834
- const workspace = await client.getWorkspace(workspaceId);
1835
- const controlAfter = Math.max(
1836
- workspaceControlSequencesRef.current.get(workspaceId) ?? 0,
1837
- workspace.inferenceControl.revision
1838
- );
1839
- const interactionAfter = workspaceInteractionSequencesRef.current.get(workspaceId) ?? 0;
1840
- workspaceControlSequencesRef.current.set(workspaceId, controlAfter);
1841
- const stream = openLiveStream.call(client, workspaceId, {
1842
- controlAfter,
1843
- interactionAfter,
1844
- signal: controller.signal,
1845
- onStateChange: setConnectionState
1846
- });
1847
- for await (const event of stream) {
1848
- if (controller.signal.aborted) return;
1849
- if (event.type === "workspace.control.changed") {
1850
- workspaceControlSequencesRef.current.set(
1851
- workspaceId,
1852
- Math.max(workspaceControlSequencesRef.current.get(workspaceId) ?? 0, event.sequence)
1853
- );
1854
- setWorkspaceControlEvent(
1855
- (current) => !current || event.sequence > current.sequence ? event : current
1856
- );
1857
- callbackRef.current?.(event);
1858
- } else {
1859
- workspaceInteractionSequencesRef.current.set(
1860
- workspaceId,
1861
- Math.max(
1862
- workspaceInteractionSequencesRef.current.get(workspaceId) ?? 0,
1863
- event.sequence
1864
- )
1865
- );
1866
- setWorkspaceInteractionEvent(
1867
- (current) => !current || event.sequence > current.sequence ? event : current
1868
- );
1869
- interactionCallbackRef.current?.(event);
1870
- }
1871
- }
1872
- } catch (error) {
1873
- if (error instanceof OpenGeniApiContractMismatchError) {
1874
- setContractMismatch(error);
1875
- reloadForContractMismatchOnce(error);
1876
- }
1877
- if (!controller.signal.aborted) {
1878
- setWorkspaceControlConnectionState("error");
1879
- setWorkspaceInteractionConnectionState("error");
1880
- }
1881
- }
1882
- })();
1883
- return () => controller.abort();
1884
- }, [client, pageLive, supportsWorkspaceLiveStream, verifyApiContract, workspaceId]);
1885
- useEffect(() => {
1886
- if (supportsWorkspaceLiveStream) return;
1887
- if (!pageLive) {
1888
- setWorkspaceControlConnectionState("idle");
1889
- return;
1890
- }
1891
- const controller = new AbortController();
1892
- setWorkspaceControlConnectionState("connecting");
1893
- void (async () => {
1894
- try {
1895
- await verifyApiContract();
1896
- const workspace = await client.getWorkspace(workspaceId);
1897
- const resumeAfter = Math.max(
1898
- workspaceControlSequencesRef.current.get(workspaceId) ?? 0,
1899
- workspace.inferenceControl.revision
1900
- );
1901
- workspaceControlSequencesRef.current.set(workspaceId, resumeAfter);
1902
- const stream = client.streamWorkspaceControlEvents(workspaceId, {
1903
- after: resumeAfter,
1904
- signal: controller.signal,
1905
- onStateChange: setWorkspaceControlConnectionState
1906
- });
1907
- for await (const event of stream) {
1908
- if (controller.signal.aborted) return;
1909
- workspaceControlSequencesRef.current.set(
1910
- workspaceId,
1911
- Math.max(workspaceControlSequencesRef.current.get(workspaceId) ?? 0, event.sequence)
1912
- );
1913
- setWorkspaceControlEvent(
1914
- (current) => !current || event.sequence > current.sequence ? event : current
1915
- );
1916
- callbackRef.current?.(event);
1917
- }
1918
- } catch (error) {
1919
- if (error instanceof OpenGeniApiContractMismatchError) {
1920
- setContractMismatch(error);
1921
- reloadForContractMismatchOnce(error);
1922
- }
1923
- if (!controller.signal.aborted) setWorkspaceControlConnectionState("error");
1924
- }
1925
- })();
1926
- return () => controller.abort();
1927
- }, [client, pageLive, supportsWorkspaceLiveStream, verifyApiContract, workspaceId]);
1928
- useEffect(() => {
1929
- if (supportsWorkspaceLiveStream) return;
1930
- setWorkspaceInteractionEvent(null);
1931
- if (!pageLive) {
1932
- setWorkspaceInteractionConnectionState("idle");
1933
- return;
1934
- }
1935
- const controller = new AbortController();
1936
- setWorkspaceInteractionConnectionState("connecting");
1937
- void (async () => {
1938
- try {
1939
- await verifyApiContract();
1940
- const resumeAfter = workspaceInteractionSequencesRef.current.get(workspaceId) ?? 0;
1941
- const stream = client.streamWorkspaceInteractionRevisions(workspaceId, {
1942
- after: resumeAfter,
1943
- signal: controller.signal,
1944
- onStateChange: setWorkspaceInteractionConnectionState
1945
- });
1946
- for await (const event of stream) {
1947
- if (controller.signal.aborted) return;
1948
- workspaceInteractionSequencesRef.current.set(
1949
- workspaceId,
1950
- Math.max(
1951
- workspaceInteractionSequencesRef.current.get(workspaceId) ?? 0,
1952
- event.sequence
1953
- )
1954
- );
1955
- setWorkspaceInteractionEvent(
1956
- (current) => !current || event.sequence > current.sequence ? event : current
1957
- );
1958
- interactionCallbackRef.current?.(event);
1959
- }
1960
- } catch (error) {
1961
- if (error instanceof OpenGeniApiContractMismatchError) {
1962
- setContractMismatch(error);
1963
- reloadForContractMismatchOnce(error);
1964
- }
1965
- if (!controller.signal.aborted) setWorkspaceInteractionConnectionState("error");
1966
- }
1967
- })();
1968
- return () => controller.abort();
1969
- }, [client, pageLive, supportsWorkspaceLiveStream, verifyApiContract, workspaceId]);
1970
- const value = useMemo(
1971
- () => ({
1972
- client,
1973
- workspaceId,
1974
- workspaceControlEvent,
1975
- workspaceControlConnectionState,
1976
- workspaceInteractionEvent,
1977
- workspaceInteractionConnectionState,
1978
- registerSessionReconciler,
1979
- reconcileSession
1980
- }),
1981
- [
1982
- client,
1983
- workspaceId,
1984
- workspaceControlEvent,
1985
- workspaceControlConnectionState,
1986
- workspaceInteractionEvent,
1987
- workspaceInteractionConnectionState,
1988
- registerSessionReconciler,
1989
- reconcileSession
1990
- ]
1991
- );
1992
- return /* @__PURE__ */ jsxs12(OpenGeniContext.Provider, { value, children: [
1993
- children,
1994
- contractMismatch ? /* @__PURE__ */ jsx12(ApiContractMismatchScreen, { mismatch: contractMismatch }) : null
1995
- ] });
2133
+ emit(share);
2134
+ } finally {
2135
+ if (share.abort === abort) share.abort = null;
2136
+ }
1996
2137
  }
1997
- function withTimeout(promise, timeoutMs, label) {
1998
- let timer;
1999
- return Promise.race([
2000
- promise,
2001
- new Promise((_resolve, reject) => {
2002
- timer = setTimeout(
2003
- () => reject(new Error(`${label} timed out after ${timeoutMs}ms`)),
2004
- timeoutMs
2005
- );
2006
- })
2007
- ]).finally(() => {
2008
- if (timer !== void 0) clearTimeout(timer);
2138
+ function run(share, force = false) {
2139
+ if (!force && share.inFlight) return share.inFlight;
2140
+ if (force && share.inFlight) {
2141
+ if (share.trailing) return share.trailing;
2142
+ let trailing;
2143
+ trailing = share.inFlight.then(async () => {
2144
+ if (!effective(share).enabled) return;
2145
+ await run(share);
2146
+ }).finally(() => {
2147
+ if (share.trailing === trailing) share.trailing = null;
2148
+ });
2149
+ share.trailing = trailing;
2150
+ return trailing;
2151
+ }
2152
+ let promise;
2153
+ promise = runFresh(share).finally(() => {
2154
+ if (share.inFlight === promise) share.inFlight = null;
2009
2155
  });
2156
+ share.inFlight = promise;
2157
+ return promise;
2010
2158
  }
2011
- function ApiContractMismatchScreen({ mismatch }) {
2012
- return /* @__PURE__ */ jsx12(
2013
- "div",
2014
- {
2015
- className: "og-root fixed inset-0 z-[2147483647] grid place-items-center bg-og-bg/95 p-6 backdrop-blur-sm",
2016
- role: "alert",
2017
- "aria-live": "assertive",
2018
- "data-opengeni-api-contract-mismatch": true,
2019
- children: /* @__PURE__ */ jsxs12("div", { className: "w-full max-w-md rounded-xl border border-og-border bg-og-surface p-6 shadow-2xl", children: [
2020
- /* @__PURE__ */ jsx12("p", { className: "text-og-menu font-semibold text-og-fg", children: "OpenGeni updated" }),
2021
- /* @__PURE__ */ jsx12("p", { className: "mt-2 text-og-menu leading-6 text-og-muted", children: "This tab cannot safely continue with the new server version. Reload it before sending or controlling work." }),
2022
- /* @__PURE__ */ jsxs12("p", { className: "mt-3 font-mono text-og-control text-og-subtle", children: [
2023
- "Client ",
2024
- mismatch.expected,
2025
- " \xB7 API ",
2026
- mismatch.actual
2027
- ] }),
2028
- /* @__PURE__ */ jsx12(
2029
- "button",
2030
- {
2031
- type: "button",
2032
- className: "mt-5 inline-flex h-9 items-center rounded-md bg-og-fg px-3 text-og-menu font-medium text-og-bg",
2033
- onClick: () => window.location.reload(),
2034
- children: "Reload now"
2035
- }
2036
- )
2037
- ] })
2159
+ function reconcile(share) {
2160
+ const { enabled } = effective(share);
2161
+ if (!enabled) {
2162
+ share.generation += 1;
2163
+ share.abort?.abort();
2164
+ share.abort = null;
2165
+ share.inFlight = null;
2166
+ stopTimer(share);
2167
+ if (share.snapshot.loading) {
2168
+ share.snapshot = { ...share.snapshot, loading: false };
2169
+ emit(share);
2038
2170
  }
2039
- );
2171
+ return;
2172
+ }
2173
+ if (share.snapshot.data !== null || share.snapshot.error) {
2174
+ arm(share);
2175
+ return;
2176
+ }
2177
+ share.snapshot = { ...share.snapshot, loading: true };
2178
+ emit(share);
2179
+ void run(share).finally(() => arm(share));
2180
+ }
2181
+ function getOrCreate(shareKey) {
2182
+ const existing = shares.get(shareKey);
2183
+ if (existing) {
2184
+ cancelDispose(existing);
2185
+ return existing;
2186
+ }
2187
+ const created = {
2188
+ snapshot: { data: null, loading: true, error: null },
2189
+ subscribers: /* @__PURE__ */ new Set(),
2190
+ timer: null,
2191
+ disposeTimer: null,
2192
+ abort: null,
2193
+ inFlight: null,
2194
+ trailing: null,
2195
+ generation: 0
2196
+ };
2197
+ shares.set(shareKey, created);
2198
+ return created;
2040
2199
  }
2041
- function reloadForContractMismatchOnce(mismatch) {
2042
- if (typeof window === "undefined" || typeof sessionStorage === "undefined") return;
2043
- const key = `${CONTRACT_RELOAD_STORAGE_PREFIX}${mismatch.actual}`;
2044
- if (sessionStorage.getItem(key) === OPENGENI_API_CONTRACT_REVISION) return;
2045
- sessionStorage.setItem(key, OPENGENI_API_CONTRACT_REVISION);
2046
- window.setTimeout(() => window.location.reload(), 150);
2200
+ async function refreshSharedMachinesList(shareKey) {
2201
+ const share = shares.get(shareKey);
2202
+ if (!share) return;
2203
+ await run(share, true);
2204
+ }
2205
+ function useSharedMachinesList(shareKey, load, options = {}) {
2206
+ const enabled = options.enabled ?? true;
2207
+ const pageLive = usePageLiveActivity();
2208
+ const [, setRevision] = useState4(0);
2209
+ const live = shares.get(shareKey)?.snapshot;
2210
+ const view = live ?? { data: null, loading: enabled && pageLive, error: null };
2211
+ useEffect2(() => {
2212
+ const share = getOrCreate(shareKey);
2213
+ const subscriber = {
2214
+ load,
2215
+ pollIntervalMs: options.pollIntervalMs,
2216
+ enabled,
2217
+ pageLive,
2218
+ onChange: () => setRevision((revision) => revision + 1)
2219
+ };
2220
+ share.subscribers.add(subscriber);
2221
+ setRevision((revision) => revision + 1);
2222
+ reconcile(share);
2223
+ return () => {
2224
+ share.subscribers.delete(subscriber);
2225
+ if (share.subscribers.size > 0) {
2226
+ reconcile(share);
2227
+ return;
2228
+ }
2229
+ share.generation += 1;
2230
+ share.abort?.abort();
2231
+ share.abort = null;
2232
+ share.inFlight = null;
2233
+ share.trailing = null;
2234
+ stopTimer(share);
2235
+ cancelDispose(share);
2236
+ share.disposeTimer = setTimeout(() => {
2237
+ share.disposeTimer = null;
2238
+ if (share.subscribers.size === 0 && shares.get(shareKey) === share) {
2239
+ shares.delete(shareKey);
2240
+ }
2241
+ }, 0);
2242
+ };
2243
+ }, [shareKey, load, options.pollIntervalMs, enabled, pageLive]);
2244
+ const refresh = useCallback(() => refreshSharedMachinesList(shareKey), [shareKey]);
2245
+ return { ...view, refresh };
2047
2246
  }
2048
2247
 
2049
2248
  // src/hooks/use-machines.ts
2050
- var EMPTY = { activeSandboxId: null, activeEpoch: 0, machines: [] };
2249
+ var MACHINES_DASHBOARD_POLL_MS = 1e4;
2250
+ var MACHINES_SESSION_POLL_MS = 15e3;
2251
+ var MACHINES_COMPOSER_POLL_MS = 3e4;
2252
+ var machinesClientIds = /* @__PURE__ */ new WeakMap();
2253
+ var nextMachinesClientId = 1;
2254
+ function machinesClientId(client) {
2255
+ const existing = machinesClientIds.get(client);
2256
+ if (existing !== void 0) return existing;
2257
+ const id = nextMachinesClientId++;
2258
+ machinesClientIds.set(client, id);
2259
+ return id;
2260
+ }
2051
2261
  function swapFailureMessage(result) {
2052
2262
  if (result.reason?.trim()) return result.reason;
2053
2263
  switch (result.code) {
@@ -2069,8 +2279,8 @@ function useMachines(options = {}) {
2069
2279
  const { client, workspaceId } = useOpenGeni(options);
2070
2280
  const machinesClient = options.machinesClient ?? client;
2071
2281
  const sessionId = options.sessionId;
2072
- const identityKey = `${workspaceId}\0${sessionId ?? ""}`;
2073
- const identityRef = useRef3(identityKey);
2282
+ const identityKey = `${workspaceId}\0${sessionId ?? ""}\0${machinesClientId(machinesClient)}`;
2283
+ const identityRef = useRef2(identityKey);
2074
2284
  identityRef.current = identityKey;
2075
2285
  const load = useCallback2(
2076
2286
  async (signal) => {
@@ -2086,18 +2296,24 @@ function useMachines(options = {}) {
2086
2296
  loading,
2087
2297
  error,
2088
2298
  refresh
2089
- } = usePolledValue(load, {
2299
+ } = useSharedMachinesList(identityKey, load, {
2090
2300
  pollIntervalMs: options.pollIntervalMs,
2091
2301
  enabled: options.enabled
2092
2302
  });
2093
- const { run, mutating, mutationError, clearMutationError } = useMutationRunner(identityKey);
2094
- const [attachState, setAttachState] = useState4(() => ({ identity: identityKey, sandboxId: null }));
2303
+ const { run: run2, mutating, mutationError, clearMutationError } = useMutationRunner(identityKey);
2304
+ const [attachState, setAttachState] = useState5(() => ({ identity: identityKey, sandboxId: null }));
2095
2305
  const attachingSandboxId = attachState.identity === identityKey ? attachState.sandboxId : null;
2096
- const [removeState, setRemoveState] = useState4(() => ({ identity: identityKey, enrollmentId: null }));
2306
+ const [removeState, setRemoveState] = useState5(() => ({ identity: identityKey, enrollmentId: null }));
2097
2307
  const removingEnrollmentId = removeState.identity === identityKey ? removeState.enrollmentId : null;
2098
- const data = loadedData ?? EMPTY;
2308
+ const [updateState, setUpdateState] = useState5(() => ({ identity: identityKey, enrollmentId: null }));
2309
+ const updatingEnrollmentId = updateState.identity === identityKey ? updateState.enrollmentId : null;
2310
+ const [operationPolicyState, setOperationPolicyState] = useState5(() => ({ identity: identityKey, enrollmentId: null }));
2311
+ const updatingOperationPolicyEnrollmentId = operationPolicyState.identity === identityKey ? operationPolicyState.enrollmentId : null;
2312
+ const data = loadedData ?? EMPTY_MACHINES;
2099
2313
  const canAttach = sessionId !== void 0 && (typeof machinesClient.attachMachine === "function" || typeof machinesClient.swapActiveSandbox === "function");
2100
2314
  const canRemove = typeof machinesClient.removeEnrollment === "function";
2315
+ const canUpdateAgent = typeof machinesClient.updateMachineAgent === "function";
2316
+ const canUpdateOperationPolicy = typeof machinesClient.updateMachineOperationPolicy === "function";
2101
2317
  const attach = useCallback2(
2102
2318
  async (sandboxId) => {
2103
2319
  if (sessionId === void 0) return false;
@@ -2105,7 +2321,7 @@ function useMachines(options = {}) {
2105
2321
  if (!runSwap) return false;
2106
2322
  const ownedIdentity = identityKey;
2107
2323
  setAttachState({ identity: ownedIdentity, sandboxId });
2108
- const result = await run(async () => {
2324
+ const result = await run2(async () => {
2109
2325
  const response = await runSwap();
2110
2326
  if (response && typeof response === "object" && "swapped" in response && response.swapped === false) {
2111
2327
  throw new Error(swapFailureMessage(response));
@@ -2118,12 +2334,12 @@ function useMachines(options = {}) {
2118
2334
  }
2119
2335
  return result === true;
2120
2336
  },
2121
- [machinesClient, workspaceId, sessionId, identityKey, run, refresh]
2337
+ [machinesClient, workspaceId, sessionId, identityKey, run2, refresh]
2122
2338
  );
2123
2339
  const fetchSeries = useCallback2(
2124
- async (enrollmentId, window2 = "1h") => {
2340
+ async (enrollmentId, window = "1h") => {
2125
2341
  if (!machinesClient.machineMetricsSeries) return [];
2126
- return await machinesClient.machineMetricsSeries(workspaceId, enrollmentId, { window: window2 });
2342
+ return await machinesClient.machineMetricsSeries(workspaceId, enrollmentId, { window });
2127
2343
  },
2128
2344
  [machinesClient, workspaceId]
2129
2345
  );
@@ -2132,7 +2348,7 @@ function useMachines(options = {}) {
2132
2348
  if (!machinesClient.removeEnrollment) return null;
2133
2349
  const ownedIdentity = identityKey;
2134
2350
  setRemoveState({ identity: ownedIdentity, enrollmentId });
2135
- const result = await run(
2351
+ const result = await run2(
2136
2352
  () => machinesClient.removeEnrollment(workspaceId, enrollmentId, request)
2137
2353
  );
2138
2354
  if (identityRef.current === ownedIdentity) {
@@ -2143,7 +2359,37 @@ function useMachines(options = {}) {
2143
2359
  }
2144
2360
  return result;
2145
2361
  },
2146
- [machinesClient, workspaceId, identityKey, run, refresh]
2362
+ [machinesClient, workspaceId, identityKey, run2, refresh]
2363
+ );
2364
+ const updateAgent = useCallback2(
2365
+ async (enrollmentId) => {
2366
+ if (!machinesClient.updateMachineAgent) return null;
2367
+ const ownedIdentity = identityKey;
2368
+ setUpdateState({ identity: ownedIdentity, enrollmentId });
2369
+ const result = await run2(() => machinesClient.updateMachineAgent(workspaceId, enrollmentId));
2370
+ if (identityRef.current === ownedIdentity) {
2371
+ setUpdateState({ identity: ownedIdentity, enrollmentId: null });
2372
+ await refresh();
2373
+ }
2374
+ return result;
2375
+ },
2376
+ [machinesClient, workspaceId, identityKey, run2, refresh]
2377
+ );
2378
+ const updateOperationPolicy = useCallback2(
2379
+ async (enrollmentId, request) => {
2380
+ if (!machinesClient.updateMachineOperationPolicy) return null;
2381
+ const ownedIdentity = identityKey;
2382
+ setOperationPolicyState({ identity: ownedIdentity, enrollmentId });
2383
+ const result = await run2(
2384
+ () => machinesClient.updateMachineOperationPolicy(workspaceId, enrollmentId, request)
2385
+ );
2386
+ if (identityRef.current === ownedIdentity) {
2387
+ setOperationPolicyState({ identity: ownedIdentity, enrollmentId: null });
2388
+ if (result) await refresh();
2389
+ }
2390
+ return result;
2391
+ },
2392
+ [machinesClient, workspaceId, identityKey, run2, refresh]
2147
2393
  );
2148
2394
  return {
2149
2395
  machines: data.machines,
@@ -2160,14 +2406,22 @@ function useMachines(options = {}) {
2160
2406
  remove,
2161
2407
  canRemove,
2162
2408
  removingEnrollmentId,
2409
+ updateAgent,
2410
+ canUpdateAgent,
2411
+ updatingEnrollmentId,
2412
+ updateOperationPolicy,
2413
+ canUpdateOperationPolicy,
2414
+ updatingOperationPolicyEnrollmentId,
2163
2415
  mutationError,
2164
2416
  clearMutationError
2165
2417
  };
2166
2418
  }
2167
2419
 
2168
2420
  export {
2169
- OpenGeniProvider,
2170
2421
  connectionStatusForState,
2422
+ MACHINES_DASHBOARD_POLL_MS,
2423
+ MACHINES_SESSION_POLL_MS,
2424
+ MACHINES_COMPOSER_POLL_MS,
2171
2425
  useMachines,
2172
2426
  CONNECTION_STATUS_META,
2173
2427
  MACHINE_STATE_BADGE_META,
@@ -2186,6 +2440,7 @@ export {
2186
2440
  WINDOW_LABEL,
2187
2441
  METRICS,
2188
2442
  pointsFor,
2443
+ MachineOperationPolicyEditor,
2189
2444
  MachineDetail,
2190
2445
  MachinesDashboard,
2191
2446
  MachineDockBar,
@@ -2193,4 +2448,4 @@ export {
2193
2448
  EnrollmentDeviceFlow,
2194
2449
  EnrollmentConsent
2195
2450
  };
2196
- //# sourceMappingURL=chunk-HA46CYQK.js.map
2451
+ //# sourceMappingURL=chunk-EESD3PY3.js.map