@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.
- package/dist/app/app-state.js +8 -8
- package/dist/app/components/Composer.js +18 -18
- package/dist/app/components/agent/agent-capability-picker.js +6 -6
- package/dist/app/components/artifacts/artifact-library.js +6 -6
- package/dist/app/components/artifacts/artifact-viewer.js +18 -18
- package/dist/app/components/artifacts/chat-interactive-block.js +11 -11
- package/dist/app/components/artifacts/file-reach-dialog.js +6 -6
- package/dist/app/components/artifacts/inline-chat-image.js +19 -19
- package/dist/app/components/artifacts/retained-file-preview.js +20 -20
- package/dist/app/components/artifacts/retained-text-preview.js +3 -3
- package/dist/app/components/artifacts/site-audience.js +3 -3
- package/dist/app/components/artifacts/site-conversations.js +9 -9
- package/dist/app/components/artifacts/site-data.js +10 -10
- package/dist/app/components/artifacts/site-publishing-page.js +25 -25
- package/dist/app/components/artifacts/site-publishing.js +22 -22
- package/dist/app/components/artifacts/site-settings.js +24 -24
- package/dist/app/components/artifacts/site-version-menu.js +3 -3
- package/dist/app/components/billing-class-mark.js +3 -3
- package/dist/app/components/bots/bot-launch-strip.js +20 -20
- package/dist/app/components/bots/bot-template-dialog.js +26 -26
- package/dist/app/components/bots/bot-template-shortcuts.js +20 -20
- package/dist/app/components/bots/bot-templates-page.js +30 -30
- package/dist/app/components/capabilities/capability-detail-sheet.js +6 -6
- package/dist/app/components/capabilities/capability-logo-source.js +13 -13
- package/dist/app/components/capabilities/connector-tool-permissions.js +4 -4
- package/dist/app/components/capabilities/native-connect-setup.js +13 -13
- package/dist/app/components/capabilities/own-logins-shared-heads-up.js +3 -3
- package/dist/app/components/capabilities/prepared-mcp-setup-card.js +15 -15
- package/dist/app/components/capabilities/session-capability-card.js +52 -52
- package/dist/app/components/capabilities/session-chrome-card.js +20 -20
- package/dist/app/components/capabilities/session-custom-mcp-card.js +16 -16
- package/dist/app/components/capabilities/session-github-card.js +16 -16
- package/dist/app/components/capabilities/session-machine-card.js +19 -19
- package/dist/app/components/capabilities/session-personal-github-card.js +14 -14
- package/dist/app/components/capabilities/session-plugin-card.js +8 -8
- package/dist/app/components/command-menu/chat-status.js +15 -15
- package/dist/app/components/command-menu/chat-switcher.js +35 -35
- package/dist/app/components/command-menu/command-menu.js +39 -39
- package/dist/app/components/command-menu/shortcut-sheet.js +8 -8
- package/dist/app/components/composer-capabilities-menu-body.js +4 -4
- package/dist/app/components/composer-mobile-plus-panel.js +8 -8
- package/dist/app/components/composer-mobile-plus.js +1 -1
- package/dist/app/components/desktop/app-shots.js +6 -6
- package/dist/app/components/desktop/computer-use.js +2 -2
- package/dist/app/components/desktop/this-computer.js +5 -5
- package/dist/app/components/feedback.js +3 -3
- package/dist/app/components/github-app-connect-launcher.js +1 -1
- package/dist/app/components/machines/connect-machine-dialog.js +11 -11
- package/dist/app/components/markdown.js +6 -6
- package/dist/app/components/models/models-ui.js +5 -5
- package/dist/app/components/models/subscription-usage.d.ts +34 -0
- package/dist/app/components/models/subscription-usage.js +24 -0
- package/dist/app/components/my-things.js +4 -4
- package/dist/app/components/own-where-it-works.js +3 -3
- package/dist/app/components/personal-resource-attachment-surface.js +4 -4
- package/dist/app/components/pickers.js +5 -5
- package/dist/app/components/rail/channel-create-dialog.js +3 -3
- package/dist/app/components/rail/project-glyph.js +20 -20
- package/dist/app/components/rail/project-profile.js +27 -27
- package/dist/app/components/rail/rail-context.js +1 -1
- package/dist/app/components/rail/rail-sections.js +55 -55
- package/dist/app/components/rail/session-header.js +47 -47
- package/dist/app/components/rail/session-list.js +53 -53
- package/dist/app/components/rail/session-row-content.js +4 -4
- package/dist/app/components/rail/session-row-hover-details.js +14 -14
- package/dist/app/components/rail/session-shell.js +76 -73
- package/dist/app/components/rail/site-session-group-heading.js +8 -8
- package/dist/app/components/session/agent-configuration-panel.js +12 -12
- package/dist/app/components/session/banners.js +8 -8
- package/dist/app/components/session/console-new-conversation.js +39 -39
- package/dist/app/components/session/descendant-requests.js +36 -36
- package/dist/app/components/session/editable-artifacts-workspace.js +16 -16
- package/dist/app/components/session/failed-session-banner.js +6 -6
- package/dist/app/components/session/failure-recovery-boundary.js +3 -3
- package/dist/app/components/session/human-input-delegation-record.js +2 -2
- package/dist/app/components/session/human-input.js +33 -33
- package/dist/app/components/session/inspector.js +43 -43
- package/dist/app/components/session/message-actions.js +3 -3
- package/dist/app/components/session/message-resource-attachments.js +10 -10
- package/dist/app/components/session/model-recovery-notice.js +3 -3
- package/dist/app/components/session/new-session-settings-menu.js +6 -6
- package/dist/app/components/session/new-session-setup-strip.js +21 -21
- package/dist/app/components/session/sandbox-recovery-actions.js +3 -3
- package/dist/app/components/session/sandbox-switcher.js +7 -7
- package/dist/app/components/session/sandbox-workspace.js +48 -48
- package/dist/app/components/session/search-markdown-highlight.js +7 -7
- package/dist/app/components/session/search-results-view.js +8 -8
- package/dist/app/components/session/session-admin-access.js +4 -4
- package/dist/app/components/session/session-admission-notice.js +4 -4
- package/dist/app/components/session/session-avatar-picker.js +21 -21
- package/dist/app/components/session/session-avatar.js +19 -19
- package/dist/app/components/session/session-machine-access-notice.js +4 -4
- package/dist/app/components/session/session-profile-dialog.js +25 -25
- package/dist/app/components/session/session-profile-editor.js +26 -26
- package/dist/app/components/session/session-retention.js +3 -3
- package/dist/app/components/session/session-search-dialog.js +8 -8
- package/dist/app/components/session/session-tenancy-control.js +2 -2
- package/dist/app/components/session/session-usage-limit-section.js +4 -4
- package/dist/app/components/session/share-chat-dialog.js +5 -5
- package/dist/app/components/session/subagents.js +8 -8
- package/dist/app/components/session/subscription-account-indicator.js +12 -7
- package/dist/app/components/session/subscription-account-menu.d.ts +15 -15
- package/dist/app/components/session/subscription-account-menu.js +6 -1
- package/dist/app/components/session/subscription-account.d.ts +16 -9
- package/dist/app/components/settings/row-select.js +4 -4
- package/dist/app/components/transcription-settings.js +6 -6
- package/dist/app/components/ui/destructive-confirm.js +5 -5
- package/dist/app/components/usage/usage-entry.js +3 -3
- package/dist/app/components/window-bar.js +9 -9
- package/dist/app/components/workspace-composer-plus.js +16 -16
- package/dist/app/components/workspace-reach.js +4 -4
- package/dist/app/embed/session-app.js +160 -157
- package/dist/app/lib/actions/actions-provider.js +8 -8
- package/dist/app/lib/agent-capabilities.d.ts +12 -2
- package/dist/app/lib/agent-capabilities.js +3 -3
- package/dist/app/lib/codex-usage-query.js +2 -2
- package/dist/app/lib/composer-connectors.js +14 -14
- package/dist/app/lib/console-site.js +2 -2
- package/dist/app/lib/console-text.js +2 -2
- package/dist/app/lib/events.js +12 -12
- package/dist/app/lib/failed-session-copy.js +3 -3
- package/dist/app/lib/model-access-onboarding.js +3 -3
- package/dist/app/lib/move-chat-to-machine.js +3 -3
- package/dist/app/lib/session-branch-cache.js +8 -8
- package/dist/app/lib/session-create.js +4 -4
- package/dist/app/lib/session-group-pagination.js +8 -8
- package/dist/app/lib/session-hover-facts.js +13 -13
- package/dist/app/lib/session-model.js +2 -2
- package/dist/app/lib/session-pins.js +1 -1
- package/dist/app/lib/session-rail.js +5 -5
- package/dist/app/lib/session-rename.js +3 -3
- package/dist/app/lib/sessions-group.d.ts +5 -3
- package/dist/app/lib/sessions-group.js +7 -7
- package/dist/app/lib/site-tool-consent-dialog.js +7 -7
- package/dist/app/lib/site-tool-consent.js +1 -1
- package/dist/app/lib/subscription-accounts.d.ts +79 -0
- package/dist/app/lib/subscription-accounts.js +18 -0
- package/dist/app/lib/turn-failure-analytics.js +4 -4
- package/dist/app/lib/use-follow-up-repositories.js +3 -3
- package/dist/app/lib/use-workspace-machines.js +4 -4
- package/dist/app/lib/use-workspace-model-catalog.js +3 -3
- package/dist/app/lib/use-workspace-rigs.js +2 -2
- package/dist/app/lib/workspace-navigation-preference.js +4 -4
- package/dist/app/lib/workspace-scope-context.js +3 -3
- package/dist/app/routes/artifacts.js +48 -48
- package/dist/app/routes/retained-artifact.js +32 -32
- package/dist/app/routes/session.js +96 -96
- package/dist/app/routes/sessions-index-hydration.js +5 -5
- package/dist/app/routes/sessions-index.js +76 -76
- package/dist/app/routes/site-view.js +55 -55
- package/dist/artifacts-document.js +4 -4
- package/dist/artifacts-presentation.js +4 -4
- package/dist/artifacts-spreadsheet.js +4 -4
- package/dist/artifacts.js +10 -10
- package/dist/automations.js +10 -10
- package/dist/{browser-viewer-ZHQDVHZ2.js → browser-viewer-F4FL7JKB.js} +4 -4
- package/dist/{chat-interactive-block-VSDD6X3M.js → chat-interactive-block-4U5JWRSY.js} +5 -5
- package/dist/{chunk-4K64EKM7.js → chunk-22YIIM3X.js} +4 -4
- package/dist/{chunk-3NNAC43A.js → chunk-2N7ACQ7M.js} +2 -2
- package/dist/{chunk-7Z76QP64.js → chunk-2PY5XD3F.js} +35 -5
- package/dist/chunk-2PY5XD3F.js.map +1 -0
- package/dist/{chunk-WDASYY4S.js → chunk-2TEYUDJD.js} +8 -8
- package/dist/{chunk-OTW25A6I.js → chunk-37JJQNZB.js} +3 -3
- package/dist/{chunk-VCJQQYRE.js → chunk-3DWQPURZ.js} +4 -4
- package/dist/{chunk-GTRAH4FG.js → chunk-3GWC3FU3.js} +2 -2
- package/dist/{chunk-AB5IW227.js → chunk-3ICY6LP3.js} +3 -3
- package/dist/{chunk-WIFDNUKD.js → chunk-3OCU5RX5.js} +3 -3
- package/dist/{chunk-UBRQ3PQD.js → chunk-3SPDJLOR.js} +2 -2
- package/dist/{chunk-IZXYFWA4.js → chunk-3WVLR7UA.js} +12 -12
- package/dist/{chunk-DEHLWZSI.js → chunk-3XMB3L57.js} +4 -4
- package/dist/{chunk-AJBDAVX3.js → chunk-4IUOBO2H.js} +7 -7
- package/dist/{chunk-NFCS5WYC.js → chunk-4KQ3A3EO.js} +3 -3
- package/dist/{chunk-LIJNVIT3.js → chunk-4L5B5AZT.js} +3 -3
- package/dist/{chunk-EDDKPIIV.js → chunk-4NB3TPNE.js} +2 -2
- package/dist/{chunk-PSM3CU7N.js → chunk-4TDKXHCD.js} +46 -39
- package/dist/chunk-4TDKXHCD.js.map +1 -0
- package/dist/{chunk-OJWDNNW3.js → chunk-4TPTGBIO.js} +5 -5
- package/dist/{chunk-J2WY42FA.js → chunk-4UHGW6WF.js} +2 -2
- package/dist/{chunk-7NLF35YL.js → chunk-4YN2JLYK.js} +4 -4
- package/dist/{chunk-OOOSGPJL.js → chunk-53MYEEMA.js} +1 -1
- package/dist/{chunk-467WDSOK.js → chunk-5HYWXPMA.js} +2 -2
- package/dist/{chunk-XMBOLFFS.js → chunk-5IMNL6IV.js} +2 -2
- package/dist/{chunk-4Z5X7PLC.js → chunk-5MLM5T5C.js} +3 -3
- package/dist/{chunk-YMI27QPF.js → chunk-5NKQZVXP.js} +2 -2
- package/dist/{chunk-ZW5YTIH3.js → chunk-5PB46DAA.js} +1 -1
- package/dist/{chunk-ZW5YTIH3.js.map → chunk-5PB46DAA.js.map} +1 -1
- package/dist/{chunk-CYDXCILL.js → chunk-5SODSGW7.js} +7 -7
- package/dist/{chunk-Q5EZNBPI.js → chunk-5YAJASCO.js} +3 -3
- package/dist/{chunk-M3FDGRB4.js → chunk-62XAL5BA.js} +3 -3
- package/dist/{chunk-SGH7I7OY.js → chunk-67R6NAFI.js} +2 -2
- package/dist/{chunk-Q5K2J5GG.js → chunk-6BN3RU7T.js} +13 -3
- package/dist/chunk-6BN3RU7T.js.map +1 -0
- package/dist/{chunk-PYB4BFEC.js → chunk-6BQLDL6R.js} +3 -3
- package/dist/{chunk-YJSCLGAW.js → chunk-6EZYHJTL.js} +3 -3
- package/dist/{chunk-OWET7EY2.js → chunk-6GW7NJMK.js} +19 -13
- package/dist/{chunk-OWET7EY2.js.map → chunk-6GW7NJMK.js.map} +1 -1
- package/dist/{chunk-G5UQBTXY.js → chunk-6LXIL3Q3.js} +2 -2
- package/dist/{chunk-T67LTMSW.js → chunk-6LYVAJFZ.js} +10 -10
- package/dist/{chunk-3L465FBR.js → chunk-6WB5UXMZ.js} +6 -6
- package/dist/{chunk-EKJHOWTZ.js → chunk-74UGYVCA.js} +4 -4
- package/dist/{chunk-PWUSSSSL.js → chunk-7BTNYZC7.js} +2 -2
- package/dist/{chunk-NQ2CPQJF.js → chunk-7D3WIDKK.js} +26 -3
- package/dist/chunk-7D3WIDKK.js.map +1 -0
- package/dist/{chunk-ESXAECZ3.js → chunk-7KZFGA25.js} +2 -2
- package/dist/{chunk-EGKARC53.js → chunk-7MGDX2TD.js} +2 -2
- package/dist/{chunk-Y3XZEKDQ.js → chunk-7N3GFGB6.js} +2 -2
- package/dist/{chunk-AH3DGOTK.js → chunk-7SFSN6AX.js} +2 -2
- package/dist/{chunk-QPQ7R77C.js → chunk-7SU4YVZ5.js} +5 -1
- package/dist/chunk-7SU4YVZ5.js.map +1 -0
- package/dist/{chunk-6QK65ZWM.js → chunk-7TGUHFGO.js} +3 -3
- package/dist/{chunk-QURYQFDN.js → chunk-7ZIWO65F.js} +2 -2
- package/dist/{chunk-OYCK4JRS.js → chunk-AJHLEJTK.js} +2 -2
- package/dist/{chunk-3PZ3LRPV.js → chunk-AN4U7EPH.js} +3 -3
- package/dist/{chunk-77BHKC43.js → chunk-APG6CEG7.js} +1 -1
- package/dist/{chunk-FSDQQQIA.js → chunk-APHLXQNP.js} +3 -3
- package/dist/{chunk-SN2WENRP.js → chunk-AXHQ7QXV.js} +3 -3
- package/dist/{chunk-54U6ZBEX.js → chunk-AYTLSPF6.js} +3 -3
- package/dist/{chunk-WYGTAQMX.js → chunk-AZFVRPQM.js} +76 -22
- package/dist/chunk-AZFVRPQM.js.map +1 -0
- package/dist/{chunk-R33SBMB7.js → chunk-BBSKKBMV.js} +3 -3
- package/dist/{chunk-2GCHGWNE.js → chunk-BGH6TU2P.js} +3 -3
- package/dist/{chunk-D3PTVN2I.js → chunk-BGIYL26H.js} +2 -2
- package/dist/{chunk-BQYRZIZ7.js → chunk-BL7UQUC3.js} +2 -2
- package/dist/{chunk-EBTUPRRQ.js → chunk-BOUHCYL6.js} +4 -4
- package/dist/{chunk-MKDFYE2E.js → chunk-BVNGDFBC.js} +2 -2
- package/dist/{chunk-ICAMYP5M.js → chunk-BWJK64CP.js} +2 -2
- package/dist/{chunk-RHXYO4H2.js → chunk-BZ2GTCQV.js} +2 -2
- package/dist/{chunk-GIWFLWXG.js → chunk-C2KASMJK.js} +4 -4
- package/dist/{chunk-KO3OHHY2.js → chunk-CAZDRDQT.js} +2 -2
- package/dist/{chunk-OK7BQMCI.js → chunk-CBJRZKZB.js} +9 -9
- package/dist/{chunk-OYOFPNLC.js → chunk-CF6NYG7J.js} +4 -4
- package/dist/{chunk-MT2R57SF.js → chunk-COITN7WN.js} +2 -2
- package/dist/{chunk-OCXTTKVA.js → chunk-CPVOXM2Q.js} +2 -2
- package/dist/{chunk-HYEIA25Y.js → chunk-CTZRCBKH.js} +2 -2
- package/dist/{chunk-OCXEY7HE.js → chunk-CWL27YTB.js} +2 -2
- package/dist/{chunk-K4DQS2ML.js → chunk-D2I33V5P.js} +4 -4
- package/dist/{chunk-736RUNIA.js → chunk-DF7WI4JH.js} +4 -4
- package/dist/{chunk-KUE5BOQE.js → chunk-DKZYCJCO.js} +4 -4
- package/dist/{chunk-74CBR5YE.js → chunk-DQ32FKFQ.js} +2 -2
- package/dist/{chunk-4O2XWOLZ.js → chunk-DTKG2YUF.js} +3 -3
- package/dist/{chunk-GMHIOYB7.js → chunk-DUDA4V5R.js} +4 -4
- package/dist/{chunk-XUOYNJPB.js → chunk-ECROT4M5.js} +24 -24
- package/dist/{chunk-PVB4YVDP.js → chunk-EOXV5XGY.js} +2 -2
- package/dist/{chunk-U6552Q3T.js → chunk-EQQOZ6DD.js} +2 -2
- package/dist/{chunk-G6ICCGJ3.js → chunk-EY6W5H4B.js} +2 -2
- package/dist/{chunk-HWVPLFIW.js → chunk-EYRFEWXJ.js} +2 -2
- package/dist/{chunk-7YTR3UFO.js → chunk-FB4JWUVJ.js} +8 -5
- package/dist/chunk-FB4JWUVJ.js.map +1 -0
- package/dist/{chunk-U4LTPFD2.js → chunk-FKK2PD7K.js} +2 -2
- package/dist/{chunk-PUUEI4W3.js → chunk-FPHHIC5K.js} +5 -5
- package/dist/{chunk-SP44O3OU.js → chunk-FQM6L22H.js} +2 -2
- package/dist/{chunk-2J77TWGH.js → chunk-FW22IREV.js} +3 -3
- package/dist/{chunk-EBIVTDEG.js → chunk-G4M6AYDB.js} +2 -2
- package/dist/{chunk-O4JOE3R7.js → chunk-G55NAU5M.js} +60 -74
- package/dist/chunk-G55NAU5M.js.map +1 -0
- package/dist/{chunk-BASI553K.js → chunk-G6AZ2WIU.js} +4 -4
- package/dist/{chunk-SJYTQLN3.js → chunk-GJ5IDSAX.js} +3 -3
- package/dist/{chunk-TDTD66BK.js → chunk-GRDSEZWZ.js} +2 -2
- package/dist/{chunk-MV2CLIO6.js → chunk-HBVJIGY2.js} +6 -6
- package/dist/{chunk-R4JA5JFI.js → chunk-HCWQLIOE.js} +3 -3
- package/dist/{chunk-MZY3VKKM.js → chunk-HEVD4A5G.js} +2 -2
- package/dist/{chunk-DLVIRJGK.js → chunk-HNDHSEVJ.js} +2 -2
- package/dist/{chunk-LPKJ77EK.js → chunk-HNTZ7B7M.js} +2 -2
- package/dist/{chunk-QQIZMVAJ.js → chunk-HQ7GTMII.js} +59 -57
- package/dist/chunk-HQ7GTMII.js.map +1 -0
- package/dist/{chunk-IN3VQFKS.js → chunk-I2FC7CAI.js} +2 -2
- package/dist/{chunk-SK5S2PCK.js → chunk-I7BGHBOM.js} +14 -14
- package/dist/chunk-I7BGHBOM.js.map +1 -0
- package/dist/{chunk-ZBHGNE2J.js → chunk-IEHZFYMH.js} +3 -3
- package/dist/{chunk-DWJ6J3YW.js → chunk-IXISEVD7.js} +4 -4
- package/dist/{chunk-TK5FWVZR.js → chunk-IZEDVQUD.js} +3 -3
- package/dist/{chunk-HEGV4QMS.js → chunk-J42QE4VO.js} +2 -2
- package/dist/{chunk-PRT4J2DL.js → chunk-J555XSUM.js} +2 -2
- package/dist/{chunk-SBXSKRFA.js → chunk-JNMHFSDF.js} +3 -3
- package/dist/{chunk-KI46GKMD.js → chunk-JTBAOPYO.js} +7 -7
- package/dist/{chunk-JHZRAYI4.js → chunk-JWSRFXRN.js} +2 -2
- package/dist/chunk-JWSRFXRN.js.map +1 -0
- package/dist/{chunk-SXGJL7UT.js → chunk-K376MPJH.js} +14 -14
- package/dist/{chunk-OSJ366KR.js → chunk-KEBVT55V.js} +30 -30
- package/dist/{chunk-U5UGM5XD.js → chunk-KFIZAXHI.js} +5 -5
- package/dist/{chunk-KFNZZ2N6.js → chunk-KKGRDBMK.js} +2 -2
- package/dist/{chunk-PLYVGZIN.js → chunk-KKIG6DN5.js} +1 -1
- package/dist/{chunk-3OK7Y6ES.js → chunk-KKQO2GAA.js} +2 -2
- package/dist/{chunk-DQPIEQGP.js → chunk-KO753ZCZ.js} +2 -2
- package/dist/{chunk-YNTLWCF4.js → chunk-KYIRWU65.js} +3 -3
- package/dist/{chunk-JKL5S7UQ.js → chunk-L6V63DVI.js} +6 -6
- package/dist/{chunk-M5IQVMLR.js → chunk-LAZ2QZTJ.js} +11 -4
- package/dist/chunk-LAZ2QZTJ.js.map +1 -0
- package/dist/{chunk-CV4VVLPZ.js → chunk-LCNJ2KNS.js} +2 -2
- package/dist/{chunk-D74Z2N4K.js → chunk-LE7YKMTU.js} +2 -2
- package/dist/{chunk-D5TIVCXG.js → chunk-LEBEOMVT.js} +2 -2
- package/dist/chunk-LKLQVANM.js +2 -0
- package/dist/{chunk-2OXSB2OL.js → chunk-LKWVBUH6.js} +3 -2
- package/dist/chunk-LKWVBUH6.js.map +1 -0
- package/dist/{chunk-WXF2RTS4.js → chunk-M6URPYUB.js} +2 -2
- package/dist/{chunk-H6BX6WOW.js → chunk-MDHFMRBC.js} +3 -3
- package/dist/{chunk-3CDJSKDW.js → chunk-MGZO7CHI.js} +3 -3
- package/dist/{chunk-DCEQCGVN.js → chunk-MIWU52TW.js} +2 -2
- package/dist/{chunk-PF2WU2IL.js → chunk-ND4IQJUM.js} +120 -17
- package/dist/chunk-ND4IQJUM.js.map +1 -0
- package/dist/{chunk-3PM3M2Q6.js → chunk-NDXBF3RW.js} +27 -11
- package/dist/chunk-NDXBF3RW.js.map +1 -0
- package/dist/{chunk-LVELUUK6.js → chunk-NF6QVVMP.js} +2 -2
- package/dist/{chunk-UMX6DZME.js → chunk-NTZ5ZNVK.js} +2 -2
- package/dist/{chunk-FBA2NXYH.js → chunk-NWLRABUR.js} +3 -3
- package/dist/{chunk-TNSJFZ6Q.js → chunk-O2H2U7YS.js} +4 -4
- package/dist/{chunk-BFFNINCC.js → chunk-OAL2PPX4.js} +3 -3
- package/dist/{chunk-WTSQUCHB.js → chunk-OCYTHZ4A.js} +3 -3
- package/dist/{chunk-ZAX4XQLN.js → chunk-OEDTCIXF.js} +2 -2
- package/dist/{chunk-CHU3RDV4.js → chunk-OLVSYB3P.js} +3 -3
- package/dist/{chunk-PZKHST7A.js → chunk-OQ6QOPK6.js} +10 -3
- package/dist/chunk-OQ6QOPK6.js.map +1 -0
- package/dist/{chunk-IFSXVU2S.js → chunk-OQHTFOCA.js} +2 -2
- package/dist/{chunk-OXQ2SXVC.js → chunk-P56AVROH.js} +2 -2
- package/dist/{chunk-CXAN2FHF.js → chunk-PCEJHHGP.js} +6 -6
- package/dist/{chunk-5MIBQ4P5.js → chunk-PHGQGVVL.js} +2 -2
- package/dist/{chunk-FLWQJDJ5.js → chunk-PUZRHEQI.js} +6 -6
- package/dist/{chunk-OP2GD6QW.js → chunk-PV7U6OOJ.js} +2 -2
- package/dist/{chunk-SPD4ULVB.js → chunk-PYMROAWS.js} +2 -1
- package/dist/chunk-PYMROAWS.js.map +1 -0
- package/dist/{chunk-X2QJXDE4.js → chunk-PZQACDH5.js} +8 -8
- package/dist/{chunk-CH4UQ4NO.js → chunk-PZTS4O6E.js} +5 -5
- package/dist/{chunk-TKQL7EDB.js → chunk-Q42QHUAQ.js} +2 -2
- package/dist/{chunk-MRECRNVU.js → chunk-QCYGB6TZ.js} +5 -5
- package/dist/{chunk-GSCGKJNK.js → chunk-QECMETOF.js} +2 -2
- package/dist/{chunk-RMCLFSMX.js → chunk-QGX3LE6H.js} +2 -2
- package/dist/{chunk-HTMQGS63.js → chunk-QI3NDQFP.js} +8 -8
- package/dist/{chunk-UU5FBVRX.js → chunk-QZE4BTLA.js} +6 -5
- package/dist/chunk-QZE4BTLA.js.map +1 -0
- package/dist/{chunk-R5QAL43H.js → chunk-RA3Q52O2.js} +2 -2
- package/dist/chunk-RBOHWUSN.js +151 -0
- package/dist/chunk-RBOHWUSN.js.map +1 -0
- package/dist/{chunk-AJDGP2N4.js → chunk-RJNOQEJJ.js} +20 -20
- package/dist/{chunk-477DTTMH.js → chunk-RSFOFUR7.js} +3 -3
- package/dist/{chunk-JV5ULONH.js → chunk-RXR6PMSH.js} +39 -39
- package/dist/{chunk-J2BTILRR.js → chunk-SM7HFCGC.js} +2 -2
- package/dist/{chunk-UTRNLNCW.js → chunk-SN6ZWYOP.js} +69 -97
- package/dist/chunk-SN6ZWYOP.js.map +1 -0
- package/dist/{chunk-OBGOLHCP.js → chunk-T4HK4XCI.js} +3 -3
- package/dist/{chunk-XVLEBB4Y.js → chunk-TBWL6YWL.js} +2 -2
- package/dist/{chunk-AAS7OWV6.js → chunk-TIDXYWFX.js} +3 -3
- package/dist/{chunk-N3FM4BNA.js → chunk-TKHRGY2P.js} +2 -2
- package/dist/{chunk-GU7T2S5N.js → chunk-TU2GSZL7.js} +2 -2
- package/dist/{chunk-OI6VI6SU.js → chunk-U6HGJXXQ.js} +8 -8
- package/dist/{chunk-4BWMAGJJ.js → chunk-UGRW6RTR.js} +3 -3
- package/dist/{chunk-AVXDIRRW.js → chunk-UMRUDYUK.js} +2 -2
- package/dist/{chunk-FNXCFIPW.js → chunk-UOT2R5ZD.js} +2 -2
- package/dist/{chunk-DIP7YALH.js → chunk-USURKJVT.js} +2 -2
- package/dist/{chunk-S27VZ5DO.js → chunk-UU6Q67XM.js} +6 -6
- package/dist/{chunk-LTJFV2JI.js → chunk-UZ7NP5CW.js} +2 -2
- package/dist/{chunk-H6MJFMHZ.js → chunk-V4FO7UOE.js} +3 -3
- package/dist/{chunk-RGR57NYY.js → chunk-V4ZOZRCW.js} +2 -2
- package/dist/{chunk-LQKVNREV.js → chunk-V57YMKQZ.js} +3 -3
- package/dist/{chunk-XZCCEKPW.js → chunk-VOIWZBY6.js} +6 -6
- package/dist/{chunk-E5KOWRDU.js → chunk-VPHPLPDA.js} +2 -2
- package/dist/{chunk-OGU73VUN.js → chunk-VUL4KPUU.js} +2 -2
- package/dist/{chunk-SFIXTOOJ.js → chunk-VWF6ILAR.js} +3 -3
- package/dist/{chunk-FER6EVIY.js → chunk-W54BHJO7.js} +2 -2
- package/dist/{chunk-34NV52R3.js → chunk-WCYE4BLC.js} +4 -4
- package/dist/{chunk-RISUROBM.js → chunk-WTV25ELY.js} +4 -4
- package/dist/{chunk-UO35OEOX.js → chunk-WZYGH7CN.js} +3 -3
- package/dist/{chunk-CEMSIU4Z.js → chunk-XG2RWUF7.js} +5 -5
- package/dist/chunk-XK72HZ4C.js +147 -0
- package/dist/chunk-XK72HZ4C.js.map +1 -0
- package/dist/{chunk-K3D7IQQP.js → chunk-XV7QOT7W.js} +6 -6
- package/dist/{chunk-GOCODNQS.js → chunk-XWECT3GX.js} +2 -2
- package/dist/{chunk-5MHMCE2G.js → chunk-XZQK2ZLW.js} +3 -3
- package/dist/{chunk-JV3UI7BH.js → chunk-Y5BR66OH.js} +3 -3
- package/dist/{chunk-VXORMNU4.js → chunk-YBHAAULA.js} +67 -2
- package/dist/chunk-YBHAAULA.js.map +1 -0
- package/dist/{chunk-4F3AEJI6.js → chunk-YD6XU6FY.js} +4 -4
- package/dist/{chunk-VATYK3JQ.js → chunk-YFE47G3C.js} +3 -3
- package/dist/{chunk-ZR5EKJT6.js → chunk-YG6TWPP7.js} +2 -2
- package/dist/{chunk-44JWVYJB.js → chunk-YH3ARKBB.js} +2 -2
- package/dist/{chunk-752WXSDN.js → chunk-YI66STKJ.js} +2 -2
- package/dist/{chunk-QRECBCJM.js → chunk-YMVPYMKB.js} +2 -2
- package/dist/{chunk-77SYIH6O.js → chunk-YPIXBAF6.js} +2 -2
- package/dist/{chunk-WRMUXZ7C.js → chunk-YSWPNY6G.js} +3 -3
- package/dist/{chunk-GTHCHCWW.js → chunk-YWNNMBZG.js} +3 -3
- package/dist/{chunk-3DRLCX5V.js → chunk-Z3HYM2JT.js} +2 -2
- package/dist/{chunk-M3HGBO2Y.js → chunk-ZAC7YPRA.js} +1 -1
- package/dist/{chunk-2VJOSU4H.js → chunk-ZENESDAF.js} +2 -2
- package/dist/{chunk-4JXPLTWV.js → chunk-ZHAPMETO.js} +2 -2
- package/dist/{chunk-IJR6VOLU.js → chunk-ZVR6DUZH.js} +2 -2
- package/dist/components/message-timeline.d.ts +10 -2
- package/dist/composer.js +8 -8
- package/dist/{computer-viewer-5LKRCEVQ.js → computer-viewer-FOIOZUF5.js} +5 -5
- package/dist/connect.js +12 -12
- package/dist/desktop-dictation.js +8 -8
- package/dist/desktop.js +2 -2
- package/dist/editor.js +2 -2
- package/dist/{embedded-new-voice-GHJRY3YL.js → embedded-new-voice-WTXAJNGO.js} +5 -5
- package/dist/{embedded-voice-ASQXBSTX.js → embedded-voice-SIJOPN2G.js} +5 -5
- package/dist/{fleet-decision-row-U7LDVBEM.js → fleet-decision-row-XKQ3GMYT.js} +2 -2
- package/dist/hooks/use-recordings.d.ts +4 -2
- package/dist/in-chat-connect-model.js +5 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.js +66 -60
- package/dist/interaction.js +5 -5
- package/dist/{latest-question-RNVF262Q.js → latest-question-KA7AQYVI.js} +2 -2
- package/dist/machines.js +3 -3
- package/dist/meetings/recorder-context.d.ts +6 -1
- package/dist/meetings/recorder-panel.d.ts +2 -5
- package/dist/meetings-recorder.js +1 -1
- package/dist/meetings.js +25 -23
- package/dist/meetings.js.map +1 -1
- package/dist/messages/en.d.ts +4 -0
- package/dist/messages.js +1 -1
- package/dist/{model-policy-picker-menu-E6XKMFTA.js → model-policy-picker-menu-6N2G7VGX.js} +4 -4
- package/dist/{payment-page-card-DJDKV2LW.js → payment-page-card-IJFZHQ52.js} +4 -4
- package/dist/{platform-activity-row-MSDCSMET.js → platform-activity-row-MFCMGI43.js} +2 -2
- package/dist/{queue-surface-implementation-GUAIG6TK.js → queue-surface-implementation-BBCDWWOP.js} +5 -5
- package/dist/realtime.js +4 -4
- package/dist/{recorder-host-2MYDJPQW.js → recorder-host-LDYYOKG7.js} +5 -5
- package/dist/recordings.js +4 -4
- package/dist/{sandbox-files-W5W2LW4K.js → sandbox-files-VYRBIXJY.js} +6 -6
- package/dist/session-app.js +160 -157
- package/dist/{session-connect-cards-HPH7JOZP.js → session-connect-cards-GBPSL6OT.js} +9 -9
- package/dist/session-connect-cards-GBPSL6OT.js.map +1 -0
- package/dist/session-list-model.js +2 -2
- package/dist/{session-realtime-SDTKFFIR.js → session-realtime-QGU57TND.js} +3 -3
- package/dist/session-realtime-QGU57TND.js.map +1 -0
- package/dist/session-realtime.js +2 -2
- package/dist/session-ui.js +33 -33
- package/dist/session.d.ts +3 -2
- package/dist/session.js +16 -10
- package/dist/sites.js +2 -2
- package/dist/terminal.js +2 -2
- package/dist/this-computer.js +3 -3
- package/dist/timeline/index.d.ts +3 -2
- package/dist/timeline/projection.d.ts +52 -0
- package/dist/timeline/turn-summary-model.d.ts +4 -3
- package/dist/timeline/types.d.ts +8 -2
- package/dist/timeline/use-timeline-pauses.d.ts +12 -0
- package/dist/timeline/work-presentation.d.ts +4 -3
- package/dist/{timeline-annotation-markers-FNILLWNU.js → timeline-annotation-markers-LL6ZVBZH.js} +2 -2
- package/dist/{timeline-annotation-selection-MBCIDO2Q.js → timeline-annotation-selection-WQA76WYC.js} +2 -2
- package/dist/{timeline-annotations-dialog-JPNKLOTE.js → timeline-annotations-dialog-HHETAEZA.js} +3 -3
- package/dist/timeline-model.js +2 -2
- package/dist/ui/access-list.js +5 -5
- package/dist/ui/cadence-picker.js +4 -4
- package/dist/ui/choice-cards.js +3 -3
- package/dist/ui/confirm-dialog.js +2 -2
- package/dist/ui/copy-field.js +3 -3
- package/dist/ui/detail-page.js +2 -2
- package/dist/ui/detail-sheet.js +2 -2
- package/dist/ui/disclosure.js +3 -3
- package/dist/ui/email-chips-input.js +3 -3
- package/dist/ui/field.js +2 -2
- package/dist/ui/flush-form-page.js +3 -3
- package/dist/ui/form-dialog.js +2 -2
- package/dist/ui/list-row.js +3 -3
- package/dist/ui/relative-time.js +2 -2
- package/dist/ui/revision-history.js +4 -4
- package/dist/ui/role-select.js +5 -5
- package/dist/ui/select-menu.js +3 -3
- package/dist/ui/usage-meter.d.ts +8 -2
- package/dist/ui/usage-meter.js +5 -3
- package/dist/usage.js +2 -2
- package/dist/workbench.js +4 -4
- package/package.json +6 -5
- package/src/app/components/agent/agent-capability-picker.test.tsx +1 -1
- package/src/app/components/models/subscription-usage.tsx +178 -0
- package/src/app/components/rail/session-row-content.tsx +27 -0
- package/src/app/components/session/subscription-account-indicator.test.ts +78 -18
- package/src/app/components/session/subscription-account-indicator.tsx +16 -31
- package/src/app/components/session/subscription-account-menu.tsx +79 -101
- package/src/app/components/session/subscription-account.test.ts +161 -54
- package/src/app/components/session/subscription-account.ts +106 -117
- package/src/app/lib/agent-capabilities.tsx +34 -7
- package/src/app/lib/session-branch-cache.tsx +1 -0
- package/src/app/lib/session-pins.tsx +1 -0
- package/src/app/lib/session-row-paused.test.tsx +183 -0
- package/src/app/lib/sessions-group-channels.test.ts +4 -4
- package/src/app/lib/sessions-group.tsx +62 -4
- package/src/app/lib/subscription-accounts.tsx +283 -0
- package/src/app/routes/session.tsx +2 -0
- package/src/components/message-timeline.tsx +14 -2
- package/src/components/session-conversation.tsx +2 -1
- package/src/components/timeline-annotations.tsx +4 -1
- package/src/components/timeline-settlement.ts +1 -1
- package/src/hooks/use-composer.ts +104 -25
- package/src/hooks/use-recordings.ts +5 -0
- package/src/index.ts +5 -0
- package/src/meetings/meeting-detail-page.tsx +4 -2
- package/src/meetings/meetings-pages.test.tsx +38 -0
- package/src/meetings/recorder-context.tsx +28 -5
- package/src/meetings/recorder-panel.tsx +13 -5
- package/src/meetings/recorder-workspace.test.tsx +57 -8
- package/src/messages/en.ts +5 -0
- package/src/recordings-model.ts +7 -0
- package/src/session.ts +8 -1
- package/src/timeline/index.ts +4 -1
- package/src/timeline/projection.ts +228 -16
- package/src/timeline/turn-summary-model.ts +4 -3
- package/src/timeline/turn-summary.tsx +15 -2
- package/src/timeline/types.ts +8 -2
- package/src/timeline/use-timeline-pauses.ts +105 -0
- package/src/timeline/work-presentation.ts +13 -4
- package/src/ui/usage-meter.tsx +10 -7
- package/styles/compiled.css +3 -0
- package/dist/chunk-2OXSB2OL.js.map +0 -1
- package/dist/chunk-3PM3M2Q6.js.map +0 -1
- package/dist/chunk-7YTR3UFO.js.map +0 -1
- package/dist/chunk-7Z76QP64.js.map +0 -1
- package/dist/chunk-JHZRAYI4.js.map +0 -1
- package/dist/chunk-M5IQVMLR.js.map +0 -1
- package/dist/chunk-NQ2CPQJF.js.map +0 -1
- package/dist/chunk-O2UPPN5M.js +0 -2
- package/dist/chunk-O4JOE3R7.js.map +0 -1
- package/dist/chunk-PF2WU2IL.js.map +0 -1
- package/dist/chunk-PSM3CU7N.js.map +0 -1
- package/dist/chunk-PZKHST7A.js.map +0 -1
- package/dist/chunk-Q5K2J5GG.js.map +0 -1
- package/dist/chunk-QPQ7R77C.js.map +0 -1
- package/dist/chunk-QQIZMVAJ.js.map +0 -1
- package/dist/chunk-SK5S2PCK.js.map +0 -1
- package/dist/chunk-SPD4ULVB.js.map +0 -1
- package/dist/chunk-UTRNLNCW.js.map +0 -1
- package/dist/chunk-UU5FBVRX.js.map +0 -1
- package/dist/chunk-VXORMNU4.js.map +0 -1
- package/dist/chunk-WYGTAQMX.js.map +0 -1
- /package/dist/{browser-viewer-ZHQDVHZ2.js.map → app/components/models/subscription-usage.js.map} +0 -0
- /package/dist/{chat-interactive-block-VSDD6X3M.js.map → app/lib/subscription-accounts.js.map} +0 -0
- /package/dist/{chunk-O2UPPN5M.js.map → browser-viewer-F4FL7JKB.js.map} +0 -0
- /package/dist/{computer-viewer-5LKRCEVQ.js.map → chat-interactive-block-4U5JWRSY.js.map} +0 -0
- /package/dist/{chunk-4K64EKM7.js.map → chunk-22YIIM3X.js.map} +0 -0
- /package/dist/{chunk-3NNAC43A.js.map → chunk-2N7ACQ7M.js.map} +0 -0
- /package/dist/{chunk-WDASYY4S.js.map → chunk-2TEYUDJD.js.map} +0 -0
- /package/dist/{chunk-OTW25A6I.js.map → chunk-37JJQNZB.js.map} +0 -0
- /package/dist/{chunk-VCJQQYRE.js.map → chunk-3DWQPURZ.js.map} +0 -0
- /package/dist/{chunk-GTRAH4FG.js.map → chunk-3GWC3FU3.js.map} +0 -0
- /package/dist/{chunk-AB5IW227.js.map → chunk-3ICY6LP3.js.map} +0 -0
- /package/dist/{chunk-WIFDNUKD.js.map → chunk-3OCU5RX5.js.map} +0 -0
- /package/dist/{chunk-UBRQ3PQD.js.map → chunk-3SPDJLOR.js.map} +0 -0
- /package/dist/{chunk-IZXYFWA4.js.map → chunk-3WVLR7UA.js.map} +0 -0
- /package/dist/{chunk-DEHLWZSI.js.map → chunk-3XMB3L57.js.map} +0 -0
- /package/dist/{chunk-AJBDAVX3.js.map → chunk-4IUOBO2H.js.map} +0 -0
- /package/dist/{chunk-NFCS5WYC.js.map → chunk-4KQ3A3EO.js.map} +0 -0
- /package/dist/{chunk-LIJNVIT3.js.map → chunk-4L5B5AZT.js.map} +0 -0
- /package/dist/{chunk-EDDKPIIV.js.map → chunk-4NB3TPNE.js.map} +0 -0
- /package/dist/{chunk-OJWDNNW3.js.map → chunk-4TPTGBIO.js.map} +0 -0
- /package/dist/{chunk-J2WY42FA.js.map → chunk-4UHGW6WF.js.map} +0 -0
- /package/dist/{chunk-7NLF35YL.js.map → chunk-4YN2JLYK.js.map} +0 -0
- /package/dist/{chunk-OOOSGPJL.js.map → chunk-53MYEEMA.js.map} +0 -0
- /package/dist/{chunk-467WDSOK.js.map → chunk-5HYWXPMA.js.map} +0 -0
- /package/dist/{chunk-XMBOLFFS.js.map → chunk-5IMNL6IV.js.map} +0 -0
- /package/dist/{chunk-4Z5X7PLC.js.map → chunk-5MLM5T5C.js.map} +0 -0
- /package/dist/{chunk-YMI27QPF.js.map → chunk-5NKQZVXP.js.map} +0 -0
- /package/dist/{chunk-CYDXCILL.js.map → chunk-5SODSGW7.js.map} +0 -0
- /package/dist/{chunk-Q5EZNBPI.js.map → chunk-5YAJASCO.js.map} +0 -0
- /package/dist/{chunk-M3FDGRB4.js.map → chunk-62XAL5BA.js.map} +0 -0
- /package/dist/{chunk-SGH7I7OY.js.map → chunk-67R6NAFI.js.map} +0 -0
- /package/dist/{chunk-PYB4BFEC.js.map → chunk-6BQLDL6R.js.map} +0 -0
- /package/dist/{chunk-YJSCLGAW.js.map → chunk-6EZYHJTL.js.map} +0 -0
- /package/dist/{chunk-G5UQBTXY.js.map → chunk-6LXIL3Q3.js.map} +0 -0
- /package/dist/{chunk-T67LTMSW.js.map → chunk-6LYVAJFZ.js.map} +0 -0
- /package/dist/{chunk-3L465FBR.js.map → chunk-6WB5UXMZ.js.map} +0 -0
- /package/dist/{chunk-EKJHOWTZ.js.map → chunk-74UGYVCA.js.map} +0 -0
- /package/dist/{chunk-PWUSSSSL.js.map → chunk-7BTNYZC7.js.map} +0 -0
- /package/dist/{chunk-ESXAECZ3.js.map → chunk-7KZFGA25.js.map} +0 -0
- /package/dist/{chunk-EGKARC53.js.map → chunk-7MGDX2TD.js.map} +0 -0
- /package/dist/{chunk-Y3XZEKDQ.js.map → chunk-7N3GFGB6.js.map} +0 -0
- /package/dist/{chunk-AH3DGOTK.js.map → chunk-7SFSN6AX.js.map} +0 -0
- /package/dist/{chunk-6QK65ZWM.js.map → chunk-7TGUHFGO.js.map} +0 -0
- /package/dist/{chunk-QURYQFDN.js.map → chunk-7ZIWO65F.js.map} +0 -0
- /package/dist/{chunk-OYCK4JRS.js.map → chunk-AJHLEJTK.js.map} +0 -0
- /package/dist/{chunk-3PZ3LRPV.js.map → chunk-AN4U7EPH.js.map} +0 -0
- /package/dist/{chunk-77BHKC43.js.map → chunk-APG6CEG7.js.map} +0 -0
- /package/dist/{chunk-FSDQQQIA.js.map → chunk-APHLXQNP.js.map} +0 -0
- /package/dist/{chunk-SN2WENRP.js.map → chunk-AXHQ7QXV.js.map} +0 -0
- /package/dist/{chunk-54U6ZBEX.js.map → chunk-AYTLSPF6.js.map} +0 -0
- /package/dist/{chunk-R33SBMB7.js.map → chunk-BBSKKBMV.js.map} +0 -0
- /package/dist/{chunk-2GCHGWNE.js.map → chunk-BGH6TU2P.js.map} +0 -0
- /package/dist/{chunk-D3PTVN2I.js.map → chunk-BGIYL26H.js.map} +0 -0
- /package/dist/{chunk-BQYRZIZ7.js.map → chunk-BL7UQUC3.js.map} +0 -0
- /package/dist/{chunk-EBTUPRRQ.js.map → chunk-BOUHCYL6.js.map} +0 -0
- /package/dist/{chunk-MKDFYE2E.js.map → chunk-BVNGDFBC.js.map} +0 -0
- /package/dist/{chunk-ICAMYP5M.js.map → chunk-BWJK64CP.js.map} +0 -0
- /package/dist/{chunk-RHXYO4H2.js.map → chunk-BZ2GTCQV.js.map} +0 -0
- /package/dist/{chunk-GIWFLWXG.js.map → chunk-C2KASMJK.js.map} +0 -0
- /package/dist/{chunk-KO3OHHY2.js.map → chunk-CAZDRDQT.js.map} +0 -0
- /package/dist/{chunk-OK7BQMCI.js.map → chunk-CBJRZKZB.js.map} +0 -0
- /package/dist/{chunk-OYOFPNLC.js.map → chunk-CF6NYG7J.js.map} +0 -0
- /package/dist/{chunk-MT2R57SF.js.map → chunk-COITN7WN.js.map} +0 -0
- /package/dist/{chunk-OCXTTKVA.js.map → chunk-CPVOXM2Q.js.map} +0 -0
- /package/dist/{chunk-HYEIA25Y.js.map → chunk-CTZRCBKH.js.map} +0 -0
- /package/dist/{chunk-OCXEY7HE.js.map → chunk-CWL27YTB.js.map} +0 -0
- /package/dist/{chunk-K4DQS2ML.js.map → chunk-D2I33V5P.js.map} +0 -0
- /package/dist/{chunk-736RUNIA.js.map → chunk-DF7WI4JH.js.map} +0 -0
- /package/dist/{chunk-KUE5BOQE.js.map → chunk-DKZYCJCO.js.map} +0 -0
- /package/dist/{chunk-74CBR5YE.js.map → chunk-DQ32FKFQ.js.map} +0 -0
- /package/dist/{chunk-4O2XWOLZ.js.map → chunk-DTKG2YUF.js.map} +0 -0
- /package/dist/{chunk-GMHIOYB7.js.map → chunk-DUDA4V5R.js.map} +0 -0
- /package/dist/{chunk-XUOYNJPB.js.map → chunk-ECROT4M5.js.map} +0 -0
- /package/dist/{chunk-PVB4YVDP.js.map → chunk-EOXV5XGY.js.map} +0 -0
- /package/dist/{chunk-U6552Q3T.js.map → chunk-EQQOZ6DD.js.map} +0 -0
- /package/dist/{chunk-G6ICCGJ3.js.map → chunk-EY6W5H4B.js.map} +0 -0
- /package/dist/{chunk-HWVPLFIW.js.map → chunk-EYRFEWXJ.js.map} +0 -0
- /package/dist/{chunk-U4LTPFD2.js.map → chunk-FKK2PD7K.js.map} +0 -0
- /package/dist/{chunk-PUUEI4W3.js.map → chunk-FPHHIC5K.js.map} +0 -0
- /package/dist/{chunk-SP44O3OU.js.map → chunk-FQM6L22H.js.map} +0 -0
- /package/dist/{chunk-2J77TWGH.js.map → chunk-FW22IREV.js.map} +0 -0
- /package/dist/{chunk-EBIVTDEG.js.map → chunk-G4M6AYDB.js.map} +0 -0
- /package/dist/{chunk-BASI553K.js.map → chunk-G6AZ2WIU.js.map} +0 -0
- /package/dist/{chunk-SJYTQLN3.js.map → chunk-GJ5IDSAX.js.map} +0 -0
- /package/dist/{chunk-TDTD66BK.js.map → chunk-GRDSEZWZ.js.map} +0 -0
- /package/dist/{chunk-MV2CLIO6.js.map → chunk-HBVJIGY2.js.map} +0 -0
- /package/dist/{chunk-R4JA5JFI.js.map → chunk-HCWQLIOE.js.map} +0 -0
- /package/dist/{chunk-MZY3VKKM.js.map → chunk-HEVD4A5G.js.map} +0 -0
- /package/dist/{chunk-DLVIRJGK.js.map → chunk-HNDHSEVJ.js.map} +0 -0
- /package/dist/{chunk-LPKJ77EK.js.map → chunk-HNTZ7B7M.js.map} +0 -0
- /package/dist/{chunk-IN3VQFKS.js.map → chunk-I2FC7CAI.js.map} +0 -0
- /package/dist/{chunk-ZBHGNE2J.js.map → chunk-IEHZFYMH.js.map} +0 -0
- /package/dist/{chunk-DWJ6J3YW.js.map → chunk-IXISEVD7.js.map} +0 -0
- /package/dist/{chunk-TK5FWVZR.js.map → chunk-IZEDVQUD.js.map} +0 -0
- /package/dist/{chunk-HEGV4QMS.js.map → chunk-J42QE4VO.js.map} +0 -0
- /package/dist/{chunk-PRT4J2DL.js.map → chunk-J555XSUM.js.map} +0 -0
- /package/dist/{chunk-SBXSKRFA.js.map → chunk-JNMHFSDF.js.map} +0 -0
- /package/dist/{chunk-KI46GKMD.js.map → chunk-JTBAOPYO.js.map} +0 -0
- /package/dist/{chunk-SXGJL7UT.js.map → chunk-K376MPJH.js.map} +0 -0
- /package/dist/{chunk-OSJ366KR.js.map → chunk-KEBVT55V.js.map} +0 -0
- /package/dist/{chunk-U5UGM5XD.js.map → chunk-KFIZAXHI.js.map} +0 -0
- /package/dist/{chunk-KFNZZ2N6.js.map → chunk-KKGRDBMK.js.map} +0 -0
- /package/dist/{chunk-PLYVGZIN.js.map → chunk-KKIG6DN5.js.map} +0 -0
- /package/dist/{chunk-3OK7Y6ES.js.map → chunk-KKQO2GAA.js.map} +0 -0
- /package/dist/{chunk-DQPIEQGP.js.map → chunk-KO753ZCZ.js.map} +0 -0
- /package/dist/{chunk-YNTLWCF4.js.map → chunk-KYIRWU65.js.map} +0 -0
- /package/dist/{chunk-JKL5S7UQ.js.map → chunk-L6V63DVI.js.map} +0 -0
- /package/dist/{chunk-CV4VVLPZ.js.map → chunk-LCNJ2KNS.js.map} +0 -0
- /package/dist/{chunk-D74Z2N4K.js.map → chunk-LE7YKMTU.js.map} +0 -0
- /package/dist/{chunk-D5TIVCXG.js.map → chunk-LEBEOMVT.js.map} +0 -0
- /package/dist/{embedded-new-voice-GHJRY3YL.js.map → chunk-LKLQVANM.js.map} +0 -0
- /package/dist/{chunk-WXF2RTS4.js.map → chunk-M6URPYUB.js.map} +0 -0
- /package/dist/{chunk-H6BX6WOW.js.map → chunk-MDHFMRBC.js.map} +0 -0
- /package/dist/{chunk-3CDJSKDW.js.map → chunk-MGZO7CHI.js.map} +0 -0
- /package/dist/{chunk-DCEQCGVN.js.map → chunk-MIWU52TW.js.map} +0 -0
- /package/dist/{chunk-LVELUUK6.js.map → chunk-NF6QVVMP.js.map} +0 -0
- /package/dist/{chunk-UMX6DZME.js.map → chunk-NTZ5ZNVK.js.map} +0 -0
- /package/dist/{chunk-FBA2NXYH.js.map → chunk-NWLRABUR.js.map} +0 -0
- /package/dist/{chunk-TNSJFZ6Q.js.map → chunk-O2H2U7YS.js.map} +0 -0
- /package/dist/{chunk-BFFNINCC.js.map → chunk-OAL2PPX4.js.map} +0 -0
- /package/dist/{chunk-WTSQUCHB.js.map → chunk-OCYTHZ4A.js.map} +0 -0
- /package/dist/{chunk-ZAX4XQLN.js.map → chunk-OEDTCIXF.js.map} +0 -0
- /package/dist/{chunk-CHU3RDV4.js.map → chunk-OLVSYB3P.js.map} +0 -0
- /package/dist/{chunk-IFSXVU2S.js.map → chunk-OQHTFOCA.js.map} +0 -0
- /package/dist/{chunk-OXQ2SXVC.js.map → chunk-P56AVROH.js.map} +0 -0
- /package/dist/{chunk-CXAN2FHF.js.map → chunk-PCEJHHGP.js.map} +0 -0
- /package/dist/{chunk-5MIBQ4P5.js.map → chunk-PHGQGVVL.js.map} +0 -0
- /package/dist/{chunk-FLWQJDJ5.js.map → chunk-PUZRHEQI.js.map} +0 -0
- /package/dist/{chunk-OP2GD6QW.js.map → chunk-PV7U6OOJ.js.map} +0 -0
- /package/dist/{chunk-X2QJXDE4.js.map → chunk-PZQACDH5.js.map} +0 -0
- /package/dist/{chunk-CH4UQ4NO.js.map → chunk-PZTS4O6E.js.map} +0 -0
- /package/dist/{chunk-TKQL7EDB.js.map → chunk-Q42QHUAQ.js.map} +0 -0
- /package/dist/{chunk-MRECRNVU.js.map → chunk-QCYGB6TZ.js.map} +0 -0
- /package/dist/{chunk-GSCGKJNK.js.map → chunk-QECMETOF.js.map} +0 -0
- /package/dist/{chunk-RMCLFSMX.js.map → chunk-QGX3LE6H.js.map} +0 -0
- /package/dist/{chunk-HTMQGS63.js.map → chunk-QI3NDQFP.js.map} +0 -0
- /package/dist/{chunk-R5QAL43H.js.map → chunk-RA3Q52O2.js.map} +0 -0
- /package/dist/{chunk-AJDGP2N4.js.map → chunk-RJNOQEJJ.js.map} +0 -0
- /package/dist/{chunk-477DTTMH.js.map → chunk-RSFOFUR7.js.map} +0 -0
- /package/dist/{chunk-JV5ULONH.js.map → chunk-RXR6PMSH.js.map} +0 -0
- /package/dist/{chunk-J2BTILRR.js.map → chunk-SM7HFCGC.js.map} +0 -0
- /package/dist/{chunk-OBGOLHCP.js.map → chunk-T4HK4XCI.js.map} +0 -0
- /package/dist/{chunk-XVLEBB4Y.js.map → chunk-TBWL6YWL.js.map} +0 -0
- /package/dist/{chunk-AAS7OWV6.js.map → chunk-TIDXYWFX.js.map} +0 -0
- /package/dist/{chunk-N3FM4BNA.js.map → chunk-TKHRGY2P.js.map} +0 -0
- /package/dist/{chunk-GU7T2S5N.js.map → chunk-TU2GSZL7.js.map} +0 -0
- /package/dist/{chunk-OI6VI6SU.js.map → chunk-U6HGJXXQ.js.map} +0 -0
- /package/dist/{chunk-4BWMAGJJ.js.map → chunk-UGRW6RTR.js.map} +0 -0
- /package/dist/{chunk-AVXDIRRW.js.map → chunk-UMRUDYUK.js.map} +0 -0
- /package/dist/{chunk-FNXCFIPW.js.map → chunk-UOT2R5ZD.js.map} +0 -0
- /package/dist/{chunk-DIP7YALH.js.map → chunk-USURKJVT.js.map} +0 -0
- /package/dist/{chunk-S27VZ5DO.js.map → chunk-UU6Q67XM.js.map} +0 -0
- /package/dist/{chunk-LTJFV2JI.js.map → chunk-UZ7NP5CW.js.map} +0 -0
- /package/dist/{chunk-H6MJFMHZ.js.map → chunk-V4FO7UOE.js.map} +0 -0
- /package/dist/{chunk-RGR57NYY.js.map → chunk-V4ZOZRCW.js.map} +0 -0
- /package/dist/{chunk-LQKVNREV.js.map → chunk-V57YMKQZ.js.map} +0 -0
- /package/dist/{chunk-XZCCEKPW.js.map → chunk-VOIWZBY6.js.map} +0 -0
- /package/dist/{chunk-E5KOWRDU.js.map → chunk-VPHPLPDA.js.map} +0 -0
- /package/dist/{chunk-OGU73VUN.js.map → chunk-VUL4KPUU.js.map} +0 -0
- /package/dist/{chunk-SFIXTOOJ.js.map → chunk-VWF6ILAR.js.map} +0 -0
- /package/dist/{chunk-FER6EVIY.js.map → chunk-W54BHJO7.js.map} +0 -0
- /package/dist/{chunk-34NV52R3.js.map → chunk-WCYE4BLC.js.map} +0 -0
- /package/dist/{chunk-RISUROBM.js.map → chunk-WTV25ELY.js.map} +0 -0
- /package/dist/{chunk-UO35OEOX.js.map → chunk-WZYGH7CN.js.map} +0 -0
- /package/dist/{chunk-CEMSIU4Z.js.map → chunk-XG2RWUF7.js.map} +0 -0
- /package/dist/{chunk-K3D7IQQP.js.map → chunk-XV7QOT7W.js.map} +0 -0
- /package/dist/{chunk-GOCODNQS.js.map → chunk-XWECT3GX.js.map} +0 -0
- /package/dist/{chunk-5MHMCE2G.js.map → chunk-XZQK2ZLW.js.map} +0 -0
- /package/dist/{chunk-JV3UI7BH.js.map → chunk-Y5BR66OH.js.map} +0 -0
- /package/dist/{chunk-4F3AEJI6.js.map → chunk-YD6XU6FY.js.map} +0 -0
- /package/dist/{chunk-VATYK3JQ.js.map → chunk-YFE47G3C.js.map} +0 -0
- /package/dist/{chunk-ZR5EKJT6.js.map → chunk-YG6TWPP7.js.map} +0 -0
- /package/dist/{chunk-44JWVYJB.js.map → chunk-YH3ARKBB.js.map} +0 -0
- /package/dist/{chunk-752WXSDN.js.map → chunk-YI66STKJ.js.map} +0 -0
- /package/dist/{chunk-QRECBCJM.js.map → chunk-YMVPYMKB.js.map} +0 -0
- /package/dist/{chunk-77SYIH6O.js.map → chunk-YPIXBAF6.js.map} +0 -0
- /package/dist/{chunk-WRMUXZ7C.js.map → chunk-YSWPNY6G.js.map} +0 -0
- /package/dist/{chunk-GTHCHCWW.js.map → chunk-YWNNMBZG.js.map} +0 -0
- /package/dist/{chunk-3DRLCX5V.js.map → chunk-Z3HYM2JT.js.map} +0 -0
- /package/dist/{chunk-M3HGBO2Y.js.map → chunk-ZAC7YPRA.js.map} +0 -0
- /package/dist/{chunk-2VJOSU4H.js.map → chunk-ZENESDAF.js.map} +0 -0
- /package/dist/{chunk-4JXPLTWV.js.map → chunk-ZHAPMETO.js.map} +0 -0
- /package/dist/{chunk-IJR6VOLU.js.map → chunk-ZVR6DUZH.js.map} +0 -0
- /package/dist/{embedded-voice-ASQXBSTX.js.map → computer-viewer-FOIOZUF5.js.map} +0 -0
- /package/dist/{model-policy-picker-menu-E6XKMFTA.js.map → embedded-new-voice-WTXAJNGO.js.map} +0 -0
- /package/dist/{sandbox-files-W5W2LW4K.js.map → embedded-voice-SIJOPN2G.js.map} +0 -0
- /package/dist/{fleet-decision-row-U7LDVBEM.js.map → fleet-decision-row-XKQ3GMYT.js.map} +0 -0
- /package/dist/{latest-question-RNVF262Q.js.map → latest-question-KA7AQYVI.js.map} +0 -0
- /package/dist/{session-connect-cards-HPH7JOZP.js.map → model-policy-picker-menu-6N2G7VGX.js.map} +0 -0
- /package/dist/{payment-page-card-DJDKV2LW.js.map → payment-page-card-IJFZHQ52.js.map} +0 -0
- /package/dist/{platform-activity-row-MSDCSMET.js.map → platform-activity-row-MFCMGI43.js.map} +0 -0
- /package/dist/{queue-surface-implementation-GUAIG6TK.js.map → queue-surface-implementation-BBCDWWOP.js.map} +0 -0
- /package/dist/{recorder-host-2MYDJPQW.js.map → recorder-host-LDYYOKG7.js.map} +0 -0
- /package/dist/{session-realtime-SDTKFFIR.js.map → sandbox-files-VYRBIXJY.js.map} +0 -0
- /package/dist/{timeline-annotation-markers-FNILLWNU.js.map → timeline-annotation-markers-LL6ZVBZH.js.map} +0 -0
- /package/dist/{timeline-annotation-selection-MBCIDO2Q.js.map → timeline-annotation-selection-WQA76WYC.js.map} +0 -0
- /package/dist/{timeline-annotations-dialog-JPNKLOTE.js.map → timeline-annotations-dialog-HHETAEZA.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/recordings-model.ts"],"sourcesContent":["/**\n * Plain helpers for meeting UIs (web, phone, embedders): words for a recording's state, clock\n * times, speaker names and colors, and the transcript grouped into turns.\n * No React here, so each rule is tested on its own.\n */\nimport {\n recordingMicrophoneIsOwner,\n recordingSpeakerDefault,\n type Recording,\n type RecordingSpeaker,\n type RecordingTrack,\n type RecordingTranscriptSegment,\n type RecordingTranscriptionModel,\n type RecordingTranscriptVersion,\n} from \"@opengeni/contracts\";\nimport type { RecorderSnapshot, RecordingUploadStatus } from \"@opengeni/sdk/recordings\";\nimport { createOpenGeniText, type OpenGeniText } from \"./messages/runtime\";\n\nconst defaultText = createOpenGeniText();\n\n/** \"4:07\", \"1:02:09\". Never negative; rounds down to the second. */\nexport function formatClock(milliseconds: number): string {\n const total = Math.max(0, Math.floor(milliseconds / 1000));\n const hours = Math.floor(total / 3600);\n const minutes = Math.floor((total % 3600) / 60);\n const seconds = total % 60;\n const ss = String(seconds).padStart(2, \"0\");\n return hours > 0 ? `${hours}:${String(minutes).padStart(2, \"0\")}:${ss}` : `${minutes}:${ss}`;\n}\n\n/** \"45 sec\", \"12 min\", \"1 h 5 min\": a recording's length in a list, in `msg`'s language. */\nexport function formatDuration(milliseconds: number, msg: OpenGeniText = defaultText): string {\n const seconds = Math.round(Math.max(0, milliseconds) / 1000);\n if (seconds < 60) return msg(\"meetings.recordings.durationSeconds\", { seconds });\n const minutes = Math.round(seconds / 60);\n if (minutes < 60) return msg(\"meetings.recordings.durationMinutes\", { minutes });\n const hours = Math.floor(minutes / 60);\n const rest = minutes % 60;\n return rest === 0\n ? msg(\"meetings.recordings.durationHours\", { hours })\n : msg(\"meetings.recordings.durationHoursMinutes\", { hours, minutes: rest });\n}\n\nexport type MeetingPhase =\n | { kind: \"uploading\" }\n | { kind: \"transcribing\"; version: RecordingTranscriptVersion | null }\n | { kind: \"ready\"; version: RecordingTranscriptVersion }\n | { kind: \"failed\"; version: RecordingTranscriptVersion | null }\n | { kind: \"no_transcript\" };\n\n/**\n * Where a recording is in its life, from the reader's side. A recording still\n * capturing is \"uploading\" (kept for compatibility; it reads \"In progress\"):\n * it is still being recorded, or its last audio is still on its way from the\n * device that recorded it. That device knows which, so it asks\n * {@link meetingHereStatus}. A failed re-run leaves an older complete version\n * current, so the transcript stays readable.\n */\nexport function meetingPhase(recording: Recording): MeetingPhase {\n if (recording.state === \"capturing\") return { kind: \"uploading\" };\n const version = recording.transcript;\n if (version?.state === \"complete\") return { kind: \"ready\", version };\n if (version?.state === \"queued\" || version?.state === \"processing\") {\n return { kind: \"transcribing\", version };\n }\n if (version?.state === \"failed\" || recording.state === \"failed\") {\n return { kind: \"failed\", version: version ?? null };\n }\n if (recording.state === \"processing\") return { kind: \"transcribing\", version: null };\n return { kind: \"no_transcript\" };\n}\n\n/**\n * What this device's recorder knows about one meeting that the server can't\n * yet: it is recording (or paused) here, or it was stopped here and its last\n * few seconds of audio are on their way, which a person reads as Transcribing.\n * The audio uploads while it records, so nothing is left to \"upload\" after\n * Stop unless the connection is down or the server refused it. Null when this\n * device isn't recording that meeting, or when capture failed before Stop\n * finished it; the server's {@link meetingPhase} says the rest.\n *\n * A meeting recorded here earlier (before a reload, a restart, or a move to\n * another page) is finished in the background from the audio kept here: it is\n * `uploading` until the server has it all, then `transcribing`, and\n * `upload_failed` when the server refused it, keeping the audio here for a retry.\n */\nexport type MeetingHereStatus =\n | \"recording\"\n | \"paused\"\n | \"uploading\"\n | \"transcribing\"\n | \"waiting_for_connection\"\n | \"upload_failed\";\n\nexport function meetingHereStatus(\n recorder:\n | (Pick<RecorderSnapshot, \"state\" | \"recordingId\" | \"upload\"> & {\n uploads?: Readonly<Record<string, RecordingUploadStatus>> | undefined;\n })\n | null,\n recordingId: string,\n online = true,\n): MeetingHereStatus | null {\n if (!recorder) return null;\n if (recorder.recordingId !== recordingId) {\n const upload = recorder.uploads?.[recordingId];\n if (!upload || upload.discarded) return null;\n if (upload.failed) return \"upload_failed\";\n if (upload.finalized) return \"transcribing\";\n if (!online || upload.retryingAfterError) return \"waiting_for_connection\";\n return \"uploading\";\n }\n if (recorder.state === \"recording\") return \"recording\";\n if (recorder.state === \"paused\") return \"paused\";\n if (recorder.state === \"idle\" || recorder.state === \"starting\") return null;\n const upload = recorder.upload;\n if (upload?.discarded) return null;\n if (upload?.failed) return \"upload_failed\";\n // Capture failed mid-recording: nothing finishes it until this browser\n // recovers it, so it isn't transcribing yet.\n if (recorder.state === \"failed\" && !upload?.finalized) return null;\n if (!upload?.finalized && (!online || upload?.retryingAfterError)) {\n return \"waiting_for_connection\";\n }\n return \"transcribing\";\n}\n\n/** The upload failure this device's recorder holds for a meeting, current or earlier. */\nexport function meetingUploadFailure(\n recorder:\n | (Pick<RecorderSnapshot, \"recordingId\" | \"upload\"> & {\n uploads?: Readonly<Record<string, RecordingUploadStatus>> | undefined;\n })\n | null,\n recordingId: string,\n): { code: string; message: string } | null {\n if (!recorder) return null;\n const upload =\n recorder.recordingId === recordingId ? recorder.upload : recorder.uploads?.[recordingId];\n return upload?.failed ?? null;\n}\n\n/** Audio up to this long is usually transcribed in a minute or two. */\nconst SHORT_AUDIO_MILLISECONDS = 5 * 60_000;\n\n/**\n * What to say while a meeting is transcribed: a short one is done in a minute\n * or two; a long one takes a while (its words may be timed on our side), so\n * the line says how much audio it is and that the reader needn't wait.\n */\nexport function transcribingText(\n durationMilliseconds: number,\n msg: OpenGeniText = defaultText,\n): string {\n if (durationMilliseconds <= SHORT_AUDIO_MILLISECONDS) {\n return msg(\"meetings.detailPage.transcribingThisUsuallyTakesA\");\n }\n return msg(\"meetings.detailPage.transcribingLongAudio\", {\n duration: formatDuration(durationMilliseconds, msg),\n });\n}\n\n/** Refusals that credits, or a model that doesn't use them, fix. */\nexport function transcriptNeedsCredits(code: string | null | undefined): boolean {\n return (\n code === \"insufficient_credits\" ||\n code === \"allowance_exhausted\" ||\n code === \"monthly_model_cost_limit\"\n );\n}\n\n/** Failures of the provider itself: any other provider may work. */\nconst PROVIDER_FAILURES = new Set([\n \"missing_provider_key\",\n \"provider_unauthorized\",\n \"provider_quota_exceeded\",\n \"policy_blocked\",\n]);\n/** Failures of the model: another model, even the same provider's, may work. */\nconst MODEL_FAILURES = new Set([\n \"provider_too_large\",\n \"provider_not_supported\",\n \"model_unavailable\",\n]);\n\n/**\n * The model to transcribe a failed meeting with instead, as its one direct\n * fix: usable here, not the one that failed (nor its provider, when the\n * provider was the problem), and for a credit refusal one that uses no\n * credits. A subscription comes first, then a model the deployment covers,\n * then the workspace's own key. Null when no other model would help.\n */\nexport function transcriptFixModel(\n code: string | null | undefined,\n failed: { providerId: string; model: string } | null,\n models: readonly RecordingTranscriptionModel[],\n): RecordingTranscriptionModel | null {\n const credits = transcriptNeedsCredits(code);\n if (!code || (!credits && !PROVIDER_FAILURES.has(code) && !MODEL_FAILURES.has(code))) {\n return null;\n }\n const charged = (entry: RecordingTranscriptionModel) =>\n entry.chargedInCredits ?? (entry.funding === \"deployment\" && entry.usdPerHour !== null);\n const rank = (entry: RecordingTranscriptionModel) =>\n entry.funding === \"workspace_subscription\"\n ? 0\n : charged(entry)\n ? 3\n : entry.usdPerHour === null\n ? 1\n : 2;\n const candidates = models.filter((entry) => {\n if (!entry.available || !entry.capabilities.batch) return false;\n if (failed && entry.providerId === failed.providerId) {\n if (!MODEL_FAILURES.has(code) || entry.model === failed.model) return false;\n }\n // The server says which models are charged in credits.\n return !credits || !charged(entry);\n });\n return [...candidates].sort((a, b) => rank(a) - rank(b))[0] ?? null;\n}\n\n/** The one-word state a list row shows, or null when there is nothing to say. */\nexport function meetingStatusLabel(\n phase: MeetingPhase,\n msg: OpenGeniText = defaultText,\n): { label: string; tone: \"progress\" | \"danger\" | \"neutral\" } | null {\n switch (phase.kind) {\n case \"uploading\":\n return { label: msg(\"meetings.recordings.inProgress\"), tone: \"progress\" };\n case \"transcribing\":\n return { label: msg(\"meetings.recordings.transcribing\"), tone: \"progress\" };\n case \"failed\":\n return { label: msg(\"meetings.recordings.transcriptFailed\"), tone: \"danger\" };\n case \"no_transcript\":\n return { label: msg(\"meetings.recordings.noTranscript\"), tone: \"neutral\" };\n case \"ready\":\n return null;\n }\n}\n\n/**\n * Plain words for a transcription error code, with what to do about it. The\n * codes are the worker's: its own (`missing_provider_key`, `invalid_audio`,\n * ...) and the provider's, prefixed `provider_`. `model` names the model the\n * version ran and its provider, when the caller knows them, so a missing key\n * says which provider isn't connected rather than that none is. Its funding\n * says who can connect it (the deployment's own key is its operator's), and\n * `pinned` that the deployment offers no other model to try instead.\n */\nexport function transcriptErrorText(\n code: string | null,\n msg: OpenGeniText = defaultText,\n model?: {\n modelName: string;\n providerName: string;\n funding?: string | undefined;\n pinned?: boolean | undefined;\n } | null,\n): string {\n switch (code) {\n case \"missing_provider_key\": {\n if (!model) return msg(\"meetings.recordings.errorMissingProviderKey\");\n const names = { modelName: model.modelName, providerName: model.providerName };\n if (model.funding === \"deployment\") {\n return model.pinned\n ? msg(\"meetings.recordings.errorMissingProviderKeyForDeploymentPinned\", names)\n : msg(\"meetings.recordings.errorMissingProviderKeyForDeployment\", names);\n }\n return model.pinned\n ? msg(\"meetings.recordings.errorMissingProviderKeyForPinned\", names)\n : msg(\"meetings.recordings.errorMissingProviderKeyFor\", names);\n }\n case \"provider_unauthorized\":\n return msg(\"meetings.recordings.errorProviderUnauthorized\");\n case \"provider_quota_exceeded\":\n return msg(\"meetings.recordings.errorProviderQuotaExceeded\");\n case \"provider_too_large\":\n return msg(\"meetings.recordings.errorProviderTooLarge\");\n case \"provider_not_supported\":\n case \"model_unavailable\":\n return msg(\"meetings.recordings.errorModelUnavailable\");\n case \"invalid_audio\":\n case \"provider_invalid_audio\":\n case \"ffmpeg_failed\":\n return msg(\"meetings.recordings.errorInvalidAudio\");\n case \"storage_unavailable\":\n return msg(\"meetings.recordings.errorStorageUnavailable\");\n case \"region_restricted\":\n return msg(\"inferenceRegion.notSupportedInEu\");\n case \"insufficient_credits\":\n return model\n ? msg(\"meetings.recordings.errorInsufficientCreditsFor\", { modelName: model.modelName })\n : msg(\"meetings.recordings.errorInsufficientCredits\");\n case \"allowance_exhausted\":\n return msg(\"meetings.recordings.errorAllowanceExhausted\");\n case \"monthly_model_cost_limit\":\n return msg(\"meetings.recordings.errorMonthlyCostLimit\");\n case \"policy_blocked\":\n return msg(\"meetings.recordings.errorPolicyBlocked\");\n case \"timed_out\":\n return msg(\"meetings.recordings.errorTimedOut\");\n default:\n return msg(\"meetings.recordings.errorUnknown\");\n }\n}\n\n/**\n * The name to show for a speaker: the person or plain name someone gave it,\n * else \"Speaker 2\" for a model's label, or the track's role for a track label.\n */\nexport function speakerDisplayName(\n label: string | null,\n speakers: readonly RecordingSpeaker[],\n tracks: readonly RecordingTrack[],\n msg: OpenGeniText = defaultText,\n): string {\n if (!label) return msg(\"meetings.recordings.unknownSpeaker\");\n const speaker = speakers.find((candidate) => candidate.label === label);\n if (speaker && speakerIsNamed(label, speakers) && speaker.name.trim()) return speaker.name;\n return defaultSpeakerName(label, tracks, msg);\n}\n\n/** \"Speaker 2\", \"Microphone\" or \"Shared audio\" for an unnamed label, in `msg`'s language. */\nexport function defaultSpeakerName(\n label: string,\n tracks: readonly RecordingTrack[],\n msg: OpenGeniText = defaultText,\n): string {\n const named = recordingSpeakerDefault(label, tracks);\n switch (named.kind) {\n case \"speaker\":\n return msg(\"meetings.recordings.speakerNumber\", { number: named.number });\n case \"microphone\":\n return msg(\"meetings.recordings.microphone\");\n case \"system\":\n return msg(\"meetings.recordings.sharedAudio\");\n case \"track\":\n return msg(\"meetings.recordings.trackNumber\", { number: named.number });\n case \"label\":\n return named.label;\n }\n}\n\n/**\n * A live preview lane's name when the microphone is the person recording\n * (computer or tab audio beside it): `ownerName` for the microphone and\n * \"Others\" for the computer or tab audio. Null otherwise, when lanes are\n * named by their source.\n */\nexport function ownerLiveLaneName(\n tracks: readonly { trackNumber: number; source: RecordingTrack[\"source\"] }[],\n trackNumber: number,\n ownerName: string,\n msg: OpenGeniText = defaultText,\n): string | null {\n if (!recordingMicrophoneIsOwner(tracks)) return null;\n const source = tracks.find((track) => track.trackNumber === trackNumber)?.source;\n if (source === \"microphone\") return ownerName;\n if (source === \"system\") return msg(\"meetings.liveTranscript.others\");\n return null;\n}\n\n/** True when the label has a name of its own: a person, a plain name, or a suggestion. */\nexport function speakerIsNamed(label: string, speakers: readonly RecordingSpeaker[]): boolean {\n const speaker = speakers.find((candidate) => candidate.label === label);\n return Boolean(speaker && (speaker.personId || speaker.source));\n}\n\n/**\n * A stable color slot (1-6, the chart palette) per speaker label, in order of\n * first appearance so the first voice is always the same hue.\n */\nexport function speakerColorSlots(\n segments: readonly RecordingTranscriptSegment[],\n): Map<string, number> {\n const slots = new Map<string, number>();\n for (const segment of segments) {\n const label = segment.speakerLabel;\n if (label && !slots.has(label)) slots.set(label, (slots.size % 6) + 1);\n }\n return slots;\n}\n\nexport type TranscriptTurn = {\n /** First segment index; stable across edits that keep the order. */\n key: number;\n speakerLabel: string | null;\n startMilliseconds: number;\n endMilliseconds: number;\n segments: RecordingTranscriptSegment[];\n};\n\n/**\n * Consecutive segments of one speaker read as one turn, the way a person reads\n * a transcript. A long pause starts a new turn even for the same voice, so a\n * timestamp is never far from the words it marks.\n */\nexport function groupTranscriptTurns(\n segments: readonly RecordingTranscriptSegment[],\n maxGapMilliseconds = 30_000,\n): TranscriptTurn[] {\n const turns: TranscriptTurn[] = [];\n for (const segment of segments) {\n const last = turns.at(-1);\n if (\n last &&\n last.speakerLabel === segment.speakerLabel &&\n segment.startMilliseconds - last.endMilliseconds <= maxGapMilliseconds\n ) {\n last.segments.push(segment);\n last.endMilliseconds = Math.max(last.endMilliseconds, segment.endMilliseconds);\n continue;\n }\n turns.push({\n key: segment.index,\n speakerLabel: segment.speakerLabel,\n startMilliseconds: segment.startMilliseconds,\n endMilliseconds: segment.endMilliseconds,\n segments: [segment],\n });\n }\n return turns;\n}\n\n/** The segment playing at `milliseconds`, or the last one that started before it. */\nexport function activeSegmentIndex(\n segments: readonly RecordingTranscriptSegment[],\n milliseconds: number,\n): number | null {\n let low = 0;\n let high = segments.length - 1;\n let found: number | null = null;\n while (low <= high) {\n const middle = (low + high) >> 1;\n const segment = segments[middle]!;\n if (segment.startMilliseconds <= milliseconds) {\n found = middle;\n low = middle + 1;\n } else {\n high = middle - 1;\n }\n }\n return found === null ? null : segments[found]!.index;\n}\n\n/** \"ElevenLabs Scribe v2 · English · 3 speakers\" style facts for a version. */\nexport function versionSummary(\n version: RecordingTranscriptVersion,\n modelName: string | null,\n locale?: string,\n): string[] {\n const parts = [modelName ?? version.model];\n const languages = version.languages.map((code) => languageName(code, locale)).filter(Boolean);\n if (languages.length > 0) parts.push(languages.join(\", \"));\n return parts;\n}\n\n/** English names for common languages, for runtimes without Intl.DisplayNames (Hermes). */\nconst LANGUAGE_NAMES: Record<string, string> = {\n ar: \"Arabic\",\n cs: \"Czech\",\n da: \"Danish\",\n de: \"German\",\n el: \"Greek\",\n en: \"English\",\n es: \"Spanish\",\n fi: \"Finnish\",\n fr: \"French\",\n he: \"Hebrew\",\n hi: \"Hindi\",\n hu: \"Hungarian\",\n id: \"Indonesian\",\n is: \"Icelandic\",\n it: \"Italian\",\n ja: \"Japanese\",\n ko: \"Korean\",\n nb: \"Norwegian Bokmål\",\n nl: \"Dutch\",\n nn: \"Norwegian Nynorsk\",\n no: \"Norwegian\",\n pl: \"Polish\",\n pt: \"Portuguese\",\n ro: \"Romanian\",\n ru: \"Russian\",\n sv: \"Swedish\",\n th: \"Thai\",\n tr: \"Turkish\",\n uk: \"Ukrainian\",\n vi: \"Vietnamese\",\n zh: \"Chinese\",\n};\n\n// Providers may report ISO 639-2 codes (\"eng\"). Hermes, the phone's\n// JavaScript engine, does not canonicalize them to \"en\", so map them here.\nconst THREE_LETTER_LANGUAGES: Record<string, string> = {\n ara: \"ar\",\n ces: \"cs\",\n cze: \"cs\",\n dan: \"da\",\n deu: \"de\",\n ger: \"de\",\n ell: \"el\",\n gre: \"el\",\n eng: \"en\",\n spa: \"es\",\n fin: \"fi\",\n fra: \"fr\",\n fre: \"fr\",\n heb: \"he\",\n hin: \"hi\",\n hun: \"hu\",\n ind: \"id\",\n isl: \"is\",\n ice: \"is\",\n ita: \"it\",\n jpn: \"ja\",\n kor: \"ko\",\n nob: \"nb\",\n nld: \"nl\",\n dut: \"nl\",\n nno: \"nn\",\n nor: \"no\",\n pol: \"pl\",\n por: \"pt\",\n ron: \"ro\",\n rum: \"ro\",\n rus: \"ru\",\n swe: \"sv\",\n tha: \"th\",\n tur: \"tr\",\n ukr: \"uk\",\n vie: \"vi\",\n zho: \"zh\",\n chi: \"zh\",\n};\n\n/**\n * \"English\" for \"en\" or a provider's \"eng\", named in `locale` (\"engelsk\" in Norwegian);\n * the code itself when no name is known.\n */\nexport function languageName(code: string, locale?: string): string {\n let tag = code;\n try {\n tag = Intl.getCanonicalLocales(code)[0] ?? code;\n } catch {\n // Not a well-formed tag: show it as given.\n }\n const [primary, ...rest] = tag.split(\"-\");\n const twoLetter = THREE_LETTER_LANGUAGES[primary!.toLowerCase()];\n if (twoLetter) tag = [twoLetter, ...rest].join(\"-\");\n try {\n const name = new Intl.DisplayNames(locale ? [locale, \"en\"] : [\"en\"], { type: \"language\" }).of(\n tag,\n );\n // Some languages write language names in lower case (\"norsk\"); a label starts upper case.\n if (name && name !== tag) return name.charAt(0).toLocaleUpperCase(locale) + name.slice(1);\n } catch {\n // No Intl.DisplayNames here.\n }\n return LANGUAGE_NAMES[tag] ?? LANGUAGE_NAMES[tag.split(\"-\")[0]!] ?? tag;\n}\n\nconst MONTH_KEYS = [\n \"time.month.jan\",\n \"time.month.feb\",\n \"time.month.mar\",\n \"time.month.apr\",\n \"time.month.may\",\n \"time.month.jun\",\n \"time.month.jul\",\n \"time.month.aug\",\n \"time.month.sep\",\n \"time.month.oct\",\n \"time.month.nov\",\n \"time.month.dec\",\n] as const;\n\n/**\n * A short, readable default title for a new recording, in local time and the\n * app's own date words and 24-hour clock: \"Meeting, 23 Oct, 14:05\".\n */\nexport function defaultMeetingTitle(now: Date, msg: OpenGeniText = defaultText): string {\n const month = msg(MONTH_KEYS[now.getMonth()] ?? \"time.month.jan\");\n const date = msg(\"time.date\", { day: now.getDate(), month });\n const time = `${String(now.getHours()).padStart(2, \"0\")}:${String(now.getMinutes()).padStart(2, \"0\")}`;\n return msg(\"meetings.recordings.defaultTitle\", { date, time });\n}\n\n/**\n * The title to show for a meeting. One started without a title carries the\n * server's stand-in, \"Recording 2026-10-26 11:15 UTC\"; it shows as a\n * recorder would have named it, in the viewer's language and time.\n */\nexport function meetingTitle(\n recording: Pick<Recording, \"title\" | \"startedAt\">,\n msg: OpenGeniText = defaultText,\n): string {\n const title = recording.title.trim();\n const startedAt = new Date(recording.startedAt);\n if (Number.isNaN(startedAt.getTime())) return title;\n if (title && title !== serverDefaultTitle(startedAt)) return title;\n return defaultMeetingTitle(startedAt, msg);\n}\n\n/** The title the server gives a recording started without one. */\nfunction serverDefaultTitle(startedAt: Date): string {\n return `Recording ${startedAt.toISOString().slice(0, 16).replace(\"T\", \" \")} UTC`;\n}\n\n/** A finished stretch of live text on one track, as the live preview shows it. */\nexport type LiveTranscriptLine = {\n trackNumber: number;\n startMilliseconds: number;\n /** When it ended; without it the line is taken as a moment at its start. */\n endMilliseconds?: number;\n text: string;\n};\n\n/** Consecutive live lines from one track, read as one turn. */\nexport type LiveTranscriptTurn = {\n key: string;\n trackNumber: number;\n startMilliseconds: number;\n texts: string[];\n};\n\n/** Consecutive lines from one track read as one turn. */\nexport function groupLiveTurns(lines: readonly LiveTranscriptLine[]): LiveTranscriptTurn[] {\n const sorted = [...lines].sort(\n (a, b) => a.startMilliseconds - b.startMilliseconds || a.trackNumber - b.trackNumber,\n );\n const turns: LiveTranscriptTurn[] = [];\n for (const line of sorted) {\n const text = line.text.trim();\n if (!text) continue;\n const last = turns.at(-1);\n if (last && last.trackNumber === line.trackNumber) {\n last.texts.push(text);\n continue;\n }\n turns.push({\n key: `${line.trackNumber}:${line.startMilliseconds}`,\n trackNumber: line.trackNumber,\n startMilliseconds: line.startMilliseconds,\n texts: [text],\n });\n }\n return turns;\n}\n\n/** How far apart a microphone line and computer audio may be and still be one sound. */\nconst LIVE_ECHO_SLACK_MILLISECONDS = 2_000;\n/** Matching words an echoed line needs, so one shared \"ja\" or \"okay\" stays. */\nconst LIVE_ECHO_MIN_MATCHED_WORDS = 2;\n/** The share of a microphone line's words heard in computer audio for it to be an echo. */\nconst LIVE_ECHO_MIN_SHARE = 0.7;\n\n/** A line's words as compared across tracks: letters and digits only, any case. */\nfunction liveWordKeys(text: string): string[] {\n return text\n .normalize(\"NFKC\")\n .toLocaleLowerCase()\n .split(/\\s+/u)\n .map((word) => word.replace(/[^\\p{L}\\p{N}]+/gu, \"\"))\n .filter(Boolean);\n}\n\n/**\n * Without headphones the microphone also hears the others in a call from the\n * speakers, so the live preview would show their words twice: from computer\n * audio, and again as if the person recording said them. Leave out a\n * microphone line when most of its words (at least two, and 70%) were heard\n * in computer audio at the same moment. The preview's text comes a sentence\n * at a time, so a line that also holds the person's own words stays whole.\n * The transcript does the same word by word once the recording is done.\n */\nexport function withoutLiveMicrophoneEchoes<Line extends LiveTranscriptLine>(\n lines: readonly Line[],\n tracks: readonly { trackNumber: number; source: RecordingTrack[\"source\"] }[],\n): Line[] {\n if (!recordingMicrophoneIsOwner(tracks)) return [...lines];\n const sourceOf = (trackNumber: number) =>\n tracks.find((track) => track.trackNumber === trackNumber)?.source;\n const computer = lines\n .filter((line) => sourceOf(line.trackNumber) === \"system\")\n .map((line) => ({\n start: line.startMilliseconds,\n end: Math.max(line.startMilliseconds, line.endMilliseconds ?? line.startMilliseconds),\n keys: new Set(liveWordKeys(line.text)),\n }));\n if (computer.length === 0) return [...lines];\n return lines.filter((line) => {\n if (sourceOf(line.trackNumber) !== \"microphone\") return true;\n const keys = liveWordKeys(line.text);\n if (keys.length < LIVE_ECHO_MIN_MATCHED_WORDS) return true;\n const start = line.startMilliseconds;\n const end = Math.max(start, line.endMilliseconds ?? start);\n const heard = computer.filter(\n (other) =>\n other.start <= end + LIVE_ECHO_SLACK_MILLISECONDS &&\n other.end >= start - LIVE_ECHO_SLACK_MILLISECONDS,\n );\n if (heard.length === 0) return true;\n const matched = keys.filter((key) => heard.some((other) => other.keys.has(key))).length;\n return !(\n matched >= LIVE_ECHO_MIN_MATCHED_WORDS && matched / keys.length >= LIVE_ECHO_MIN_SHARE\n );\n });\n}\n\n/**\n * Joins a turn's pieces into readable text. Streaming providers send pieces\n * that end in a trailing ellipsis while they wait, or a space before a full\n * stop; joined naively those read as \"between you….\" or \"dog .\".\n */\nexport function tidyLiveText(pieces: readonly string[]): string {\n return pieces\n .map((piece) => piece.trim())\n .filter(Boolean)\n .join(\" \")\n .replace(/\\s+([.,!?;:])/g, \"$1\")\n .replace(/(?:…|\\.{3})(?=[.,!?;:…])/g, \"\")\n .replace(/([,!?;:])\\1+/g, \"$1\")\n .replace(/(?<!\\.)\\.\\.(?!\\.)/g, \".\")\n .replace(/\\s{2,}/g, \" \");\n}\n\n/** Words still being heard, without the provider's \"still listening\" ellipsis. */\nexport function tidyPartialText(text: string): string {\n return tidyLiveText([text]).replace(/\\s*(?:…|\\.{3})$/, \"\");\n}\n"],"mappings":"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","names":["upload"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/meetings/recorder-context.tsx","../src/meetings/recorder-state.ts"],"sourcesContent":["/**\n * The workspace's one meeting recorder, held above the routes so a recording\n * keeps going while the person moves around the app.\n *\n * The capture code (MediaRecorder, IndexedDB, the uploader) loads lazily: the\n * host mounts the first time someone opens Meetings, or at startup when this\n * browser still holds a recording that hasn't finished uploading. The live\n * snapshot changes several times a second while recording, so it lives in an\n * external store; only the components that read it re-render.\n *\n * In the desktop app, the provider also carries out the call notifications'\n * choices; the host says where Meetings and a meeting are with\n * `onOpenMeetings` and `onOpenMeeting`.\n *\n * A recording belongs to the workspace it started in and keeps going when the\n * person moves to another workspace: the recorder follows the host's current\n * workspace only while nothing is being captured. It belongs to the person\n * too: a host that signs people in passes them as `scope`, and a recording\n * ends at once when they sign out or someone else signs in.\n */\nimport {\n createContext,\n lazy,\n Suspense,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n type ReactNode,\n} from \"react\";\nimport { getDesktopMeetingDetection } from \"@opengeni/sdk/desktop-bridge\";\nimport type { UseRecorderResult } from \"../recordings\";\nimport { canStartRecording, capturing } from \"./recorder-state\";\n\nexport { canStartRecording } from \"./recorder-state\";\n\nexport type MeetingRecorder = UseRecorderResult;\n\n/**\n * A recording someone asked for outside the recorder, such as from a desktop\n * call notification. An empty title leaves the name to Opengeni; `app` marks\n * a title the app guessed (the call app's name), which a calendar event or\n * the conversation replaces.\n */\nexport type MeetingStartRequest = { title: string; titleSource?: \"person\" | \"app\" };\n\nexport type MeetingRecorderStore = {\n get: () => MeetingRecorder | null;\n subscribe: (listener: () => void) => () => void;\n /** Publish the recorder, and the workspace its recordings go to. */\n set: (recorder: MeetingRecorder | null, workspaceId?: string | null) => void;\n /** Recordings whose upload finished in this tab, newest last. */\n finished: () => readonly string[];\n markFinished: (recordingId: string) => void;\n /** A start the recorder panel should make as soon as it can, or null. */\n pendingStart: () => MeetingStartRequest | null;\n requestStart: (request: MeetingStartRequest) => void;\n /** Take the pending start, so it happens once. */\n takeStart: () => MeetingStartRequest | null;\n /** Load the capture code. Idempotent. */\n activate: () => void;\n /**\n * The workspace the recorder's recordings go to: while one records, the\n * workspace it started in, even after the person moved to another one.\n * Absent from stores made before it existed.\n */\n workspaceId?: () => string | null;\n /**\n * Open a recorded meeting in its own workspace, through the host's\n * `onOpenMeeting`. False when the host gave no way to.\n */\n openMeeting?: (recordingId: string, workspaceId: string) => boolean;\n};\n\nexport function createMeetingRecorderStore(\n onActivate: () => void = () => {},\n onOpenMeeting: (recordingId: string, workspaceId: string) => boolean = () => false,\n): MeetingRecorderStore {\n let current: MeetingRecorder | null = null;\n let currentWorkspaceId: string | null = null;\n let finished: string[] = [];\n let pending: MeetingStartRequest | null = null;\n const listeners = new Set<() => void>();\n const notify = () => {\n for (const listener of listeners) listener();\n };\n return {\n get: () => current,\n subscribe: (listener) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n set: (recorder, workspaceId = null) => {\n current = recorder;\n currentWorkspaceId = recorder ? workspaceId : null;\n // A recording that started some other way (the Start button) uses up a\n // start still waiting, so it can't begin a second one after Stop.\n if (pending && capturing(recorder?.state)) pending = null;\n notify();\n },\n workspaceId: () => currentWorkspaceId,\n finished: () => finished,\n markFinished: (recordingId) => {\n finished = [...finished.filter((id) => id !== recordingId), recordingId];\n notify();\n },\n pendingStart: () => pending,\n requestStart: (request) => {\n pending = request;\n onActivate();\n notify();\n },\n takeStart: () => {\n const request = pending;\n if (request) {\n pending = null;\n notify();\n }\n return request;\n },\n activate: onActivate,\n openMeeting: (recordingId, workspaceId) => onOpenMeeting(recordingId, workspaceId),\n };\n}\n\nconst MeetingRecorderContext = createContext<MeetingRecorderStore | null>(null);\n\nexport const MeetingRecorderStoreProvider = MeetingRecorderContext.Provider;\n\nconst LazyRecorderHost = lazy(() => import(\"./recorder-host\"));\n\nconst RECORDING_DATABASE = \"opengeni-recordings\";\n\n/** True when this browser still holds recording chunks from an earlier visit. */\nasync function hasLocalRecordings(): Promise<boolean> {\n if (typeof indexedDB === \"undefined\" || typeof indexedDB.databases !== \"function\") return false;\n try {\n const databases = await indexedDB.databases();\n return databases.some((database) => database.name === RECORDING_DATABASE);\n } catch {\n return false;\n }\n}\n\nexport function MeetingRecorderProvider({\n workspaceId,\n scope,\n client,\n onOpenMeetings,\n onOpenMeeting,\n children,\n}: {\n /** The workspace recordings go to; null while the host is still finding it. */\n workspaceId: string | null;\n /**\n * Who records, such as the signed-in person's id, for a host that mounts\n * this above sign-in. A new value ends a recording at once and starts a\n * fresh recorder; null means nobody is signed in, so there is no recorder.\n * Omit it when the host remounts the provider when the person changes.\n */\n scope?: string | null | undefined;\n /**\n * The SDK client the recorder uploads with, for a host that mounts this\n * above its routes without an <OpenGeniProvider> there. The provider's\n * client otherwise.\n */\n client?: object | undefined;\n /** Show the Meetings page, where a desktop call notification's recording starts. */\n onOpenMeetings?: (() => void) | undefined;\n /**\n * Show one meeting, after a desktop call notification stopped its recording\n * or a recording made in another workspace stopped. `workspaceId` is the\n * workspace the meeting is in, which may not be the one shown.\n */\n onOpenMeeting?: ((recordingId: string, workspaceId: string) => void) | undefined;\n children: ReactNode;\n}) {\n const [active, setActive] = useState(false);\n const openMeeting = useRef(onOpenMeeting);\n useEffect(() => {\n openMeeting.current = onOpenMeeting;\n });\n const store = useMemo(\n () =>\n createMeetingRecorderStore(\n () => setActive(true),\n (recordingId, recordingWorkspaceId) => {\n if (!openMeeting.current) return false;\n openMeeting.current(recordingId, recordingWorkspaceId);\n return true;\n },\n ),\n [],\n );\n useEffect(() => {\n let cancelled = false;\n void hasLocalRecordings().then((found) => {\n if (found && !cancelled) setActive(true);\n });\n return () => {\n cancelled = true;\n };\n }, []);\n // Leaving a workspace must not end a recording made in it: the host, and\n // with it the capture, stays in the recording's workspace until it stops,\n // then follows the host's current workspace. Another person (scope) gets a\n // fresh host at once, which ends the capture.\n const busy = useSyncExternalStore(\n store.subscribe,\n () => capturing(store.get()?.state),\n () => false,\n );\n useDesktopMeetingRequests(store, {\n // The desktop app asks about calls only while a page can record them:\n // someone signed in, with a workspace to record to, or a recording going.\n canRecord: scope !== null && (workspaceId !== null || busy),\n signedOut: scope === null,\n onOpenMeetings,\n });\n // A start someone asked for belongs to who was signed in then.\n useEffect(() => {\n store.takeStart();\n }, [store, scope]);\n const [host, setHost] = useState({ scope, workspaceId });\n if (host.scope !== scope || (!busy && host.workspaceId !== workspaceId)) {\n setHost({ scope, workspaceId });\n }\n const hostWorkspaceId = host.scope === scope ? host.workspaceId : workspaceId;\n return (\n <MeetingRecorderContext.Provider value={store}>\n {children}\n {active && scope !== null && hostWorkspaceId ? (\n <Suspense fallback={null}>\n <LazyRecorderHost\n key={`${scope ?? \"\"}:${hostWorkspaceId}`}\n store={store}\n workspaceId={hostWorkspaceId}\n client={client}\n />\n </Suspense>\n ) : null}\n </MeetingRecorderContext.Provider>\n );\n}\n\nconst NO_FINISHED: readonly string[] = [];\n\n/**\n * The desktop app's meeting card: \"Record\" opens Meetings and starts\n * recording the call; \"Stop recording\" (the call ended) stops and opens the\n * meeting.\n */\nfunction useDesktopMeetingRequests(\n store: MeetingRecorderStore,\n navigation: {\n canRecord: boolean;\n signedOut: boolean;\n onOpenMeetings?: (() => void) | undefined;\n },\n): void {\n const latest = useRef(navigation);\n useEffect(() => {\n latest.current = navigation;\n });\n const canRecord = navigation.canRecord;\n useEffect(() => {\n // Taking choices tells the app this page can record; stopping while the\n // page stays (signed out, no workspace) tells it nobody can.\n if (!canRecord) return;\n // The bridge itself, not the app layer's helper, which would bring every\n // contract into this module, mounted above a host's routes. Any Electron\n // app that embeds these pages can offer it, not only the Opengeni app.\n const detection = getDesktopMeetingDetection();\n if (!detection) return;\n return detection.onRequest((request) => {\n const recorder = store.get();\n if (request.kind === \"record\") {\n // Nobody signed in: a start kept for later would record, for whoever\n // signs in next, a call that may be long over.\n if (latest.current.signedOut) return;\n // Already recording shows that recording rather than start a second one.\n // The call app's name is only a guess at the meeting's.\n if (canStartRecording(recorder?.state)) {\n store.requestStart({ title: request.title, titleSource: \"app\" });\n }\n latest.current.onOpenMeetings?.();\n return;\n }\n const recordingId = recorder?.recordingId ?? null;\n const recordingWorkspaceId = store.workspaceId?.() ?? null;\n if (request.kind === \"open\") {\n // The app's menu: show the meeting this page records, its live transcript.\n const opened =\n recordingId && recordingWorkspaceId && capturing(recorder?.state)\n ? store.openMeeting?.(recordingId, recordingWorkspaceId)\n : false;\n if (!opened) latest.current.onOpenMeetings?.();\n return;\n }\n if (request.kind !== \"stop\") return;\n if (!recorder || (recorder.state !== \"recording\" && recorder.state !== \"paused\")) return;\n void recorder.stop().then(() => {\n if (recordingId && recordingWorkspaceId) {\n store.openMeeting?.(recordingId, recordingWorkspaceId);\n }\n });\n });\n }, [store, canRecord]);\n}\n\n/** The start a desktop notification asked for, until the recorder panel takes it. */\nexport function usePendingMeetingStart(): {\n request: MeetingStartRequest | null;\n take: () => MeetingStartRequest | null;\n} {\n const store = useContext(MeetingRecorderContext);\n const request = useSyncExternalStore(\n store?.subscribe ?? noopSubscribe,\n store?.pendingStart ?? nullSnapshot,\n nullSnapshot,\n );\n return { request, take: store?.takeStart ?? nullSnapshot };\n}\n\n/** The live recorder, loading it on first use. Null until the capture code is ready. */\nexport function useMeetingRecorder(): {\n recorder: MeetingRecorder | null;\n finished: readonly string[];\n /** The workspace the recorder's recording is in; may differ from the one shown. */\n workspaceId: string | null;\n /**\n * Open a meeting the recorder made in its own workspace. False when the\n * host gave no way to, so the caller opens it as usual.\n */\n openMeeting: (recordingId: string, workspaceId: string) => boolean;\n} {\n const store = useContext(MeetingRecorderContext);\n useEffect(() => store?.activate(), [store]);\n const recorder = useSyncExternalStore(\n store?.subscribe ?? noopSubscribe,\n store?.get ?? nullSnapshot,\n nullSnapshot,\n );\n const finished = useSyncExternalStore(\n store?.subscribe ?? noopSubscribe,\n store?.finished ?? (() => NO_FINISHED),\n () => NO_FINISHED,\n );\n const workspaceId = useSyncExternalStore(\n store?.subscribe ?? noopSubscribe,\n store?.workspaceId ?? nullSnapshot,\n nullSnapshot,\n );\n return { recorder, finished, workspaceId, openMeeting: store?.openMeeting ?? neverOpens };\n}\n\n/** Only the recorder's state word, for the rail: re-renders on state changes, not on every tick. */\nexport function useMeetingRecorderState(): MeetingRecorder[\"state\"] | null {\n const store = useContext(MeetingRecorderContext);\n return useSyncExternalStore(\n store?.subscribe ?? noopSubscribe,\n () => store?.get()?.state ?? null,\n () => null,\n );\n}\n\n/**\n * The recorder's Start and Stop, for the app's actions (⌘K, keys, the desktop\n * menu bar). Null without a recorder provider. Re-renders on state changes,\n * not on every tick.\n */\nexport type MeetingRecorderControls = {\n /** The recorder's state; null until its capture code loads. */\n state: MeetingRecorder[\"state\"] | null;\n /** Whether this browser can record; null until the capture code loads. */\n supported: boolean | null;\n /**\n * Start recording as the Meetings page's Start recording button does, once\n * that page's recorder is ready; the caller shows Meetings next. Does\n * nothing while a recording is going.\n */\n requestStart: () => void;\n /** Stop the recording and open it, as a desktop call notification's Stop does. */\n stop: () => Promise<StoppedMeeting | null>;\n};\n\n/** The meeting a Stop ended; `opened` is false when the host gave no way to open it. */\nexport type StoppedMeeting = { recordingId: string; workspaceId: string; opened: boolean };\n\nexport function useMeetingRecorderControls(): MeetingRecorderControls | null {\n const store = useContext(MeetingRecorderContext);\n const state = useSyncExternalStore(\n store?.subscribe ?? noopSubscribe,\n () => store?.get()?.state ?? null,\n () => null,\n );\n const supported = useSyncExternalStore(\n store?.subscribe ?? noopSubscribe,\n () => store?.get()?.supported ?? null,\n () => null,\n );\n return useMemo(() => {\n if (!store) return null;\n return {\n state,\n supported,\n requestStart: () => {\n if (canStartRecording(store.get()?.state)) store.requestStart({ title: \"\" });\n },\n stop: async () => {\n const recorder = store.get();\n if (!recorder || (recorder.state !== \"recording\" && recorder.state !== \"paused\")) {\n return null;\n }\n const recordingId = recorder.recordingId;\n const recordingWorkspaceId = store.workspaceId?.() ?? null;\n await recorder.stop();\n if (!recordingId || !recordingWorkspaceId) return null;\n const opened = store.openMeeting?.(recordingId, recordingWorkspaceId) ?? false;\n return { recordingId, workspaceId: recordingWorkspaceId, opened };\n },\n };\n }, [store, state, supported]);\n}\n\nfunction noopSubscribe(): () => void {\n return () => {};\n}\n\nfunction nullSnapshot(): null {\n return null;\n}\n\nfunction neverOpens(): boolean {\n return false;\n}\n","/**\n * What the recorder's state word means for starting and keeping a recording.\n * Pure, so the app's action registry can read it without the recorder's\n * React context.\n */\nimport type { RecorderState } from \"@opengeni/sdk/recordings\";\n\n/** States in which the recorder holds a capture that unmounting its host would end. */\nexport function capturing(state: RecorderState | null | undefined): boolean {\n return (\n state === \"starting\" || state === \"recording\" || state === \"paused\" || state === \"stopping\"\n );\n}\n\n/**\n * States in which Start recording starts a new recording: nothing recorded\n * yet, the last one stopped, or the last start failed. Null is a recorder\n * whose capture code hasn't loaded yet.\n */\nexport function canStartRecording(state: RecorderState | null | undefined): boolean {\n return !capturing(state);\n}\n"],"mappings":"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","names":[]}
|