@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
|
@@ -1503,6 +1503,44 @@ describe("Meeting page", () => {
|
|
|
1503
1503
|
}
|
|
1504
1504
|
});
|
|
1505
1505
|
|
|
1506
|
+
test("a delayed subscription plan refusal offers upgrading, not adding credits", async () => {
|
|
1507
|
+
const fixture = createMeetingsFixture();
|
|
1508
|
+
const client = {
|
|
1509
|
+
...fixture.client,
|
|
1510
|
+
getRecording: async (workspaceId: string, id: string) => {
|
|
1511
|
+
const recording = await fixture.client.getRecording(workspaceId, id);
|
|
1512
|
+
return {
|
|
1513
|
+
...recording,
|
|
1514
|
+
transcript: { ...recording.transcript!, errorCode: "subscription_plan_required" },
|
|
1515
|
+
};
|
|
1516
|
+
},
|
|
1517
|
+
} as typeof fixture.client;
|
|
1518
|
+
let opened = 0;
|
|
1519
|
+
const view = await render(
|
|
1520
|
+
<MeetingDetailPage
|
|
1521
|
+
workspaceId={fixture.workspaceId}
|
|
1522
|
+
recordingId={FAILED_RECORDING_ID}
|
|
1523
|
+
viewerSubjectId={fixture.viewerSubjectId}
|
|
1524
|
+
recordings={client}
|
|
1525
|
+
onBack={() => {}}
|
|
1526
|
+
onOpenBilling={() => {
|
|
1527
|
+
opened++;
|
|
1528
|
+
}}
|
|
1529
|
+
/>,
|
|
1530
|
+
);
|
|
1531
|
+
try {
|
|
1532
|
+
await waitForText(view.container, "Upgrade to Pro to use your own subscription.");
|
|
1533
|
+
const buttons = [...view.container.querySelectorAll("button")];
|
|
1534
|
+
expect(buttons.some((button) => button.textContent?.trim() === "Add credits")).toBe(false);
|
|
1535
|
+
const upgrade = buttons.find((button) => button.textContent?.trim() === "Upgrade to Pro")!;
|
|
1536
|
+
expect(upgrade).toBeDefined();
|
|
1537
|
+
await act(async () => upgrade.click());
|
|
1538
|
+
expect(opened).toBe(1);
|
|
1539
|
+
} finally {
|
|
1540
|
+
await view.unmount();
|
|
1541
|
+
}
|
|
1542
|
+
});
|
|
1543
|
+
|
|
1506
1544
|
/** The fixture's failed meeting, refused for credits on the deployment's model. */
|
|
1507
1545
|
async function creditRefusal(withSubscription: boolean) {
|
|
1508
1546
|
const fixture = createMeetingsFixture();
|
|
@@ -42,9 +42,14 @@ export type MeetingRecorder = UseRecorderResult;
|
|
|
42
42
|
* A recording someone asked for outside the recorder, such as from a desktop
|
|
43
43
|
* call notification. An empty title leaves the name to Opengeni; `app` marks
|
|
44
44
|
* a title the app guessed (the call app's name), which a calendar event or
|
|
45
|
-
* the conversation replaces.
|
|
45
|
+
* the conversation replaces. `calendarEvent` is the owner's calendar event
|
|
46
|
+
* the meeting is of, such as one joined from a reminder; it names the meeting.
|
|
46
47
|
*/
|
|
47
|
-
export type MeetingStartRequest = {
|
|
48
|
+
export type MeetingStartRequest = {
|
|
49
|
+
title: string;
|
|
50
|
+
titleSource?: "person" | "app";
|
|
51
|
+
calendarEvent?: { provider: "google" | "microsoft"; id: string };
|
|
52
|
+
};
|
|
48
53
|
|
|
49
54
|
export type MeetingRecorderStore = {
|
|
50
55
|
get: () => MeetingRecorder | null;
|
|
@@ -280,10 +285,28 @@ function useDesktopMeetingRequests(
|
|
|
280
285
|
// Nobody signed in: a start kept for later would record, for whoever
|
|
281
286
|
// signs in next, a call that may be long over.
|
|
282
287
|
if (latest.current.signedOut) return;
|
|
283
|
-
//
|
|
284
|
-
//
|
|
288
|
+
// The call app's name is only a guess at the meeting's; the calendar
|
|
289
|
+
// event a reminder joined names it.
|
|
290
|
+
const start: MeetingStartRequest = {
|
|
291
|
+
title: request.title,
|
|
292
|
+
titleSource: "app",
|
|
293
|
+
...(request.calendarEvent ? { calendarEvent: request.calendarEvent } : {}),
|
|
294
|
+
};
|
|
295
|
+
// Already recording shows that recording rather than start a second
|
|
296
|
+
// one, unless the person chose to switch to recording the next meeting:
|
|
297
|
+
// this one stops and is kept, then the next starts.
|
|
285
298
|
if (canStartRecording(recorder?.state)) {
|
|
286
|
-
store.requestStart(
|
|
299
|
+
store.requestStart(start);
|
|
300
|
+
} else if (
|
|
301
|
+
request.replace === true &&
|
|
302
|
+
recorder &&
|
|
303
|
+
(recorder.state === "recording" || recorder.state === "paused")
|
|
304
|
+
) {
|
|
305
|
+
// A stop that fails leaves that recording showing its error, and starts nothing.
|
|
306
|
+
void recorder.stop().then(
|
|
307
|
+
() => store.requestStart(start),
|
|
308
|
+
() => undefined,
|
|
309
|
+
);
|
|
287
310
|
}
|
|
288
311
|
latest.current.onOpenMeetings?.();
|
|
289
312
|
return;
|
|
@@ -48,7 +48,7 @@ import { Notice } from "../ui/notice";
|
|
|
48
48
|
import { cn } from "../app/lib/utils";
|
|
49
49
|
|
|
50
50
|
import { formatClock, ownerLiveLaneName } from "../recordings";
|
|
51
|
-
import type { MeetingRecorder } from "./recorder-context";
|
|
51
|
+
import type { MeetingRecorder, MeetingStartRequest } from "./recorder-context";
|
|
52
52
|
import { canStartRecording } from "./recorder-state";
|
|
53
53
|
import { LiveTranscript, liveStatus, type LiveTranscriptLine } from "./live-transcript";
|
|
54
54
|
import { DETECT_LANGUAGE, meetingLanguageOptions } from "./meeting-languages";
|
|
@@ -618,7 +618,7 @@ function RecorderPanelContent({
|
|
|
618
618
|
*/
|
|
619
619
|
autoStart?: {
|
|
620
620
|
pending: boolean;
|
|
621
|
-
take: () =>
|
|
621
|
+
take: () => MeetingStartRequest | null;
|
|
622
622
|
} | null;
|
|
623
623
|
/** The host's own id for what new recordings belong to, such as a project. */
|
|
624
624
|
externalRef?: string | null | undefined;
|
|
@@ -645,8 +645,15 @@ function RecorderPanelContent({
|
|
|
645
645
|
const state = recorder?.state ?? "idle";
|
|
646
646
|
const live = state === "recording" || state === "paused" || state === "stopping";
|
|
647
647
|
|
|
648
|
-
/**
|
|
649
|
-
|
|
648
|
+
/**
|
|
649
|
+
* `guess` is the app's name for the meeting, used only when nobody typed
|
|
650
|
+
* one; `calendarEvent` the calendar event it is of, which names it.
|
|
651
|
+
*/
|
|
652
|
+
const start = async (
|
|
653
|
+
titleText: string = title,
|
|
654
|
+
guess?: string,
|
|
655
|
+
calendarEvent?: MeetingStartRequest["calendarEvent"],
|
|
656
|
+
) => {
|
|
650
657
|
if (!recorder) return;
|
|
651
658
|
setErrorDismissed(false);
|
|
652
659
|
const name = titleText.trim();
|
|
@@ -658,6 +665,7 @@ function RecorderPanelContent({
|
|
|
658
665
|
systemAudio: tabAudio,
|
|
659
666
|
...(liveOn ? { liveTranscript: true } : {}),
|
|
660
667
|
...(externalRef ? { externalRef } : {}),
|
|
668
|
+
...(calendarEvent ? { calendarEvent } : {}),
|
|
661
669
|
// Names their microphone in the transcript when Opengeni has no name for them.
|
|
662
670
|
...(viewerName?.trim() ? { ownerName: viewerName } : {}),
|
|
663
671
|
// Sent even when it's the workspace's, so this meeting keeps it.
|
|
@@ -679,7 +687,7 @@ function RecorderPanelContent({
|
|
|
679
687
|
if (!request) return;
|
|
680
688
|
// The call app's name is a guess: a title already typed wins over it.
|
|
681
689
|
if (request.titleSource === "app") {
|
|
682
|
-
void startRef.current(undefined, request.title);
|
|
690
|
+
void startRef.current(undefined, request.title, request.calendarEvent);
|
|
683
691
|
return;
|
|
684
692
|
}
|
|
685
693
|
// A start without a title (the Start recording key) keeps one already typed, as the button does.
|
|
@@ -6,7 +6,11 @@ import { GlobalRegistrator } from "@happy-dom/global-registrator";
|
|
|
6
6
|
import { act, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
7
7
|
import { createRoot } from "react-dom/client";
|
|
8
8
|
|
|
9
|
-
import type {
|
|
9
|
+
import type {
|
|
10
|
+
MeetingRecorder,
|
|
11
|
+
MeetingRecorderStore,
|
|
12
|
+
MeetingStartRequest,
|
|
13
|
+
} from "./recorder-context";
|
|
10
14
|
|
|
11
15
|
beforeAll(() => {
|
|
12
16
|
GlobalRegistrator.register();
|
|
@@ -83,7 +87,17 @@ async function until(check: () => boolean) {
|
|
|
83
87
|
|
|
84
88
|
type Desktop = {
|
|
85
89
|
listener:
|
|
86
|
-
| ((
|
|
90
|
+
| ((
|
|
91
|
+
request:
|
|
92
|
+
| {
|
|
93
|
+
kind: "record";
|
|
94
|
+
title?: string;
|
|
95
|
+
calendarEvent?: { provider: "google" | "microsoft"; id: string };
|
|
96
|
+
replace?: boolean;
|
|
97
|
+
}
|
|
98
|
+
| { kind: "stop" }
|
|
99
|
+
| { kind: "open" },
|
|
100
|
+
) => void)
|
|
87
101
|
| null;
|
|
88
102
|
};
|
|
89
103
|
|
|
@@ -118,7 +132,7 @@ function mountProvider() {
|
|
|
118
132
|
};
|
|
119
133
|
const opened: string[] = [];
|
|
120
134
|
const meetingsOpened: string[] = [];
|
|
121
|
-
let pendingStart: () =>
|
|
135
|
+
let pendingStart: () => MeetingStartRequest | null = () => null;
|
|
122
136
|
let open: ((recordingId: string, workspaceId: string) => boolean) | null = null;
|
|
123
137
|
function Probe() {
|
|
124
138
|
const current = useMeetingRecorder();
|
|
@@ -129,23 +143,24 @@ function mountProvider() {
|
|
|
129
143
|
}
|
|
130
144
|
function PendingStart() {
|
|
131
145
|
const { take } = usePendingMeetingStart();
|
|
132
|
-
pendingStart =
|
|
146
|
+
pendingStart = take;
|
|
133
147
|
return null;
|
|
134
148
|
}
|
|
135
149
|
const container = document.createElement("div");
|
|
136
150
|
document.body.append(container);
|
|
137
151
|
const root = createRoot(container);
|
|
138
|
-
|
|
152
|
+
const view = {
|
|
139
153
|
seen,
|
|
140
154
|
opened,
|
|
141
155
|
meetingsOpened,
|
|
142
156
|
// Taking the pending start clears provider state, so it runs inside act.
|
|
143
|
-
takePendingStart: () =>
|
|
144
|
-
|
|
157
|
+
takePendingStart: () => view.takePendingRequest() !== null,
|
|
158
|
+
takePendingRequest: () => {
|
|
159
|
+
let taken: MeetingStartRequest | null = null;
|
|
145
160
|
act(() => {
|
|
146
161
|
taken = pendingStart();
|
|
147
162
|
});
|
|
148
|
-
return taken;
|
|
163
|
+
return taken as MeetingStartRequest | null;
|
|
149
164
|
},
|
|
150
165
|
open: (recordingId: string, workspaceId: string) => open!(recordingId, workspaceId),
|
|
151
166
|
render: (workspaceId: string | null, options: { scope?: string | null } = {}) =>
|
|
@@ -170,6 +185,7 @@ function mountProvider() {
|
|
|
170
185
|
container.remove();
|
|
171
186
|
},
|
|
172
187
|
};
|
|
188
|
+
return view;
|
|
173
189
|
}
|
|
174
190
|
|
|
175
191
|
describe("A recording and the workspace it was made in", () => {
|
|
@@ -423,4 +439,37 @@ describe("A recording and the person who made it", () => {
|
|
|
423
439
|
removeDesktop();
|
|
424
440
|
}
|
|
425
441
|
});
|
|
442
|
+
test("a reminder's Join and record this one stops the recording, then starts the next meeting's", async () => {
|
|
443
|
+
events.length = 0;
|
|
444
|
+
const desktop = installDesktop();
|
|
445
|
+
const view = mountProvider();
|
|
446
|
+
try {
|
|
447
|
+
await view.render("workspace-a");
|
|
448
|
+
await until(() => view.seen.recorder !== null);
|
|
449
|
+
await settle();
|
|
450
|
+
await act(async () => setStates.get("workspace-a")!("recording"));
|
|
451
|
+
const calendarEvent = { provider: "google" as const, id: "event-2" };
|
|
452
|
+
// Without replace, a reminder's Join shows the recording going on.
|
|
453
|
+
await act(async () =>
|
|
454
|
+
desktop.listener!({ kind: "record", title: "Planning", calendarEvent }),
|
|
455
|
+
);
|
|
456
|
+
expect(view.takePendingRequest()).toBeNull();
|
|
457
|
+
expect(view.seen.recorder?.state).toBe("recording");
|
|
458
|
+
// With it, the recording stops and is kept, then the next one starts for its event.
|
|
459
|
+
await act(async () =>
|
|
460
|
+
desktop.listener!({ kind: "record", title: "Planning", calendarEvent, replace: true }),
|
|
461
|
+
);
|
|
462
|
+
await settle();
|
|
463
|
+
expect(view.seen.recorder?.state).toBe("stopped");
|
|
464
|
+
expect(view.takePendingRequest()).toEqual({
|
|
465
|
+
title: "Planning",
|
|
466
|
+
titleSource: "app",
|
|
467
|
+
calendarEvent,
|
|
468
|
+
});
|
|
469
|
+
expect(view.meetingsOpened).toEqual(["workspace-a", "workspace-a"]);
|
|
470
|
+
} finally {
|
|
471
|
+
await view.unmount();
|
|
472
|
+
removeDesktop();
|
|
473
|
+
}
|
|
474
|
+
});
|
|
426
475
|
});
|
package/src/messages/en.ts
CHANGED
|
@@ -2524,6 +2524,7 @@ export const englishMessages = {
|
|
|
2524
2524
|
"meetings.detailPage.aboutLessThan001": "Less than $0.01 for this {duration} meeting.",
|
|
2525
2525
|
"meetings.detailPage.aboutThisTranscript": "About this transcript",
|
|
2526
2526
|
"meetings.detailPage.addCredits": "Add credits",
|
|
2527
|
+
"meetings.detailPage.upgradeToPro": "Upgrade to Pro",
|
|
2527
2528
|
"meetings.detailPage.auto": "Auto",
|
|
2528
2529
|
"meetings.detailPage.backToMeetings": "Back to Meetings",
|
|
2529
2530
|
"meetings.detailPage.canTLoadThePreview": "Can't show the live text right now",
|
|
@@ -2945,6 +2946,8 @@ export const englishMessages = {
|
|
|
2945
2946
|
"The credit allowance is used up for now. An admin can raise it, or transcribe with a model that doesn't use credits.",
|
|
2946
2947
|
"meetings.recordings.errorMonthlyCostLimit":
|
|
2947
2948
|
"This organization has reached its monthly spending limit. An admin can raise it, or transcribe with a model that doesn't use credits.",
|
|
2949
|
+
"meetings.recordings.errorSubscriptionApiUnavailable":
|
|
2950
|
+
"Connected subscriptions aren't available through the API. Choose a credit-billed model.",
|
|
2948
2951
|
"meetings.recordings.errorPolicyBlocked":
|
|
2949
2952
|
"This organization's policy doesn't allow this model. Try another model.",
|
|
2950
2953
|
"meetings.recordings.errorTimedOut":
|
|
@@ -3740,6 +3743,7 @@ export const englishMessages = {
|
|
|
3740
3743
|
"native.timeline.messages.onAMachine": "On a machine",
|
|
3741
3744
|
"native.timeline.messages.output": "Output",
|
|
3742
3745
|
"native.timeline.messages.pauseGoal": "Pause goal",
|
|
3746
|
+
"native.timeline.messages.paused": "Paused",
|
|
3743
3747
|
"native.timeline.messages.pin": "Pin",
|
|
3744
3748
|
"native.timeline.messages.pinned": "Pinned",
|
|
3745
3749
|
"native.timeline.messages.proposedKnowledge": "Proposed knowledge",
|
|
@@ -6081,6 +6085,7 @@ export const englishMessages = {
|
|
|
6081
6085
|
"timeline.turnSummary.contextCompactedExpandForDetails": "Context compacted; expand for details",
|
|
6082
6086
|
"timeline.turnSummary.copyTurn": "Copy turn",
|
|
6083
6087
|
"timeline.turnSummary.interrupted": "· interrupted",
|
|
6088
|
+
"timeline.turnSummary.paused": "Paused",
|
|
6084
6089
|
"timeline.turnSummary.preparation": "Preparation",
|
|
6085
6090
|
"timeline.turnSummary.steps": "Steps",
|
|
6086
6091
|
"timeline.turnSummary.waiting": "Waiting",
|
package/src/recordings-model.ts
CHANGED
|
@@ -175,6 +175,7 @@ const PROVIDER_FAILURES = new Set([
|
|
|
175
175
|
"provider_unauthorized",
|
|
176
176
|
"provider_quota_exceeded",
|
|
177
177
|
"policy_blocked",
|
|
178
|
+
"subscription_api_unavailable",
|
|
178
179
|
]);
|
|
179
180
|
/** Failures of the model: another model, even the same provider's, may work. */
|
|
180
181
|
const MODEL_FAILURES = new Set([
|
|
@@ -211,6 +212,8 @@ export function transcriptFixModel(
|
|
|
211
212
|
: 2;
|
|
212
213
|
const candidates = models.filter((entry) => {
|
|
213
214
|
if (!entry.available || !entry.capabilities.batch) return false;
|
|
215
|
+
if (code === "subscription_api_unavailable" && entry.funding === "workspace_subscription")
|
|
216
|
+
return false;
|
|
214
217
|
if (failed && entry.providerId === failed.providerId) {
|
|
215
218
|
if (!MODEL_FAILURES.has(code) || entry.model === failed.model) return false;
|
|
216
219
|
}
|
|
@@ -259,6 +262,10 @@ export function transcriptErrorText(
|
|
|
259
262
|
} | null,
|
|
260
263
|
): string {
|
|
261
264
|
switch (code) {
|
|
265
|
+
case "subscription_plan_required":
|
|
266
|
+
return msg("lib.format.subscriptionUpgradeRequiredHeadline");
|
|
267
|
+
case "subscription_api_unavailable":
|
|
268
|
+
return msg("meetings.recordings.errorSubscriptionApiUnavailable");
|
|
262
269
|
case "missing_provider_key": {
|
|
263
270
|
if (!model) return msg("meetings.recordings.errorMissingProviderKey");
|
|
264
271
|
const names = { modelName: model.modelName, providerName: model.providerName };
|
package/src/session.ts
CHANGED
|
@@ -141,9 +141,16 @@ export {
|
|
|
141
141
|
extractSessionRef,
|
|
142
142
|
groupTimeline,
|
|
143
143
|
sessionStatusFromEvents,
|
|
144
|
+
timelineLivePause,
|
|
145
|
+
timelinePauseSpans,
|
|
144
146
|
toolDisplayName,
|
|
145
147
|
} from "./timeline/projection";
|
|
146
|
-
export type {
|
|
148
|
+
export type {
|
|
149
|
+
GroupTimelineOptions,
|
|
150
|
+
TimelineLivePause,
|
|
151
|
+
TimelinePauseSpan,
|
|
152
|
+
} from "./timeline/projection";
|
|
153
|
+
export { useTimelinePauses } from "./timeline/use-timeline-pauses";
|
|
147
154
|
export type {
|
|
148
155
|
ActivityItem,
|
|
149
156
|
AgentMessageItem,
|
package/src/timeline/index.ts
CHANGED
|
@@ -24,10 +24,13 @@ export {
|
|
|
24
24
|
groupTimeline,
|
|
25
25
|
sessionStatusFromEvents,
|
|
26
26
|
mcpToolLeaf,
|
|
27
|
+
timelineLivePause,
|
|
28
|
+
timelinePauseSpans,
|
|
27
29
|
toolDisplayName,
|
|
28
30
|
toolMatchesLeaf,
|
|
29
31
|
} from "./projection";
|
|
30
|
-
export type { GroupTimelineOptions } from "./projection";
|
|
32
|
+
export type { GroupTimelineOptions, TimelineLivePause, TimelinePauseSpan } from "./projection";
|
|
33
|
+
export { useTimelinePauses } from "./use-timeline-pauses";
|
|
31
34
|
|
|
32
35
|
// item types
|
|
33
36
|
export type {
|
|
@@ -2482,6 +2482,184 @@ export function sessionStatusFromEvents(events: SessionEvent[]): SessionStatus |
|
|
|
2482
2482
|
return null;
|
|
2483
2483
|
}
|
|
2484
2484
|
|
|
2485
|
+
/**
|
|
2486
|
+
* A span in which the session's work was paused: by Pause of the chat, of
|
|
2487
|
+
* an ancestor, or of the workspace. An open span (no `endedAt`) is a pause
|
|
2488
|
+
* still in force.
|
|
2489
|
+
*/
|
|
2490
|
+
export type TimelinePauseSpan = { startedAt: string; endedAt?: string };
|
|
2491
|
+
|
|
2492
|
+
/**
|
|
2493
|
+
* The host's live view of the session's Pause, from its effective control.
|
|
2494
|
+
* `since` is when the pause in force began, when known. `resumedAt` is when
|
|
2495
|
+
* the host saw the pause end, for a resume whose events have not arrived.
|
|
2496
|
+
*/
|
|
2497
|
+
export type TimelineLivePause = {
|
|
2498
|
+
paused: boolean;
|
|
2499
|
+
since?: string | null | undefined;
|
|
2500
|
+
resumedAt?: string | null | undefined;
|
|
2501
|
+
};
|
|
2502
|
+
|
|
2503
|
+
/** Interruption reasons that park a turn for Resume rather than end it. */
|
|
2504
|
+
const PAUSE_INTERRUPTION_REASONS: ReadonlySet<unknown> = new Set([
|
|
2505
|
+
"session_pause",
|
|
2506
|
+
"workspace_pause",
|
|
2507
|
+
]);
|
|
2508
|
+
|
|
2509
|
+
type LivePauseBlocker = { changedAt?: string | null | undefined };
|
|
2510
|
+
|
|
2511
|
+
/**
|
|
2512
|
+
* The live pause from an effective session control; undefined when it is
|
|
2513
|
+
* unknown. A pause in force since several blockers took hold began with the
|
|
2514
|
+
* earliest of them.
|
|
2515
|
+
*/
|
|
2516
|
+
export function timelineLivePause(
|
|
2517
|
+
control:
|
|
2518
|
+
| {
|
|
2519
|
+
state: string;
|
|
2520
|
+
primaryBlocker?: LivePauseBlocker | null | undefined;
|
|
2521
|
+
blockers?: readonly LivePauseBlocker[] | null | undefined;
|
|
2522
|
+
}
|
|
2523
|
+
| null
|
|
2524
|
+
| undefined,
|
|
2525
|
+
): TimelineLivePause | undefined {
|
|
2526
|
+
if (!control) return undefined;
|
|
2527
|
+
if (control.state !== "paused") return { paused: false };
|
|
2528
|
+
let since: string | null = null;
|
|
2529
|
+
for (const blocker of [control.primaryBlocker, ...(control.blockers ?? [])]) {
|
|
2530
|
+
const changedAt = blocker?.changedAt;
|
|
2531
|
+
if (changedAt && (since === null || Date.parse(changedAt) < Date.parse(since)))
|
|
2532
|
+
since = changedAt;
|
|
2533
|
+
}
|
|
2534
|
+
return { paused: true, since };
|
|
2535
|
+
}
|
|
2536
|
+
|
|
2537
|
+
/** Events that start or end a pause span. */
|
|
2538
|
+
const PAUSE_EVENT_TYPES: ReadonlySet<string> = new Set([
|
|
2539
|
+
"session.control.paused",
|
|
2540
|
+
"session.control.resumed",
|
|
2541
|
+
"turn.recovery.requested",
|
|
2542
|
+
"session.status.changed",
|
|
2543
|
+
"turn.started",
|
|
2544
|
+
]);
|
|
2545
|
+
|
|
2546
|
+
/**
|
|
2547
|
+
* When the session's work was paused, from its events and (when the host
|
|
2548
|
+
* knows it) its live control.
|
|
2549
|
+
*
|
|
2550
|
+
* Pause parks the running turn for Resume instead of ending it, so the turn
|
|
2551
|
+
* stays open. A direct Pause records `session.control.paused`; a Pause of an
|
|
2552
|
+
* ancestor or of the workspace reaches the chat only as the interruption
|
|
2553
|
+
* (`turn.recovery.requested` with a pause reason) and the parked idle status.
|
|
2554
|
+
* Work resumes with `session.control.resumed`, or when the turn runs again.
|
|
2555
|
+
* A wait that a pause held without interrupting anything has no events at
|
|
2556
|
+
* all, so the live control decides whether a pause is in force now, and
|
|
2557
|
+
* `observed` carries pauses the host saw begin and end only through it.
|
|
2558
|
+
*/
|
|
2559
|
+
export function timelinePauseSpans(
|
|
2560
|
+
events: readonly SessionEvent[],
|
|
2561
|
+
live?: TimelineLivePause | null,
|
|
2562
|
+
observed: readonly TimelinePauseSpan[] = [],
|
|
2563
|
+
): TimelinePauseSpan[] {
|
|
2564
|
+
let latest: SessionEvent | undefined;
|
|
2565
|
+
const relevant: SessionEvent[] = [];
|
|
2566
|
+
for (const event of events) {
|
|
2567
|
+
if (!latest || event.sequence > latest.sequence) latest = event;
|
|
2568
|
+
if (PAUSE_EVENT_TYPES.has(event.type)) relevant.push(event);
|
|
2569
|
+
}
|
|
2570
|
+
relevant.sort((left, right) => left.sequence - right.sequence);
|
|
2571
|
+
const spans: TimelinePauseSpan[] = [];
|
|
2572
|
+
let open: TimelinePauseSpan | null = null;
|
|
2573
|
+
// Cancel also leaves the control paused while the turn winds down; that is
|
|
2574
|
+
// not a pause of the work, which is ending.
|
|
2575
|
+
let cancelling = false;
|
|
2576
|
+
for (const event of relevant) {
|
|
2577
|
+
const payload = asRecord(event.payload);
|
|
2578
|
+
if (
|
|
2579
|
+
(event.type === "session.control.paused" && payload.terminal === true) ||
|
|
2580
|
+
// A parent's Cancel reaches its sub-chats as their status alone.
|
|
2581
|
+
(event.type === "session.status.changed" && payload.status === "cancelled")
|
|
2582
|
+
) {
|
|
2583
|
+
cancelling = true;
|
|
2584
|
+
continue;
|
|
2585
|
+
}
|
|
2586
|
+
const starts =
|
|
2587
|
+
event.type === "session.control.paused" ||
|
|
2588
|
+
(event.type === "turn.recovery.requested" &&
|
|
2589
|
+
PAUSE_INTERRUPTION_REASONS.has(payload.reason)) ||
|
|
2590
|
+
(event.type === "session.status.changed" &&
|
|
2591
|
+
payload.status === "idle" &&
|
|
2592
|
+
payload.reason === "paused_recovery_settled");
|
|
2593
|
+
if (starts) {
|
|
2594
|
+
open ??= { startedAt: event.occurredAt };
|
|
2595
|
+
continue;
|
|
2596
|
+
}
|
|
2597
|
+
if (
|
|
2598
|
+
event.type === "session.control.resumed" ||
|
|
2599
|
+
event.type === "turn.started" ||
|
|
2600
|
+
(event.type === "session.status.changed" && payload.status === "running")
|
|
2601
|
+
) {
|
|
2602
|
+
cancelling = false;
|
|
2603
|
+
if (open) {
|
|
2604
|
+
spans.push({ startedAt: open.startedAt, endedAt: event.occurredAt });
|
|
2605
|
+
open = null;
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2609
|
+
const latestAt = latest?.occurredAt;
|
|
2610
|
+
if (live?.paused && !cancelling) {
|
|
2611
|
+
const startedAt = open?.startedAt ?? live.since ?? latestAt;
|
|
2612
|
+
if (startedAt) spans.push({ startedAt });
|
|
2613
|
+
} else if (open) {
|
|
2614
|
+
if (live) {
|
|
2615
|
+
// The host already sees the session running again; its resume events
|
|
2616
|
+
// are still on their way. End the pause when the host saw it end.
|
|
2617
|
+
const endedAt = live.resumedAt ?? latestAt ?? open.startedAt;
|
|
2618
|
+
spans.push({
|
|
2619
|
+
startedAt: open.startedAt,
|
|
2620
|
+
endedAt: Date.parse(endedAt) > Date.parse(open.startedAt) ? endedAt : open.startedAt,
|
|
2621
|
+
});
|
|
2622
|
+
} else {
|
|
2623
|
+
spans.push(open);
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2626
|
+
// A pause seen only through the live control, by the host's clock; skip it
|
|
2627
|
+
// where the events record the same pause.
|
|
2628
|
+
const recorded = [...spans];
|
|
2629
|
+
for (const span of observed) {
|
|
2630
|
+
if (!span.endedAt) continue;
|
|
2631
|
+
const start = Date.parse(span.startedAt);
|
|
2632
|
+
const end = Date.parse(span.endedAt);
|
|
2633
|
+
const overlaps = recorded.some(
|
|
2634
|
+
(other) =>
|
|
2635
|
+
Date.parse(other.startedAt) < end &&
|
|
2636
|
+
(other.endedAt === undefined || Date.parse(other.endedAt) > start),
|
|
2637
|
+
);
|
|
2638
|
+
if (!overlaps) spans.push(span);
|
|
2639
|
+
}
|
|
2640
|
+
return spans;
|
|
2641
|
+
}
|
|
2642
|
+
|
|
2643
|
+
/** Total length of the union of intervals, each clipped to `[from, to)`. */
|
|
2644
|
+
function unionLength(
|
|
2645
|
+
intervals: ReadonlyArray<readonly [number, number]>,
|
|
2646
|
+
from: number,
|
|
2647
|
+
to: number,
|
|
2648
|
+
): number {
|
|
2649
|
+
const clipped = intervals
|
|
2650
|
+
.map(([start, end]) => [Math.max(start, from), Math.min(end, to)] as const)
|
|
2651
|
+
.filter(([start, end]) => Number.isFinite(start) && Number.isFinite(end) && end > start)
|
|
2652
|
+
.sort((left, right) => left[0] - right[0]);
|
|
2653
|
+
let total = 0;
|
|
2654
|
+
let cursor = Number.NEGATIVE_INFINITY;
|
|
2655
|
+
for (const [start, end] of clipped) {
|
|
2656
|
+
const begin = Math.max(start, cursor);
|
|
2657
|
+
if (end > begin) total += end - begin;
|
|
2658
|
+
cursor = Math.max(cursor, end);
|
|
2659
|
+
}
|
|
2660
|
+
return total;
|
|
2661
|
+
}
|
|
2662
|
+
|
|
2485
2663
|
/* ----------------------------------------------------------------------------
|
|
2486
2664
|
Visual grouping: consecutive activity items (reasoning / tools / workers /
|
|
2487
2665
|
sandbox) cluster into collapsible blocks. Once a turn settles, the full
|
|
@@ -2549,6 +2727,12 @@ export type GroupTimelineOptions = {
|
|
|
2549
2727
|
readableTurns?: boolean;
|
|
2550
2728
|
/** @deprecated Use readableTurns. Cross-turn exchange folding has been removed. */
|
|
2551
2729
|
foldExchanges?: boolean;
|
|
2730
|
+
/**
|
|
2731
|
+
* When the session was paused ({@link timelinePauseSpans}). A readable
|
|
2732
|
+
* turn still open under a pause in force reads as paused, and paused time
|
|
2733
|
+
* is not counted as work.
|
|
2734
|
+
*/
|
|
2735
|
+
pauses?: readonly TimelinePauseSpan[];
|
|
2552
2736
|
};
|
|
2553
2737
|
|
|
2554
2738
|
export function groupTimeline(
|
|
@@ -2556,7 +2740,8 @@ export function groupTimeline(
|
|
|
2556
2740
|
items: TimelineItem[],
|
|
2557
2741
|
options: GroupTimelineOptions = {},
|
|
2558
2742
|
): TimelineGroup[] {
|
|
2559
|
-
if (options.readableTurns || options.foldExchanges)
|
|
2743
|
+
if (options.readableTurns || options.foldExchanges)
|
|
2744
|
+
return groupReadableTurns(t, items, options.pauses ?? []);
|
|
2560
2745
|
const groups: TimelineGroup[] = [];
|
|
2561
2746
|
for (const item of items) {
|
|
2562
2747
|
// A recovered capacity wait is over; it leaves no warning behind.
|
|
@@ -2585,7 +2770,11 @@ export function groupTimeline(
|
|
|
2585
2770
|
}
|
|
2586
2771
|
|
|
2587
2772
|
/** Live prose stays primary; settled progress joins its own turn's work history. */
|
|
2588
|
-
function groupReadableTurns(
|
|
2773
|
+
function groupReadableTurns(
|
|
2774
|
+
t: OpenGeniText,
|
|
2775
|
+
items: TimelineItem[],
|
|
2776
|
+
pauses: readonly TimelinePauseSpan[],
|
|
2777
|
+
): TimelineGroup[] {
|
|
2589
2778
|
type Work = Extract<TimelineGroup, { kind: "activity" }>;
|
|
2590
2779
|
let groups: TimelineGroup[] = [];
|
|
2591
2780
|
const turns = new Map<string, Work>();
|
|
@@ -2721,12 +2910,12 @@ function groupReadableTurns(t: OpenGeniText, items: TimelineItem[]): TimelineGro
|
|
|
2721
2910
|
group.work!.details.push({ kind: "activity", id: `work-item-${item.id}`, items: [item] });
|
|
2722
2911
|
delete group.work!.waiting;
|
|
2723
2912
|
} else if (item.kind === "notice" && item.capacityWait) {
|
|
2724
|
-
const
|
|
2725
|
-
|
|
2913
|
+
const idle = idleSpans.get(key) ?? [];
|
|
2914
|
+
idle.push({
|
|
2726
2915
|
startedAt: item.occurredAt,
|
|
2727
2916
|
...(item.resolvedAt ? { endedAt: item.resolvedAt } : {}),
|
|
2728
2917
|
});
|
|
2729
|
-
idleSpans.set(key,
|
|
2918
|
+
idleSpans.set(key, idle);
|
|
2730
2919
|
if (!item.resolvedAt) {
|
|
2731
2920
|
if (settlements.has(key)) groups.push({ kind: "item", item });
|
|
2732
2921
|
else {
|
|
@@ -2842,6 +3031,7 @@ function groupReadableTurns(t: OpenGeniText, items: TimelineItem[]): TimelineGro
|
|
|
2842
3031
|
? t("timeline.projection.waitingForYou")
|
|
2843
3032
|
: t("timeline.projection.waiting"),
|
|
2844
3033
|
since: item.occurredAt,
|
|
3034
|
+
...(item.approval === true ? { waitingOn: "you" as const } : {}),
|
|
2845
3035
|
};
|
|
2846
3036
|
} else if (
|
|
2847
3037
|
item.kind === "session-status" &&
|
|
@@ -2852,6 +3042,7 @@ function groupReadableTurns(t: OpenGeniText, items: TimelineItem[]): TimelineGro
|
|
|
2852
3042
|
current.waiting = {
|
|
2853
3043
|
label: t("timeline.projection.waitingForYou"),
|
|
2854
3044
|
since: item.occurredAt,
|
|
3045
|
+
waitingOn: "you",
|
|
2855
3046
|
};
|
|
2856
3047
|
} else if (
|
|
2857
3048
|
item.kind === "session-status" &&
|
|
@@ -2890,17 +3081,38 @@ function groupReadableTurns(t: OpenGeniText, items: TimelineItem[]): TimelineGro
|
|
|
2890
3081
|
untimed: true,
|
|
2891
3082
|
};
|
|
2892
3083
|
}
|
|
2893
|
-
const
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
3084
|
+
const workStart = Date.parse(work.startedAt);
|
|
3085
|
+
const workEnd = work.endedAt ? Date.parse(work.endedAt) : Number.POSITIVE_INFINITY;
|
|
3086
|
+
// A pause still in force over this open turn: the turn is parked for
|
|
3087
|
+
// Resume, so it reads as paused and its clock stops when the pause began.
|
|
3088
|
+
// A wait on the person (an approval, a question) keeps saying so.
|
|
3089
|
+
const openPause =
|
|
3090
|
+
work.endedAt || work.waiting?.waitingOn === "you"
|
|
3091
|
+
? undefined
|
|
3092
|
+
: pauses.find((pause) => !pause.endedAt && Date.parse(pause.startedAt) < workEnd);
|
|
3093
|
+
const pausedAt = openPause
|
|
3094
|
+
? Math.max(workStart, Date.parse(openPause.startedAt))
|
|
3095
|
+
: Number.POSITIVE_INFINITY;
|
|
3096
|
+
if (openPause && Number.isFinite(pausedAt)) {
|
|
3097
|
+
work.pausedAt = new Date(pausedAt).toISOString();
|
|
3098
|
+
delete work.waiting;
|
|
3099
|
+
}
|
|
3100
|
+
// Capacity waits, failed-attempt gaps and pauses can overlap; their union
|
|
3101
|
+
// is time the agent was not working. A span still open runs to the end of
|
|
3102
|
+
// the work (a turn cancelled while paused) or to the pause that stopped
|
|
3103
|
+
// its clock; on a turn still running it has no end yet and counts later.
|
|
3104
|
+
const until = Math.min(workEnd, pausedAt);
|
|
3105
|
+
const pausedMs = unionLength(
|
|
3106
|
+
[...(idleSpans.get(key) ?? []), ...pauses].flatMap((span) =>
|
|
3107
|
+
span.endedAt
|
|
3108
|
+
? [[Date.parse(span.startedAt), Date.parse(span.endedAt)] as const]
|
|
3109
|
+
: Number.isFinite(until)
|
|
3110
|
+
? [[Date.parse(span.startedAt), until] as const]
|
|
3111
|
+
: [],
|
|
3112
|
+
),
|
|
3113
|
+
workStart,
|
|
3114
|
+
until,
|
|
3115
|
+
);
|
|
2904
3116
|
if (pausedMs > 0) work.pausedMs = pausedMs;
|
|
2905
3117
|
}
|
|
2906
3118
|
groups = groups.filter((entry) => {
|