@arbidocs/react 0.5.111 → 0.5.113
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/account/client.js +96 -0
- package/dist/account/client.js.map +7 -0
- package/dist/account/delete.js +70 -0
- package/dist/account/delete.js.map +7 -0
- package/dist/account/didit.js +34 -0
- package/dist/account/didit.js.map +7 -0
- package/dist/account/dismissed-tips.js +33 -0
- package/dist/account/dismissed-tips.js.map +7 -0
- package/dist/account/email.js +84 -0
- package/dist/account/email.js.map +7 -0
- package/dist/account/entitlements.js +47 -0
- package/dist/account/entitlements.js.map +7 -0
- package/dist/account/identity.js +270 -0
- package/dist/account/identity.js.map +7 -0
- package/dist/account/index.js +93 -0
- package/dist/account/index.js.map +7 -0
- package/dist/account/notifications.js +59 -0
- package/dist/account/notifications.js.map +7 -0
- package/dist/account/password.js +103 -0
- package/dist/account/password.js.map +7 -0
- package/dist/account/profile.js +116 -0
- package/dist/account/profile.js.map +7 -0
- package/dist/account/recovery.js +13 -0
- package/dist/account/recovery.js.map +7 -0
- package/dist/account/relevance.js +82 -0
- package/dist/account/relevance.js.map +7 -0
- package/dist/account/sessions.js +37 -0
- package/dist/account/sessions.js.map +7 -0
- package/dist/account/settings.js +39 -0
- package/dist/account/settings.js.map +7 -0
- package/dist/account/table-views.js +16 -0
- package/dist/account/table-views.js.map +7 -0
- package/dist/ai/AiAnswer.js +83 -0
- package/dist/ai/AiAnswer.js.map +7 -0
- package/dist/ai/AiMarkdown.js +40 -0
- package/dist/ai/AiMarkdown.js.map +7 -0
- package/dist/ai/ArtifactCanvas.js +193 -0
- package/dist/ai/ArtifactCanvas.js.map +7 -0
- package/dist/ai/CitationRenderer.js +413 -0
- package/dist/ai/CitationRenderer.js.map +7 -0
- package/dist/{chunk-WL2Y2T47.js → ai/MarkdownRenderer.js} +35 -101
- package/dist/ai/MarkdownRenderer.js.map +7 -0
- package/dist/ai/MessageArtifactCard.js +75 -0
- package/dist/ai/MessageArtifactCard.js.map +7 -0
- package/dist/ai/PassageCard.js +79 -0
- package/dist/ai/PassageCard.js.map +7 -0
- package/dist/ai/engine.js +110 -0
- package/dist/ai/engine.js.map +7 -0
- package/dist/ai/index.js +63 -0
- package/dist/ai/index.js.map +7 -0
- package/dist/ai/markdown-base-components.js +37 -0
- package/dist/ai/markdown-base-components.js.map +7 -0
- package/dist/ai/markdown-streaming-context.js +6 -0
- package/dist/ai/markdown-streaming-context.js.map +7 -0
- package/dist/{chunk-VSCU7K4V.js → ai/normalize-citations.js} +12 -19
- package/dist/ai/normalize-citations.js.map +7 -0
- package/dist/ai/redline.js +41 -0
- package/dist/ai/redline.js.map +7 -0
- package/dist/ai/split-markdown-blocks.js +40 -0
- package/dist/ai/split-markdown-blocks.js.map +7 -0
- package/dist/{chunk-UW2SGTI5.js → ai/stored-markdown.js} +41 -93
- package/dist/ai/stored-markdown.js.map +7 -0
- package/dist/annotations/AnnotationPageOverlay.js +807 -0
- package/dist/annotations/AnnotationPageOverlay.js.map +7 -0
- package/dist/annotations/AnnotationToolbar.js +398 -0
- package/dist/annotations/AnnotationToolbar.js.map +7 -0
- package/dist/annotations/FreezeDialog.js +170 -0
- package/dist/annotations/FreezeDialog.js.map +7 -0
- package/dist/annotations/ProductionDialog.js +354 -0
- package/dist/annotations/ProductionDialog.js.map +7 -0
- package/dist/annotations/controller.js +49 -0
- package/dist/annotations/controller.js.map +7 -0
- package/dist/annotations/freeze/browser.js +21 -0
- package/dist/annotations/freeze/browser.js.map +7 -0
- package/dist/annotations/freeze/bundle.js +201 -0
- package/dist/annotations/freeze/bundle.js.map +7 -0
- package/dist/annotations/freeze/coords.js +37 -0
- package/dist/annotations/freeze/coords.js.map +7 -0
- package/dist/annotations/freeze/freeze.js +261 -0
- package/dist/annotations/freeze/freeze.js.map +7 -0
- package/dist/annotations/freeze/hash.js +28 -0
- package/dist/annotations/freeze/hash.js.map +7 -0
- package/dist/annotations/freeze/index-page.js +78 -0
- package/dist/annotations/freeze/index-page.js.map +7 -0
- package/dist/annotations/freeze/index.js +28 -22
- package/dist/annotations/freeze/index.js.map +7 -1
- package/dist/annotations/freeze/raster.js +208 -0
- package/dist/annotations/freeze/raster.js.map +7 -0
- package/dist/annotations/freeze/stamp.js +117 -0
- package/dist/annotations/freeze/stamp.js.map +7 -0
- package/dist/annotations/freeze/types.js +14 -0
- package/dist/annotations/freeze/types.js.map +7 -0
- package/dist/annotations/freeze/vector.js +283 -0
- package/dist/annotations/freeze/vector.js.map +7 -0
- package/dist/annotations/geometry.js +81 -0
- package/dist/annotations/geometry.js.map +7 -0
- package/dist/annotations/index.js +125 -6
- package/dist/annotations/index.js.map +7 -1
- package/dist/annotations/merge.js +53 -0
- package/dist/annotations/merge.js.map +7 -0
- package/dist/{chunk-T3USOSVN.js → annotations/model.js} +23 -16
- package/dist/annotations/model.js.map +7 -0
- package/dist/annotations/overlay-geometry.js +41 -0
- package/dist/annotations/overlay-geometry.js.map +7 -0
- package/dist/annotations/redaction-log.js +33 -0
- package/dist/annotations/redaction-log.js.map +7 -0
- package/dist/annotations/selection-marks.js +122 -0
- package/dist/annotations/selection-marks.js.map +7 -0
- package/dist/annotations/state.js +140 -0
- package/dist/annotations/state.js.map +7 -0
- package/dist/annotations/store.js +49 -0
- package/dist/annotations/store.js.map +7 -0
- package/dist/annotations/useAnnotationLayer.js +306 -0
- package/dist/annotations/useAnnotationLayer.js.map +7 -0
- package/dist/annotations/useAnnotationShortcuts.js +31 -0
- package/dist/annotations/useAnnotationShortcuts.js.map +7 -0
- package/dist/annotations/useTextSelectionMarks.js +100 -0
- package/dist/annotations/useTextSelectionMarks.js.map +7 -0
- package/dist/artifacts/artifact-kind.js +19 -0
- package/dist/artifacts/artifact-kind.js.map +7 -0
- package/dist/artifacts/index.js +89 -571
- package/dist/artifacts/index.js.map +7 -1
- package/dist/{chunk-WUTL62MC.js → artifacts/normalize-markdown.js} +12 -14
- package/dist/artifacts/normalize-markdown.js.map +7 -0
- package/dist/artifacts/redline-core.js +12 -3
- package/dist/artifacts/redline-core.js.map +7 -1
- package/dist/{chunk-74N436VK.js → artifacts/redline-diff.js} +10 -9
- package/dist/artifacts/redline-diff.js.map +7 -0
- package/dist/artifacts/redline-engine.js +14 -0
- package/dist/artifacts/redline-engine.js.map +7 -0
- package/dist/artifacts/renderArtifactMarkdown.js +9 -0
- package/dist/artifacts/renderArtifactMarkdown.js.map +7 -0
- package/dist/artifacts/useArtifactEditSession.js +183 -0
- package/dist/artifacts/useArtifactEditSession.js.map +7 -0
- package/dist/artifacts/useArtifactSession.js +173 -0
- package/dist/artifacts/useArtifactSession.js.map +7 -0
- package/dist/artifacts/useArtifactSource.js +16 -0
- package/dist/artifacts/useArtifactSource.js.map +7 -0
- package/dist/artifacts/useArtifactText.js +78 -0
- package/dist/artifacts/useArtifactText.js.map +7 -0
- package/dist/artifacts/useRedline.js +65 -0
- package/dist/artifacts/useRedline.js.map +7 -0
- package/dist/artifacts/useStreamedArtifact.js +74 -0
- package/dist/artifacts/useStreamedArtifact.js.map +7 -0
- package/dist/artifacts/versions.js +68 -0
- package/dist/artifacts/versions.js.map +7 -0
- package/dist/billing.js +200 -0
- package/dist/billing.js.map +7 -0
- package/dist/boot-timeout.js +19 -0
- package/dist/boot-timeout.js.map +7 -0
- package/dist/calendar/accounts.js +213 -0
- package/dist/calendar/accounts.js.map +7 -0
- package/dist/calendar/hooks.js +409 -0
- package/dist/calendar/hooks.js.map +7 -0
- package/dist/calendar/index.js +31 -0
- package/dist/calendar/index.js.map +7 -0
- package/dist/calendar/keys.js +5 -0
- package/dist/calendar/keys.js.map +7 -0
- package/dist/calendar/offline/outbox.js +231 -0
- package/dist/calendar/offline/outbox.js.map +7 -0
- package/dist/calendar/offline/runtime.js +109 -0
- package/dist/calendar/offline/runtime.js.map +7 -0
- package/dist/calendar/offline/support.js +41 -0
- package/dist/calendar/offline/support.js.map +7 -0
- package/dist/calendar/support.js +34 -0
- package/dist/calendar/support.js.map +7 -0
- package/dist/calls/actions.js +226 -0
- package/dist/calls/actions.js.map +7 -0
- package/dist/calls/events.js +138 -0
- package/dist/calls/events.js.map +7 -0
- package/dist/calls/gate.js +19 -0
- package/dist/calls/gate.js.map +7 -0
- package/dist/calls/hooks.js +115 -0
- package/dist/calls/hooks.js.map +7 -0
- package/dist/calls/in-call-chat.js +132 -0
- package/dist/calls/in-call-chat.js.map +7 -0
- package/dist/calls/index.js +24 -0
- package/dist/calls/index.js.map +7 -0
- package/dist/calls/keys.js +17 -0
- package/dist/calls/keys.js.map +7 -0
- package/dist/calls/livekit/index.js +6 -958
- package/dist/calls/livekit/index.js.map +7 -1
- package/dist/calls/livekit/room.js +98 -0
- package/dist/calls/livekit/room.js.map +7 -0
- package/dist/calls/livekit/useCallRecorder.js +219 -0
- package/dist/calls/livekit/useCallRecorder.js.map +7 -0
- package/dist/calls/livekit/useCallTranscriber.js +309 -0
- package/dist/calls/livekit/useCallTranscriber.js.map +7 -0
- package/dist/calls/livekit/useHostMuteNotice.js +29 -0
- package/dist/calls/livekit/useHostMuteNotice.js.map +7 -0
- package/dist/calls/livekit/useInCallChat.js +161 -0
- package/dist/calls/livekit/useInCallChat.js.map +7 -0
- package/dist/calls/livekit/useWebinar.js +239 -0
- package/dist/calls/livekit/useWebinar.js.map +7 -0
- package/dist/calls/meeting-chat.js +149 -0
- package/dist/calls/meeting-chat.js.map +7 -0
- package/dist/calls/moderation.js +50 -0
- package/dist/calls/moderation.js.map +7 -0
- package/dist/calls/open-meeting-chat.js +29 -0
- package/dist/calls/open-meeting-chat.js.map +7 -0
- package/dist/calls/read-only.js +24 -0
- package/dist/calls/read-only.js.map +7 -0
- package/dist/calls/recording-media.js +218 -0
- package/dist/calls/recording-media.js.map +7 -0
- package/dist/calls/recording-playback.js +260 -0
- package/dist/calls/recording-playback.js.map +7 -0
- package/dist/calls/recording.js +268 -0
- package/dist/calls/recording.js.map +7 -0
- package/dist/calls/save-to-thread.js +80 -0
- package/dist/calls/save-to-thread.js.map +7 -0
- package/dist/calls/session.js +134 -0
- package/dist/calls/session.js.map +7 -0
- package/dist/calls/transcript-format.js +147 -0
- package/dist/calls/transcript-format.js.map +7 -0
- package/dist/calls/transcription.js +101 -0
- package/dist/calls/transcription.js.map +7 -0
- package/dist/calls/webinar.js +71 -0
- package/dist/calls/webinar.js.map +7 -0
- package/dist/charge-watch.js +71 -0
- package/dist/charge-watch.js.map +7 -0
- package/dist/chat/ChatBubble.js +146 -0
- package/dist/chat/ChatBubble.js.map +7 -0
- package/dist/chat/ConversationScope.js +30 -0
- package/dist/chat/ConversationScope.js.map +7 -0
- package/dist/chat/active-config.js +20 -0
- package/dist/chat/active-config.js.map +7 -0
- package/dist/chat/agent-chat-owner.js +25 -0
- package/dist/chat/agent-chat-owner.js.map +7 -0
- package/dist/chat/chat-artifacts.js +64 -0
- package/dist/chat/chat-artifacts.js.map +7 -0
- package/dist/chat/citations.js +32 -0
- package/dist/chat/citations.js.map +7 -0
- package/dist/chat/config-model.js +10 -0
- package/dist/chat/config-model.js.map +7 -0
- package/dist/chat/conversation-cache.js +676 -0
- package/dist/chat/conversation-cache.js.map +7 -0
- package/dist/chat/conversation-events.js +57 -0
- package/dist/chat/conversation-events.js.map +7 -0
- package/dist/chat/conversation-mentions.js +58 -0
- package/dist/chat/conversation-mentions.js.map +7 -0
- package/dist/chat/conversation-workspace.js +58 -0
- package/dist/chat/conversation-workspace.js.map +7 -0
- package/dist/chat/mentions.js +116 -0
- package/dist/chat/mentions.js.map +7 -0
- package/dist/chat/open-document.js +106 -0
- package/dist/chat/open-document.js.map +7 -0
- package/dist/chat/orphaned.js +44 -0
- package/dist/chat/orphaned.js.map +7 -0
- package/dist/chat/pendingFirstTurn.js +30 -0
- package/dist/chat/pendingFirstTurn.js.map +7 -0
- package/dist/chat/reply-target.js +12 -0
- package/dist/chat/reply-target.js.map +7 -0
- package/dist/chat/run-finished.js +28 -0
- package/dist/chat/run-finished.js.map +7 -0
- package/dist/chat/run-state.js +91 -0
- package/dist/chat/run-state.js.map +7 -0
- package/dist/chat/stream-handlers.js +419 -0
- package/dist/chat/stream-handlers.js.map +7 -0
- package/dist/chat/thread-binding.js +76 -0
- package/dist/chat/thread-binding.js.map +7 -0
- package/dist/chat/thread-document.js +53 -0
- package/dist/chat/thread-document.js.map +7 -0
- package/dist/chat/turn-control.js +79 -0
- package/dist/chat/turn-control.js.map +7 -0
- package/dist/chat/useAgentRunControl.js +36 -0
- package/dist/chat/useAgentRunControl.js.map +7 -0
- package/dist/chat/useAnswerAgentQuestion.js +19 -0
- package/dist/chat/useAnswerAgentQuestion.js.map +7 -0
- package/dist/chat/useAskAgain.js +32 -0
- package/dist/chat/useAskAgain.js.map +7 -0
- package/dist/chat/useAutoSendDraft.js +17 -0
- package/dist/chat/useAutoSendDraft.js.map +7 -0
- package/dist/chat/useBranchNavigation.js +97 -0
- package/dist/chat/useBranchNavigation.js.map +7 -0
- package/dist/chat/useConnectRunStream.js +169 -0
- package/dist/chat/useConnectRunStream.js.map +7 -0
- package/dist/chat/useConversation.js +431 -0
- package/dist/chat/useConversation.js.map +7 -0
- package/dist/chat/useConversationActions.js +662 -0
- package/dist/chat/useConversationActions.js.map +7 -0
- package/dist/chat/useConversationData.js +143 -0
- package/dist/chat/useConversationData.js.map +7 -0
- package/dist/chat/useConversationDocuments.js +41 -0
- package/dist/chat/useConversationDocuments.js.map +7 -0
- package/dist/chat/useConversationSettings.js +78 -0
- package/dist/chat/useConversationSettings.js.map +7 -0
- package/dist/chat/useConversationTurn.js +31 -0
- package/dist/chat/useConversationTurn.js.map +7 -0
- package/dist/chat/useConversationWorkspace.js +12 -0
- package/dist/chat/useConversationWorkspace.js.map +7 -0
- package/dist/chat/useDeleteMessage.js +15 -0
- package/dist/chat/useDeleteMessage.js.map +7 -0
- package/dist/chat/useDocumentAutoAdd.js +73 -0
- package/dist/chat/useDocumentAutoAdd.js.map +7 -0
- package/dist/chat/useMessageTimer.js +39 -0
- package/dist/chat/useMessageTimer.js.map +7 -0
- package/dist/chat/useThinkingContent.js +67 -0
- package/dist/chat/useThinkingContent.js.map +7 -0
- package/dist/chat/useThreadDocument.js +61 -0
- package/dist/chat/useThreadDocument.js.map +7 -0
- package/dist/chat/workflow-run-titles.js +50 -0
- package/dist/chat/workflow-run-titles.js.map +7 -0
- package/dist/config/config-hooks.js +209 -0
- package/dist/config/config-hooks.js.map +7 -0
- package/dist/connectivity.js +72 -0
- package/dist/connectivity.js.map +7 -0
- package/dist/connectors/hooks.js +263 -0
- package/dist/connectors/hooks.js.map +7 -0
- package/dist/connectors/index.js +28 -0
- package/dist/connectors/index.js.map +7 -0
- package/dist/contacts.js +100 -0
- package/dist/contacts.js.map +7 -0
- package/dist/conversation-list.js +65 -0
- package/dist/conversation-list.js.map +7 -0
- package/dist/databases.js +195 -0
- package/dist/databases.js.map +7 -0
- package/dist/datasets/aggregate.js +281 -0
- package/dist/datasets/aggregate.js.map +7 -0
- package/dist/datasets/index.js +122 -0
- package/dist/datasets/index.js.map +7 -0
- package/dist/datasets/members.js +27 -0
- package/dist/datasets/members.js.map +7 -0
- package/dist/datasets/panel.js +44 -0
- package/dist/datasets/panel.js.map +7 -0
- package/dist/datasets/registry.js +47 -0
- package/dist/datasets/registry.js.map +7 -0
- package/dist/datasets/rows-source.js +44 -0
- package/dist/datasets/rows-source.js.map +7 -0
- package/dist/datasets/sources/activity.js +83 -0
- package/dist/datasets/sources/activity.js.map +7 -0
- package/dist/datasets/sources/conversations.js +74 -0
- package/dist/datasets/sources/conversations.js.map +7 -0
- package/dist/datasets/sources/database.js +209 -0
- package/dist/datasets/sources/database.js.map +7 -0
- package/dist/datasets/sources/documents.js +93 -0
- package/dist/datasets/sources/documents.js.map +7 -0
- package/dist/datasets/sources/facts.js +56 -0
- package/dist/datasets/sources/facts.js.map +7 -0
- package/dist/datasets/sources/projects.js +117 -0
- package/dist/datasets/sources/projects.js.map +7 -0
- package/dist/datasets/sources/tags.js +67 -0
- package/dist/datasets/sources/tags.js.map +7 -0
- package/dist/datasets/sources/usage.js +268 -0
- package/dist/datasets/sources/usage.js.map +7 -0
- package/dist/datasets/sources/workflows.js +91 -0
- package/dist/datasets/sources/workflows.js.map +7 -0
- package/dist/datasets/sources/workspaces.js +67 -0
- package/dist/datasets/sources/workspaces.js.map +7 -0
- package/dist/datasets/store.js +194 -0
- package/dist/datasets/store.js.map +7 -0
- package/dist/datasets/types.js +14 -0
- package/dist/datasets/types.js.map +7 -0
- package/dist/directmessages/ConversationList.js +148 -0
- package/dist/directmessages/ConversationList.js.map +7 -0
- package/dist/directmessages/DateSeparator.js +8 -0
- package/dist/directmessages/DateSeparator.js.map +7 -0
- package/dist/directmessages/DmAvatar.js +29 -0
- package/dist/directmessages/DmAvatar.js.map +7 -0
- package/dist/directmessages/DmComposer.js +201 -0
- package/dist/directmessages/DmComposer.js.map +7 -0
- package/dist/directmessages/arrivals.js +29 -0
- package/dist/directmessages/arrivals.js.map +7 -0
- package/dist/directmessages/chat-cache.js +192 -0
- package/dist/directmessages/chat-cache.js.map +7 -0
- package/dist/directmessages/grouping.js +26 -0
- package/dist/directmessages/grouping.js.map +7 -0
- package/dist/directmessages/index.js +81 -0
- package/dist/directmessages/index.js.map +7 -0
- package/dist/directmessages/useChats.js +266 -0
- package/dist/directmessages/useChats.js.map +7 -0
- package/dist/directmessages/utils.js +23 -0
- package/dist/directmessages/utils.js.map +7 -0
- package/dist/document-tools/can-annotate.js +7 -0
- package/dist/document-tools/can-annotate.js.map +7 -0
- package/dist/document-tools/core.js +218 -12
- package/dist/document-tools/core.js.map +7 -1
- package/dist/document-tools/document-pdf.js +76 -0
- package/dist/document-tools/document-pdf.js.map +7 -0
- package/dist/document-tools/environment.js +136 -0
- package/dist/document-tools/environment.js.map +7 -0
- package/dist/document-tools/file-shares.js +112 -0
- package/dist/document-tools/file-shares.js.map +7 -0
- package/dist/document-tools/frozen-copy.js +27 -0
- package/dist/document-tools/frozen-copy.js.map +7 -0
- package/dist/document-tools/index.js +26 -148
- package/dist/document-tools/index.js.map +7 -1
- package/dist/document-tools/markup-download.js +51 -0
- package/dist/document-tools/markup-download.js.map +7 -0
- package/dist/document-tools/markup-store.js +138 -0
- package/dist/document-tools/markup-store.js.map +7 -0
- package/dist/document-tools/markup-transfer.js +88 -0
- package/dist/document-tools/markup-transfer.js.map +7 -0
- package/dist/document-tools/production.js +147 -0
- package/dist/document-tools/production.js.map +7 -0
- package/dist/document-tools/saved-signature.js +90 -0
- package/dist/document-tools/saved-signature.js.map +7 -0
- package/dist/document-tools/signature-requests.js +310 -0
- package/dist/document-tools/signature-requests.js.map +7 -0
- package/dist/document-tools/signing.js +127 -0
- package/dist/document-tools/signing.js.map +7 -0
- package/dist/document-tools/useDocumentBytes.js +38 -0
- package/dist/document-tools/useDocumentBytes.js.map +7 -0
- package/dist/document-tools/useDocumentMarkup.js +154 -0
- package/dist/document-tools/useDocumentMarkup.js.map +7 -0
- package/dist/document-tools/useIsOnline.js +13 -0
- package/dist/document-tools/useIsOnline.js.map +7 -0
- package/dist/document-tools/verification.js +60 -0
- package/dist/document-tools/verification.js.map +7 -0
- package/dist/documents/DocumentReview.js +220 -0
- package/dist/documents/DocumentReview.js.map +7 -0
- package/dist/documents/DraftTitleControls.js +41 -0
- package/dist/documents/DraftTitleControls.js.map +7 -0
- package/dist/documents/InlineMicButton.js +90 -0
- package/dist/documents/InlineMicButton.js.map +7 -0
- package/dist/documents/MicRecordingOverlay.js +29 -0
- package/dist/documents/MicRecordingOverlay.js.map +7 -0
- package/dist/documents/MicWaveformIndicator.js +68 -0
- package/dist/documents/MicWaveformIndicator.js.map +7 -0
- package/dist/documents/PhotoCapture.js +120 -0
- package/dist/documents/PhotoCapture.js.map +7 -0
- package/dist/documents/VideoCapture.js +129 -0
- package/dist/documents/VideoCapture.js.map +7 -0
- package/dist/documents/VoiceNoteRecorder.js +166 -0
- package/dist/documents/VoiceNoteRecorder.js.map +7 -0
- package/dist/documents/audio-segmenter.js +63 -0
- package/dist/documents/audio-segmenter.js.map +7 -0
- package/dist/documents/capture-frame.js +21 -0
- package/dist/documents/capture-frame.js.map +7 -0
- package/dist/documents/chunked-recorder.js +190 -0
- package/dist/documents/chunked-recorder.js.map +7 -0
- package/dist/documents/document-download.js +53 -0
- package/dist/documents/document-download.js.map +7 -0
- package/dist/documents/document-fields.js +109 -0
- package/dist/documents/document-fields.js.map +7 -0
- package/dist/documents/documents-cache.js +110 -0
- package/dist/documents/documents-cache.js.map +7 -0
- package/dist/documents/documents-data.js +128 -0
- package/dist/documents/documents-data.js.map +7 -0
- package/dist/documents/documents-loader.js +113 -0
- package/dist/documents/documents-loader.js.map +7 -0
- package/dist/documents/documents-writes.js +448 -0
- package/dist/documents/documents-writes.js.map +7 -0
- package/dist/documents/format-elapsed.js +10 -0
- package/dist/documents/format-elapsed.js.map +7 -0
- package/dist/documents/has-video-track.js +26 -0
- package/dist/documents/has-video-track.js.map +7 -0
- package/dist/documents/index.js +266 -0
- package/dist/documents/index.js.map +7 -0
- package/dist/documents/media-error.js +18 -0
- package/dist/documents/media-error.js.map +7 -0
- package/dist/documents/offline-documents.js +160 -0
- package/dist/documents/offline-documents.js.map +7 -0
- package/dist/documents/pending-sync.js +210 -0
- package/dist/documents/pending-sync.js.map +7 -0
- package/dist/documents/processing-live.js +122 -0
- package/dist/documents/processing-live.js.map +7 -0
- package/dist/documents/processing-order.js +59 -0
- package/dist/documents/processing-order.js.map +7 -0
- package/dist/documents/processing-settle.js +21 -0
- package/dist/documents/processing-settle.js.map +7 -0
- package/dist/documents/related-documents.js +133 -0
- package/dist/documents/related-documents.js.map +7 -0
- package/dist/documents/support.js +29 -0
- package/dist/documents/support.js.map +7 -0
- package/dist/documents/upload-files.js +169 -0
- package/dist/documents/upload-files.js.map +7 -0
- package/dist/documents/useAudioRecorder.js +315 -0
- package/dist/documents/useAudioRecorder.js.map +7 -0
- package/dist/documents/useCameraStream.js +35 -0
- package/dist/documents/useCameraStream.js.map +7 -0
- package/dist/documents/useDocumentThumbnails.js +71 -0
- package/dist/documents/useDocumentThumbnails.js.map +7 -0
- package/dist/documents/useDownloadDocuments.js +90 -0
- package/dist/documents/useDownloadDocuments.js.map +7 -0
- package/dist/documents/usePassageQuotes.js +37 -0
- package/dist/documents/usePassageQuotes.js.map +7 -0
- package/dist/documents/useUploadFiles.js +165 -0
- package/dist/documents/useUploadFiles.js.map +7 -0
- package/dist/documents/useUploadFromUrls.js +63 -0
- package/dist/documents/useUploadFromUrls.js.map +7 -0
- package/dist/documents/useVideoRecorder.js +62 -0
- package/dist/documents/useVideoRecorder.js.map +7 -0
- package/dist/entities/AgentMarkers.js +61 -0
- package/dist/entities/AgentMarkers.js.map +7 -0
- package/dist/entities/DocumentEntity.js +125 -0
- package/dist/entities/DocumentEntity.js.map +7 -0
- package/dist/entities/EntityPill.js +250 -0
- package/dist/entities/EntityPill.js.map +7 -0
- package/dist/entities/ProjectEntity.js +61 -0
- package/dist/entities/ProjectEntity.js.map +7 -0
- package/dist/entities/ShieldIcon.js +49 -0
- package/dist/entities/ShieldIcon.js.map +7 -0
- package/dist/entities/TagEntity.js +79 -0
- package/dist/entities/TagEntity.js.map +7 -0
- package/dist/entities/ThreadVisibilityIcon.js +15 -0
- package/dist/entities/ThreadVisibilityIcon.js.map +7 -0
- package/dist/entities/UserEntity.js +211 -0
- package/dist/entities/UserEntity.js.map +7 -0
- package/dist/entities/VerifiedBadge.js +19 -0
- package/dist/entities/VerifiedBadge.js.map +7 -0
- package/dist/entities/agent-avatar-colors.js +26 -0
- package/dist/entities/agent-avatar-colors.js.map +7 -0
- package/dist/entities/colors.js +64 -0
- package/dist/entities/colors.js.map +7 -0
- package/dist/entities/file-type.js +151 -0
- package/dist/entities/file-type.js.map +7 -0
- package/dist/entities/index.js +100 -0
- package/dist/entities/index.js.map +7 -0
- package/dist/entities/media-type.js +61 -0
- package/dist/entities/media-type.js.map +7 -0
- package/dist/entities/registry.js +385 -0
- package/dist/entities/registry.js.map +7 -0
- package/dist/entities/status.js +43 -0
- package/dist/entities/status.js.map +7 -0
- package/dist/entities/tag-kinds.js +23 -0
- package/dist/entities/tag-kinds.js.map +7 -0
- package/dist/entities/tag-types.js +44 -0
- package/dist/entities/tag-types.js.map +7 -0
- package/dist/entities/vocabulary.js +12 -0
- package/dist/entities/vocabulary.js.map +7 -0
- package/dist/entity-extraction.js +25 -0
- package/dist/entity-extraction.js.map +7 -0
- package/dist/facts-search.js +57 -0
- package/dist/facts-search.js.map +7 -0
- package/dist/facts.js +69 -0
- package/dist/facts.js.map +7 -0
- package/dist/hooks.js +320 -0
- package/dist/hooks.js.map +7 -0
- package/dist/host/ArbiHost.js +24 -0
- package/dist/host/ArbiHost.js.map +7 -0
- package/dist/host/assistant-copy.js +54 -0
- package/dist/host/assistant-copy.js.map +7 -0
- package/dist/host/config.js +9 -0
- package/dist/host/config.js.map +7 -0
- package/dist/host/context.js +10 -0
- package/dist/host/context.js.map +7 -0
- package/dist/host/features.js +144 -0
- package/dist/host/features.js.map +7 -0
- package/dist/host/index.js +12 -0
- package/dist/host/index.js.map +7 -0
- package/dist/{chunk-DPYBZDJB.js → host/merge.js} +7 -7
- package/dist/host/merge.js.map +7 -0
- package/dist/house-template.js +40 -0
- package/dist/house-template.js.map +7 -0
- package/dist/icons/AppleIcon.js +25 -0
- package/dist/icons/AppleIcon.js.map +7 -0
- package/dist/icons/ArbiBotHeadIcon.js +46 -0
- package/dist/icons/ArbiBotHeadIcon.js.map +7 -0
- package/dist/icons/ArbiIcon.js +24 -0
- package/dist/icons/ArbiIcon.js.map +7 -0
- package/dist/icons/AudIcon.js +56 -0
- package/dist/icons/AudIcon.js.map +7 -0
- package/dist/icons/ClaudeIcon.js +28 -0
- package/dist/icons/ClaudeIcon.js.map +7 -0
- package/dist/icons/DocIcon.js +56 -0
- package/dist/icons/DocIcon.js.map +7 -0
- package/dist/icons/EmlIcon.js +57 -0
- package/dist/icons/EmlIcon.js.map +7 -0
- package/dist/icons/FireworksIcon.js +47 -0
- package/dist/icons/FireworksIcon.js.map +7 -0
- package/dist/icons/GeminiIcon.js +37 -0
- package/dist/icons/GeminiIcon.js.map +7 -0
- package/dist/icons/GitHubIcon.js +32 -0
- package/dist/icons/GitHubIcon.js.map +7 -0
- package/dist/icons/GoogleIcon.js +53 -0
- package/dist/icons/GoogleIcon.js.map +7 -0
- package/dist/icons/HtmlIcon.js +56 -0
- package/dist/icons/HtmlIcon.js.map +7 -0
- package/dist/icons/ImgIcon.js +56 -0
- package/dist/icons/ImgIcon.js.map +7 -0
- package/dist/icons/LinkedInIcon.js +25 -0
- package/dist/icons/LinkedInIcon.js.map +7 -0
- package/dist/icons/OpenAIIcon.js +28 -0
- package/dist/icons/OpenAIIcon.js.map +7 -0
- package/dist/icons/PdfIcon.js +56 -0
- package/dist/icons/PdfIcon.js.map +7 -0
- package/dist/icons/ProviderIcon.js +42 -0
- package/dist/icons/ProviderIcon.js.map +7 -0
- package/dist/icons/TxtIcon.js +56 -0
- package/dist/icons/TxtIcon.js.map +7 -0
- package/dist/icons/VidIcon.js +56 -0
- package/dist/icons/VidIcon.js.map +7 -0
- package/dist/icons/XlsIcon.js +56 -0
- package/dist/icons/XlsIcon.js.map +7 -0
- package/dist/icons/arbi-mark.js +5 -0
- package/dist/icons/arbi-mark.js.map +7 -0
- package/dist/icons/colors.js +31 -0
- package/dist/icons/colors.js.map +7 -0
- package/dist/icons/file-type.js +105 -0
- package/dist/icons/file-type.js.map +7 -0
- package/dist/icons/index.js +55 -0
- package/dist/icons/index.js.map +7 -0
- package/dist/imagecrop/ImageCropModal.js +56 -0
- package/dist/imagecrop/ImageCropModal.js.map +7 -0
- package/dist/imagecrop/ImageCropper.js +100 -0
- package/dist/imagecrop/ImageCropper.js.map +7 -0
- package/dist/imagecrop/cropImage.js +43 -0
- package/dist/imagecrop/cropImage.js.map +7 -0
- package/dist/imagecrop/index.js +13 -0
- package/dist/imagecrop/index.js.map +7 -0
- package/dist/index.js +702 -17116
- package/dist/index.js.map +7 -1
- package/dist/{chunk-SSXFVWCT.js → lazy-chunk.js} +8 -8
- package/dist/lazy-chunk.js.map +7 -0
- package/dist/lib/collision-padding.js +13 -0
- package/dist/lib/collision-padding.js.map +7 -0
- package/dist/lib/format-friendly-date.js +55 -0
- package/dist/lib/format-friendly-date.js.map +7 -0
- package/dist/lib/format-relative-time.js +52 -0
- package/dist/lib/format-relative-time.js.map +7 -0
- package/dist/lib/markdown-to-text.js +35 -0
- package/dist/lib/markdown-to-text.js.map +7 -0
- package/dist/lib/toast-interaction.js +9 -0
- package/dist/lib/toast-interaction.js.map +7 -0
- package/dist/lib/utils.js +9 -0
- package/dist/lib/utils.js.map +7 -0
- package/dist/mail/client.js +103 -0
- package/dist/mail/client.js.map +7 -0
- package/dist/mail/document-attachment.js +38 -0
- package/dist/mail/document-attachment.js.map +7 -0
- package/dist/mail/filing.js +132 -0
- package/dist/mail/filing.js.map +7 -0
- package/dist/mail/hooks.js +393 -0
- package/dist/mail/hooks.js.map +7 -0
- package/dist/mail/index.js +120 -0
- package/dist/mail/index.js.map +7 -0
- package/dist/mail/offline/changes.js +258 -0
- package/dist/mail/offline/changes.js.map +7 -0
- package/dist/mail/offline/confirm-sign-out.js +37 -0
- package/dist/mail/offline/confirm-sign-out.js.map +7 -0
- package/dist/mail/offline/crypto.js +26 -0
- package/dist/mail/offline/crypto.js.map +7 -0
- package/dist/mail/offline/drafts.js +69 -0
- package/dist/mail/offline/drafts.js.map +7 -0
- package/dist/mail/offline/hooks.js +104 -0
- package/dist/mail/offline/hooks.js.map +7 -0
- package/dist/mail/offline/index.js +48 -0
- package/dist/mail/offline/index.js.map +7 -0
- package/dist/mail/offline/live.js +233 -0
- package/dist/mail/offline/live.js.map +7 -0
- package/dist/mail/offline/mailbox.js +191 -0
- package/dist/mail/offline/mailbox.js.map +7 -0
- package/dist/mail/offline/outbox.js +167 -0
- package/dist/mail/offline/outbox.js.map +7 -0
- package/dist/mail/offline/reads.js +159 -0
- package/dist/mail/offline/reads.js.map +7 -0
- package/dist/mail/offline/runtime.js +100 -0
- package/dist/mail/offline/runtime.js.map +7 -0
- package/dist/mail/offline/settings.js +84 -0
- package/dist/mail/offline/settings.js.map +7 -0
- package/dist/mail/offline/store.js +29 -0
- package/dist/mail/offline/store.js.map +7 -0
- package/dist/mail/offline/sync.js +251 -0
- package/dist/mail/offline/sync.js.map +7 -0
- package/dist/mail/offline/wipe.js +19 -0
- package/dist/mail/offline/wipe.js.map +7 -0
- package/dist/mail/thread-keys.js +53 -0
- package/dist/mail/thread-keys.js.map +7 -0
- package/dist/mail/threads.js +71 -0
- package/dist/mail/threads.js.map +7 -0
- package/dist/mail/useMailClient.js +42 -0
- package/dist/mail/useMailClient.js.map +7 -0
- package/dist/model-connections.js +58 -0
- package/dist/model-connections.js.map +7 -0
- package/dist/notifications/ActivityFeed.js +70 -0
- package/dist/notifications/ActivityFeed.js.map +7 -0
- package/dist/notifications/NotificationBell.js +200 -0
- package/dist/notifications/NotificationBell.js.map +7 -0
- package/dist/notifications/Toaster.js +24 -0
- package/dist/notifications/Toaster.js.map +7 -0
- package/dist/notifications/activity-types.js +65 -0
- package/dist/notifications/activity-types.js.map +7 -0
- package/dist/notifications/bell.js +24 -0
- package/dist/notifications/bell.js.map +7 -0
- package/dist/notifications/calendar-notifications.js +79 -0
- package/dist/notifications/calendar-notifications.js.map +7 -0
- package/dist/notifications/index.js +108 -0
- package/dist/notifications/index.js.map +7 -0
- package/dist/notifications/live.js +28 -0
- package/dist/notifications/live.js.map +7 -0
- package/dist/notifications/notification-types.js +127 -0
- package/dist/notifications/notification-types.js.map +7 -0
- package/dist/{chunk-BF5KW5ZI.js → notifications/notify-store.js} +24 -74
- package/dist/notifications/notify-store.js.map +7 -0
- package/dist/notifications/server-notifications.js +452 -0
- package/dist/notifications/server-notifications.js.map +7 -0
- package/dist/notifications/useNotifications.js +34 -0
- package/dist/notifications/useNotifications.js.map +7 -0
- package/dist/offline-store/network.js +11 -0
- package/dist/offline-store/network.js.map +7 -0
- package/dist/offline-store/store.js +136 -0
- package/dist/offline-store/store.js.map +7 -0
- package/dist/offline-store/wipe.js +8 -0
- package/dist/offline-store/wipe.js.map +7 -0
- package/dist/offline.js +58 -0
- package/dist/offline.js.map +7 -0
- package/dist/people.js +122 -0
- package/dist/people.js.map +7 -0
- package/dist/projects.js +30 -0
- package/dist/projects.js.map +7 -0
- package/dist/query-client.js +63 -0
- package/dist/query-client.js.map +7 -0
- package/dist/{chunk-ZM6N7YZH.js → query-keys.js} +18 -31
- package/dist/query-keys.js.map +7 -0
- package/dist/query-persist.js +66 -0
- package/dist/query-persist.js.map +7 -0
- package/dist/queued-writes.js +59 -0
- package/dist/queued-writes.js.map +7 -0
- package/dist/remote-control.js +67 -0
- package/dist/remote-control.js.map +7 -0
- package/dist/search/index.js +23 -0
- package/dist/search/index.js.map +7 -0
- package/dist/search/session.js +58 -0
- package/dist/search/session.js.map +7 -0
- package/dist/search/useSemanticSearch.js +82 -0
- package/dist/search/useSemanticSearch.js.map +7 -0
- package/dist/session/chat.js +512 -0
- package/dist/session/chat.js.map +7 -0
- package/dist/session/documents.js +196 -0
- package/dist/session/documents.js.map +7 -0
- package/dist/session/drafts.js +103 -0
- package/dist/session/drafts.js.map +7 -0
- package/dist/session/index.js +123 -0
- package/dist/session/index.js.map +7 -0
- package/dist/session/layout.js +339 -0
- package/dist/session/layout.js.map +7 -0
- package/dist/session/persist.js +106 -0
- package/dist/session/persist.js.map +7 -0
- package/dist/session/session-hooks.js +53 -0
- package/dist/session/session-hooks.js.map +7 -0
- package/dist/session/signed-in.js +36 -0
- package/dist/session/signed-in.js.map +7 -0
- package/dist/session/store.js +166 -0
- package/dist/session/store.js.map +7 -0
- package/dist/session/thread-tabs.js +121 -0
- package/dist/session/thread-tabs.js.map +7 -0
- package/dist/session/ui-state-storage.js +76 -0
- package/dist/session/ui-state-storage.js.map +7 -0
- package/dist/session/workspace.js +77 -0
- package/dist/session/workspace.js.map +7 -0
- package/dist/shell/index.js +43 -10
- package/dist/shell/index.js.map +7 -1
- package/dist/skill-pack.js +111 -0
- package/dist/skill-pack.js.map +7 -0
- package/dist/storage.js +186 -0
- package/dist/storage.js.map +7 -0
- package/dist/support/index.js +35 -0
- package/dist/support/index.js.map +7 -0
- package/dist/tags.js +204 -0
- package/dist/tags.js.map +7 -0
- package/dist/ui/DebouncedInput.js +109 -0
- package/dist/ui/DebouncedInput.js.map +7 -0
- package/dist/ui/DictateContext.js +8 -0
- package/dist/ui/DictateContext.js.map +7 -0
- package/dist/ui/IconToggle.js +79 -0
- package/dist/ui/IconToggle.js.map +7 -0
- package/dist/ui/VerifiedToggle.js +38 -0
- package/dist/ui/VerifiedToggle.js.map +7 -0
- package/dist/ui/VisibilityToggle.js +103 -0
- package/dist/ui/VisibilityToggle.js.map +7 -0
- package/dist/ui/avatar.js +40 -0
- package/dist/ui/avatar.js.map +7 -0
- package/dist/ui/badge.js +28 -0
- package/dist/ui/badge.js.map +7 -0
- package/dist/ui/button.js +48 -0
- package/dist/ui/button.js.map +7 -0
- package/dist/ui/card.js +90 -0
- package/dist/ui/card.js.map +7 -0
- package/dist/ui/checkbox.js +22 -0
- package/dist/ui/checkbox.js.map +7 -0
- package/dist/ui/collapsible.js +10 -0
- package/dist/ui/collapsible.js.map +7 -0
- package/dist/ui/command.js +103 -0
- package/dist/ui/command.js.map +7 -0
- package/dist/{chunk-YNNAJJ5Z.js → ui/dialog.js} +30 -68
- package/dist/ui/dialog.js.map +7 -0
- package/dist/{chunk-47CCGUWR.js → ui/dropdown-menu.js} +40 -45
- package/dist/ui/dropdown-menu.js.map +7 -0
- package/dist/ui/hover-card.js +36 -0
- package/dist/ui/hover-card.js.map +7 -0
- package/dist/ui/index.js +290 -10
- package/dist/ui/index.js.map +7 -1
- package/dist/ui/input.js +65 -0
- package/dist/ui/input.js.map +7 -0
- package/dist/ui/label.js +16 -0
- package/dist/ui/label.js.map +7 -0
- package/dist/ui/mark-menu.js +300 -0
- package/dist/ui/mark-menu.js.map +7 -0
- package/dist/ui/popover.js +40 -0
- package/dist/ui/popover.js.map +7 -0
- package/dist/ui/portal-container.js +17 -0
- package/dist/ui/portal-container.js.map +7 -0
- package/dist/ui/progress.js +24 -0
- package/dist/ui/progress.js.map +7 -0
- package/dist/ui/radio-group.js +29 -0
- package/dist/ui/radio-group.js.map +7 -0
- package/dist/ui/scroll-area.js +39 -0
- package/dist/ui/scroll-area.js.map +7 -0
- package/dist/ui/select.js +130 -0
- package/dist/ui/select.js.map +7 -0
- package/dist/ui/separator.js +23 -0
- package/dist/ui/separator.js.map +7 -0
- package/dist/ui/slider.js +23 -0
- package/dist/ui/slider.js.map +7 -0
- package/dist/ui/switch.js +28 -0
- package/dist/ui/switch.js.map +7 -0
- package/dist/ui/table.js +75 -0
- package/dist/ui/table.js.map +7 -0
- package/dist/ui/tabs.js +48 -0
- package/dist/ui/tabs.js.map +7 -0
- package/dist/ui/textarea.js +63 -0
- package/dist/ui/textarea.js.map +7 -0
- package/dist/ui/toggle-group.js +43 -0
- package/dist/ui/toggle-group.js.map +7 -0
- package/dist/ui/toggle.js +40 -0
- package/dist/ui/toggle.js.map +7 -0
- package/dist/ui/tooltip.js +215 -0
- package/dist/ui/tooltip.js.map +7 -0
- package/dist/usage-metered.js +8 -0
- package/dist/usage-metered.js.map +7 -0
- package/dist/useArbi.js +16 -0
- package/dist/useArbi.js.map +7 -0
- package/dist/useInstallSkillPack.js +81 -0
- package/dist/useInstallSkillPack.js.map +7 -0
- package/dist/usermenu/UserMenu.js +188 -0
- package/dist/usermenu/UserMenu.js.map +7 -0
- package/dist/usermenu/index.js +5 -0
- package/dist/usermenu/index.js.map +7 -0
- package/dist/users/index.js +15 -0
- package/dist/users/index.js.map +7 -0
- package/dist/users/user-display.js +60 -0
- package/dist/users/user-display.js.map +7 -0
- package/dist/viewers/AudioViewer.js +23 -0
- package/dist/viewers/AudioViewer.js.map +7 -0
- package/dist/viewers/DocxViewer.js +81 -0
- package/dist/viewers/DocxViewer.js.map +7 -0
- package/dist/viewers/ImageViewer.js +31 -0
- package/dist/viewers/ImageViewer.js.map +7 -0
- package/dist/viewers/PdfViewer.js +19 -3
- package/dist/viewers/PdfViewer.js.map +7 -1
- package/dist/{PdfViewerImpl-TEBYF2QI.js → viewers/PdfViewerImpl.js} +25 -19
- package/dist/viewers/PdfViewerImpl.js.map +7 -0
- package/dist/viewers/VideoViewer.js +31 -0
- package/dist/viewers/VideoViewer.js.map +7 -0
- package/dist/viewers/XlsxViewer.js +102 -0
- package/dist/viewers/XlsxViewer.js.map +7 -0
- package/dist/viewers/index.js +61 -271
- package/dist/viewers/index.js.map +7 -1
- package/dist/viewers/page-scroll.js +59 -0
- package/dist/viewers/page-scroll.js.map +7 -0
- package/dist/viewers/pdf-viewer-constants.js +9 -0
- package/dist/viewers/pdf-viewer-constants.js.map +7 -0
- package/dist/{chunk-PTOP7OHG.js → viewers/pdfjs-polyfills.js} +5 -6
- package/dist/viewers/pdfjs-polyfills.js.map +7 -0
- package/dist/viewers/selection-runs.js +38 -0
- package/dist/viewers/selection-runs.js.map +7 -0
- package/dist/viewers/usePageIntersectionObserver.js +68 -0
- package/dist/viewers/usePageIntersectionObserver.js.map +7 -0
- package/dist/viewers/useProcessedChunks.js +58 -0
- package/dist/viewers/useProcessedChunks.js.map +7 -0
- package/dist/viewers/viewer-zoom.js +163 -0
- package/dist/viewers/viewer-zoom.js.map +7 -0
- package/dist/websocket/ArbiWebSocketProvider.js +207 -0
- package/dist/websocket/ArbiWebSocketProvider.js.map +7 -0
- package/dist/websocket/context.js +14 -0
- package/dist/websocket/context.js.map +7 -0
- package/dist/websocket/hooks.js +30 -0
- package/dist/websocket/hooks.js.map +7 -0
- package/dist/websocket/index.js +22 -0
- package/dist/websocket/index.js.map +7 -0
- package/dist/websocket/live-updates.js +38 -0
- package/dist/websocket/live-updates.js.map +7 -0
- package/dist/websocket/reconnect.js +13 -0
- package/dist/websocket/reconnect.js.map +7 -0
- package/dist/websocket/store.js +58 -0
- package/dist/websocket/store.js.map +7 -0
- package/dist/workforce.js +607 -0
- package/dist/workforce.js.map +7 -0
- package/dist/workspaces/access-request.js +35 -0
- package/dist/workspaces/access-request.js.map +7 -0
- package/dist/workspaces/archive.js +59 -0
- package/dist/workspaces/archive.js.map +7 -0
- package/dist/workspaces/current.js +20 -0
- package/dist/workspaces/current.js.map +7 -0
- package/dist/workspaces/delete-workspaces.js +15 -0
- package/dist/workspaces/delete-workspaces.js.map +7 -0
- package/dist/workspaces/export-archive.js +40 -0
- package/dist/workspaces/export-archive.js.map +7 -0
- package/dist/workspaces/index.js +99 -0
- package/dist/workspaces/index.js.map +7 -0
- package/dist/workspaces/settings.js +45 -0
- package/dist/workspaces/settings.js.map +7 -0
- package/dist/workspaces/shell-workspaces.js +49 -0
- package/dist/workspaces/shell-workspaces.js.map +7 -0
- package/dist/workspaces/switch.js +234 -0
- package/dist/workspaces/switch.js.map +7 -0
- package/dist/workspaces/transfer.js +170 -0
- package/dist/workspaces/transfer.js.map +7 -0
- package/dist/workspaces/useShellWorkspaces.js +86 -0
- package/dist/workspaces/useShellWorkspaces.js.map +7 -0
- package/dist/workspaces/workspace-users.js +65 -0
- package/dist/workspaces/workspace-users.js.map +7 -0
- package/package.json +4 -4
- package/dist/PdfViewerImpl-TEBYF2QI.js.map +0 -1
- package/dist/PdfViewerImpl.d-B28hLEuj.d.cts +0 -62
- package/dist/ProductionDialog.d-CpzslFn0.d.cts +0 -51
- package/dist/annotations/freeze/index.d.cts +0 -205
- package/dist/annotations/index.d.cts +0 -360
- package/dist/artifacts/index.d.cts +0 -476
- package/dist/artifacts/redline-core.d.cts +0 -39
- package/dist/bundle-YNOX7VIL.js +0 -5
- package/dist/bundle-YNOX7VIL.js.map +0 -1
- package/dist/bundle.d-BnCSbHy2.d.cts +0 -85
- package/dist/calls/livekit/index.d.cts +0 -280
- package/dist/chunk-47CCGUWR.js.map +0 -1
- package/dist/chunk-4FL3X3LA.js +0 -2057
- package/dist/chunk-4FL3X3LA.js.map +0 -1
- package/dist/chunk-6QNBSXCE.js +0 -271
- package/dist/chunk-6QNBSXCE.js.map +0 -1
- package/dist/chunk-74N436VK.js.map +0 -1
- package/dist/chunk-APZZQZ6P.js +0 -147
- package/dist/chunk-APZZQZ6P.js.map +0 -1
- package/dist/chunk-BF5KW5ZI.js.map +0 -1
- package/dist/chunk-DPYBZDJB.js.map +0 -1
- package/dist/chunk-DZKRL5H3.js +0 -2766
- package/dist/chunk-DZKRL5H3.js.map +0 -1
- package/dist/chunk-HDCRPPBW.js +0 -75
- package/dist/chunk-HDCRPPBW.js.map +0 -1
- package/dist/chunk-L2IPPTVC.js +0 -20
- package/dist/chunk-L2IPPTVC.js.map +0 -1
- package/dist/chunk-LSU4UPS5.js +0 -1011
- package/dist/chunk-LSU4UPS5.js.map +0 -1
- package/dist/chunk-NIKPG4PW.js +0 -1128
- package/dist/chunk-NIKPG4PW.js.map +0 -1
- package/dist/chunk-NNAJLY6B.js +0 -4974
- package/dist/chunk-NNAJLY6B.js.map +0 -1
- package/dist/chunk-OYPKKHXY.js +0 -559
- package/dist/chunk-OYPKKHXY.js.map +0 -1
- package/dist/chunk-PTOP7OHG.js.map +0 -1
- package/dist/chunk-QMY2JKBI.js +0 -246
- package/dist/chunk-QMY2JKBI.js.map +0 -1
- package/dist/chunk-SN5YV6FF.js +0 -11
- package/dist/chunk-SN5YV6FF.js.map +0 -1
- package/dist/chunk-SSXFVWCT.js.map +0 -1
- package/dist/chunk-T3USOSVN.js.map +0 -1
- package/dist/chunk-T4CLW3DN.js +0 -2560
- package/dist/chunk-T4CLW3DN.js.map +0 -1
- package/dist/chunk-UW2SGTI5.js.map +0 -1
- package/dist/chunk-VSCU7K4V.js.map +0 -1
- package/dist/chunk-WL2Y2T47.js.map +0 -1
- package/dist/chunk-WUTL62MC.js.map +0 -1
- package/dist/chunk-XWPLOFDN.js +0 -644
- package/dist/chunk-XWPLOFDN.js.map +0 -1
- package/dist/chunk-Y3MTRA7D.js +0 -97
- package/dist/chunk-Y3MTRA7D.js.map +0 -1
- package/dist/chunk-YNNAJJ5Z.js.map +0 -1
- package/dist/chunk-ZM6N7YZH.js.map +0 -1
- package/dist/document-tools/core.d.cts +0 -883
- package/dist/document-tools/index.d.cts +0 -90
- package/dist/index.d-LArLnpI8.d.cts +0 -2036
- package/dist/index.d-oR5FKZpJ.d.cts +0 -579
- package/dist/index.d.cts +0 -15923
- package/dist/lazy-chunk.d-B6YDLMKI.d.cts +0 -31
- package/dist/model.d-CNtRWKVK.d.cts +0 -110
- package/dist/query-keys.d-B1Am9tIF.d.cts +0 -337
- package/dist/shell/index.d.cts +0 -6
- package/dist/store.d-GADDvC7w.d.cts +0 -35
- package/dist/stored-markdown.d-Bp18vrbr.d.cts +0 -125
- package/dist/ui/index.d.cts +0 -26
- package/dist/useAudioRecorder.d-B9rlMI_E.d.cts +0 -778
- package/dist/viewers/PdfViewer.d.cts +0 -9
- package/dist/viewers/index.d.cts +0 -262
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/chat/conversation-cache.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * A conversation's threads in the query cache (`arbiQueryKeys.conversationThreads(id)`), and the\n * writers every chat engine and event uses on them: a turn's user and assistant messages, streamed\n * text (buffered per animation frame), settled output items, the resolving commit (held behind\n * the narration dwell), failure, loading state and pending questions.\n */\n\nimport type { QueryClient } from '@tanstack/react-query'\nimport type { components } from '@arbidocs/client'\nimport {\n reduceOutputItem,\n createIndexAssigner,\n type ChatMessage as Message,\n type OutputItemDone,\n type Thread,\n type ThreadsResponse,\n type UserInputRequestEvent,\n} from '@arbidocs/sdk/browser'\nimport { arbiQueryKeys } from '../hooks'\n\ntype MessageResponse = components['schemas']['MessageResponse']\n\n/** The query key of a conversation's threads. */\nexport function getThreadsQueryKey(conversationId: string) {\n return arbiQueryKeys.conversationThreads(conversationId)\n}\n\n/** Every conversation's cached threads (a filter for `invalidateQueries`, `getQueriesData`, \u2026). */\nexport const allConversationThreads = {\n predicate: ({ queryKey }: { queryKey: readonly unknown[] }) =>\n queryKey[0] === 'arbi' && queryKey[1] === 'conversations' && queryKey[3] === 'threads',\n}\n\n/**\n * Whether the cached thread says a message is still being generated on the server\n */\nexport function isMessageRunning(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string\n): boolean {\n const data = queryClient.getQueryData<ThreadsResponse>(getThreadsQueryKey(conversationId))\n return (data?.threads ?? []).some((t: Thread) =>\n t.history.some(\n (m: Message) =>\n m.external_id === messageId && (m.status === 'in_progress' || m.status === 'queued')\n )\n )\n}\n\n/**\n * Add a user message to the conversation cache\n */\nexport function addUserMessageToCache(\n queryClient: QueryClient,\n conversationId: string,\n userMessage: Message,\n options: {\n parentId?: string | null\n parentMessageId?: string | null\n currentParentMessageId?: string | null\n }\n): void {\n const { parentId, parentMessageId, currentParentMessageId } = options\n\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) {\n return {\n conversation_ext_id: conversationId,\n threads: [\n {\n history: [userMessage],\n leaf_message_ext_id: userMessage.external_id,\n },\n ],\n }\n }\n\n const threads = [...(oldData.threads || [])]\n\n // The server's parent is authoritative. A follow-up sent while a turn generates names\n // that turn, but the server queues each one behind the follow-ups already waiting, so\n // it may answer it after a later turn. Placing it under the client's guess made ordered\n // follow-ups siblings (\"Branch 1 of 2\") instead of one line.\n const serverParentId = userMessage.parent_message_ext_id\n // A server parent that already has a reply is a real branch point.\n const serverParentKnown =\n !!serverParentId &&\n threads.some((t) => t.history.some((msg) => msg.external_id === serverParentId))\n // A follow-up queued behind another one is chained after that one's answer, which has not\n // streamed in yet. Until it does, the follow-up continues the thread ending at the queued\n // message. The client's guess (the running turn) would wrongly branch it off that turn.\n const queuedLeafIndex = threads.findIndex((t) =>\n t.history.some(\n (msg) => msg.external_id === t.leaf_message_ext_id && msg.status === 'queued'\n )\n )\n const continueIndex =\n serverParentId && !serverParentKnown\n ? queuedLeafIndex\n : threads.findIndex((t) => t.leaf_message_ext_id === serverParentId)\n if (serverParentId && continueIndex !== -1) {\n threads[continueIndex] = {\n ...threads[continueIndex],\n history: [...threads[continueIndex].history, userMessage],\n leaf_message_ext_id: userMessage.external_id,\n }\n return { ...oldData, threads }\n }\n\n const branchFrom = serverParentKnown ? serverParentId : parentId\n const isBranching = serverParentKnown || (parentId && parentId !== currentParentMessageId)\n\n if (isBranching) {\n // Branching: create new thread with shared history up to parent\n let sharedHistory: Message[] = []\n const parentThread = threads.find((thread) =>\n thread.history.some((msg) => msg.external_id === branchFrom)\n )\n if (parentThread) {\n const parentIndex = parentThread.history.findIndex(\n (msg) => msg.external_id === branchFrom\n )\n if (parentIndex !== -1) {\n sharedHistory = parentThread.history.slice(0, parentIndex + 1)\n }\n }\n threads.push({\n history: [...sharedHistory, userMessage],\n leaf_message_ext_id: userMessage.external_id,\n })\n } else if (parentMessageId) {\n // Appending to selected thread\n const threadIndex = threads.findIndex((t) => t.leaf_message_ext_id === parentMessageId)\n if (threadIndex !== -1) {\n threads[threadIndex] = {\n ...threads[threadIndex],\n history: [...threads[threadIndex].history, userMessage],\n leaf_message_ext_id: userMessage.external_id,\n }\n } else {\n threads.push({\n history: [userMessage],\n leaf_message_ext_id: userMessage.external_id,\n })\n }\n } else {\n // New conversation or appending to current thread\n if (threads.length > 0) {\n threads[threads.length - 1] = {\n ...threads[threads.length - 1],\n history: [...threads[threads.length - 1].history, userMessage],\n leaf_message_ext_id: userMessage.external_id,\n }\n } else {\n threads.push({\n history: [userMessage],\n leaf_message_ext_id: userMessage.external_id,\n })\n }\n }\n\n return { ...oldData, threads }\n }\n )\n}\n\n/**\n * Update an existing user message in the cache (e.g., status change from queued to completed).\n * Returns true if the message was found and updated, false otherwise.\n */\nexport function updateUserMessageInCache(\n queryClient: QueryClient,\n conversationId: string,\n userMessage: Message\n): boolean {\n let found = false\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n\n const updated = {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) => {\n if (msg.external_id === userMessage.external_id) {\n found = true\n return { ...msg, ...userMessage }\n }\n return msg\n }),\n })),\n }\n return updated\n }\n )\n return found\n}\n\n/** Update only the transient state of a cached user message. */\nexport function updateUserMessageStateInCache(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string,\n status: Message['status'],\n isLoading: boolean\n): void {\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((message: Message) =>\n message.external_id === messageId ? { ...message, status, isLoading } : message\n ),\n })),\n }\n }\n )\n}\n\n/** Settle the oldest queued prompt matching an interjection step's content. */\nexport function completeQueuedUserMessageByContent(\n queryClient: QueryClient,\n conversationId: string,\n content: string\n): boolean {\n let completed = false\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((message: Message) => {\n if (\n !completed &&\n message.role === 'user' &&\n message.status === 'queued' &&\n message.content === content\n ) {\n completed = true\n return { ...message, status: 'completed', isLoading: false }\n }\n return message\n }),\n })),\n }\n }\n )\n return completed\n}\n\n/**\n * The text of a steering interjection that a run picked up, or null for any other item.\n *\n * The backend reports a queued prompt it steered into the run as a reasoning item of\n * kind `interjection` (`arbi.step`); the \"Your message\" label is the fallback for a\n * backend that predates that field.\n */\nexport function getInterjectionText(item: unknown): string | null {\n const candidate = item as {\n type?: string\n arbi?: { label?: string; step?: string }\n summary?: unknown\n } | null\n if (\n candidate?.type !== 'reasoning' ||\n (candidate.arbi?.step !== 'interjection' && candidate.arbi?.label !== 'Your message')\n ) {\n return null\n }\n const text = Array.isArray(candidate.summary)\n ? (candidate.summary as Array<{ text?: string }>).map((c) => c.text ?? '').join('')\n : ''\n return text || null\n}\n\n/**\n * Whether the thread that ends at `leafId` contains `messageId`, i.e. `leafId` is\n * `messageId` itself or a later turn in the same line.\n */\nexport function threadEndingAtContains(\n queryClient: QueryClient,\n conversationId: string,\n leafId: string,\n messageId: string\n): boolean {\n const data = queryClient.getQueryData<ThreadsResponse>(getThreadsQueryKey(conversationId))\n const thread = data?.threads?.find((t: Thread) => t.leaf_message_ext_id === leafId)\n return !!thread?.history.some((m: Message) => m.external_id === messageId)\n}\n\n/**\n * When the run's assistant message is already in the cache, the moment it was created (ms),\n * so a reattached live timer keeps counting from the run's real start instead of from the\n * attach. Undefined when the row isn't loaded yet or has no usable timestamp.\n */\nexport function getRunStartedAt(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string\n): number | undefined {\n const data = queryClient.getQueryData<ThreadsResponse>(getThreadsQueryKey(conversationId))\n const message = data?.threads\n .flatMap((thread: Thread) => thread.history)\n .find((m: Message) => m.external_id === messageId)\n const startedAt = message?.created_at ? Date.parse(message.created_at) : NaN\n // Never in the future: a server clock ahead of this one would show a negative timer.\n return Number.isFinite(startedAt) ? Math.min(startedAt, Date.now()) : undefined\n}\n\n/**\n * Ensure an assistant message row exists in the cache for a run we're ATTACHING to\n * (foregrounding a background run in the conversation view). Unlike\n * `addAssistantMessageToCache`, this is idempotent: if the run's assistant message\n * is already present (loaded from history), it just flips `isLoading` on; otherwise\n * it appends a loading placeholder to the last thread so the live steps/answer have\n * a row to accumulate under. No-op when the threads cache hasn't loaded yet.\n */\nexport function ensureAssistantMessageLoading(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string\n): void {\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n\n const exists = oldData.threads.some((t: Thread) =>\n t.history.some((m: Message) => m.external_id === messageId)\n )\n if (exists) {\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) =>\n msg.external_id === messageId ? { ...msg, isLoading: true } : msg\n ),\n })),\n }\n }\n\n const placeholder: Message = {\n role: 'assistant',\n content: '',\n external_id: messageId,\n created_at: new Date().toISOString(),\n config_ext_id: null,\n created_by_ext_id: '',\n conversation_ext_id: conversationId,\n tokens: 0,\n status: 'in_progress',\n isLoading: true,\n }\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread, index: number) =>\n index === oldData.threads.length - 1\n ? {\n ...thread,\n history: [...thread.history, placeholder],\n leaf_message_ext_id: placeholder.external_id,\n }\n : thread\n ),\n }\n }\n )\n}\n\n/**\n * Replace an assistant message's content outright. Used when attaching to a\n * background run (`response.output_text.done` carries the whole answer, not\n * deltas), and at the one moment a live stream's body legitimately loses text:\n * the answer item settles and replaces the interim narration lines accumulated\n * during the turn (see handleOutputItemDone).\n */\nexport function setMessageContent(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string,\n content: string\n): void {\n discardStreamingTokensForMessage(conversationId, messageId)\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) =>\n msg.external_id === messageId ? { ...msg, content } : msg\n ),\n })),\n }\n }\n )\n}\n\n/**\n * Record that a narration item just settled: everything streamed so far is now\n * superseded prose, and whatever arrives next is the live segment.\n *\n * Buffered tokens are flushed first \u2014 the boundary is a character offset into\n * `content`, so it is only correct once every delta for the settled item has\n * actually landed in the cache.\n *\n * Also guarantees the block separator. Items are concatenated into one string,\n * so a paragraph break between two of them depended entirely on the model\n * ending its prose with newlines. When it did not, the next item ran on\n * mid-line (\"\u2026in parallel.Step 2: Read the relevant document\") \u2014 the boundary\n * has to supply the break itself.\n */\nexport function markNarrationSettled(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string\n): void {\n flushStreamingTokens(queryClient)\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) => {\n if (msg.external_id !== messageId) return msg\n const settled = (msg.content ?? '').replace(/\\s+$/, '')\n if (!settled) return msg\n const content = `${settled}\\n\\n`\n return { ...msg, content, settledNarrationLength: content.length }\n }),\n })),\n }\n }\n )\n}\n\n/**\n * Take a settled narration item's text out of a streaming answer's body. The item's deltas were\n * appended verbatim, so its text is in the body as streamed, normally at the end (the server\n * settles a narration item before anything else streams). The text stays in the steps trace.\n */\nexport function removeSettledNarration(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string,\n /** The settled item's `content` parts. */\n itemContent: unknown\n): void {\n const text = Array.isArray(itemContent)\n ? (itemContent as Array<{ text?: string }>).map((c) => c.text ?? '').join('')\n : ''\n if (!text.trim()) return\n flushStreamingTokens(queryClient)\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) => {\n if (msg.external_id !== messageId) return msg\n const body = msg.content ?? ''\n const at = body.lastIndexOf(text)\n if (at === -1) return msg\n const rest = body.slice(0, at) + body.slice(at + text.length)\n const content = rest.trim() ? rest : ''\n // The dimmed prefix cannot reach past the text that is left.\n const settled = Math.min(msg.settledNarrationLength ?? 0, content.length)\n return { ...msg, content, settledNarrationLength: settled || undefined }\n }),\n })),\n }\n }\n )\n}\n\n/**\n * Add an assistant message placeholder to the cache (for streaming), placed right after the\n * user message it answers.\n *\n * Follow-ups sent while a turn runs are saved at once, each with its own answer row (status\n * `queued`), so when a queued turn starts its user message may no longer be the thread's leaf:\n * later follow-ups already sit below it. The answer then goes right after its user message, not\n * at the end, and a stored queued row (loaded by a refetch) is started in place, not duplicated.\n *\n * @returns false when the user message was named but is not in the cache, so the answer could\n * only be appended to the last thread; the caller re-reads the thread to correct it.\n */\nexport function addAssistantMessageToCache(\n queryClient: QueryClient,\n conversationId: string,\n assistantMessage: Message,\n /** The user message this answers. Its thread gets the answer; else the last thread. */\n userMessageId?: string | null\n): boolean {\n let placed = true\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n const answerId = assistantMessage.external_id\n\n // The server stored this answer row already (queued): start it where it is.\n const stored = oldData.threads.some((t: Thread) =>\n t.history.some((m: Message) => m.external_id === answerId)\n )\n if (stored) {\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((m: Message) =>\n m.external_id === answerId\n ? { ...m, status: assistantMessage.status, isLoading: assistantMessage.isLoading }\n : m\n ),\n })),\n }\n }\n\n // The user message ends a thread: the answer becomes that thread's new leaf.\n const leafIndex = userMessageId\n ? oldData.threads.findIndex((t: Thread) => t.leaf_message_ext_id === userMessageId)\n : -1\n // Follow-ups are queued after the user message: insert the answer right after it.\n let holderIndex = -1\n if (userMessageId && leafIndex === -1) {\n oldData.threads.forEach((t: Thread, index: number) => {\n if (t.history.some((m: Message) => m.external_id === userMessageId)) holderIndex = index\n })\n }\n if (userMessageId && leafIndex === -1 && holderIndex === -1) placed = false\n const appendIndex = leafIndex !== -1 ? leafIndex : oldData.threads.length - 1\n\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread, index: number) => {\n if (holderIndex !== -1) {\n if (index !== holderIndex) return thread\n const at = thread.history.findIndex((m: Message) => m.external_id === userMessageId)\n const history = [...thread.history]\n history.splice(at + 1, 0, assistantMessage)\n return { ...thread, history }\n }\n if (index === appendIndex) {\n return {\n ...thread,\n history: [...thread.history, assistantMessage],\n leaf_message_ext_id: answerId,\n }\n }\n return thread\n }),\n }\n }\n )\n return placed\n}\n\n/**\n * Internal helper that synchronously writes a chunk of text onto an assistant\n * message's content. Called by the rAF flusher below and by tests that want\n * deterministic behavior.\n */\nfunction applyTokenChunkToCache(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string,\n chunk: string\n): void {\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) => {\n if (msg.external_id === messageId) {\n return { ...msg, content: msg.content + chunk }\n }\n return msg\n }),\n })),\n }\n }\n )\n}\n\n/**\n * Per-stream pending token buffer. We coalesce every token that arrives in the\n * same frame into a single string, then commit it to React Query once on the\n * next animation frame. This turns a 20\u201330 Hz stream of full-tree clones into\n * ~60 Hz at most, and ensures <Message> only re-renders once per frame even\n * when the model emits many deltas in quick succession.\n */\ninterface PendingTokenEntry {\n conversationId: string\n messageId: string\n buffer: string\n}\n\nconst pendingTokens = new Map<string, PendingTokenEntry>()\nlet rafHandle: number | null = null\nlet rafSchedule: ((cb: () => void) => number) | null = null\nlet rafCancel: ((handle: number) => void) | null = null\n\nfunction getRafSchedule(): (cb: () => void) => number {\n if (rafSchedule) return rafSchedule\n if (typeof globalThis.requestAnimationFrame === 'function') {\n rafSchedule = (cb) => globalThis.requestAnimationFrame(cb)\n rafCancel = (h) => globalThis.cancelAnimationFrame(h)\n } else {\n // SSR / test fallback \u2014 use a microtask-ish timeout.\n rafSchedule = (cb) => {\n const id = setTimeout(cb, 16) as unknown as number\n return id\n }\n rafCancel = (h) => clearTimeout(h as unknown as ReturnType<typeof setTimeout>)\n }\n return rafSchedule\n}\n\nfunction flushPendingTokens(queryClient: QueryClient): void {\n rafHandle = null\n if (pendingTokens.size === 0) return\n // Snapshot and clear before writing, so tokens that arrive while we flush\n // are scheduled for the next frame rather than dropped.\n const entries = Array.from(pendingTokens.values())\n pendingTokens.clear()\n for (const entry of entries) {\n if (entry.buffer.length === 0) continue\n applyTokenChunkToCache(queryClient, entry.conversationId, entry.messageId, entry.buffer)\n }\n}\n\n/**\n * Append streaming token content to an assistant message.\n *\n * Tokens are buffered and flushed once per animation frame. Within a single\n * frame all deltas targeting the same message coalesce into one cache write,\n * so the React tree is diffed at most ~60 times/sec regardless of the model's\n * emit rate. A terminal event should call `flushStreamingTokens()` before\n * committing final metadata so no buffered text is lost.\n */\nexport function appendTokenToMessage(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string,\n tokenContent: string\n): void {\n if (!tokenContent) return\n const key = `${conversationId}::${messageId}`\n const existing = pendingTokens.get(key)\n if (existing) {\n existing.buffer += tokenContent\n } else {\n pendingTokens.set(key, { conversationId, messageId, buffer: tokenContent })\n }\n if (rafHandle === null) {\n const schedule = getRafSchedule()\n rafHandle = schedule(() => flushPendingTokens(queryClient))\n }\n}\n\n/**\n * Force any buffered tokens to be committed to the cache immediately.\n * Call this from terminal handlers (metadata arrival, error, abort) so that\n * the final message reflects every token the server sent before the commit.\n */\nexport function flushStreamingTokens(queryClient: QueryClient): void {\n if (rafHandle !== null && rafCancel) {\n rafCancel(rafHandle)\n rafHandle = null\n }\n flushPendingTokens(queryClient)\n}\n\n/**\n * Drop any buffered tokens for a specific message without writing them.\n * Used when a stream resets content (agent-step transitions) so stale\n * deltas from the previous phase don't clobber the fresh buffer.\n */\nexport function discardStreamingTokensForMessage(conversationId: string, messageId: string): void {\n pendingTokens.delete(`${conversationId}::${messageId}`)\n}\n\n/**\n * Test-only hook: clear all pending buffers and cancel the scheduled flush.\n * @internal\n */\nexport function __resetStreamingTokenBufferForTests(): void {\n if (rafHandle !== null && rafCancel) {\n rafCancel(rafHandle)\n }\n rafHandle = null\n pendingTokens.clear()\n}\n\n/**\n * Assistant messages whose body swap is waiting out the narration dwell,\n * keyed `conversationId::messageId` \u2192 timer handle.\n *\n * Two things read this, and both are the point:\n * - `commitFinalMessage` itself, so a second `response.completed` for the same\n * message replaces the pending swap instead of racing it;\n * - `clearLoadingState`, which runs when the stream socket closes and would\n * otherwise un-fade the body a beat before the swap lands \u2014 splitting the\n * single resolving reflow back into two.\n */\nconst pendingFinalCommits = new Map<string, ReturnType<typeof setTimeout>>()\n\nconst finalCommitKey = (conversationId: string, messageId: string) =>\n `${conversationId}::${messageId}`\n\n/** Is this message's resolving commit still queued behind the dwell? */\nexport function hasPendingFinalCommit(conversationId: string, messageId: string): boolean {\n return pendingFinalCommits.has(finalCommitKey(conversationId, messageId))\n}\n\nfunction cancelPendingFinalCommit(conversationId: string, messageId: string): void {\n const key = finalCommitKey(conversationId, messageId)\n const handle = pendingFinalCommits.get(key)\n if (handle !== undefined) {\n clearTimeout(handle)\n pendingFinalCommits.delete(key)\n }\n}\n\n/**\n * Resolve a streamed assistant message: the server's answer replaces everything\n * the model said, the citations computed against that exact string arrive with\n * it, and `isLoading` clears \u2014 all in ONE write, so the window moves once.\n * Committing the content swap and the un-fading separately is what made it\n * jitter.\n *\n * `notBefore` (epoch ms, 0 = now) is the narration dwell: freshly-settled prose\n * is guaranteed its reading window before the swap is allowed to remove it.\n *\n * What waits is only the DISPLAY. Everything the rest of the app reasons about \u2014\n * `status` above all \u2014 lands immediately, because the leaf assistant message's\n * status is how the app knows whether a run is still in flight: hold it at\n * `in_progress` after the stream has closed and the conversation attaches a run\n * stream to its own finished turn (Conversation.tsx `attachResponseId`), which\n * spins into an infinite update loop. The early write is invisible: the body is\n * unchanged, the footer is still hidden behind `isLoading`, and the citation\n * markers the payload brings do not appear in the streamed text, so nothing\n * renders differently until the swap.\n */\nexport function commitFinalMessage(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string,\n metadata: MessageResponse,\n notBefore = 0\n): void {\n cancelPendingFinalCommit(conversationId, messageId)\n cancelPendingFinalCommit(conversationId, metadata.external_id)\n const delay = Math.max(0, notBefore - Date.now())\n if (delay === 0) {\n updateMessageWithMetadata(queryClient, conversationId, messageId, metadata)\n return\n }\n // Buffered deltas are flushed rather than dropped, so the body the user is\n // reading is the complete one and does not twitch while it waits.\n flushStreamingTokens(queryClient)\n // Keyed by the SERVER's id: the early write rebuilds the message from the\n // payload, so that is the id it carries while the swap is pending \u2014 and the id\n // clearLoadingState will look up.\n const key = finalCommitKey(conversationId, metadata.external_id)\n applyMetadata(queryClient, conversationId, messageId, metadata, { holdBody: true })\n pendingFinalCommits.set(\n key,\n setTimeout(() => {\n pendingFinalCommits.delete(key)\n // The message now carries the server's id; the swap targets that.\n swapInFinalBody(queryClient, conversationId, metadata.external_id, metadata.content ?? '')\n }, delay)\n )\n}\n\n/** The one visible move: the answer takes the window and stops being provisional. */\nfunction swapInFinalBody(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string,\n content: string\n): void {\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) =>\n msg.external_id === messageId ? { ...msg, content, isLoading: false } : msg\n ),\n })),\n }\n }\n )\n}\n\n/**\n * Test-only hook: drop every deferred commit without running it.\n * @internal\n */\nexport function __resetPendingFinalCommitsForTests(): void {\n for (const handle of pendingFinalCommits.values()) clearTimeout(handle)\n pendingFinalCommits.clear()\n}\n\n/**\n * Update an assistant message with final metadata from server\n */\nexport function updateMessageWithMetadata(\n queryClient: QueryClient,\n conversationId: string,\n streamingMessageId: string,\n metadata: MessageResponse\n): void {\n applyMetadata(queryClient, conversationId, streamingMessageId, metadata, { holdBody: false })\n}\n\n/**\n * Rebuild a streaming assistant message from the server's final payload.\n *\n * `holdBody` keeps the body exactly as the reader currently sees it (and keeps it\n * provisional) while letting every other fact land \u2014 see commitFinalMessage for\n * why the facts must not wait.\n */\nfunction applyMetadata(\n queryClient: QueryClient,\n conversationId: string,\n streamingMessageId: string,\n metadata: MessageResponse,\n { holdBody }: { holdBody: boolean }\n): void {\n // Final content comes from server metadata \u2014 drop any buffered tokens so\n // we don't re-append what's about to be overwritten.\n if (!holdBody) discardStreamingTokensForMessage(conversationId, streamingMessageId)\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n\n const serverAssistantId = metadata.external_id\n\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) => {\n if (msg.external_id === streamingMessageId) {\n // Always use server metadata content \u2014 it includes citation markers\n // with offset_start/offset_end calculated against this exact string.\n // This REBUILDS the message from the server payload, so every\n // client-side field has to be carried over explicitly or it is\n // destroyed here at the end of the turn.\n return {\n ...metadata,\n isLoading: holdBody ? true : false,\n content: holdBody ? msg.content : metadata.content,\n agentSteps: msg.agentSteps,\n pendingUserInput: msg.pendingUserInput,\n // While the body is held for the narration dwell, the dimmed\n // prose must stay dimmed: dropping the boundary here would\n // un-fade it a beat before the swap, splitting the one resolving\n // reflow in two.\n settledNarrationLength: msg.settledNarrationLength,\n }\n }\n return msg\n }),\n leaf_message_ext_id:\n thread.leaf_message_ext_id === streamingMessageId\n ? serverAssistantId\n : thread.leaf_message_ext_id,\n })),\n }\n }\n )\n}\n\n/**\n * Mark a specific assistant message as failed in the conversation cache.\n * Called when WebSocket response_complete arrives with status='failed'.\n */\nexport function markMessageAsFailed(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string\n): void {\n // Flush any buffered tokens first so the failed message still reflects\n // whatever the model produced before the failure.\n flushStreamingTokens(queryClient)\n // A failure supersedes a queued resolving commit \u2014 letting it fire afterwards\n // would quietly un-fail the message.\n cancelPendingFinalCommit(conversationId, messageId)\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) =>\n msg.external_id === messageId\n ? { ...msg, status: 'failed' as const, isLoading: false }\n : msg\n ),\n })),\n }\n }\n )\n}\n\n/**\n * Clear loading state on all messages in a conversation.\n *\n * A message whose resolving commit is still queued behind the narration dwell is\n * left alone: clearing `isLoading` early would un-fade a body that still holds\n * the narration, and the real commit would then reflow it a second time \u2014 the\n * two-step ending this design exists to remove. The pending commit clears\n * `isLoading` itself when it lands.\n */\nexport function clearLoadingState(queryClient: QueryClient, conversationId: string): void {\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) =>\n msg.isLoading && !hasPendingFinalCommit(conversationId, msg.external_id ?? '')\n ? { ...msg, isLoading: false }\n : msg\n ),\n })),\n }\n }\n )\n}\n\n/**\n * Append an agent step event to a message's agentSteps array\n */\nexport function applyOutputItemToMessage(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string,\n ev: OutputItemDone\n): void {\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) => {\n if (msg.external_id !== messageId) return msg\n const existing = msg.agentSteps || []\n // The id->index map is rebuilt from the current steps each call: the\n // cache is immutable, so there is nowhere to keep it, and it is O(n)\n // over a handful of steps. The reducer is the one home for protocol\n // logic \u2014 this function just persists its result.\n const { assign, resolve } = createIndexAssigner(existing)\n const updated = reduceOutputItem(existing, ev, assign, resolve)\n return updated === existing ? msg : { ...msg, agentSteps: updated }\n }),\n })),\n }\n }\n )\n\n // A sub-agent that just settled has persisted its own branch server-side\n // (task message + reply) \u2014 a whole new thread this conversation's cached\n // `threads` list has never seen. The map above only patches steps on\n // EXISTING messages, so without this the branch stays invisible (no open-\n // thread affordance, no branch badge) until something else happens to\n // refetch. `staleTime` on useConversationThreads is long specifically because\n // WebSocket/SSE traffic is expected to keep it fresh \u2014 this is that update.\n const arbi = ev.item?.arbi\n if (\n (arbi?.subagent_status === 'done' || arbi?.subagent_status === 'failed') &&\n arbi.task_message_ext_id\n ) {\n queryClient.invalidateQueries({ queryKey: getThreadsQueryKey(conversationId) })\n }\n}\n\n/**\n * Persist the turn's final token/\u00A3 budget snapshot (from\n * response.completed) onto the assistant message. Distinct from\n * applyOutputItemToMessage's agentSteps: steps only ever cover\n * function_call/reasoning items, so they never carry the true final total \u2014\n * see the finalContextUsage doc comment on Message in types/ui.ts.\n */\nexport function applyFinalContextToMessage(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string,\n context: Message['finalContextUsage']\n): void {\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) =>\n msg.external_id === messageId ? { ...msg, finalContextUsage: context } : msg\n ),\n })),\n }\n }\n )\n}\n\nexport function setUserInputRequest(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string,\n request: UserInputRequestEvent\n): void {\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) => {\n if (msg.external_id === messageId) {\n return { ...msg, pendingUserInput: request }\n }\n return msg\n }),\n })),\n }\n }\n )\n}\n\n/**\n * Reset the content of a message (clear the body).\n */\nexport function resetMessageContent(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string\n): void {\n setMessageContent(queryClient, conversationId, messageId, '')\n}\n\n/**\n * Clear the pending user input request on a message\n */\nexport function clearUserInputRequest(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string\n): void {\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) => {\n if (msg.external_id === messageId) {\n return { ...msg, pendingUserInput: null }\n }\n return msg\n }),\n })),\n }\n }\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { arbiQueryKeys } from "../hooks.js";
|
|
2
|
+
import { invalidateConversationLists, patchConversation } from "../conversation-list.js";
|
|
3
|
+
import {
|
|
4
|
+
getThreadsQueryKey,
|
|
5
|
+
markMessageAsFailed,
|
|
6
|
+
updateUserMessageStateInCache
|
|
7
|
+
} from "./conversation-cache.js";
|
|
8
|
+
async function applyConversationEvent(queryClient, event) {
|
|
9
|
+
const e = event;
|
|
10
|
+
if (e.type === "response_complete") return applyRunEnded(queryClient, e);
|
|
11
|
+
if (e.type === "conversation.message_posted") return applyMessagePosted(queryClient, e);
|
|
12
|
+
if (e.type === "conversation.title_updated" && e.conversation_ext_id) {
|
|
13
|
+
patchConversation(queryClient, e.conversation_ext_id, { title: e.title ?? null });
|
|
14
|
+
}
|
|
15
|
+
if (e.type === "conversation.document_binding_changed" && e.conversation_ext_id) {
|
|
16
|
+
void queryClient.invalidateQueries({ queryKey: getThreadsQueryKey(e.conversation_ext_id) });
|
|
17
|
+
void invalidateConversationLists(queryClient);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function applyRunEnded(queryClient, e) {
|
|
21
|
+
const conversationId = e.conversation_ext_id;
|
|
22
|
+
if (!conversationId) return;
|
|
23
|
+
const failed = e.status === "failed";
|
|
24
|
+
if (e.user_message_id) {
|
|
25
|
+
updateUserMessageStateInCache(
|
|
26
|
+
queryClient,
|
|
27
|
+
conversationId,
|
|
28
|
+
e.user_message_id,
|
|
29
|
+
"completed",
|
|
30
|
+
false
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
if (failed && e.response_id) markMessageAsFailed(queryClient, conversationId, e.response_id);
|
|
34
|
+
patchConversation(queryClient, conversationId, {
|
|
35
|
+
last_message_status: failed ? "failed" : "completed"
|
|
36
|
+
});
|
|
37
|
+
void invalidateConversationLists(queryClient);
|
|
38
|
+
void queryClient.invalidateQueries({ queryKey: getThreadsQueryKey(conversationId) });
|
|
39
|
+
if (!failed) void queryClient.invalidateQueries({ queryKey: arbiQueryKeys.userUsageToday() });
|
|
40
|
+
}
|
|
41
|
+
async function applyMessagePosted(queryClient, e) {
|
|
42
|
+
if (!e.conversation_ext_id) return;
|
|
43
|
+
const queryKey = getThreadsQueryKey(e.conversation_ext_id);
|
|
44
|
+
const refreshed = queryClient.invalidateQueries({ queryKey });
|
|
45
|
+
void invalidateConversationLists(queryClient);
|
|
46
|
+
await refreshed;
|
|
47
|
+
const cached = queryClient.getQueryData(
|
|
48
|
+
queryKey
|
|
49
|
+
);
|
|
50
|
+
if (cached && e.message_ext_id && !cached.threads.some((thread) => thread.history.some((m) => m.external_id === e.message_ext_id))) {
|
|
51
|
+
await queryClient.refetchQueries({ queryKey, type: "active" });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
export {
|
|
55
|
+
applyConversationEvent
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=conversation-events.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/chat/conversation-events.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * The conversation events of the server's WebSocket, applied to the cache: a run that ended\n * (`response_complete`), a message somebody else posted (`conversation.message_posted`), a\n * generated title (`conversation.title_updated`) and a thread bound to a document, rebound or\n * unbound by another member or device (`conversation.document_binding_changed`). The cache half\n * of what a host does on them; the\n * session half (generation, the queue box, notices) stays with the host until the engine moves.\n */\n\nimport type { QueryClient } from '@tanstack/react-query'\nimport { arbiQueryKeys } from '../hooks'\nimport { invalidateConversationLists, patchConversation } from '../conversation-list'\nimport {\n getThreadsQueryKey,\n markMessageAsFailed,\n updateUserMessageStateInCache,\n} from './conversation-cache'\n\n/** The conversation events of the server's WebSocket, as `applyConversationEvent` takes them. */\nexport type ConversationEvent =\n | {\n type: 'response_complete'\n /** The conversation the run belongs to (the host resolves it when the event lacks it). */\n conversation_ext_id?: string | null\n response_id?: string | null\n status?: string | null\n /** The follow-up this run answered: no longer waiting. */\n user_message_id?: string | null\n }\n | { type: 'conversation.message_posted'; conversation_ext_id?: string; message_ext_id?: string }\n | { type: 'conversation.title_updated'; conversation_ext_id?: string; title?: string | null }\n | { type: 'conversation.document_binding_changed'; conversation_ext_id?: string }\n\n/** Apply one conversation event of the server's WebSocket to the cache. Other messages are ignored. */\nexport async function applyConversationEvent(\n queryClient: QueryClient,\n event: { type: string; [field: string]: unknown }\n): Promise<void> {\n const e = event as ConversationEvent\n if (e.type === 'response_complete') return applyRunEnded(queryClient, e)\n if (e.type === 'conversation.message_posted') return applyMessagePosted(queryClient, e)\n if (e.type === 'conversation.title_updated' && e.conversation_ext_id) {\n // The generated title, committed after the first turn: the row inserted at the first message\n // (title null) would otherwise stay untitled until the list is read again.\n patchConversation(queryClient, e.conversation_ext_id, { title: e.title ?? null })\n }\n if (e.type === 'conversation.document_binding_changed' && e.conversation_ext_id) {\n // Ids only: the binding is read again under this reader's access (a document they cannot open\n // comes back as unavailable, never by its id).\n void queryClient.invalidateQueries({ queryKey: getThreadsQueryKey(e.conversation_ext_id) })\n void invalidateConversationLists(queryClient)\n }\n}\n\nfunction applyRunEnded(\n queryClient: QueryClient,\n e: Extract<ConversationEvent, { type: 'response_complete' }>\n): void {\n const conversationId = e.conversation_ext_id\n if (!conversationId) return\n const failed = e.status === 'failed'\n if (e.user_message_id) {\n updateUserMessageStateInCache(\n queryClient,\n conversationId,\n e.user_message_id,\n 'completed',\n false\n )\n }\n // A failed answer shows failed at once, so nothing replies to it.\n if (failed && e.response_id) markMessageAsFailed(queryClient, conversationId, e.response_id)\n // The list was patched to in progress when the turn started.\n patchConversation(queryClient, conversationId, {\n last_message_status: failed ? 'failed' : 'completed',\n })\n // The persisted last-turn speaker and time, background replies included.\n void invalidateConversationLists(queryClient)\n void queryClient.invalidateQueries({ queryKey: getThreadsQueryKey(conversationId) })\n // A completed run spent AI usage.\n if (!failed) void queryClient.invalidateQueries({ queryKey: arbiQueryKeys.userUsageToday() })\n}\n\nasync function applyMessagePosted(\n queryClient: QueryClient,\n e: Extract<ConversationEvent, { type: 'conversation.message_posted' }>\n): Promise<void> {\n if (!e.conversation_ext_id) return\n const queryKey = getThreadsQueryKey(e.conversation_ext_id)\n const refreshed = queryClient.invalidateQueries({ queryKey })\n void invalidateConversationLists(queryClient)\n await refreshed\n // A burst can arrive while an earlier refresh is in flight: check that the posted message reached\n // the cache, rather than leaving that earlier snapshot visible.\n const cached = queryClient.getQueryData<{ threads: { history: { external_id: string }[] }[] }>(\n queryKey\n )\n if (\n cached &&\n e.message_ext_id &&\n !cached.threads.some((thread) => thread.history.some((m) => m.external_id === e.message_ext_id))\n ) {\n await queryClient.refetchQueries({ queryKey, type: 'active' })\n }\n}\n"],
|
|
5
|
+
"mappings": "AAUA,SAAS,qBAAqB;AAC9B,SAAS,6BAA6B,yBAAyB;AAC/D;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAkBP,eAAsB,uBACpB,aACA,OACe;AACf,QAAM,IAAI;AACV,MAAI,EAAE,SAAS,oBAAqB,QAAO,cAAc,aAAa,CAAC;AACvE,MAAI,EAAE,SAAS,8BAA+B,QAAO,mBAAmB,aAAa,CAAC;AACtF,MAAI,EAAE,SAAS,gCAAgC,EAAE,qBAAqB;AAGpE,sBAAkB,aAAa,EAAE,qBAAqB,EAAE,OAAO,EAAE,SAAS,KAAK,CAAC;AAAA,EAClF;AACA,MAAI,EAAE,SAAS,2CAA2C,EAAE,qBAAqB;AAG/E,SAAK,YAAY,kBAAkB,EAAE,UAAU,mBAAmB,EAAE,mBAAmB,EAAE,CAAC;AAC1F,SAAK,4BAA4B,WAAW;AAAA,EAC9C;AACF;AAEA,SAAS,cACP,aACA,GACM;AACN,QAAM,iBAAiB,EAAE;AACzB,MAAI,CAAC,eAAgB;AACrB,QAAM,SAAS,EAAE,WAAW;AAC5B,MAAI,EAAE,iBAAiB;AACrB;AAAA,MACE;AAAA,MACA;AAAA,MACA,EAAE;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,UAAU,EAAE,YAAa,qBAAoB,aAAa,gBAAgB,EAAE,WAAW;AAE3F,oBAAkB,aAAa,gBAAgB;AAAA,IAC7C,qBAAqB,SAAS,WAAW;AAAA,EAC3C,CAAC;AAED,OAAK,4BAA4B,WAAW;AAC5C,OAAK,YAAY,kBAAkB,EAAE,UAAU,mBAAmB,cAAc,EAAE,CAAC;AAEnF,MAAI,CAAC,OAAQ,MAAK,YAAY,kBAAkB,EAAE,UAAU,cAAc,eAAe,EAAE,CAAC;AAC9F;AAEA,eAAe,mBACb,aACA,GACe;AACf,MAAI,CAAC,EAAE,oBAAqB;AAC5B,QAAM,WAAW,mBAAmB,EAAE,mBAAmB;AACzD,QAAM,YAAY,YAAY,kBAAkB,EAAE,SAAS,CAAC;AAC5D,OAAK,4BAA4B,WAAW;AAC5C,QAAM;AAGN,QAAM,SAAS,YAAY;AAAA,IACzB;AAAA,EACF;AACA,MACE,UACA,EAAE,kBACF,CAAC,OAAO,QAAQ,KAAK,CAAC,WAAW,OAAO,QAAQ,KAAK,CAAC,MAAM,EAAE,gBAAgB,EAAE,cAAc,CAAC,GAC/F;AACA,UAAM,YAAY,eAAe,EAAE,UAAU,MAAM,SAAS,CAAC;AAAA,EAC/D;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
import { getUserDisplayName } from "../users/user-display.js";
|
|
3
|
+
import { arbiQueryKeys } from "../hooks.js";
|
|
4
|
+
import { useAssistantName } from "../host/assistant-copy.js";
|
|
5
|
+
import { findConversation, isConversationShared } from "../conversation-list.js";
|
|
6
|
+
import { allConversationThreads } from "./conversation-cache.js";
|
|
7
|
+
import {
|
|
8
|
+
extractMentions,
|
|
9
|
+
linkMentions
|
|
10
|
+
} from "./mentions.js";
|
|
11
|
+
const ASSISTANT_MENTION_LABEL = "ARBI";
|
|
12
|
+
function assistantLabels(assistantName = ASSISTANT_MENTION_LABEL) {
|
|
13
|
+
return assistantName.toLowerCase() === ASSISTANT_MENTION_LABEL.toLowerCase() ? [assistantName] : [assistantName, ASSISTANT_MENTION_LABEL];
|
|
14
|
+
}
|
|
15
|
+
function useLinkMentions() {
|
|
16
|
+
const assistantName = useAssistantName();
|
|
17
|
+
return useCallback(
|
|
18
|
+
(content, mentions) => linkMentions(content, mentions, [assistantName]),
|
|
19
|
+
[assistantName]
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
function buildMentionCandidates(users, currentUserId, assistantName = ASSISTANT_MENTION_LABEL) {
|
|
23
|
+
const people = users.filter((wu) => !wu.agent_ext_id && wu.user.external_id !== currentUserId).map((wu) => ({
|
|
24
|
+
id: wu.user.external_id,
|
|
25
|
+
kind: "user",
|
|
26
|
+
label: getUserDisplayName(wu.user),
|
|
27
|
+
description: wu.user.email
|
|
28
|
+
})).sort((a, b) => a.label.localeCompare(b.label));
|
|
29
|
+
return [{ id: "assistant", kind: "assistant", label: assistantName }, ...people];
|
|
30
|
+
}
|
|
31
|
+
function cachedMentionCandidates(queryClient, workspaceId, currentUserId, assistantName = ASSISTANT_MENTION_LABEL) {
|
|
32
|
+
const users = workspaceId && queryClient.getQueryData(arbiQueryKeys.workspaceUsers(workspaceId)) || [];
|
|
33
|
+
const aliases = assistantLabels(assistantName).slice(1).map((label) => ({ id: "assistant", kind: "assistant", label }));
|
|
34
|
+
return [...buildMentionCandidates(users, currentUserId, assistantName), ...aliases];
|
|
35
|
+
}
|
|
36
|
+
function cachedAssistantMode(queryClient, conversationId, newMode) {
|
|
37
|
+
if (!conversationId) return newMode;
|
|
38
|
+
const threads = queryClient.getQueriesData(allConversationThreads).map(([, data]) => data).find((data) => data?.conversation_ext_id === conversationId);
|
|
39
|
+
if (threads?.assistant_mode) return threads.assistant_mode;
|
|
40
|
+
return findConversation(queryClient, conversationId)?.assistant_mode ?? "always";
|
|
41
|
+
}
|
|
42
|
+
function isCommentToPeople(queryClient, conversationId, content, candidates) {
|
|
43
|
+
const mentioned = extractMentions(content, candidates);
|
|
44
|
+
if (mentioned.some((c) => c.kind === "assistant")) return false;
|
|
45
|
+
if (isConversationShared(queryClient, conversationId)) return true;
|
|
46
|
+
if (mentioned.some((c) => c.kind === "user")) return true;
|
|
47
|
+
return !!conversationId && cachedAssistantMode(queryClient, conversationId, "always") === "mentioned";
|
|
48
|
+
}
|
|
49
|
+
export {
|
|
50
|
+
ASSISTANT_MENTION_LABEL,
|
|
51
|
+
assistantLabels,
|
|
52
|
+
buildMentionCandidates,
|
|
53
|
+
cachedAssistantMode,
|
|
54
|
+
cachedMentionCandidates,
|
|
55
|
+
isCommentToPeople,
|
|
56
|
+
useLinkMentions
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=conversation-mentions.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/chat/conversation-mentions.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Who can be @mentioned in a conversation, which mode it is in, and how a message is routed: to\n * ARBI (a turn) or to the people in the thread (a comment). The send path reads the caches here, so\n * it routes exactly as the composer shows.\n */\n\nimport { useCallback } from 'react'\nimport type { QueryClient } from '@tanstack/react-query'\nimport type { components } from '@arbidocs/client'\nimport { getUserDisplayName } from '../users/user-display'\nimport { arbiQueryKeys } from '../hooks'\nimport { useAssistantName } from '../host/assistant-copy'\nimport { findConversation, isConversationShared } from '../conversation-list'\nimport { allConversationThreads } from './conversation-cache'\nimport {\n extractMentions,\n linkMentions,\n type MentionCandidate,\n type MessageMentionRef,\n} from './mentions'\n\ntype WorkspaceUser = components['schemas']['WorkspaceUserResponse']\ntype ThreadsResponse = components['schemas']['ThreadsResponse']\n\n/** When the assistant answers in a conversation: every message, or only when @mentioned. */\nexport type AssistantMode = components['schemas']['AssistantMode']\n\n/**\n * What the assistant is called in the composer when the host names it nothing else\n * (`ArbiHostConfig.assistantName`). The server stores this label with every assistant mention.\n */\nexport const ASSISTANT_MENTION_LABEL = 'ARBI'\n\n/**\n * Every name the assistant answers to: the host's, and \"ARBI\" (the server's stored label, and what\n * people may still type out of habit under a host's own name).\n */\nexport function assistantLabels(assistantName: string = ASSISTANT_MENTION_LABEL): string[] {\n return assistantName.toLowerCase() === ASSISTANT_MENTION_LABEL.toLowerCase()\n ? [assistantName]\n : [assistantName, ASSISTANT_MENTION_LABEL]\n}\n\n/**\n * `linkMentions` on this site: a mention of the assistant typed with the host's name for it is a\n * chip as well as one under the server's stored label (earlier `@ARBI` mentions).\n */\nexport function useLinkMentions(): (\n content: string,\n mentions: ReadonlyArray<MessageMentionRef> | null | undefined\n) => string {\n const assistantName = useAssistantName()\n return useCallback(\n (content, mentions) => linkMentions(content, mentions, [assistantName]),\n [assistantName]\n )\n}\n\n/**\n * The mention candidates for a workspace: the assistant first (as `assistantName`), then every\n * human member except the current user (agents are not mentionable). People's labels use the\n * server's display-name rule so the inserted `@<label>` matches what the server stores.\n */\nexport function buildMentionCandidates(\n users: ReadonlyArray<WorkspaceUser>,\n currentUserId: string | null | undefined,\n assistantName: string = ASSISTANT_MENTION_LABEL\n): MentionCandidate[] {\n const people = users\n .filter((wu) => !wu.agent_ext_id && wu.user.external_id !== currentUserId)\n .map<MentionCandidate>((wu) => ({\n id: wu.user.external_id,\n kind: 'user',\n label: getUserDisplayName(wu.user),\n description: wu.user.email,\n }))\n .sort((a, b) => a.label.localeCompare(b.label))\n return [{ id: 'assistant', kind: 'assistant', label: assistantName }, ...people]\n}\n\n/**\n * A workspace's mention candidates for routing a send, from the cached member list: the menu's,\n * plus the assistant under \"ARBI\" when the host names it otherwise, so a typed `@ARBI` still\n * reaches it (the menu offers only the host's name).\n */\nexport function cachedMentionCandidates(\n queryClient: QueryClient,\n workspaceId: string | null | undefined,\n currentUserId: string | null | undefined,\n assistantName: string = ASSISTANT_MENTION_LABEL\n): MentionCandidate[] {\n const users =\n (workspaceId &&\n queryClient.getQueryData<WorkspaceUser[]>(arbiQueryKeys.workspaceUsers(workspaceId))) ||\n []\n const aliases = assistantLabels(assistantName)\n .slice(1)\n .map<MentionCandidate>((label) => ({ id: 'assistant', kind: 'assistant', label }))\n return [...buildMentionCandidates(users, currentUserId, assistantName), ...aliases]\n}\n\n/**\n * The assistant mode of a conversation from whatever is cached: its threads response (always\n * present once it is open, even when it is not in the cached list, e.g. a thread someone just\n * shared by mentioning you), else its list row. A conversation not created yet uses `newMode`, the\n * mode chosen in the composer.\n */\nexport function cachedAssistantMode(\n queryClient: QueryClient,\n conversationId: string | null | undefined,\n newMode: AssistantMode\n): AssistantMode {\n if (!conversationId) return newMode\n const threads = queryClient\n .getQueriesData<ThreadsResponse>(allConversationThreads)\n .map(([, data]) => data)\n .find((data) => data?.conversation_ext_id === conversationId)\n if (threads?.assistant_mode) return threads.assistant_mode\n return findConversation(queryClient, conversationId)?.assistant_mode ?? 'always'\n}\n\n/**\n * Whether a message is a comment to people rather than a prompt for ARBI. The one rule for\n * routing a message: an @mention of ARBI always addresses ARBI. Otherwise it's a comment in a\n * shared thread, when it @mentions a person, or in a `mentioned`-mode thread (ARBI only on\n * @mention), solo or not: the mode the composer's toggle shows is the one the send follows, and a\n * group chat never calls ARBI unasked because this user's cached list doesn't show it shared yet.\n */\nexport function isCommentToPeople(\n queryClient: QueryClient,\n conversationId: string | null | undefined,\n content: string,\n candidates: ReadonlyArray<MentionCandidate>\n): boolean {\n const mentioned = extractMentions(content, candidates)\n if (mentioned.some((c) => c.kind === 'assistant')) return false\n if (isConversationShared(queryClient, conversationId)) return true\n if (mentioned.some((c) => c.kind === 'user')) return true\n return (\n !!conversationId && cachedAssistantMode(queryClient, conversationId, 'always') === 'mentioned'\n )\n}\n"],
|
|
5
|
+
"mappings": "AAMA,SAAS,mBAAmB;AAG5B,SAAS,0BAA0B;AACnC,SAAS,qBAAqB;AAC9B,SAAS,wBAAwB;AACjC,SAAS,kBAAkB,4BAA4B;AACvD,SAAS,8BAA8B;AACvC;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAYA,MAAM,0BAA0B;AAMhC,SAAS,gBAAgB,gBAAwB,yBAAmC;AACzF,SAAO,cAAc,YAAY,MAAM,wBAAwB,YAAY,IACvE,CAAC,aAAa,IACd,CAAC,eAAe,uBAAuB;AAC7C;AAMO,SAAS,kBAGJ;AACV,QAAM,gBAAgB,iBAAiB;AACvC,SAAO;AAAA,IACL,CAAC,SAAS,aAAa,aAAa,SAAS,UAAU,CAAC,aAAa,CAAC;AAAA,IACtE,CAAC,aAAa;AAAA,EAChB;AACF;AAOO,SAAS,uBACd,OACA,eACA,gBAAwB,yBACJ;AACpB,QAAM,SAAS,MACZ,OAAO,CAAC,OAAO,CAAC,GAAG,gBAAgB,GAAG,KAAK,gBAAgB,aAAa,EACxE,IAAsB,CAAC,QAAQ;AAAA,IAC9B,IAAI,GAAG,KAAK;AAAA,IACZ,MAAM;AAAA,IACN,OAAO,mBAAmB,GAAG,IAAI;AAAA,IACjC,aAAa,GAAG,KAAK;AAAA,EACvB,EAAE,EACD,KAAK,CAAC,GAAG,MAAM,EAAE,MAAM,cAAc,EAAE,KAAK,CAAC;AAChD,SAAO,CAAC,EAAE,IAAI,aAAa,MAAM,aAAa,OAAO,cAAc,GAAG,GAAG,MAAM;AACjF;AAOO,SAAS,wBACd,aACA,aACA,eACA,gBAAwB,yBACJ;AACpB,QAAM,QACH,eACC,YAAY,aAA8B,cAAc,eAAe,WAAW,CAAC,KACrF,CAAC;AACH,QAAM,UAAU,gBAAgB,aAAa,EAC1C,MAAM,CAAC,EACP,IAAsB,CAAC,WAAW,EAAE,IAAI,aAAa,MAAM,aAAa,MAAM,EAAE;AACnF,SAAO,CAAC,GAAG,uBAAuB,OAAO,eAAe,aAAa,GAAG,GAAG,OAAO;AACpF;AAQO,SAAS,oBACd,aACA,gBACA,SACe;AACf,MAAI,CAAC,eAAgB,QAAO;AAC5B,QAAM,UAAU,YACb,eAAgC,sBAAsB,EACtD,IAAI,CAAC,CAAC,EAAE,IAAI,MAAM,IAAI,EACtB,KAAK,CAAC,SAAS,MAAM,wBAAwB,cAAc;AAC9D,MAAI,SAAS,eAAgB,QAAO,QAAQ;AAC5C,SAAO,iBAAiB,aAAa,cAAc,GAAG,kBAAkB;AAC1E;AASO,SAAS,kBACd,aACA,gBACA,SACA,YACS;AACT,QAAM,YAAY,gBAAgB,SAAS,UAAU;AACrD,MAAI,UAAU,KAAK,CAAC,MAAM,EAAE,SAAS,WAAW,EAAG,QAAO;AAC1D,MAAI,qBAAqB,aAAa,cAAc,EAAG,QAAO;AAC9D,MAAI,UAAU,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,EAAG,QAAO;AACrD,SACE,CAAC,CAAC,kBAAkB,oBAAoB,aAAa,gBAAgB,QAAQ,MAAM;AAEvF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { arbiQueryKeys } from "../query-keys.js";
|
|
2
|
+
const byClient = /* @__PURE__ */ new WeakMap();
|
|
3
|
+
function bindingsOf(queryClient) {
|
|
4
|
+
let bindings = byClient.get(queryClient);
|
|
5
|
+
if (!bindings) {
|
|
6
|
+
bindings = { confirmed: /* @__PURE__ */ new Map(), observed: /* @__PURE__ */ new Map() };
|
|
7
|
+
byClient.set(queryClient, bindings);
|
|
8
|
+
}
|
|
9
|
+
return bindings;
|
|
10
|
+
}
|
|
11
|
+
function confirmConversationWorkspace(queryClient, conversationId, workspaceId) {
|
|
12
|
+
if (conversationId === "new") return;
|
|
13
|
+
bindingsOf(queryClient).confirmed.set(conversationId, workspaceId);
|
|
14
|
+
}
|
|
15
|
+
function observeConversationWorkspace(queryClient, conversationId, workspaceId) {
|
|
16
|
+
const { observed } = bindingsOf(queryClient);
|
|
17
|
+
if (conversationId !== "new" && !observed.has(conversationId))
|
|
18
|
+
observed.set(conversationId, workspaceId);
|
|
19
|
+
}
|
|
20
|
+
function listedWorkspaceOf(queryClient, conversationId) {
|
|
21
|
+
for (const [key, data] of queryClient.getQueriesData({
|
|
22
|
+
queryKey: arbiQueryKeys.allConversations()
|
|
23
|
+
})) {
|
|
24
|
+
const workspaceId = key[2];
|
|
25
|
+
if (key.length !== 3 || typeof workspaceId !== "string" || !Array.isArray(data)) continue;
|
|
26
|
+
if (data.some((row) => row?.external_id === conversationId)) return workspaceId;
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
function conversationWorkspaceOf(queryClient, conversationId) {
|
|
31
|
+
if (!conversationId || conversationId === "new") return null;
|
|
32
|
+
const { confirmed, observed } = bindingsOf(queryClient);
|
|
33
|
+
return confirmed.get(conversationId) ?? listedWorkspaceOf(queryClient, conversationId) ?? observed.get(conversationId) ?? null;
|
|
34
|
+
}
|
|
35
|
+
const watchedSessions = /* @__PURE__ */ new WeakMap();
|
|
36
|
+
function watchConversationWorkspaces(queryClient, session) {
|
|
37
|
+
const clients = watchedSessions.get(session) ?? /* @__PURE__ */ new WeakSet();
|
|
38
|
+
if (clients.has(queryClient)) return;
|
|
39
|
+
clients.add(queryClient);
|
|
40
|
+
watchedSessions.set(session, clients);
|
|
41
|
+
let last = null;
|
|
42
|
+
const record = () => {
|
|
43
|
+
const { conversationId, workspaceId } = session.getState();
|
|
44
|
+
if (conversationId === last) return;
|
|
45
|
+
last = conversationId;
|
|
46
|
+
if (conversationId && workspaceId)
|
|
47
|
+
observeConversationWorkspace(queryClient, conversationId, workspaceId);
|
|
48
|
+
};
|
|
49
|
+
record();
|
|
50
|
+
session.subscribe(record);
|
|
51
|
+
}
|
|
52
|
+
export {
|
|
53
|
+
confirmConversationWorkspace,
|
|
54
|
+
conversationWorkspaceOf,
|
|
55
|
+
observeConversationWorkspace,
|
|
56
|
+
watchConversationWorkspaces
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=conversation-workspace.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/chat/conversation-workspace.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * The workspace each conversation is in, so a turn names its conversation's workspace rather than\n * whichever one the surface (or the server session) is on when it is sent. A docked or scoped chat\n * keeps its open conversation across a workspace switch, and a deferred follow-up is sent after a\n * long turn: both must keep writing in the conversation's own workspace.\n *\n * Kept per query client (a sign-out clears it with the cache), from, in order of trust:\n * 1. the server: the workspace a turn of the conversation was accepted in;\n * 2. the cached conversation lists, each of which is one workspace's;\n * 3. the workspace its session was in when the conversation was opened there.\n * The server stores a follow-up in its thread's workspace whatever is named, refusing a different\n * one with 409 `workspace_mismatch` (the SDK then sends it once more there), so a stale guess can\n * cost a round trip but can never write under another workspace's key.\n */\n\nimport type { QueryClient } from '@tanstack/react-query'\nimport { arbiQueryKeys } from '../query-keys'\n\ninterface Bindings {\n confirmed: Map<string, string>\n observed: Map<string, string>\n}\n\nconst byClient = new WeakMap<QueryClient, Bindings>()\n\nfunction bindingsOf(queryClient: QueryClient): Bindings {\n let bindings = byClient.get(queryClient)\n if (!bindings) {\n bindings = { confirmed: new Map(), observed: new Map() }\n byClient.set(queryClient, bindings)\n }\n return bindings\n}\n\n/** The server accepted a turn of `conversationId` in `workspaceId`. */\nexport function confirmConversationWorkspace(\n queryClient: QueryClient,\n conversationId: string,\n workspaceId: string\n): void {\n if (conversationId === 'new') return\n bindingsOf(queryClient).confirmed.set(conversationId, workspaceId)\n}\n\n/** `conversationId` was opened while its session was in `workspaceId` (kept only if unknown). */\nexport function observeConversationWorkspace(\n queryClient: QueryClient,\n conversationId: string,\n workspaceId: string\n): void {\n const { observed } = bindingsOf(queryClient)\n if (conversationId !== 'new' && !observed.has(conversationId))\n observed.set(conversationId, workspaceId)\n}\n\n/** The workspace whose cached conversation list holds `conversationId`, if one does. */\nfunction listedWorkspaceOf(queryClient: QueryClient, conversationId: string): string | null {\n for (const [key, data] of queryClient.getQueriesData<Array<{ external_id?: string }>>({\n queryKey: arbiQueryKeys.allConversations(),\n })) {\n const workspaceId = key[2]\n if (key.length !== 3 || typeof workspaceId !== 'string' || !Array.isArray(data)) continue\n if (data.some((row) => row?.external_id === conversationId)) return workspaceId\n }\n return null\n}\n\n/** The workspace `conversationId` is in, as far as this client knows (null: unknown). */\nexport function conversationWorkspaceOf(\n queryClient: QueryClient,\n conversationId: string | null | undefined\n): string | null {\n if (!conversationId || conversationId === 'new') return null\n const { confirmed, observed } = bindingsOf(queryClient)\n return (\n confirmed.get(conversationId) ??\n listedWorkspaceOf(queryClient, conversationId) ??\n observed.get(conversationId) ??\n null\n )\n}\n\ninterface ObservableSession {\n getState(): { conversationId: string | null; workspaceId: string | null }\n subscribe(listener: () => void): () => void\n}\n\nconst watchedSessions = new WeakMap<ObservableSession, WeakSet<QueryClient>>()\n\n/**\n * Record, once per session store, the workspace each conversation is opened in: the session's\n * workspace at that moment. A later switch of the session's workspace does not move it.\n */\nexport function watchConversationWorkspaces(\n queryClient: QueryClient,\n session: ObservableSession\n): void {\n const clients = watchedSessions.get(session) ?? new WeakSet<QueryClient>()\n if (clients.has(queryClient)) return\n clients.add(queryClient)\n watchedSessions.set(session, clients)\n let last: string | null = null\n const record = () => {\n const { conversationId, workspaceId } = session.getState()\n if (conversationId === last) return\n last = conversationId\n if (conversationId && workspaceId)\n observeConversationWorkspace(queryClient, conversationId, workspaceId)\n }\n record()\n session.subscribe(record)\n}\n"],
|
|
5
|
+
"mappings": "AAgBA,SAAS,qBAAqB;AAO9B,MAAM,WAAW,oBAAI,QAA+B;AAEpD,SAAS,WAAW,aAAoC;AACtD,MAAI,WAAW,SAAS,IAAI,WAAW;AACvC,MAAI,CAAC,UAAU;AACb,eAAW,EAAE,WAAW,oBAAI,IAAI,GAAG,UAAU,oBAAI,IAAI,EAAE;AACvD,aAAS,IAAI,aAAa,QAAQ;AAAA,EACpC;AACA,SAAO;AACT;AAGO,SAAS,6BACd,aACA,gBACA,aACM;AACN,MAAI,mBAAmB,MAAO;AAC9B,aAAW,WAAW,EAAE,UAAU,IAAI,gBAAgB,WAAW;AACnE;AAGO,SAAS,6BACd,aACA,gBACA,aACM;AACN,QAAM,EAAE,SAAS,IAAI,WAAW,WAAW;AAC3C,MAAI,mBAAmB,SAAS,CAAC,SAAS,IAAI,cAAc;AAC1D,aAAS,IAAI,gBAAgB,WAAW;AAC5C;AAGA,SAAS,kBAAkB,aAA0B,gBAAuC;AAC1F,aAAW,CAAC,KAAK,IAAI,KAAK,YAAY,eAAgD;AAAA,IACpF,UAAU,cAAc,iBAAiB;AAAA,EAC3C,CAAC,GAAG;AACF,UAAM,cAAc,IAAI,CAAC;AACzB,QAAI,IAAI,WAAW,KAAK,OAAO,gBAAgB,YAAY,CAAC,MAAM,QAAQ,IAAI,EAAG;AACjF,QAAI,KAAK,KAAK,CAAC,QAAQ,KAAK,gBAAgB,cAAc,EAAG,QAAO;AAAA,EACtE;AACA,SAAO;AACT;AAGO,SAAS,wBACd,aACA,gBACe;AACf,MAAI,CAAC,kBAAkB,mBAAmB,MAAO,QAAO;AACxD,QAAM,EAAE,WAAW,SAAS,IAAI,WAAW,WAAW;AACtD,SACE,UAAU,IAAI,cAAc,KAC5B,kBAAkB,aAAa,cAAc,KAC7C,SAAS,IAAI,cAAc,KAC3B;AAEJ;AAOA,MAAM,kBAAkB,oBAAI,QAAiD;AAMtE,SAAS,4BACd,aACA,SACM;AACN,QAAM,UAAU,gBAAgB,IAAI,OAAO,KAAK,oBAAI,QAAqB;AACzE,MAAI,QAAQ,IAAI,WAAW,EAAG;AAC9B,UAAQ,IAAI,WAAW;AACvB,kBAAgB,IAAI,SAAS,OAAO;AACpC,MAAI,OAAsB;AAC1B,QAAM,SAAS,MAAM;AACnB,UAAM,EAAE,gBAAgB,YAAY,IAAI,QAAQ,SAAS;AACzD,QAAI,mBAAmB,KAAM;AAC7B,WAAO;AACP,QAAI,kBAAkB;AACpB,mCAA6B,aAAa,gBAAgB,WAAW;AAAA,EACzE;AACA,SAAO;AACP,UAAQ,UAAU,MAAM;AAC1B;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
const MAX_QUERY_LENGTH = 40;
|
|
2
|
+
function findMentionQuery(text, caret) {
|
|
3
|
+
const before = text.slice(0, caret);
|
|
4
|
+
const at = before.lastIndexOf("@");
|
|
5
|
+
if (at < 0) return null;
|
|
6
|
+
if (at > 0 && !/\s/.test(before[at - 1])) return null;
|
|
7
|
+
const query = before.slice(at + 1);
|
|
8
|
+
if (query.length > MAX_QUERY_LENGTH || query.includes("\n") || query.startsWith(" ")) return null;
|
|
9
|
+
return { start: at, query };
|
|
10
|
+
}
|
|
11
|
+
function filterMentionCandidates(candidates, query) {
|
|
12
|
+
const q = query.trim().toLowerCase();
|
|
13
|
+
if (!q) return candidates.slice();
|
|
14
|
+
const scored = [];
|
|
15
|
+
for (const c of candidates) {
|
|
16
|
+
const label = c.label.toLowerCase();
|
|
17
|
+
if (label.startsWith(q)) scored.push({ c, score: 0 });
|
|
18
|
+
else if (label.split(/\s+/).some((word) => word.startsWith(q))) scored.push({ c, score: 1 });
|
|
19
|
+
else if (c.description?.toLowerCase().startsWith(q)) scored.push({ c, score: 2 });
|
|
20
|
+
}
|
|
21
|
+
return scored.sort((a, b) => a.score - b.score).map((s) => s.c);
|
|
22
|
+
}
|
|
23
|
+
function insertMention(text, start, caret, label) {
|
|
24
|
+
const inserted = `@${label} `;
|
|
25
|
+
return {
|
|
26
|
+
text: text.slice(0, start) + inserted + text.slice(caret),
|
|
27
|
+
caret: start + inserted.length
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function tokenRanges(text, label) {
|
|
31
|
+
const needle = `@${label}`;
|
|
32
|
+
const ranges = [];
|
|
33
|
+
let from = 0;
|
|
34
|
+
for (; ; ) {
|
|
35
|
+
const i = text.indexOf(needle, from);
|
|
36
|
+
if (i < 0) break;
|
|
37
|
+
const end = i + needle.length;
|
|
38
|
+
const startsToken = i === 0 || /\s|\(|\[/.test(text[i - 1]);
|
|
39
|
+
const endsToken = end === text.length || !/[\p{L}\p{N}_]/u.test(text[end]);
|
|
40
|
+
if (startsToken && endsToken) ranges.push([i, end]);
|
|
41
|
+
from = end;
|
|
42
|
+
}
|
|
43
|
+
return ranges;
|
|
44
|
+
}
|
|
45
|
+
function extractMentions(text, candidates) {
|
|
46
|
+
const taken = [];
|
|
47
|
+
const found = [];
|
|
48
|
+
const byLength = [...candidates].sort((a, b) => b.label.length - a.label.length);
|
|
49
|
+
for (const c of byLength) {
|
|
50
|
+
if (!c.label) continue;
|
|
51
|
+
for (const [from, to] of tokenRanges(text, c.label)) {
|
|
52
|
+
if (taken.some(([a, b]) => from < b && to > a)) continue;
|
|
53
|
+
taken.push([from, to]);
|
|
54
|
+
if (!found.some((f) => f.c.id === c.id)) found.push({ c, at: from });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return found.sort((a, b) => a.at - b.at).map((f) => f.c);
|
|
58
|
+
}
|
|
59
|
+
function toMessageMentions(mentioned) {
|
|
60
|
+
return mentioned.map(
|
|
61
|
+
(c) => c.kind === "assistant" ? { type: "assistant" } : { type: "user", user_ext_id: c.id }
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
const MENTION_HREF_PREFIX = "#mention-";
|
|
65
|
+
function escapeLinkText(label) {
|
|
66
|
+
return label.replace(/[[\]\\]/g, (ch) => `\\${ch}`);
|
|
67
|
+
}
|
|
68
|
+
function linkMentions(content, mentions, assistantLabels = []) {
|
|
69
|
+
if (!mentions || mentions.length === 0 || !content) return content;
|
|
70
|
+
const targets = [];
|
|
71
|
+
for (const m of mentions) {
|
|
72
|
+
const id = m.type === "assistant" ? "assistant" : m.user_ext_id;
|
|
73
|
+
if (!id) continue;
|
|
74
|
+
const labels = m.type === "assistant" ? [m.label ?? "", ...assistantLabels] : [m.label ?? ""];
|
|
75
|
+
for (const label of labels) if (label) targets.push({ label, id });
|
|
76
|
+
}
|
|
77
|
+
targets.sort((a, b) => b.label.length - a.label.length);
|
|
78
|
+
const replacements = [];
|
|
79
|
+
for (const { label, id } of targets) {
|
|
80
|
+
for (const [from, to] of tokenRanges(content, label)) {
|
|
81
|
+
if (replacements.some((r) => from < r.to && to > r.from)) continue;
|
|
82
|
+
replacements.push({
|
|
83
|
+
from,
|
|
84
|
+
to,
|
|
85
|
+
text: `[@${escapeLinkText(label)}](${MENTION_HREF_PREFIX}${id})`
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
replacements.sort((a, b) => b.from - a.from);
|
|
90
|
+
let out = content;
|
|
91
|
+
for (const r of replacements) out = out.slice(0, r.from) + r.text + out.slice(r.to);
|
|
92
|
+
return out;
|
|
93
|
+
}
|
|
94
|
+
function mentionFromHref(href) {
|
|
95
|
+
if (!href?.startsWith(MENTION_HREF_PREFIX)) return null;
|
|
96
|
+
const id = href.slice(MENTION_HREF_PREFIX.length);
|
|
97
|
+
if (!id) return null;
|
|
98
|
+
return { kind: id === "assistant" ? "assistant" : "user", id };
|
|
99
|
+
}
|
|
100
|
+
function hasMessageBody(value, recipientLabel = "ARBI") {
|
|
101
|
+
const text = value.trim().toLowerCase();
|
|
102
|
+
const labels = typeof recipientLabel === "string" ? [recipientLabel] : recipientLabel;
|
|
103
|
+
return !!text && !labels.some((label) => text === `@${label}`.toLowerCase());
|
|
104
|
+
}
|
|
105
|
+
export {
|
|
106
|
+
MENTION_HREF_PREFIX,
|
|
107
|
+
extractMentions,
|
|
108
|
+
filterMentionCandidates,
|
|
109
|
+
findMentionQuery,
|
|
110
|
+
hasMessageBody,
|
|
111
|
+
insertMention,
|
|
112
|
+
linkMentions,
|
|
113
|
+
mentionFromHref,
|
|
114
|
+
toMessageMentions
|
|
115
|
+
};
|
|
116
|
+
//# sourceMappingURL=mentions.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/chat/mentions.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * @mentions in chat text: pure helpers shared by the composer (autocomplete, extraction) and\n * the message renderer (chips). No React, no SDK.\n *\n * A mention lives in two places: the readable `@Label` text in the message content, and a\n * structured entry on the message (`{ type, user_ext_id, label }`) that the server reads to share\n * the conversation and notify. The composer only ever inserts `@<label>` for a known candidate,\n * so the structured list can be recovered from the text at send time ({@link extractMentions});\n * the renderer turns each stored mention back into a chip ({@link linkMentions}).\n */\n\n/** Who can be mentioned: a workspace member, or the assistant. */\nexport type MentionKind = 'user' | 'assistant'\n\n/** One entry of the mention autocomplete. */\nexport interface MentionCandidate {\n /** User external id (`usr-\u2026`) for a person; any stable key (e.g. `assistant`) for the assistant. */\n id: string\n kind: MentionKind\n /** Inserted as `@<label>`. For people this must be the server's display name (given + family). */\n label: string\n /** Secondary line in the menu (email, role, \u2026). */\n description?: string\n}\n\n/** The structured mention a message carries (the API's `MessageMention`). */\nexport interface MessageMentionRef {\n type: MentionKind\n user_ext_id?: string | null\n label?: string | null\n}\n\n/** Longest text after `@` that still counts as a query in progress. */\nconst MAX_QUERY_LENGTH = 40\n\n/**\n * The `@query` the caret is in, if any: the `@` must start the text or follow whitespace, and the\n * query may contain spaces (names do) but no newline. Returns the index of the `@` and the query.\n */\nexport function findMentionQuery(\n text: string,\n caret: number\n): { start: number; query: string } | null {\n const before = text.slice(0, caret)\n const at = before.lastIndexOf('@')\n if (at < 0) return null\n if (at > 0 && !/\\s/.test(before[at - 1])) return null\n const query = before.slice(at + 1)\n if (query.length > MAX_QUERY_LENGTH || query.includes('\\n') || query.startsWith(' ')) return null\n return { start: at, query }\n}\n\n/** Candidates matching a query: label prefix (or word-prefix) matches, prefix matches first. */\nexport function filterMentionCandidates(\n candidates: ReadonlyArray<MentionCandidate>,\n query: string\n): MentionCandidate[] {\n const q = query.trim().toLowerCase()\n if (!q) return candidates.slice()\n const scored: Array<{ c: MentionCandidate; score: number }> = []\n for (const c of candidates) {\n const label = c.label.toLowerCase()\n if (label.startsWith(q)) scored.push({ c, score: 0 })\n else if (label.split(/\\s+/).some((word) => word.startsWith(q))) scored.push({ c, score: 1 })\n else if (c.description?.toLowerCase().startsWith(q)) scored.push({ c, score: 2 })\n }\n return scored.sort((a, b) => a.score - b.score).map((s) => s.c)\n}\n\n/** Replace the `@query` at `start\u2026caret` with `@<label> `; returns the new text and caret. */\nexport function insertMention(\n text: string,\n start: number,\n caret: number,\n label: string\n): { text: string; caret: number } {\n const inserted = `@${label} `\n return {\n text: text.slice(0, start) + inserted + text.slice(caret),\n caret: start + inserted.length,\n }\n}\n\n/** Every `[from, to)` range where `@<label>` occurs as a whole token. */\nfunction tokenRanges(text: string, label: string): Array<[number, number]> {\n const needle = `@${label}`\n const ranges: Array<[number, number]> = []\n let from = 0\n for (;;) {\n const i = text.indexOf(needle, from)\n if (i < 0) break\n const end = i + needle.length\n const startsToken = i === 0 || /\\s|\\(|\\[/.test(text[i - 1])\n const endsToken = end === text.length || !/[\\p{L}\\p{N}_]/u.test(text[end])\n if (startsToken && endsToken) ranges.push([i, end])\n from = end\n }\n return ranges\n}\n\n/**\n * The candidates mentioned in `text`, in order of first appearance. Longer labels win overlaps,\n * so `@Bob Smith` is Bob Smith, not a separate `@Bob`.\n */\nexport function extractMentions(\n text: string,\n candidates: ReadonlyArray<MentionCandidate>\n): MentionCandidate[] {\n const taken: Array<[number, number]> = []\n const found: Array<{ c: MentionCandidate; at: number }> = []\n const byLength = [...candidates].sort((a, b) => b.label.length - a.label.length)\n for (const c of byLength) {\n if (!c.label) continue\n for (const [from, to] of tokenRanges(text, c.label)) {\n if (taken.some(([a, b]) => from < b && to > a)) continue\n taken.push([from, to])\n if (!found.some((f) => f.c.id === c.id)) found.push({ c, at: from })\n }\n }\n return found.sort((a, b) => a.at - b.at).map((f) => f.c)\n}\n\n/** The API payload for mentioned candidates. */\nexport function toMessageMentions(mentioned: ReadonlyArray<MentionCandidate>): MessageMentionRef[] {\n return mentioned.map((c) =>\n c.kind === 'assistant' ? { type: 'assistant' } : { type: 'user', user_ext_id: c.id }\n )\n}\n\n/** Fragment prefix of the links {@link linkMentions} writes. */\nexport const MENTION_HREF_PREFIX = '#mention-'\n\n/** Escape the characters that would end a markdown link text early. */\nfunction escapeLinkText(label: string): string {\n return label.replace(/[[\\]\\\\]/g, (ch) => `\\\\${ch}`)\n}\n\n/**\n * Turn each stored mention's `@<label>` in `content` into a markdown link\n * `[@<label>](#mention-<id>)`, so a markdown renderer can draw it as a chip (see\n * {@link mentionFromHref}). Text that no longer matches (a renamed user) stays plain text.\n * `assistantLabels` lists other names the assistant may have been mentioned by.\n */\nexport function linkMentions(\n content: string,\n mentions: ReadonlyArray<MessageMentionRef> | null | undefined,\n assistantLabels: ReadonlyArray<string> = []\n): string {\n if (!mentions || mentions.length === 0 || !content) return content\n const targets: Array<{ label: string; id: string }> = []\n for (const m of mentions) {\n const id = m.type === 'assistant' ? 'assistant' : m.user_ext_id\n if (!id) continue\n const labels = m.type === 'assistant' ? [m.label ?? '', ...assistantLabels] : [m.label ?? '']\n for (const label of labels) if (label) targets.push({ label, id })\n }\n targets.sort((a, b) => b.label.length - a.label.length)\n const replacements: Array<{ from: number; to: number; text: string }> = []\n for (const { label, id } of targets) {\n for (const [from, to] of tokenRanges(content, label)) {\n if (replacements.some((r) => from < r.to && to > r.from)) continue\n replacements.push({\n from,\n to,\n text: `[@${escapeLinkText(label)}](${MENTION_HREF_PREFIX}${id})`,\n })\n }\n }\n replacements.sort((a, b) => b.from - a.from)\n let out = content\n for (const r of replacements) out = out.slice(0, r.from) + r.text + out.slice(r.to)\n return out\n}\n\n/** The mention a `#mention-\u2026` href points at, or null for any other href. */\nexport function mentionFromHref(\n href: string | null | undefined\n): { kind: MentionKind; id: string } | null {\n if (!href?.startsWith(MENTION_HREF_PREFIX)) return null\n const id = href.slice(MENTION_HREF_PREFIX.length)\n if (!id) return null\n return { kind: id === 'assistant' ? 'assistant' : 'user', id }\n}\n\n/** A recipient alone (by any of its labels) is not a message. */\nexport function hasMessageBody(\n value: string,\n recipientLabel: string | ReadonlyArray<string> = 'ARBI'\n): boolean {\n const text = value.trim().toLowerCase()\n const labels = typeof recipientLabel === 'string' ? [recipientLabel] : recipientLabel\n return !!text && !labels.some((label) => text === `@${label}`.toLowerCase())\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { useEffect, useRef, useSyncExternalStore } from "react";
|
|
2
|
+
import { parseVersionRef } from "../artifacts/versions.js";
|
|
3
|
+
function opensInWord(doc) {
|
|
4
|
+
return !!doc && (doc.wp_type === "artifact" || !!doc.file_name?.toLowerCase().endsWith(".docx"));
|
|
5
|
+
}
|
|
6
|
+
function savedDocumentIdFor(input) {
|
|
7
|
+
const { documentId, isDraft, isStreaming, isBlobArtifact, documentData } = input;
|
|
8
|
+
if (!documentId || isDraft || isStreaming || isBlobArtifact) return null;
|
|
9
|
+
if (!documentData || !opensInWord(documentData)) return null;
|
|
10
|
+
if (documentData.external_id !== documentId) return null;
|
|
11
|
+
return documentId;
|
|
12
|
+
}
|
|
13
|
+
let entries = [];
|
|
14
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
15
|
+
function subscribe(listener) {
|
|
16
|
+
listeners.add(listener);
|
|
17
|
+
return () => listeners.delete(listener);
|
|
18
|
+
}
|
|
19
|
+
function emit() {
|
|
20
|
+
listeners.forEach((l) => l());
|
|
21
|
+
}
|
|
22
|
+
const top = () => entries[entries.length - 1];
|
|
23
|
+
function useRegisterOpenDocument(registration) {
|
|
24
|
+
const latest = useRef(registration);
|
|
25
|
+
const { documentId, workspaceId, conversationId, ambient } = registration;
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
latest.current = registration;
|
|
28
|
+
});
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (documentId) emit();
|
|
31
|
+
}, [documentId, workspaceId, conversationId, ambient]);
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (!documentId) return;
|
|
34
|
+
const entry = { documentId, current: () => latest.current };
|
|
35
|
+
entries = [...entries, entry];
|
|
36
|
+
emit();
|
|
37
|
+
return () => {
|
|
38
|
+
entries = entries.filter((e) => e !== entry);
|
|
39
|
+
emit();
|
|
40
|
+
};
|
|
41
|
+
}, [documentId]);
|
|
42
|
+
}
|
|
43
|
+
function useOpenDocumentId(options) {
|
|
44
|
+
const workspaceId = options?.workspaceId ?? null;
|
|
45
|
+
return useSyncExternalStore(
|
|
46
|
+
subscribe,
|
|
47
|
+
() => openDocumentId({ workspaceId }),
|
|
48
|
+
() => null
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
function openDocumentId(options) {
|
|
52
|
+
const entry = top();
|
|
53
|
+
if (!entry || !inWorkspace(entry, options?.workspaceId)) return null;
|
|
54
|
+
return entry.documentId;
|
|
55
|
+
}
|
|
56
|
+
function inWorkspace(entry, workspaceId) {
|
|
57
|
+
const own = entry.current().workspaceId;
|
|
58
|
+
return !workspaceId || !own || own === workspaceId;
|
|
59
|
+
}
|
|
60
|
+
function pickTurnDocument({
|
|
61
|
+
boundDocumentId,
|
|
62
|
+
conversationId,
|
|
63
|
+
workspaceId
|
|
64
|
+
}) {
|
|
65
|
+
if (boundDocumentId) {
|
|
66
|
+
const entry = [...entries].reverse().find((e) => e.documentId === boundDocumentId);
|
|
67
|
+
return { documentId: boundDocumentId, entry };
|
|
68
|
+
}
|
|
69
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
70
|
+
const entry = entries[i];
|
|
71
|
+
if (!inWorkspace(entry, workspaceId)) continue;
|
|
72
|
+
const { ambient, conversationId: madeIn } = entry.current();
|
|
73
|
+
if (ambient || conversationId && madeIn === conversationId)
|
|
74
|
+
return { documentId: entry.documentId, entry };
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
function useTurnDocumentId(input) {
|
|
79
|
+
const { boundDocumentId = null, conversationId = null, workspaceId = null } = input;
|
|
80
|
+
return useSyncExternalStore(
|
|
81
|
+
subscribe,
|
|
82
|
+
() => pickTurnDocument({ boundDocumentId, conversationId, workspaceId })?.documentId ?? null,
|
|
83
|
+
() => null
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
function takeDocumentForTurn(input) {
|
|
87
|
+
const picked = pickTurnDocument(input);
|
|
88
|
+
if (!picked) return null;
|
|
89
|
+
const { documentId, entry } = picked;
|
|
90
|
+
if (entry) {
|
|
91
|
+
const { shownId, showLive } = entry.current();
|
|
92
|
+
if (shownId && shownId !== documentId && parseVersionRef(shownId).docId === documentId)
|
|
93
|
+
showLive?.();
|
|
94
|
+
}
|
|
95
|
+
return documentId;
|
|
96
|
+
}
|
|
97
|
+
export {
|
|
98
|
+
openDocumentId,
|
|
99
|
+
opensInWord,
|
|
100
|
+
savedDocumentIdFor,
|
|
101
|
+
takeDocumentForTurn,
|
|
102
|
+
useOpenDocumentId,
|
|
103
|
+
useRegisterOpenDocument,
|
|
104
|
+
useTurnDocumentId
|
|
105
|
+
};
|
|
106
|
+
//# sourceMappingURL=open-document.js.map
|