@opengeni/react 4.6.1 → 4.6.2-canary.39854174564001

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 (465) hide show
  1. package/dist/app/app-state.js +5 -5
  2. package/dist/app/components/Composer.js +14 -14
  3. package/dist/app/components/artifacts/artifact-library.js +2 -2
  4. package/dist/app/components/artifacts/chat-interactive-block.js +10 -10
  5. package/dist/app/components/artifacts/inline-chat-image.js +14 -14
  6. package/dist/app/components/artifacts/retained-file-preview.js +15 -15
  7. package/dist/app/components/artifacts/retained-text-preview.js +2 -2
  8. package/dist/app/components/artifacts/site-conversations.js +4 -3
  9. package/dist/app/components/artifacts/site-data.js +2 -2
  10. package/dist/app/components/artifacts/site-publishing.js +11 -11
  11. package/dist/app/components/artifacts/site-settings.js +12 -12
  12. package/dist/app/components/billing-class-mark.js +3 -3
  13. package/dist/app/components/capabilities/capability-detail-sheet.js +2 -2
  14. package/dist/app/components/capabilities/capability-logo-source.js +7 -7
  15. package/dist/app/components/capabilities/native-connect-readiness.js +1 -0
  16. package/dist/app/components/capabilities/native-connect-readiness.js.map +1 -1
  17. package/dist/app/components/capabilities/native-connect-setup.js +6 -6
  18. package/dist/app/components/capabilities/perform-capability-action.js +2 -1
  19. package/dist/app/components/capabilities/prepared-mcp-setup-card.js +8 -8
  20. package/dist/app/components/capabilities/session-capability-card.js +28 -27
  21. package/dist/app/components/capabilities/session-capability-card.js.map +1 -1
  22. package/dist/app/components/capabilities/session-chrome-card.js +14 -14
  23. package/dist/app/components/capabilities/session-custom-mcp-card.js +9 -9
  24. package/dist/app/components/capabilities/session-github-card.js +9 -9
  25. package/dist/app/components/capabilities/session-machine-card.js +13 -13
  26. package/dist/app/components/command-menu/chat-status.js +6 -5
  27. package/dist/app/components/command-menu/chat-switcher.d.ts +2 -0
  28. package/dist/app/components/command-menu/chat-switcher.js +26 -9
  29. package/dist/app/components/command-menu/chat-switcher.js.map +1 -1
  30. package/dist/app/components/command-menu/command-menu.js +9 -8
  31. package/dist/app/components/command-menu/command-menu.js.map +1 -1
  32. package/dist/app/components/command-menu/shortcut-sheet.js +4 -4
  33. package/dist/app/components/composer-mobile-plus-panel.js +5 -5
  34. package/dist/app/components/composer-mobile-plus.js +1 -1
  35. package/dist/app/components/credit-required-gate.js +1 -1
  36. package/dist/app/components/credit-required-prompt.js +3 -3
  37. package/dist/app/components/desktop/app-shots.js +5 -5
  38. package/dist/app/components/desktop/this-computer.js +4 -4
  39. package/dist/app/components/feedback.js +3 -3
  40. package/dist/app/components/github-app-connect-launcher.js +1 -1
  41. package/dist/app/components/machines/connect-machine-dialog.js +3 -3
  42. package/dist/app/components/markdown.js +4 -4
  43. package/dist/app/components/models/models-ui.js +2 -2
  44. package/dist/app/components/pickers.js +5 -5
  45. package/dist/app/components/rail/rail-context.js +1 -1
  46. package/dist/app/components/rail/rail-sections.js +15 -14
  47. package/dist/app/components/rail/session-header.d.ts +6 -5
  48. package/dist/app/components/rail/session-header.js +11 -10
  49. package/dist/app/components/rail/session-list.js +14 -13
  50. package/dist/app/components/rail/session-row-hover-details.js +7 -6
  51. package/dist/app/components/rail/session-shell.js +30 -32
  52. package/dist/app/components/rail/site-session-group-heading.js +2 -1
  53. package/dist/app/components/session/agent-configuration-panel.js +3 -3
  54. package/dist/app/components/session/banners.js +6 -6
  55. package/dist/app/components/session/editable-artifacts-workspace.js +12 -12
  56. package/dist/app/components/session/failed-session-banner.js +4 -4
  57. package/dist/app/components/session/human-input.js +24 -24
  58. package/dist/app/components/session/inspector.js +30 -30
  59. package/dist/app/components/session/message-actions.js +3 -3
  60. package/dist/app/components/session/message-resource-attachments.js +5 -5
  61. package/dist/app/components/session/model-recovery-notice.js +3 -3
  62. package/dist/app/components/session/new-session-settings-menu.js +4 -4
  63. package/dist/app/components/session/sandbox-switcher.js +7 -7
  64. package/dist/app/components/session/sandbox-workspace.js +33 -33
  65. package/dist/app/components/session/search-markdown-highlight.js +5 -5
  66. package/dist/app/components/session/search-results-view.js +6 -6
  67. package/dist/app/components/session/session-admission-notice.js +4 -4
  68. package/dist/app/components/session/session-machine-access-notice.js +4 -4
  69. package/dist/app/components/session/session-search-dialog.js +6 -6
  70. package/dist/app/components/session/session-usage-limit-section.js +3 -3
  71. package/dist/app/components/session/session-wait-status.js +2 -1
  72. package/dist/app/components/session/session-wait-status.js.map +1 -1
  73. package/dist/app/components/session/subagents.js +5 -4
  74. package/dist/app/components/session/subscription-account-indicator.d.ts +35 -0
  75. package/dist/app/components/session/{codex-account-indicator.js → subscription-account-indicator.js} +23 -10
  76. package/dist/app/components/session/subscription-account-menu.d.ts +11 -12
  77. package/dist/app/components/session/subscription-account-menu.js +1 -1
  78. package/dist/app/components/session/subscription-account.d.ts +105 -0
  79. package/dist/app/components/usage/usage-entry.js +3 -3
  80. package/dist/app/components/workspace-composer-plus.js +10 -10
  81. package/dist/app/embed/session-app.js +92 -94
  82. package/dist/app/lib/actions/actions-provider.js +4 -4
  83. package/dist/app/lib/actions/chat-switcher.d.ts +19 -7
  84. package/dist/app/lib/codex-usage-query.js +2 -2
  85. package/dist/app/lib/composer-connectors.js +8 -8
  86. package/dist/app/lib/console-text.js +2 -2
  87. package/dist/app/lib/drive-connect-return.d.ts +26 -0
  88. package/dist/app/lib/drive-connect-return.js +16 -0
  89. package/dist/app/lib/events.js +7 -7
  90. package/dist/app/lib/failed-session-copy.js +3 -3
  91. package/dist/app/lib/model-access-onboarding.js +3 -3
  92. package/dist/app/lib/move-chat-to-machine.js +3 -3
  93. package/dist/app/lib/session-branch-cache.js +6 -5
  94. package/dist/app/lib/session-group-pagination.js +6 -5
  95. package/dist/app/lib/session-hover-facts.js +6 -5
  96. package/dist/app/lib/session-rail.js +2 -1
  97. package/dist/app/lib/sessions-group.js +5 -4
  98. package/dist/app/lib/turn-failure-analytics.js +4 -4
  99. package/dist/app/lib/use-workspace-machines.js +4 -4
  100. package/dist/app/lib/use-workspace-model-catalog.js +3 -3
  101. package/dist/app/lib/use-workspace-rigs.js +2 -2
  102. package/dist/app/lib/workspace-navigation-preference.js +4 -4
  103. package/dist/app/lib/workspace-scope-context.js +3 -3
  104. package/dist/app/routes/artifacts.js +26 -25
  105. package/dist/app/routes/artifacts.js.map +1 -1
  106. package/dist/app/routes/retained-artifact.js +15 -15
  107. package/dist/app/routes/session.js +64 -63
  108. package/dist/app/routes/sessions-index.js +41 -41
  109. package/dist/app/routes/site-view.js +30 -29
  110. package/dist/app/routes/site-view.js.map +1 -1
  111. package/dist/artifacts-document.js +4 -4
  112. package/dist/artifacts-presentation.js +4 -4
  113. package/dist/artifacts-spreadsheet.js +4 -4
  114. package/dist/artifacts.js +10 -10
  115. package/dist/{browser-viewer-YQC6BFMS.js → browser-viewer-VKIAULG7.js} +4 -4
  116. package/dist/{chat-interactive-block-Z22YHDRU.js → chat-interactive-block-JGYSW4KB.js} +5 -5
  117. package/dist/{chunk-WN2MIB4Q.js → chunk-22V2QCEM.js} +2 -2
  118. package/dist/{chunk-SJPAKWWP.js → chunk-2BISI664.js} +2 -2
  119. package/dist/{chunk-O5UOCMH4.js → chunk-2LPJVEWY.js} +3 -3
  120. package/dist/{chunk-JI6WPLZB.js → chunk-2SBCOGQN.js} +4 -4
  121. package/dist/{chunk-6JF7C3U3.js → chunk-2WERWWSS.js} +2 -2
  122. package/dist/{chunk-4XKT4ENZ.js → chunk-2Y3QL3DA.js} +4 -4
  123. package/dist/{chunk-KVMFT6FN.js → chunk-3FL3F4WF.js} +2 -2
  124. package/dist/{chunk-4VJOZJDV.js → chunk-3JPQAIYJ.js} +2 -2
  125. package/dist/{chunk-27EORKJ4.js → chunk-3N4LNBJF.js} +2 -2
  126. package/dist/{chunk-7JZSFJHB.js → chunk-3OJU3RUR.js} +2 -2
  127. package/dist/{chunk-NV5OYV3G.js → chunk-3U6K36QA.js} +5 -5
  128. package/dist/{chunk-MDRLP5DO.js → chunk-3W7ROHN4.js} +3 -3
  129. package/dist/{chunk-3MQM4ZOC.js → chunk-3Y6ZR2VN.js} +3 -3
  130. package/dist/{chunk-HXZIX7MR.js → chunk-47AB65IO.js} +4 -4
  131. package/dist/{chunk-DNYD7AUG.js → chunk-4BOLIZ7Y.js} +3 -3
  132. package/dist/{chunk-4XO346BW.js → chunk-4FBJFQFU.js} +2 -2
  133. package/dist/{chunk-DAQG3C4W.js → chunk-4HM6YDBX.js} +3 -3
  134. package/dist/{chunk-BWKZEW6K.js → chunk-4T3E56NT.js} +3 -3
  135. package/dist/{chunk-4PC7LIQK.js → chunk-4ZMUWRFF.js} +3 -3
  136. package/dist/{chunk-O4AWXTZQ.js → chunk-52XIYULR.js} +3 -3
  137. package/dist/{chunk-GXK4CUAB.js → chunk-5WQKTT5Z.js} +2 -2
  138. package/dist/{chunk-MHIYYHCL.js → chunk-5ZAHAUWD.js} +10 -10
  139. package/dist/{chunk-6N7W3TOV.js → chunk-63BPMTBM.js} +2 -2
  140. package/dist/{chunk-R5YZ3ROM.js → chunk-63PQKTTT.js} +2 -2
  141. package/dist/{chunk-WLZVXCPZ.js → chunk-6GO6WN22.js} +3 -3
  142. package/dist/{chunk-6PQBKMUL.js → chunk-6IIA63VD.js} +11 -7
  143. package/dist/chunk-6IIA63VD.js.map +1 -0
  144. package/dist/{chunk-PQCFW2KT.js → chunk-6IRDW7K3.js} +18 -13
  145. package/dist/chunk-6IRDW7K3.js.map +1 -0
  146. package/dist/{chunk-XDCZBOEY.js → chunk-6LGBGPBU.js} +1 -1
  147. package/dist/{chunk-D4QOZXPM.js → chunk-7ITDATTP.js} +2 -2
  148. package/dist/{chunk-M5E3CKSE.js → chunk-7QWWE5XL.js} +2 -2
  149. package/dist/{chunk-RABKQFTA.js → chunk-A2HCAMRH.js} +2 -2
  150. package/dist/{chunk-6K3WNTRI.js → chunk-AODISQO6.js} +2 -2
  151. package/dist/{chunk-C6JL6PBL.js → chunk-AQDRH6VF.js} +3 -3
  152. package/dist/{chunk-72XEFLMD.js → chunk-ASWINLSW.js} +2 -2
  153. package/dist/{chunk-DNLXQUBX.js → chunk-B746OUJC.js} +24 -36
  154. package/dist/chunk-B746OUJC.js.map +1 -0
  155. package/dist/{chunk-FVCLVASD.js → chunk-B7ZKSROO.js} +24 -24
  156. package/dist/{chunk-EURDMOXZ.js → chunk-BYJZUCOQ.js} +2 -2
  157. package/dist/{chunk-ZWACUOU5.js → chunk-CDBGAAJY.js} +3 -3
  158. package/dist/chunk-CDBGAAJY.js.map +1 -0
  159. package/dist/{chunk-BPD4IJBG.js → chunk-CG6CJMIS.js} +2 -2
  160. package/dist/{chunk-B254JG72.js → chunk-CQX24PT7.js} +2 -2
  161. package/dist/{chunk-HJTTDLF6.js → chunk-CY3NO4JN.js} +4 -4
  162. package/dist/{chunk-OLUG4IFF.js → chunk-D2RLPRSG.js} +2 -2
  163. package/dist/{chunk-74NIHMAT.js → chunk-D653JH6D.js} +3 -3
  164. package/dist/{chunk-FMATVQFW.js → chunk-DA6EQDFR.js} +6 -6
  165. package/dist/{chunk-2LUO22FR.js → chunk-DAI5CTQF.js} +4 -4
  166. package/dist/{chunk-HTKVYEVB.js → chunk-DBM4ZXDN.js} +2 -2
  167. package/dist/{chunk-MB2DTUEG.js → chunk-DNYKLU3K.js} +4 -4
  168. package/dist/{chunk-NPDL4W4Y.js → chunk-DT53LBQN.js} +44 -45
  169. package/dist/chunk-DT53LBQN.js.map +1 -0
  170. package/dist/{chunk-26P7B46A.js → chunk-DXYARXK3.js} +3 -3
  171. package/dist/{chunk-JQKURO3S.js → chunk-E4MQRQ6Z.js} +2 -2
  172. package/dist/{chunk-KW53DBY7.js → chunk-EBW2E32G.js} +2 -2
  173. package/dist/{chunk-O73DRA77.js → chunk-ENKBO7FC.js} +4 -4
  174. package/dist/{chunk-32HA7DXJ.js → chunk-EQNGX77H.js} +11 -11
  175. package/dist/{chunk-CA64OZLZ.js → chunk-FAPYRTG6.js} +4 -4
  176. package/dist/{chunk-WWM7WVD2.js → chunk-GABFKHQE.js} +2 -2
  177. package/dist/chunk-GLCOKWLH.js +42 -0
  178. package/dist/chunk-GLCOKWLH.js.map +1 -0
  179. package/dist/{chunk-OHG2UQ2O.js → chunk-GNM3OY36.js} +51 -13
  180. package/dist/chunk-GNM3OY36.js.map +1 -0
  181. package/dist/{chunk-JJ7VMIEQ.js → chunk-H2GTWX4D.js} +14 -14
  182. package/dist/{chunk-LR7U3HCD.js → chunk-HPSATFLQ.js} +4 -4
  183. package/dist/{chunk-TM2ZLY3Q.js → chunk-I56TUH3Z.js} +13 -13
  184. package/dist/{chunk-ZZUKJ5HQ.js → chunk-IG2ERMSB.js} +2 -2
  185. package/dist/{chunk-2SZ3KC5S.js → chunk-IMKIIS4Y.js} +2 -2
  186. package/dist/{chunk-I57HZMMA.js → chunk-IXIE3H43.js} +2 -2
  187. package/dist/{chunk-OWJD3V4V.js → chunk-J3YQ3554.js} +2 -2
  188. package/dist/{chunk-BCFHMBMK.js → chunk-J5HZBHU4.js} +7 -7
  189. package/dist/{chunk-UHMMRQGU.js → chunk-KD7GNHOP.js} +3 -3
  190. package/dist/{chunk-RXMIXKB3.js → chunk-KIKAVZOW.js} +2 -2
  191. package/dist/{chunk-X7Z4B5GK.js → chunk-KPL7EXS6.js} +2 -2
  192. package/dist/{chunk-GTR2WUBA.js → chunk-KX6M5CJI.js} +1 -1
  193. package/dist/{chunk-CYO5HL4C.js → chunk-KYL2BPS2.js} +2 -2
  194. package/dist/{chunk-ZPZYYSHW.js → chunk-L7EAQGWN.js} +5 -5
  195. package/dist/{chunk-QLDMF7MH.js → chunk-LC5HE7PZ.js} +2 -2
  196. package/dist/{chunk-3SMJ2BIQ.js → chunk-LGD5RESZ.js} +7 -33
  197. package/dist/chunk-LGD5RESZ.js.map +1 -0
  198. package/dist/{chunk-4ICPJZAB.js → chunk-LMYSYG6U.js} +2 -2
  199. package/dist/{chunk-3ZZOE4SN.js → chunk-LOCDYMD6.js} +4 -4
  200. package/dist/{chunk-DNWBLT4U.js → chunk-MASBMJ2M.js} +2 -2
  201. package/dist/{chunk-6VITVQ23.js → chunk-MTYE2PPR.js} +1 -1
  202. package/dist/{chunk-NZMQDUOD.js → chunk-MU6HYDNF.js} +5 -5
  203. package/dist/{chunk-GMVKCEBG.js → chunk-MY6QEDZ2.js} +2 -2
  204. package/dist/{chunk-SK57RWSA.js → chunk-MZGKQ5WV.js} +2 -2
  205. package/dist/{chunk-HSQRYJ4P.js → chunk-N52SFH2K.js} +2 -2
  206. package/dist/{chunk-CEQUNJJY.js → chunk-NDCP5TVN.js} +2 -2
  207. package/dist/{chunk-MY6VZVCP.js → chunk-OAJX5CEL.js} +4 -4
  208. package/dist/{chunk-BQWUXC55.js → chunk-OBBLVC2W.js} +9 -9
  209. package/dist/{chunk-IWIMIRV3.js → chunk-OSJTLQXA.js} +9 -4
  210. package/dist/chunk-OSJTLQXA.js.map +1 -0
  211. package/dist/{chunk-FH75NNLB.js → chunk-OZ5NAXCP.js} +2 -2
  212. package/dist/{chunk-PEGNFZ3F.js → chunk-P5S777YI.js} +2 -2
  213. package/dist/{chunk-LY6727IF.js → chunk-PPSVFNEA.js} +1 -1
  214. package/dist/{chunk-K4FDZVMQ.js → chunk-PR42VIVY.js} +2 -2
  215. package/dist/{chunk-I74J2UZ2.js → chunk-PWMZCW4H.js} +8 -8
  216. package/dist/{chunk-6YDXUE5H.js → chunk-PYA2O3WS.js} +2 -2
  217. package/dist/{chunk-GUIZDI5T.js → chunk-Q2PA4KZS.js} +2 -2
  218. package/dist/{chunk-DZH2HTTB.js → chunk-R27GW5WV.js} +1 -1
  219. package/dist/chunk-R4U4EWZG.js +414 -0
  220. package/dist/chunk-R4U4EWZG.js.map +1 -0
  221. package/dist/{chunk-7OIBLMDP.js → chunk-RAQISW42.js} +2 -2
  222. package/dist/{chunk-CPKD2YGK.js → chunk-RNU5CUPI.js} +2 -2
  223. package/dist/{chunk-467VRP4E.js → chunk-RO5YZQHZ.js} +3 -3
  224. package/dist/{chunk-SSZROOOI.js → chunk-ROLXYGT5.js} +2 -2
  225. package/dist/{chunk-F4B2YYCN.js → chunk-TAWFXRXB.js} +3 -3
  226. package/dist/{chunk-G3FU2IF7.js → chunk-TB7UW5BB.js} +3 -3
  227. package/dist/{chunk-NF6Q4XTN.js → chunk-TQF2I5SY.js} +3 -3
  228. package/dist/{chunk-MM7OKOTE.js → chunk-UBXHP224.js} +43 -18
  229. package/dist/chunk-UBXHP224.js.map +1 -0
  230. package/dist/{chunk-M7A226EQ.js → chunk-UL44R3W2.js} +2 -2
  231. package/dist/{chunk-65K5LV4L.js → chunk-UQKBV22P.js} +21 -20
  232. package/dist/{chunk-65K5LV4L.js.map → chunk-UQKBV22P.js.map} +1 -1
  233. package/dist/{chunk-GTR5NLVP.js → chunk-VCRQPLKS.js} +2 -2
  234. package/dist/{chunk-NWSAF6P5.js → chunk-WJDH7CH5.js} +22 -1
  235. package/dist/chunk-WJDH7CH5.js.map +1 -0
  236. package/dist/{chunk-LG67ZNRU.js → chunk-WK2ZCTUF.js} +2 -2
  237. package/dist/{chunk-XGE75VPK.js → chunk-WNARM3LY.js} +3 -3
  238. package/dist/{chunk-RNBH5TSM.js → chunk-WQ2RTQYO.js} +2 -2
  239. package/dist/chunk-X5XEYQ4B.js +84 -0
  240. package/dist/chunk-X5XEYQ4B.js.map +1 -0
  241. package/dist/{chunk-W57QFLQD.js → chunk-X6JIGNLI.js} +4 -4
  242. package/dist/{chunk-CKA4SJRK.js → chunk-XIQDCQX7.js} +2 -2
  243. package/dist/{chunk-AJ7PY4FJ.js → chunk-Y3GCG6CA.js} +2 -2
  244. package/dist/{chunk-2K27S6LK.js → chunk-Y565N5ZJ.js} +24 -7
  245. package/dist/chunk-Y565N5ZJ.js.map +1 -0
  246. package/dist/{chunk-ZRB4M3GG.js → chunk-YC5KH7ZB.js} +3 -3
  247. package/dist/{chunk-4RY64KQY.js → chunk-YJUKLLNP.js} +2 -2
  248. package/dist/{chunk-24POWVUY.js → chunk-ZDJNRRVS.js} +4 -4
  249. package/dist/{chunk-S6WJ6TUT.js → chunk-ZEVJGMNB.js} +2 -2
  250. package/dist/chunk-ZEVJGMNB.js.map +1 -0
  251. package/dist/{chunk-M7YEZR6X.js → chunk-ZITMDA4C.js} +2 -2
  252. package/dist/components/model-policy-picker.d.ts +2 -0
  253. package/dist/composer.js +6 -6
  254. package/dist/{computer-viewer-BWVNDFTO.js → computer-viewer-6CRLWQHP.js} +5 -5
  255. package/dist/connect.js +6 -6
  256. package/dist/connection-service-presentation.d.ts +1 -4
  257. package/dist/desktop.js +2 -2
  258. package/dist/editor.js +2 -2
  259. package/dist/{embedded-new-voice-GBXSZ3TO.js → embedded-new-voice-KILV3RYM.js} +5 -5
  260. package/dist/{embedded-voice-MGI7EK7C.js → embedded-voice-GHDRLCFX.js} +5 -5
  261. package/dist/{fleet-decision-row-35S3GAUN.js → fleet-decision-row-DQXRRBT7.js} +2 -2
  262. package/dist/index.js +36 -36
  263. package/dist/interaction.js +5 -5
  264. package/dist/machines.js +3 -3
  265. package/dist/messages/en.d.ts +1 -1
  266. package/dist/messages.js +1 -1
  267. package/dist/{model-policy-picker-menu-KP53N6UJ.js → model-policy-picker-menu-5ALKUJMR.js} +4 -4
  268. package/dist/{platform-activity-row-ISMXR7NJ.js → platform-activity-row-227C764Z.js} +2 -2
  269. package/dist/{queue-surface-implementation-ULW7DDJA.js → queue-surface-implementation-H3NOBXU5.js} +5 -5
  270. package/dist/realtime.js +4 -4
  271. package/dist/{sandbox-files-QYSD4XCZ.js → sandbox-files-5FEOHUMD.js} +6 -6
  272. package/dist/session-app.js +92 -94
  273. package/dist/{session-realtime-JXRLPNUH.js → session-realtime-OHBMODNX.js} +3 -3
  274. package/dist/session-realtime.js +2 -2
  275. package/dist/session-ui.js +24 -24
  276. package/dist/session.js +5 -5
  277. package/dist/sites.js +2 -2
  278. package/dist/terminal.js +2 -2
  279. package/dist/this-computer.js +3 -3
  280. package/dist/timeline/connector-logo-index.d.ts +19 -0
  281. package/dist/{timeline-annotation-markers-OJYKHBEO.js → timeline-annotation-markers-NDHS7MCK.js} +2 -2
  282. package/dist/{timeline-annotation-selection-6OAZLXFU.js → timeline-annotation-selection-DRQSTJOV.js} +2 -2
  283. package/dist/{timeline-annotations-dialog-5M6DP5FX.js → timeline-annotations-dialog-G6J5ZJKN.js} +3 -3
  284. package/dist/timeline-model.d.ts +2 -0
  285. package/dist/timeline-model.js +9 -1
  286. package/dist/ui/list-row.js +1 -1
  287. package/dist/usage.js +2 -2
  288. package/dist/workbench.js +4 -4
  289. package/package.json +4 -4
  290. package/src/app/components/capabilities/native-connect-readiness.tsx +1 -0
  291. package/src/app/components/capabilities/perform-capability-action.test.ts +67 -0
  292. package/src/app/components/capabilities/perform-capability-action.tsx +28 -0
  293. package/src/app/components/command-menu/chat-switcher.tsx +25 -4
  294. package/src/app/components/rail/session-header.test.tsx +73 -2
  295. package/src/app/components/rail/session-header.tsx +20 -12
  296. package/src/app/components/rail/session-shell.tsx +10 -18
  297. package/src/app/components/session/subscription-account-indicator.test.ts +239 -0
  298. package/src/app/components/session/subscription-account-indicator.tsx +361 -0
  299. package/src/app/components/session/subscription-account-menu.tsx +21 -43
  300. package/src/app/components/session/subscription-account.test.ts +314 -0
  301. package/src/app/components/session/subscription-account.ts +354 -0
  302. package/src/app/lib/actions/actions-provider.tsx +11 -0
  303. package/src/app/lib/actions/actions.test.ts +59 -4
  304. package/src/app/lib/actions/chat-switcher.ts +73 -20
  305. package/src/app/lib/drive-connect-return.test.ts +183 -0
  306. package/src/app/lib/drive-connect-return.tsx +116 -0
  307. package/src/app/routes/session.tsx +12 -14
  308. package/src/app/routes/sessions-index.tsx +1 -0
  309. package/src/components/model-policy-picker-menu.tsx +25 -4
  310. package/src/components/model-policy-picker.tsx +2 -0
  311. package/src/components/session-mcp-capability-card.tsx +13 -4
  312. package/src/connection-service-presentation.ts +6 -1
  313. package/src/messages/en.ts +1 -1
  314. package/src/timeline/connector-logo-index.test.ts +46 -0
  315. package/src/timeline/connector-logo-index.ts +68 -0
  316. package/src/timeline-model.ts +6 -0
  317. package/src/ui/list-row.tsx +38 -10
  318. package/styles/compiled.css +13 -0
  319. package/dist/app/components/session/codex-account-indicator.d.ts +0 -9
  320. package/dist/app/components/session/model-account-indicator.d.ts +0 -10
  321. package/dist/app/components/session/model-account-indicator.js +0 -34
  322. package/dist/app/components/session/model-account-usage.d.ts +0 -8
  323. package/dist/app/components/session/model-account-usage.js +0 -8
  324. package/dist/chunk-2K27S6LK.js.map +0 -1
  325. package/dist/chunk-3SMJ2BIQ.js.map +0 -1
  326. package/dist/chunk-6PQBKMUL.js.map +0 -1
  327. package/dist/chunk-7H2D4VNU.js +0 -150
  328. package/dist/chunk-7H2D4VNU.js.map +0 -1
  329. package/dist/chunk-DNLXQUBX.js.map +0 -1
  330. package/dist/chunk-HCCSAECI.js +0 -132
  331. package/dist/chunk-HCCSAECI.js.map +0 -1
  332. package/dist/chunk-IWIMIRV3.js.map +0 -1
  333. package/dist/chunk-M77ZQE5T.js +0 -58
  334. package/dist/chunk-M77ZQE5T.js.map +0 -1
  335. package/dist/chunk-MM7OKOTE.js.map +0 -1
  336. package/dist/chunk-NPDL4W4Y.js.map +0 -1
  337. package/dist/chunk-NWSAF6P5.js.map +0 -1
  338. package/dist/chunk-OHG2UQ2O.js.map +0 -1
  339. package/dist/chunk-PQCFW2KT.js.map +0 -1
  340. package/dist/chunk-S6WJ6TUT.js.map +0 -1
  341. package/dist/chunk-ZWACUOU5.js.map +0 -1
  342. package/dist/session-realtime-JXRLPNUH.js.map +0 -1
  343. package/src/app/components/session/codex-account-indicator.tsx +0 -207
  344. package/src/app/components/session/model-account-indicator.tsx +0 -189
  345. package/src/app/components/session/model-account-usage.test.ts +0 -59
  346. package/src/app/components/session/model-account-usage.tsx +0 -89
  347. /package/dist/app/components/session/{codex-account-indicator.js.map → subscription-account-indicator.js.map} +0 -0
  348. /package/dist/app/{components/session/model-account-indicator.js.map → lib/drive-connect-return.js.map} +0 -0
  349. /package/dist/{app/components/session/model-account-usage.js.map → browser-viewer-VKIAULG7.js.map} +0 -0
  350. /package/dist/{browser-viewer-YQC6BFMS.js.map → chat-interactive-block-JGYSW4KB.js.map} +0 -0
  351. /package/dist/{chunk-WN2MIB4Q.js.map → chunk-22V2QCEM.js.map} +0 -0
  352. /package/dist/{chunk-SJPAKWWP.js.map → chunk-2BISI664.js.map} +0 -0
  353. /package/dist/{chunk-O5UOCMH4.js.map → chunk-2LPJVEWY.js.map} +0 -0
  354. /package/dist/{chunk-JI6WPLZB.js.map → chunk-2SBCOGQN.js.map} +0 -0
  355. /package/dist/{chunk-6JF7C3U3.js.map → chunk-2WERWWSS.js.map} +0 -0
  356. /package/dist/{chunk-4XKT4ENZ.js.map → chunk-2Y3QL3DA.js.map} +0 -0
  357. /package/dist/{chunk-KVMFT6FN.js.map → chunk-3FL3F4WF.js.map} +0 -0
  358. /package/dist/{chunk-4VJOZJDV.js.map → chunk-3JPQAIYJ.js.map} +0 -0
  359. /package/dist/{chunk-27EORKJ4.js.map → chunk-3N4LNBJF.js.map} +0 -0
  360. /package/dist/{chunk-7JZSFJHB.js.map → chunk-3OJU3RUR.js.map} +0 -0
  361. /package/dist/{chunk-NV5OYV3G.js.map → chunk-3U6K36QA.js.map} +0 -0
  362. /package/dist/{chunk-MDRLP5DO.js.map → chunk-3W7ROHN4.js.map} +0 -0
  363. /package/dist/{chunk-3MQM4ZOC.js.map → chunk-3Y6ZR2VN.js.map} +0 -0
  364. /package/dist/{chunk-HXZIX7MR.js.map → chunk-47AB65IO.js.map} +0 -0
  365. /package/dist/{chunk-DNYD7AUG.js.map → chunk-4BOLIZ7Y.js.map} +0 -0
  366. /package/dist/{chunk-4XO346BW.js.map → chunk-4FBJFQFU.js.map} +0 -0
  367. /package/dist/{chunk-DAQG3C4W.js.map → chunk-4HM6YDBX.js.map} +0 -0
  368. /package/dist/{chunk-BWKZEW6K.js.map → chunk-4T3E56NT.js.map} +0 -0
  369. /package/dist/{chunk-4PC7LIQK.js.map → chunk-4ZMUWRFF.js.map} +0 -0
  370. /package/dist/{chunk-O4AWXTZQ.js.map → chunk-52XIYULR.js.map} +0 -0
  371. /package/dist/{chunk-GXK4CUAB.js.map → chunk-5WQKTT5Z.js.map} +0 -0
  372. /package/dist/{chunk-MHIYYHCL.js.map → chunk-5ZAHAUWD.js.map} +0 -0
  373. /package/dist/{chunk-6N7W3TOV.js.map → chunk-63BPMTBM.js.map} +0 -0
  374. /package/dist/{chunk-R5YZ3ROM.js.map → chunk-63PQKTTT.js.map} +0 -0
  375. /package/dist/{chunk-WLZVXCPZ.js.map → chunk-6GO6WN22.js.map} +0 -0
  376. /package/dist/{chunk-XDCZBOEY.js.map → chunk-6LGBGPBU.js.map} +0 -0
  377. /package/dist/{chunk-D4QOZXPM.js.map → chunk-7ITDATTP.js.map} +0 -0
  378. /package/dist/{chunk-M5E3CKSE.js.map → chunk-7QWWE5XL.js.map} +0 -0
  379. /package/dist/{chunk-RABKQFTA.js.map → chunk-A2HCAMRH.js.map} +0 -0
  380. /package/dist/{chunk-6K3WNTRI.js.map → chunk-AODISQO6.js.map} +0 -0
  381. /package/dist/{chunk-C6JL6PBL.js.map → chunk-AQDRH6VF.js.map} +0 -0
  382. /package/dist/{chunk-72XEFLMD.js.map → chunk-ASWINLSW.js.map} +0 -0
  383. /package/dist/{chunk-FVCLVASD.js.map → chunk-B7ZKSROO.js.map} +0 -0
  384. /package/dist/{chunk-EURDMOXZ.js.map → chunk-BYJZUCOQ.js.map} +0 -0
  385. /package/dist/{chunk-BPD4IJBG.js.map → chunk-CG6CJMIS.js.map} +0 -0
  386. /package/dist/{chunk-B254JG72.js.map → chunk-CQX24PT7.js.map} +0 -0
  387. /package/dist/{chunk-HJTTDLF6.js.map → chunk-CY3NO4JN.js.map} +0 -0
  388. /package/dist/{chunk-OLUG4IFF.js.map → chunk-D2RLPRSG.js.map} +0 -0
  389. /package/dist/{chunk-74NIHMAT.js.map → chunk-D653JH6D.js.map} +0 -0
  390. /package/dist/{chunk-FMATVQFW.js.map → chunk-DA6EQDFR.js.map} +0 -0
  391. /package/dist/{chunk-2LUO22FR.js.map → chunk-DAI5CTQF.js.map} +0 -0
  392. /package/dist/{chunk-HTKVYEVB.js.map → chunk-DBM4ZXDN.js.map} +0 -0
  393. /package/dist/{chunk-MB2DTUEG.js.map → chunk-DNYKLU3K.js.map} +0 -0
  394. /package/dist/{chunk-26P7B46A.js.map → chunk-DXYARXK3.js.map} +0 -0
  395. /package/dist/{chunk-JQKURO3S.js.map → chunk-E4MQRQ6Z.js.map} +0 -0
  396. /package/dist/{chunk-KW53DBY7.js.map → chunk-EBW2E32G.js.map} +0 -0
  397. /package/dist/{chunk-O73DRA77.js.map → chunk-ENKBO7FC.js.map} +0 -0
  398. /package/dist/{chunk-32HA7DXJ.js.map → chunk-EQNGX77H.js.map} +0 -0
  399. /package/dist/{chunk-CA64OZLZ.js.map → chunk-FAPYRTG6.js.map} +0 -0
  400. /package/dist/{chunk-WWM7WVD2.js.map → chunk-GABFKHQE.js.map} +0 -0
  401. /package/dist/{chunk-JJ7VMIEQ.js.map → chunk-H2GTWX4D.js.map} +0 -0
  402. /package/dist/{chunk-LR7U3HCD.js.map → chunk-HPSATFLQ.js.map} +0 -0
  403. /package/dist/{chunk-TM2ZLY3Q.js.map → chunk-I56TUH3Z.js.map} +0 -0
  404. /package/dist/{chunk-ZZUKJ5HQ.js.map → chunk-IG2ERMSB.js.map} +0 -0
  405. /package/dist/{chunk-2SZ3KC5S.js.map → chunk-IMKIIS4Y.js.map} +0 -0
  406. /package/dist/{chunk-I57HZMMA.js.map → chunk-IXIE3H43.js.map} +0 -0
  407. /package/dist/{chunk-OWJD3V4V.js.map → chunk-J3YQ3554.js.map} +0 -0
  408. /package/dist/{chunk-BCFHMBMK.js.map → chunk-J5HZBHU4.js.map} +0 -0
  409. /package/dist/{chunk-UHMMRQGU.js.map → chunk-KD7GNHOP.js.map} +0 -0
  410. /package/dist/{chunk-RXMIXKB3.js.map → chunk-KIKAVZOW.js.map} +0 -0
  411. /package/dist/{chunk-X7Z4B5GK.js.map → chunk-KPL7EXS6.js.map} +0 -0
  412. /package/dist/{chunk-GTR2WUBA.js.map → chunk-KX6M5CJI.js.map} +0 -0
  413. /package/dist/{chunk-CYO5HL4C.js.map → chunk-KYL2BPS2.js.map} +0 -0
  414. /package/dist/{chunk-ZPZYYSHW.js.map → chunk-L7EAQGWN.js.map} +0 -0
  415. /package/dist/{chunk-QLDMF7MH.js.map → chunk-LC5HE7PZ.js.map} +0 -0
  416. /package/dist/{chunk-4ICPJZAB.js.map → chunk-LMYSYG6U.js.map} +0 -0
  417. /package/dist/{chunk-3ZZOE4SN.js.map → chunk-LOCDYMD6.js.map} +0 -0
  418. /package/dist/{chunk-DNWBLT4U.js.map → chunk-MASBMJ2M.js.map} +0 -0
  419. /package/dist/{chunk-6VITVQ23.js.map → chunk-MTYE2PPR.js.map} +0 -0
  420. /package/dist/{chunk-NZMQDUOD.js.map → chunk-MU6HYDNF.js.map} +0 -0
  421. /package/dist/{chunk-GMVKCEBG.js.map → chunk-MY6QEDZ2.js.map} +0 -0
  422. /package/dist/{chunk-SK57RWSA.js.map → chunk-MZGKQ5WV.js.map} +0 -0
  423. /package/dist/{chunk-HSQRYJ4P.js.map → chunk-N52SFH2K.js.map} +0 -0
  424. /package/dist/{chunk-CEQUNJJY.js.map → chunk-NDCP5TVN.js.map} +0 -0
  425. /package/dist/{chunk-MY6VZVCP.js.map → chunk-OAJX5CEL.js.map} +0 -0
  426. /package/dist/{chunk-BQWUXC55.js.map → chunk-OBBLVC2W.js.map} +0 -0
  427. /package/dist/{chunk-FH75NNLB.js.map → chunk-OZ5NAXCP.js.map} +0 -0
  428. /package/dist/{chunk-PEGNFZ3F.js.map → chunk-P5S777YI.js.map} +0 -0
  429. /package/dist/{chunk-LY6727IF.js.map → chunk-PPSVFNEA.js.map} +0 -0
  430. /package/dist/{chunk-K4FDZVMQ.js.map → chunk-PR42VIVY.js.map} +0 -0
  431. /package/dist/{chunk-I74J2UZ2.js.map → chunk-PWMZCW4H.js.map} +0 -0
  432. /package/dist/{chunk-6YDXUE5H.js.map → chunk-PYA2O3WS.js.map} +0 -0
  433. /package/dist/{chunk-GUIZDI5T.js.map → chunk-Q2PA4KZS.js.map} +0 -0
  434. /package/dist/{chunk-DZH2HTTB.js.map → chunk-R27GW5WV.js.map} +0 -0
  435. /package/dist/{chunk-7OIBLMDP.js.map → chunk-RAQISW42.js.map} +0 -0
  436. /package/dist/{chunk-CPKD2YGK.js.map → chunk-RNU5CUPI.js.map} +0 -0
  437. /package/dist/{chunk-467VRP4E.js.map → chunk-RO5YZQHZ.js.map} +0 -0
  438. /package/dist/{chunk-SSZROOOI.js.map → chunk-ROLXYGT5.js.map} +0 -0
  439. /package/dist/{chunk-F4B2YYCN.js.map → chunk-TAWFXRXB.js.map} +0 -0
  440. /package/dist/{chunk-G3FU2IF7.js.map → chunk-TB7UW5BB.js.map} +0 -0
  441. /package/dist/{chunk-NF6Q4XTN.js.map → chunk-TQF2I5SY.js.map} +0 -0
  442. /package/dist/{chunk-M7A226EQ.js.map → chunk-UL44R3W2.js.map} +0 -0
  443. /package/dist/{chunk-GTR5NLVP.js.map → chunk-VCRQPLKS.js.map} +0 -0
  444. /package/dist/{chunk-LG67ZNRU.js.map → chunk-WK2ZCTUF.js.map} +0 -0
  445. /package/dist/{chunk-XGE75VPK.js.map → chunk-WNARM3LY.js.map} +0 -0
  446. /package/dist/{chunk-RNBH5TSM.js.map → chunk-WQ2RTQYO.js.map} +0 -0
  447. /package/dist/{chunk-W57QFLQD.js.map → chunk-X6JIGNLI.js.map} +0 -0
  448. /package/dist/{chunk-CKA4SJRK.js.map → chunk-XIQDCQX7.js.map} +0 -0
  449. /package/dist/{chunk-AJ7PY4FJ.js.map → chunk-Y3GCG6CA.js.map} +0 -0
  450. /package/dist/{chunk-ZRB4M3GG.js.map → chunk-YC5KH7ZB.js.map} +0 -0
  451. /package/dist/{chunk-4RY64KQY.js.map → chunk-YJUKLLNP.js.map} +0 -0
  452. /package/dist/{chunk-24POWVUY.js.map → chunk-ZDJNRRVS.js.map} +0 -0
  453. /package/dist/{chunk-M7YEZR6X.js.map → chunk-ZITMDA4C.js.map} +0 -0
  454. /package/dist/{chat-interactive-block-Z22YHDRU.js.map → computer-viewer-6CRLWQHP.js.map} +0 -0
  455. /package/dist/{computer-viewer-BWVNDFTO.js.map → embedded-new-voice-KILV3RYM.js.map} +0 -0
  456. /package/dist/{embedded-new-voice-GBXSZ3TO.js.map → embedded-voice-GHDRLCFX.js.map} +0 -0
  457. /package/dist/{fleet-decision-row-35S3GAUN.js.map → fleet-decision-row-DQXRRBT7.js.map} +0 -0
  458. /package/dist/{embedded-voice-MGI7EK7C.js.map → model-policy-picker-menu-5ALKUJMR.js.map} +0 -0
  459. /package/dist/{platform-activity-row-ISMXR7NJ.js.map → platform-activity-row-227C764Z.js.map} +0 -0
  460. /package/dist/{queue-surface-implementation-ULW7DDJA.js.map → queue-surface-implementation-H3NOBXU5.js.map} +0 -0
  461. /package/dist/{model-policy-picker-menu-KP53N6UJ.js.map → sandbox-files-5FEOHUMD.js.map} +0 -0
  462. /package/dist/{sandbox-files-QYSD4XCZ.js.map → session-realtime-OHBMODNX.js.map} +0 -0
  463. /package/dist/{timeline-annotation-markers-OJYKHBEO.js.map → timeline-annotation-markers-NDHS7MCK.js.map} +0 -0
  464. /package/dist/{timeline-annotation-selection-6OAZLXFU.js.map → timeline-annotation-selection-DRQSTJOV.js.map} +0 -0
  465. /package/dist/{timeline-annotations-dialog-5M6DP5FX.js.map → timeline-annotations-dialog-G6J5ZJKN.js.map} +0 -0
