@arbidocs/blocks 0.5.120 → 0.5.122
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/ClippingMediaViewer-IEIBT74X.cjs +156 -0
- package/dist/ClippingMediaViewer-IEIBT74X.cjs.map +1 -0
- package/dist/ClippingPdfViewer-OGYLMVCE.cjs +79 -0
- package/dist/ClippingPdfViewer-OGYLMVCE.cjs.map +1 -0
- package/dist/{ConnectedCallDock-WER7R222.cjs → ConnectedCallDock-XJOYVVAH.cjs} +9 -7
- package/dist/ConnectedCallDock-XJOYVVAH.cjs.map +1 -0
- package/dist/{ConnectedCallRoom-T7OBQTYP.cjs → ConnectedCallRoom-CUDYAPQK.cjs} +9 -7
- package/dist/{ConnectedCallRoom-T7OBQTYP.cjs.map → ConnectedCallRoom-CUDYAPQK.cjs.map} +1 -1
- package/dist/{ConnectedNativeDocxComparison-SGE4R3M4.cjs → ConnectedNativeDocxComparison-QKHCYD6W.cjs} +7 -7
- package/dist/{ConnectedNativeDocxComparison-SGE4R3M4.cjs.map → ConnectedNativeDocxComparison-QKHCYD6W.cjs.map} +1 -1
- package/dist/ConnectedPresentation-AU25OW25.cjs +321 -0
- package/dist/ConnectedPresentation-AU25OW25.cjs.map +1 -0
- package/dist/ConnectedSlidesTab-I75LKKN7.cjs +236 -0
- package/dist/ConnectedSlidesTab-I75LKKN7.cjs.map +1 -0
- package/dist/{ConnectedStreamedWordArtifact-6MCLJRIT.cjs → ConnectedStreamedWordArtifact-AG62232A.cjs} +7 -7
- package/dist/{ConnectedStreamedWordArtifact-6MCLJRIT.cjs.map → ConnectedStreamedWordArtifact-AG62232A.cjs.map} +1 -1
- package/dist/{DocumentReviewCard-BPIAJJED.cjs → DocumentReviewCard-M53XFLI2.cjs} +15 -14
- package/dist/DocumentReviewCard-M53XFLI2.cjs.map +1 -0
- package/dist/{FilesViewerDialog-67WK3TZC.cjs → FilesViewerDialog-4352KIOG.cjs} +30 -22
- package/dist/FilesViewerDialog-4352KIOG.cjs.map +1 -0
- package/dist/{GridViewImpl-ZMJJWTOM.cjs → GridViewImpl-LTYET77Q.cjs} +3 -3
- package/dist/GridViewImpl-LTYET77Q.cjs.map +1 -0
- package/dist/{WorkspaceTableView-J3C6VH4T.cjs → WorkspaceTableView-3XYAV4BV.cjs} +9 -8
- package/dist/WorkspaceTableView-3XYAV4BV.cjs.map +1 -0
- package/dist/agents/index.cjs +186 -186
- package/dist/{ai-IM4A23YT.cjs → ai-IEIR7SC2.cjs} +17 -15
- package/dist/ai-IEIR7SC2.cjs.map +1 -0
- package/dist/calls/connected/CallControls.d.ts +2 -0
- package/dist/calls/connected/CallControls.js +71 -9
- package/dist/calls/connected/CallControls.js.map +2 -2
- package/dist/calls/connected/ShareDocumentDialog.d.ts +14 -0
- package/dist/calls/connected/ShareDocumentDialog.js +77 -0
- package/dist/calls/connected/ShareDocumentDialog.js.map +7 -0
- package/dist/calls/index.cjs +2 -2
- package/dist/chat/index.cjs +8 -7
- package/dist/{chunk-557MJ4IH.cjs → chunk-2F57IO7S.cjs} +9 -146
- package/dist/chunk-2F57IO7S.cjs.map +1 -0
- package/dist/chunk-2RLA6QO2.cjs +174 -0
- package/dist/chunk-2RLA6QO2.cjs.map +1 -0
- package/dist/chunk-4TTX6ZNS.cjs +1374 -0
- package/dist/chunk-4TTX6ZNS.cjs.map +1 -0
- package/dist/chunk-5GCCUXMT.cjs +63 -0
- package/dist/chunk-5GCCUXMT.cjs.map +1 -0
- package/dist/{chunk-BUVIBHFU.cjs → chunk-5QERK4PK.cjs} +38 -38
- package/dist/chunk-5QERK4PK.cjs.map +1 -0
- package/dist/chunk-6OK7ESTL.cjs +134 -0
- package/dist/chunk-6OK7ESTL.cjs.map +1 -0
- package/dist/{chunk-ECLUFKYR.cjs → chunk-7557LDAN.cjs} +4 -4
- package/dist/{chunk-ECLUFKYR.cjs.map → chunk-7557LDAN.cjs.map} +1 -1
- package/dist/{chunk-KTQOGT2L.cjs → chunk-7L4X6QN2.cjs} +7 -7
- package/dist/{chunk-KTQOGT2L.cjs.map → chunk-7L4X6QN2.cjs.map} +1 -1
- package/dist/{chunk-BP3IJ34D.cjs → chunk-7NLO7ASW.cjs} +4 -4
- package/dist/{chunk-BP3IJ34D.cjs.map → chunk-7NLO7ASW.cjs.map} +1 -1
- package/dist/{chunk-3GWWOYGS.cjs → chunk-7PN3YENO.cjs} +4 -4
- package/dist/{chunk-3GWWOYGS.cjs.map → chunk-7PN3YENO.cjs.map} +1 -1
- package/dist/{chunk-DFBDQKGE.cjs → chunk-ADDQKZ5I.cjs} +4 -4
- package/dist/{chunk-DFBDQKGE.cjs.map → chunk-ADDQKZ5I.cjs.map} +1 -1
- package/dist/chunk-AFQTQC7A.cjs +35 -0
- package/dist/chunk-AFQTQC7A.cjs.map +1 -0
- package/dist/{chunk-NLSWDP42.cjs → chunk-ALK3PUUB.cjs} +21 -11
- package/dist/chunk-ALK3PUUB.cjs.map +1 -0
- package/dist/{chunk-775S43W7.cjs → chunk-CQQQIZU4.cjs} +8 -8
- package/dist/{chunk-775S43W7.cjs.map → chunk-CQQQIZU4.cjs.map} +1 -1
- package/dist/{chunk-TDO5UWXF.cjs → chunk-E3L5DB5F.cjs} +5 -5
- package/dist/{chunk-TDO5UWXF.cjs.map → chunk-E3L5DB5F.cjs.map} +1 -1
- package/dist/chunk-GFUOCGY6.cjs +32 -0
- package/dist/chunk-GFUOCGY6.cjs.map +1 -0
- package/dist/chunk-HYUKPHCT.cjs +66 -0
- package/dist/chunk-HYUKPHCT.cjs.map +1 -0
- package/dist/{chunk-QQWHG3KF.cjs → chunk-JJZOL5MG.cjs} +4 -4
- package/dist/{chunk-QQWHG3KF.cjs.map → chunk-JJZOL5MG.cjs.map} +1 -1
- package/dist/chunk-K4763GD5.cjs +301 -0
- package/dist/chunk-K4763GD5.cjs.map +1 -0
- package/dist/{chunk-B3LZITVF.cjs → chunk-KA3F6TIH.cjs} +2 -442
- package/dist/chunk-KA3F6TIH.cjs.map +1 -0
- package/dist/{chunk-PGJYD67F.cjs → chunk-KNGZZC4O.cjs} +7 -6
- package/dist/chunk-KNGZZC4O.cjs.map +1 -0
- package/dist/{chunk-YYPZOEED.cjs → chunk-LHWOKOMP.cjs} +23 -2
- package/dist/chunk-LHWOKOMP.cjs.map +1 -0
- package/dist/{chunk-HA66DHW6.cjs → chunk-MLA2BJ2Y.cjs} +28 -28
- package/dist/chunk-MLA2BJ2Y.cjs.map +1 -0
- package/dist/{chunk-CPR6EHG7.cjs → chunk-NG2EE7HR.cjs} +134 -10
- package/dist/chunk-NG2EE7HR.cjs.map +1 -0
- package/dist/{chunk-CKCG4NDB.cjs → chunk-OHHKBURG.cjs} +29 -29
- package/dist/chunk-OHHKBURG.cjs.map +1 -0
- package/dist/{chunk-4XJEHKVZ.cjs → chunk-PIYYBPHH.cjs} +4 -4
- package/dist/{chunk-4XJEHKVZ.cjs.map → chunk-PIYYBPHH.cjs.map} +1 -1
- package/dist/{chunk-YYSBWMDJ.cjs → chunk-QG2U2JGX.cjs} +4 -4
- package/dist/{chunk-YYSBWMDJ.cjs.map → chunk-QG2U2JGX.cjs.map} +1 -1
- package/dist/{chunk-5IZFSAEZ.cjs → chunk-SDRYSLOX.cjs} +4 -4
- package/dist/{chunk-5IZFSAEZ.cjs.map → chunk-SDRYSLOX.cjs.map} +1 -1
- package/dist/{chunk-NJCK6V6U.cjs → chunk-T73BHNQX.cjs} +2 -58
- package/dist/chunk-T73BHNQX.cjs.map +1 -0
- package/dist/{chunk-EOG6OT5I.cjs → chunk-TXP2N3DC.cjs} +4 -4
- package/dist/{chunk-EOG6OT5I.cjs.map → chunk-TXP2N3DC.cjs.map} +1 -1
- package/dist/{chunk-6UTKM5AB.cjs → chunk-UFT22LAB.cjs} +75 -75
- package/dist/chunk-UFT22LAB.cjs.map +1 -0
- package/dist/chunk-USNTRL22.cjs +4790 -0
- package/dist/chunk-USNTRL22.cjs.map +1 -0
- package/dist/{chunk-X36UR4A7.cjs → chunk-UTJ223TI.cjs} +413 -90
- package/dist/chunk-UTJ223TI.cjs.map +1 -0
- package/dist/{chunk-VZCPMXWC.cjs → chunk-V6MW7B4B.cjs} +4 -4
- package/dist/{chunk-VZCPMXWC.cjs.map → chunk-V6MW7B4B.cjs.map} +1 -1
- package/dist/{chunk-T23UTIRI.cjs → chunk-VWBYE3XY.cjs} +5 -5
- package/dist/{chunk-T23UTIRI.cjs.map → chunk-VWBYE3XY.cjs.map} +1 -1
- package/dist/chunk-WFMWKPGY.cjs +102 -0
- package/dist/chunk-WFMWKPGY.cjs.map +1 -0
- package/dist/chunk-WOOOMTTA.cjs +19 -0
- package/dist/chunk-WOOOMTTA.cjs.map +1 -0
- package/dist/{chunk-W6INT5GS.cjs → chunk-WRLGLZIA.cjs} +8 -8
- package/dist/{chunk-W6INT5GS.cjs.map → chunk-WRLGLZIA.cjs.map} +1 -1
- package/dist/{chunk-CJYWHUZR.cjs → chunk-XCKHOXRP.cjs} +4 -4
- package/dist/{chunk-CJYWHUZR.cjs.map → chunk-XCKHOXRP.cjs.map} +1 -1
- package/dist/chunk-XF355M7O.cjs +154 -0
- package/dist/chunk-XF355M7O.cjs.map +1 -0
- package/dist/{chunk-Q6CLWOP2.cjs → chunk-XGM4VVNV.cjs} +34 -34
- package/dist/{chunk-Q6CLWOP2.cjs.map → chunk-XGM4VVNV.cjs.map} +1 -1
- package/dist/{chunk-6WMMZLEV.cjs → chunk-XJEXFEWG.cjs} +2 -27
- package/dist/chunk-XJEXFEWG.cjs.map +1 -0
- package/dist/chunk-XK4TVJKD.cjs +73 -0
- package/dist/chunk-XK4TVJKD.cjs.map +1 -0
- package/dist/{chunk-E7TE2WVT.cjs → chunk-ZVEW3JBT.cjs} +3 -3
- package/dist/{chunk-E7TE2WVT.cjs.map → chunk-ZVEW3JBT.cjs.map} +1 -1
- package/dist/collaboration/index.cjs +70 -70
- package/dist/components/ZoomSlider.d.ts +25 -0
- package/dist/components/ZoomSlider.js +59 -0
- package/dist/components/ZoomSlider.js.map +7 -0
- package/dist/connect/docx.cjs +10 -10
- package/dist/connect/index.cjs +1066 -1147
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/viewer.cjs +19 -12
- package/dist/connection/ai.d.ts +1 -1
- package/dist/connection/conversation/ConnectedMessage.js +1 -1
- package/dist/connection/conversation/ConnectedMessage.js.map +2 -2
- package/dist/connection/files/ConnectedNewFileMenu.d.ts +2 -1
- package/dist/connection/files/ConnectedNewFileMenu.js +9 -3
- package/dist/connection/files/ConnectedNewFileMenu.js.map +2 -2
- package/dist/connection/files/explorer/ConnectedFilesExplorer.js +1 -1
- package/dist/connection/files/explorer/ConnectedFilesExplorer.js.map +2 -2
- package/dist/connection/files/explorer/FileTiles.js +1 -1
- package/dist/connection/files/explorer/FileTiles.js.map +2 -2
- package/dist/connection/files/fields/documentField.js +1 -1
- package/dist/connection/files/fields/documentField.js.map +2 -2
- package/dist/connection/files/grid/documentColumns.js +1 -1
- package/dist/connection/files/grid/documentColumns.js.map +2 -2
- package/dist/connection/files/page/DocumentsFilterBarActions.js +17 -28
- package/dist/connection/files/page/DocumentsFilterBarActions.js.map +2 -2
- package/dist/connection/mail/useMailboxDefaults.js +1 -1
- package/dist/connection/mail/useMailboxDefaults.js.map +2 -2
- package/dist/connection/panels/useSessionPanelMode.js +3 -2
- package/dist/connection/panels/useSessionPanelMode.js.map +2 -2
- package/dist/connection/presentation/ClippingMediaViewer.d.ts +12 -0
- package/dist/connection/presentation/ClippingMediaViewer.js +153 -0
- package/dist/connection/presentation/ClippingMediaViewer.js.map +7 -0
- package/dist/connection/presentation/ClippingPdfViewer.d.ts +22 -0
- package/dist/connection/presentation/ClippingPdfViewer.js +75 -0
- package/dist/connection/presentation/ClippingPdfViewer.js.map +7 -0
- package/dist/connection/presentation/ConnectedPresentation.d.ts +12 -0
- package/dist/connection/presentation/ConnectedPresentation.js +100 -0
- package/dist/connection/presentation/ConnectedPresentation.js.map +7 -0
- package/dist/connection/presentation/ConnectedSlidesTab.d.ts +20 -0
- package/dist/connection/presentation/ConnectedSlidesTab.js +222 -0
- package/dist/connection/presentation/ConnectedSlidesTab.js.map +7 -0
- package/dist/connection/presentation/CropClipDialog.d.ts +11 -0
- package/dist/connection/presentation/CropClipDialog.js +86 -0
- package/dist/connection/presentation/CropClipDialog.js.map +7 -0
- package/dist/connection/presentation/GenerateTile.d.ts +4 -0
- package/dist/connection/presentation/GenerateTile.js +24 -0
- package/dist/connection/presentation/GenerateTile.js.map +7 -0
- package/dist/connection/presentation/LabelColumnMenu.d.ts +8 -0
- package/dist/connection/presentation/LabelColumnMenu.js +38 -0
- package/dist/connection/presentation/LabelColumnMenu.js.map +7 -0
- package/dist/connection/presentation/PresentationDialogs.d.ts +39 -0
- package/dist/connection/presentation/PresentationDialogs.js +295 -0
- package/dist/connection/presentation/PresentationDialogs.js.map +7 -0
- package/dist/connection/presentation/PresentationFileCard.d.ts +10 -0
- package/dist/connection/presentation/PresentationFileCard.js +35 -0
- package/dist/connection/presentation/PresentationFileCard.js.map +7 -0
- package/dist/connection/presentation/PresentationPill.d.ts +8 -0
- package/dist/connection/presentation/PresentationPill.js +39 -0
- package/dist/connection/presentation/PresentationPill.js.map +7 -0
- package/dist/connection/presentation/PresentationSlot.d.ts +7 -0
- package/dist/connection/presentation/PresentationSlot.js +35 -0
- package/dist/connection/presentation/PresentationSlot.js.map +7 -0
- package/dist/connection/presentation/requests.d.ts +21 -0
- package/dist/connection/presentation/requests.js +27 -0
- package/dist/connection/presentation/requests.js.map +7 -0
- package/dist/connection/presentation/useImageGeneration.d.ts +11 -0
- package/dist/connection/presentation/useImageGeneration.js +66 -0
- package/dist/connection/presentation/useImageGeneration.js.map +7 -0
- package/dist/connection/presentation/useLabelColumns.d.ts +15 -0
- package/dist/connection/presentation/useLabelColumns.js +33 -0
- package/dist/connection/presentation/useLabelColumns.js.map +7 -0
- package/dist/connection/presentation/usePresentationController.d.ts +15 -0
- package/dist/connection/presentation/usePresentationController.js +118 -0
- package/dist/connection/presentation/usePresentationController.js.map +7 -0
- package/dist/connection/presentation/usePresentationFiles.d.ts +44 -0
- package/dist/connection/presentation/usePresentationFiles.js +307 -0
- package/dist/connection/presentation/usePresentationFiles.js.map +7 -0
- package/dist/connection/presentation/useViewerClipping.d.ts +14 -0
- package/dist/connection/presentation/useViewerClipping.js +18 -0
- package/dist/connection/presentation/useViewerClipping.js.map +7 -0
- package/dist/connection/shell/ConnectedAppShell.js +5 -1
- package/dist/connection/shell/ConnectedAppShell.js.map +2 -2
- package/dist/connection/viewer/CleanViewControl.d.ts +8 -0
- package/dist/connection/viewer/CleanViewControl.js +76 -0
- package/dist/connection/viewer/CleanViewControl.js.map +7 -0
- package/dist/connection/viewer/ConnectedDocumentViewer.js +28 -29
- package/dist/connection/viewer/ConnectedDocumentViewer.js.map +2 -2
- package/dist/connection/viewer/ViewerCropModal.d.ts +5 -0
- package/dist/connection/viewer/ViewerCropModal.js +22 -0
- package/dist/connection/viewer/ViewerCropModal.js.map +7 -0
- package/dist/connection/viewer/ViewerPdfPane.d.ts +3 -1
- package/dist/connection/viewer/ViewerPdfPane.js +41 -1
- package/dist/connection/viewer/ViewerPdfPane.js.map +2 -2
- package/dist/connection/viewer/documentPlace.d.ts +5 -4
- package/dist/connection/viewer/documentPlace.js +2 -2
- package/dist/connection/viewer/documentPlace.js.map +2 -2
- package/dist/connection/viewer/drafts.js +6 -4
- package/dist/connection/viewer/drafts.js.map +2 -2
- package/dist/connection/viewer/pdf/PdfClipOutlines.d.ts +11 -0
- package/dist/connection/viewer/pdf/PdfClipOutlines.js +42 -0
- package/dist/connection/viewer/pdf/PdfClipOutlines.js.map +7 -0
- package/dist/connection/viewer/pdf/clipOutlines.d.ts +17 -0
- package/dist/connection/viewer/pdf/clipOutlines.js +24 -0
- package/dist/connection/viewer/pdf/clipOutlines.js.map +7 -0
- package/dist/connection/viewer/pdf/passageHighlights.d.ts +2 -0
- package/dist/connection/viewer/pdf/passageHighlights.js +12 -1
- package/dist/connection/viewer/pdf/passageHighlights.js.map +2 -2
- package/dist/connection/viewer/pdf/usePdfClipOutlines.d.ts +7 -0
- package/dist/connection/viewer/pdf/usePdfClipOutlines.js +36 -0
- package/dist/connection/viewer/pdf/usePdfClipOutlines.js.map +7 -0
- package/dist/connection/viewer/pdf/usePdfPassageHighlights.js +11 -2
- package/dist/connection/viewer/pdf/usePdfPassageHighlights.js.map +2 -2
- package/dist/connection/viewer/shareDocument.d.ts +11 -0
- package/dist/connection/viewer/shareDocument.js +11 -0
- package/dist/connection/viewer/shareDocument.js.map +7 -0
- package/dist/connection/viewer/slidesTabChunk.d.ts +2 -0
- package/dist/connection/viewer/slidesTabChunk.js +9 -0
- package/dist/connection/viewer/slidesTabChunk.js.map +7 -0
- package/dist/connection/viewer/useCleanView.d.ts +14 -0
- package/dist/connection/viewer/useCleanView.js +29 -0
- package/dist/connection/viewer/useCleanView.js.map +7 -0
- package/dist/connection/viewer/useViewedDocument.d.ts +1 -0
- package/dist/connection/viewer/useViewedDocument.js +9 -1
- package/dist/connection/viewer/useViewedDocument.js.map +2 -2
- package/dist/connection/viewer/useViewerTabs.js +18 -4
- package/dist/connection/viewer/useViewerTabs.js.map +2 -2
- package/dist/connection/workflows/ConnectedWorkflowStart.d.ts +14 -2
- package/dist/connection/workflows/ConnectedWorkflowStart.js +5 -2
- package/dist/connection/workflows/ConnectedWorkflowStart.js.map +2 -2
- package/dist/databases/index.cjs +49 -49
- package/dist/document-tools/DocumentToolButtons.d.ts +2 -0
- package/dist/document-tools/DocumentToolButtons.js +22 -1
- package/dist/document-tools/DocumentToolButtons.js.map +2 -2
- package/dist/document-tools/index.cjs +16 -12
- package/dist/document-tools/index.d.ts +1 -1
- package/dist/document-tools/index.js +2 -0
- package/dist/document-tools/index.js.map +2 -2
- package/dist/embed/index.cjs +17 -15
- package/dist/files/GridViewImpl.js +1 -1
- package/dist/files/GridViewImpl.js.map +2 -2
- package/dist/files/ViewerChrome.d.ts +5 -1
- package/dist/files/ViewerChrome.js +16 -6
- package/dist/files/ViewerChrome.js.map +2 -2
- package/dist/files/index.cjs +224 -224
- package/dist/files/navigator/DocumentSearchList.js +1 -1
- package/dist/files/navigator/DocumentSearchList.js.map +2 -2
- package/dist/index.cjs +359 -356
- package/dist/index.cjs.map +1 -1
- package/dist/presentation/BoxActionBar.d.ts +11 -0
- package/dist/presentation/BoxActionBar.js +182 -0
- package/dist/presentation/BoxActionBar.js.map +7 -0
- package/dist/presentation/ClipActionBar.d.ts +26 -0
- package/dist/presentation/ClipActionBar.js +103 -0
- package/dist/presentation/ClipActionBar.js.map +7 -0
- package/dist/presentation/ClipCaptureOverlay.d.ts +14 -0
- package/dist/presentation/ClipCaptureOverlay.js +69 -0
- package/dist/presentation/ClipCaptureOverlay.js.map +7 -0
- package/dist/presentation/ClipImage.d.ts +21 -0
- package/dist/presentation/ClipImage.js +119 -0
- package/dist/presentation/ClipImage.js.map +7 -0
- package/dist/presentation/ClipTray.d.ts +11 -0
- package/dist/presentation/ClipTray.js +152 -0
- package/dist/presentation/ClipTray.js.map +7 -0
- package/dist/presentation/ClipViewControls.d.ts +11 -0
- package/dist/presentation/ClipViewControls.js +142 -0
- package/dist/presentation/ClipViewControls.js.map +7 -0
- package/dist/presentation/DesignMenu.d.ts +8 -0
- package/dist/presentation/DesignMenu.js +199 -0
- package/dist/presentation/DesignMenu.js.map +7 -0
- package/dist/presentation/LayoutMenu.d.ts +17 -0
- package/dist/presentation/LayoutMenu.js +122 -0
- package/dist/presentation/LayoutMenu.js.map +7 -0
- package/dist/presentation/MediaClip.d.ts +15 -0
- package/dist/presentation/MediaClip.js +67 -0
- package/dist/presentation/MediaClip.js.map +7 -0
- package/dist/presentation/Notice.d.ts +6 -0
- package/dist/presentation/Notice.js +43 -0
- package/dist/presentation/Notice.js.map +7 -0
- package/dist/presentation/PresentControls.d.ts +11 -0
- package/dist/presentation/PresentControls.js +117 -0
- package/dist/presentation/PresentControls.js.map +7 -0
- package/dist/presentation/PresentationStage.d.ts +32 -0
- package/dist/presentation/PresentationStage.js +232 -0
- package/dist/presentation/PresentationStage.js.map +7 -0
- package/dist/presentation/PresenterView.d.ts +16 -0
- package/dist/presentation/PresenterView.js +100 -0
- package/dist/presentation/PresenterView.js.map +7 -0
- package/dist/presentation/SlideDecor.d.ts +25 -0
- package/dist/presentation/SlideDecor.js +189 -0
- package/dist/presentation/SlideDecor.js.map +7 -0
- package/dist/presentation/SlidesEditor.d.ts +25 -0
- package/dist/presentation/SlidesEditor.js +375 -0
- package/dist/presentation/SlidesEditor.js.map +7 -0
- package/dist/presentation/StageBox.d.ts +30 -0
- package/dist/presentation/StageBox.js +281 -0
- package/dist/presentation/StageBox.js.map +7 -0
- package/dist/presentation/StageItem.d.ts +37 -0
- package/dist/presentation/StageItem.js +211 -0
- package/dist/presentation/StageItem.js.map +7 -0
- package/dist/presentation/box-style.d.ts +6 -0
- package/dist/presentation/box-style.js +19 -0
- package/dist/presentation/box-style.js.map +7 -0
- package/dist/presentation/boxes.d.ts +105 -0
- package/dist/presentation/boxes.js +103 -0
- package/dist/presentation/boxes.js.map +7 -0
- package/dist/presentation/draw-boxes.d.ts +8 -0
- package/dist/presentation/draw-boxes.js +130 -0
- package/dist/presentation/draw-boxes.js.map +7 -0
- package/dist/presentation/export-boxes.d.ts +10 -0
- package/dist/presentation/export-boxes.js +74 -0
- package/dist/presentation/export-boxes.js.map +7 -0
- package/dist/presentation/export-pptx.d.ts +16 -0
- package/dist/presentation/export-pptx.js +194 -0
- package/dist/presentation/export-pptx.js.map +7 -0
- package/dist/presentation/import-pptx.d.ts +35 -0
- package/dist/presentation/import-pptx.js +659 -0
- package/dist/presentation/import-pptx.js.map +7 -0
- package/dist/presentation/merge-outside-edits.d.ts +12 -0
- package/dist/presentation/merge-outside-edits.js +35 -0
- package/dist/presentation/merge-outside-edits.js.map +7 -0
- package/dist/presentation/model.d.ts +201 -0
- package/dist/presentation/model.js +271 -0
- package/dist/presentation/model.js.map +7 -0
- package/dist/presentation/panel-id.d.ts +44 -0
- package/dist/presentation/panel-id.js +29 -0
- package/dist/presentation/panel-id.js.map +7 -0
- package/dist/presentation/persistence.d.ts +121 -0
- package/dist/presentation/persistence.js +141 -0
- package/dist/presentation/persistence.js.map +7 -0
- package/dist/presentation/pptx-data.d.ts +22 -0
- package/dist/presentation/pptx-data.js +83 -0
- package/dist/presentation/pptx-data.js.map +7 -0
- package/dist/presentation/pptx-xml.d.ts +90 -0
- package/dist/presentation/pptx-xml.js +333 -0
- package/dist/presentation/pptx-xml.js.map +7 -0
- package/dist/presentation/render-slides.d.ts +58 -0
- package/dist/presentation/render-slides.js +309 -0
- package/dist/presentation/render-slides.js.map +7 -0
- package/dist/presentation/saved-boxes.d.ts +11 -0
- package/dist/presentation/saved-boxes.js +80 -0
- package/dist/presentation/saved-boxes.js.map +7 -0
- package/dist/presentation/slide-layout.d.ts +58 -0
- package/dist/presentation/slide-layout.js +133 -0
- package/dist/presentation/slide-layout.js.map +7 -0
- package/dist/presentation/stage-videos.d.ts +5 -0
- package/dist/presentation/stage-videos.js +19 -0
- package/dist/presentation/stage-videos.js.map +7 -0
- package/dist/presentation/store.d.ts +203 -0
- package/dist/presentation/store.js +429 -0
- package/dist/presentation/store.js.map +7 -0
- package/dist/presentation/theme.d.ts +102 -0
- package/dist/presentation/theme.js +276 -0
- package/dist/presentation/theme.js.map +7 -0
- package/dist/presentation/useClipDrag.d.ts +26 -0
- package/dist/presentation/useClipDrag.js +65 -0
- package/dist/presentation/useClipDrag.js.map +7 -0
- package/dist/presentation/useObjectUrl.d.ts +6 -0
- package/dist/presentation/useObjectUrl.js +15 -0
- package/dist/presentation/useObjectUrl.js.map +7 -0
- package/dist/presentation/usePresenterKeys.d.ts +13 -0
- package/dist/presentation/usePresenterKeys.js +62 -0
- package/dist/presentation/usePresenterKeys.js.map +7 -0
- package/dist/settings/index.cjs +149 -148
- package/dist/shell/PanelPortal.js +13 -3
- package/dist/shell/PanelPortal.js.map +2 -2
- package/dist/shell/index.cjs +49 -46
- package/dist/shell/panel-windows.d.ts +2 -0
- package/dist/shell/panel-windows.js +8 -2
- package/dist/shell/panel-windows.js.map +2 -2
- package/dist/studio/index.cjs +8 -6
- package/dist/studio/index.cjs.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/workflow-canvas/index.cjs +26 -25
- package/dist/workflow-canvas/index.cjs.map +1 -1
- package/node_modules/@arbidocs/coedit/package.json +1 -1
- package/package.json +6 -5
- package/dist/ConnectedCallDock-WER7R222.cjs.map +0 -1
- package/dist/DocumentReviewCard-BPIAJJED.cjs.map +0 -1
- package/dist/FilesViewerDialog-67WK3TZC.cjs.map +0 -1
- package/dist/GridViewImpl-ZMJJWTOM.cjs.map +0 -1
- package/dist/WorkspaceTableView-J3C6VH4T.cjs.map +0 -1
- package/dist/ai-IM4A23YT.cjs.map +0 -1
- package/dist/chunk-557MJ4IH.cjs.map +0 -1
- package/dist/chunk-6UTKM5AB.cjs.map +0 -1
- package/dist/chunk-6WMMZLEV.cjs.map +0 -1
- package/dist/chunk-B3LZITVF.cjs.map +0 -1
- package/dist/chunk-BUVIBHFU.cjs.map +0 -1
- package/dist/chunk-CKCG4NDB.cjs.map +0 -1
- package/dist/chunk-CPR6EHG7.cjs.map +0 -1
- package/dist/chunk-HA66DHW6.cjs.map +0 -1
- package/dist/chunk-NJCK6V6U.cjs.map +0 -1
- package/dist/chunk-NLSWDP42.cjs.map +0 -1
- package/dist/chunk-PGJYD67F.cjs.map +0 -1
- package/dist/chunk-X36UR4A7.cjs.map +0 -1
- package/dist/chunk-YYPZOEED.cjs.map +0 -1
package/dist/connect/viewer.cjs
CHANGED
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var chunkUTJ223TI_cjs = require('../chunk-UTJ223TI.cjs');
|
|
5
|
+
require('../chunk-WFMWKPGY.cjs');
|
|
6
|
+
require('../chunk-4TTX6ZNS.cjs');
|
|
5
7
|
require('../chunk-4CIVQWAX.cjs');
|
|
6
8
|
var chunkPL7HUTM3_cjs = require('../chunk-PL7HUTM3.cjs');
|
|
7
|
-
require('../chunk-
|
|
9
|
+
require('../chunk-GFUOCGY6.cjs');
|
|
10
|
+
require('../chunk-ADDQKZ5I.cjs');
|
|
8
11
|
require('../chunk-KXIRVKCJ.cjs');
|
|
9
|
-
require('../chunk-
|
|
10
|
-
require('../chunk-
|
|
11
|
-
require('../chunk-
|
|
12
|
+
require('../chunk-5QERK4PK.cjs');
|
|
13
|
+
require('../chunk-T73BHNQX.cjs');
|
|
14
|
+
require('../chunk-HYUKPHCT.cjs');
|
|
15
|
+
require('../chunk-ALK3PUUB.cjs');
|
|
12
16
|
require('../chunk-223D4727.cjs');
|
|
13
17
|
require('../chunk-SNUBQMIS.cjs');
|
|
14
|
-
require('../chunk-
|
|
18
|
+
require('../chunk-7557LDAN.cjs');
|
|
15
19
|
require('../chunk-4ONPEVTP.cjs');
|
|
16
20
|
require('../chunk-V3KLUWQQ.cjs');
|
|
17
21
|
require('../chunk-P5AQYC4D.cjs');
|
|
18
22
|
require('../chunk-WAV762GP.cjs');
|
|
19
|
-
require('../chunk-
|
|
23
|
+
require('../chunk-LHWOKOMP.cjs');
|
|
20
24
|
require('../chunk-GNZAH6UI.cjs');
|
|
21
25
|
require('../chunk-JH6JTI76.cjs');
|
|
22
26
|
require('../chunk-QQMMCXBP.cjs');
|
|
@@ -24,7 +28,9 @@ require('../chunk-DTMBAFIL.cjs');
|
|
|
24
28
|
require('../chunk-ZESMRGDV.cjs');
|
|
25
29
|
require('../chunk-VCEX7COE.cjs');
|
|
26
30
|
require('../chunk-34HQO4ZQ.cjs');
|
|
27
|
-
require('../chunk-
|
|
31
|
+
require('../chunk-KA3F6TIH.cjs');
|
|
32
|
+
require('../chunk-K4763GD5.cjs');
|
|
33
|
+
require('../chunk-2RLA6QO2.cjs');
|
|
28
34
|
require('../chunk-MZZ3SBQL.cjs');
|
|
29
35
|
require('../chunk-NY3YUCOW.cjs');
|
|
30
36
|
require('../chunk-325GVZE6.cjs');
|
|
@@ -40,7 +46,7 @@ require('../chunk-OEJQFPWO.cjs');
|
|
|
40
46
|
require('../chunk-OYXWQTHF.cjs');
|
|
41
47
|
require('../chunk-S237ORM3.cjs');
|
|
42
48
|
require('../chunk-II2OEXHW.cjs');
|
|
43
|
-
require('../chunk-
|
|
49
|
+
require('../chunk-JJZOL5MG.cjs');
|
|
44
50
|
require('../chunk-3YEXZX4H.cjs');
|
|
45
51
|
require('../chunk-4PA6VCCR.cjs');
|
|
46
52
|
require('../chunk-WXUU3COI.cjs');
|
|
@@ -49,7 +55,7 @@ require('../chunk-RL2HI6NP.cjs');
|
|
|
49
55
|
require('../chunk-6UZC4XVV.cjs');
|
|
50
56
|
require('../chunk-YVCOQHCE.cjs');
|
|
51
57
|
require('../chunk-JV5TVUOU.cjs');
|
|
52
|
-
require('../chunk-
|
|
58
|
+
require('../chunk-ZVEW3JBT.cjs');
|
|
53
59
|
require('../chunk-EG7EJFUE.cjs');
|
|
54
60
|
require('../chunk-VG24E4JJ.cjs');
|
|
55
61
|
require('../chunk-U2FFG2B3.cjs');
|
|
@@ -63,7 +69,8 @@ require('../chunk-SJSGSHIT.cjs');
|
|
|
63
69
|
require('../chunk-ZW6FPIFC.cjs');
|
|
64
70
|
require('../chunk-CT3SLXB7.cjs');
|
|
65
71
|
require('../chunk-DEXUL3T6.cjs');
|
|
66
|
-
require('../chunk-
|
|
72
|
+
require('../chunk-AFQTQC7A.cjs');
|
|
73
|
+
require('../chunk-XJEXFEWG.cjs');
|
|
67
74
|
require('../chunk-Z2XZ2D4N.cjs');
|
|
68
75
|
require('../chunk-YZSQ7F5K.cjs');
|
|
69
76
|
require('../chunk-MCXS6X37.cjs');
|
|
@@ -85,7 +92,7 @@ require('../chunk-PLIF5CUV.cjs');
|
|
|
85
92
|
|
|
86
93
|
Object.defineProperty(exports, "ConnectedDocumentViewer", {
|
|
87
94
|
enumerable: true,
|
|
88
|
-
get: function () { return
|
|
95
|
+
get: function () { return chunkUTJ223TI_cjs.ConnectedDocumentViewer; }
|
|
89
96
|
});
|
|
90
97
|
Object.defineProperty(exports, "ConnectedDocumentToolsProvider", {
|
|
91
98
|
enumerable: true,
|
package/dist/connection/ai.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export declare function useConnectedAiTask(): {
|
|
|
21
21
|
type: "arbi.artifact";
|
|
22
22
|
doc_ext_id: string;
|
|
23
23
|
title: string;
|
|
24
|
-
mode: "markdown" | "html" | "text" | "react" | "image";
|
|
24
|
+
mode: "markdown" | "html" | "text" | "react" | "image" | "presentation";
|
|
25
25
|
content: string;
|
|
26
26
|
file_type: string;
|
|
27
27
|
is_complete: boolean;
|
|
@@ -119,7 +119,7 @@ const MessageComponent = ({
|
|
|
119
119
|
docExtId: doc.external_id,
|
|
120
120
|
title: getDocumentTitle(doc),
|
|
121
121
|
isComplete: true,
|
|
122
|
-
mode: isImageDocument(doc) ? "image" : kind ?? "markdown"
|
|
122
|
+
mode: isImageDocument(doc) ? "image" : /\.pptx$/i.test(doc.file_name ?? "") ? "presentation" : kind ?? "markdown"
|
|
123
123
|
};
|
|
124
124
|
}, [streaming, workspaceDocs, message.external_id]);
|
|
125
125
|
const handleOpenArtifact = useCallback(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/connection/conversation/ConnectedMessage.tsx"],
|
|
4
|
-
"sourcesContent": ["/**\n * ConnectedMessage\n *\n * Renders a single message in the conversation, connected to the session and the host.\n * This component:\n * - Displays user and assistant messages with appropriate styling\n * - Handles message editing and context actions\n * - Supports markdown content rendering with syntax highlighting\n * - Manages message state (loading, error, edit mode)\n * - Coordinates with branch controls for forked conversations\n */\n\nimport {\n MessageArtifactCard,\n workflowStepOf,\n type MessageArtifact,\n useCreateFact,\n useCreateFacts,\n useDocuments,\n useWorkspaceUsers,\n useConversationWorkspace,\n stripSpeakerPrefix,\n transcriptSegmentOf,\n useThinkingContent,\n useConversationItems,\n resolveConfigModel,\n useArbiSession,\n useArbiSessionState,\n useArbiSessionStore,\n useAvailableModels,\n useConfig,\n useDeleteMessage,\n useUserSettings,\n useLinkMentions,\n} from '@arbidocs/react'\nimport { useMessageChatArtifact, useAssistantCopy } from '@arbidocs/react/shell'\nimport {\n formatFriendlyDate,\n getDocumentTitle,\n isImageDocument,\n getUserDisplayName,\n} from '@arbidocs/react/ui'\nimport React, { useState, useRef, useEffect, useMemo, useCallback, useContext } from 'react'\nimport type { ChatMessage as MessageType } from '@arbidocs/sdk/browser'\nimport { ErrorBoundary } from '../../components/ErrorBoundary'\nimport {\n MessageRoot,\n MessageContent,\n MessageAuthor,\n MessageBubble,\n MessageByline,\n MessageSubagentBadge,\n MessageBody,\n MessageNarration,\n MessageFooter,\n MessageActionButton,\n MessageActionMenu,\n type MessageActionMenuItem,\n} from '../../chat/Message'\nimport { buildDeepLinkPath } from '../../lib/deep-link'\nimport { Copy, Check, Clock, Edit3, Link, Trash2, Milestone, Share2, RotateCcw } from 'lucide-react'\nimport { AssistantEntity } from '../../agents/tasks/AssistantEntity'\nimport { AgentSteps } from './AgentSteps'\nimport { ConnectedCitationRenderer } from './ConnectedCitationRenderer'\nimport { ConnectedMarkdown } from './ConnectedMarkdown'\nimport { MessageDetailsModal } from './MessageDetailsModal'\nimport { MessageLiveSeconds } from './MessageLiveSeconds'\nimport { buildCitationChunkData } from '@arbidocs/sdk/browser'\nimport { artifactKindFromFileName, viewerTabForArtifactMode } from '@arbidocs/react/artifacts'\nimport { findMessageDocument } from '../../chat/generatedDocuments'\nimport { useOpenWorkspaceIcon } from './useOpenWorkspaceIcon'\nimport { useBlocksEnvironment } from '../../provider/environment'\nimport { DocumentUser } from '../files/fields/DocumentUser'\nimport { buildFactCitations } from '../../facts/fact-citations'\nimport { chronologyFactBodies } from '../../facts/fact-chronology'\nimport { topLevelAgentSteps } from '@arbidocs/sdk/browser'\nimport { copyMessageToClipboard } from '../../chat/message-copy'\nimport { getCurrentAgentStepPresentation } from '../../agents/runs/step-presentation'\nimport { getSubagentBranchRecord } from '@arbidocs/sdk/browser'\nimport { AskAgainContext } from './AskAgainContext'\nimport { WorkflowStepMessage } from './WorkflowStepMessage'\nimport { TranscriptEntry } from '../../calls/connected/TranscriptEntry'\nimport { useTranscriptRuns } from '../../calls/connected/transcript-runs-context'\n\nexport interface ConnectedMessageProps {\n message: MessageType\n index: number\n className?: string\n ['data-message-id']?: string\n branchControl?: React.ReactNode\n subagentLinks?: React.ReactNode\n messageHistory?: MessageType[]\n participantTint?: string\n}\n\nconst MessageComponent = ({\n message,\n index,\n branchControl,\n subagentLinks,\n messageHistory,\n participantTint,\n ...rest\n}: ConnectedMessageProps) => {\n const [isCopied, setIsCopied] = useState(false)\n const [factSaved, setFactSaved] = useState(false)\n const [isStepsExpanded, setIsStepsExpanded] = useState(false)\n const [showDetailsModal, setShowDetailsModal] = useState(false)\n const messageRef = useRef<HTMLDivElement>(null)\n\n const session = useArbiSessionStore()\n const environment = useBlocksEnvironment()\n // Stored @mentions become chips, the assistant's under the host's name for it as well.\n const linkMentions = useLinkMentions()\n const { notify } = environment\n const editingMessageId = useArbiSessionState((state) => state.editingMessageId)\n const isEditing = editingMessageId === message.external_id\n const { conversations } = useConversationItems()\n const isShared = !!conversations?.find(\n (conversation) => conversation.external_id === message.conversation_ext_id\n )?.is_shared\n const assistantTint = isShared ? 'var(--color-secondary)' : 'var(--color-primary)'\n const deleteMessage = useDeleteMessage()\n\n // Get user settings to check developer status\n const { data: userSettings } = useUserSettings()\n const isDeveloper = userSettings?.developer === true\n\n const role = (message.role || '').toLowerCase()\n const isUser = role === 'user'\n const isTopLevel = index === 0\n\n // A sub-agent task message is a `role: user` message ARBI generates itself\n // to hand a task to a delegate \u2014 it is created_by the human (the human did\n // delegate it), so it would otherwise render pixel-identical to a message\n // that human actually typed: same \"You\" pill, same bubble. Sitting right\n // next to the human's real ask, two visually-identical \"You\" bubbles read\n // as a duplicate-send bug, not \"the system rephrased this for a delegate\".\n const subagentTaskRecord = isUser ? getSubagentBranchRecord(message) : null\n\n // Get current user and workspace users to determine message author\n const currentUser = useArbiSession().user\n const {\n workspaceId: selectedWorkspaceId,\n workspace: currentWorkspace,\n icon: workspaceIcon,\n } = useOpenWorkspaceIcon()\n const { data: workspaceUsers = [] } = useWorkspaceUsers()\n\n // Inline artifact (drafted document) linked to this assistant message \u2014\n // surfaces the draft in the conversation, not only a docked panel.\n const streaming = useMessageChatArtifact(message.external_id)\n const { data: workspaceDocs } = useDocuments()\n const linkedArtifact = useMemo((): MessageArtifact | undefined => {\n if (!message.external_id) return undefined\n if (streaming) return streaming\n const doc = findMessageDocument(workspaceDocs, message.external_id)\n if (!doc) return undefined\n // A saved artifact's mode is its file's extension: .html/.jsx are live artifacts, an image is\n // an image, and anything else is a document draft (stored by the server as .docx).\n const kind = artifactKindFromFileName(doc.file_name)\n return {\n docExtId: doc.external_id,\n title: getDocumentTitle(doc),\n isComplete: true,\n mode: isImageDocument(doc) ? 'image' : (kind ?? 'markdown'),\n }\n }, [streaming, workspaceDocs, message.external_id])\n const handleOpenArtifact = useCallback(\n (docExtId: string) => {\n // Open on the tab that fits the artifact: a document draft in the Word editor, an html/react\n // artifact on its Preview, an image on its media view.\n session.setDocumentViewer({ tab: viewerTabForArtifactMode(linkedArtifact?.mode) })\n environment.openDocument(docExtId)\n },\n [linkedArtifact?.mode, session, environment]\n )\n\n // Find the user object for the message author\n const messageAuthorUser = useMemo(() => {\n if (!isUser) return null\n\n // Check if message is from current user\n const isCurrentUser = message.created_by_ext_id === currentUser?.external_id\n if (isCurrentUser && currentUser) {\n // Current user from auth store is already User-compatible\n return currentUser\n }\n\n // Find the workspace user who created this message\n const workspaceUser = workspaceUsers.find(\n (wu) => wu.user.external_id === message.created_by_ext_id\n )\n return workspaceUser?.user || null\n }, [isUser, message.created_by_ext_id, currentUser, workspaceUsers])\n\n // Someone else's typed message: left-aligned, under their person pill each time the author\n // changes (my own stay on the right; transcript lines are centred for everyone).\n const isOtherPerson =\n isUser && !!message.created_by_ext_id && message.created_by_ext_id !== currentUser?.external_id\n const startsAuthorRun = useMemo(() => {\n if (!isOtherPerson) return false\n const prev = messageHistory && index > 0 ? messageHistory[index - 1] : null\n if (!prev) return true\n const prevIsTranscript = !!transcriptSegmentOf(prev.tools ?? prev.meta?.tools)\n return (\n prev.role !== 'user' ||\n prevIsTranscript ||\n prev.created_by_ext_id !== message.created_by_ext_id\n )\n }, [isOtherPerson, messageHistory, index, message.created_by_ext_id])\n\n // Get config for this message to extract model info\n // For user messages, get the config from the immediately following assistant message\n const configId = useMemo(() => {\n if (!isUser) {\n return message.config_ext_id\n }\n\n // For user messages, get the next message (which should be the assistant response)\n if (messageHistory && index + 1 < messageHistory.length) {\n const nextMessage = messageHistory[index + 1]\n if (nextMessage.role === 'assistant') {\n return nextMessage.config_ext_id\n }\n }\n\n return message.config_ext_id // fallback\n }, [isUser, message.config_ext_id, messageHistory, index])\n\n const { data: messageConfig } = useConfig(configId || 'default')\n\n // Extract the model that actually ran for the message footer.\n //\n // Source of truth is the assistant response itself, not the request config:\n // assistant messages persist `tools.stream_events.events` which hydrate into\n // `message.agentSteps`. Each step's `usage.model` is the LLM the backend\n // actually called for that step (resolved post-FilterPlan in auto mode).\n //\n // The 'answering' step is the LLM call that produced the response content,\n // so it's the most accurate source. We fall back to the last step with a\n // recorded model (handles edge cases like a still-streaming answering step\n // or non-standard step ordering), and finally to the goal step's\n // `selected_model` for messages mid-stream that haven't recorded usage yet.\n //\n // The request config can't be used here \u2014 assistant messages typically\n // have `config_ext_id = null`, so it would just read the user's *current*\n // default config (not what ran), and in auto mode it stores the\n // placeholder `AGENT_MODEL_NAME = \"auto\"` which isn't a real model.\n const modelName = useMemo(() => {\n const steps = message.agentSteps\n if (!steps?.length) return null\n const answering = steps.find((s) => s.step === 'answering' && s.usage?.model)\n if (answering?.usage?.model) return answering.usage.model\n for (let i = steps.length - 1; i >= 0; i--) {\n const used = steps[i].usage?.model\n if (used) return used\n }\n return steps.find((s) => s.selected_model)?.selected_model ?? null\n }, [message.agentSteps])\n\n // Look up model tag for the footer icon (matches ModelSelector's tag icons)\n const { data: availableModels } = useAvailableModels()\n const modelTag = useMemo(() => {\n if (!modelName || !availableModels?.models) return null\n const info = availableModels.models.find((m) => m.model_name === modelName)\n return info?.tags?.[0] || null\n }, [modelName, availableModels])\n\n // Use model name directly for footer label \u2014 matches the ModelSelector dropdown\n const modelDisplayName = modelName\n\n // Extract citations and convert to the format CitationRenderer expects\n const activeCitations = useMemo(() => {\n const tools = message.tools || message.meta?.tools\n const modelCitations = tools?.model_citations\n const toolResponses =\n modelCitations && 'tool_responses' in modelCitations ? modelCitations.tool_responses : null\n\n if (!toolResponses || typeof toolResponses !== 'object') {\n return null\n }\n\n // Schema format: citation number as key, CitationData object as value\n // Convert to simple Record<string, string[]> for CitationRenderer\n const citationMap: Record<string, string[]> = {}\n\n Object.entries(toolResponses).forEach(([citationNum, citationData]) => {\n if (citationData && typeof citationData === 'object' && 'chunk_ids' in citationData) {\n // Frontend only needs chunk_ids from CitationData\n const citation = citationData as { chunk_ids: string[] }\n citationMap[citationNum] = citation.chunk_ids\n }\n })\n\n return Object.keys(citationMap).length > 0 ? citationMap : null\n }, [message.tools, message.meta?.tools])\n\n // Stable citation-data object so CitationRenderer (memo'd) doesn't re-render per token\n const citationData = useMemo(() => buildCitationChunkData(message), [message])\n\n // Keep faded until WebSocket confirms completion (isLoading becomes false/undefined).\n // Assistant-only: the user's own message is also stamped isLoading=true while its\n // response streams (see the chat stream handlers (@arbidocs/react)) purely to suppress the orphan-alert\n // flash, so it must not be treated as \"still generating\" for footer purposes.\n const isGenerating = !isUser && message.isLoading === true\n const isFailed = message.status === 'failed'\n // The person stopped this answer; the server keeps whatever had streamed so far.\n const isStopped = !isUser && message.status === 'cancelled'\n const isQueued = isUser && message.status === 'queued'\n\n // Kept purely to STRIP a leaked `<think>\u2026</think>` block out of the body, so a\n // model that emits one does not show raw reasoning (or a stray `</think>`) as\n // its answer. The extracted reasoning itself is discarded and shown nowhere:\n // the backend already streams real reasoning on its own channel\n // (`reasoning_content` \u2192 a reasoning output item \u2192 a row in the steps trace),\n // so surfacing this legacy copy would only duplicate it.\n const { responseContent } = useThinkingContent({\n content: message.content || '',\n modelName,\n isUser,\n isGenerating,\n })\n\n // Split the body at the settled/live boundary the stream stamped on it.\n // Before it: prose the model has moved on from, which dims. After it: what is\n // being written now, which never dims \u2014 so the answer's opacity is constant\n // from its first token and nothing un-fades at the end.\n //\n // The boundary only exists while a turn is streaming. Once the answer is\n // committed the narration has already left the body, so everything is live.\n const settledLength = isGenerating ? (message.settledNarrationLength ?? 0) : 0\n const settledNarration = settledLength ? responseContent.slice(0, settledLength).trimEnd() : ''\n const liveContent = settledLength ? responseContent.slice(settledLength) : responseContent\n\n // The server still has this turn running, but this client is not streaming it (e.g. it\n // left the thread mid-stream and cleared its local loading flag). It is not finished, so\n // do not claim it is. The attach re-connects once the thread is viewed again.\n const isRunningOnServer =\n !isUser && (message.status === 'in_progress' || message.status === 'queued')\n // A follow-up's answer waiting behind the running turn: saved with status `queued` until its\n // turn starts. Nothing is being worked on yet, so it reads as queued, not as working. Once this\n // client streams it (the row may still say `queued` until the next refetch) it is working.\n const isQueuedAnswer = !isUser && message.status === 'queued' && !isGenerating\n\n // A running turn may spend many seconds on tool steps before its first token. Show that\n // inside the bubble, since the footer step label sits well away from the answer. The same\n // line covers a turn the server still runs while this client is not streaming it.\n // A pending question means the turn is paused on the person, not working. Its card is docked\n // by the composer, out of sight from the bubble, so the bubble says whose move it is. Only while\n // the turn is live: a stopped or settled turn must not claim to be waiting on the person.\n const isAwaitingAnswer =\n (isGenerating || isRunningOnServer) && !isStopped && !!message.pendingUserInput\n const showWorkingIndicator =\n (isGenerating || isRunningOnServer) &&\n !isQueuedAnswer &&\n !responseContent.trim() &&\n !linkedArtifact &&\n !isAwaitingAnswer\n\n // What the run is doing right now (e.g. \"Thinking\", \"Searching the web\"). Without it the\n // bubble says only \"Working on the answer\u2026\" for the whole wait, and the progress lives in\n // the step bar far below. Same step the bar shows, so the two never disagree.\n const workingStepLabel = showWorkingIndicator\n ? getCurrentAgentStepPresentation(message.agentSteps ?? [])?.description\n : undefined\n\n // A settled turn can finish with no answer text (the model returned nothing). Say so\n // rather than leave an empty bubble, unless the turn produced a drafted document.\n const showEmptyAnswer =\n !isUser &&\n !isGenerating &&\n !isRunningOnServer &&\n !isFailed &&\n !isStopped &&\n !responseContent.trim() &&\n !linkedArtifact\n\n // A stopped answer with nothing streamed has no body to show.\n const isEmptyStopped = isStopped && !responseContent.trim()\n\n // \"Ask again\" on a stopped answer re-runs its question: the conversation view sends it again\n // (AskAgainContext). Where no view provides that, fall back to the question's own edit action,\n // or, for the first question (it has no edit action), to putting its text in the composer.\n const stoppedQuestion = useMemo(() => {\n if (!isStopped || !messageHistory || !message.parent_message_ext_id) return null\n const parentIndex = messageHistory.findIndex(\n (m) => m.external_id === message.parent_message_ext_id\n )\n const parent = parentIndex >= 0 ? messageHistory[parentIndex] : null\n if (!parent || (parent.role || '').toLowerCase() !== 'user') return null\n return { question: parent, isEditable: parentIndex > 0 }\n }, [isStopped, messageHistory, message.parent_message_ext_id])\n\n const askAgain = useContext(AskAgainContext)\n const askStoppedQuestionAgain = (retry: { question: MessageType; isEditable: boolean }) => {\n if (askAgain) askAgain(retry.question, message)\n else if (retry.isEditable) startEditing(retry.question)\n else session.setDraft(retry.question.content)\n }\n\n // The clean text a fact would carry PLUS its per-claim citations (each cited\n // statement's span + the chunks and quotes backing it), so a fact saved from\n // this answer keeps the chat's click-a-statement \u2192 highlight-passage\n // behaviour. The text stays clean \u2014 the mapping rides in `citations`. Whether\n // saving makes sense: a finished (not streaming, not failed) answer with real\n // content \u2014 never an empty, mid-stream, or citation-only (\"cite-1\") message.\n const factData = useMemo(\n () => buildFactCitations(responseContent, activeCitations, citationData),\n [responseContent, activeCitations, citationData]\n )\n const factText = factData.text\n const canCreateFact = !isUser && !isGenerating && !isFailed && factText.length > 2\n\n // Count the rows the drawer actually renders: raw events collapse (heartbeats,\n // same-index follow-ups) AND sub-agent steps fold under their parent, so both\n // `agentSteps.length` and a merged count would promise rows that aren't there.\n const visibleStepCount = useMemo(\n () => (message.agentSteps ? topLevelAgentSteps(message.agentSteps).length : 0),\n [message.agentSteps]\n )\n\n // The settled turn's elapsed time. The live ticker for the in-flight turn is\n // owned by the docked AgentControlBar (MessageLiveSeconds); Message itself only\n // reads the FINAL value from Zustand (written once when generation ends), so it\n // does not re-render at the 100 ms timer cadence.\n const timerKey = `${message.conversation_ext_id || 'new'}:${message.external_id}`\n const finalElapsedSeconds =\n useArbiSessionState((state) => state.messageTimers[timerKey]?.elapsedTime) ??\n message.agentStepsTotalElapsed ??\n 0\n\n // Reset copy state after delay\n useEffect(() => {\n let timeout: NodeJS.Timeout\n if (isCopied) {\n timeout = setTimeout(() => setIsCopied(false), 2000)\n }\n return () => clearTimeout(timeout)\n }, [isCopied])\n\n // Clear the \"fact created\" confirmation when this component is reused for a\n // different message (React.memo + list virtualization), so a stale green\n // check never appears on a message whose fact was never created.\n useEffect(() => {\n setFactSaved(false)\n }, [message.external_id])\n\n // Steps stay collapsed by default \u2014 the user can click the step-count chip to\n // expand. The trace is rich info but noisy for short prompts (e.g. a fresh PA\n // session's bootstrap rituals \u2014 IDENTITY.md reads, memory_search \u2014 feel like\n // garbage when the user typed a trivial message). Keep the rendered chat\n // clean; let power users opt in.\n\n const { openShare } = environment\n\n const handleCopyLink = () => {\n if (!selectedWorkspaceId || !message.conversation_ext_id || !message.external_id) {\n notify('Unable to copy link', 'error')\n return\n }\n\n const path = buildDeepLinkPath({\n workspaceId: selectedWorkspaceId,\n conversationId: message.conversation_ext_id,\n messageId: message.external_id,\n })\n\n const domain = environment.runtimeConfig.deploymentDomain\n const fullUrl = domain ? `https://${domain}${path}` : `${window.location.origin}${path}`\n\n navigator.clipboard\n .writeText(fullUrl)\n .then(() =>\n notify(\n React.createElement(\n 'span',\n {},\n React.createElement(\n 'a',\n {\n href: fullUrl,\n target: '_blank',\n rel: 'noopener noreferrer',\n className: 'text-blue-text hover:underline',\n onClick: (e: React.MouseEvent) => e.stopPropagation(),\n },\n 'Message link'\n ),\n ' copied to clipboard'\n ),\n 'success',\n { icon: workspaceIcon(20), workspaceId: selectedWorkspaceId }\n )\n )\n .catch(() => notify('Failed to copy link', 'error'))\n }\n\n const handleCopy = async () => {\n try {\n // For assistant messages, find the preceding user message\n let precedingUserMessage: string | undefined\n if (!isUser && message.parent_message_ext_id && messageHistory) {\n const parentMessage = messageHistory.find(\n (m) => m.external_id === message.parent_message_ext_id\n )\n if (parentMessage?.role === 'user') {\n precedingUserMessage = parentMessage.content\n }\n }\n\n await copyMessageToClipboard({\n messageRef,\n responseContent,\n messageContent: message.content,\n isUser,\n selectedWorkspaceId,\n conversationExtId: message.conversation_ext_id,\n messageExtId: message.external_id,\n activeCitations,\n citationData,\n precedingUserMessage,\n deploymentDomain: environment.runtimeConfig.deploymentDomain,\n })\n setIsCopied(true)\n notify('Message copied to clipboard', 'success')\n } catch (err) {\n console.error('Copy error:', err)\n // Ultimate fallback - try plain text\n const plainTextContent = isUser ? message.content : responseContent\n navigator.clipboard\n .writeText(plainTextContent)\n .then(() => {\n setIsCopied(true)\n notify('Message copied to clipboard', 'success')\n })\n .catch((err) => {\n console.error('All copy attempts failed:', err)\n notify('Could not copy message', 'error')\n })\n }\n }\n\n // Turn this assistant answer into a workspace Fact. The stored text is the\n // answer's markdown with citation links flattened to their label (a fact is\n // curated knowledge, not a link back into this thread); the answer's model\n // citations ride along as the fact's sources AND its per-statement claims, so\n // the fact stays as clickable as the answer. The fact is saved in the\n // conversation's workspace (named on the request), whichever one is open. A\n // chronology table saves as one dated fact per row, so the Timeline can place\n // each event.\n const factWorkspaceId = useConversationWorkspace(message.conversation_ext_id)\n const createFact = useCreateFact(factWorkspaceId)\n const createFacts = useCreateFacts(factWorkspaceId)\n const handleCreateFact = async () => {\n if (!canCreateFact || createFact.isPending || createFacts.isPending) return\n if (!factWorkspaceId) {\n notify('Cannot create fact: no workspace open', 'error')\n return\n }\n const chronology = chronologyFactBodies(factText, factData.citations)\n try {\n if (chronology) {\n await createFacts.mutateAsync({ facts: chronology })\n notify(`${chronology.length} facts created from the table`, 'success')\n } else {\n await createFact.mutateAsync({\n text: factText,\n shared: false,\n confirmed: true,\n tag_ext_ids: [],\n citations: factData.citations,\n })\n notify('Fact created from message', 'success')\n }\n setFactSaved(true)\n } catch (err) {\n console.error('Create fact error:', err)\n notify('Could not create fact', 'error')\n }\n }\n\n // Puts a user message back in the composer for editing; sending it branches a new answer.\n const startEditing = (target: MessageType) => {\n session.startEditing(target.external_id || '', target.content)\n\n // The edit runs on the config this message ran with, and the picker shows its model.\n if (messageConfig && 'QueryLLM' in messageConfig) {\n session.setChatModelName(resolveConfigModel(messageConfig))\n if (configId) session.setChatModel(configId)\n }\n }\n const handleEditStart = () => startEditing(message)\n\n const handleDeleteFailedMessage = async () => {\n if (!message.external_id) return\n try {\n await deleteMessage.mutateAsync(message.external_id)\n notify('Failed message deleted', 'success')\n } catch {\n notify('Failed to delete message', 'error')\n }\n }\n\n // Toggle handler removed - citations always show when available\n\n const settledForHeader = !isGenerating || isFailed\n const statusLabel = isFailed\n ? 'Response failed'\n : isStopped\n ? 'Stopped'\n : finalElapsedSeconds >= 0.05\n ? `Answered in ${finalElapsedSeconds.toFixed(1)}s`\n : 'Complete'\n const timeLabel = formatFriendlyDate(message.created_at || '')\n const messageId = message.external_id\n // A meeting thread's transcript lines: runs of one speaker, and each speaker's newest line.\n const assistant = useAssistantCopy()\n const transcriptRuns = useTranscriptRuns()\n const messageRole = isUser ? 'user' : 'assistant'\n\n const menuItems: MessageActionMenuItem[] = [\n ...(isUser\n ? [\n ...(!isTopLevel\n ? [\n {\n id: 'edit',\n label: 'Edit message',\n icon: <Edit3 size={14} />,\n onSelect: handleEditStart,\n testId: `edit-message-button-${messageId}`,\n },\n ]\n : []),\n {\n id: 'copy',\n label: 'Copy message',\n icon: <Copy size={14} />,\n onSelect: handleCopy,\n testId: `copy-message-button-${messageId}`,\n },\n ]\n : []),\n ...(isDeveloper\n ? [\n {\n id: 'details',\n label: 'View details',\n onSelect: () => setShowDetailsModal(true),\n testId: `message-details-button-${messageId}`,\n },\n ]\n : []),\n {\n id: 'copy-link',\n label: 'Copy link',\n icon: <Link size={14} className=\"mr-2\" />,\n onSelect: handleCopyLink,\n testId: `copy-link-button-${messageId}`,\n },\n ...(message.conversation_ext_id && selectedWorkspaceId && openShare\n ? [\n {\n id: 'share',\n label: 'Share via email',\n icon: <Share2 size={14} className=\"mr-2\" />,\n onSelect: () =>\n openShare({\n resourceType: 'conversation',\n resourceExtId: message.conversation_ext_id!,\n workspaceExtId: selectedWorkspaceId,\n isPrivate: !isShared,\n }),\n testId: `share-conversation-button-${messageId}`,\n },\n ]\n : []),\n ...(isFailed\n ? [\n {\n id: 'delete-failed',\n label: 'Delete failed message',\n icon: <Trash2 size={14} className=\"mr-2\" />,\n onSelect: handleDeleteFailedMessage,\n tone: 'danger' as const,\n testId: `delete-message-button-${messageId}`,\n },\n ]\n : []),\n ]\n\n const actions = (\n <>\n {branchControl}\n {isUser ? (\n <MessageActionMenu\n items={menuItems}\n heading={\n <>\n <div>\n {messageAuthorUser\n ? `${messageAuthorUser.given_name} ${messageAuthorUser.family_name ?? ''}`.trim()\n : 'Participant'}\n </div>\n <div className=\"text-xs text-muted-foreground\">{timeLabel}</div>\n </>\n }\n testId={`message-actions-menu-${messageId}`}\n />\n ) : (\n <>\n <MessageActionButton\n onClick={(e) => {\n e.stopPropagation()\n handleCreateFact()\n }}\n disabled={createFact.isPending || !canCreateFact}\n isDone={factSaved}\n title={factSaved ? 'Fact created' : 'Create a fact from this message'}\n aria-label=\"Create a fact from this message\"\n data-testid={`create-fact-button-${messageId}`}\n >\n {factSaved ? <Check size={16} /> : <Milestone size={16} />}\n </MessageActionButton>\n <MessageActionButton\n onClick={(e) => {\n e.stopPropagation()\n handleCopy()\n }}\n isDone={isCopied}\n title={isCopied ? 'Copied!' : 'Copy message with formatting'}\n data-testid={`copy-message-button-${messageId}`}\n >\n {isCopied ? <Check size={16} /> : <Copy size={16} />}\n </MessageActionButton>\n <MessageActionMenu\n items={menuItems}\n heading={\n <>\n <div>{modelDisplayName || assistant.name}</div>\n <div className=\"text-xs text-muted-foreground\">\n {timeLabel} \u00B7 {statusLabel}\n </div>\n </>\n }\n testId={`message-actions-menu-${messageId}`}\n />\n </>\n )}\n </>\n )\n\n // A stopped answer with no text and no steps has nothing for the footer to carry: its avatar\n // would float alone under the stopped note. Keep the footer when steps exist (Show steps).\n const isBareStopped = isEmptyStopped && visibleStepCount === 0\n\n const footer = settledForHeader && !isBareStopped && (\n <MessageFooter\n role={messageRole}\n align={isOtherPerson ? 'start' : 'end'}\n leading={\n isUser ? (\n // Someone else's author is the pill above their run; only mine is marked here.\n !isOtherPerson && messageAuthorUser && <DocumentUser user={messageAuthorUser} />\n ) : (\n <span\n className=\"inline-flex rounded-full p-1\"\n style={{\n backgroundColor: `color-mix(in srgb, ${assistantTint} 8%, transparent)`,\n color: assistantTint,\n }}\n // The model that wrote the answer: an icon whose tooltip names it.\n data-testid={`message-model-${messageId}`}\n >\n <AssistantEntity\n name={modelDisplayName}\n modelName={modelName}\n tag={modelTag}\n size={20}\n variant=\"icon\"\n />\n </span>\n )\n }\n actions={actions}\n steps={\n !isUser\n ? {\n count: visibleStepCount,\n open: isStepsExpanded,\n onOpenChange: setIsStepsExpanded,\n panel: message.agentSteps ? (\n <AgentSteps\n steps={message.agentSteps}\n isStreaming={false}\n totalElapsedTime={message.agentStepsTotalElapsed ?? undefined}\n className=\"border-b-0\"\n contextUsage={message.finalContextUsage}\n />\n ) : null,\n }\n : undefined\n }\n />\n )\n\n const stoppedNote = isStopped && !isGenerating && (\n <p\n className=\"mt-2 flex flex-wrap items-center gap-2 text-sm text-muted-foreground\"\n data-testid={`message-stopped-${messageId}`}\n >\n <span>\n {isEmptyStopped\n ? 'You stopped this answer before it wrote anything.'\n : 'You stopped this answer.'}\n </span>\n {stoppedQuestion && (\n <button\n type=\"button\"\n onClick={() => askStoppedQuestionAgain(stoppedQuestion)}\n className=\"inline-flex items-center gap-1 underline-offset-2 hover:text-foreground hover:underline\"\n data-testid={`retry-stopped-answer-button-${messageId}`}\n >\n <RotateCcw size={12} aria-hidden=\"true\" />\n Ask again\n </button>\n )}\n </p>\n )\n\n // The server's instruction that starts a workflow step reads as that step, not as raw text.\n const workflowStep = isUser ? workflowStepOf(message.tools ?? message.meta?.tools) : undefined\n if (workflowStep)\n return (\n <WorkflowStepMessage\n messageId={messageId}\n conversationId={message.conversation_ext_id}\n step={workflowStep}\n content={message.content ?? ''}\n />\n )\n\n // A call's transcript line in its meeting thread: a compact attributed line, not a comment.\n const transcriptSegment = isUser\n ? transcriptSegmentOf(message.tools ?? message.meta?.tools)\n : undefined\n if (transcriptSegment) {\n const speaker =\n transcriptSegment.speaker_ext_id === currentUser?.external_id\n ? currentUser\n : workspaceUsers.find((wu) => wu.user.external_id === transcriptSegment.speaker_ext_id)\n ?.user\n const speakerName = speaker ? getUserDisplayName(speaker) : null\n const isMe = transcriptSegment.speaker_ext_id === currentUser?.external_id\n return (\n <TranscriptEntry\n speakerId={transcriptSegment.speaker_ext_id}\n speakerName={isMe ? 'Me' : speakerName || 'Former member'}\n text={stripSpeakerPrefix(message.content ?? '', speakerName)}\n at={transcriptSegment.started_at ?? message.created_at}\n continued={!!messageId && transcriptRuns.continued.has(messageId)}\n />\n )\n }\n\n return (\n <ErrorBoundary testId=\"message-error-boundary\">\n <MessageRoot\n role={messageRole}\n messageId={messageId}\n tone={isFailed ? 'error' : subagentTaskRecord ? 'subagent' : 'default'}\n {...rest}\n >\n <MessageContent\n role={messageRole}\n messageId={messageId}\n align={isOtherPerson ? 'start' : 'end'}\n >\n {startsAuthorRun && messageAuthorUser && (\n <MessageAuthor>\n <DocumentUser user={messageAuthorUser} variant=\"pill\" />\n </MessageAuthor>\n )}\n <MessageBubble\n ref={messageRef}\n role={messageRole}\n messageId={messageId}\n isEditing={isEditing}\n // Other people's messages share ONE surface (the chats' peer bubble: card + hairline),\n // whoever wrote them: a per-person tint at 4% read as beige for one hue and as no\n // bubble at all for another. My own keep their tint; the assistant its own.\n participantTint={\n isFailed || isEmptyStopped || isOtherPerson\n ? undefined\n : isUser\n ? participantTint\n : assistantTint\n }\n className={isOtherPerson ? 'border border-border bg-card' : undefined}\n >\n {!isUser && isGenerating && (\n <MessageByline\n messageId={messageId}\n identity={\n // Stays the ARBI identity while streaming: the model name arrives\n // with the first step that reports one and would swap the author\n // mid-answer. The model is shown in the footer once settled.\n <AssistantEntity size={16} />\n }\n timeLabel={timeLabel}\n isSettled={settledForHeader}\n isFailed={isFailed}\n statusLabel={statusLabel}\n />\n )}\n {/* Marks this as ARBI's own instruction to a delegate, not something the human\n typed (see `subagentTaskRecord`). */}\n {subagentTaskRecord && <MessageSubagentBadge messageId={messageId} />}\n {/* While the turn runs this holds EVERYTHING the model has said. Only SUPERSEDED\n prose dims (a real opacity, not a colour token); the live segment is solid so\n the answer's opacity never changes and nothing un-fades at the end. The single\n commit at `response.completed` swaps in the server's answer and its citations. */}\n <MessageBody messageId={messageId}>\n {settledNarration ? (\n <MessageNarration messageId={messageId}>\n <ConnectedMarkdown isStreaming={false}>{settledNarration}</ConnectedMarkdown>\n </MessageNarration>\n ) : null}\n {liveContent ? (\n role === 'assistant' ? (\n <ConnectedCitationRenderer\n content={liveContent}\n citations={activeCitations || undefined}\n citationData={citationData}\n messageId={message.external_id || 'unknown'}\n isStreaming={isGenerating}\n />\n ) : (\n <ConnectedMarkdown isStreaming={isGenerating}>\n {/* ``/pa `` is internal routing: show the user's actual text. Stored\n @mentions become chips. */}\n {linkMentions(\n isUser && liveContent.startsWith('/pa ') ? liveContent.slice(4) : liveContent,\n message.mentions\n )}\n </ConnectedMarkdown>\n )\n ) : null}\n {showWorkingIndicator && (\n // One line of running text, not a flex row: in a narrow column (the viewer docked\n // beside the chat) flex items each shrank and wrapped on their own, as columns.\n <div>\n <p\n className=\"text-muted-foreground italic\"\n data-testid={`message-thinking-${messageId}`}\n >\n <span className=\"mr-2 inline-block h-2 w-2 animate-pulse rounded-full bg-current align-middle\" />\n Working on the answer\u2026\n {workingStepLabel && (\n <>\n {' '}\n <span\n className=\"not-italic\"\n data-testid={`message-thinking-step-${messageId}`}\n >\n \u00B7 {workingStepLabel}\n </span>\n </>\n )}\n {/* Total wait stays visible as individual steps change in the control bar.\n Only a turn this client is streaming has a clock to show. */}\n {isGenerating && (\n <>\n {' '}\n <span\n className=\"whitespace-nowrap not-italic\"\n data-testid={`message-thinking-elapsed-${messageId}`}\n >\n \u00B7{' '}\n <MessageLiveSeconds\n conversationId={message.conversation_ext_id}\n messageId={messageId}\n isUser={false}\n isGenerating={isGenerating}\n suffix=\"s elapsed\"\n />\n </span>\n </>\n )}\n </p>\n {isGenerating && (\n <p\n className=\"text-sm text-muted-foreground\"\n data-testid={`message-wait-help-${messageId}`}\n >\n You can stop this answer or choose Ask for status from the menu beside Stop.\n </p>\n )}\n </div>\n )}\n {isQueuedAnswer && !responseContent.trim() && (\n <p\n className=\"flex items-center gap-2 text-muted-foreground\"\n data-testid={`message-queued-${messageId}`}\n >\n <Clock className=\"size-3.5 shrink-0\" aria-hidden />\n Queued\n </p>\n )}\n {isAwaitingAnswer && (\n <p\n className=\"font-medium text-foreground\"\n data-testid={`message-awaiting-answer-${messageId}`}\n >\n Waiting for your answer below\n </p>\n )}\n {showEmptyAnswer && (\n <p\n className=\"text-muted-foreground italic\"\n data-testid={`message-empty-answer-${messageId}`}\n >\n ARBI finished without an answer. Ask again or request changes to retry.\n </p>\n )}\n </MessageBody>\n {/* A follow-up sent mid-answer waits its turn. The bubble stays solid (a faded\n bubble read as lost), so the state is said in words. */}\n {isQueued && (\n <p\n className=\"mt-1 flex items-center gap-1.5 text-xs text-muted-foreground\"\n data-testid={`message-queued-${messageId}`}\n >\n <Clock className=\"size-3 shrink-0\" aria-hidden />\n Queued, ARBI will answer after the current reply\n </p>\n )}\n\n {/* Inline drafted-document affordance */}\n {!isUser && linkedArtifact && (\n <MessageArtifactCard artifact={linkedArtifact} onOpen={handleOpenArtifact} />\n )}\n\n {/* Sub-agent thread links sit OUTSIDE the settled-only footer: a delegated thread\n must be openable whether this turn is streaming or long done. */}\n {!isUser && subagentLinks}\n </MessageBubble>\n {footer}\n {/* Below the footer, not in the bubble, for every stopped answer: the steps popover\n opens upward over the bubble and would hide the note while the trace is open. */}\n {stoppedNote}\n </MessageContent>\n\n <MessageDetailsModal\n open={showDetailsModal}\n onOpenChange={setShowDetailsModal}\n messageExtId={message.external_id || null}\n workspace={\n currentWorkspace\n ? {\n name: currentWorkspace.name,\n icon: workspaceIcon(16),\n }\n : null\n }\n />\n </MessageRoot>\n </ErrorBoundary>\n )\n}\n\n/**\n * Custom comparison for React.memo to prevent unnecessary re-renders during streaming.\n *\n * Most fields are read directly off `prevProps.message` / `nextProps.message`\n * \u2014 we deliberately do NOT peek into `messageHistory[index + 1]` for\n * assistant messages, because during streaming every message's\n * `messageHistory` reference changes on every rAF flush and a neighbor-index\n * read would cascade re-renders across the whole list.\n *\n * Exception: a USER message's model-switch indicator is derived from the\n * NEXT message's `config_ext_id` (the assistant response \u2014 see the\n * `configId` useMemo at line ~106). For user messages we must re-render\n * when that specific neighbor's config changes, or the indicator stays\n * stale after an assistant completes. Assistant messages still only look\n * at their own config_ext_id, so the cascade stays contained.\n */\nfunction areMessagesEqual(\n prevProps: ConnectedMessageProps,\n nextProps: ConnectedMessageProps\n): boolean {\n if (prevProps.participantTint !== nextProps.participantTint) return false\n // Always re-render if the message content or loading state changed\n if (prevProps.message.content !== nextProps.message.content) return false\n if (prevProps.message.isLoading !== nextProps.message.isLoading) return false\n if (prevProps.message.status !== nextProps.message.status) return false\n if (prevProps.message.external_id !== nextProps.message.external_id) return false\n if (prevProps.message.created_at !== nextProps.message.created_at) return false\n if (prevProps.message.config_ext_id !== nextProps.message.config_ext_id) return false\n if (prevProps.message.mentions !== nextProps.message.mentions) return false\n\n // User messages derive their model indicator from the next (assistant)\n // message's config \u2014 catch changes there so the indicator refreshes when\n // the assistant response arrives / switches model.\n if (prevProps.message.role === 'user') {\n const prevNext = prevProps.messageHistory?.[prevProps.index + 1]\n const nextNext = nextProps.messageHistory?.[nextProps.index + 1]\n if (prevNext?.config_ext_id !== nextNext?.config_ext_id) return false\n }\n\n // Re-render if message metadata changed (tools contain citations)\n if (prevProps.message.tools !== nextProps.message.tools) return false\n if (prevProps.message.meta !== nextProps.message.meta) return false\n\n // Re-render if agent steps or pending user input changed\n if (prevProps.message.agentSteps !== nextProps.message.agentSteps) return false\n if (prevProps.message.pendingUserInput !== nextProps.message.pendingUserInput) return false\n\n // Re-render if structural props changed\n if (prevProps.index !== nextProps.index) return false\n\n // branchControl is React node - compare by reference (will be same if parent doesn't re-render)\n if (prevProps.branchControl !== nextProps.branchControl) return false\n if (prevProps.subagentLinks !== nextProps.subagentLinks) return false\n\n return true\n}\n\nexport const ConnectedMessage = React.memo(MessageComponent, areMessagesEqual)\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/**\n * ConnectedMessage\n *\n * Renders a single message in the conversation, connected to the session and the host.\n * This component:\n * - Displays user and assistant messages with appropriate styling\n * - Handles message editing and context actions\n * - Supports markdown content rendering with syntax highlighting\n * - Manages message state (loading, error, edit mode)\n * - Coordinates with branch controls for forked conversations\n */\n\nimport {\n MessageArtifactCard,\n workflowStepOf,\n type MessageArtifact,\n useCreateFact,\n useCreateFacts,\n useDocuments,\n useWorkspaceUsers,\n useConversationWorkspace,\n stripSpeakerPrefix,\n transcriptSegmentOf,\n useThinkingContent,\n useConversationItems,\n resolveConfigModel,\n useArbiSession,\n useArbiSessionState,\n useArbiSessionStore,\n useAvailableModels,\n useConfig,\n useDeleteMessage,\n useUserSettings,\n useLinkMentions,\n} from '@arbidocs/react'\nimport { useMessageChatArtifact, useAssistantCopy } from '@arbidocs/react/shell'\nimport {\n formatFriendlyDate,\n getDocumentTitle,\n isImageDocument,\n getUserDisplayName,\n} from '@arbidocs/react/ui'\nimport React, { useState, useRef, useEffect, useMemo, useCallback, useContext } from 'react'\nimport type { ChatMessage as MessageType } from '@arbidocs/sdk/browser'\nimport { ErrorBoundary } from '../../components/ErrorBoundary'\nimport {\n MessageRoot,\n MessageContent,\n MessageAuthor,\n MessageBubble,\n MessageByline,\n MessageSubagentBadge,\n MessageBody,\n MessageNarration,\n MessageFooter,\n MessageActionButton,\n MessageActionMenu,\n type MessageActionMenuItem,\n} from '../../chat/Message'\nimport { buildDeepLinkPath } from '../../lib/deep-link'\nimport { Copy, Check, Clock, Edit3, Link, Trash2, Milestone, Share2, RotateCcw } from 'lucide-react'\nimport { AssistantEntity } from '../../agents/tasks/AssistantEntity'\nimport { AgentSteps } from './AgentSteps'\nimport { ConnectedCitationRenderer } from './ConnectedCitationRenderer'\nimport { ConnectedMarkdown } from './ConnectedMarkdown'\nimport { MessageDetailsModal } from './MessageDetailsModal'\nimport { MessageLiveSeconds } from './MessageLiveSeconds'\nimport { buildCitationChunkData } from '@arbidocs/sdk/browser'\nimport { artifactKindFromFileName, viewerTabForArtifactMode } from '@arbidocs/react/artifacts'\nimport { findMessageDocument } from '../../chat/generatedDocuments'\nimport { useOpenWorkspaceIcon } from './useOpenWorkspaceIcon'\nimport { useBlocksEnvironment } from '../../provider/environment'\nimport { DocumentUser } from '../files/fields/DocumentUser'\nimport { buildFactCitations } from '../../facts/fact-citations'\nimport { chronologyFactBodies } from '../../facts/fact-chronology'\nimport { topLevelAgentSteps } from '@arbidocs/sdk/browser'\nimport { copyMessageToClipboard } from '../../chat/message-copy'\nimport { getCurrentAgentStepPresentation } from '../../agents/runs/step-presentation'\nimport { getSubagentBranchRecord } from '@arbidocs/sdk/browser'\nimport { AskAgainContext } from './AskAgainContext'\nimport { WorkflowStepMessage } from './WorkflowStepMessage'\nimport { TranscriptEntry } from '../../calls/connected/TranscriptEntry'\nimport { useTranscriptRuns } from '../../calls/connected/transcript-runs-context'\n\nexport interface ConnectedMessageProps {\n message: MessageType\n index: number\n className?: string\n ['data-message-id']?: string\n branchControl?: React.ReactNode\n subagentLinks?: React.ReactNode\n messageHistory?: MessageType[]\n participantTint?: string\n}\n\nconst MessageComponent = ({\n message,\n index,\n branchControl,\n subagentLinks,\n messageHistory,\n participantTint,\n ...rest\n}: ConnectedMessageProps) => {\n const [isCopied, setIsCopied] = useState(false)\n const [factSaved, setFactSaved] = useState(false)\n const [isStepsExpanded, setIsStepsExpanded] = useState(false)\n const [showDetailsModal, setShowDetailsModal] = useState(false)\n const messageRef = useRef<HTMLDivElement>(null)\n\n const session = useArbiSessionStore()\n const environment = useBlocksEnvironment()\n // Stored @mentions become chips, the assistant's under the host's name for it as well.\n const linkMentions = useLinkMentions()\n const { notify } = environment\n const editingMessageId = useArbiSessionState((state) => state.editingMessageId)\n const isEditing = editingMessageId === message.external_id\n const { conversations } = useConversationItems()\n const isShared = !!conversations?.find(\n (conversation) => conversation.external_id === message.conversation_ext_id\n )?.is_shared\n const assistantTint = isShared ? 'var(--color-secondary)' : 'var(--color-primary)'\n const deleteMessage = useDeleteMessage()\n\n // Get user settings to check developer status\n const { data: userSettings } = useUserSettings()\n const isDeveloper = userSettings?.developer === true\n\n const role = (message.role || '').toLowerCase()\n const isUser = role === 'user'\n const isTopLevel = index === 0\n\n // A sub-agent task message is a `role: user` message ARBI generates itself\n // to hand a task to a delegate \u2014 it is created_by the human (the human did\n // delegate it), so it would otherwise render pixel-identical to a message\n // that human actually typed: same \"You\" pill, same bubble. Sitting right\n // next to the human's real ask, two visually-identical \"You\" bubbles read\n // as a duplicate-send bug, not \"the system rephrased this for a delegate\".\n const subagentTaskRecord = isUser ? getSubagentBranchRecord(message) : null\n\n // Get current user and workspace users to determine message author\n const currentUser = useArbiSession().user\n const {\n workspaceId: selectedWorkspaceId,\n workspace: currentWorkspace,\n icon: workspaceIcon,\n } = useOpenWorkspaceIcon()\n const { data: workspaceUsers = [] } = useWorkspaceUsers()\n\n // Inline artifact (drafted document) linked to this assistant message \u2014\n // surfaces the draft in the conversation, not only a docked panel.\n const streaming = useMessageChatArtifact(message.external_id)\n const { data: workspaceDocs } = useDocuments()\n const linkedArtifact = useMemo((): MessageArtifact | undefined => {\n if (!message.external_id) return undefined\n if (streaming) return streaming\n const doc = findMessageDocument(workspaceDocs, message.external_id)\n if (!doc) return undefined\n // A saved artifact's mode is its file's extension: .html/.jsx are live artifacts, an image is\n // an image, a .pptx a slide deck, and anything else is a document draft (stored as .docx).\n const kind = artifactKindFromFileName(doc.file_name)\n return {\n docExtId: doc.external_id,\n title: getDocumentTitle(doc),\n isComplete: true,\n mode: isImageDocument(doc)\n ? 'image'\n : /\\.pptx$/i.test(doc.file_name ?? '')\n ? 'presentation'\n : (kind ?? 'markdown'),\n }\n }, [streaming, workspaceDocs, message.external_id])\n const handleOpenArtifact = useCallback(\n (docExtId: string) => {\n // Open on the tab that fits the artifact: a document draft in the Word editor, an html/react\n // artifact on its Preview, an image on its media view.\n session.setDocumentViewer({ tab: viewerTabForArtifactMode(linkedArtifact?.mode) })\n environment.openDocument(docExtId)\n },\n [linkedArtifact?.mode, session, environment]\n )\n\n // Find the user object for the message author\n const messageAuthorUser = useMemo(() => {\n if (!isUser) return null\n\n // Check if message is from current user\n const isCurrentUser = message.created_by_ext_id === currentUser?.external_id\n if (isCurrentUser && currentUser) {\n // Current user from auth store is already User-compatible\n return currentUser\n }\n\n // Find the workspace user who created this message\n const workspaceUser = workspaceUsers.find(\n (wu) => wu.user.external_id === message.created_by_ext_id\n )\n return workspaceUser?.user || null\n }, [isUser, message.created_by_ext_id, currentUser, workspaceUsers])\n\n // Someone else's typed message: left-aligned, under their person pill each time the author\n // changes (my own stay on the right; transcript lines are centred for everyone).\n const isOtherPerson =\n isUser && !!message.created_by_ext_id && message.created_by_ext_id !== currentUser?.external_id\n const startsAuthorRun = useMemo(() => {\n if (!isOtherPerson) return false\n const prev = messageHistory && index > 0 ? messageHistory[index - 1] : null\n if (!prev) return true\n const prevIsTranscript = !!transcriptSegmentOf(prev.tools ?? prev.meta?.tools)\n return (\n prev.role !== 'user' ||\n prevIsTranscript ||\n prev.created_by_ext_id !== message.created_by_ext_id\n )\n }, [isOtherPerson, messageHistory, index, message.created_by_ext_id])\n\n // Get config for this message to extract model info\n // For user messages, get the config from the immediately following assistant message\n const configId = useMemo(() => {\n if (!isUser) {\n return message.config_ext_id\n }\n\n // For user messages, get the next message (which should be the assistant response)\n if (messageHistory && index + 1 < messageHistory.length) {\n const nextMessage = messageHistory[index + 1]\n if (nextMessage.role === 'assistant') {\n return nextMessage.config_ext_id\n }\n }\n\n return message.config_ext_id // fallback\n }, [isUser, message.config_ext_id, messageHistory, index])\n\n const { data: messageConfig } = useConfig(configId || 'default')\n\n // Extract the model that actually ran for the message footer.\n //\n // Source of truth is the assistant response itself, not the request config:\n // assistant messages persist `tools.stream_events.events` which hydrate into\n // `message.agentSteps`. Each step's `usage.model` is the LLM the backend\n // actually called for that step (resolved post-FilterPlan in auto mode).\n //\n // The 'answering' step is the LLM call that produced the response content,\n // so it's the most accurate source. We fall back to the last step with a\n // recorded model (handles edge cases like a still-streaming answering step\n // or non-standard step ordering), and finally to the goal step's\n // `selected_model` for messages mid-stream that haven't recorded usage yet.\n //\n // The request config can't be used here \u2014 assistant messages typically\n // have `config_ext_id = null`, so it would just read the user's *current*\n // default config (not what ran), and in auto mode it stores the\n // placeholder `AGENT_MODEL_NAME = \"auto\"` which isn't a real model.\n const modelName = useMemo(() => {\n const steps = message.agentSteps\n if (!steps?.length) return null\n const answering = steps.find((s) => s.step === 'answering' && s.usage?.model)\n if (answering?.usage?.model) return answering.usage.model\n for (let i = steps.length - 1; i >= 0; i--) {\n const used = steps[i].usage?.model\n if (used) return used\n }\n return steps.find((s) => s.selected_model)?.selected_model ?? null\n }, [message.agentSteps])\n\n // Look up model tag for the footer icon (matches ModelSelector's tag icons)\n const { data: availableModels } = useAvailableModels()\n const modelTag = useMemo(() => {\n if (!modelName || !availableModels?.models) return null\n const info = availableModels.models.find((m) => m.model_name === modelName)\n return info?.tags?.[0] || null\n }, [modelName, availableModels])\n\n // Use model name directly for footer label \u2014 matches the ModelSelector dropdown\n const modelDisplayName = modelName\n\n // Extract citations and convert to the format CitationRenderer expects\n const activeCitations = useMemo(() => {\n const tools = message.tools || message.meta?.tools\n const modelCitations = tools?.model_citations\n const toolResponses =\n modelCitations && 'tool_responses' in modelCitations ? modelCitations.tool_responses : null\n\n if (!toolResponses || typeof toolResponses !== 'object') {\n return null\n }\n\n // Schema format: citation number as key, CitationData object as value\n // Convert to simple Record<string, string[]> for CitationRenderer\n const citationMap: Record<string, string[]> = {}\n\n Object.entries(toolResponses).forEach(([citationNum, citationData]) => {\n if (citationData && typeof citationData === 'object' && 'chunk_ids' in citationData) {\n // Frontend only needs chunk_ids from CitationData\n const citation = citationData as { chunk_ids: string[] }\n citationMap[citationNum] = citation.chunk_ids\n }\n })\n\n return Object.keys(citationMap).length > 0 ? citationMap : null\n }, [message.tools, message.meta?.tools])\n\n // Stable citation-data object so CitationRenderer (memo'd) doesn't re-render per token\n const citationData = useMemo(() => buildCitationChunkData(message), [message])\n\n // Keep faded until WebSocket confirms completion (isLoading becomes false/undefined).\n // Assistant-only: the user's own message is also stamped isLoading=true while its\n // response streams (see the chat stream handlers (@arbidocs/react)) purely to suppress the orphan-alert\n // flash, so it must not be treated as \"still generating\" for footer purposes.\n const isGenerating = !isUser && message.isLoading === true\n const isFailed = message.status === 'failed'\n // The person stopped this answer; the server keeps whatever had streamed so far.\n const isStopped = !isUser && message.status === 'cancelled'\n const isQueued = isUser && message.status === 'queued'\n\n // Kept purely to STRIP a leaked `<think>\u2026</think>` block out of the body, so a\n // model that emits one does not show raw reasoning (or a stray `</think>`) as\n // its answer. The extracted reasoning itself is discarded and shown nowhere:\n // the backend already streams real reasoning on its own channel\n // (`reasoning_content` \u2192 a reasoning output item \u2192 a row in the steps trace),\n // so surfacing this legacy copy would only duplicate it.\n const { responseContent } = useThinkingContent({\n content: message.content || '',\n modelName,\n isUser,\n isGenerating,\n })\n\n // Split the body at the settled/live boundary the stream stamped on it.\n // Before it: prose the model has moved on from, which dims. After it: what is\n // being written now, which never dims \u2014 so the answer's opacity is constant\n // from its first token and nothing un-fades at the end.\n //\n // The boundary only exists while a turn is streaming. Once the answer is\n // committed the narration has already left the body, so everything is live.\n const settledLength = isGenerating ? (message.settledNarrationLength ?? 0) : 0\n const settledNarration = settledLength ? responseContent.slice(0, settledLength).trimEnd() : ''\n const liveContent = settledLength ? responseContent.slice(settledLength) : responseContent\n\n // The server still has this turn running, but this client is not streaming it (e.g. it\n // left the thread mid-stream and cleared its local loading flag). It is not finished, so\n // do not claim it is. The attach re-connects once the thread is viewed again.\n const isRunningOnServer =\n !isUser && (message.status === 'in_progress' || message.status === 'queued')\n // A follow-up's answer waiting behind the running turn: saved with status `queued` until its\n // turn starts. Nothing is being worked on yet, so it reads as queued, not as working. Once this\n // client streams it (the row may still say `queued` until the next refetch) it is working.\n const isQueuedAnswer = !isUser && message.status === 'queued' && !isGenerating\n\n // A running turn may spend many seconds on tool steps before its first token. Show that\n // inside the bubble, since the footer step label sits well away from the answer. The same\n // line covers a turn the server still runs while this client is not streaming it.\n // A pending question means the turn is paused on the person, not working. Its card is docked\n // by the composer, out of sight from the bubble, so the bubble says whose move it is. Only while\n // the turn is live: a stopped or settled turn must not claim to be waiting on the person.\n const isAwaitingAnswer =\n (isGenerating || isRunningOnServer) && !isStopped && !!message.pendingUserInput\n const showWorkingIndicator =\n (isGenerating || isRunningOnServer) &&\n !isQueuedAnswer &&\n !responseContent.trim() &&\n !linkedArtifact &&\n !isAwaitingAnswer\n\n // What the run is doing right now (e.g. \"Thinking\", \"Searching the web\"). Without it the\n // bubble says only \"Working on the answer\u2026\" for the whole wait, and the progress lives in\n // the step bar far below. Same step the bar shows, so the two never disagree.\n const workingStepLabel = showWorkingIndicator\n ? getCurrentAgentStepPresentation(message.agentSteps ?? [])?.description\n : undefined\n\n // A settled turn can finish with no answer text (the model returned nothing). Say so\n // rather than leave an empty bubble, unless the turn produced a drafted document.\n const showEmptyAnswer =\n !isUser &&\n !isGenerating &&\n !isRunningOnServer &&\n !isFailed &&\n !isStopped &&\n !responseContent.trim() &&\n !linkedArtifact\n\n // A stopped answer with nothing streamed has no body to show.\n const isEmptyStopped = isStopped && !responseContent.trim()\n\n // \"Ask again\" on a stopped answer re-runs its question: the conversation view sends it again\n // (AskAgainContext). Where no view provides that, fall back to the question's own edit action,\n // or, for the first question (it has no edit action), to putting its text in the composer.\n const stoppedQuestion = useMemo(() => {\n if (!isStopped || !messageHistory || !message.parent_message_ext_id) return null\n const parentIndex = messageHistory.findIndex(\n (m) => m.external_id === message.parent_message_ext_id\n )\n const parent = parentIndex >= 0 ? messageHistory[parentIndex] : null\n if (!parent || (parent.role || '').toLowerCase() !== 'user') return null\n return { question: parent, isEditable: parentIndex > 0 }\n }, [isStopped, messageHistory, message.parent_message_ext_id])\n\n const askAgain = useContext(AskAgainContext)\n const askStoppedQuestionAgain = (retry: { question: MessageType; isEditable: boolean }) => {\n if (askAgain) askAgain(retry.question, message)\n else if (retry.isEditable) startEditing(retry.question)\n else session.setDraft(retry.question.content)\n }\n\n // The clean text a fact would carry PLUS its per-claim citations (each cited\n // statement's span + the chunks and quotes backing it), so a fact saved from\n // this answer keeps the chat's click-a-statement \u2192 highlight-passage\n // behaviour. The text stays clean \u2014 the mapping rides in `citations`. Whether\n // saving makes sense: a finished (not streaming, not failed) answer with real\n // content \u2014 never an empty, mid-stream, or citation-only (\"cite-1\") message.\n const factData = useMemo(\n () => buildFactCitations(responseContent, activeCitations, citationData),\n [responseContent, activeCitations, citationData]\n )\n const factText = factData.text\n const canCreateFact = !isUser && !isGenerating && !isFailed && factText.length > 2\n\n // Count the rows the drawer actually renders: raw events collapse (heartbeats,\n // same-index follow-ups) AND sub-agent steps fold under their parent, so both\n // `agentSteps.length` and a merged count would promise rows that aren't there.\n const visibleStepCount = useMemo(\n () => (message.agentSteps ? topLevelAgentSteps(message.agentSteps).length : 0),\n [message.agentSteps]\n )\n\n // The settled turn's elapsed time. The live ticker for the in-flight turn is\n // owned by the docked AgentControlBar (MessageLiveSeconds); Message itself only\n // reads the FINAL value from Zustand (written once when generation ends), so it\n // does not re-render at the 100 ms timer cadence.\n const timerKey = `${message.conversation_ext_id || 'new'}:${message.external_id}`\n const finalElapsedSeconds =\n useArbiSessionState((state) => state.messageTimers[timerKey]?.elapsedTime) ??\n message.agentStepsTotalElapsed ??\n 0\n\n // Reset copy state after delay\n useEffect(() => {\n let timeout: NodeJS.Timeout\n if (isCopied) {\n timeout = setTimeout(() => setIsCopied(false), 2000)\n }\n return () => clearTimeout(timeout)\n }, [isCopied])\n\n // Clear the \"fact created\" confirmation when this component is reused for a\n // different message (React.memo + list virtualization), so a stale green\n // check never appears on a message whose fact was never created.\n useEffect(() => {\n setFactSaved(false)\n }, [message.external_id])\n\n // Steps stay collapsed by default \u2014 the user can click the step-count chip to\n // expand. The trace is rich info but noisy for short prompts (e.g. a fresh PA\n // session's bootstrap rituals \u2014 IDENTITY.md reads, memory_search \u2014 feel like\n // garbage when the user typed a trivial message). Keep the rendered chat\n // clean; let power users opt in.\n\n const { openShare } = environment\n\n const handleCopyLink = () => {\n if (!selectedWorkspaceId || !message.conversation_ext_id || !message.external_id) {\n notify('Unable to copy link', 'error')\n return\n }\n\n const path = buildDeepLinkPath({\n workspaceId: selectedWorkspaceId,\n conversationId: message.conversation_ext_id,\n messageId: message.external_id,\n })\n\n const domain = environment.runtimeConfig.deploymentDomain\n const fullUrl = domain ? `https://${domain}${path}` : `${window.location.origin}${path}`\n\n navigator.clipboard\n .writeText(fullUrl)\n .then(() =>\n notify(\n React.createElement(\n 'span',\n {},\n React.createElement(\n 'a',\n {\n href: fullUrl,\n target: '_blank',\n rel: 'noopener noreferrer',\n className: 'text-blue-text hover:underline',\n onClick: (e: React.MouseEvent) => e.stopPropagation(),\n },\n 'Message link'\n ),\n ' copied to clipboard'\n ),\n 'success',\n { icon: workspaceIcon(20), workspaceId: selectedWorkspaceId }\n )\n )\n .catch(() => notify('Failed to copy link', 'error'))\n }\n\n const handleCopy = async () => {\n try {\n // For assistant messages, find the preceding user message\n let precedingUserMessage: string | undefined\n if (!isUser && message.parent_message_ext_id && messageHistory) {\n const parentMessage = messageHistory.find(\n (m) => m.external_id === message.parent_message_ext_id\n )\n if (parentMessage?.role === 'user') {\n precedingUserMessage = parentMessage.content\n }\n }\n\n await copyMessageToClipboard({\n messageRef,\n responseContent,\n messageContent: message.content,\n isUser,\n selectedWorkspaceId,\n conversationExtId: message.conversation_ext_id,\n messageExtId: message.external_id,\n activeCitations,\n citationData,\n precedingUserMessage,\n deploymentDomain: environment.runtimeConfig.deploymentDomain,\n })\n setIsCopied(true)\n notify('Message copied to clipboard', 'success')\n } catch (err) {\n console.error('Copy error:', err)\n // Ultimate fallback - try plain text\n const plainTextContent = isUser ? message.content : responseContent\n navigator.clipboard\n .writeText(plainTextContent)\n .then(() => {\n setIsCopied(true)\n notify('Message copied to clipboard', 'success')\n })\n .catch((err) => {\n console.error('All copy attempts failed:', err)\n notify('Could not copy message', 'error')\n })\n }\n }\n\n // Turn this assistant answer into a workspace Fact. The stored text is the\n // answer's markdown with citation links flattened to their label (a fact is\n // curated knowledge, not a link back into this thread); the answer's model\n // citations ride along as the fact's sources AND its per-statement claims, so\n // the fact stays as clickable as the answer. The fact is saved in the\n // conversation's workspace (named on the request), whichever one is open. A\n // chronology table saves as one dated fact per row, so the Timeline can place\n // each event.\n const factWorkspaceId = useConversationWorkspace(message.conversation_ext_id)\n const createFact = useCreateFact(factWorkspaceId)\n const createFacts = useCreateFacts(factWorkspaceId)\n const handleCreateFact = async () => {\n if (!canCreateFact || createFact.isPending || createFacts.isPending) return\n if (!factWorkspaceId) {\n notify('Cannot create fact: no workspace open', 'error')\n return\n }\n const chronology = chronologyFactBodies(factText, factData.citations)\n try {\n if (chronology) {\n await createFacts.mutateAsync({ facts: chronology })\n notify(`${chronology.length} facts created from the table`, 'success')\n } else {\n await createFact.mutateAsync({\n text: factText,\n shared: false,\n confirmed: true,\n tag_ext_ids: [],\n citations: factData.citations,\n })\n notify('Fact created from message', 'success')\n }\n setFactSaved(true)\n } catch (err) {\n console.error('Create fact error:', err)\n notify('Could not create fact', 'error')\n }\n }\n\n // Puts a user message back in the composer for editing; sending it branches a new answer.\n const startEditing = (target: MessageType) => {\n session.startEditing(target.external_id || '', target.content)\n\n // The edit runs on the config this message ran with, and the picker shows its model.\n if (messageConfig && 'QueryLLM' in messageConfig) {\n session.setChatModelName(resolveConfigModel(messageConfig))\n if (configId) session.setChatModel(configId)\n }\n }\n const handleEditStart = () => startEditing(message)\n\n const handleDeleteFailedMessage = async () => {\n if (!message.external_id) return\n try {\n await deleteMessage.mutateAsync(message.external_id)\n notify('Failed message deleted', 'success')\n } catch {\n notify('Failed to delete message', 'error')\n }\n }\n\n // Toggle handler removed - citations always show when available\n\n const settledForHeader = !isGenerating || isFailed\n const statusLabel = isFailed\n ? 'Response failed'\n : isStopped\n ? 'Stopped'\n : finalElapsedSeconds >= 0.05\n ? `Answered in ${finalElapsedSeconds.toFixed(1)}s`\n : 'Complete'\n const timeLabel = formatFriendlyDate(message.created_at || '')\n const messageId = message.external_id\n // A meeting thread's transcript lines: runs of one speaker, and each speaker's newest line.\n const assistant = useAssistantCopy()\n const transcriptRuns = useTranscriptRuns()\n const messageRole = isUser ? 'user' : 'assistant'\n\n const menuItems: MessageActionMenuItem[] = [\n ...(isUser\n ? [\n ...(!isTopLevel\n ? [\n {\n id: 'edit',\n label: 'Edit message',\n icon: <Edit3 size={14} />,\n onSelect: handleEditStart,\n testId: `edit-message-button-${messageId}`,\n },\n ]\n : []),\n {\n id: 'copy',\n label: 'Copy message',\n icon: <Copy size={14} />,\n onSelect: handleCopy,\n testId: `copy-message-button-${messageId}`,\n },\n ]\n : []),\n ...(isDeveloper\n ? [\n {\n id: 'details',\n label: 'View details',\n onSelect: () => setShowDetailsModal(true),\n testId: `message-details-button-${messageId}`,\n },\n ]\n : []),\n {\n id: 'copy-link',\n label: 'Copy link',\n icon: <Link size={14} className=\"mr-2\" />,\n onSelect: handleCopyLink,\n testId: `copy-link-button-${messageId}`,\n },\n ...(message.conversation_ext_id && selectedWorkspaceId && openShare\n ? [\n {\n id: 'share',\n label: 'Share via email',\n icon: <Share2 size={14} className=\"mr-2\" />,\n onSelect: () =>\n openShare({\n resourceType: 'conversation',\n resourceExtId: message.conversation_ext_id!,\n workspaceExtId: selectedWorkspaceId,\n isPrivate: !isShared,\n }),\n testId: `share-conversation-button-${messageId}`,\n },\n ]\n : []),\n ...(isFailed\n ? [\n {\n id: 'delete-failed',\n label: 'Delete failed message',\n icon: <Trash2 size={14} className=\"mr-2\" />,\n onSelect: handleDeleteFailedMessage,\n tone: 'danger' as const,\n testId: `delete-message-button-${messageId}`,\n },\n ]\n : []),\n ]\n\n const actions = (\n <>\n {branchControl}\n {isUser ? (\n <MessageActionMenu\n items={menuItems}\n heading={\n <>\n <div>\n {messageAuthorUser\n ? `${messageAuthorUser.given_name} ${messageAuthorUser.family_name ?? ''}`.trim()\n : 'Participant'}\n </div>\n <div className=\"text-xs text-muted-foreground\">{timeLabel}</div>\n </>\n }\n testId={`message-actions-menu-${messageId}`}\n />\n ) : (\n <>\n <MessageActionButton\n onClick={(e) => {\n e.stopPropagation()\n handleCreateFact()\n }}\n disabled={createFact.isPending || !canCreateFact}\n isDone={factSaved}\n title={factSaved ? 'Fact created' : 'Create a fact from this message'}\n aria-label=\"Create a fact from this message\"\n data-testid={`create-fact-button-${messageId}`}\n >\n {factSaved ? <Check size={16} /> : <Milestone size={16} />}\n </MessageActionButton>\n <MessageActionButton\n onClick={(e) => {\n e.stopPropagation()\n handleCopy()\n }}\n isDone={isCopied}\n title={isCopied ? 'Copied!' : 'Copy message with formatting'}\n data-testid={`copy-message-button-${messageId}`}\n >\n {isCopied ? <Check size={16} /> : <Copy size={16} />}\n </MessageActionButton>\n <MessageActionMenu\n items={menuItems}\n heading={\n <>\n <div>{modelDisplayName || assistant.name}</div>\n <div className=\"text-xs text-muted-foreground\">\n {timeLabel} \u00B7 {statusLabel}\n </div>\n </>\n }\n testId={`message-actions-menu-${messageId}`}\n />\n </>\n )}\n </>\n )\n\n // A stopped answer with no text and no steps has nothing for the footer to carry: its avatar\n // would float alone under the stopped note. Keep the footer when steps exist (Show steps).\n const isBareStopped = isEmptyStopped && visibleStepCount === 0\n\n const footer = settledForHeader && !isBareStopped && (\n <MessageFooter\n role={messageRole}\n align={isOtherPerson ? 'start' : 'end'}\n leading={\n isUser ? (\n // Someone else's author is the pill above their run; only mine is marked here.\n !isOtherPerson && messageAuthorUser && <DocumentUser user={messageAuthorUser} />\n ) : (\n <span\n className=\"inline-flex rounded-full p-1\"\n style={{\n backgroundColor: `color-mix(in srgb, ${assistantTint} 8%, transparent)`,\n color: assistantTint,\n }}\n // The model that wrote the answer: an icon whose tooltip names it.\n data-testid={`message-model-${messageId}`}\n >\n <AssistantEntity\n name={modelDisplayName}\n modelName={modelName}\n tag={modelTag}\n size={20}\n variant=\"icon\"\n />\n </span>\n )\n }\n actions={actions}\n steps={\n !isUser\n ? {\n count: visibleStepCount,\n open: isStepsExpanded,\n onOpenChange: setIsStepsExpanded,\n panel: message.agentSteps ? (\n <AgentSteps\n steps={message.agentSteps}\n isStreaming={false}\n totalElapsedTime={message.agentStepsTotalElapsed ?? undefined}\n className=\"border-b-0\"\n contextUsage={message.finalContextUsage}\n />\n ) : null,\n }\n : undefined\n }\n />\n )\n\n const stoppedNote = isStopped && !isGenerating && (\n <p\n className=\"mt-2 flex flex-wrap items-center gap-2 text-sm text-muted-foreground\"\n data-testid={`message-stopped-${messageId}`}\n >\n <span>\n {isEmptyStopped\n ? 'You stopped this answer before it wrote anything.'\n : 'You stopped this answer.'}\n </span>\n {stoppedQuestion && (\n <button\n type=\"button\"\n onClick={() => askStoppedQuestionAgain(stoppedQuestion)}\n className=\"inline-flex items-center gap-1 underline-offset-2 hover:text-foreground hover:underline\"\n data-testid={`retry-stopped-answer-button-${messageId}`}\n >\n <RotateCcw size={12} aria-hidden=\"true\" />\n Ask again\n </button>\n )}\n </p>\n )\n\n // The server's instruction that starts a workflow step reads as that step, not as raw text.\n const workflowStep = isUser ? workflowStepOf(message.tools ?? message.meta?.tools) : undefined\n if (workflowStep)\n return (\n <WorkflowStepMessage\n messageId={messageId}\n conversationId={message.conversation_ext_id}\n step={workflowStep}\n content={message.content ?? ''}\n />\n )\n\n // A call's transcript line in its meeting thread: a compact attributed line, not a comment.\n const transcriptSegment = isUser\n ? transcriptSegmentOf(message.tools ?? message.meta?.tools)\n : undefined\n if (transcriptSegment) {\n const speaker =\n transcriptSegment.speaker_ext_id === currentUser?.external_id\n ? currentUser\n : workspaceUsers.find((wu) => wu.user.external_id === transcriptSegment.speaker_ext_id)\n ?.user\n const speakerName = speaker ? getUserDisplayName(speaker) : null\n const isMe = transcriptSegment.speaker_ext_id === currentUser?.external_id\n return (\n <TranscriptEntry\n speakerId={transcriptSegment.speaker_ext_id}\n speakerName={isMe ? 'Me' : speakerName || 'Former member'}\n text={stripSpeakerPrefix(message.content ?? '', speakerName)}\n at={transcriptSegment.started_at ?? message.created_at}\n continued={!!messageId && transcriptRuns.continued.has(messageId)}\n />\n )\n }\n\n return (\n <ErrorBoundary testId=\"message-error-boundary\">\n <MessageRoot\n role={messageRole}\n messageId={messageId}\n tone={isFailed ? 'error' : subagentTaskRecord ? 'subagent' : 'default'}\n {...rest}\n >\n <MessageContent\n role={messageRole}\n messageId={messageId}\n align={isOtherPerson ? 'start' : 'end'}\n >\n {startsAuthorRun && messageAuthorUser && (\n <MessageAuthor>\n <DocumentUser user={messageAuthorUser} variant=\"pill\" />\n </MessageAuthor>\n )}\n <MessageBubble\n ref={messageRef}\n role={messageRole}\n messageId={messageId}\n isEditing={isEditing}\n // Other people's messages share ONE surface (the chats' peer bubble: card + hairline),\n // whoever wrote them: a per-person tint at 4% read as beige for one hue and as no\n // bubble at all for another. My own keep their tint; the assistant its own.\n participantTint={\n isFailed || isEmptyStopped || isOtherPerson\n ? undefined\n : isUser\n ? participantTint\n : assistantTint\n }\n className={isOtherPerson ? 'border border-border bg-card' : undefined}\n >\n {!isUser && isGenerating && (\n <MessageByline\n messageId={messageId}\n identity={\n // Stays the ARBI identity while streaming: the model name arrives\n // with the first step that reports one and would swap the author\n // mid-answer. The model is shown in the footer once settled.\n <AssistantEntity size={16} />\n }\n timeLabel={timeLabel}\n isSettled={settledForHeader}\n isFailed={isFailed}\n statusLabel={statusLabel}\n />\n )}\n {/* Marks this as ARBI's own instruction to a delegate, not something the human\n typed (see `subagentTaskRecord`). */}\n {subagentTaskRecord && <MessageSubagentBadge messageId={messageId} />}\n {/* While the turn runs this holds EVERYTHING the model has said. Only SUPERSEDED\n prose dims (a real opacity, not a colour token); the live segment is solid so\n the answer's opacity never changes and nothing un-fades at the end. The single\n commit at `response.completed` swaps in the server's answer and its citations. */}\n <MessageBody messageId={messageId}>\n {settledNarration ? (\n <MessageNarration messageId={messageId}>\n <ConnectedMarkdown isStreaming={false}>{settledNarration}</ConnectedMarkdown>\n </MessageNarration>\n ) : null}\n {liveContent ? (\n role === 'assistant' ? (\n <ConnectedCitationRenderer\n content={liveContent}\n citations={activeCitations || undefined}\n citationData={citationData}\n messageId={message.external_id || 'unknown'}\n isStreaming={isGenerating}\n />\n ) : (\n <ConnectedMarkdown isStreaming={isGenerating}>\n {/* ``/pa `` is internal routing: show the user's actual text. Stored\n @mentions become chips. */}\n {linkMentions(\n isUser && liveContent.startsWith('/pa ') ? liveContent.slice(4) : liveContent,\n message.mentions\n )}\n </ConnectedMarkdown>\n )\n ) : null}\n {showWorkingIndicator && (\n // One line of running text, not a flex row: in a narrow column (the viewer docked\n // beside the chat) flex items each shrank and wrapped on their own, as columns.\n <div>\n <p\n className=\"text-muted-foreground italic\"\n data-testid={`message-thinking-${messageId}`}\n >\n <span className=\"mr-2 inline-block h-2 w-2 animate-pulse rounded-full bg-current align-middle\" />\n Working on the answer\u2026\n {workingStepLabel && (\n <>\n {' '}\n <span\n className=\"not-italic\"\n data-testid={`message-thinking-step-${messageId}`}\n >\n \u00B7 {workingStepLabel}\n </span>\n </>\n )}\n {/* Total wait stays visible as individual steps change in the control bar.\n Only a turn this client is streaming has a clock to show. */}\n {isGenerating && (\n <>\n {' '}\n <span\n className=\"whitespace-nowrap not-italic\"\n data-testid={`message-thinking-elapsed-${messageId}`}\n >\n \u00B7{' '}\n <MessageLiveSeconds\n conversationId={message.conversation_ext_id}\n messageId={messageId}\n isUser={false}\n isGenerating={isGenerating}\n suffix=\"s elapsed\"\n />\n </span>\n </>\n )}\n </p>\n {isGenerating && (\n <p\n className=\"text-sm text-muted-foreground\"\n data-testid={`message-wait-help-${messageId}`}\n >\n You can stop this answer or choose Ask for status from the menu beside Stop.\n </p>\n )}\n </div>\n )}\n {isQueuedAnswer && !responseContent.trim() && (\n <p\n className=\"flex items-center gap-2 text-muted-foreground\"\n data-testid={`message-queued-${messageId}`}\n >\n <Clock className=\"size-3.5 shrink-0\" aria-hidden />\n Queued\n </p>\n )}\n {isAwaitingAnswer && (\n <p\n className=\"font-medium text-foreground\"\n data-testid={`message-awaiting-answer-${messageId}`}\n >\n Waiting for your answer below\n </p>\n )}\n {showEmptyAnswer && (\n <p\n className=\"text-muted-foreground italic\"\n data-testid={`message-empty-answer-${messageId}`}\n >\n ARBI finished without an answer. Ask again or request changes to retry.\n </p>\n )}\n </MessageBody>\n {/* A follow-up sent mid-answer waits its turn. The bubble stays solid (a faded\n bubble read as lost), so the state is said in words. */}\n {isQueued && (\n <p\n className=\"mt-1 flex items-center gap-1.5 text-xs text-muted-foreground\"\n data-testid={`message-queued-${messageId}`}\n >\n <Clock className=\"size-3 shrink-0\" aria-hidden />\n Queued, ARBI will answer after the current reply\n </p>\n )}\n\n {/* Inline drafted-document affordance */}\n {!isUser && linkedArtifact && (\n <MessageArtifactCard artifact={linkedArtifact} onOpen={handleOpenArtifact} />\n )}\n\n {/* Sub-agent thread links sit OUTSIDE the settled-only footer: a delegated thread\n must be openable whether this turn is streaming or long done. */}\n {!isUser && subagentLinks}\n </MessageBubble>\n {footer}\n {/* Below the footer, not in the bubble, for every stopped answer: the steps popover\n opens upward over the bubble and would hide the note while the trace is open. */}\n {stoppedNote}\n </MessageContent>\n\n <MessageDetailsModal\n open={showDetailsModal}\n onOpenChange={setShowDetailsModal}\n messageExtId={message.external_id || null}\n workspace={\n currentWorkspace\n ? {\n name: currentWorkspace.name,\n icon: workspaceIcon(16),\n }\n : null\n }\n />\n </MessageRoot>\n </ErrorBoundary>\n )\n}\n\n/**\n * Custom comparison for React.memo to prevent unnecessary re-renders during streaming.\n *\n * Most fields are read directly off `prevProps.message` / `nextProps.message`\n * \u2014 we deliberately do NOT peek into `messageHistory[index + 1]` for\n * assistant messages, because during streaming every message's\n * `messageHistory` reference changes on every rAF flush and a neighbor-index\n * read would cascade re-renders across the whole list.\n *\n * Exception: a USER message's model-switch indicator is derived from the\n * NEXT message's `config_ext_id` (the assistant response \u2014 see the\n * `configId` useMemo at line ~106). For user messages we must re-render\n * when that specific neighbor's config changes, or the indicator stays\n * stale after an assistant completes. Assistant messages still only look\n * at their own config_ext_id, so the cascade stays contained.\n */\nfunction areMessagesEqual(\n prevProps: ConnectedMessageProps,\n nextProps: ConnectedMessageProps\n): boolean {\n if (prevProps.participantTint !== nextProps.participantTint) return false\n // Always re-render if the message content or loading state changed\n if (prevProps.message.content !== nextProps.message.content) return false\n if (prevProps.message.isLoading !== nextProps.message.isLoading) return false\n if (prevProps.message.status !== nextProps.message.status) return false\n if (prevProps.message.external_id !== nextProps.message.external_id) return false\n if (prevProps.message.created_at !== nextProps.message.created_at) return false\n if (prevProps.message.config_ext_id !== nextProps.message.config_ext_id) return false\n if (prevProps.message.mentions !== nextProps.message.mentions) return false\n\n // User messages derive their model indicator from the next (assistant)\n // message's config \u2014 catch changes there so the indicator refreshes when\n // the assistant response arrives / switches model.\n if (prevProps.message.role === 'user') {\n const prevNext = prevProps.messageHistory?.[prevProps.index + 1]\n const nextNext = nextProps.messageHistory?.[nextProps.index + 1]\n if (prevNext?.config_ext_id !== nextNext?.config_ext_id) return false\n }\n\n // Re-render if message metadata changed (tools contain citations)\n if (prevProps.message.tools !== nextProps.message.tools) return false\n if (prevProps.message.meta !== nextProps.message.meta) return false\n\n // Re-render if agent steps or pending user input changed\n if (prevProps.message.agentSteps !== nextProps.message.agentSteps) return false\n if (prevProps.message.pendingUserInput !== nextProps.message.pendingUserInput) return false\n\n // Re-render if structural props changed\n if (prevProps.index !== nextProps.index) return false\n\n // branchControl is React node - compare by reference (will be same if parent doesn't re-render)\n if (prevProps.branchControl !== nextProps.branchControl) return false\n if (prevProps.subagentLinks !== nextProps.subagentLinks) return false\n\n return true\n}\n\nexport const ConnectedMessage = React.memo(MessageComponent, areMessagesEqual)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["citationData", "err"]
|
|
7
7
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The "Create a file" menu: Doc, Voice, Photo or
|
|
2
|
+
* The "Create a file" menu: Doc, Voice, Photo, Video or Presentation. A plain menu of one-click
|
|
3
|
+
* actions
|
|
3
4
|
* (`ActionMenuDialog`): the pick starts a draft of that kind in the session
|
|
4
5
|
* (`startDraftDocument`, which shows it in the viewer) and lands on Files, where the user sees it.
|
|
5
6
|
* The viewer's draft-kind dropdown still lets them change their mind.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
|
-
import { Camera, FilePlus2, FileText, Mic, Video } from "lucide-react";
|
|
3
|
+
import { Camera, FilePlus2, FileText, Mic, Presentation, Video } from "lucide-react";
|
|
4
4
|
import { useArbiSessionStore } from "@arbidocs/react";
|
|
5
5
|
import { ActionMenuDialog } from "../../home/ActionMenuDialog.js";
|
|
6
6
|
const ITEMS = [
|
|
@@ -17,7 +17,13 @@ const ITEMS = [
|
|
|
17
17
|
description: "Take a picture",
|
|
18
18
|
icon: /* @__PURE__ */ jsx(Camera, { className: "size-7" })
|
|
19
19
|
},
|
|
20
|
-
{ id: "video", label: "Video", description: "Record video", icon: /* @__PURE__ */ jsx(Video, { className: "size-7" }) }
|
|
20
|
+
{ id: "video", label: "Video", description: "Record video", icon: /* @__PURE__ */ jsx(Video, { className: "size-7" }) },
|
|
21
|
+
{
|
|
22
|
+
id: "presentation",
|
|
23
|
+
label: "Presentation",
|
|
24
|
+
description: "Show parts of documents",
|
|
25
|
+
icon: /* @__PURE__ */ jsx(Presentation, { className: "size-7" })
|
|
26
|
+
}
|
|
21
27
|
];
|
|
22
28
|
function ConnectedNewFileMenu({ open, onOpenChange }) {
|
|
23
29
|
const session = useArbiSessionStore();
|
|
@@ -33,7 +39,7 @@ function ConnectedNewFileMenu({ open, onOpenChange }) {
|
|
|
33
39
|
onOpenChange,
|
|
34
40
|
icon: /* @__PURE__ */ jsx(FilePlus2, { className: "size-5" }),
|
|
35
41
|
title: "Create a file",
|
|
36
|
-
description: "Pick what to start \u2014 write a doc,
|
|
42
|
+
description: "Pick what to start \u2014 write a doc, record a voice note, photo or video, or build a presentation.",
|
|
37
43
|
items: ITEMS,
|
|
38
44
|
onPick: pick,
|
|
39
45
|
testId: "new-file-menu",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/connection/files/ConnectedNewFileMenu.tsx"],
|
|
4
|
-
"sourcesContent": ["/**\n * The \"Create a file\" menu: Doc, Voice, Photo or
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["/**\n * The \"Create a file\" menu: Doc, Voice, Photo, Video or Presentation. A plain menu of one-click\n * actions\n * (`ActionMenuDialog`): the pick starts a draft of that kind in the session\n * (`startDraftDocument`, which shows it in the viewer) and lands on Files, where the user sees it.\n * The viewer's draft-kind dropdown still lets them change their mind.\n */\n\nimport { Camera, FilePlus2, FileText, Mic, Presentation, Video } from 'lucide-react'\nimport { useArbiSessionStore, type ArbiDraftKind } from '@arbidocs/react'\nimport { ActionMenuDialog, type ActionMenuItem } from '../../home/ActionMenuDialog'\n\nconst ITEMS: ActionMenuItem[] = [\n {\n id: 'text',\n label: 'Doc',\n description: 'Write or paste text',\n icon: <FileText className=\"size-7\" />,\n },\n { id: 'audio', label: 'Voice', description: 'Record audio', icon: <Mic className=\"size-7\" /> },\n {\n id: 'photo',\n label: 'Photo',\n description: 'Take a picture',\n icon: <Camera className=\"size-7\" />,\n },\n { id: 'video', label: 'Video', description: 'Record video', icon: <Video className=\"size-7\" /> },\n {\n id: 'presentation',\n label: 'Presentation',\n description: 'Show parts of documents',\n icon: <Presentation className=\"size-7\" />,\n },\n]\n\nexport interface ConnectedNewFileMenuProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n}\n\nexport function ConnectedNewFileMenu({ open, onOpenChange }: ConnectedNewFileMenuProps) {\n const session = useArbiSessionStore()\n const pick = (id: string) => {\n session.startDraftDocument(id as ArbiDraftKind)\n onOpenChange(false)\n session.setPage('documents')\n }\n return (\n <ActionMenuDialog\n open={open}\n onOpenChange={onOpenChange}\n icon={<FilePlus2 className=\"size-5\" />}\n title=\"Create a file\"\n description=\"Pick what to start \u2014 write a doc, record a voice note, photo or video, or build a presentation.\"\n items={ITEMS}\n onPick={pick}\n testId=\"new-file-menu\"\n itemTestId=\"new-file-item\"\n />\n )\n}\n"],
|
|
5
|
+
"mappings": ";AAiBU;AATV,SAAS,QAAQ,WAAW,UAAU,KAAK,cAAc,aAAa;AACtE,SAAS,2BAA+C;AACxD,SAAS,wBAA6C;AAEtD,MAAM,QAA0B;AAAA,EAC9B;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,MAAM,oBAAC,YAAS,WAAU,UAAS;AAAA,EACrC;AAAA,EACA,EAAE,IAAI,SAAS,OAAO,SAAS,aAAa,gBAAgB,MAAM,oBAAC,OAAI,WAAU,UAAS,EAAG;AAAA,EAC7F;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,MAAM,oBAAC,UAAO,WAAU,UAAS;AAAA,EACnC;AAAA,EACA,EAAE,IAAI,SAAS,OAAO,SAAS,aAAa,gBAAgB,MAAM,oBAAC,SAAM,WAAU,UAAS,EAAG;AAAA,EAC/F;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,MAAM,oBAAC,gBAAa,WAAU,UAAS;AAAA,EACzC;AACF;AAOO,SAAS,qBAAqB,EAAE,MAAM,aAAa,GAA8B;AACtF,QAAM,UAAU,oBAAoB;AACpC,QAAM,OAAO,CAAC,OAAe;AAC3B,YAAQ,mBAAmB,EAAmB;AAC9C,iBAAa,KAAK;AAClB,YAAQ,QAAQ,WAAW;AAAA,EAC7B;AACA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,MAAM,oBAAC,aAAU,WAAU,UAAS;AAAA,MACpC,OAAM;AAAA,MACN,aAAY;AAAA,MACZ,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,QAAO;AAAA,MACP,YAAW;AAAA;AAAA,EACb;AAEJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -770,7 +770,7 @@ const ConnectedFilesExplorer = forwardRef(function ConnectedFilesExplorer2({
|
|
|
770
770
|
);
|
|
771
771
|
});
|
|
772
772
|
function DragPreview({ doc, count }) {
|
|
773
|
-
const Icon = getFileTypeIcon(doc.file_name, { mime: doc.file_type });
|
|
773
|
+
const Icon = getFileTypeIcon(doc.file_name, { mime: doc.file_type, folder: doc.folder });
|
|
774
774
|
return /* @__PURE__ */ jsx(
|
|
775
775
|
ExplorerDragPreview,
|
|
776
776
|
{
|