@opengeni/react 6.8.0 → 6.9.1-canary.41937124785001

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 (719) hide show
  1. package/dist/app/app-state.js +8 -8
  2. package/dist/app/components/Composer.js +18 -18
  3. package/dist/app/components/agent/agent-capability-picker.js +6 -6
  4. package/dist/app/components/artifacts/artifact-library.js +6 -6
  5. package/dist/app/components/artifacts/artifact-viewer.js +18 -18
  6. package/dist/app/components/artifacts/chat-interactive-block.js +11 -11
  7. package/dist/app/components/artifacts/file-reach-dialog.js +6 -6
  8. package/dist/app/components/artifacts/inline-chat-image.js +19 -19
  9. package/dist/app/components/artifacts/retained-file-preview.js +20 -20
  10. package/dist/app/components/artifacts/retained-text-preview.js +3 -3
  11. package/dist/app/components/artifacts/site-audience.js +3 -3
  12. package/dist/app/components/artifacts/site-conversations.js +9 -9
  13. package/dist/app/components/artifacts/site-data.js +10 -10
  14. package/dist/app/components/artifacts/site-publishing-page.js +25 -25
  15. package/dist/app/components/artifacts/site-publishing.js +22 -22
  16. package/dist/app/components/artifacts/site-settings.js +24 -24
  17. package/dist/app/components/artifacts/site-version-menu.js +3 -3
  18. package/dist/app/components/billing-class-mark.js +3 -3
  19. package/dist/app/components/bots/bot-launch-strip.js +20 -20
  20. package/dist/app/components/bots/bot-template-dialog.js +26 -26
  21. package/dist/app/components/bots/bot-template-shortcuts.js +20 -20
  22. package/dist/app/components/bots/bot-templates-page.js +30 -30
  23. package/dist/app/components/capabilities/capability-detail-sheet.js +6 -6
  24. package/dist/app/components/capabilities/capability-logo-source.js +13 -13
  25. package/dist/app/components/capabilities/connector-tool-permissions.js +4 -4
  26. package/dist/app/components/capabilities/native-connect-setup.js +13 -13
  27. package/dist/app/components/capabilities/own-logins-shared-heads-up.js +3 -3
  28. package/dist/app/components/capabilities/prepared-mcp-setup-card.js +15 -15
  29. package/dist/app/components/capabilities/session-capability-card.js +52 -52
  30. package/dist/app/components/capabilities/session-chrome-card.js +20 -20
  31. package/dist/app/components/capabilities/session-custom-mcp-card.js +16 -16
  32. package/dist/app/components/capabilities/session-github-card.js +16 -16
  33. package/dist/app/components/capabilities/session-machine-card.js +19 -19
  34. package/dist/app/components/capabilities/session-personal-github-card.js +14 -14
  35. package/dist/app/components/capabilities/session-plugin-card.js +8 -8
  36. package/dist/app/components/command-menu/chat-status.js +15 -15
  37. package/dist/app/components/command-menu/chat-switcher.js +35 -35
  38. package/dist/app/components/command-menu/command-menu.js +39 -39
  39. package/dist/app/components/command-menu/shortcut-sheet.js +8 -8
  40. package/dist/app/components/composer-capabilities-menu-body.js +4 -4
  41. package/dist/app/components/composer-mobile-plus-panel.js +8 -8
  42. package/dist/app/components/composer-mobile-plus.js +1 -1
  43. package/dist/app/components/desktop/app-shots.js +6 -6
  44. package/dist/app/components/desktop/computer-use.js +2 -2
  45. package/dist/app/components/desktop/this-computer.js +5 -5
  46. package/dist/app/components/feedback.js +3 -3
  47. package/dist/app/components/github-app-connect-launcher.js +1 -1
  48. package/dist/app/components/machines/connect-machine-dialog.js +11 -11
  49. package/dist/app/components/markdown.js +6 -6
  50. package/dist/app/components/models/models-ui.js +5 -5
  51. package/dist/app/components/models/subscription-usage.d.ts +34 -0
  52. package/dist/app/components/models/subscription-usage.js +24 -0
  53. package/dist/app/components/my-things.js +4 -4
  54. package/dist/app/components/own-where-it-works.js +3 -3
  55. package/dist/app/components/personal-resource-attachment-surface.js +4 -4
  56. package/dist/app/components/pickers.js +5 -5
  57. package/dist/app/components/rail/channel-create-dialog.js +3 -3
  58. package/dist/app/components/rail/project-glyph.js +20 -20
  59. package/dist/app/components/rail/project-profile.js +27 -27
  60. package/dist/app/components/rail/rail-context.js +1 -1
  61. package/dist/app/components/rail/rail-sections.js +55 -55
  62. package/dist/app/components/rail/session-header.js +47 -47
  63. package/dist/app/components/rail/session-list.js +53 -53
  64. package/dist/app/components/rail/session-row-content.js +4 -4
  65. package/dist/app/components/rail/session-row-hover-details.js +14 -14
  66. package/dist/app/components/rail/session-shell.js +76 -73
  67. package/dist/app/components/rail/site-session-group-heading.js +8 -8
  68. package/dist/app/components/session/agent-configuration-panel.js +12 -12
  69. package/dist/app/components/session/banners.js +8 -8
  70. package/dist/app/components/session/console-new-conversation.js +39 -39
  71. package/dist/app/components/session/descendant-requests.js +36 -36
  72. package/dist/app/components/session/editable-artifacts-workspace.js +16 -16
  73. package/dist/app/components/session/failed-session-banner.js +6 -6
  74. package/dist/app/components/session/failure-recovery-boundary.js +3 -3
  75. package/dist/app/components/session/human-input-delegation-record.js +2 -2
  76. package/dist/app/components/session/human-input.js +33 -33
  77. package/dist/app/components/session/inspector.js +43 -43
  78. package/dist/app/components/session/message-actions.js +3 -3
  79. package/dist/app/components/session/message-resource-attachments.js +10 -10
  80. package/dist/app/components/session/model-recovery-notice.js +3 -3
  81. package/dist/app/components/session/new-session-settings-menu.js +6 -6
  82. package/dist/app/components/session/new-session-setup-strip.js +21 -21
  83. package/dist/app/components/session/sandbox-recovery-actions.js +3 -3
  84. package/dist/app/components/session/sandbox-switcher.js +7 -7
  85. package/dist/app/components/session/sandbox-workspace.js +48 -48
  86. package/dist/app/components/session/search-markdown-highlight.js +7 -7
  87. package/dist/app/components/session/search-results-view.js +8 -8
  88. package/dist/app/components/session/session-admin-access.js +4 -4
  89. package/dist/app/components/session/session-admission-notice.js +4 -4
  90. package/dist/app/components/session/session-avatar-picker.js +21 -21
  91. package/dist/app/components/session/session-avatar.js +19 -19
  92. package/dist/app/components/session/session-machine-access-notice.js +4 -4
  93. package/dist/app/components/session/session-profile-dialog.js +25 -25
  94. package/dist/app/components/session/session-profile-editor.js +26 -26
  95. package/dist/app/components/session/session-retention.js +3 -3
  96. package/dist/app/components/session/session-search-dialog.js +8 -8
  97. package/dist/app/components/session/session-tenancy-control.js +2 -2
  98. package/dist/app/components/session/session-usage-limit-section.js +4 -4
  99. package/dist/app/components/session/share-chat-dialog.js +5 -5
  100. package/dist/app/components/session/subagents.js +8 -8
  101. package/dist/app/components/session/subscription-account-indicator.js +12 -7
  102. package/dist/app/components/session/subscription-account-menu.d.ts +15 -15
  103. package/dist/app/components/session/subscription-account-menu.js +6 -1
  104. package/dist/app/components/session/subscription-account.d.ts +16 -9
  105. package/dist/app/components/settings/row-select.js +4 -4
  106. package/dist/app/components/transcription-settings.js +6 -6
  107. package/dist/app/components/ui/destructive-confirm.js +5 -5
  108. package/dist/app/components/usage/usage-entry.js +3 -3
  109. package/dist/app/components/window-bar.js +9 -9
  110. package/dist/app/components/workspace-composer-plus.js +16 -16
  111. package/dist/app/components/workspace-reach.js +4 -4
  112. package/dist/app/embed/session-app.js +160 -157
  113. package/dist/app/lib/actions/actions-provider.js +8 -8
  114. package/dist/app/lib/agent-capabilities.d.ts +12 -2
  115. package/dist/app/lib/agent-capabilities.js +3 -3
  116. package/dist/app/lib/codex-usage-query.js +2 -2
  117. package/dist/app/lib/composer-connectors.js +14 -14
  118. package/dist/app/lib/console-site.js +2 -2
  119. package/dist/app/lib/console-text.js +2 -2
  120. package/dist/app/lib/events.js +12 -12
  121. package/dist/app/lib/failed-session-copy.js +3 -3
  122. package/dist/app/lib/model-access-onboarding.js +3 -3
  123. package/dist/app/lib/move-chat-to-machine.js +3 -3
  124. package/dist/app/lib/session-branch-cache.js +8 -8
  125. package/dist/app/lib/session-create.js +4 -4
  126. package/dist/app/lib/session-group-pagination.js +8 -8
  127. package/dist/app/lib/session-hover-facts.js +13 -13
  128. package/dist/app/lib/session-model.js +2 -2
  129. package/dist/app/lib/session-pins.js +1 -1
  130. package/dist/app/lib/session-rail.js +5 -5
  131. package/dist/app/lib/session-rename.js +3 -3
  132. package/dist/app/lib/sessions-group.d.ts +5 -3
  133. package/dist/app/lib/sessions-group.js +7 -7
  134. package/dist/app/lib/site-tool-consent-dialog.js +7 -7
  135. package/dist/app/lib/site-tool-consent.js +1 -1
  136. package/dist/app/lib/subscription-accounts.d.ts +79 -0
  137. package/dist/app/lib/subscription-accounts.js +18 -0
  138. package/dist/app/lib/turn-failure-analytics.js +4 -4
  139. package/dist/app/lib/use-follow-up-repositories.js +3 -3
  140. package/dist/app/lib/use-workspace-machines.js +4 -4
  141. package/dist/app/lib/use-workspace-model-catalog.js +3 -3
  142. package/dist/app/lib/use-workspace-rigs.js +2 -2
  143. package/dist/app/lib/workspace-navigation-preference.js +4 -4
  144. package/dist/app/lib/workspace-scope-context.js +3 -3
  145. package/dist/app/routes/artifacts.js +48 -48
  146. package/dist/app/routes/retained-artifact.js +32 -32
  147. package/dist/app/routes/session.js +96 -96
  148. package/dist/app/routes/sessions-index-hydration.js +5 -5
  149. package/dist/app/routes/sessions-index.js +76 -76
  150. package/dist/app/routes/site-view.js +55 -55
  151. package/dist/artifacts-document.js +4 -4
  152. package/dist/artifacts-presentation.js +4 -4
  153. package/dist/artifacts-spreadsheet.js +4 -4
  154. package/dist/artifacts.js +10 -10
  155. package/dist/automations.js +10 -10
  156. package/dist/{browser-viewer-ZHQDVHZ2.js → browser-viewer-F4FL7JKB.js} +4 -4
  157. package/dist/{chat-interactive-block-VSDD6X3M.js → chat-interactive-block-4U5JWRSY.js} +5 -5
  158. package/dist/{chunk-4K64EKM7.js → chunk-22YIIM3X.js} +4 -4
  159. package/dist/{chunk-3NNAC43A.js → chunk-2N7ACQ7M.js} +2 -2
  160. package/dist/{chunk-7Z76QP64.js → chunk-2PY5XD3F.js} +35 -5
  161. package/dist/chunk-2PY5XD3F.js.map +1 -0
  162. package/dist/{chunk-WDASYY4S.js → chunk-2TEYUDJD.js} +8 -8
  163. package/dist/{chunk-OTW25A6I.js → chunk-37JJQNZB.js} +3 -3
  164. package/dist/{chunk-VCJQQYRE.js → chunk-3DWQPURZ.js} +4 -4
  165. package/dist/{chunk-GTRAH4FG.js → chunk-3GWC3FU3.js} +2 -2
  166. package/dist/{chunk-AB5IW227.js → chunk-3ICY6LP3.js} +3 -3
  167. package/dist/{chunk-WIFDNUKD.js → chunk-3OCU5RX5.js} +3 -3
  168. package/dist/{chunk-UBRQ3PQD.js → chunk-3SPDJLOR.js} +2 -2
  169. package/dist/{chunk-IZXYFWA4.js → chunk-3WVLR7UA.js} +12 -12
  170. package/dist/{chunk-DEHLWZSI.js → chunk-3XMB3L57.js} +4 -4
  171. package/dist/{chunk-AJBDAVX3.js → chunk-4IUOBO2H.js} +7 -7
  172. package/dist/{chunk-NFCS5WYC.js → chunk-4KQ3A3EO.js} +3 -3
  173. package/dist/{chunk-LIJNVIT3.js → chunk-4L5B5AZT.js} +3 -3
  174. package/dist/{chunk-EDDKPIIV.js → chunk-4NB3TPNE.js} +2 -2
  175. package/dist/{chunk-PSM3CU7N.js → chunk-4TDKXHCD.js} +46 -39
  176. package/dist/chunk-4TDKXHCD.js.map +1 -0
  177. package/dist/{chunk-OJWDNNW3.js → chunk-4TPTGBIO.js} +5 -5
  178. package/dist/{chunk-J2WY42FA.js → chunk-4UHGW6WF.js} +2 -2
  179. package/dist/{chunk-7NLF35YL.js → chunk-4YN2JLYK.js} +4 -4
  180. package/dist/{chunk-OOOSGPJL.js → chunk-53MYEEMA.js} +1 -1
  181. package/dist/{chunk-467WDSOK.js → chunk-5HYWXPMA.js} +2 -2
  182. package/dist/{chunk-XMBOLFFS.js → chunk-5IMNL6IV.js} +2 -2
  183. package/dist/{chunk-4Z5X7PLC.js → chunk-5MLM5T5C.js} +3 -3
  184. package/dist/{chunk-YMI27QPF.js → chunk-5NKQZVXP.js} +2 -2
  185. package/dist/{chunk-ZW5YTIH3.js → chunk-5PB46DAA.js} +1 -1
  186. package/dist/{chunk-ZW5YTIH3.js.map → chunk-5PB46DAA.js.map} +1 -1
  187. package/dist/{chunk-CYDXCILL.js → chunk-5SODSGW7.js} +7 -7
  188. package/dist/{chunk-Q5EZNBPI.js → chunk-5YAJASCO.js} +3 -3
  189. package/dist/{chunk-M3FDGRB4.js → chunk-62XAL5BA.js} +3 -3
  190. package/dist/{chunk-SGH7I7OY.js → chunk-67R6NAFI.js} +2 -2
  191. package/dist/{chunk-Q5K2J5GG.js → chunk-6BN3RU7T.js} +13 -3
  192. package/dist/chunk-6BN3RU7T.js.map +1 -0
  193. package/dist/{chunk-PYB4BFEC.js → chunk-6BQLDL6R.js} +3 -3
  194. package/dist/{chunk-YJSCLGAW.js → chunk-6EZYHJTL.js} +3 -3
  195. package/dist/{chunk-OWET7EY2.js → chunk-6GW7NJMK.js} +19 -13
  196. package/dist/{chunk-OWET7EY2.js.map → chunk-6GW7NJMK.js.map} +1 -1
  197. package/dist/{chunk-G5UQBTXY.js → chunk-6LXIL3Q3.js} +2 -2
  198. package/dist/{chunk-T67LTMSW.js → chunk-6LYVAJFZ.js} +10 -10
  199. package/dist/{chunk-3L465FBR.js → chunk-6WB5UXMZ.js} +6 -6
  200. package/dist/{chunk-EKJHOWTZ.js → chunk-74UGYVCA.js} +4 -4
  201. package/dist/{chunk-PWUSSSSL.js → chunk-7BTNYZC7.js} +2 -2
  202. package/dist/{chunk-NQ2CPQJF.js → chunk-7D3WIDKK.js} +26 -3
  203. package/dist/chunk-7D3WIDKK.js.map +1 -0
  204. package/dist/{chunk-ESXAECZ3.js → chunk-7KZFGA25.js} +2 -2
  205. package/dist/{chunk-EGKARC53.js → chunk-7MGDX2TD.js} +2 -2
  206. package/dist/{chunk-Y3XZEKDQ.js → chunk-7N3GFGB6.js} +2 -2
  207. package/dist/{chunk-AH3DGOTK.js → chunk-7SFSN6AX.js} +2 -2
  208. package/dist/{chunk-QPQ7R77C.js → chunk-7SU4YVZ5.js} +5 -1
  209. package/dist/chunk-7SU4YVZ5.js.map +1 -0
  210. package/dist/{chunk-6QK65ZWM.js → chunk-7TGUHFGO.js} +3 -3
  211. package/dist/{chunk-QURYQFDN.js → chunk-7ZIWO65F.js} +2 -2
  212. package/dist/{chunk-OYCK4JRS.js → chunk-AJHLEJTK.js} +2 -2
  213. package/dist/{chunk-3PZ3LRPV.js → chunk-AN4U7EPH.js} +3 -3
  214. package/dist/{chunk-77BHKC43.js → chunk-APG6CEG7.js} +1 -1
  215. package/dist/{chunk-FSDQQQIA.js → chunk-APHLXQNP.js} +3 -3
  216. package/dist/{chunk-SN2WENRP.js → chunk-AXHQ7QXV.js} +3 -3
  217. package/dist/{chunk-54U6ZBEX.js → chunk-AYTLSPF6.js} +3 -3
  218. package/dist/{chunk-WYGTAQMX.js → chunk-AZFVRPQM.js} +76 -22
  219. package/dist/chunk-AZFVRPQM.js.map +1 -0
  220. package/dist/{chunk-R33SBMB7.js → chunk-BBSKKBMV.js} +3 -3
  221. package/dist/{chunk-2GCHGWNE.js → chunk-BGH6TU2P.js} +3 -3
  222. package/dist/{chunk-D3PTVN2I.js → chunk-BGIYL26H.js} +2 -2
  223. package/dist/{chunk-BQYRZIZ7.js → chunk-BL7UQUC3.js} +2 -2
  224. package/dist/{chunk-EBTUPRRQ.js → chunk-BOUHCYL6.js} +4 -4
  225. package/dist/{chunk-MKDFYE2E.js → chunk-BVNGDFBC.js} +2 -2
  226. package/dist/{chunk-ICAMYP5M.js → chunk-BWJK64CP.js} +2 -2
  227. package/dist/{chunk-RHXYO4H2.js → chunk-BZ2GTCQV.js} +2 -2
  228. package/dist/{chunk-GIWFLWXG.js → chunk-C2KASMJK.js} +4 -4
  229. package/dist/{chunk-KO3OHHY2.js → chunk-CAZDRDQT.js} +2 -2
  230. package/dist/{chunk-OK7BQMCI.js → chunk-CBJRZKZB.js} +9 -9
  231. package/dist/{chunk-OYOFPNLC.js → chunk-CF6NYG7J.js} +4 -4
  232. package/dist/{chunk-MT2R57SF.js → chunk-COITN7WN.js} +2 -2
  233. package/dist/{chunk-OCXTTKVA.js → chunk-CPVOXM2Q.js} +2 -2
  234. package/dist/{chunk-HYEIA25Y.js → chunk-CTZRCBKH.js} +2 -2
  235. package/dist/{chunk-OCXEY7HE.js → chunk-CWL27YTB.js} +2 -2
  236. package/dist/{chunk-K4DQS2ML.js → chunk-D2I33V5P.js} +4 -4
  237. package/dist/{chunk-736RUNIA.js → chunk-DF7WI4JH.js} +4 -4
  238. package/dist/{chunk-KUE5BOQE.js → chunk-DKZYCJCO.js} +4 -4
  239. package/dist/{chunk-74CBR5YE.js → chunk-DQ32FKFQ.js} +2 -2
  240. package/dist/{chunk-4O2XWOLZ.js → chunk-DTKG2YUF.js} +3 -3
  241. package/dist/{chunk-GMHIOYB7.js → chunk-DUDA4V5R.js} +4 -4
  242. package/dist/{chunk-XUOYNJPB.js → chunk-ECROT4M5.js} +24 -24
  243. package/dist/{chunk-PVB4YVDP.js → chunk-EOXV5XGY.js} +2 -2
  244. package/dist/{chunk-U6552Q3T.js → chunk-EQQOZ6DD.js} +2 -2
  245. package/dist/{chunk-G6ICCGJ3.js → chunk-EY6W5H4B.js} +2 -2
  246. package/dist/{chunk-HWVPLFIW.js → chunk-EYRFEWXJ.js} +2 -2
  247. package/dist/{chunk-7YTR3UFO.js → chunk-FB4JWUVJ.js} +8 -5
  248. package/dist/chunk-FB4JWUVJ.js.map +1 -0
  249. package/dist/{chunk-U4LTPFD2.js → chunk-FKK2PD7K.js} +2 -2
  250. package/dist/{chunk-PUUEI4W3.js → chunk-FPHHIC5K.js} +5 -5
  251. package/dist/{chunk-SP44O3OU.js → chunk-FQM6L22H.js} +2 -2
  252. package/dist/{chunk-2J77TWGH.js → chunk-FW22IREV.js} +3 -3
  253. package/dist/{chunk-EBIVTDEG.js → chunk-G4M6AYDB.js} +2 -2
  254. package/dist/{chunk-O4JOE3R7.js → chunk-G55NAU5M.js} +60 -74
  255. package/dist/chunk-G55NAU5M.js.map +1 -0
  256. package/dist/{chunk-BASI553K.js → chunk-G6AZ2WIU.js} +4 -4
  257. package/dist/{chunk-SJYTQLN3.js → chunk-GJ5IDSAX.js} +3 -3
  258. package/dist/{chunk-TDTD66BK.js → chunk-GRDSEZWZ.js} +2 -2
  259. package/dist/{chunk-MV2CLIO6.js → chunk-HBVJIGY2.js} +6 -6
  260. package/dist/{chunk-R4JA5JFI.js → chunk-HCWQLIOE.js} +3 -3
  261. package/dist/{chunk-MZY3VKKM.js → chunk-HEVD4A5G.js} +2 -2
  262. package/dist/{chunk-DLVIRJGK.js → chunk-HNDHSEVJ.js} +2 -2
  263. package/dist/{chunk-LPKJ77EK.js → chunk-HNTZ7B7M.js} +2 -2
  264. package/dist/{chunk-QQIZMVAJ.js → chunk-HQ7GTMII.js} +59 -57
  265. package/dist/chunk-HQ7GTMII.js.map +1 -0
  266. package/dist/{chunk-IN3VQFKS.js → chunk-I2FC7CAI.js} +2 -2
  267. package/dist/{chunk-SK5S2PCK.js → chunk-I7BGHBOM.js} +14 -14
  268. package/dist/chunk-I7BGHBOM.js.map +1 -0
  269. package/dist/{chunk-ZBHGNE2J.js → chunk-IEHZFYMH.js} +3 -3
  270. package/dist/{chunk-DWJ6J3YW.js → chunk-IXISEVD7.js} +4 -4
  271. package/dist/{chunk-TK5FWVZR.js → chunk-IZEDVQUD.js} +3 -3
  272. package/dist/{chunk-HEGV4QMS.js → chunk-J42QE4VO.js} +2 -2
  273. package/dist/{chunk-PRT4J2DL.js → chunk-J555XSUM.js} +2 -2
  274. package/dist/{chunk-SBXSKRFA.js → chunk-JNMHFSDF.js} +3 -3
  275. package/dist/{chunk-KI46GKMD.js → chunk-JTBAOPYO.js} +7 -7
  276. package/dist/{chunk-JHZRAYI4.js → chunk-JWSRFXRN.js} +2 -2
  277. package/dist/chunk-JWSRFXRN.js.map +1 -0
  278. package/dist/{chunk-SXGJL7UT.js → chunk-K376MPJH.js} +14 -14
  279. package/dist/{chunk-OSJ366KR.js → chunk-KEBVT55V.js} +30 -30
  280. package/dist/{chunk-U5UGM5XD.js → chunk-KFIZAXHI.js} +5 -5
  281. package/dist/{chunk-KFNZZ2N6.js → chunk-KKGRDBMK.js} +2 -2
  282. package/dist/{chunk-PLYVGZIN.js → chunk-KKIG6DN5.js} +1 -1
  283. package/dist/{chunk-3OK7Y6ES.js → chunk-KKQO2GAA.js} +2 -2
  284. package/dist/{chunk-DQPIEQGP.js → chunk-KO753ZCZ.js} +2 -2
  285. package/dist/{chunk-YNTLWCF4.js → chunk-KYIRWU65.js} +3 -3
  286. package/dist/{chunk-JKL5S7UQ.js → chunk-L6V63DVI.js} +6 -6
  287. package/dist/{chunk-M5IQVMLR.js → chunk-LAZ2QZTJ.js} +11 -4
  288. package/dist/chunk-LAZ2QZTJ.js.map +1 -0
  289. package/dist/{chunk-CV4VVLPZ.js → chunk-LCNJ2KNS.js} +2 -2
  290. package/dist/{chunk-D74Z2N4K.js → chunk-LE7YKMTU.js} +2 -2
  291. package/dist/{chunk-D5TIVCXG.js → chunk-LEBEOMVT.js} +2 -2
  292. package/dist/chunk-LKLQVANM.js +2 -0
  293. package/dist/{chunk-2OXSB2OL.js → chunk-LKWVBUH6.js} +3 -2
  294. package/dist/chunk-LKWVBUH6.js.map +1 -0
  295. package/dist/{chunk-WXF2RTS4.js → chunk-M6URPYUB.js} +2 -2
  296. package/dist/{chunk-H6BX6WOW.js → chunk-MDHFMRBC.js} +3 -3
  297. package/dist/{chunk-3CDJSKDW.js → chunk-MGZO7CHI.js} +3 -3
  298. package/dist/{chunk-DCEQCGVN.js → chunk-MIWU52TW.js} +2 -2
  299. package/dist/{chunk-PF2WU2IL.js → chunk-ND4IQJUM.js} +120 -17
  300. package/dist/chunk-ND4IQJUM.js.map +1 -0
  301. package/dist/{chunk-3PM3M2Q6.js → chunk-NDXBF3RW.js} +27 -11
  302. package/dist/chunk-NDXBF3RW.js.map +1 -0
  303. package/dist/{chunk-LVELUUK6.js → chunk-NF6QVVMP.js} +2 -2
  304. package/dist/{chunk-UMX6DZME.js → chunk-NTZ5ZNVK.js} +2 -2
  305. package/dist/{chunk-FBA2NXYH.js → chunk-NWLRABUR.js} +3 -3
  306. package/dist/{chunk-TNSJFZ6Q.js → chunk-O2H2U7YS.js} +4 -4
  307. package/dist/{chunk-BFFNINCC.js → chunk-OAL2PPX4.js} +3 -3
  308. package/dist/{chunk-WTSQUCHB.js → chunk-OCYTHZ4A.js} +3 -3
  309. package/dist/{chunk-ZAX4XQLN.js → chunk-OEDTCIXF.js} +2 -2
  310. package/dist/{chunk-CHU3RDV4.js → chunk-OLVSYB3P.js} +3 -3
  311. package/dist/{chunk-PZKHST7A.js → chunk-OQ6QOPK6.js} +10 -3
  312. package/dist/chunk-OQ6QOPK6.js.map +1 -0
  313. package/dist/{chunk-IFSXVU2S.js → chunk-OQHTFOCA.js} +2 -2
  314. package/dist/{chunk-OXQ2SXVC.js → chunk-P56AVROH.js} +2 -2
  315. package/dist/{chunk-CXAN2FHF.js → chunk-PCEJHHGP.js} +6 -6
  316. package/dist/{chunk-5MIBQ4P5.js → chunk-PHGQGVVL.js} +2 -2
  317. package/dist/{chunk-FLWQJDJ5.js → chunk-PUZRHEQI.js} +6 -6
  318. package/dist/{chunk-OP2GD6QW.js → chunk-PV7U6OOJ.js} +2 -2
  319. package/dist/{chunk-SPD4ULVB.js → chunk-PYMROAWS.js} +2 -1
  320. package/dist/chunk-PYMROAWS.js.map +1 -0
  321. package/dist/{chunk-X2QJXDE4.js → chunk-PZQACDH5.js} +8 -8
  322. package/dist/{chunk-CH4UQ4NO.js → chunk-PZTS4O6E.js} +5 -5
  323. package/dist/{chunk-TKQL7EDB.js → chunk-Q42QHUAQ.js} +2 -2
  324. package/dist/{chunk-MRECRNVU.js → chunk-QCYGB6TZ.js} +5 -5
  325. package/dist/{chunk-GSCGKJNK.js → chunk-QECMETOF.js} +2 -2
  326. package/dist/{chunk-RMCLFSMX.js → chunk-QGX3LE6H.js} +2 -2
  327. package/dist/{chunk-HTMQGS63.js → chunk-QI3NDQFP.js} +8 -8
  328. package/dist/{chunk-UU5FBVRX.js → chunk-QZE4BTLA.js} +6 -5
  329. package/dist/chunk-QZE4BTLA.js.map +1 -0
  330. package/dist/{chunk-R5QAL43H.js → chunk-RA3Q52O2.js} +2 -2
  331. package/dist/chunk-RBOHWUSN.js +151 -0
  332. package/dist/chunk-RBOHWUSN.js.map +1 -0
  333. package/dist/{chunk-AJDGP2N4.js → chunk-RJNOQEJJ.js} +20 -20
  334. package/dist/{chunk-477DTTMH.js → chunk-RSFOFUR7.js} +3 -3
  335. package/dist/{chunk-JV5ULONH.js → chunk-RXR6PMSH.js} +39 -39
  336. package/dist/{chunk-J2BTILRR.js → chunk-SM7HFCGC.js} +2 -2
  337. package/dist/{chunk-UTRNLNCW.js → chunk-SN6ZWYOP.js} +69 -97
  338. package/dist/chunk-SN6ZWYOP.js.map +1 -0
  339. package/dist/{chunk-OBGOLHCP.js → chunk-T4HK4XCI.js} +3 -3
  340. package/dist/{chunk-XVLEBB4Y.js → chunk-TBWL6YWL.js} +2 -2
  341. package/dist/{chunk-AAS7OWV6.js → chunk-TIDXYWFX.js} +3 -3
  342. package/dist/{chunk-N3FM4BNA.js → chunk-TKHRGY2P.js} +2 -2
  343. package/dist/{chunk-GU7T2S5N.js → chunk-TU2GSZL7.js} +2 -2
  344. package/dist/{chunk-OI6VI6SU.js → chunk-U6HGJXXQ.js} +8 -8
  345. package/dist/{chunk-4BWMAGJJ.js → chunk-UGRW6RTR.js} +3 -3
  346. package/dist/{chunk-AVXDIRRW.js → chunk-UMRUDYUK.js} +2 -2
  347. package/dist/{chunk-FNXCFIPW.js → chunk-UOT2R5ZD.js} +2 -2
  348. package/dist/{chunk-DIP7YALH.js → chunk-USURKJVT.js} +2 -2
  349. package/dist/{chunk-S27VZ5DO.js → chunk-UU6Q67XM.js} +6 -6
  350. package/dist/{chunk-LTJFV2JI.js → chunk-UZ7NP5CW.js} +2 -2
  351. package/dist/{chunk-H6MJFMHZ.js → chunk-V4FO7UOE.js} +3 -3
  352. package/dist/{chunk-RGR57NYY.js → chunk-V4ZOZRCW.js} +2 -2
  353. package/dist/{chunk-LQKVNREV.js → chunk-V57YMKQZ.js} +3 -3
  354. package/dist/{chunk-XZCCEKPW.js → chunk-VOIWZBY6.js} +6 -6
  355. package/dist/{chunk-E5KOWRDU.js → chunk-VPHPLPDA.js} +2 -2
  356. package/dist/{chunk-OGU73VUN.js → chunk-VUL4KPUU.js} +2 -2
  357. package/dist/{chunk-SFIXTOOJ.js → chunk-VWF6ILAR.js} +3 -3
  358. package/dist/{chunk-FER6EVIY.js → chunk-W54BHJO7.js} +2 -2
  359. package/dist/{chunk-34NV52R3.js → chunk-WCYE4BLC.js} +4 -4
  360. package/dist/{chunk-RISUROBM.js → chunk-WTV25ELY.js} +4 -4
  361. package/dist/{chunk-UO35OEOX.js → chunk-WZYGH7CN.js} +3 -3
  362. package/dist/{chunk-CEMSIU4Z.js → chunk-XG2RWUF7.js} +5 -5
  363. package/dist/chunk-XK72HZ4C.js +147 -0
  364. package/dist/chunk-XK72HZ4C.js.map +1 -0
  365. package/dist/{chunk-K3D7IQQP.js → chunk-XV7QOT7W.js} +6 -6
  366. package/dist/{chunk-GOCODNQS.js → chunk-XWECT3GX.js} +2 -2
  367. package/dist/{chunk-5MHMCE2G.js → chunk-XZQK2ZLW.js} +3 -3
  368. package/dist/{chunk-JV3UI7BH.js → chunk-Y5BR66OH.js} +3 -3
  369. package/dist/{chunk-VXORMNU4.js → chunk-YBHAAULA.js} +67 -2
  370. package/dist/chunk-YBHAAULA.js.map +1 -0
  371. package/dist/{chunk-4F3AEJI6.js → chunk-YD6XU6FY.js} +4 -4
  372. package/dist/{chunk-VATYK3JQ.js → chunk-YFE47G3C.js} +3 -3
  373. package/dist/{chunk-ZR5EKJT6.js → chunk-YG6TWPP7.js} +2 -2
  374. package/dist/{chunk-44JWVYJB.js → chunk-YH3ARKBB.js} +2 -2
  375. package/dist/{chunk-752WXSDN.js → chunk-YI66STKJ.js} +2 -2
  376. package/dist/{chunk-QRECBCJM.js → chunk-YMVPYMKB.js} +2 -2
  377. package/dist/{chunk-77SYIH6O.js → chunk-YPIXBAF6.js} +2 -2
  378. package/dist/{chunk-WRMUXZ7C.js → chunk-YSWPNY6G.js} +3 -3
  379. package/dist/{chunk-GTHCHCWW.js → chunk-YWNNMBZG.js} +3 -3
  380. package/dist/{chunk-3DRLCX5V.js → chunk-Z3HYM2JT.js} +2 -2
  381. package/dist/{chunk-M3HGBO2Y.js → chunk-ZAC7YPRA.js} +1 -1
  382. package/dist/{chunk-2VJOSU4H.js → chunk-ZENESDAF.js} +2 -2
  383. package/dist/{chunk-4JXPLTWV.js → chunk-ZHAPMETO.js} +2 -2
  384. package/dist/{chunk-IJR6VOLU.js → chunk-ZVR6DUZH.js} +2 -2
  385. package/dist/components/message-timeline.d.ts +10 -2
  386. package/dist/composer.js +8 -8
  387. package/dist/{computer-viewer-5LKRCEVQ.js → computer-viewer-FOIOZUF5.js} +5 -5
  388. package/dist/connect.js +12 -12
  389. package/dist/desktop-dictation.js +8 -8
  390. package/dist/desktop.js +2 -2
  391. package/dist/editor.js +2 -2
  392. package/dist/{embedded-new-voice-GHJRY3YL.js → embedded-new-voice-WTXAJNGO.js} +5 -5
  393. package/dist/{embedded-voice-ASQXBSTX.js → embedded-voice-SIJOPN2G.js} +5 -5
  394. package/dist/{fleet-decision-row-U7LDVBEM.js → fleet-decision-row-XKQ3GMYT.js} +2 -2
  395. package/dist/hooks/use-recordings.d.ts +4 -2
  396. package/dist/in-chat-connect-model.js +5 -5
  397. package/dist/index.d.ts +2 -2
  398. package/dist/index.js +66 -60
  399. package/dist/interaction.js +5 -5
  400. package/dist/{latest-question-RNVF262Q.js → latest-question-KA7AQYVI.js} +2 -2
  401. package/dist/machines.js +3 -3
  402. package/dist/meetings/recorder-context.d.ts +6 -1
  403. package/dist/meetings/recorder-panel.d.ts +2 -5
  404. package/dist/meetings-recorder.js +1 -1
  405. package/dist/meetings.js +25 -23
  406. package/dist/meetings.js.map +1 -1
  407. package/dist/messages/en.d.ts +4 -0
  408. package/dist/messages.js +1 -1
  409. package/dist/{model-policy-picker-menu-E6XKMFTA.js → model-policy-picker-menu-6N2G7VGX.js} +4 -4
  410. package/dist/{payment-page-card-DJDKV2LW.js → payment-page-card-IJFZHQ52.js} +4 -4
  411. package/dist/{platform-activity-row-MSDCSMET.js → platform-activity-row-MFCMGI43.js} +2 -2
  412. package/dist/{queue-surface-implementation-GUAIG6TK.js → queue-surface-implementation-BBCDWWOP.js} +5 -5
  413. package/dist/realtime.js +4 -4
  414. package/dist/{recorder-host-2MYDJPQW.js → recorder-host-LDYYOKG7.js} +5 -5
  415. package/dist/recordings.js +4 -4
  416. package/dist/{sandbox-files-W5W2LW4K.js → sandbox-files-VYRBIXJY.js} +6 -6
  417. package/dist/session-app.js +160 -157
  418. package/dist/{session-connect-cards-HPH7JOZP.js → session-connect-cards-GBPSL6OT.js} +9 -9
  419. package/dist/session-connect-cards-GBPSL6OT.js.map +1 -0
  420. package/dist/session-list-model.js +2 -2
  421. package/dist/{session-realtime-SDTKFFIR.js → session-realtime-QGU57TND.js} +3 -3
  422. package/dist/session-realtime-QGU57TND.js.map +1 -0
  423. package/dist/session-realtime.js +2 -2
  424. package/dist/session-ui.js +33 -33
  425. package/dist/session.d.ts +3 -2
  426. package/dist/session.js +16 -10
  427. package/dist/sites.js +2 -2
  428. package/dist/terminal.js +2 -2
  429. package/dist/this-computer.js +3 -3
  430. package/dist/timeline/index.d.ts +3 -2
  431. package/dist/timeline/projection.d.ts +52 -0
  432. package/dist/timeline/turn-summary-model.d.ts +4 -3
  433. package/dist/timeline/types.d.ts +8 -2
  434. package/dist/timeline/use-timeline-pauses.d.ts +12 -0
  435. package/dist/timeline/work-presentation.d.ts +4 -3
  436. package/dist/{timeline-annotation-markers-FNILLWNU.js → timeline-annotation-markers-LL6ZVBZH.js} +2 -2
  437. package/dist/{timeline-annotation-selection-MBCIDO2Q.js → timeline-annotation-selection-WQA76WYC.js} +2 -2
  438. package/dist/{timeline-annotations-dialog-JPNKLOTE.js → timeline-annotations-dialog-HHETAEZA.js} +3 -3
  439. package/dist/timeline-model.js +2 -2
  440. package/dist/ui/access-list.js +5 -5
  441. package/dist/ui/cadence-picker.js +4 -4
  442. package/dist/ui/choice-cards.js +3 -3
  443. package/dist/ui/confirm-dialog.js +2 -2
  444. package/dist/ui/copy-field.js +3 -3
  445. package/dist/ui/detail-page.js +2 -2
  446. package/dist/ui/detail-sheet.js +2 -2
  447. package/dist/ui/disclosure.js +3 -3
  448. package/dist/ui/email-chips-input.js +3 -3
  449. package/dist/ui/field.js +2 -2
  450. package/dist/ui/flush-form-page.js +3 -3
  451. package/dist/ui/form-dialog.js +2 -2
  452. package/dist/ui/list-row.js +3 -3
  453. package/dist/ui/relative-time.js +2 -2
  454. package/dist/ui/revision-history.js +4 -4
  455. package/dist/ui/role-select.js +5 -5
  456. package/dist/ui/select-menu.js +3 -3
  457. package/dist/ui/usage-meter.d.ts +8 -2
  458. package/dist/ui/usage-meter.js +5 -3
  459. package/dist/usage.js +2 -2
  460. package/dist/workbench.js +4 -4
  461. package/package.json +6 -5
  462. package/src/app/components/agent/agent-capability-picker.test.tsx +1 -1
  463. package/src/app/components/models/subscription-usage.tsx +178 -0
  464. package/src/app/components/rail/session-row-content.tsx +27 -0
  465. package/src/app/components/session/subscription-account-indicator.test.ts +78 -18
  466. package/src/app/components/session/subscription-account-indicator.tsx +16 -31
  467. package/src/app/components/session/subscription-account-menu.tsx +79 -101
  468. package/src/app/components/session/subscription-account.test.ts +161 -54
  469. package/src/app/components/session/subscription-account.ts +106 -117
  470. package/src/app/lib/agent-capabilities.tsx +34 -7
  471. package/src/app/lib/session-branch-cache.tsx +1 -0
  472. package/src/app/lib/session-pins.tsx +1 -0
  473. package/src/app/lib/session-row-paused.test.tsx +183 -0
  474. package/src/app/lib/sessions-group-channels.test.ts +4 -4
  475. package/src/app/lib/sessions-group.tsx +62 -4
  476. package/src/app/lib/subscription-accounts.tsx +283 -0
  477. package/src/app/routes/session.tsx +2 -0
  478. package/src/components/message-timeline.tsx +14 -2
  479. package/src/components/session-conversation.tsx +2 -1
  480. package/src/components/timeline-annotations.tsx +4 -1
  481. package/src/components/timeline-settlement.ts +1 -1
  482. package/src/hooks/use-composer.ts +104 -25
  483. package/src/hooks/use-recordings.ts +5 -0
  484. package/src/index.ts +5 -0
  485. package/src/meetings/meeting-detail-page.tsx +4 -2
  486. package/src/meetings/meetings-pages.test.tsx +38 -0
  487. package/src/meetings/recorder-context.tsx +28 -5
  488. package/src/meetings/recorder-panel.tsx +13 -5
  489. package/src/meetings/recorder-workspace.test.tsx +57 -8
  490. package/src/messages/en.ts +5 -0
  491. package/src/recordings-model.ts +7 -0
  492. package/src/session.ts +8 -1
  493. package/src/timeline/index.ts +4 -1
  494. package/src/timeline/projection.ts +228 -16
  495. package/src/timeline/turn-summary-model.ts +4 -3
  496. package/src/timeline/turn-summary.tsx +15 -2
  497. package/src/timeline/types.ts +8 -2
  498. package/src/timeline/use-timeline-pauses.ts +105 -0
  499. package/src/timeline/work-presentation.ts +13 -4
  500. package/src/ui/usage-meter.tsx +10 -7
  501. package/styles/compiled.css +3 -0
  502. package/dist/chunk-2OXSB2OL.js.map +0 -1
  503. package/dist/chunk-3PM3M2Q6.js.map +0 -1
  504. package/dist/chunk-7YTR3UFO.js.map +0 -1
  505. package/dist/chunk-7Z76QP64.js.map +0 -1
  506. package/dist/chunk-JHZRAYI4.js.map +0 -1
  507. package/dist/chunk-M5IQVMLR.js.map +0 -1
  508. package/dist/chunk-NQ2CPQJF.js.map +0 -1
  509. package/dist/chunk-O2UPPN5M.js +0 -2
  510. package/dist/chunk-O4JOE3R7.js.map +0 -1
  511. package/dist/chunk-PF2WU2IL.js.map +0 -1
  512. package/dist/chunk-PSM3CU7N.js.map +0 -1
  513. package/dist/chunk-PZKHST7A.js.map +0 -1
  514. package/dist/chunk-Q5K2J5GG.js.map +0 -1
  515. package/dist/chunk-QPQ7R77C.js.map +0 -1
  516. package/dist/chunk-QQIZMVAJ.js.map +0 -1
  517. package/dist/chunk-SK5S2PCK.js.map +0 -1
  518. package/dist/chunk-SPD4ULVB.js.map +0 -1
  519. package/dist/chunk-UTRNLNCW.js.map +0 -1
  520. package/dist/chunk-UU5FBVRX.js.map +0 -1
  521. package/dist/chunk-VXORMNU4.js.map +0 -1
  522. package/dist/chunk-WYGTAQMX.js.map +0 -1
  523. /package/dist/{browser-viewer-ZHQDVHZ2.js.map → app/components/models/subscription-usage.js.map} +0 -0
  524. /package/dist/{chat-interactive-block-VSDD6X3M.js.map → app/lib/subscription-accounts.js.map} +0 -0
  525. /package/dist/{chunk-O2UPPN5M.js.map → browser-viewer-F4FL7JKB.js.map} +0 -0
  526. /package/dist/{computer-viewer-5LKRCEVQ.js.map → chat-interactive-block-4U5JWRSY.js.map} +0 -0
  527. /package/dist/{chunk-4K64EKM7.js.map → chunk-22YIIM3X.js.map} +0 -0
  528. /package/dist/{chunk-3NNAC43A.js.map → chunk-2N7ACQ7M.js.map} +0 -0
  529. /package/dist/{chunk-WDASYY4S.js.map → chunk-2TEYUDJD.js.map} +0 -0
  530. /package/dist/{chunk-OTW25A6I.js.map → chunk-37JJQNZB.js.map} +0 -0
  531. /package/dist/{chunk-VCJQQYRE.js.map → chunk-3DWQPURZ.js.map} +0 -0
  532. /package/dist/{chunk-GTRAH4FG.js.map → chunk-3GWC3FU3.js.map} +0 -0
  533. /package/dist/{chunk-AB5IW227.js.map → chunk-3ICY6LP3.js.map} +0 -0
  534. /package/dist/{chunk-WIFDNUKD.js.map → chunk-3OCU5RX5.js.map} +0 -0
  535. /package/dist/{chunk-UBRQ3PQD.js.map → chunk-3SPDJLOR.js.map} +0 -0
  536. /package/dist/{chunk-IZXYFWA4.js.map → chunk-3WVLR7UA.js.map} +0 -0
  537. /package/dist/{chunk-DEHLWZSI.js.map → chunk-3XMB3L57.js.map} +0 -0
  538. /package/dist/{chunk-AJBDAVX3.js.map → chunk-4IUOBO2H.js.map} +0 -0
  539. /package/dist/{chunk-NFCS5WYC.js.map → chunk-4KQ3A3EO.js.map} +0 -0
  540. /package/dist/{chunk-LIJNVIT3.js.map → chunk-4L5B5AZT.js.map} +0 -0
  541. /package/dist/{chunk-EDDKPIIV.js.map → chunk-4NB3TPNE.js.map} +0 -0
  542. /package/dist/{chunk-OJWDNNW3.js.map → chunk-4TPTGBIO.js.map} +0 -0
  543. /package/dist/{chunk-J2WY42FA.js.map → chunk-4UHGW6WF.js.map} +0 -0
  544. /package/dist/{chunk-7NLF35YL.js.map → chunk-4YN2JLYK.js.map} +0 -0
  545. /package/dist/{chunk-OOOSGPJL.js.map → chunk-53MYEEMA.js.map} +0 -0
  546. /package/dist/{chunk-467WDSOK.js.map → chunk-5HYWXPMA.js.map} +0 -0
  547. /package/dist/{chunk-XMBOLFFS.js.map → chunk-5IMNL6IV.js.map} +0 -0
  548. /package/dist/{chunk-4Z5X7PLC.js.map → chunk-5MLM5T5C.js.map} +0 -0
  549. /package/dist/{chunk-YMI27QPF.js.map → chunk-5NKQZVXP.js.map} +0 -0
  550. /package/dist/{chunk-CYDXCILL.js.map → chunk-5SODSGW7.js.map} +0 -0
  551. /package/dist/{chunk-Q5EZNBPI.js.map → chunk-5YAJASCO.js.map} +0 -0
  552. /package/dist/{chunk-M3FDGRB4.js.map → chunk-62XAL5BA.js.map} +0 -0
  553. /package/dist/{chunk-SGH7I7OY.js.map → chunk-67R6NAFI.js.map} +0 -0
  554. /package/dist/{chunk-PYB4BFEC.js.map → chunk-6BQLDL6R.js.map} +0 -0
  555. /package/dist/{chunk-YJSCLGAW.js.map → chunk-6EZYHJTL.js.map} +0 -0
  556. /package/dist/{chunk-G5UQBTXY.js.map → chunk-6LXIL3Q3.js.map} +0 -0
  557. /package/dist/{chunk-T67LTMSW.js.map → chunk-6LYVAJFZ.js.map} +0 -0
  558. /package/dist/{chunk-3L465FBR.js.map → chunk-6WB5UXMZ.js.map} +0 -0
  559. /package/dist/{chunk-EKJHOWTZ.js.map → chunk-74UGYVCA.js.map} +0 -0
  560. /package/dist/{chunk-PWUSSSSL.js.map → chunk-7BTNYZC7.js.map} +0 -0
  561. /package/dist/{chunk-ESXAECZ3.js.map → chunk-7KZFGA25.js.map} +0 -0
  562. /package/dist/{chunk-EGKARC53.js.map → chunk-7MGDX2TD.js.map} +0 -0
  563. /package/dist/{chunk-Y3XZEKDQ.js.map → chunk-7N3GFGB6.js.map} +0 -0
  564. /package/dist/{chunk-AH3DGOTK.js.map → chunk-7SFSN6AX.js.map} +0 -0
  565. /package/dist/{chunk-6QK65ZWM.js.map → chunk-7TGUHFGO.js.map} +0 -0
  566. /package/dist/{chunk-QURYQFDN.js.map → chunk-7ZIWO65F.js.map} +0 -0
  567. /package/dist/{chunk-OYCK4JRS.js.map → chunk-AJHLEJTK.js.map} +0 -0
  568. /package/dist/{chunk-3PZ3LRPV.js.map → chunk-AN4U7EPH.js.map} +0 -0
  569. /package/dist/{chunk-77BHKC43.js.map → chunk-APG6CEG7.js.map} +0 -0
  570. /package/dist/{chunk-FSDQQQIA.js.map → chunk-APHLXQNP.js.map} +0 -0
  571. /package/dist/{chunk-SN2WENRP.js.map → chunk-AXHQ7QXV.js.map} +0 -0
  572. /package/dist/{chunk-54U6ZBEX.js.map → chunk-AYTLSPF6.js.map} +0 -0
  573. /package/dist/{chunk-R33SBMB7.js.map → chunk-BBSKKBMV.js.map} +0 -0
  574. /package/dist/{chunk-2GCHGWNE.js.map → chunk-BGH6TU2P.js.map} +0 -0
  575. /package/dist/{chunk-D3PTVN2I.js.map → chunk-BGIYL26H.js.map} +0 -0
  576. /package/dist/{chunk-BQYRZIZ7.js.map → chunk-BL7UQUC3.js.map} +0 -0
  577. /package/dist/{chunk-EBTUPRRQ.js.map → chunk-BOUHCYL6.js.map} +0 -0
  578. /package/dist/{chunk-MKDFYE2E.js.map → chunk-BVNGDFBC.js.map} +0 -0
  579. /package/dist/{chunk-ICAMYP5M.js.map → chunk-BWJK64CP.js.map} +0 -0
  580. /package/dist/{chunk-RHXYO4H2.js.map → chunk-BZ2GTCQV.js.map} +0 -0
  581. /package/dist/{chunk-GIWFLWXG.js.map → chunk-C2KASMJK.js.map} +0 -0
  582. /package/dist/{chunk-KO3OHHY2.js.map → chunk-CAZDRDQT.js.map} +0 -0
  583. /package/dist/{chunk-OK7BQMCI.js.map → chunk-CBJRZKZB.js.map} +0 -0
  584. /package/dist/{chunk-OYOFPNLC.js.map → chunk-CF6NYG7J.js.map} +0 -0
  585. /package/dist/{chunk-MT2R57SF.js.map → chunk-COITN7WN.js.map} +0 -0
  586. /package/dist/{chunk-OCXTTKVA.js.map → chunk-CPVOXM2Q.js.map} +0 -0
  587. /package/dist/{chunk-HYEIA25Y.js.map → chunk-CTZRCBKH.js.map} +0 -0
  588. /package/dist/{chunk-OCXEY7HE.js.map → chunk-CWL27YTB.js.map} +0 -0
  589. /package/dist/{chunk-K4DQS2ML.js.map → chunk-D2I33V5P.js.map} +0 -0
  590. /package/dist/{chunk-736RUNIA.js.map → chunk-DF7WI4JH.js.map} +0 -0
  591. /package/dist/{chunk-KUE5BOQE.js.map → chunk-DKZYCJCO.js.map} +0 -0
  592. /package/dist/{chunk-74CBR5YE.js.map → chunk-DQ32FKFQ.js.map} +0 -0
  593. /package/dist/{chunk-4O2XWOLZ.js.map → chunk-DTKG2YUF.js.map} +0 -0
  594. /package/dist/{chunk-GMHIOYB7.js.map → chunk-DUDA4V5R.js.map} +0 -0
  595. /package/dist/{chunk-XUOYNJPB.js.map → chunk-ECROT4M5.js.map} +0 -0
  596. /package/dist/{chunk-PVB4YVDP.js.map → chunk-EOXV5XGY.js.map} +0 -0
  597. /package/dist/{chunk-U6552Q3T.js.map → chunk-EQQOZ6DD.js.map} +0 -0
  598. /package/dist/{chunk-G6ICCGJ3.js.map → chunk-EY6W5H4B.js.map} +0 -0
  599. /package/dist/{chunk-HWVPLFIW.js.map → chunk-EYRFEWXJ.js.map} +0 -0
  600. /package/dist/{chunk-U4LTPFD2.js.map → chunk-FKK2PD7K.js.map} +0 -0
  601. /package/dist/{chunk-PUUEI4W3.js.map → chunk-FPHHIC5K.js.map} +0 -0
  602. /package/dist/{chunk-SP44O3OU.js.map → chunk-FQM6L22H.js.map} +0 -0
  603. /package/dist/{chunk-2J77TWGH.js.map → chunk-FW22IREV.js.map} +0 -0
  604. /package/dist/{chunk-EBIVTDEG.js.map → chunk-G4M6AYDB.js.map} +0 -0
  605. /package/dist/{chunk-BASI553K.js.map → chunk-G6AZ2WIU.js.map} +0 -0
  606. /package/dist/{chunk-SJYTQLN3.js.map → chunk-GJ5IDSAX.js.map} +0 -0
  607. /package/dist/{chunk-TDTD66BK.js.map → chunk-GRDSEZWZ.js.map} +0 -0
  608. /package/dist/{chunk-MV2CLIO6.js.map → chunk-HBVJIGY2.js.map} +0 -0
  609. /package/dist/{chunk-R4JA5JFI.js.map → chunk-HCWQLIOE.js.map} +0 -0
  610. /package/dist/{chunk-MZY3VKKM.js.map → chunk-HEVD4A5G.js.map} +0 -0
  611. /package/dist/{chunk-DLVIRJGK.js.map → chunk-HNDHSEVJ.js.map} +0 -0
  612. /package/dist/{chunk-LPKJ77EK.js.map → chunk-HNTZ7B7M.js.map} +0 -0
  613. /package/dist/{chunk-IN3VQFKS.js.map → chunk-I2FC7CAI.js.map} +0 -0
  614. /package/dist/{chunk-ZBHGNE2J.js.map → chunk-IEHZFYMH.js.map} +0 -0
  615. /package/dist/{chunk-DWJ6J3YW.js.map → chunk-IXISEVD7.js.map} +0 -0
  616. /package/dist/{chunk-TK5FWVZR.js.map → chunk-IZEDVQUD.js.map} +0 -0
  617. /package/dist/{chunk-HEGV4QMS.js.map → chunk-J42QE4VO.js.map} +0 -0
  618. /package/dist/{chunk-PRT4J2DL.js.map → chunk-J555XSUM.js.map} +0 -0
  619. /package/dist/{chunk-SBXSKRFA.js.map → chunk-JNMHFSDF.js.map} +0 -0
  620. /package/dist/{chunk-KI46GKMD.js.map → chunk-JTBAOPYO.js.map} +0 -0
  621. /package/dist/{chunk-SXGJL7UT.js.map → chunk-K376MPJH.js.map} +0 -0
  622. /package/dist/{chunk-OSJ366KR.js.map → chunk-KEBVT55V.js.map} +0 -0
  623. /package/dist/{chunk-U5UGM5XD.js.map → chunk-KFIZAXHI.js.map} +0 -0
  624. /package/dist/{chunk-KFNZZ2N6.js.map → chunk-KKGRDBMK.js.map} +0 -0
  625. /package/dist/{chunk-PLYVGZIN.js.map → chunk-KKIG6DN5.js.map} +0 -0
  626. /package/dist/{chunk-3OK7Y6ES.js.map → chunk-KKQO2GAA.js.map} +0 -0
  627. /package/dist/{chunk-DQPIEQGP.js.map → chunk-KO753ZCZ.js.map} +0 -0
  628. /package/dist/{chunk-YNTLWCF4.js.map → chunk-KYIRWU65.js.map} +0 -0
  629. /package/dist/{chunk-JKL5S7UQ.js.map → chunk-L6V63DVI.js.map} +0 -0
  630. /package/dist/{chunk-CV4VVLPZ.js.map → chunk-LCNJ2KNS.js.map} +0 -0
  631. /package/dist/{chunk-D74Z2N4K.js.map → chunk-LE7YKMTU.js.map} +0 -0
  632. /package/dist/{chunk-D5TIVCXG.js.map → chunk-LEBEOMVT.js.map} +0 -0
  633. /package/dist/{embedded-new-voice-GHJRY3YL.js.map → chunk-LKLQVANM.js.map} +0 -0
  634. /package/dist/{chunk-WXF2RTS4.js.map → chunk-M6URPYUB.js.map} +0 -0
  635. /package/dist/{chunk-H6BX6WOW.js.map → chunk-MDHFMRBC.js.map} +0 -0
  636. /package/dist/{chunk-3CDJSKDW.js.map → chunk-MGZO7CHI.js.map} +0 -0
  637. /package/dist/{chunk-DCEQCGVN.js.map → chunk-MIWU52TW.js.map} +0 -0
  638. /package/dist/{chunk-LVELUUK6.js.map → chunk-NF6QVVMP.js.map} +0 -0
  639. /package/dist/{chunk-UMX6DZME.js.map → chunk-NTZ5ZNVK.js.map} +0 -0
  640. /package/dist/{chunk-FBA2NXYH.js.map → chunk-NWLRABUR.js.map} +0 -0
  641. /package/dist/{chunk-TNSJFZ6Q.js.map → chunk-O2H2U7YS.js.map} +0 -0
  642. /package/dist/{chunk-BFFNINCC.js.map → chunk-OAL2PPX4.js.map} +0 -0
  643. /package/dist/{chunk-WTSQUCHB.js.map → chunk-OCYTHZ4A.js.map} +0 -0
  644. /package/dist/{chunk-ZAX4XQLN.js.map → chunk-OEDTCIXF.js.map} +0 -0
  645. /package/dist/{chunk-CHU3RDV4.js.map → chunk-OLVSYB3P.js.map} +0 -0
  646. /package/dist/{chunk-IFSXVU2S.js.map → chunk-OQHTFOCA.js.map} +0 -0
  647. /package/dist/{chunk-OXQ2SXVC.js.map → chunk-P56AVROH.js.map} +0 -0
  648. /package/dist/{chunk-CXAN2FHF.js.map → chunk-PCEJHHGP.js.map} +0 -0
  649. /package/dist/{chunk-5MIBQ4P5.js.map → chunk-PHGQGVVL.js.map} +0 -0
  650. /package/dist/{chunk-FLWQJDJ5.js.map → chunk-PUZRHEQI.js.map} +0 -0
  651. /package/dist/{chunk-OP2GD6QW.js.map → chunk-PV7U6OOJ.js.map} +0 -0
  652. /package/dist/{chunk-X2QJXDE4.js.map → chunk-PZQACDH5.js.map} +0 -0
  653. /package/dist/{chunk-CH4UQ4NO.js.map → chunk-PZTS4O6E.js.map} +0 -0
  654. /package/dist/{chunk-TKQL7EDB.js.map → chunk-Q42QHUAQ.js.map} +0 -0
  655. /package/dist/{chunk-MRECRNVU.js.map → chunk-QCYGB6TZ.js.map} +0 -0
  656. /package/dist/{chunk-GSCGKJNK.js.map → chunk-QECMETOF.js.map} +0 -0
  657. /package/dist/{chunk-RMCLFSMX.js.map → chunk-QGX3LE6H.js.map} +0 -0
  658. /package/dist/{chunk-HTMQGS63.js.map → chunk-QI3NDQFP.js.map} +0 -0
  659. /package/dist/{chunk-R5QAL43H.js.map → chunk-RA3Q52O2.js.map} +0 -0
  660. /package/dist/{chunk-AJDGP2N4.js.map → chunk-RJNOQEJJ.js.map} +0 -0
  661. /package/dist/{chunk-477DTTMH.js.map → chunk-RSFOFUR7.js.map} +0 -0
  662. /package/dist/{chunk-JV5ULONH.js.map → chunk-RXR6PMSH.js.map} +0 -0
  663. /package/dist/{chunk-J2BTILRR.js.map → chunk-SM7HFCGC.js.map} +0 -0
  664. /package/dist/{chunk-OBGOLHCP.js.map → chunk-T4HK4XCI.js.map} +0 -0
  665. /package/dist/{chunk-XVLEBB4Y.js.map → chunk-TBWL6YWL.js.map} +0 -0
  666. /package/dist/{chunk-AAS7OWV6.js.map → chunk-TIDXYWFX.js.map} +0 -0
  667. /package/dist/{chunk-N3FM4BNA.js.map → chunk-TKHRGY2P.js.map} +0 -0
  668. /package/dist/{chunk-GU7T2S5N.js.map → chunk-TU2GSZL7.js.map} +0 -0
  669. /package/dist/{chunk-OI6VI6SU.js.map → chunk-U6HGJXXQ.js.map} +0 -0
  670. /package/dist/{chunk-4BWMAGJJ.js.map → chunk-UGRW6RTR.js.map} +0 -0
  671. /package/dist/{chunk-AVXDIRRW.js.map → chunk-UMRUDYUK.js.map} +0 -0
  672. /package/dist/{chunk-FNXCFIPW.js.map → chunk-UOT2R5ZD.js.map} +0 -0
  673. /package/dist/{chunk-DIP7YALH.js.map → chunk-USURKJVT.js.map} +0 -0
  674. /package/dist/{chunk-S27VZ5DO.js.map → chunk-UU6Q67XM.js.map} +0 -0
  675. /package/dist/{chunk-LTJFV2JI.js.map → chunk-UZ7NP5CW.js.map} +0 -0
  676. /package/dist/{chunk-H6MJFMHZ.js.map → chunk-V4FO7UOE.js.map} +0 -0
  677. /package/dist/{chunk-RGR57NYY.js.map → chunk-V4ZOZRCW.js.map} +0 -0
  678. /package/dist/{chunk-LQKVNREV.js.map → chunk-V57YMKQZ.js.map} +0 -0
  679. /package/dist/{chunk-XZCCEKPW.js.map → chunk-VOIWZBY6.js.map} +0 -0
  680. /package/dist/{chunk-E5KOWRDU.js.map → chunk-VPHPLPDA.js.map} +0 -0
  681. /package/dist/{chunk-OGU73VUN.js.map → chunk-VUL4KPUU.js.map} +0 -0
  682. /package/dist/{chunk-SFIXTOOJ.js.map → chunk-VWF6ILAR.js.map} +0 -0
  683. /package/dist/{chunk-FER6EVIY.js.map → chunk-W54BHJO7.js.map} +0 -0
  684. /package/dist/{chunk-34NV52R3.js.map → chunk-WCYE4BLC.js.map} +0 -0
  685. /package/dist/{chunk-RISUROBM.js.map → chunk-WTV25ELY.js.map} +0 -0
  686. /package/dist/{chunk-UO35OEOX.js.map → chunk-WZYGH7CN.js.map} +0 -0
  687. /package/dist/{chunk-CEMSIU4Z.js.map → chunk-XG2RWUF7.js.map} +0 -0
  688. /package/dist/{chunk-K3D7IQQP.js.map → chunk-XV7QOT7W.js.map} +0 -0
  689. /package/dist/{chunk-GOCODNQS.js.map → chunk-XWECT3GX.js.map} +0 -0
  690. /package/dist/{chunk-5MHMCE2G.js.map → chunk-XZQK2ZLW.js.map} +0 -0
  691. /package/dist/{chunk-JV3UI7BH.js.map → chunk-Y5BR66OH.js.map} +0 -0
  692. /package/dist/{chunk-4F3AEJI6.js.map → chunk-YD6XU6FY.js.map} +0 -0
  693. /package/dist/{chunk-VATYK3JQ.js.map → chunk-YFE47G3C.js.map} +0 -0
  694. /package/dist/{chunk-ZR5EKJT6.js.map → chunk-YG6TWPP7.js.map} +0 -0
  695. /package/dist/{chunk-44JWVYJB.js.map → chunk-YH3ARKBB.js.map} +0 -0
  696. /package/dist/{chunk-752WXSDN.js.map → chunk-YI66STKJ.js.map} +0 -0
  697. /package/dist/{chunk-QRECBCJM.js.map → chunk-YMVPYMKB.js.map} +0 -0
  698. /package/dist/{chunk-77SYIH6O.js.map → chunk-YPIXBAF6.js.map} +0 -0
  699. /package/dist/{chunk-WRMUXZ7C.js.map → chunk-YSWPNY6G.js.map} +0 -0
  700. /package/dist/{chunk-GTHCHCWW.js.map → chunk-YWNNMBZG.js.map} +0 -0
  701. /package/dist/{chunk-3DRLCX5V.js.map → chunk-Z3HYM2JT.js.map} +0 -0
  702. /package/dist/{chunk-M3HGBO2Y.js.map → chunk-ZAC7YPRA.js.map} +0 -0
  703. /package/dist/{chunk-2VJOSU4H.js.map → chunk-ZENESDAF.js.map} +0 -0
  704. /package/dist/{chunk-4JXPLTWV.js.map → chunk-ZHAPMETO.js.map} +0 -0
  705. /package/dist/{chunk-IJR6VOLU.js.map → chunk-ZVR6DUZH.js.map} +0 -0
  706. /package/dist/{embedded-voice-ASQXBSTX.js.map → computer-viewer-FOIOZUF5.js.map} +0 -0
  707. /package/dist/{model-policy-picker-menu-E6XKMFTA.js.map → embedded-new-voice-WTXAJNGO.js.map} +0 -0
  708. /package/dist/{sandbox-files-W5W2LW4K.js.map → embedded-voice-SIJOPN2G.js.map} +0 -0
  709. /package/dist/{fleet-decision-row-U7LDVBEM.js.map → fleet-decision-row-XKQ3GMYT.js.map} +0 -0
  710. /package/dist/{latest-question-RNVF262Q.js.map → latest-question-KA7AQYVI.js.map} +0 -0
  711. /package/dist/{session-connect-cards-HPH7JOZP.js.map → model-policy-picker-menu-6N2G7VGX.js.map} +0 -0
  712. /package/dist/{payment-page-card-DJDKV2LW.js.map → payment-page-card-IJFZHQ52.js.map} +0 -0
  713. /package/dist/{platform-activity-row-MSDCSMET.js.map → platform-activity-row-MFCMGI43.js.map} +0 -0
  714. /package/dist/{queue-surface-implementation-GUAIG6TK.js.map → queue-surface-implementation-BBCDWWOP.js.map} +0 -0
  715. /package/dist/{recorder-host-2MYDJPQW.js.map → recorder-host-LDYYOKG7.js.map} +0 -0
  716. /package/dist/{session-realtime-SDTKFFIR.js.map → sandbox-files-VYRBIXJY.js.map} +0 -0
  717. /package/dist/{timeline-annotation-markers-FNILLWNU.js.map → timeline-annotation-markers-LL6ZVBZH.js.map} +0 -0
  718. /package/dist/{timeline-annotation-selection-MBCIDO2Q.js.map → timeline-annotation-selection-WQA76WYC.js.map} +0 -0
  719. /package/dist/{timeline-annotations-dialog-JPNKLOTE.js.map → timeline-annotations-dialog-HHETAEZA.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/hooks/use-recordings.ts"],"sourcesContent":["import type {\n CreateRecordingPersonRequest,\n ListRecordingModelsResponse,\n Recording,\n RecordingCreateTitleSource,\n RecordingLiveSegment,\n RecordingNote,\n RecordingNoteKind,\n RecordingPerson,\n RecordingVoiceprintConsent,\n RecordingSpeaker,\n RecordingTranscriptionRequest,\n RecordingTranscriptPage,\n RecordingTranscriptSegment,\n RecordingTranscriptVersion,\n RecordingVisibility,\n UpdateRecordingRequest,\n} from \"@opengeni/contracts\";\nimport {\n browserRecorderPlatform,\n OpenGeniRecordingsClient,\n RecordingUploader,\n type Recorder,\n type RecorderPlatform,\n type RecorderSnapshot,\n type RecordingChunkStore,\n type RecordingUploadStatus,\n type SystemAudioKind,\n type RecordingTransport,\n type OpenGeniRecordingsTransport,\n uploadRecordingAudio,\n} from \"@opengeni/sdk/recordings\";\nimport { useCallback, useContext, useEffect, useMemo, useRef, useState } from \"react\";\nimport { OpenGeniContext } from \"../session-context\";\nimport { usePolledValue } from \"./internal\";\n\nconst PROCESSING_POLL_MS = 3_000;\n// A meeting recorded on another device changes little until it ends, so pages\n// showing it read it less often, only to notice when the capture finishes.\nconst CAPTURING_POLL_MS = 10_000;\n\n/**\n * Client surface of the recording hooks, as `OpenGeniRecordingsClient` provides\n * it. Each hook checks only the methods it calls, so a host proxy can expose a subset.\n */\nexport type RecordingsClientLike = Pick<\n OpenGeniRecordingsClient,\n | \"listRecordings\"\n | \"createRecording\"\n | \"getRecording\"\n | \"updateRecording\"\n | \"deleteRecording\"\n | \"createRecordingUploads\"\n | \"completeRecordingChunks\"\n | \"finalizeRecording\"\n | \"listRecordingTranscriptVersions\"\n | \"createRecordingTranscript\"\n | \"getRecordingTranscript\"\n | \"setCurrentRecordingTranscript\"\n | \"updateRecordingSpeakers\"\n | \"updateRecordingSegments\"\n | \"getRecordingTrackAudio\"\n | \"listRecordingPeople\"\n | \"createRecordingPerson\"\n | \"rememberRecordingPersonVoice\"\n | \"forgetRecordingPersonVoice\"\n | \"listRecordingModels\"\n | \"createRecordingLiveSession\"\n | \"appendRecordingLiveSegments\"\n | \"listRecordingLiveSegments\"\n | \"listRecordingNotes\"\n | \"saveRecordingNote\"\n>;\n\n/** Refresh every `intervalMs` while `active`, without an extra read when it turns on. */\nfunction useRefreshWhile(\n active: boolean,\n refresh: () => Promise<void>,\n intervalMs: number = PROCESSING_POLL_MS,\n): void {\n const refreshRef = useRef(refresh);\n refreshRef.current = refresh;\n useEffect(() => {\n if (!active) return;\n let cancelled = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n const tick = () => {\n timer = setTimeout(() => {\n void refreshRef.current().finally(() => {\n if (!cancelled) tick();\n });\n }, intervalMs);\n };\n tick();\n return () => {\n cancelled = true;\n if (timer) clearTimeout(timer);\n };\n }, [active, intervalMs]);\n}\n\nexport type RecordingsClientOverride = {\n /** A recordings client, such as a host proxy. Built from the provider's client otherwise. */\n recordings?: Partial<RecordingsClientLike> | undefined;\n /** A client exposing `requestJson` (the SDK client) to build the recordings client from. */\n client?: object | undefined;\n workspaceId?: string | undefined;\n};\n\nconst recordingClients = new WeakMap<object, OpenGeniRecordingsClient>();\n\n/**\n * Resolve the recording methods one hook calls: the explicit `recordings`\n * client, else an `OpenGeniRecordingsClient` over the provider's SDK client.\n */\nfunction useEmbeddedRecordings(\n override: RecordingsClientOverride,\n requiredMethods: readonly (keyof RecordingsClientLike)[],\n hookName: string,\n): { client: RecordingsClientLike; workspaceId: string } {\n const context = useContext(OpenGeniContext);\n const workspaceId = override.workspaceId ?? context?.workspaceId;\n let candidate: object | undefined = override.recordings;\n if (!candidate) {\n const base = (override.client ?? context?.client) as\n | Partial<OpenGeniRecordingsTransport>\n | undefined;\n if (base && typeof base.requestJson === \"function\") {\n candidate = recordingClients.get(base);\n if (!candidate) {\n const created = new OpenGeniRecordingsClient(base as OpenGeniRecordingsTransport);\n recordingClients.set(base, created);\n candidate = created;\n }\n }\n }\n if (!candidate || !workspaceId) {\n throw new Error(\n `@opengeni/react: ${hookName} needs a recordings client and workspace. Wrap the tree in <OpenGeniProvider> with the SDK client, or pass { recordings, workspaceId }.`,\n );\n }\n const methods = candidate as Record<string, unknown>;\n const missing = requiredMethods.filter((method) => typeof methods[method] !== \"function\");\n if (missing.length > 0) {\n throw new Error(\n `@opengeni/react: ${hookName} requires recordings client method${missing.length === 1 ? \"\" : \"s\"} ${missing.join(\", \")}.`,\n );\n }\n return { client: candidate as RecordingsClientLike, workspaceId };\n}\n\n/**\n * The recordings client the hooks use, for calls no hook wraps (deleting from\n * a list, reading track audio): the explicit `recordings` client, else one\n * built over the provider's SDK client.\n */\nexport function useRecordingsClient(options: RecordingsClientOverride = {}): {\n client: RecordingsClientLike;\n workspaceId: string;\n} {\n return useEmbeddedRecordings(options, [], \"useRecordingsClient\");\n}\n\n// --- Capture -------------------------------------------------------------------\n\nexport type UseRecorderOptions = RecordingsClientOverride & {\n /** Leave it out unless the person gave one; Opengeni then names the meeting. */\n title?: string;\n /** `app` when `title` is your app's guess, such as \"Zoom meeting\", for Opengeni to replace. */\n titleSource?: RecordingCreateTitleSource;\n visibility?: RecordingVisibility;\n /** Your own id for what this recording belongs to, to find it again with `useRecordings`. */\n externalRef?: string;\n metadata?: Record<string, unknown>;\n transcription?: RecordingTranscriptionRequest;\n /**\n * The person recording's name, as your app knows it: their microphone's\n * name in the transcript when computer or tab audio is recorded beside it\n * and Opengeni has no name for them.\n */\n ownerName?: string;\n /** Microphone constraints; false records no microphone. Default: on. */\n microphone?: boolean | MediaTrackConstraints;\n /** Also record shared tab or system audio as its own track (Chromium). Default: off. */\n systemAudio?: boolean;\n timesliceMilliseconds?: number;\n keepAwake?: boolean;\n /**\n * Also show a live transcript while recording, in `live`: each track is\n * streamed to the workspace's live speech model as it is captured, which\n * the provider bills for. A preview only. Default: off.\n */\n liveTranscript?: boolean;\n /**\n * Where capture runs. Default: the browser (MediaRecorder and IndexedDB).\n * React Native passes `useNativeRecorderPlatform()` from `@opengeni/react-native/recordings`.\n */\n platform?: RecorderPlatform;\n /** Local storage for chunks not uploaded yet. Default: the platform's (IndexedDB in browsers). */\n store?: RecordingChunkStore;\n /** Finish recordings an earlier page left behind when the hook mounts. Default: on. */\n resumePending?: boolean;\n /** Called once the server has every chunk of a recording and transcription has started. */\n onFinished?: (recordingId: string) => void;\n};\n\nexport type UseRecorderResult = RecorderSnapshot & {\n /** This browser can record audio at all. */\n supported: boolean;\n /** This browser can share a tab's or the system's audio. */\n systemAudioSupported: boolean;\n /**\n * How: `desktop` records other apps' audio directly (inside a desktop app);\n * `display` asks the browser to share a tab or screen. Null when it can't.\n */\n systemAudioKind: SystemAudioKind | null;\n /**\n * Recordings from an earlier page or app run this hook is still finishing in\n * the background. Each leaves the list once it is uploaded, removed for having\n * no audio, or failed for good.\n */\n recovered: string[];\n /**\n * The upload of every recording this device holds audio for, by recording\n * id: the current one and those finished in the background, including one\n * that failed and keeps its audio here until it is tried again.\n */\n uploads: Readonly<Record<string, RecordingUploadStatus>>;\n /** Upload a failed recording again from the audio kept here. False when none failed. */\n retryUpload: (recordingId: string) => boolean;\n /** Start a new recording; per-recording options override the hook's. */\n start: (\n overrides?: Pick<\n UseRecorderOptions,\n | \"title\"\n | \"titleSource\"\n | \"systemAudio\"\n | \"microphone\"\n | \"visibility\"\n | \"liveTranscript\"\n | \"transcription\"\n | \"externalRef\"\n | \"metadata\"\n | \"ownerName\"\n >,\n ) => Promise<void>;\n pause: () => void;\n resume: () => void;\n stop: () => Promise<void>;\n discard: () => Promise<void>;\n /** Rename the recording being made; the title reaches the server with the upload. */\n rename: (title: string) => Promise<void>;\n /** Input level per track number, 0 to 1. Read it from an animation frame for a meter. */\n levels: () => Record<number, number>;\n /**\n * Make a meeting from audio recorded somewhere else, such as a phone's call\n * recording or a voice memo. It goes the way a capture does: saved on this\n * device first, then uploaded in the background and transcribed, and it\n * shows in `uploads` while it uploads. Resolves with the new recording's id\n * once the audio is saved here; a capture under way is not affected.\n */\n importAudio: (input: ImportRecordingAudioInput) => Promise<string>;\n};\n\nexport type ImportRecordingAudioInput = {\n /** One audio file: M4A (MP4), WebM, Ogg or ADTS AAC. */\n audio: Blob;\n /** Its type; the blob's own type by default. */\n mimeType?: string;\n /** The meeting's name. Opengeni names it when omitted. */\n title?: string;\n /** `app` when `title` is a guess, such as the file's name, for Opengeni to replace. */\n titleSource?: RecordingCreateTitleSource;\n /**\n * When it was recorded, if known. By default the date an M4A file states,\n * otherwise it ended just now.\n */\n startedAt?: Date;\n /** How long it plays. Read from an M4A file when omitted. */\n durationMilliseconds?: number;\n /** Recorded with this id (a project, a customer). The hook's `externalRef` otherwise. */\n externalRef?: string;\n};\n\nconst IDLE_SNAPSHOT: RecorderSnapshot = {\n state: \"idle\",\n recordingId: null,\n elapsedMilliseconds: 0,\n tracks: [],\n upload: null,\n error: null,\n};\n\n/**\n * Record a meeting in the browser. Audio is saved locally every few seconds\n * and uploaded in the background, so a reload or a lost connection loses\n * nothing. Unmounting while recording stops capture (the microphone is\n * released) and finishes the upload in the background; keep the hook in a\n * component that outlives page navigation to record across it.\n */\nexport function useRecorder(options: UseRecorderOptions = {}): UseRecorderResult {\n const { client, workspaceId } = useEmbeddedRecordings(\n options,\n [\n \"createRecording\",\n \"createRecordingUploads\",\n \"completeRecordingChunks\",\n \"finalizeRecording\",\n \"deleteRecording\",\n ],\n \"useRecorder\",\n );\n const optionsRef = useRef(options);\n optionsRef.current = options;\n // The uploader outlives client changes (a sign-in token that loads late or is\n // refreshed, a switched account), so it calls through to the latest client\n // instead of keeping the one it was created with.\n const clientRef = useRef(client);\n clientRef.current = client;\n const transport = useMemo<RecordingTransport>(() => {\n const methods = clientRef.current as Partial<RecordingsClientLike>;\n return {\n createRecording: (...args) => clientRef.current.createRecording(...args),\n createRecordingUploads: (...args) => clientRef.current.createRecordingUploads(...args),\n completeRecordingChunks: (...args) => clientRef.current.completeRecordingChunks(...args),\n finalizeRecording: (...args) => clientRef.current.finalizeRecording(...args),\n deleteRecording: (...args) => clientRef.current.deleteRecording(...args),\n ...(typeof methods.updateRecording === \"function\"\n ? {\n updateRecording: (...args) => clientRef.current.updateRecording(...args),\n }\n : {}),\n // Only a client that has the live calls can show a live transcript.\n ...(typeof methods.createRecordingLiveSession === \"function\" &&\n typeof methods.appendRecordingLiveSegments === \"function\"\n ? {\n createRecordingLiveSession: (...args) =>\n clientRef.current.createRecordingLiveSession(...args),\n appendRecordingLiveSegments: (...args) =>\n clientRef.current.appendRecordingLiveSegments(...args),\n }\n : {}),\n };\n }, []);\n const [snapshot, setSnapshot] = useState<RecorderSnapshot>(IDLE_SNAPSHOT);\n const [recovered, setRecovered] = useState<string[]>([]);\n const [uploads, setUploads] = useState<Readonly<Record<string, RecordingUploadStatus>>>({});\n const recorderRef = useRef<Recorder | null>(null);\n const uploaderRef = useRef<RecordingUploader | null>(null);\n const defaultPlatform = useMemo(() => browserRecorderPlatform(), []);\n const platform = options.platform ?? defaultPlatform;\n const platformRef = useRef(platform);\n platformRef.current = platform;\n const support = {\n supported: platform.supported,\n systemAudio: platform.systemAudioSupported,\n systemAudioKind:\n platform.systemAudioKind ?? (platform.systemAudioSupported ? (\"display\" as const) : null),\n };\n const storeRef = useRef<RecordingChunkStore | null>(null);\n const store = useCallback(\n (): RecordingChunkStore =>\n optionsRef.current.store ?? (storeRef.current ??= platformRef.current.createStore()),\n [],\n );\n\n const uploader = useCallback((): RecordingUploader => {\n if (!uploaderRef.current) {\n const isCaptureActive = platformRef.current.isCaptureActive;\n const platformFetch = platformRef.current.fetch;\n uploaderRef.current = new RecordingUploader({\n client: transport,\n store: store(),\n ...(platformFetch ? { fetch: platformFetch } : {}),\n ...(isCaptureActive ? { isCaptureActive: (id: string) => isCaptureActive(id) } : {}),\n onStatus: (status) => {\n if (status.finalized) optionsRef.current.onFinished?.(status.recordingId);\n setUploads((previous) => ({\n ...previous,\n [status.recordingId]: status,\n }));\n if (status.finalized || status.discarded || status.failed) {\n setRecovered((previous) =>\n previous.includes(status.recordingId)\n ? previous.filter((id) => id !== status.recordingId)\n : previous,\n );\n }\n },\n });\n }\n return uploaderRef.current;\n }, [transport, store]);\n\n useEffect(() => {\n if (!support.supported || optionsRef.current.resumePending === false) return;\n let cancelled = false;\n void (async () => {\n // Save what a capture cut short left half-written, then finish everything.\n await platformRef.current.recover?.(store()).catch(() => undefined);\n // Dictations are the composer's to finish; this hook finishes the rest.\n return await uploader().resume({\n only: (recording) => recording.create.purpose !== \"dictation\",\n });\n })()\n .then((ids) => {\n if (cancelled) return;\n // Some may already be done by now: keep only those still in flight.\n const open = ids.filter((id) => {\n const status = uploader().status(id);\n return !(status?.finalized || status?.discarded || status?.failed);\n });\n if (open.length > 0) setRecovered(open);\n })\n .catch(() => undefined);\n return () => {\n cancelled = true;\n };\n }, [support.supported, uploader, store]);\n\n useEffect(\n () => () => {\n const recorder = recorderRef.current;\n if (\n recorder &&\n (recorder.snapshot.state === \"recording\" || recorder.snapshot.state === \"paused\")\n ) {\n void recorder.stop().catch(() => undefined);\n }\n },\n [],\n );\n\n const start = useCallback<UseRecorderResult[\"start\"]>(\n async (overrides = {}) => {\n const current = recorderRef.current?.snapshot.state;\n if (\n current === \"starting\" ||\n current === \"recording\" ||\n current === \"paused\" ||\n current === \"stopping\"\n ) {\n return;\n }\n const merged = {\n ...optionsRef.current,\n ...overrides,\n // A title given at start is the person's unless the start says otherwise.\n ...(overrides.title !== undefined && overrides.titleSource === undefined\n ? { titleSource: undefined }\n : {}),\n // A start can set one transcription option, such as the language, and\n // keep the rest the hook was given.\n ...(overrides.transcription\n ? {\n transcription: {\n ...optionsRef.current.transcription,\n ...overrides.transcription,\n },\n }\n : {}),\n };\n // Earlier recorders stay subscribed to the shared uploader for their own\n // recording; only the current one may change what the hook shows.\n let recorder: Recorder | null = null;\n recorder = platformRef.current.createRecorder({\n client: transport,\n workspaceId,\n store: store(),\n uploader: uploader(),\n ...(merged.title ? { title: merged.title } : {}),\n ...(merged.title && merged.titleSource ? { titleSource: merged.titleSource } : {}),\n ...(merged.visibility ? { visibility: merged.visibility } : {}),\n ...(merged.externalRef ? { externalRef: merged.externalRef } : {}),\n ...(merged.metadata ? { metadata: merged.metadata as never } : {}),\n ...(merged.transcription ? { transcription: merged.transcription } : {}),\n ...(merged.ownerName?.trim() ? { ownerName: merged.ownerName } : {}),\n ...(merged.microphone !== undefined ? { microphone: merged.microphone } : {}),\n ...(merged.systemAudio !== undefined ? { systemAudio: merged.systemAudio } : {}),\n ...(merged.timesliceMilliseconds\n ? { timesliceMilliseconds: merged.timesliceMilliseconds }\n : {}),\n ...(merged.keepAwake !== undefined ? { keepAwake: merged.keepAwake } : {}),\n ...(merged.liveTranscript ? { liveTranscript: true } : {}),\n onChange: (next) => {\n if (recorderRef.current === recorder) setSnapshot(next);\n },\n });\n recorderRef.current = recorder;\n await recorder.start();\n },\n [transport, workspaceId, store, uploader],\n );\n\n return {\n ...snapshot,\n supported: support.supported,\n systemAudioSupported: support.systemAudio,\n systemAudioKind: support.systemAudioKind,\n recovered,\n uploads,\n retryUpload: useCallback((recordingId: string) => {\n const retried = uploaderRef.current?.retry(recordingId) ?? false;\n if (retried) {\n setRecovered((previous) =>\n previous.includes(recordingId) ? previous : [...previous, recordingId],\n );\n }\n return retried;\n }, []),\n start,\n pause: useCallback(() => recorderRef.current?.pause(), []),\n resume: useCallback(() => recorderRef.current?.resume(), []),\n stop: useCallback(async () => {\n await recorderRef.current?.stop();\n }, []),\n discard: useCallback(async () => {\n await recorderRef.current?.discard();\n }, []),\n rename: useCallback(async (title: string) => {\n const recorder = recorderRef.current;\n if (!recorder) throw new Error(\"Nothing is being recorded to rename.\");\n await recorder.rename(title);\n }, []),\n levels: useCallback(() => recorderRef.current?.levels() ?? {}, []),\n importAudio: useCallback(\n async (input: ImportRecordingAudioInput) => {\n const current = optionsRef.current;\n const title = input.title?.trim();\n const externalRef = input.externalRef ?? current.externalRef;\n return await new Promise<string>((resolve, reject) => {\n uploadRecordingAudio({\n uploader: uploader(),\n workspaceId,\n audio: input.audio,\n source: \"upload\",\n ...(input.mimeType ? { mimeType: input.mimeType } : {}),\n ...(input.durationMilliseconds !== undefined\n ? { durationMilliseconds: input.durationMilliseconds }\n : {}),\n create: {\n purpose: \"meeting\",\n ...(title ? { title } : {}),\n ...(title && input.titleSource ? { titleSource: input.titleSource } : {}),\n ...(input.startedAt ? { startedAt: input.startedAt.toISOString() } : {}),\n ...(current.visibility ? { visibility: current.visibility } : {}),\n ...(externalRef ? { externalRef } : {}),\n ...(current.metadata ? { metadata: current.metadata as never } : {}),\n ...(current.transcription ? { transcription: current.transcription } : {}),\n },\n onStored: resolve,\n }).catch(reject);\n });\n },\n [uploader, workspaceId],\n ),\n };\n}\n\n// --- Reads -------------------------------------------------------------------------\n\nexport type UseRecordingsOptions = RecordingsClientOverride & {\n query?: string;\n externalRef?: string;\n limit?: number;\n pollIntervalMs?: number;\n enabled?: boolean;\n};\n\nexport type UseRecordingsResult = {\n recordings: Recording[];\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n hasMore: boolean;\n loadingMore: boolean;\n loadMore: () => Promise<void>;\n};\n\nfunction isProcessing(recording: Recording | null | undefined): boolean {\n if (!recording) return false;\n const state = recording.transcript?.state;\n return recording.state === \"processing\" || state === \"queued\" || state === \"processing\";\n}\n\n/**\n * The recordings the signed-in person can see, newest first. Polls while any is\n * being transcribed, and less often while any is still being recorded.\n */\nexport function useRecordings(options: UseRecordingsOptions = {}): UseRecordingsResult {\n const { client, workspaceId } = useEmbeddedRecordings(\n options,\n [\"listRecordings\"],\n \"useRecordings\",\n );\n const { query, externalRef, limit } = options;\n const load = useCallback(\n async (signal?: AbortSignal) =>\n await client.listRecordings(workspaceId, {\n ...(query ? { query } : {}),\n ...(externalRef ? { externalRef } : {}),\n ...(limit ? { limit } : {}),\n ...(signal ? { signal } : {}),\n }),\n [client, workspaceId, query, externalRef, limit],\n );\n const state = usePolledValue(load, {\n pollIntervalMs: options.pollIntervalMs,\n enabled: options.enabled,\n });\n const [older, setOlder] = useState<{\n key: unknown;\n recordings: Recording[];\n nextBefore: { startedAt: string; id: string } | null;\n } | null>(null);\n const [loadingMore, setLoadingMore] = useState(false);\n // Older pages belong to the first page they continued; a new query starts over.\n const olderForThisList = older && older.key === load ? older : null;\n const recordings = useMemo(() => {\n const first = state.data?.recordings ?? [];\n if (!olderForThisList) return first;\n const seen = new Set(first.map((recording) => recording.id));\n return [\n ...first,\n ...olderForThisList.recordings.filter((recording) => !seen.has(recording.id)),\n ];\n }, [state.data, olderForThisList]);\n const anyProcessing = recordings.some(isProcessing);\n useRefreshWhile(\n options.pollIntervalMs === undefined &&\n (options.enabled ?? true) &&\n (anyProcessing || recordings.some((recording) => recording.state === \"capturing\")),\n state.refresh,\n anyProcessing ? PROCESSING_POLL_MS : CAPTURING_POLL_MS,\n );\n const nextBefore = olderForThisList\n ? olderForThisList.nextBefore\n : (state.data?.nextBefore ?? null);\n const loadMore = useCallback(async () => {\n if (!nextBefore || loadingMore) return;\n setLoadingMore(true);\n try {\n const page = await client.listRecordings(workspaceId, {\n ...(query ? { query } : {}),\n ...(externalRef ? { externalRef } : {}),\n ...(limit ? { limit } : {}),\n before: nextBefore,\n });\n setOlder((previous) => ({\n key: load,\n recordings: [\n ...(previous && previous.key === load ? previous.recordings : []),\n ...page.recordings,\n ],\n nextBefore: page.nextBefore,\n }));\n } finally {\n setLoadingMore(false);\n }\n }, [client, workspaceId, query, externalRef, limit, nextBefore, loadingMore, load]);\n return {\n recordings,\n loading: state.loading,\n error: state.error,\n refresh: state.refresh,\n hasMore: nextBefore !== null,\n loadingMore,\n loadMore,\n };\n}\n\nexport type UseRecordingOptions = RecordingsClientOverride & {\n enabled?: boolean;\n};\n\nexport type UseRecordingResult = {\n recording: Recording | null;\n versions: RecordingTranscriptVersion[];\n loading: boolean;\n error: Error | null;\n /** Transcription is still running; the hook polls until it is done. */\n processing: boolean;\n refresh: () => Promise<void>;\n update: (request: UpdateRecordingRequest) => Promise<Recording>;\n /** Transcribe again, optionally with another model, as a new version. */\n rerun: (transcription?: RecordingTranscriptionRequest) => Promise<RecordingTranscriptVersion>;\n setCurrentVersion: (versionId: string) => Promise<void>;\n remove: () => Promise<void>;\n};\n\n/**\n * One recording with its transcript versions. Polls while it is being\n * transcribed, and less often while it is still being recorded, here or on\n * another device, so a page showing it notices when the recording ends.\n */\nexport function useRecording(\n recordingId: string | null,\n options: UseRecordingOptions = {},\n): UseRecordingResult {\n const { client, workspaceId } = useEmbeddedRecordings(\n options,\n [\"getRecording\", \"listRecordingTranscriptVersions\"],\n \"useRecording\",\n );\n const load = useCallback(\n async (signal?: AbortSignal) => {\n if (!recordingId) return null;\n const [recording, versions] = await Promise.all([\n client.getRecording(workspaceId, recordingId, signal ? { signal } : {}),\n client.listRecordingTranscriptVersions(workspaceId, recordingId),\n ]);\n return { recording, versions };\n },\n [client, workspaceId, recordingId],\n );\n const enabled = (options.enabled ?? true) && recordingId !== null;\n const state = usePolledValue(load, { enabled });\n const recording = state.data?.recording ?? null;\n const versions = state.data?.versions ?? [];\n const nowProcessing =\n isProcessing(recording) ||\n versions.some((version) => version.state === \"queued\" || version.state === \"processing\");\n useRefreshWhile(\n enabled && (nowProcessing || recording?.state === \"capturing\"),\n state.refresh,\n nowProcessing ? PROCESSING_POLL_MS : CAPTURING_POLL_MS,\n );\n const refresh = state.refresh;\n const require = () => {\n if (!recordingId) throw new Error(\"No recording selected.\");\n return recordingId;\n };\n return {\n recording,\n versions,\n loading: state.loading,\n error: state.error,\n processing: nowProcessing,\n refresh,\n update: useCallback(\n async (request: UpdateRecordingRequest) => {\n const updated = await client.updateRecording(workspaceId, require(), request);\n await refresh();\n return updated;\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [client, workspaceId, recordingId, refresh],\n ),\n rerun: useCallback(\n async (transcription?: RecordingTranscriptionRequest) => {\n const version = await client.createRecordingTranscript(\n workspaceId,\n require(),\n transcription ? { transcription } : {},\n );\n await refresh();\n return version;\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [client, workspaceId, recordingId, refresh],\n ),\n setCurrentVersion: useCallback(\n async (versionId: string) => {\n await client.setCurrentRecordingTranscript(workspaceId, require(), versionId);\n await refresh();\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [client, workspaceId, recordingId, refresh],\n ),\n remove: useCallback(\n async () => {\n await client.deleteRecording(workspaceId, require());\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [client, workspaceId, recordingId],\n ),\n };\n}\n\nconst LIVE_POLL_MS = 2_000;\n\nexport type UseLiveTranscriptOptions = RecordingsClientOverride & {\n /** Default: on while a recording id is given. */\n enabled?: boolean;\n};\n\nexport type UseLiveTranscriptResult = {\n /** Finished live text from every track, in time order. */\n segments: RecordingLiveSegment[];\n /** A transcript is ready, so the preview is over. */\n ended: boolean;\n error: Error | null;\n};\n\n/**\n * The live transcript of a recording someone is capturing, as the recorder\n * saves it, for viewers on other devices. Polls every two seconds until the\n * transcript is ready. The device recording has it sooner in `useRecorder().live`.\n */\nexport function useLiveTranscript(\n recordingId: string | null,\n options: UseLiveTranscriptOptions = {},\n): UseLiveTranscriptResult {\n const { client, workspaceId } = useEmbeddedRecordings(\n options,\n [\"listRecordingLiveSegments\"],\n \"useLiveTranscript\",\n );\n const enabled = (options.enabled ?? true) && recordingId !== null;\n const [state, setState] = useState<UseLiveTranscriptResult & { recordingId: string | null }>({\n recordingId,\n segments: [],\n ended: false,\n error: null,\n });\n const current = state.recordingId === recordingId ? state : null;\n const ended = current?.ended ?? false;\n useEffect(() => {\n if (!enabled || !recordingId || ended) return;\n let cancelled = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let after = 0;\n let segments: RecordingLiveSegment[] = [];\n const read = async () => {\n try {\n const page = await client.listRecordingLiveSegments(workspaceId, recordingId, { after });\n if (cancelled) return;\n after = page.after;\n if (page.segments.length > 0) {\n segments = [...segments, ...page.segments].sort(\n (left, right) =>\n left.startMilliseconds - right.startMilliseconds || left.sequence - right.sequence,\n );\n }\n setState({\n recordingId,\n segments: page.ended ? [] : segments,\n ended: page.ended,\n error: null,\n });\n if (page.ended) return;\n } catch (error) {\n if (cancelled) return;\n setState((previous) => ({\n ...(previous.recordingId === recordingId ? previous : { segments: [], ended: false }),\n recordingId,\n error: error instanceof Error ? error : new Error(String(error)),\n }));\n }\n timer = setTimeout(() => void read(), LIVE_POLL_MS);\n };\n void read();\n return () => {\n cancelled = true;\n if (timer) clearTimeout(timer);\n };\n }, [client, workspaceId, recordingId, enabled, ended]);\n return {\n segments: current?.segments ?? [],\n ended,\n error: current?.error ?? null,\n };\n}\n\nexport type UseTranscriptOptions = RecordingsClientOverride & {\n /** A specific version; the current one by default. */\n versionId?: string;\n /** Change it to read again, for example when a new version completes. */\n refreshKey?: unknown;\n enabled?: boolean;\n};\n\nexport type UseTranscriptResult = {\n version: RecordingTranscriptVersion | null;\n speakers: RecordingSpeaker[];\n segments: RecordingTranscriptSegment[];\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n /** Name a speaker label after a person in the directory or with a plain name; null clears it. */\n nameSpeaker: (\n label: string,\n name: { personId: string } | { name: string } | null,\n ) => Promise<void>;\n /** Turn down a voice suggestion; that person is not suggested for this voice again. */\n rejectSuggestion: (label: string) => Promise<void>;\n /** Move one segment to another speaker label. */\n moveSegment: (segmentIndex: number, label: string) => Promise<void>;\n /** Correct one segment's text; null restores the original. */\n editSegment: (segmentIndex: number, text: string | null) => Promise<void>;\n};\n\nconst TRANSCRIPT_PAGE = 2_000;\n\n/** A whole transcript version with its speakers, and the edits people make to it. */\nexport function useTranscript(\n recordingId: string | null,\n options: UseTranscriptOptions = {},\n): UseTranscriptResult {\n const { client, workspaceId } = useEmbeddedRecordings(\n options,\n [\"getRecordingTranscript\", \"updateRecordingSpeakers\", \"updateRecordingSegments\"],\n \"useTranscript\",\n );\n const { versionId, refreshKey } = options;\n const load = useCallback(\n async (signal?: AbortSignal): Promise<RecordingTranscriptPage | null> => {\n void refreshKey;\n if (!recordingId) return null;\n let page = await client.getRecordingTranscript(workspaceId, recordingId, {\n ...(versionId ? { versionId } : {}),\n limit: TRANSCRIPT_PAGE,\n ...(signal ? { signal } : {}),\n });\n const segments = [...page.segments];\n while (page.nextAfter !== null) {\n page = await client.getRecordingTranscript(workspaceId, recordingId, {\n versionId: page.version.id,\n after: page.nextAfter,\n limit: TRANSCRIPT_PAGE,\n ...(signal ? { signal } : {}),\n });\n segments.push(...page.segments);\n }\n return { ...page, segments, nextAfter: null };\n },\n [client, workspaceId, recordingId, versionId, refreshKey],\n );\n const state = usePolledValue(load, {\n enabled: (options.enabled ?? true) && recordingId !== null,\n });\n // Edits answer with the new speakers or segments; keep them until the next read.\n const [local, setLocal] = useState<{\n base: unknown;\n speakers?: RecordingSpeaker[];\n segments?: Map<number, RecordingTranscriptSegment>;\n } | null>(null);\n const base = state.data;\n const overlay = local && local.base === base ? local : null;\n const speakers = overlay?.speakers ?? base?.speakers ?? [];\n const segments = useMemo(() => {\n const original = base?.segments ?? [];\n const changed = overlay?.segments;\n return changed ? original.map((segment) => changed.get(segment.index) ?? segment) : original;\n }, [base, overlay]);\n const versionFor = () => {\n if (!recordingId || !base) throw new Error(\"The transcript is not loaded yet.\");\n return { recordingId, versionId: base.version.id };\n };\n const applySpeakers = (next: RecordingSpeaker[]) =>\n setLocal((previous) => ({\n ...(previous && previous.base === base ? previous : {}),\n base,\n speakers: next,\n }));\n const applySegments = (next: RecordingTranscriptSegment[]) =>\n setLocal((previous) => {\n const kept = previous && previous.base === base ? previous : { base };\n const merged = new Map(kept.segments ?? []);\n for (const segment of next) merged.set(segment.index, segment);\n return { ...kept, base, segments: merged };\n });\n return {\n version: base?.version ?? null,\n speakers,\n segments,\n loading: state.loading,\n error: state.error,\n refresh: state.refresh,\n nameSpeaker: async (label, name) => {\n const target = versionFor();\n const result = await client.updateRecordingSpeakers(\n workspaceId,\n target.recordingId,\n {\n assignments: [\n name === null\n ? { label, personId: null, name: null }\n : \"personId\" in name\n ? { label, personId: name.personId }\n : { label, name: name.name },\n ],\n },\n { versionId: target.versionId },\n );\n applySpeakers(result.speakers);\n },\n rejectSuggestion: async (label) => {\n const target = versionFor();\n const result = await client.updateRecordingSpeakers(\n workspaceId,\n target.recordingId,\n { rejectSuggestions: [{ label }] },\n { versionId: target.versionId },\n );\n applySpeakers(result.speakers);\n },\n moveSegment: async (segmentIndex, label) => {\n const target = versionFor();\n const result = await client.updateRecordingSpeakers(\n workspaceId,\n target.recordingId,\n { segmentOverrides: [{ segmentIndex, label }] },\n { versionId: target.versionId },\n );\n applySpeakers(result.speakers);\n const moved = segments.find((segment) => segment.index === segmentIndex);\n if (moved) applySegments([{ ...moved, speakerLabel: label }]);\n },\n editSegment: async (segmentIndex, text) => {\n const target = versionFor();\n const result = await client.updateRecordingSegments(\n workspaceId,\n target.recordingId,\n { edits: [{ segmentIndex, text }] },\n { versionId: target.versionId },\n );\n applySegments(result.segments);\n },\n };\n}\n\n/** The organization's people directory, to name speakers with. */\nexport function useRecordingPeople(\n options: RecordingsClientOverride & {\n query?: string;\n enabled?: boolean;\n } = {},\n): {\n people: RecordingPerson[];\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n create: (request: CreateRecordingPersonRequest) => Promise<RecordingPerson>;\n /** Agree to have a person's voice remembered (see rememberRecordingPersonVoice). */\n rememberVoice: (\n personId: string,\n consent: RecordingVoiceprintConsent,\n ) => Promise<RecordingPerson>;\n /** Forget a person's voice and withdraw their agreement. */\n forgetVoice: (personId: string) => Promise<RecordingPerson>;\n} {\n const { client, workspaceId } = useEmbeddedRecordings(\n options,\n [\n \"listRecordingPeople\",\n \"createRecordingPerson\",\n \"rememberRecordingPersonVoice\",\n \"forgetRecordingPersonVoice\",\n ],\n \"useRecordingPeople\",\n );\n const query = options.query;\n const load = useCallback(\n async () => await client.listRecordingPeople(workspaceId, query ? { query } : {}),\n [client, workspaceId, query],\n );\n const state = usePolledValue(load, { enabled: options.enabled });\n const refresh = state.refresh;\n return {\n people: state.data ?? [],\n loading: state.loading,\n error: state.error,\n refresh,\n create: useCallback(\n async (request: CreateRecordingPersonRequest) => {\n const person = await client.createRecordingPerson(workspaceId, request);\n await refresh();\n return person;\n },\n [client, workspaceId, refresh],\n ),\n rememberVoice: useCallback(\n async (personId: string, consent: RecordingVoiceprintConsent) => {\n const person = await client.rememberRecordingPersonVoice(workspaceId, personId, {\n consent,\n });\n await refresh();\n return person;\n },\n [client, workspaceId, refresh],\n ),\n forgetVoice: useCallback(\n async (personId: string) => {\n const person = await client.forgetRecordingPersonVoice(workspaceId, personId);\n await refresh();\n return person;\n },\n [client, workspaceId, refresh],\n ),\n };\n}\n\n/**\n * Models this workspace offers, with capabilities, price and the default:\n * `models` make transcripts; `liveModels` stream the live transcript.\n */\nexport function useRecordingModels(\n options: RecordingsClientOverride & { enabled?: boolean } = {},\n): {\n models: ListRecordingModelsResponse[\"models\"];\n liveModels: ListRecordingModelsResponse[\"models\"];\n defaultModel: ListRecordingModelsResponse[\"default\"] | null;\n /** The deployment uses one model for every transcription; workspaces cannot pick. */\n pinned: boolean;\n /**\n * The workspace's meeting language (null detects it), or undefined until\n * the server says, or when it is too old to.\n */\n language: string | null | undefined;\n /**\n * Whether the workspace's recorders start with the live transcript on, or\n * undefined until the server says, or when it is too old to.\n */\n liveTranscript: boolean | undefined;\n loading: boolean;\n error: Error | null;\n} {\n const { client, workspaceId } = useEmbeddedRecordings(\n options,\n [\"listRecordingModels\"],\n \"useRecordingModels\",\n );\n const load = useCallback(\n async () => await client.listRecordingModels(workspaceId),\n [client, workspaceId],\n );\n const state = usePolledValue(load, { enabled: options.enabled });\n const all = state.data?.models;\n const models = useMemo(() => (all ?? []).filter((entry) => entry.capabilities.batch), [all]);\n const liveModels = useMemo(() => (all ?? []).filter((entry) => entry.capabilities.live), [all]);\n return {\n models,\n liveModels,\n defaultModel: state.data?.default ?? null,\n pinned: state.data?.pinned === true,\n language: state.data ? state.data.language : undefined,\n liveTranscript: state.data?.liveTranscript,\n loading: state.loading,\n error: state.error,\n };\n}\n\n// --- Notes -------------------------------------------------------------------\n\n/** How often an open meeting checks for notes someone else, or an agent, saved. */\nconst NOTES_POLL_MS = 15_000;\n\nexport type UseRecordingNotesOptions = RecordingsClientOverride & {\n enabled?: boolean;\n /** Check for notes saved elsewhere this often; default 15 seconds, 0 to never. */\n pollIntervalMs?: number;\n};\n\nexport type UseRecordingNotesResult = {\n /** What people jotted down while the meeting was recorded. */\n notepad: RecordingNote | null;\n /** The written-up summary, decisions and action items. */\n notes: RecordingNote | null;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n /**\n * Replace the notepad or the notes. The notes are saved against the revision\n * this hook last read, so a newer save made elsewhere fails with 409\n * `notes_changed` instead of being overwritten; the notepad, saved as people\n * type, always wins.\n */\n save: (kind: RecordingNoteKind, body: string) => Promise<RecordingNote>;\n};\n\n/** A meeting's notepad and notes, kept fresh while it is open. */\nexport function useRecordingNotes(\n recordingId: string | null,\n options: UseRecordingNotesOptions = {},\n): UseRecordingNotesResult {\n const { client, workspaceId } = useEmbeddedRecordings(\n options,\n [\"listRecordingNotes\", \"saveRecordingNote\"],\n \"useRecordingNotes\",\n );\n const load = useCallback(\n async () =>\n recordingId ? (await client.listRecordingNotes(workspaceId, recordingId)).notes : [],\n [client, workspaceId, recordingId],\n );\n const pollIntervalMs = options.pollIntervalMs ?? NOTES_POLL_MS;\n const state = usePolledValue(load, {\n enabled: (options.enabled ?? true) && recordingId !== null,\n ...(pollIntervalMs > 0 ? { pollIntervalMs } : {}),\n });\n const notes = state.data ?? [];\n const notepad = notes.find((note) => note.kind === \"notepad\") ?? null;\n const written = notes.find((note) => note.kind === \"notes\") ?? null;\n const writtenRevision = written?.revision ?? 0;\n const refresh = state.refresh;\n return {\n notepad,\n notes: written,\n loading: state.loading,\n error: state.error,\n refresh,\n save: useCallback(\n async (kind: RecordingNoteKind, body: string) => {\n if (!recordingId) throw new Error(\"No recording selected.\");\n const saved = await client.saveRecordingNote(workspaceId, recordingId, kind, {\n body,\n ...(kind === \"notes\" ? { expectedRevision: writtenRevision } : {}),\n });\n await refresh();\n return saved;\n },\n [client, workspaceId, recordingId, writtenRevision, refresh],\n ),\n };\n}\n"],"mappings":"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","names":["recording","versions","require","segments"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/app/components/session/subscription-account-indicator.tsx","../src/app/components/session/subscription-account.ts"],"sourcesContent":["// The session-header account control for every subscription provider: the\n// provider's mark opens one menu with the account the chat uses, its usage,\n// and the accounts that can serve the next turn. The control and its content\n// are provider-neutral (`subscription-account.ts`); only where the data comes\n// from differs. Codex still reads its session endpoint, which alone reports a\n// turn waiting for capacity and offers a live usage check.\nimport { useState } from \"react\";\nimport type {\n CodexAccount,\n CodexUsageMap,\n ModelAccountChoiceOption,\n SessionEvent,\n SessionModelAccountChoiceResponse,\n} from \"@opengeni/sdk\";\n\nimport { useCodexAccounts, type UseCodexAccountsResult } from \"../../../hooks/use-codex-accounts\";\nimport {\n useSessionModelAccount,\n type UseSessionModelAccountResult,\n} from \"../../../hooks/use-session-model-account\";\nimport { Skeleton } from \"../../../ui/skeleton\";\nimport { BillingClassMark } from \"../billing-class-mark\";\nimport {\n showsSubscriptionAccountMenu,\n subscriptionAccountMenuContent,\n subscriptionProviderPresentation,\n type SubscriptionAccount,\n type SubscriptionAccountState,\n type SubscriptionAccountUsage,\n} from \"./subscription-account\";\nimport { SubscriptionAccountMenu } from \"./subscription-account-menu\";\n\ntype IndicatorProps = {\n workspaceId: string;\n sessionId: string;\n /** The session's organization; scopes personal-account choices. */\n organizationId: string | null;\n /** The session model's subscription provider (`codex`, `claude`, `xai`). */\n provider: string;\n /** The newest started turn, to show the account that served it. */\n servingTurnId?: string | undefined;\n events?: SessionEvent[];\n};\n\nexport function SubscriptionAccountIndicator(props: IndicatorProps) {\n return props.provider === \"codex\" ? (\n <CodexAccountSource {...props} />\n ) : (\n <SharedAccountSource {...props} />\n );\n}\n\n/** Renders the neutral state; identical for every provider. */\nexport function SubscriptionAccountControl({\n state,\n onChoose,\n onOpenChange,\n}: {\n state: SubscriptionAccountState;\n onChoose: (accountId: string | null) => void;\n onOpenChange?: ((open: boolean) => void) | undefined;\n}) {\n const { name, billingClass } = subscriptionProviderPresentation(state.provider);\n if (state.loading) {\n return (\n <Skeleton\n role=\"status\"\n className=\"h-6 w-11 shrink-0 rounded-full\"\n aria-label={`Loading ${name} account`}\n />\n );\n }\n // Nothing to choose or show (the provider's accounts are not offered for\n // this chat): the provider's mark alone, as on any other subscription chat.\n if (!showsSubscriptionAccountMenu(state)) {\n return (\n <BillingClassMark\n billingClass={billingClass}\n className=\"size-3.5 shrink-0 text-fg-muted\"\n aria-label=\"\"\n />\n );\n }\n return (\n <SubscriptionAccountMenu\n {...subscriptionAccountMenuContent(state)}\n triggerMark={\n <BillingClassMark\n billingClass={billingClass}\n className=\"size-3.5 text-current\"\n aria-label=\"\"\n />\n }\n headerMark={<BillingClassMark billingClass={billingClass} className=\"size-4 text-current\" />}\n choosing={state.choosing}\n choosingTarget={state.choosingTarget}\n onChoose={onChoose}\n onOpenChange={onOpenChange}\n />\n );\n}\n\n// ── Shared subscription core (Claude, SuperGrok, …) ─────────────────────────\n\nexport function sharedAccount(option: ModelAccountChoiceOption): SubscriptionAccount {\n return {\n id: option.connectionId,\n label: option.label,\n email: option.accountEmail,\n plan: option.planType,\n source: option.personal ? \"personal\" : option.source,\n status: option.status,\n refusal: option.refusal,\n choosable: option.choosable,\n usage: option.usage,\n };\n}\n\n/** The shared subscription core's session choice as the neutral state. */\nexport function sharedAccountState(\n provider: string,\n account: Pick<\n UseSessionModelAccountResult,\n \"loading\" | \"choosing\" | \"choosingTarget\" | \"appliedTo\" | \"mutationError\"\n > & { choice: SessionModelAccountChoiceResponse | null },\n servingTurnId: string | undefined,\n): SubscriptionAccountState {\n const choice = account.choice;\n const options = (choice?.accounts ?? []).filter((each) => each.provider === provider);\n const binding =\n choice?.bindings?.find((each) => each.provider === provider) ??\n (choice?.binding?.provider === provider ? choice.binding : null);\n const explicit = binding?.choice === \"explicit\";\n const serving =\n choice?.serving &&\n choice.serving.turnId === servingTurnId &&\n choice.serving.provider === provider\n ? choice.serving\n : null;\n const currentId = serving ? serving.connectionId : binding?.connectionId;\n const current = currentId\n ? (options.find((each) => each.connectionId === currentId) ?? null)\n : null;\n return {\n provider,\n loading: account.loading && !choice,\n unavailable: !choice,\n accounts: options.map(sharedAccount),\n current: current ? sharedAccount(current) : null,\n currentHidden: !current && (explicit || serving !== null),\n serving: serving !== null,\n automatic: !explicit,\n chosenId: explicit ? (binding?.connectionId ?? null) : null,\n waiting: false,\n // Only the authorized stored reading; opening the menu never probes a provider.\n usageCheck: \"idle\",\n choosing: account.choosing,\n choosingTarget: account.choosingTarget,\n appliedTo: account.appliedTo,\n mutationError: account.mutationError?.message ?? null,\n };\n}\n\nfunction SharedAccountSource(props: IndicatorProps) {\n const { provider } = props;\n const account = useSessionModelAccount({\n workspaceId: props.workspaceId,\n sessionId: props.sessionId,\n provider,\n organizationId: props.organizationId,\n pollIntervalMs: 60_000,\n ...(props.events !== undefined ? { events: props.events } : {}),\n });\n const state = sharedAccountState(provider, account, props.servingTurnId);\n return (\n <SubscriptionAccountControl\n state={state}\n onChoose={(id) => {\n // After a failed read the selection is unknown, so Automatic is sent.\n if (\n !state.unavailable &&\n (id === null ? state.automatic : !state.automatic && state.chosenId === id)\n ) {\n return;\n }\n void account.choose(id);\n }}\n />\n );\n}\n\n// ── Codex ───────────────────────────────────────────────────────────────────\n\nconst AUTO = \"auto\";\n// Reopening the menu reuses live readings this recent instead of asking the\n// provider again; older ones stay on screen while the menu re-checks.\nconst LIVE_USAGE_REUSE_MS = 30_000;\n\nexport function codexUsage(\n account: CodexAccount,\n live: CodexUsageMap[string] | undefined,\n now = Date.now(),\n): SubscriptionAccountUsage | null {\n const window = (\n id: string,\n reading: CodexAccount[\"fiveHour\"],\n ): SubscriptionAccountUsage[\"windows\"] => {\n if (!reading) return [];\n const usedPercent =\n typeof reading.percent === \"number\"\n ? reading.percent\n : typeof reading.remaining === \"number\"\n ? 100 - reading.remaining\n : null;\n return [\n {\n id,\n usedPercent,\n resetsAt: reading.resetAt ?? null,\n status:\n usedPercent === null\n ? \"unknown\"\n : usedPercent >= 100\n ? \"exhausted\"\n : usedPercent >= 90\n ? \"warning\"\n : \"ok\",\n },\n ];\n };\n const windows = [\n ...window(\"five_hour\", account.fiveHour),\n ...window(\"seven_day\", account.weekly),\n ];\n // The endpoint reports a cooldown even after it ended; only a future one applies.\n const exhaustedUntil =\n account.exhaustedUntil && Date.parse(account.exhaustedUntil) > now\n ? account.exhaustedUntil\n : null;\n if (windows.length === 0 && !exhaustedUntil) return null;\n return {\n observedAt: live?.usage?.fetchedAt ?? account.usageCheckedAt ?? null,\n windows,\n exhaustedUntil,\n exhaustedKind: exhaustedUntil ? \"quota\" : null,\n };\n}\n\n/** The Codex session endpoint as the neutral state. */\nexport function codexAccountState(\n codex: Pick<\n UseCodexAccountsResult,\n | \"accounts\"\n | \"pinnedAccountId\"\n | \"currentSelection\"\n | \"currentAccount\"\n | \"switchAppliedTo\"\n | \"loading\"\n | \"error\"\n | \"liveUsage\"\n | \"liveUsageUpdatedAt\"\n | \"pinning\"\n | \"pinningTarget\"\n | \"mutationError\"\n >,\n check: { checking: boolean; checked: boolean; failed: boolean },\n): SubscriptionAccountState {\n // Live readings from an earlier check (this menu, another session's, or\n // Settings) stay visible while a new check runs instead of flashing away.\n const awaitingFirstUsage = check.checking && codex.liveUsageUpdatedAt === null;\n const selection = codex.currentSelection;\n const effective =\n (selection ? codex.currentAccount : null) ??\n codex.accounts.find(\n (account) => account.id === (selection ? selection.credentialId : codex.pinnedAccountId),\n ) ??\n null;\n // A live check that returned nothing for an account hides its older reading.\n const liveMissing = (id: string) => {\n const status = codex.liveUsage[id]?.status;\n return check.failed || (check.checked && !status) || status === \"error\" || status === \"no-data\";\n };\n const account = (each: CodexAccount): SubscriptionAccount => ({\n id: each.id,\n // The ChatGPT account id names an account only when nothing else does.\n label: each.label ?? (each.email || each.plan ? null : (each.chatgptAccountId ?? null)),\n email: each.email ?? null,\n plan: each.plan ?? null,\n source: each.source ?? null,\n status: each.status,\n refusal: null,\n choosable: true,\n usage: liveMissing(each.id) ? null : codexUsage(each, codex.liveUsage[each.id]),\n });\n return {\n provider: \"codex\",\n loading: codex.loading && !effective,\n unavailable: Boolean(codex.error),\n accounts: codex.accounts.map(account),\n current: effective ? account(effective) : null,\n currentHidden: !effective && Boolean(selection?.credentialId ?? codex.pinnedAccountId),\n serving: selection !== null,\n automatic: codex.pinnedAccountId === null,\n chosenId: codex.pinnedAccountId,\n waiting: selection?.waiting === true,\n usageCheck: awaitingFirstUsage\n ? \"checking\"\n : effective && liveMissing(effective.id)\n ? \"failed\"\n : \"idle\",\n choosing: codex.pinning,\n choosingTarget: codex.pinningTarget === AUTO ? null : (codex.pinningTarget ?? undefined),\n appliedTo: codex.switchAppliedTo,\n mutationError: codex.mutationError?.message ?? null,\n };\n}\n\nfunction CodexAccountSource(props: IndicatorProps) {\n const codex = useCodexAccounts({\n sessionId: props.sessionId,\n pollIntervalMs: 30_000,\n ...(props.events !== undefined ? { events: props.events } : {}),\n });\n const [checkingUsage, setCheckingUsage] = useState(false);\n const [usageChecked, setUsageChecked] = useState(false);\n const [usageCheckFailed, setUsageCheckFailed] = useState(false);\n const state = codexAccountState(codex, {\n checking: checkingUsage,\n checked: usageChecked,\n failed: usageCheckFailed,\n });\n const waiting = state.waiting;\n return (\n <SubscriptionAccountControl\n state={state}\n onChoose={(id) => {\n // Choosing again while a turn waits retries it on that account.\n // After a failed read the selection is unknown, so the choice is sent.\n if (codex.pinnedAccountId === id && !waiting && !state.unavailable) return;\n void codex.pin(id ?? AUTO);\n }}\n onOpenChange={(open) => {\n if (!open) return;\n setCheckingUsage(true);\n setUsageChecked(false);\n setUsageCheckFailed(false);\n void codex.refreshUsage({ maxAgeMs: LIVE_USAGE_REUSE_MS }).then(\n (ok) => {\n setUsageChecked(ok);\n setUsageCheckFailed(!ok);\n setCheckingUsage(false);\n },\n () => {\n setUsageCheckFailed(true);\n setCheckingUsage(false);\n },\n );\n }}\n />\n );\n}\n","// One provider-neutral shape for a chat's subscription account (Codex, Claude,\n// SuperGrok) and its projection onto the account menu. Data sources normalize\n// into `SubscriptionAccountState`; everything a person sees is decided here,\n// so every provider shows the same structure and copy. Only names, marks and\n// plan labels differ.\nimport type { ClientModel, ModelAccountChoiceRefusal } from \"@opengeni/sdk\";\nimport { isClaudeSubscriptionModelId } from \"@opengeni/contracts/claude-subscription-model-ids\";\nimport { connectedSubscriptionProvider } from \"../../../model-policy\";\nimport { isCodexProductModel } from \"../../lib/session-model\";\nimport type { BillingClass } from \"../billing-class-mark\";\nimport type {\n SubscriptionAccountMenuRow,\n SubscriptionAccountMenuUsage,\n SubscriptionAccountUsageWindow,\n} from \"./subscription-account-menu\";\n\nexport type SubscriptionAccountUsage = {\n /** When the reading was taken; null when unknown. */\n observedAt: string | null;\n windows: Array<{\n id: string;\n /** Null means unknown; values over 100 can represent overage. */\n usedPercent: number | null;\n resetsAt: string | null;\n status: \"ok\" | \"warning\" | \"exhausted\" | \"unknown\";\n }>;\n exhaustedUntil: string | null;\n exhaustedKind: \"quota\" | \"rate_limit\" | null;\n};\n\nexport type SubscriptionAccount = {\n id: string;\n label: string | null;\n email: string | null;\n plan: string | null;\n /** Who the account belongs to; null when the source does not say. */\n source: \"personal\" | \"workspace\" | \"organization\" | null;\n /** The provider's account status (`active`, `needs_relogin`, …). */\n status: string;\n refusal: ModelAccountChoiceRefusal | null;\n choosable: boolean;\n /** Undefined: not reported. Null: no reading yet. */\n usage: SubscriptionAccountUsage | null | undefined;\n};\n\nexport type SubscriptionAccountState = {\n /** `codex`, `claude`, `xai`, … */\n provider: string;\n /** True until the first read settles. */\n loading: boolean;\n /** The accounts could not be read. */\n unavailable: boolean;\n /** Accounts this person can pick for the next turn. */\n accounts: SubscriptionAccount[];\n /** The account the chat runs on (or will next), when this person can see it. */\n current: SubscriptionAccount | null;\n /** The chat runs on a chosen or serving account this person cannot see. */\n currentHidden: boolean;\n /** `current`/`currentHidden` is the account serving the chat's latest turn. */\n serving: boolean;\n /** Automatic selection, not a person's explicit choice. */\n automatic: boolean;\n /** The explicitly chosen account, when this person can see it. */\n chosenId: string | null;\n /** A turn waits for capacity on the current account. */\n waiting: boolean;\n /**\n * A live usage check, for sources that offer one: `checking` until its\n * first reading arrives, `failed` when it produced none for this account.\n */\n usageCheck: \"idle\" | \"checking\" | \"failed\";\n choosing: boolean;\n /** The in-flight target (`null` is automatic; `undefined` when idle). */\n choosingTarget: string | null | undefined;\n appliedTo: \"waiting_turn\" | \"next_turn\" | null;\n mutationError: string | null;\n};\n\nconst PROVIDER: Record<string, { name: string; billingClass: BillingClass }> = {\n codex: { name: \"Codex\", billingClass: \"codex_subscription\" },\n claude: { name: \"Claude\", billingClass: \"claude_subscription\" },\n xai: { name: \"SuperGrok\", billingClass: \"supergrok_subscription\" },\n};\n\nexport function subscriptionProviderPresentation(provider: string): {\n name: string;\n billingClass: BillingClass;\n} {\n return PROVIDER[provider] ?? { name: \"Subscription\", billingClass: \"external\" };\n}\n\n// Presentation labels only. Preserve every supplied window; never combine\n// family-specific, overage or partial windows into an account capacity score.\nconst WINDOW_LABEL: Record<string, string> = {\n // Neutral ids: they do not say how long the window is.\n primary: \"Primary\",\n secondary: \"Secondary\",\n five_hour: \"5h\",\n seven_day: \"Week\",\n seven_day_opus: \"Week · Opus\",\n seven_day_sonnet: \"Week · Sonnet\",\n overage: \"Overage\",\n billing: \"Billing\",\n};\n\nconst REFUSAL_COPY: Record<ModelAccountChoiceRefusal, string> = {\n inactive: \"Unavailable\",\n personal_not_allowed: \"Turned off here\",\n personal_not_owner_work: \"Not available for this chat\",\n session_has_no_owner: \"Needs an owner\",\n};\n\nconst STATUS_COPY: Record<string, string> = {\n needs_relogin: \"Needs reconnect\",\n error: \"Error\",\n disabled: \"Disabled\",\n revoked: \"Revoked\",\n expired: \"Expired\",\n suspended: \"Suspended\",\n paused: \"Paused\",\n inactive: \"Inactive\",\n limit_reached: \"Limit reached\",\n};\n\nfunction time(value: string | null): string | null {\n if (!value || !Number.isFinite(Date.parse(value))) return null;\n return new Date(value).toLocaleString(undefined, {\n month: \"short\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n });\n}\n\nexport function accountLabel(account: SubscriptionAccount): string {\n return account.label ?? account.email ?? account.plan ?? \"Account\";\n}\n\nexport function accountStatus(account: SubscriptionAccount): string | null {\n // Inactive is a broad refusal; retain the actual status when it explains why.\n if (account.refusal && account.refusal !== \"inactive\") return REFUSAL_COPY[account.refusal];\n if (account.status !== \"active\") return STATUS_COPY[account.status] ?? account.status;\n return account.refusal ? REFUSAL_COPY[account.refusal] : null;\n}\n\nfunction accountSource(account: SubscriptionAccount): string | null {\n return account.source === \"personal\"\n ? \"Your account\"\n : account.source === \"workspace\"\n ? \"This workspace\"\n : account.source === \"organization\"\n ? \"Organization\"\n : null;\n}\n\nfunction windowLabel(id: string): string {\n return WINDOW_LABEL[id] ?? id;\n}\n\n/** The reading as usage rows: percentage used, with when each window resets. */\nexport function subscriptionAccountUsage(\n usage: SubscriptionAccountUsage | null | undefined,\n now = Date.now(),\n): {\n windows?: SubscriptionAccountUsageWindow[];\n message?: string;\n note?: string;\n summary?: string;\n} {\n if (!usage) return { message: \"No usage reading yet\" };\n const observed = time(usage.observedAt);\n const windows = usage.windows.map((window) => {\n const reset = time(window.resetsAt);\n const past = reset !== null && Date.parse(window.resetsAt!) <= now;\n return {\n label: windowLabel(window.id),\n usedPercent: window.usedPercent,\n detail: [\n window.status === \"unknown\"\n ? \"Status unknown\"\n : window.status === \"warning\"\n ? \"Near its limit\"\n : window.status === \"exhausted\"\n ? \"Limit reached\"\n : null,\n past ? \"Reset passed; usage may be outdated\" : reset ? `Resets ${reset}` : null,\n ]\n .filter(Boolean)\n .join(\" · \"),\n };\n });\n const exhaustedTime = time(usage.exhaustedUntil);\n // A limit whose end has passed no longer applies.\n const exhausted =\n usage.exhaustedKind !== null &&\n !(usage.exhaustedUntil && Date.parse(usage.exhaustedUntil) <= now);\n return {\n windows,\n ...(windows.length === 0\n ? {\n message: exhausted\n ? `Limit reached${exhaustedTime ? ` until ${exhaustedTime}` : \"\"}`\n : \"No usage reading yet\",\n }\n : {}),\n ...(observed ? { note: `Updated ${observed}` } : {}),\n ...(windows.length > 0\n ? {\n summary: `${windows\n .map(\n (window) =>\n `${window.label} ${window.usedPercent === null ? \"unknown\" : `${Math.round(window.usedPercent)}%`}`,\n )\n .join(\" · \")} used`,\n }\n : {}),\n };\n}\n\nfunction nearLimit(usage: SubscriptionAccountUsage | null | undefined): boolean {\n return (usage?.windows ?? []).some(\n (window) =>\n window.status === \"warning\" ||\n window.status === \"exhausted\" ||\n (window.usedPercent !== null && window.usedPercent >= 90),\n );\n}\n\n/** The most-used window with a known reading: the one that runs out first. */\nfunction tightestWindow(\n windows: SubscriptionAccountUsageWindow[] | undefined,\n): { label: string; usedPercent: number } | undefined {\n let tightest: { label: string; usedPercent: number } | undefined;\n for (const window of windows ?? []) {\n if (window.usedPercent === null || !Number.isFinite(window.usedPercent)) continue;\n if (!tightest || window.usedPercent > tightest.usedPercent) {\n tightest = { label: window.label, usedPercent: window.usedPercent };\n }\n }\n return tightest;\n}\n\n/**\n * Whether there is anything to show or choose. A chat whose provider offers\n * no accounts to this person, with nothing chosen, serving or waiting, shows\n * the provider's mark alone instead of an empty menu.\n */\nexport function showsSubscriptionAccountMenu(state: SubscriptionAccountState): boolean {\n return (\n state.unavailable ||\n state.accounts.length > 0 ||\n state.current !== null ||\n state.currentHidden ||\n state.waiting ||\n !state.automatic\n );\n}\n\n/**\n * The subscription whose accounts a chat's header offers, or null for a chat\n * that does not run on a subscription. Codex product models are Codex\n * subscriptions even before the catalog lists them, and so are Claude\n * subscription model ids. The workspace catalog leaves `credentialSource`\n * out, so its public provider id and rail decide for the rest.\n */\nexport function subscriptionAccountProvider(\n modelId: string,\n model: Pick<ClientModel, \"id\" | \"provider\" | \"source\" | \"credentialSource\"> | null | undefined,\n): string | null {\n if (isCodexProductModel(modelId)) return \"codex\";\n if (isClaudeSubscriptionModelId(modelId)) return \"claude\";\n return model ? connectedSubscriptionProvider(model) : null;\n}\n\n/** Everything the account menu shows, from the neutral state. */\nexport function subscriptionAccountMenuContent(state: SubscriptionAccountState) {\n const { name } = subscriptionProviderPresentation(state.provider);\n const current = state.current;\n // A failed read does not know the selection; never claim Automatic for it.\n const unknown = state.unavailable && !current && !state.currentHidden;\n const displayName = current\n ? accountLabel(current)\n : state.currentHidden\n ? \"Account unavailable\"\n : unknown\n ? \"Accounts unavailable\"\n : \"Automatic\";\n const status = current ? accountStatus(current) : null;\n const selectionLabel = state.waiting\n ? \"Limit reached\"\n : state.serving && (current || state.currentHidden)\n ? \"Current account\"\n : !state.automatic && !unknown && (!current || current.id === state.chosenId)\n ? \"Chosen account\"\n : current\n ? \"Current account\"\n : \"Account selection\";\n const usageNearLimit = nearLimit(current?.usage);\n const tone: \"ok\" | \"warn\" | \"bad\" =\n current?.status === \"needs_relogin\" || current?.status === \"error\"\n ? \"bad\"\n : status || state.waiting || usageNearLimit\n ? \"warn\"\n : \"ok\";\n const usage: SubscriptionAccountMenuUsage = !current\n ? {\n message: state.currentHidden\n ? \"Account usage hidden\"\n : unknown\n ? \"Usage unavailable\"\n : \"Choose an account to see usage\",\n }\n : state.usageCheck === \"checking\"\n ? { checking: true }\n : state.usageCheck === \"failed\"\n ? { unavailable: true }\n : subscriptionAccountUsage(current.usage);\n const accounts: SubscriptionAccountMenuRow[] = state.accounts.map((account) => {\n // The current account's usage is already shown above the list.\n const rowUsage =\n account.id === current?.id || state.usageCheck === \"checking\"\n ? undefined\n : subscriptionAccountUsage(account.usage);\n return {\n id: account.id,\n label: accountLabel(account),\n plan: account.plan,\n status: accountStatus(account),\n detail: [\n accountLabel(account),\n account.email,\n account.plan,\n accountSource(account),\n accountStatus(account),\n ]\n .filter(Boolean)\n .join(\" · \"),\n personal: account.source === \"personal\",\n disabled: !account.choosable,\n usageSummary: rowUsage?.summary,\n usageBar: rowUsage?.summary ? tightestWindow(rowUsage.windows) : undefined,\n };\n });\n return {\n ariaLabel: [\n `${name} account`,\n displayName,\n state.waiting ? \"Limit reached\" : (status ?? (usageNearLimit ? \"Near its limit\" : null)),\n ]\n .filter(Boolean)\n .join(\" · \"),\n selectionLabel,\n displayName,\n identity: current?.email && current.email !== displayName ? current.email : null,\n metadata: current\n ? [current.plan, accountSource(current), status].filter(Boolean).join(\" · \") ||\n `${name} subscription`\n : `${name} subscription`,\n tone,\n usage,\n accounts,\n selectedId: state.automatic || unknown ? null : state.chosenId,\n automaticSelected: state.automatic && !unknown,\n actionLabel: state.waiting ? \"Retry with\" : \"Use for next turn\",\n automaticLabel: \"Automatic\",\n emptyMessage: state.unavailable ? \"Accounts unavailable.\" : \"No accounts available.\",\n error: state.mutationError ? `Couldn't switch: ${state.mutationError}` : null,\n note:\n state.appliedTo === \"waiting_turn\"\n ? \"Selection saved. Capacity is being rechecked.\"\n : state.appliedTo === \"next_turn\"\n ? \"Selection saved for the next turn.\"\n : state.waiting\n ? \"Changing accounts retries the waiting turn.\"\n : \"Applies next turn. The current turn keeps its account.\",\n };\n}\n"],"mappings":"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","names":["account"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/ui/usage-meter.tsx"],"sourcesContent":["import { CircleAlertIcon, RefreshCwIcon } from \"lucide-react\";\nimport type { ReactNode } from \"react\";\n\nimport { DisabledReason } from \"./disabled-reason\";\nimport {\n type DateInput,\n formatAbsoluteTime,\n formatShortTime,\n inSentence,\n toDate,\n useMinuteNow,\n} from \"./relative-time\";\nimport { cn } from \"../lib/cn\";\n\n/* ----------------------------------------------------------------------------\n UsageMeter (design brief 7.20) - remaining quota at a glance and in detail.\n\n Labels are full words (\"Weekly\", \"5-hour\"), never \"Wk\" or \"5h\". Color is\n quiet until it matters: a status tone only below 10% left. Reset times are\n passed in already formatted (\"Mon 28 Sep, 09:00\"); the relative \"Checked\n just now\" line comes from the shared RelativeTime helper.\n\n Three looks, same data:\n - \"bar\" A. 4px bar, \"22% left\" and the reset time. In a row the bar\n drops away and it reads as text: bar in the sheet, text in the row.\n - \"text\" B. \"Weekly 22% left\", no bar. The quietest.\n - \"ring\" C. A small ring per window. Compact, harder to compare.\n Each has two densities: \"full\" (account sheet) and \"compact\" (a row).\n -------------------------------------------------------------------------- */\n\nexport type UsageMeterVariant = \"bar\" | \"text\" | \"ring\";\nexport type UsageMeterDensity = \"full\" | \"compact\";\nexport type UsageLevel = \"healthy\" | \"low\" | \"exhausted\" | \"unknown\";\n\n/** Below this share left, the meter takes the danger tone. */\nexport const USAGE_LOW_THRESHOLD = 10;\n\n/**\n * The level for a reading. `percent` is what the meter measures: the share\n * left (default) or the share used (machines).\n */\nexport function usageLevel(\n percent: number | null | undefined,\n measure: \"left\" | \"used\" = \"left\",\n lowAt: number = USAGE_LOW_THRESHOLD,\n): UsageLevel {\n if (percent === null || percent === undefined || Number.isNaN(percent)) return \"unknown\";\n const left = measure === \"left\" ? percent : 100 - percent;\n if (left <= 0) return \"exhausted\";\n if (left < lowAt) return \"low\";\n return \"healthy\";\n}\n\n/** Clamps to 0-100 and rounds, so \"21.6\" never shows as \"21.6% left\". */\nexport function clampPercent(percent: number): number {\n return Math.round(Math.min(100, Math.max(0, percent)));\n}\n\n/** The short value text: \"22% left\", \"Limit reached\", \"Not reported yet\". */\nexport function usageValueText(\n percent: number | null | undefined,\n measure: \"left\" | \"used\" = \"left\",\n lowAt: number = USAGE_LOW_THRESHOLD,\n): string {\n const level = usageLevel(percent, measure, lowAt);\n if (level === \"unknown\") return \"Not reported yet\";\n if (level === \"exhausted\") return \"Limit reached\";\n if (percent! > 0 && percent! < 1) return `<1% ${measure}`;\n return `${clampPercent(percent as number)}% ${measure}`;\n}\n\n/**\n * The reset time as it reads after \"Resets\": \"Mon 28 Sep, 09:00\" stays, but\n * \"Today, 17:10\" becomes \"today, 17:10\" mid-sentence.\n */\nexport function resetPhrase(resetsLabel: string): string {\n return /^(Today|Tomorrow|Tonight)\\b/.test(resetsLabel)\n ? resetsLabel.charAt(0).toLowerCase() + resetsLabel.slice(1)\n : resetsLabel;\n}\n\n/** The sentence a screen reader hears for one meter. */\nexport function usageAccessibleText({\n label,\n percent,\n measure = \"left\",\n valueLabel,\n resetsLabel,\n lowAt,\n}: {\n label: string;\n percent: number | null | undefined;\n measure?: \"left\" | \"used\" | undefined;\n valueLabel?: string | undefined;\n resetsLabel?: string | undefined;\n lowAt?: number | undefined;\n}): string {\n const value = valueLabel ?? usageValueText(percent, measure, lowAt);\n const reset = resetsLabel ? `, resets ${resetPhrase(resetsLabel)}` : \"\";\n return `${label}: ${value}${reset}`;\n}\n\nconst LEVEL_FILL: Record<UsageLevel, string> = {\n healthy: \"bg-brand\",\n low: \"bg-danger\",\n exhausted: \"bg-danger\",\n unknown: \"bg-transparent\",\n};\n\nconst LEVEL_STROKE: Record<UsageLevel, string> = {\n healthy: \"text-brand\",\n low: \"text-danger\",\n exhausted: \"text-danger\",\n unknown: \"text-transparent\",\n};\n\nconst LEVEL_VALUE_TEXT: Record<UsageLevel, string> = {\n healthy: \"text-fg-muted\",\n low: \"text-danger\",\n exhausted: \"text-danger\",\n unknown: \"text-fg-subtle\",\n};\n\nexport interface UsageMeterProps {\n /** \"Weekly\", \"5-hour\", \"Memory\". Never abbreviated. */\n label: string;\n /** 0-100, or null when the provider hasn't reported a reading. */\n percent: number | null;\n /** What `percent` measures. Quotas count what's left; machines count what's used. */\n measure?: \"left\" | \"used\" | undefined;\n /** Overrides the value text, for example \"5.1 of 16 GB\". */\n valueLabel?: string | undefined;\n /** Explicit provider rejection, independent of a missing or approximate percentage. */\n limitReached?: boolean | undefined;\n /** Formatted reset time, \"Mon 28 Sep, 09:00\". */\n resetsLabel?: string | undefined;\n /** A (bar, default), B (text) or C (ring). */\n variant?: UsageMeterVariant | undefined;\n /** \"full\" in a sheet, \"compact\" in a row. */\n density?: UsageMeterDensity | undefined;\n /** Share left below which the meter turns red. Default 10. */\n lowAt?: number | undefined;\n loading?: boolean | undefined;\n className?: string | undefined;\n}\n\n/** One quota window. */\nexport function UsageMeter({\n label,\n percent,\n measure = \"left\",\n valueLabel,\n limitReached = false,\n resetsLabel,\n variant = \"bar\",\n density = \"full\",\n lowAt = USAGE_LOW_THRESHOLD,\n loading = false,\n className,\n}: UsageMeterProps) {\n const level = limitReached ? \"exhausted\" : usageLevel(percent, measure, lowAt);\n const value =\n valueLabel ?? (limitReached ? \"Limit reached\" : usageValueText(percent, measure, lowAt));\n const hasPercent = percent !== null && Number.isFinite(percent);\n const shown = level === \"unknown\" ? 0 : clampPercent(percent as number);\n const fill = level === \"exhausted\" ? 0 : shown;\n const meterProps =\n loading || !hasPercent\n ? { role: \"group\" as const, \"aria-label\": `${label} usage` }\n : {\n role: \"meter\" as const,\n \"aria-label\": `${label} usage`,\n \"aria-valuemin\": 0,\n \"aria-valuemax\": 100,\n \"aria-valuenow\": Math.min(100, Math.max(0, percent!)),\n \"aria-valuetext\": usageAccessibleText({\n label,\n percent,\n measure,\n valueLabel: value,\n resetsLabel,\n lowAt,\n }),\n };\n const percentDisplay = hasPercent && percent! > 0 && percent! < 1 ? \"<1\" : String(shown);\n const parts = { label, value, level, fill, resetsLabel, loading, hasPercent, percentDisplay };\n const Root = density === \"compact\" ? \"span\" : \"div\";\n\n return (\n <Root\n data-slot=\"usage-meter\"\n data-level={loading ? \"loading\" : level}\n data-variant={variant}\n aria-busy={loading || undefined}\n {...meterProps}\n className={cn(\"min-w-0\", density === \"compact\" && \"inline-flex max-w-full\", className)}\n >\n {variant === \"bar\" ? (\n density === \"full\" ? (\n <BarFull {...parts} />\n ) : (\n <TextCompact {...parts} />\n )\n ) : variant === \"text\" ? (\n density === \"full\" ? (\n <TextFull {...parts} />\n ) : (\n <TextCompact {...parts} />\n )\n ) : density === \"full\" ? (\n <RingFull {...parts} />\n ) : (\n <RingCompact {...parts} />\n )}\n </Root>\n );\n}\n\n/**\n * The usage readout at the end of an account row: \"78% left this week\" and a\n * 64px bar, right-aligned so it sits against the row's chevron, and under it\n * when the limits reset: \"Resets Thu 09:00 · 5-hour 14:20\". Without a reading\n * it says why in words (\"No usage yet\"). Where the row folds its facts into\n * the meta line (narrow lists), only the words stay.\n */\nexport function UsageReadout({\n percent,\n window: windowLabel,\n resets = NO_RESETS,\n loading = false,\n fallback = \"No usage yet\",\n limitReached = false,\n now: fixedNow,\n className,\n}: {\n /** Share left, 0-100, or null when there is no reading. */\n percent: number | null;\n /** How the window reads after \"left\": \"this week\", \"this period\". */\n window: string;\n /**\n * When the account's limits reset, the shown window's first (no label),\n * then any other window by name. Times already past are left out.\n */\n resets?: readonly UsageReset[] | undefined;\n loading?: boolean | undefined;\n /** Words for a missing reading: \"No usage yet\", \"Usage unavailable\". */\n fallback?: string | undefined;\n limitReached?: boolean | undefined;\n /** The clock reset times are read against. Defaults to the shared minute clock. */\n now?: number | undefined;\n className?: string | undefined;\n}) {\n const level = limitReached ? \"exhausted\" : usageLevel(percent);\n const minuteNow = useMinuteNow();\n const now = fixedNow ?? minuteNow;\n if (loading) {\n return (\n <span\n data-slot=\"usage-readout\"\n aria-busy=\"true\"\n className={cn(\"inline-flex items-center justify-end gap-3\", className)}\n >\n <ValueSkeleton className=\"w-24\" />\n <span\n aria-hidden=\"true\"\n className=\"block h-1 w-16 rounded-full bg-surface-3 motion-safe:animate-pulse @max-[639px]/list:hidden\"\n />\n </span>\n );\n }\n if (level === \"unknown\") {\n return (\n <span data-slot=\"usage-readout\" className={cn(\"text-xs text-fg-subtle\", className)}>\n {fallback}\n </span>\n );\n }\n const shown = percent === null ? 0 : clampPercent(percent);\n const text =\n level === \"exhausted\" ? \"Limit reached\" : `${usageValueText(percent)} ${windowLabel}`;\n const upcoming = resets.filter((reset) => toDate(reset.at).getTime() > now);\n const resetLong = upcoming.length\n ? upcoming\n .map((reset, index) => {\n const at = inSentence(formatAbsoluteTime(reset.at, { now }));\n if (!reset.label) return `${index === 0 ? \"Resets\" : \"resets\"} ${at}`;\n return `${reset.label} resets ${at}`;\n })\n .join(\"; \")\n : null;\n const resetShort = upcoming.length\n ? upcoming\n .map((reset, index) => {\n const at = formatShortTime(reset.at, { now });\n if (!reset.label) return `Resets ${at}`;\n return index === 0 ? `${reset.label} resets ${at}` : `${reset.label} ${at}`;\n })\n .join(\" · \")\n : null;\n const meterProps =\n percent === null\n ? { role: \"group\" as const }\n : {\n role: \"meter\" as const,\n \"aria-valuemin\": 0,\n \"aria-valuemax\": 100,\n \"aria-valuenow\": shown,\n \"aria-valuetext\": `${text}${resetLong ? `. ${resetLong}` : \"\"}`,\n };\n return (\n <span\n data-slot=\"usage-readout\"\n aria-label={`Usage ${windowLabel}`}\n {...meterProps}\n title={resetLong ?? undefined}\n className={cn(\"inline-flex max-w-full min-w-0 flex-col items-end\", className)}\n >\n <span className=\"inline-flex max-w-full min-w-0 items-center justify-end gap-3\">\n <span\n className={cn(\n \"min-w-0 truncate text-xs whitespace-nowrap tabular-nums\",\n LEVEL_VALUE_TEXT[level],\n level !== \"healthy\" && \"font-medium\",\n )}\n >\n {text}\n </span>\n <Track\n level={level}\n fill={level === \"exhausted\" ? 0 : shown}\n className=\"w-16 shrink-0 @max-[639px]/list:hidden\"\n />\n </span>\n {resetShort ? (\n <span\n data-slot=\"usage-readout-resets\"\n aria-hidden=\"true\"\n className={cn(\n \"max-w-full truncate text-2xs leading-4 whitespace-nowrap tabular-nums @max-[639px]/list:hidden\",\n level === \"exhausted\" ? \"text-fg-muted\" : \"text-fg-subtle\",\n )}\n >\n {resetShort}\n </span>\n ) : null}\n </span>\n );\n}\n\n/** When one quota window resets. Without a label it is the window the readout shows. */\nexport interface UsageReset {\n label?: string | undefined;\n at: DateInput;\n}\n\nconst NO_RESETS: readonly UsageReset[] = [];\n\n/**\n * A readout's resets from an account's windows: the shown window first, then\n * the others that report a reset, in their given order. A window resetting\n * in the same minute as an earlier one adds nothing and is left out.\n */\nexport function usageResets(readings: readonly UsageWindowReading[], shown: string): UsageReset[] {\n const first = readings.find((reading) => reading.label === shown);\n const all: UsageReset[] = [\n ...(first?.resetsAt !== undefined ? [{ at: first.resetsAt }] : []),\n ...readings\n .filter((reading) => reading !== first && reading.resetsAt !== undefined)\n .map((reading) => ({ label: reading.label, at: reading.resetsAt! })),\n ];\n const minutes = new Set<number>();\n return all.filter((reset) => {\n const minute = Math.floor(toDate(reset.at).getTime() / 60_000);\n if (minutes.has(minute)) return false;\n minutes.add(minute);\n return true;\n });\n}\n\ninterface Parts {\n hasPercent: boolean;\n percentDisplay: string;\n label: string;\n value: string;\n level: UsageLevel;\n fill: number;\n resetsLabel?: string | undefined;\n loading: boolean;\n}\n\nfunction ValueSkeleton({ className }: { className?: string }) {\n return (\n <span\n aria-hidden=\"true\"\n className={cn(\n \"inline-block h-2.5 w-14 rounded-full bg-surface-3 motion-safe:animate-pulse\",\n className,\n )}\n />\n );\n}\n\nfunction ResetLine({ level, resetsLabel }: { level: UsageLevel; resetsLabel?: string }) {\n if (!resetsLabel) return null;\n return (\n <span className={cn(level === \"exhausted\" ? \"text-fg\" : \"text-fg-subtle\")}>\n Resets {resetPhrase(resetsLabel)}\n </span>\n );\n}\n\nfunction Track({\n level,\n fill,\n className,\n}: {\n level: UsageLevel;\n fill: number;\n className?: string | undefined;\n}) {\n return (\n <span\n aria-hidden=\"true\"\n className={cn(\n \"relative block h-1 overflow-hidden rounded-full\",\n level === \"exhausted\" ? \"bg-danger/15\" : \"bg-surface-3\",\n className,\n )}\n >\n <span\n className={cn(\"absolute inset-y-0 left-0 rounded-full\", LEVEL_FILL[level])}\n style={{ width: `${fill}%` }}\n />\n </span>\n );\n}\n\n/* A: bar -------------------------------------------------------------------- */\n\nfunction BarFull({ label, value, level, fill, resetsLabel, loading }: Parts) {\n return (\n <div className=\"flex min-w-0 flex-col gap-2\">\n <div className=\"flex min-w-0 items-baseline justify-between gap-3\">\n <span className=\"min-w-0 truncate text-sm font-medium text-fg\">{label}</span>\n {loading ? (\n <ValueSkeleton />\n ) : (\n <span\n className={cn(\n \"shrink-0 text-sm whitespace-nowrap tabular-nums\",\n LEVEL_VALUE_TEXT[level],\n level !== \"healthy\" && level !== \"unknown\" && \"font-medium\",\n )}\n >\n {value}\n </span>\n )}\n </div>\n {loading ? (\n <span\n aria-hidden=\"true\"\n className=\"block h-1 rounded-full bg-surface-3 motion-safe:animate-pulse\"\n />\n ) : (\n <Track level={level} fill={fill} />\n )}\n {loading ? (\n <span\n aria-hidden=\"true\"\n className=\"block h-4.5 w-32 rounded bg-surface-2 motion-safe:animate-pulse\"\n />\n ) : resetsLabel ? (\n <p className=\"text-xs leading-4.5\">\n <ResetLine level={level} resetsLabel={resetsLabel} />\n </p>\n ) : null}\n </div>\n );\n}\n\n/* B: text ------------------------------------------------------------------- */\n\nfunction TextFull({ label, value, level, resetsLabel, loading }: Parts) {\n return (\n <div className=\"flex min-w-0 items-start justify-between gap-4\">\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-fg\">{label}</p>\n {resetsLabel && !loading ? (\n <p className=\"mt-0.5 text-xs leading-4.5\">\n <ResetLine level={level} resetsLabel={resetsLabel} />\n </p>\n ) : null}\n </div>\n {loading ? (\n <ValueSkeleton className=\"mt-1.5\" />\n ) : (\n <span\n className={cn(\n \"inline-flex shrink-0 items-center gap-1.5 text-sm whitespace-nowrap tabular-nums\",\n level === \"healthy\" ? \"text-fg\" : LEVEL_VALUE_TEXT[level],\n level !== \"unknown\" && \"font-medium\",\n )}\n >\n {level === \"low\" || level === \"exhausted\" ? (\n <span aria-hidden=\"true\" className=\"size-1.5 rounded-full bg-danger\" />\n ) : null}\n {value}\n </span>\n )}\n </div>\n );\n}\n\nfunction TextCompact({ label, value, level, loading }: Parts) {\n return (\n <span className=\"inline-flex max-w-full min-w-0 items-center gap-1 text-xs leading-4 whitespace-nowrap\">\n <span className=\"text-fg-subtle\">{label}</span>\n {loading ? (\n <ValueSkeleton className=\"w-10\" />\n ) : (\n <span\n className={cn(\n \"tabular-nums\",\n LEVEL_VALUE_TEXT[level],\n level !== \"healthy\" && \"font-medium\",\n )}\n >\n {value}\n </span>\n )}\n </span>\n );\n}\n\n/* C: ring ------------------------------------------------------------------- */\n\nfunction Ring({\n level,\n fill,\n size,\n loading,\n children,\n}: {\n level: UsageLevel;\n fill: number;\n size: number;\n loading: boolean;\n children?: ReactNode | undefined;\n}) {\n const stroke = size >= 32 ? 3 : 2.5;\n const radius = (size - stroke) / 2;\n return (\n <span\n aria-hidden=\"true\"\n className={cn(\n \"relative inline-grid shrink-0 place-items-center\",\n loading && \"motion-safe:animate-pulse\",\n )}\n style={{ width: size, height: size }}\n >\n <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`} className=\"-rotate-90\">\n <circle\n cx={size / 2}\n cy={size / 2}\n r={radius}\n fill=\"none\"\n strokeWidth={stroke}\n className={level === \"exhausted\" ? \"stroke-danger/20\" : \"stroke-surface-3\"}\n />\n {!loading && fill > 0 ? (\n <circle\n cx={size / 2}\n cy={size / 2}\n r={radius}\n fill=\"none\"\n strokeWidth={stroke}\n strokeLinecap=\"round\"\n pathLength={100}\n strokeDasharray={`${fill} 100`}\n className={cn(\"stroke-current\", LEVEL_STROKE[level])}\n />\n ) : null}\n </svg>\n {children ? (\n <span className=\"absolute inset-0 grid place-items-center\">{children}</span>\n ) : null}\n </span>\n );\n}\n\nfunction RingFull({\n label,\n value,\n level,\n fill,\n resetsLabel,\n loading,\n hasPercent,\n percentDisplay,\n}: Parts) {\n const center =\n !hasPercent || loading ? null : (\n <span\n className={cn(\n \"text-2xs font-semibold tabular-nums\",\n level === \"healthy\" ? \"text-fg\" : \"text-danger\",\n )}\n >\n {percentDisplay}%\n </span>\n );\n return (\n <div className=\"flex min-w-0 items-center gap-3\">\n <Ring level={level} fill={fill} size={44} loading={loading}>\n {center}\n </Ring>\n <div className=\"min-w-0 text-xs leading-4.5\">\n <p className=\"truncate text-sm leading-5 font-medium text-fg\">{label}</p>\n {loading ? (\n <ValueSkeleton className=\"mt-1\" />\n ) : (\n <>\n <p className={cn(LEVEL_VALUE_TEXT[level], level !== \"healthy\" && \"font-medium\")}>\n {value}\n </p>\n {resetsLabel ? (\n <p>\n <ResetLine level={level} resetsLabel={resetsLabel} />\n </p>\n ) : null}\n </>\n )}\n </div>\n </div>\n );\n}\n\nfunction RingCompact({ label, value, level, fill, loading }: Parts) {\n return (\n <span className=\"inline-flex max-w-full min-w-0 items-center gap-1.5 text-xs leading-4 whitespace-nowrap\">\n <Ring level={level} fill={fill} size={14} loading={loading} />\n <span className=\"text-fg-subtle\">{label}</span>\n {loading ? (\n <ValueSkeleton className=\"w-10\" />\n ) : (\n <span\n className={cn(\n \"tabular-nums\",\n LEVEL_VALUE_TEXT[level],\n level !== \"healthy\" && \"font-medium\",\n )}\n >\n {value}\n </span>\n )}\n </span>\n );\n}\n\n/* Group --------------------------------------------------------------------- */\n\nexport interface UsageWindowReading {\n label: string;\n percent: number | null;\n resetsLabel?: string | undefined;\n /** The reset time `resetsLabel` formats, for places that format it themselves. */\n resetsAt?: number | undefined;\n limitReached?: boolean | undefined;\n valueLabel?: string | undefined;\n}\n\nexport interface UsageMeterGroupProps {\n windows: UsageWindowReading[];\n variant?: UsageMeterVariant | undefined;\n density?: UsageMeterDensity | undefined;\n /** \"Checked just now\". Pass a RelativeTime for the exact time on hover. */\n checked?: ReactNode | undefined;\n /** Shows a refresh button next to `checked`. */\n onRefresh?: (() => void) | undefined;\n refreshing?: boolean | undefined;\n /** Disables the refresh button and explains why, for example a reconnect. */\n refreshDisabledReason?: ReactNode | undefined;\n /** Replaces the footer line when the last check failed. */\n error?: ReactNode | undefined;\n loading?: boolean | undefined;\n className?: string | undefined;\n}\n\n/**\n * Every window of one account: stacked in a sheet, inline in a row. The\n * footer carries when it was checked and a refresh button.\n */\nexport function UsageMeterGroup({\n windows,\n variant = \"bar\",\n density = \"full\",\n checked,\n onRefresh,\n refreshing = false,\n refreshDisabledReason,\n error,\n loading = false,\n className,\n}: UsageMeterGroupProps) {\n if (density === \"compact\") {\n return (\n <span\n data-slot=\"usage-meter-group\"\n className={cn(\n \"inline-flex max-w-full min-w-0 flex-wrap items-center gap-x-3 gap-y-1\",\n className,\n )}\n >\n {windows.map((reading) => (\n <UsageMeter\n key={reading.label}\n label={reading.label}\n percent={reading.percent}\n limitReached={reading.limitReached}\n valueLabel={reading.valueLabel}\n resetsLabel={reading.resetsLabel}\n variant={variant}\n density=\"compact\"\n loading={loading}\n />\n ))}\n </span>\n );\n }\n\n return (\n <div\n data-slot=\"usage-meter-group\"\n className={cn(\"@container flex min-w-0 flex-col gap-4\", className)}\n >\n <div\n className={cn(\n \"grid min-w-0\",\n variant === \"ring\" ? \"gap-4 @sm:grid-cols-2\" : variant === \"text\" ? \"gap-3\" : \"gap-4\",\n )}\n >\n {windows.map((reading) => (\n <UsageMeter\n key={reading.label}\n label={reading.label}\n percent={reading.percent}\n limitReached={reading.limitReached}\n valueLabel={reading.valueLabel}\n resetsLabel={reading.resetsLabel}\n variant={variant}\n density=\"full\"\n loading={loading}\n />\n ))}\n </div>\n {error || checked || onRefresh ? (\n <div className=\"flex min-h-8 min-w-0 items-center justify-between gap-3\">\n <p\n aria-live=\"polite\"\n className={cn(\n \"flex min-w-0 items-start gap-1.5 text-xs leading-4.5\",\n error && !refreshing ? \"text-fg-muted\" : \"text-fg-subtle\",\n )}\n >\n {error && !refreshing ? (\n <CircleAlertIcon\n aria-hidden=\"true\"\n className=\"mt-0.5 size-3.5 shrink-0 text-danger\"\n />\n ) : null}\n <span className=\"min-w-0\">{refreshing ? \"Checking usage…\" : (error ?? checked)}</span>\n </p>\n {onRefresh ? (\n <DisabledReason\n reason={refreshDisabledReason}\n disabled={Boolean(refreshDisabledReason)}\n >\n {/* aria-disabled, not disabled, while checking: a disabled button drops keyboard focus. */}\n <button\n type=\"button\"\n onClick={refreshing ? undefined : onRefresh}\n aria-disabled={refreshing || undefined}\n aria-label=\"Check usage now\"\n className=\"-mr-2 inline-grid size-8 shrink-0 place-items-center rounded-md text-fg-subtle transition-colors duration-[120ms] hover:bg-surface-2 hover:text-fg aria-disabled:cursor-default aria-disabled:hover:bg-transparent aria-disabled:hover:text-fg-subtle pointer-coarse:-mr-3.5 pointer-coarse:size-11\"\n >\n <RefreshCwIcon\n aria-hidden=\"true\"\n className={cn(\"size-4\", refreshing && \"motion-safe:animate-spin\")}\n />\n </button>\n </DisabledReason>\n ) : null}\n </div>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/approvals.ts"],"sourcesContent":["import {\n parseToolDisplayMetadata,\n type ToolDisplayMetadata,\n type SessionEvent,\n} from \"@opengeni/sdk\";\nimport {\n parseMcpElicitationApprovalRequest,\n type McpElicitationApprovalRequest as McpElicitation,\n} from \"@opengeni/contracts/mcp-elicitation-model\";\n\n/* ----------------------------------------------------------------------------\n Pending-approvals projection\n\n `session.requiresAction` events live forever in the durable log, so a\n console that replays the log from sequence 0 must not render every\n historical approval as actionable. `projectPendingApprovals` folds the\n ordered event log into the approvals that are still undecided *now*:\n\n - `session.requiresAction` replaces the pending set with the payload's\n approvals (the producer always emits the full currently-pending set, so\n re-emission after a worker re-dispatch cannot duplicate cards);\n - `user.approvalDecision` subtracts the decided approval;\n - the owning turn finishing (`turn.completed`/`turn.failed`/\n `turn.cancelled`) clears the set — whatever was pending died with the\n turn. A `turn.cancelled` for a *different* turn (deleting a queued turn\n while the session waits on an approval) leaves the set alone.\n\n Pure function — same events in, same approvals out — so approve-then-reload\n projects to an empty set instead of a zombie Approve button.\n -------------------------------------------------------------------------- */\n\nexport type PendingApproval = {\n /** The id to send back via `user.approvalDecision` (`approvalId`). */\n id: string;\n /** Tool/function name awaiting the decision. */\n name: string;\n display?: ToolDisplayMetadata;\n arguments?: unknown;\n /**\n * The tool's MCP server stopped mid-call to ask the person these questions.\n * Approving answers them; declining ends the call.\n */\n elicitation?: McpElicitation;\n /** The raw approval entry from the `session.requiresAction` payload. */\n raw?: unknown;\n};\n\n/** The approvals carried by one `session.requiresAction` payload. */\nexport function approvalsFromRequiresAction(payload: unknown): PendingApproval[] {\n const approvals =\n payload && typeof payload === \"object\"\n ? (payload as { approvals?: unknown }).approvals\n : undefined;\n if (!Array.isArray(approvals)) {\n return [];\n }\n return approvals.map((approval, index) => {\n const raw = (approval && typeof approval === \"object\" ? approval : {}) as Record<\n string,\n unknown\n >;\n const rawItem =\n raw.rawItem && typeof raw.rawItem === \"object\"\n ? (raw.rawItem as Record<string, unknown>)\n : {};\n const display = parseToolDisplayMetadata(raw.display);\n const elicitation =\n raw.elicitation === undefined ? null : parseMcpElicitationApprovalRequest(raw.elicitation);\n return {\n // Mirror the runtime's canonical interruption identity before retaining\n // the legacy top-level callId fallback for already-normalized payloads.\n id: String(rawItem.callId ?? rawItem.id ?? raw.id ?? raw.callId ?? raw.name ?? index),\n name: String(raw.name ?? raw.toolName ?? rawItem.name ?? \"approval\"),\n ...(display ? { display } : {}),\n ...(elicitation ? { elicitation } : {}),\n arguments: raw.arguments ?? rawItem.arguments,\n raw: approval,\n };\n });\n}\n\n/** The approvals still awaiting a decision after replaying `events` in order. */\nexport function projectPendingApprovals(events: SessionEvent[]): PendingApproval[] {\n let pending: PendingApproval[] = [];\n let owningTurnId: string | null = null;\n for (const event of events) {\n switch (event.type) {\n case \"session.requiresAction\": {\n pending = approvalsFromRequiresAction(event.payload);\n owningTurnId = event.turnId ?? null;\n break;\n }\n case \"user.approvalDecision\": {\n const payload =\n event.payload && typeof event.payload === \"object\"\n ? (event.payload as { approvalId?: unknown })\n : {};\n if (typeof payload.approvalId === \"string\") {\n pending = pending.filter((approval) => approval.id !== payload.approvalId);\n }\n break;\n }\n case \"turn.completed\":\n case \"turn.failed\":\n case \"turn.cancelled\":\n // A Steer that replaces an approval wait closes its approvals unexecuted.\n case \"turn.superseded\": {\n // Scope clearing to the turn that raised the approvals when both\n // sides carry a turn id; clear conservatively when either is unknown.\n if (owningTurnId === null || event.turnId == null || event.turnId === owningTurnId) {\n pending = [];\n owningTurnId = null;\n }\n break;\n }\n default:\n break;\n }\n }\n return pending;\n}\n\n/**\n * Whether a session in `status` takes decisions for its pending approvals.\n * Deciding one approval resumes the turn, and the pause's other approvals stay\n * decidable while it resumes: their cards stay up instead of vanishing until\n * the turn pauses again. Only a session whose turn ended has none.\n */\nexport function approvalsDecidable(status: string | null | undefined): boolean {\n return (\n status === \"requires_action\" ||\n status === \"running\" ||\n status === \"queued\" ||\n status === \"recovering\" ||\n status === \"waiting_capacity\"\n );\n}\n"],"mappings":";;;AAAA;AAAA,EACE;AAAA,OAGK;AACP;AAAA,EACE;AAAA,OAEK;AAwCA,SAAS,4BAA4B,SAAqC;AAC/E,QAAM,YACJ,WAAW,OAAO,YAAY,WACzB,QAAoC,YACrC;AACN,MAAI,CAAC,MAAM,QAAQ,SAAS,GAAG;AAC7B,WAAO,CAAC;AAAA,EACV;AACA,SAAO,UAAU,IAAI,CAAC,UAAU,UAAU;AACxC,UAAM,MAAO,YAAY,OAAO,aAAa,WAAW,WAAW,CAAC;AAIpE,UAAM,UACJ,IAAI,WAAW,OAAO,IAAI,YAAY,WACjC,IAAI,UACL,CAAC;AACP,UAAM,UAAU,yBAAyB,IAAI,OAAO;AACpD,UAAM,cACJ,IAAI,gBAAgB,SAAY,OAAO,mCAAmC,IAAI,WAAW;AAC3F,WAAO;AAAA;AAAA;AAAA,MAGL,IAAI,OAAO,QAAQ,UAAU,QAAQ,MAAM,IAAI,MAAM,IAAI,UAAU,IAAI,QAAQ,KAAK;AAAA,MACpF,MAAM,OAAO,IAAI,QAAQ,IAAI,YAAY,QAAQ,QAAQ,UAAU;AAAA,MACnE,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC7B,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;AAAA,MACrC,WAAW,IAAI,aAAa,QAAQ;AAAA,MACpC,KAAK;AAAA,IACP;AAAA,EACF,CAAC;AACH;AAGO,SAAS,wBAAwB,QAA2C;AACjF,MAAI,UAA6B,CAAC;AAClC,MAAI,eAA8B;AAClC,aAAW,SAAS,QAAQ;AAC1B,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK,0BAA0B;AAC7B,kBAAU,4BAA4B,MAAM,OAAO;AACnD,uBAAe,MAAM,UAAU;AAC/B;AAAA,MACF;AAAA,MACA,KAAK,yBAAyB;AAC5B,cAAM,UACJ,MAAM,WAAW,OAAO,MAAM,YAAY,WACrC,MAAM,UACP,CAAC;AACP,YAAI,OAAO,QAAQ,eAAe,UAAU;AAC1C,oBAAU,QAAQ,OAAO,CAAC,aAAa,SAAS,OAAO,QAAQ,UAAU;AAAA,QAC3E;AACA;AAAA,MACF;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA;AAAA,MAEL,KAAK,mBAAmB;AAGtB,YAAI,iBAAiB,QAAQ,MAAM,UAAU,QAAQ,MAAM,WAAW,cAAc;AAClF,oBAAU,CAAC;AACX,yBAAe;AAAA,QACjB;AACA;AAAA,MACF;AAAA,MACA;AACE;AAAA,IACJ;AAAA,EACF;AACA,SAAO;AACT;AAQO,SAAS,mBAAmB,QAA4C;AAC7E,SACE,WAAW,qBACX,WAAW,aACX,WAAW,YACX,WAAW,gBACX,WAAW;AAEf;","names":[]}