@@ -0,0 +1,183 @@
1
+ import { expect, mock, test } from "bun:test";
2
+ import type { OpenGeniBrowserClient } from "@opengeni/sdk/browser";
3
+ import {
4
+ beginDriveConnect,
5
+ resolveDriveConnectReturn,
6
+ completeDriveConnectReturn,
7
+ } from "./drive-connect-return";
8
+
9
+ function fixture() {
10
+ const values = new Map<string, string>();
11
+ const storage = {
12
+ getItem: (key: string) => values.get(key) ?? null,
13
+ setItem: (key: string, value: string) => {
14
+ values.set(key, value);
15
+ },
16
+ removeItem: (key: string) => {
17
+ values.delete(key);
18
+ },
19
+ };
20
+ let outcome = {
21
+ id: "attempt",
22
+ providerId: "google-drive",
23
+ ownership: "personal",
24
+ state: "complete",
25
+ credentialsCommitted: true,
26
+ account: { id: "exact-account", providerId: "google-drive", ownership: "personal" },
27
+ } as Record<string, unknown>;
28
+ const beginConnect = mock(async () => ({
29
+ id: "attempt",
30
+ revision: 1,
31
+ state: "credential_input",
32
+ }));
33
+ const advanceConnectAttempt = mock(async () => ({
34
+ id: "attempt",
35
+ nextAction: { type: "authorize", url: "https://accounts.google.com/consent" },
36
+ }));
37
+ const getConnectAttempt = mock(async () => outcome);
38
+ const client = {
39
+ beginConnect,
40
+ connectTransport: () => ({ advance: advanceConnectAttempt, get: getConnectAttempt }),
41
+ } as unknown as OpenGeniBrowserClient;
42
+ return {
43
+ storage,
44
+ values,
45
+ client,
46
+ beginConnect,
47
+ advanceConnectAttempt,
48
+ getConnectAttempt,
49
+ setOutcome: (value: Record<string, unknown>) => {
50
+ outcome = value;
51
+ },
52
+ };
53
+ }
54
+
55
+ test("Drive return reads the exact durable account, scoped to its original workspace and return nonce", async () => {
56
+ const f = fixture();
57
+ expect(
58
+ await beginDriveConnect({
59
+ client: f.client,
60
+ workspaceId: "display",
61
+ connectionWorkspaceId: "owner",
62
+ itemId: "drive",
63
+ reconnectAccountId: "existing",
64
+ returnUrl: "https://app.example/settings?connect_item=drive",
65
+ storage: f.storage,
66
+ }),
67
+ ).toBe("https://accounts.google.com/consent");
68
+ expect(f.beginConnect).toHaveBeenCalledWith(
69
+ "owner",
70
+ expect.objectContaining({
71
+ providerId: "google-drive",
72
+ ownership: "personal",
73
+ reconnectAccountId: "existing",
74
+ }),
75
+ );
76
+ expect(f.advanceConnectAttempt).toHaveBeenCalledWith(
77
+ "owner",
78
+ "attempt",
79
+ expect.objectContaining({ expectedRevision: 1, action: { type: "credentials", values: {} } }),
80
+ );
81
+ const receipt = JSON.parse([...f.values.values()][0]!);
82
+ await expect(
83
+ resolveDriveConnectReturn({
84
+ client: f.client,
85
+ workspaceId: "display",
86
+ nonce: "wrong",
87
+ storage: f.storage,
88
+ }),
89
+ ).rejects.toThrow("could not be matched");
90
+ expect(f.getConnectAttempt).not.toHaveBeenCalled();
91
+ await expect(
92
+ resolveDriveConnectReturn({
93
+ client: f.client,
94
+ workspaceId: "other",
95
+ nonce: receipt.nonce,
96
+ storage: f.storage,
97
+ }),
98
+ ).rejects.toThrow("could not be matched");
99
+ expect(
100
+ await resolveDriveConnectReturn({
101
+ client: f.client,
102
+ workspaceId: "display",
103
+ nonce: receipt.nonce,
104
+ storage: f.storage,
105
+ }),
106
+ ).toEqual({ itemId: "drive", connectionId: "exact-account" });
107
+ expect(f.getConnectAttempt).toHaveBeenCalledWith("owner", "attempt");
108
+ // StrictMode/effect cleanup can discard the first reader. The locator remains
109
+ // until its active consumer confirms the connector was enabled.
110
+ expect(
111
+ await resolveDriveConnectReturn({
112
+ client: f.client,
113
+ workspaceId: "display",
114
+ nonce: receipt.nonce,
115
+ storage: f.storage,
116
+ }),
117
+ ).toEqual({ itemId: "drive", connectionId: "exact-account" });
118
+ completeDriveConnectReturn("display", "different-return", f.storage);
119
+ expect(f.values.size).toBe(1);
120
+ completeDriveConnectReturn("display", receipt.nonce, f.storage);
121
+ expect(f.values.size).toBe(0);
122
+ });
123
+
124
+ test("failed or incomplete Drive returns never produce an account to auto-enable", async () => {
125
+ for (const state of ["failed", "requires_user_action", "complete"]) {
126
+ const f = fixture();
127
+ await beginDriveConnect({
128
+ client: f.client,
129
+ workspaceId: "workspace",
130
+ itemId: "drive",
131
+ returnUrl: "https://app.example/settings",
132
+ storage: f.storage,
133
+ });
134
+ const receipt = JSON.parse([...f.values.values()][0]!);
135
+ f.setOutcome({
136
+ id: "attempt",
137
+ providerId: "google-drive",
138
+ ownership: "personal",
139
+ state,
140
+ credentialsCommitted: false,
141
+ error: { message: "Provider rejected access" },
142
+ });
143
+ await expect(
144
+ resolveDriveConnectReturn({
145
+ client: f.client,
146
+ workspaceId: "workspace",
147
+ nonce: receipt.nonce,
148
+ storage: f.storage,
149
+ }),
150
+ ).rejects.toThrow();
151
+ expect(f.values.size).toBe(state === "failed" ? 0 : 1);
152
+ }
153
+ });
154
+
155
+ test("a different provider or ownership cannot satisfy a saved Drive return", async () => {
156
+ for (const patch of [{ providerId: "mcp-oauth" }, { ownership: "workspace" }]) {
157
+ const f = fixture();
158
+ await beginDriveConnect({
159
+ client: f.client,
160
+ workspaceId: "workspace",
161
+ itemId: "drive",
162
+ returnUrl: "https://app.example/settings",
163
+ storage: f.storage,
164
+ });
165
+ const receipt = JSON.parse([...f.values.values()][0]!);
166
+ f.setOutcome({
167
+ id: "attempt",
168
+ providerId: "google-drive",
169
+ ownership: "personal",
170
+ state: "complete",
171
+ credentialsCommitted: true,
172
+ ...patch,
173
+ });
174
+ await expect(
175
+ resolveDriveConnectReturn({
176
+ client: f.client,
177
+ workspaceId: "workspace",
178
+ nonce: receipt.nonce,
179
+ storage: f.storage,
180
+ }),
181
+ ).rejects.toThrow("account changed");
182
+ }
183
+ });
@@ -0,0 +1,116 @@
1
+ import type { OpenGeniBrowserClient } from "@opengeni/sdk/browser";
2
+
3
+ export const DRIVE_MCP_URL = "https://drivemcp.googleapis.com/mcp/v1";
4
+ export const DRIVE_CONNECT_RETURN_PARAM = "drive_connect_return";
5
+ const storageKey = (workspaceId: string) => `opengeni.drive-connect.v1:${workspaceId}`;
6
+ type Receipt = { nonce: string; attemptId: string; connectionWorkspaceId: string; itemId: string };
7
+ type Storage = Pick<globalThis.Storage, "getItem" | "setItem" | "removeItem">;
8
+
9
+ /** Browser state is only a locator. Completion and the account come from Connect. */
10
+ export async function beginDriveConnect(input: {
11
+ client: Pick<OpenGeniBrowserClient, "beginConnect" | "connectTransport">;
12
+ workspaceId: string;
13
+ connectionWorkspaceId?: string;
14
+ itemId: string;
15
+ reconnectAccountId?: string;
16
+ returnUrl: string;
17
+ storage: Storage;
18
+ }): Promise<string> {
19
+ const nonce = crypto.randomUUID();
20
+ const returnUrl = new URL(input.returnUrl);
21
+ returnUrl.searchParams.set(DRIVE_CONNECT_RETURN_PARAM, nonce);
22
+ const connectionWorkspaceId = input.connectionWorkspaceId ?? input.workspaceId;
23
+ const created = await input.client.beginConnect(connectionWorkspaceId, {
24
+ providerId: "google-drive",
25
+ ownership: "personal",
26
+ returnUrl: returnUrl.toString(),
27
+ idempotencyKey: crypto.randomUUID(),
28
+ ...(input.reconnectAccountId ? { reconnectAccountId: input.reconnectAccountId } : {}),
29
+ });
30
+ if (created.state !== "credential_input")
31
+ throw new Error("Google Drive setup did not start. Try again.");
32
+ const attempt = await input.client.connectTransport().advance(connectionWorkspaceId, created.id, {
33
+ expectedRevision: created.revision,
34
+ idempotencyKey: crypto.randomUUID(),
35
+ action: { type: "credentials", values: {} },
36
+ });
37
+ if (attempt.nextAction.type !== "authorize")
38
+ throw new Error(attempt.error?.message ?? "Google Drive did not return an authorization link.");
39
+ input.storage.setItem(
40
+ storageKey(input.workspaceId),
41
+ JSON.stringify({
42
+ nonce,
43
+ attemptId: attempt.id,
44
+ connectionWorkspaceId,
45
+ itemId: input.itemId,
46
+ } satisfies Receipt),
47
+ );
48
+ return attempt.nextAction.url;
49
+ }
50
+
51
+ export async function resolveDriveConnectReturn(input: {
52
+ client: Pick<OpenGeniBrowserClient, "connectTransport">;
53
+ workspaceId: string;
54
+ nonce: string;
55
+ storage: Storage;
56
+ }): Promise<{ itemId: string; connectionId: string }> {
57
+ const key = storageKey(input.workspaceId);
58
+ const raw = input.storage.getItem(key);
59
+ let receipt: Receipt;
60
+ try {
61
+ receipt = JSON.parse(raw ?? "null");
62
+ if (
63
+ !receipt ||
64
+ receipt.nonce !== input.nonce ||
65
+ ![receipt.attemptId, receipt.connectionWorkspaceId, receipt.itemId].every(
66
+ (value) => typeof value === "string" && value.length > 0 && value.length <= 4096,
67
+ )
68
+ )
69
+ throw new Error();
70
+ } catch {
71
+ throw new Error(
72
+ "The Google Drive setup return could not be matched. Open Drive to check your connection.",
73
+ );
74
+ }
75
+ const attempt = await input.client
76
+ .connectTransport()
77
+ .get(receipt.connectionWorkspaceId, receipt.attemptId);
78
+ if (
79
+ attempt.id !== receipt.attemptId ||
80
+ attempt.providerId !== "google-drive" ||
81
+ attempt.ownership !== "personal"
82
+ ) {
83
+ throw new Error("The Google Drive setup account changed. Open Drive to try again.");
84
+ }
85
+ if (["failed", "expired", "cancelled"].includes(attempt.state)) {
86
+ input.storage.removeItem(key);
87
+ throw new Error(
88
+ attempt.error?.message ??
89
+ "Google Drive connection was not completed. Open Drive to try again.",
90
+ );
91
+ }
92
+ if (
93
+ attempt.state !== "complete" ||
94
+ !attempt.credentialsCommitted ||
95
+ attempt.account?.providerId !== "google-drive" ||
96
+ attempt.account.ownership !== "personal" ||
97
+ !attempt.account.id
98
+ ) {
99
+ throw new Error("Google Drive setup is still incomplete. Reload to check it again.");
100
+ }
101
+ return { itemId: receipt.itemId, connectionId: attempt.account.id };
102
+ }
103
+
104
+ /** Clear only after the UI has finished enabling; never consume a newer attempt. */
105
+ export function completeDriveConnectReturn(
106
+ workspaceId: string,
107
+ nonce: string,
108
+ storage: Storage,
109
+ ): void {
110
+ const key = storageKey(workspaceId);
111
+ try {
112
+ if (JSON.parse(storage.getItem(key) ?? "null")?.nonce === nonce) storage.removeItem(key);
113
+ } catch {
114
+ /* An absent or replaced browser locator grants no authority. */
115
+ }
116
+ }
@@ -57,6 +57,7 @@ import {
57
57
  // composer. Enter queues and Cmd/Ctrl+Enter steers; failed sessions stay
58
58
  // honest (reason + retry history) and revivable from the same composer.
59
59
  import { LightboxProvider } from "../../timeline";
60
+ import { connectorLogo, connectorLogoIndex } from "../../timeline/connector-logo-index";
60
61
  import { sessionAdmissionBlocked, sessionDisplayStatus } from "../../session-status-model";
61
62
  import { useSessionSecrets } from "../../hooks/use-vaults";
62
63
  import type { WorkspaceTab } from "../../components/workspace-dock";
@@ -182,7 +183,6 @@ import type {
182
183
  SessionEditableArtifactsStatus,
183
184
  } from "../components/session/editable-artifacts-workspace";
184
185
  import {
185
- normalizeProviderDomain,
186
186
  oauthConnectionOwnership,
187
187
  oauthConnectionRef,
188
188
  catalogConnectionAccountSelection,
@@ -1159,20 +1159,15 @@ export function SessionRoute({
1159
1159
  // The workspace shell already needs the capability catalog for session tool
1160
1160
  // policy. Reuse that authoritative read for timeline logos instead of
1161
1161
  // downloading the same large catalog again from the session route.
1162
- const providerLogos = useMemo(() => {
1163
- const logos = new Map<string, string>();
1164
- for (const capability of context.workspaceCapabilityCatalog) {
1165
- const domain = capability.providerDomain ?? capability.connectionRef?.providerDomain ?? null;
1166
- const url = context.client.catalogAssetUrl(capability.logoAssetPath);
1167
- if (domain && url) {
1168
- const key = normalizeProviderDomain(domain);
1169
- if (!logos.has(key)) logos.set(key, url);
1170
- }
1171
- }
1172
- return logos;
1173
- }, [context.client, context.workspaceCapabilityCatalog]);
1162
+ const providerLogos = useMemo(
1163
+ () =>
1164
+ connectorLogoIndex(context.workspaceCapabilityCatalog, (path) =>
1165
+ context.client.catalogAssetUrl(path ?? null),
1166
+ ),
1167
+ [context.client, context.workspaceCapabilityCatalog],
1168
+ );
1174
1169
  const resolveProviderLogo = useCallback(
1175
- (domain: string) => providerLogos.get(normalizeProviderDomain(domain)) ?? null,
1170
+ (domain: string) => connectorLogo(providerLogos, domain),
1176
1171
  [providerLogos],
1177
1172
  );
1178
1173
  // One lineage read feeds the single composer-anchored agents surface. Events
@@ -4027,6 +4022,9 @@ function SessionChatPane(props: {
4027
4022
  sessionKey={props.session.id}
4028
4023
  menuSide="top"
4029
4024
  connectModelsHref={`/workspaces/${encodeURIComponent(props.session.workspaceId)}/settings?section=models`}
4025
+ claudeSubscriptionAvailable={
4026
+ context.clientConfig.claudeSubscriptionEnabled === true
4027
+ }
4030
4028
  codexOnly={props.session.codexCompactionMode === "remote_v2"}
4031
4029
  onModelChange={composer.setModel}
4032
4030
  onEffortChange={composer.setReasoningEffort}
@@ -2228,6 +2228,7 @@ function SessionModelControl({
2228
2228
  error={modelCatalog.error ?? policyError}
2229
2229
  menuSide="bottom"
2230
2230
  connectModelsHref={`/workspaces/${encodeURIComponent(workspaceId)}/settings?section=models`}
2231
+ claudeSubscriptionAvailable={context.clientConfig.claudeSubscriptionEnabled === true}
2231
2232
  onModelChange={(model) => {
2232
2233
  onPolicyChosen();
2233
2234
  context.setModel(model);
@@ -181,7 +181,11 @@ export function ModelPolicyPickerMenu(props: ModelPolicyPickerProps) {
181
181
  ) : null}
182
182
  </>
183
183
  ) : props.connectModelsHref || rows.length > 0 ? (
184
- <ConnectModelsPanel href={props.connectModelsHref} messages={messages} />
184
+ <ConnectModelsPanel
185
+ href={props.connectModelsHref}
186
+ claude={props.claudeSubscriptionAvailable === true}
187
+ messages={messages}
188
+ />
185
189
  ) : (
186
190
  <p className={MENU_NOTE_CLASS}>{messages.noModels}</p>
187
191
  )}
@@ -204,8 +208,14 @@ export function ModelPolicyPickerMenu(props: ModelPolicyPickerProps) {
204
208
 
205
209
  const CONNECT_MODEL_OPTIONS = (
206
210
  t: OpenGeniText,
211
+ claude: boolean,
207
212
  ): Array<{
208
- billingClass: "codex_subscription" | "supergrok_subscription" | "byok" | "external";
213
+ billingClass:
214
+ | "codex_subscription"
215
+ | "claude_subscription"
216
+ | "supergrok_subscription"
217
+ | "byok"
218
+ | "external";
209
219
  title: string;
210
220
  detail: string;
211
221
  }> => [
@@ -214,6 +224,15 @@ const CONNECT_MODEL_OPTIONS = (
214
224
  title: t("modelPolicyPickerMenu.codex"),
215
225
  detail: "ChatGPT",
216
226
  },
227
+ ...(claude
228
+ ? [
229
+ {
230
+ billingClass: "claude_subscription" as const,
231
+ title: t("modelPolicyPicker.claude"),
232
+ detail: "Anthropic",
233
+ },
234
+ ]
235
+ : []),
217
236
  { billingClass: "supergrok_subscription", title: "SuperGrok", detail: "xAI" },
218
237
  {
219
238
  billingClass: "byok",
@@ -225,6 +244,7 @@ const CONNECT_MODEL_OPTIONS = (
225
244
 
226
245
  function ConnectModelsPanel(props: {
227
246
  href: string | undefined;
247
+ claude: boolean;
228
248
  messages: ReturnType<typeof defaultModelPolicyPickerMessages>;
229
249
  }) {
230
250
  const t = useOpenGeniText();
@@ -239,7 +259,7 @@ function ConnectModelsPanel(props: {
239
259
  </p>
240
260
  </div>
241
261
  <div className="grid grid-cols-2 gap-1">
242
- {CONNECT_MODEL_OPTIONS(t).map((option) => {
262
+ {CONNECT_MODEL_OPTIONS(t, props.claude).map((option) => {
243
263
  const content = (
244
264
  <>
245
265
  <span className="flex size-8 shrink-0 items-center justify-center rounded-og-md bg-og-surface-2 text-og-fg">
@@ -260,7 +280,8 @@ function ConnectModelsPanel(props: {
260
280
  </>
261
281
  );
262
282
  const className =
263
- "flex min-w-0 items-center gap-2 rounded-og-md px-1.5 py-1.5 outline-hidden transition-colors hover:bg-og-hover focus-visible:ring-2 focus-visible:ring-og-accent/40";
283
+ // An odd last tile spans both columns instead of sitting alone.
284
+ "flex min-w-0 items-center gap-2 rounded-og-md px-1.5 py-1.5 outline-hidden transition-colors odd:last:col-span-2 hover:bg-og-hover focus-visible:ring-2 focus-visible:ring-og-accent/40";
264
285
  return props.href ? (
265
286
  <a key={option.title} href={props.href} className={className}>
266
287
  {content}
@@ -96,6 +96,8 @@ export type ModelPolicyPickerProps = {
96
96
  allowModelOptions?: boolean | undefined;
97
97
  /** Settings → Models. Shown when the catalog has no model that can run. */
98
98
  connectModelsHref?: string | undefined;
99
+ /** The deployment offers Claude subscriptions; the connect panel lists Claude too. */
100
+ claudeSubscriptionAvailable?: boolean | undefined;
99
101
  /** Classes for the portalled menu surface. Prefer --og-* tokens for theming. */
100
102
  contentClassName?: string | undefined;
101
103
  /** Inline styles for the portalled menu, applied after inherited --og-* tokens. */
@@ -83,7 +83,7 @@ function ScopedCard({
83
83
  onConfigured,
84
84
  dialogOnly = false,
85
85
  onClose,
86
- personalOnly = false,
86
+ personalOnly: configuredPersonalOnly = false,
87
87
  connectLabel,
88
88
  dialogSubtitle,
89
89
  description: hostDescription,
@@ -96,6 +96,9 @@ function ScopedCard({
96
96
  );
97
97
  const view = useConnect(controller);
98
98
  const [item, setItem] = useState<CapabilityCatalogItem | null>(null);
99
+ const personalOnly =
100
+ configuredPersonalOnly ||
101
+ (item?.mcpUrl ?? item?.endpointUrl) === "https://drivemcp.googleapis.com/mcp/v1";
99
102
  const [logo, setLogo] = useState<string | null>(null);
100
103
  const [expanded, setExpanded] = useState(dialogOnly);
101
104
  const [complete, setComplete] = useState(false);
@@ -151,7 +154,9 @@ function ScopedCard({
151
154
  setOwnership(resolved.connectionRef.subjectScope === "subject" ? "personal" : "workspace");
152
155
  else if (
153
156
  !item &&
154
- (personalOnly || resolved.metadata?.defaultConnectionOwnership === "personal")
157
+ (personalOnly ||
158
+ (resolved.mcpUrl ?? resolved.endpointUrl) === "https://drivemcp.googleapis.com/mcp/v1" ||
159
+ resolved.metadata?.defaultConnectionOwnership === "personal")
155
160
  )
156
161
  setOwnership("personal");
157
162
  let accountReady = false;
@@ -399,7 +404,8 @@ function ScopedCard({
399
404
  }
400
405
  startInput.current = input;
401
406
  let attempt = await controller.begin({
402
- providerId: "mcp-oauth",
407
+ providerId:
408
+ mcpUrl === "https://drivemcp.googleapis.com/mcp/v1" ? "google-drive" : "mcp-oauth",
403
409
  ownership,
404
410
  returnUrl,
405
411
  idempotencyKey: startKey.current,
@@ -409,7 +415,10 @@ function ScopedCard({
409
415
  remember(attempt.id);
410
416
  if (attempt.state === "credential_input")
411
417
  attempt = await controller.advance(
412
- { type: "credentials", values: { mcpUrl } },
418
+ {
419
+ type: "credentials",
420
+ values: mcpUrl === "https://drivemcp.googleapis.com/mcp/v1" ? {} : { mcpUrl },
421
+ },
413
422
  advanceKey.current,
414
423
  );
415
424
  if (!active()) return;
@@ -4,7 +4,12 @@ import gmailLogo from "./assets/gmail.ico";
4
4
  import outlookLogo from "./assets/outlook.ico";
5
5
 
6
6
  /** Passive service identity only. Never selects an account or grants tool access. */
7
- const services: Record<string, { name: string; logo: string; mcpUrl?: string }> = {
7
+ const services: Record<string, { name: string; logo: string | null; mcpUrl?: string }> = {
8
+ "google-drive": {
9
+ name: "Google Drive",
10
+ logo: null,
11
+ mcpUrl: "https://drivemcp.googleapis.com/mcp/v1",
12
+ },
8
13
  gmail: { name: "Gmail", logo: gmailLogo, mcpUrl: "https://gmailmcp.googleapis.com/mcp/v1" },
9
14
  "microsoft-outlook-mail": { name: "Outlook Mail", logo: outlookLogo },
10
15
  "microsoft-outlook-calendar": { name: "Outlook Calendar", logo: outlookLogo },
@@ -1817,7 +1817,7 @@ export const englishMessages = {
1817
1817
  "modelPolicy.billedToTheWorkspaceProvider": "Billed to the workspace provider account",
1818
1818
  "modelPolicy.billedToTheWorkspaceVercel": "Billed to the workspace Vercel account",
1819
1819
  "modelPolicy.blockedByWorkspacePolicy": "Blocked by workspace policy",
1820
- "modelPolicy.claudeSubscription": "Claude subscription",
1820
+ "modelPolicy.claudeSubscription": "Claude",
1821
1821
  "modelPolicy.claudeSubscriptionExternalBilling": "Claude subscription · external billing",
1822
1822
  "modelPolicy.codex": "Codex",
1823
1823
  "modelPolicy.codexSubscriptionExternalBilling": "Codex subscription · external billing",
@@ -0,0 +1,46 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import { connectorLogo, connectorLogoIndex } from "./connector-logo-index";
4
+
5
+ const url = (path: string | null | undefined) => (path ? `/v1/${path}` : null);
6
+
7
+ describe("connectorLogoIndex", () => {
8
+ test("a connector's server host finds the provider's logo", () => {
9
+ const index = connectorLogoIndex(
10
+ [
11
+ {
12
+ providerDomain: "linear.app",
13
+ mcpUrl: "https://mcp.linear.app/mcp",
14
+ logoAssetPath: "logos/linear.png",
15
+ },
16
+ {
17
+ providerDomain: "notion.com",
18
+ connectionRef: { providerDomain: "mcp.notion.com" },
19
+ logoAssetPath: "logos/notion.png",
20
+ },
21
+ ],
22
+ url,
23
+ );
24
+ expect(connectorLogo(index, "mcp.linear.app")).toBe("/v1/logos/linear.png");
25
+ expect(connectorLogo(index, "Linear.app")).toBe("/v1/logos/linear.png");
26
+ expect(connectorLogo(index, "mcp.notion.com")).toBe("/v1/logos/notion.png");
27
+ expect(connectorLogo(index, "example.com")).toBeNull();
28
+ });
29
+
30
+ test("a provider's own domain wins over another entry's server host", () => {
31
+ const index = connectorLogoIndex(
32
+ [
33
+ {
34
+ providerDomain: "relay.example",
35
+ mcpUrl: "https://github.com/mcp",
36
+ logoAssetPath: "logos/relay.png",
37
+ },
38
+ { providerDomain: "github.com", logoAssetPath: "logos/github.png" },
39
+ { providerDomain: "nologo.app", logoAssetPath: null },
40
+ ],
41
+ url,
42
+ );
43
+ expect(connectorLogo(index, "github.com")).toBe("/v1/logos/github.png");
44
+ expect(connectorLogo(index, "nologo.app")).toBeNull();
45
+ });
46
+ });
@@ -0,0 +1,68 @@
1
+ /*
2
+ * Which logo belongs to a connector domain. Tool steps and sign-in cards name
3
+ * their connector by the domain of the connection or MCP server they used
4
+ * (Linear's is mcp.linear.app), while the catalog files the logo under the
5
+ * provider's own domain (linear.app). Indexing every domain a catalog entry is
6
+ * known by lets any of them find the logo. Framework-neutral, so web, native
7
+ * and embedded surfaces resolve logos the same way.
8
+ */
9
+
10
+ /** The catalog fields that name a connector's domains and logo. */
11
+ export type ConnectorLogoSource = {
12
+ providerDomain?: string | null | undefined;
13
+ mcpUrl?: string | null | undefined;
14
+ connectionRef?: { providerDomain?: string | null | undefined } | null | undefined;
15
+ logoAssetPath?: string | null | undefined;
16
+ };
17
+
18
+ /** "WWW.Linear.app " → "linear.app". */
19
+ export function normalizeConnectorDomain(domain: string): string {
20
+ return domain
21
+ .trim()
22
+ .toLowerCase()
23
+ .replace(/^www\./, "");
24
+ }
25
+
26
+ function urlHost(url: string | null | undefined): string | null {
27
+ if (!url) return null;
28
+ try {
29
+ return new URL(url).hostname || null;
30
+ } catch {
31
+ return null;
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Every domain each catalog entry is known by, mapped to its logo URL. The
37
+ * provider's own domain is claimed first across the whole catalog, so another
38
+ * entry's server host never takes over a provider's logo.
39
+ */
40
+ export function connectorLogoIndex(
41
+ catalog: readonly ConnectorLogoSource[],
42
+ logoUrl: (logoAssetPath: string | null | undefined) => string | null | undefined,
43
+ ): ReadonlyMap<string, string> {
44
+ const logos = new Map<string, string>();
45
+ const entries = catalog.flatMap((item) => {
46
+ const url = logoUrl(item.logoAssetPath);
47
+ return url ? [{ item, url }] : [];
48
+ });
49
+ const claim = (domain: string | null | undefined, url: string) => {
50
+ if (!domain) return;
51
+ const key = normalizeConnectorDomain(domain);
52
+ if (key && !logos.has(key)) logos.set(key, url);
53
+ };
54
+ for (const { item, url } of entries) claim(item.providerDomain, url);
55
+ for (const { item, url } of entries) {
56
+ claim(item.connectionRef?.providerDomain, url);
57
+ claim(urlHost(item.mcpUrl), url);
58
+ }
59
+ return logos;
60
+ }
61
+
62
+ /** The logo for a connector domain from an index built by `connectorLogoIndex`. */
63
+ export function connectorLogo(
64
+ index: ReadonlyMap<string, string>,
65
+ domain: string | null | undefined,
66
+ ): string | null {
67
+ return domain ? (index.get(normalizeConnectorDomain(domain)) ?? null) : null;
68
+ }
@@ -32,6 +32,12 @@ export {
32
32
  export type { ActivityGroup, ReadableWorkOptions, TurnGroup } from "./timeline/work-presentation";
33
33
  export { timelineGroupContainsPresentedImage } from "./timeline/presented-image";
34
34
  export { mcpToolLeaf, toolDisplayName } from "./timeline/tool-display-name";
35
+ export {
36
+ connectorLogo,
37
+ connectorLogoIndex,
38
+ normalizeConnectorDomain,
39
+ } from "./timeline/connector-logo-index";
40
+ export type { ConnectorLogoSource } from "./timeline/connector-logo-index";
35
41
  export {
36
42
  BUILT_IN_TOOL_STEP_NAMES,
37
43
  builtInToolStep,