@arbidocs/react 0.5.110 → 0.5.112
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/PdfViewerImpl-QUSDLNNM.cjs +380 -0
- package/dist/PdfViewerImpl-QUSDLNNM.cjs.map +1 -0
- package/dist/{PdfViewer.d-bQH9yxFg.d.cts → PdfViewerImpl.d-B28hLEuj.d.ts} +8 -1
- 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.d.ts +1 -1
- 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.cjs +13 -13
- 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.cjs +48 -48
- 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/{chunk-W2FATOTX.cjs → chunk-3JAEX57E.cjs} +4 -4
- package/dist/{chunk-W2FATOTX.cjs.map → chunk-3JAEX57E.cjs.map} +1 -1
- package/dist/{chunk-HD5H2PPP.cjs → chunk-5TRUFWKT.cjs} +66 -66
- package/dist/{chunk-HD5H2PPP.cjs.map → chunk-5TRUFWKT.cjs.map} +1 -1
- package/dist/{chunk-Z3W4XFWB.cjs → chunk-C72FSQUE.cjs} +3 -3
- package/dist/{chunk-Z3W4XFWB.cjs.map → chunk-C72FSQUE.cjs.map} +1 -1
- package/dist/{chunk-LBAG7KL7.cjs → chunk-FQVNZCTD.cjs} +3 -3
- package/dist/{chunk-LBAG7KL7.cjs.map → chunk-FQVNZCTD.cjs.map} +1 -1
- package/dist/{chunk-RVUGSM65.cjs → chunk-GKGAPU6T.cjs} +44 -44
- package/dist/{chunk-RVUGSM65.cjs.map → chunk-GKGAPU6T.cjs.map} +1 -1
- package/dist/{chunk-7LIMHY56.cjs → chunk-O32T7XRD.cjs} +3 -3
- package/dist/{chunk-7LIMHY56.cjs.map → chunk-O32T7XRD.cjs.map} +1 -1
- package/dist/chunk-PWGSIM3F.cjs +291 -0
- package/dist/chunk-PWGSIM3F.cjs.map +1 -0
- package/dist/chunk-QP3WQSAA.cjs +23 -0
- package/dist/chunk-QP3WQSAA.cjs.map +1 -0
- package/dist/chunk-T5FZICXN.cjs +50 -0
- package/dist/chunk-T5FZICXN.cjs.map +1 -0
- package/dist/{chunk-QF2BW6HZ.cjs → chunk-UDDJIUHJ.cjs} +38 -38
- package/dist/{chunk-QF2BW6HZ.cjs.map → chunk-UDDJIUHJ.cjs.map} +1 -1
- package/dist/{chunk-5HDKL6XB.cjs → chunk-YMB6XUR2.cjs} +57 -57
- package/dist/{chunk-5HDKL6XB.cjs.map → chunk-YMB6XUR2.cjs.map} +1 -1
- 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.cjs +99 -99
- package/dist/document-tools/core.d.ts +2 -2
- 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.cjs +101 -101
- package/dist/document-tools/index.d.ts +1 -1
- 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.cjs +1689 -1619
- package/dist/index.cjs.map +1 -1
- package/dist/{index.d-BMhTH98a.d.ts → index.d-CYXcTKYt.d.ts} +1 -0
- package/dist/index.d.ts +38 -8
- package/dist/index.js +702 -17060
- package/dist/index.js.map +7 -1
- package/dist/lazy-chunk.d-B6YDLMKI.d.ts +31 -0
- package/dist/lazy-chunk.js +46 -0
- 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/{query-keys.d-ChgpJLPF.d.ts → query-keys.d-B1Am9tIF.d.ts} +1 -1
- package/dist/{chunk-6H3O63TQ.js → query-keys.js} +19 -32
- 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.cjs +37 -37
- 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.cjs +167 -154
- package/dist/ui/index.d.ts +2 -1
- package/dist/ui/index.js +290 -9
- 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.cjs +17 -0
- package/dist/viewers/PdfViewer.cjs.map +1 -0
- package/dist/viewers/PdfViewer.d.ts +9 -0
- package/dist/viewers/PdfViewer.js +20 -0
- package/dist/viewers/PdfViewer.js.map +7 -0
- package/dist/viewers/PdfViewerImpl.js +384 -0
- 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.cjs +79 -653
- package/dist/viewers/index.cjs.map +1 -1
- package/dist/viewers/index.d.ts +3 -1
- package/dist/viewers/index.js +60 -903
- 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 +12 -4
- package/dist/PdfViewer.d-bQH9yxFg.d.ts +0 -55
- 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-6H3O63TQ.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-CPQ3CU4B.js +0 -246
- package/dist/chunk-CPQ3CU4B.js.map +0 -1
- package/dist/chunk-DPYBZDJB.js.map +0 -1
- package/dist/chunk-DQALOQPI.js +0 -2766
- package/dist/chunk-DQALOQPI.js.map +0 -1
- package/dist/chunk-FZJMA32S.js +0 -1011
- package/dist/chunk-FZJMA32S.js.map +0 -1
- package/dist/chunk-H5M7FXLB.js +0 -2057
- package/dist/chunk-H5M7FXLB.js.map +0 -1
- package/dist/chunk-HDCRPPBW.js +0 -75
- package/dist/chunk-HDCRPPBW.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-P6WLV5UY.js +0 -644
- package/dist/chunk-P6WLV5UY.js.map +0 -1
- package/dist/chunk-PTOP7OHG.js.map +0 -1
- package/dist/chunk-SN5YV6FF.js +0 -11
- package/dist/chunk-SN5YV6FF.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-Y3MTRA7D.js +0 -97
- package/dist/chunk-Y3MTRA7D.js.map +0 -1
- package/dist/chunk-YNNAJJ5Z.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-BMhTH98a.d.cts +0 -2035
- package/dist/index.d-oR5FKZpJ.d.cts +0 -579
- package/dist/index.d.cts +0 -15893
- package/dist/model.d-CNtRWKVK.d.cts +0 -110
- package/dist/query-keys.d-ChgpJLPF.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 -25
- package/dist/useAudioRecorder.d-B9rlMI_E.d.cts +0 -778
- package/dist/viewers/index.d.cts +0 -260
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/session/chat.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * The session's chat state: the open conversation and its composer (line, draft, edit, model), the\n * turns running in each conversation, the documents and facts in each conversation's context, and\n * the agent bar's queue and run control. One implementation for every host: the in-memory session\n * store is built on it, and so is ARBI-frontend's (which keeps it across reloads).\n *\n * The open composer and the thread tabs move together: a thread tab change (`openThreadTab` and the\n * like) is the layout's (`layout.threads`) applied here, and readers are told once, after both have\n * moved ({@link ArbiChatStore.batch}), so none sees a tab over another tab's conversation.\n *\n * Kept across reloads (with a `persist`): the open conversation and its line, the context documents\n * and facts, each agent chat's agent and the chosen model. The drafts are kept apart, sealed to the\n * person ({@link ArbiDraftStorage}); everything else lives for the visit.\n */\n\nimport type { components } from '@arbidocs/client'\nimport type { ProbeAnswerEvent } from '@arbidocs/sdk/browser'\nimport {\n agentControl,\n queuedMessages,\n type AgentControlMaps,\n type AgentRunControlState,\n type QueuedMessage,\n type QueuedMessages,\n} from '../chat/run-state'\nimport type { ArbiDraftStorage } from './drafts'\nimport type { ArbiLayoutStore } from './layout'\nimport type { ArbiSessionPersist } from './persist'\nimport { threadTabId, type ArbiThreadComposer, type ArbiThreadTabShow } from './thread-tabs'\n\n/** Generation in one conversation. */\nexport interface ArbiConversationGeneration {\n isGenerating: boolean\n error: string | null\n /** When the running turn started (epoch ms), once the server named its answer. */\n startTime: number | null\n /** The answer being streamed (its response id), once the server named it. */\n streamingAssistantId?: string | null\n /** The server's elapsed time for the running turn (seconds). */\n backendElapsed?: number | null\n /** The question of a send that failed, for Retry. */\n lastFailedMessage?: string | null\n /** The local stream of the running turn, which Stop aborts (absent for an attached run). */\n abortController?: AbortController | null\n}\n\n/** A document in a conversation's context; a pinned one stays there across turns. */\nexport interface ArbiConversationDocument {\n docId: string\n isPinned: boolean\n}\n\n/** An answer's timer: when its run started (epoch ms) and how long it took (seconds). */\nexport interface ArbiMessageTimer {\n startTime: number\n elapsedTime: number\n}\n\n/** A send's structured tools (`MessageInput.tools`). */\nexport type TurnTools = components['schemas']['MessageInput']['tools']\n\nexport interface ArbiChatState extends AgentControlMaps {\n /** The open conversation, or null for a new one / none. */\n conversationId: string | null\n /** Generation state per conversation id. */\n generating: Readonly<Record<string, ArbiConversationGeneration>>\n /** Personal Assistant mode for new conversations. */\n paMode: boolean\n /** The documents in each conversation's context, per conversation id. */\n conversationDocuments: Readonly<Record<string, readonly ArbiConversationDocument[]>>\n /**\n * Per conversation id: true while an empty chat follows the workspace's documents (set by\n * `useDocumentAutoAdd`); any other change of its documents is a choice and turns it off.\n * Missing for a selection made before this was recorded.\n */\n conversationDocumentAutoAdd: Readonly<Record<string, boolean>>\n /** The facts in each conversation's context, per conversation id (`new` for a new chat). */\n conversationFacts: Readonly<Record<string, readonly string[]>>\n /** The message the open conversation continues from: the leaf of the line being viewed. */\n cursor: string | null\n /** A follow-up the backend suggested for a conversation, offered in its composer. */\n suggestedQuery: { conversationExtId: string; text: string } | null\n /** Follow-ups waiting in a running turn's agent bar, per response id. */\n queuedMessages: QueuedMessages\n /**\n * What is typed in each composer, per conversation id (`new` for a new chat): the open one's\n * (`selectDraft`) and each open thread tab's. A host may keep them across reloads, stored locally\n * and encrypted ({@link ArbiDraftStorage}).\n */\n drafts: Readonly<Record<string, string>>\n /** The question being edited in the open conversation (sent as a new branch), or null. */\n editingMessageId: string | null\n /** A message a link opened the conversation at: its thread opens and the view goes to it. */\n deepLinkMessageId: string | null\n /** The citation whose sources are open (`<message id>-<citation number>`), or null. */\n activeCitationKey: string | null\n /** The config (model) chosen for the open conversation; absent: the person's last one. */\n chatModel: string | undefined\n /** The model name the open conversation's picker shows (an edit or a launch sets it). */\n chatModelName: string | undefined\n /** The mode a new conversation starts in: `always` answers, `mentioned` only when @mentioned. */\n newConversationAssistantMode: 'always' | 'mentioned'\n /** Structured tools a launch wants on the next send (the send consumes them). */\n pendingTools: TurnTools | null\n /**\n * Send the open composer's draft as soon as the conversation is ready (a launch that composed it);\n * the send clears it.\n */\n autoSendDraft: boolean\n /** The owned agent each agent chat runs through, per conversation id. */\n agentChatOwners: Readonly<Record<string, string>>\n /** A new agent chat about to start: its agent and workspace. */\n newAgentChat: { agentId: string; workspaceId: string } | null\n /**\n * The document a new chat about to start is bound to (`doc-\u2026`): set only by starting a chat from\n * a document (\"Chat about this document\") or attaching it in the new chat, never by a document\n * merely being open. Starting another new chat clears it; the first turn moves it to the\n * conversation (`chat/thread-document`).\n */\n newChatDocumentId: string | null\n /** Each answer's timer, saved when it stops showing (`<conversation id>:<message id>`). */\n messageTimers: Readonly<Record<string, ArbiMessageTimer>>\n}\n\n/** The chat's changes: every session store has them (`ArbiSessionStore`). */\nexport interface ArbiChatActions {\n /** Open a conversation in its thread tab (null: a new chat), as `openThreadTab`. */\n setConversationId(id: string | null): void\n /** Start or end a conversation's turn; `abortController` is its local stream, which Stop aborts. */\n setConversationGenerating(\n conversationId: string,\n isGenerating: boolean,\n abortController?: AbortController | null\n ): void\n setPaMode(enabled: boolean): void\n /** Set a conversation's documents; `autoAdd` marks an automatic pick (default: the user's). */\n setConversationDocuments(\n conversationId: string,\n documents: ArbiConversationDocument[],\n autoAdd?: boolean\n ): void\n setConversationFacts(conversationId: string, factIds: string[]): void\n /** The answer a conversation is streaming; `startTime` defaults to now (a re-attach passes the run's). */\n setStreamingAssistantId(conversationId: string, assistantId: string, startTime?: number): void\n setBackendElapsed(conversationId: string, seconds: number): void\n /**\n * A new chat got its server id: its generation, documents, facts, draft and tab move from\n * `fromId` (`new`) to `toId`, and it stays the open conversation.\n */\n moveConversation(fromId: string, toId: string): void\n setCursor(messageId: string | null): void\n setSuggestedQuery(suggestion: ArbiChatState['suggestedQuery']): void\n addQueuedMessage(responseId: string, message: QueuedMessage): void\n acknowledgeQueuedMessage(clientId: string, serverId: string | null): void\n removeQueuedMessage(clientId: string): void\n removeQueuedMessageByServerId(serverId: string): void\n consumeQueuedMessage(responseId: string, combinedContent: string): void\n clearQueuedMessages(responseId: string): void\n moveQueuedMessages(fromResponseId: string, toResponseId: string): void\n setAgentControlState(responseId: string, state: AgentRunControlState): void\n setAgentProbeAnswer(responseId: string, probe: ProbeAnswerEvent): void\n setAgentProbePending(responseId: string, pending: boolean): void\n clearAgentControl(responseId: string): void\n /** Set what is typed in the open conversation's composer. */\n setDraft(text: string): void\n /** The config (model) the open conversation's turns use; undefined: the person's last one. */\n setChatModel(model: string | undefined): void\n setChatModelName(model: string | undefined): void\n /**\n * Show a conversation in its thread tab (null: a new chat) at its latest message, opening the tab\n * when it is not open (`tabs.threads`); it is also the Threads page's tab. Returns the tab's id.\n */\n openThreadTab(conversationId: string | null): string\n /** Close a thread tab; closing the one on screen shows the one beside it, else the thread list. */\n closeThreadTab(tabId: string): void\n /**\n * Show a thread tab's conversation with the composer it was left with, or (null) the thread list;\n * the tabs stay open.\n */\n selectThreadTab(tabId: string | null): void\n setNewConversationAssistantMode(mode: 'always' | 'mentioned'): void\n /** Start a new chat with an owned agent (null: an ordinary new chat). */\n setNewAgentChat(chat: { agentId: string; workspaceId: string } | null): void\n /** Bind the new chat to a document (null: unbound). Opening a new chat's tab clears it. */\n setNewChatDocumentId(documentId: string | null): void\n /** Edit a question: the composer holds it (its draft and line come back on cancel). */\n startEditing(messageId: string, content: string): void\n /** Leave the edit: the composer gets its draft back, and the view the line it was on. */\n cancelEditing(): void\n /** The edit was sent: leave it. */\n completeEditing(): void\n setDeepLinkMessageId(messageId: string | null): void\n setActiveCitationKey(key: string | null): void\n setPendingTools(tools: TurnTools | null): void\n setAutoSendDraft(on: boolean): void\n setAgentChatOwner(conversationId: string, agentId: string): void\n /** Save an answer's timer (`<conversation id>:<message id>`). */\n setMessageTimer(key: string, timer: ArbiMessageTimer): void\n clearMessageTimer(key: string): void\n /** A send failed: the turn stops, with the server's words and the question to retry. */\n setConversationError(\n conversationId: string,\n error: string | null,\n lastFailedMessage?: string | null\n ): void\n clearConversationError(conversationId: string): void\n /** Stop the conversation's local stream and end its turn. */\n abortConversationGeneration(conversationId: string): void\n /**\n * Leave the open conversation for a new one (its conversation was deleted): no line, edit, model\n * or document binding, Personal Assistant mode off.\n */\n startNewConversation(): void\n}\n\nexport interface ArbiChatStore extends ArbiChatActions {\n /** The current state. The same object until something in it changes. */\n getState(): ArbiChatState\n /** Be told after each change (once per batch). Returns the unsubscribe. */\n subscribe(listener: () => void): () => void\n /**\n * `listener`, told after the batch running when it is called (at once outside one): a session\n * store subscribes its readers to the layout and the rest through this, so a thread tab change\n * reaches them once.\n */\n settled(listener: () => void): () => void\n /** Drop a reader's notification still waiting for a batch to end (it unsubscribed). */\n forget(listener: () => void): void\n /** Run `change`, telling readers once when it is done. */\n batch<T>(change: () => T): T\n /** Resolves once the saved chat state has been read (at once without a `persist`). */\n hydrated(): Promise<void>\n isHydrated(): boolean\n /**\n * Bring back the saved drafts once they can be opened (the person's key is there once signed in\n * and a workspace is open); a draft typed meanwhile wins over its saved copy. Safe to call often.\n */\n restoreDrafts(): void\n /**\n * The workspace is being left: its turns stop (the server finishes them), and its conversation,\n * composers, thread tabs, facts, timers and the new chat's documents are dropped. Saved\n * conversations keep their documents.\n */\n leave(): void\n /**\n * Start over (sign-in, sign-out): everything is dropped and every running turn stopped, except\n * the agent chats' agents, which another person's sign-in drops.\n */\n reset(): void\n}\n\n/** What is kept across reloads. */\nexport interface ArbiSavedChat {\n version: 1\n /** The pieces an earlier build's own saved state was brought in for (the host's migration). */\n migrated: string[]\n conversationId: string | null\n cursor: string | null\n conversationDocuments: Record<string, ArbiConversationDocument[]>\n conversationDocumentAutoAdd: Record<string, boolean>\n conversationFacts: Record<string, string[]>\n agentChatOwners: Record<string, string>\n /** Who the agent chats belong to (null: not known, as in an earlier build's save). */\n agentChatOwnersUser: string | null\n chatModel: string | null\n}\n\nexport const EMPTY_CHAT_STATE: ArbiChatState = {\n conversationId: null,\n generating: {},\n paMode: false,\n conversationDocuments: {},\n conversationDocumentAutoAdd: {},\n conversationFacts: {},\n cursor: null,\n suggestedQuery: null,\n queuedMessages: {},\n agentControlStates: {},\n agentProbeAnswers: {},\n agentProbePending: {},\n drafts: {},\n editingMessageId: null,\n deepLinkMessageId: null,\n activeCitationKey: null,\n chatModel: undefined,\n chatModelName: undefined,\n newConversationAssistantMode: 'always',\n pendingTools: null,\n autoSendDraft: false,\n agentChatOwners: {},\n newAgentChat: null,\n newChatDocumentId: null,\n messageTimers: {},\n}\n\n// \u2500\u2500 Saving \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\nconst isString = (v: unknown): v is string => typeof v === 'string'\nconst stringOrNull = (v: unknown): string | null => (isString(v) ? v : null)\n\nconst recordOf = <T>(value: unknown, read: (entry: unknown) => T | null): Record<string, T> => {\n if (!isRecord(value)) return {}\n const out: Record<string, T> = {}\n for (const [key, entry] of Object.entries(value)) {\n const parsed = read(entry)\n if (parsed !== null) out[key] = parsed\n }\n return out\n}\n\nconst readDocuments = (value: unknown): ArbiConversationDocument[] | null =>\n Array.isArray(value)\n ? value\n .filter((doc): doc is Record<string, unknown> => isRecord(doc) && isString(doc.docId))\n .map((doc) => ({ docId: doc.docId as string, isPinned: doc.isPinned === true }))\n : null\n\nconst readFacts = (value: unknown): string[] | null =>\n Array.isArray(value) ? Array.from(new Set(value.filter(isString))) : null\n\n/**\n * A saved chat state as this build reads it: whatever an earlier or a broken save left is dropped\n * rather than read. Never throws; null when there is nothing usable.\n */\nexport function parseSavedChat(saved: unknown): ArbiSavedChat | null {\n if (!isRecord(saved) || saved.version !== 1) return null\n return {\n version: 1,\n migrated: Array.isArray(saved.migrated) ? saved.migrated.filter(isString) : [],\n conversationId: stringOrNull(saved.conversationId),\n cursor: stringOrNull(saved.cursor),\n conversationDocuments: recordOf(saved.conversationDocuments, readDocuments),\n conversationDocumentAutoAdd: recordOf(saved.conversationDocumentAutoAdd, (v) =>\n typeof v === 'boolean' ? v : null\n ),\n conversationFacts: recordOf(saved.conversationFacts, readFacts),\n agentChatOwners: recordOf(saved.agentChatOwners, (v) => (isString(v) ? v : null)),\n agentChatOwnersUser: stringOrNull(saved.agentChatOwnersUser),\n chatModel: stringOrNull(saved.chatModel),\n }\n}\n\n/** What of a chat state is saved. */\nexport function savedChatOf(\n state: ArbiChatState,\n migrated: string[],\n agentChatOwnersUser: string | null = null\n): ArbiSavedChat {\n return {\n version: 1,\n migrated,\n conversationId: state.conversationId,\n cursor: state.cursor,\n conversationDocuments: state.conversationDocuments as Record<\n string,\n ArbiConversationDocument[]\n >,\n conversationDocumentAutoAdd: { ...state.conversationDocumentAutoAdd },\n conversationFacts: state.conversationFacts as Record<string, string[]>,\n agentChatOwners: { ...state.agentChatOwners },\n agentChatOwnersUser,\n chatModel: state.chatModel ?? null,\n }\n}\n\nconst SAVED_FIELDS = [\n 'conversationId',\n 'cursor',\n 'conversationDocuments',\n 'conversationDocumentAutoAdd',\n 'conversationFacts',\n 'agentChatOwners',\n 'chatModel',\n] as const satisfies readonly (keyof ArbiChatState)[]\n\n// \u2500\u2500 The store \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface ArbiChatStoreOptions {\n /** The layout whose thread tabs the composer moves with. */\n layout: ArbiLayoutStore\n /** Keep the open conversation, the context and the model across reloads. */\n persist?: ArbiSessionPersist<ArbiSavedChat>\n /** Keep the composers' drafts across reloads (see `createSealedDraftStorage`). */\n draftStorage?: ArbiDraftStorage\n /** Where the open conversation is scrolled to, saved with its tab when another one shows. */\n scrollTop?: () => number | null\n /**\n * The signed-in user (default: the draft storage's owner). The agent chats' agents are kept over a\n * sign-in of the same person and dropped when another person signs in.\n */\n user?: () => string | null\n /** The state to start from (unit tests, a host's initial state); a saved one fills it in. */\n initial?: Partial<ArbiChatState>\n}\n\n/** A per-conversation record without the unsent new chat's entry. */\nfunction withoutNew<T>(record: Readonly<Record<string, T>>): Record<string, T> {\n const saved = { ...record }\n delete saved.new\n return saved\n}\n\n/** `record` with `fromId`'s entry under `toId` (the same record when it has none). */\nfunction moveKey<T>(\n record: Readonly<Record<string, T>>,\n fromId: string,\n toId: string\n): Readonly<Record<string, T>> {\n if (!(fromId in record)) return record\n const next = { ...record, [toId]: record[fromId] }\n delete next[fromId]\n return next\n}\n\nconst NO_EDIT = { draft: '', cursor: null as string | null }\n\nexport function createArbiChatStore({\n layout,\n persist,\n draftStorage,\n scrollTop = () => null,\n user = () => draftStorage?.owner() ?? null,\n initial,\n}: ArbiChatStoreOptions): ArbiChatStore {\n let state: ArbiChatState = { ...EMPTY_CHAT_STATE, ...initial }\n let migrated: string[] = []\n // Whose agent chats `agentChatOwners` records (null: not known yet).\n let ownersUser: string | null = null\n let isHydrated = !persist\n\n // Readers are told once per batch: a thread tab change moves the layout's tabs and the composer.\n const listeners = new Set<() => void>()\n const waiting = new Set<() => void>()\n let depth = 0\n const settle = (listener: () => void) => (depth > 0 ? waiting.add(listener) : listener())\n const notify = () => listeners.forEach(settle)\n const batch = <T>(change: () => T): T => {\n depth += 1\n try {\n return change()\n } finally {\n depth -= 1\n if (depth === 0) {\n const told = [...waiting]\n waiting.clear()\n told.forEach((listener) => listener())\n }\n }\n }\n\n const save = () => {\n // Nothing is saved before the saved state is read: it would overwrite it with the defaults.\n if (persist && isHydrated) persist.save(savedChatOf(state, migrated, ownersUser))\n }\n const update = (patch: Partial<ArbiChatState>) => {\n const next = { ...state, ...patch }\n const saved = SAVED_FIELDS.some((key) => next[key] !== state[key])\n state = next\n notify()\n if (saved) save()\n }\n\n // The draft and line the composer had when an edit began, given back when it is cancelled.\n let preEdit = NO_EDIT\n\n // \u2500\u2500 Drafts \u2500\u2500\n // The saved drafts come back once the person's key is there; nothing is written before (it would\n // replace the saved ones). Whose they are is checked on each restore: another person's never carry\n // over to the next sign-in.\n let draftsRestored = !draftStorage\n let restoring = false\n let draftsOwner = draftStorage?.owner() ?? null\n const setDrafts = (drafts: Readonly<Record<string, string>>) => {\n if (drafts === state.drafts) return\n update({ drafts })\n if (draftsRestored) draftStorage?.save(drafts)\n }\n const setDraftOf = (key: string, text: string) => {\n if ((state.drafts[key] ?? '') === text) return\n const drafts = { ...state.drafts }\n if (text) drafts[key] = text\n else delete drafts[key]\n setDrafts(drafts)\n }\n /** The drafts of the open composer and the open thread tabs; any other is gone with its tab. */\n const keptDrafts = (drafts: Readonly<Record<string, string>>) => {\n const open = new Set(layout.getLayout().tabs.threads.map(threadTabId))\n open.add(state.conversationId ?? 'new')\n const keys = Object.keys(drafts)\n if (keys.every((key) => open.has(key))) return drafts\n return Object.fromEntries(keys.filter((key) => open.has(key)).map((key) => [key, drafts[key]]))\n }\n const restoreDrafts = () => {\n if (!draftStorage) return\n const owner = draftStorage.owner()\n if (owner !== draftsOwner) {\n if (draftsOwner !== null) update({ drafts: {} })\n draftsOwner = owner\n draftsRestored = false\n }\n if (draftsRestored || restoring || owner === null) return\n restoring = true\n // The tabs are read first: their drafts come back with them.\n void Promise.all([layout.hydrated(), hydration])\n .then(() => draftStorage.load())\n .then(\n (saved) => {\n restoring = false\n if (!saved || draftStorage.owner() !== owner) return\n draftsRestored = true\n setDrafts(keptDrafts({ ...saved, ...state.drafts }))\n draftStorage.save(state.drafts)\n },\n () => {\n restoring = false\n }\n )\n }\n // The session ended: what was typed goes with it.\n draftStorage?.onClear(() => {\n draftsRestored = false\n draftsOwner = null\n preEdit = NO_EDIT\n if (Object.keys(state.drafts).length > 0) update({ drafts: {} })\n })\n\n // \u2500\u2500 The composer and the thread tabs \u2500\u2500\n const composer = (): ArbiThreadComposer => ({\n conversationId: state.conversationId,\n view: {\n cursor: state.cursor,\n editingMessageId: state.editingMessageId,\n preEditDraft: state.editingMessageId ? preEdit.draft : null,\n preEditCursor: state.editingMessageId ? preEdit.cursor : null,\n chatModel: state.chatModel,\n chatModelName: state.chatModelName,\n scrollTop: scrollTop(),\n },\n })\n /** Show what a thread tab change shows: a tab's own composer, or a fresh one (`list`: none). */\n const show = (next: ArbiThreadTabShow) => {\n if (next === null) return\n const target = next === 'list' ? { conversationId: null, view: undefined } : next\n const view = target.view\n preEdit = view\n ? { draft: view.preEditDraft ?? '', cursor: view.preEditCursor ?? null }\n : NO_EDIT\n update({\n conversationId: target.conversationId,\n cursor: view?.cursor ?? null,\n editingMessageId: view?.editingMessageId ?? null,\n chatModel: view?.chatModel,\n chatModelName: view?.chatModelName,\n })\n // A conversation opened afresh starts with an empty composer.\n if (!view) setDraftOf(target.conversationId ?? 'new', '')\n }\n const afterTabs = () => setDrafts(keptDrafts(state.drafts))\n const openThreadTab = (conversationId: string | null): string =>\n batch(() => {\n // Starting a new chat starts it unbound, whatever document is open.\n update(\n conversationId === null\n ? { newAgentChat: null, newChatDocumentId: null }\n : { newAgentChat: null }\n )\n const { tabId, show: next } = layout.threads.open(conversationId, composer())\n show(next)\n layout.setPageTab('conversations', tabId)\n afterTabs()\n return tabId\n })\n\n // \u2500\u2500 Hydration \u2500\u2500\n const hydration: Promise<void> = persist\n ? persist.load().then(\n (saved) => {\n const parsed = parseSavedChat(saved)\n if (parsed) {\n migrated = parsed.migrated\n ownersUser ??= parsed.agentChatOwnersUser\n // What changed before the save was read stays. The saved line and model are the saved\n // conversation's: another conversation opened meanwhile does not inherit them.\n const conversationId = state.conversationId ?? parsed.conversationId\n const savedOpen = conversationId === parsed.conversationId\n state = {\n ...state,\n conversationId,\n cursor: state.cursor ?? (savedOpen ? parsed.cursor : null),\n chatModel:\n state.chatModel ?? (savedOpen ? (parsed.chatModel ?? undefined) : undefined),\n conversationDocuments: {\n ...parsed.conversationDocuments,\n ...state.conversationDocuments,\n },\n conversationDocumentAutoAdd: {\n ...parsed.conversationDocumentAutoAdd,\n ...state.conversationDocumentAutoAdd,\n },\n conversationFacts: { ...parsed.conversationFacts, ...state.conversationFacts },\n agentChatOwners: { ...parsed.agentChatOwners, ...state.agentChatOwners },\n }\n }\n isHydrated = true\n notify()\n },\n () => {\n isHydrated = true\n notify()\n }\n )\n : Promise.resolve()\n\n // An active thread tab shows its own conversation: an earlier build could save a thread's tab as\n // active with the conversation cleared (its title over an empty chat on every load). Once both the\n // tabs and the saved conversation are read, the conversation follows the tab.\n void Promise.all([layout.hydrated(), hydration]).then(() => {\n const { threads, activeThread } = layout.getLayout().tabs\n const tab = activeThread ? threads.find((t) => threadTabId(t) === activeThread) : null\n if (tab && state.conversationId !== tab.conversationId)\n update({ conversationId: tab.conversationId })\n })\n\n const generationOf = (conversationId: string) => state.generating[conversationId]\n const setGeneration = (conversationId: string, generation: ArbiConversationGeneration) =>\n update({ generating: { ...state.generating, [conversationId]: generation } })\n const stopAll = () =>\n Object.values(state.generating).forEach((generation) => generation.abortController?.abort())\n\n return {\n getState: () => state,\n subscribe: (listener) => {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n waiting.delete(listener)\n }\n },\n settled: (listener) => () => settle(listener),\n forget: (listener) => void waiting.delete(listener),\n batch,\n hydrated: () => hydration,\n isHydrated: () => isHydrated,\n restoreDrafts,\n leave: () =>\n batch(() => {\n stopAll()\n preEdit = NO_EDIT\n update({\n conversationId: null,\n cursor: null,\n editingMessageId: null,\n chatModel: undefined,\n chatModelName: undefined,\n newConversationAssistantMode: 'always',\n paMode: false,\n generating: {},\n // Saved conversations keep their documents; the unsent new chat's belong to this workspace.\n conversationDocuments: withoutNew(state.conversationDocuments),\n conversationDocumentAutoAdd: withoutNew(state.conversationDocumentAutoAdd),\n conversationFacts: {},\n newAgentChat: null,\n newChatDocumentId: null,\n messageTimers: {},\n })\n layout.threads.clear()\n // The composers were this workspace's.\n setDrafts({})\n }),\n reset: () =>\n batch(() => {\n stopAll()\n preEdit = NO_EDIT\n // What was typed is the person's: their sealed copy goes with their session (sign-out).\n // The agent chats' agents stay unless another person signs in: an agent chat opened again\n // after the same person signs back in must still reach its agent.\n const signedIn = user()\n const keepOwners = signedIn === null || ownersUser === null || signedIn === ownersUser\n if (signedIn !== null) ownersUser = signedIn\n update({ ...EMPTY_CHAT_STATE, agentChatOwners: keepOwners ? state.agentChatOwners : {} })\n }),\n setConversationId: (id) => void openThreadTab(id),\n openThreadTab,\n closeThreadTab: (tabId) =>\n batch(() => {\n show(layout.threads.close(tabId))\n layout.setPageTab('conversations', layout.getLayout().tabs.activeThread ?? 'history')\n afterTabs()\n }),\n selectThreadTab: (tabId) =>\n batch(() => {\n if (tabId !== null) {\n show(layout.threads.select(tabId, composer()))\n layout.setPageTab('conversations', tabId)\n return\n }\n // The list leaves the open thread (so the URL is the list's); its tab keeps its composer.\n layout.threads.showList(composer())\n preEdit = NO_EDIT\n update({ conversationId: null, cursor: null, editingMessageId: null })\n layout.setPageTab('conversations', 'history')\n afterTabs()\n }),\n moveConversation: (fromId, toId) =>\n batch(() => {\n update({\n generating: moveKey(state.generating, fromId, toId),\n conversationDocuments: moveKey(state.conversationDocuments, fromId, toId),\n conversationDocumentAutoAdd: moveKey(state.conversationDocumentAutoAdd, fromId, toId),\n conversationFacts: moveKey(state.conversationFacts, fromId, toId),\n conversationId: state.conversationId ?? toId,\n })\n // The new chat's tab is now the conversation's, and what is typed stays where it was typed.\n layout.threads.rename(fromId, toId)\n setDrafts(moveKey(state.drafts, fromId, toId))\n }),\n setConversationGenerating: (conversationId, isGenerating, abortController) => {\n const current = generationOf(conversationId)\n setGeneration(conversationId, {\n ...current,\n isGenerating,\n error: isGenerating ? null : (current?.error ?? null),\n // Starting with an explicit null means generation this client does not own (an attach to a\n // run started elsewhere): it must not inherit a finished local turn's controller, or the\n // view takes it for a local stream and detaches, which makes it attachable again (an\n // endless loop that froze the tab after Stop). Stopping keeps the controller: the finished\n // turn's bookkeeping still matches on it.\n abortController:\n isGenerating && abortController === null\n ? null\n : (abortController ?? current?.abortController ?? null),\n // The run's start is set when the server names its answer (setStreamingAssistantId).\n startTime: null,\n streamingAssistantId: null,\n ...(isGenerating ? { lastFailedMessage: null, backendElapsed: null } : {}),\n })\n },\n setStreamingAssistantId: (conversationId, streamingAssistantId, startTime = Date.now()) =>\n setGeneration(conversationId, {\n ...(generationOf(conversationId) ?? { isGenerating: false, error: null }),\n streamingAssistantId,\n startTime,\n }),\n setBackendElapsed: (conversationId, backendElapsed) =>\n setGeneration(conversationId, {\n ...(generationOf(conversationId) ?? { isGenerating: false, error: null, startTime: null }),\n backendElapsed,\n }),\n setConversationError: (conversationId, error, lastFailedMessage) => {\n const current = generationOf(conversationId)\n setGeneration(conversationId, {\n ...current,\n isGenerating: false,\n error,\n startTime: current?.startTime ?? null,\n lastFailedMessage: lastFailedMessage ?? current?.lastFailedMessage ?? null,\n })\n },\n clearConversationError: (conversationId) =>\n setGeneration(conversationId, {\n ...(generationOf(conversationId) ?? { isGenerating: false, startTime: null }),\n error: null,\n lastFailedMessage: null,\n }),\n abortConversationGeneration: (conversationId) => {\n const current = generationOf(conversationId)\n current?.abortController?.abort()\n setGeneration(conversationId, {\n ...(current ?? { error: null, startTime: null }),\n isGenerating: false,\n abortController: null,\n })\n },\n setPaMode: (paMode) => {\n if (state.paMode !== paMode) update({ paMode })\n },\n setConversationDocuments: (conversationId, documents, autoAdd = false) =>\n update({\n conversationDocuments: { ...state.conversationDocuments, [conversationId]: documents },\n conversationDocumentAutoAdd: {\n ...state.conversationDocumentAutoAdd,\n [conversationId]: autoAdd,\n },\n }),\n setConversationFacts: (conversationId, factIds) =>\n update({\n conversationFacts: {\n ...state.conversationFacts,\n [conversationId]: Array.from(new Set(factIds)),\n },\n }),\n setCursor: (cursor) => {\n if (state.cursor !== cursor) update({ cursor })\n },\n setSuggestedQuery: (suggestedQuery) => update({ suggestedQuery }),\n addQueuedMessage: (id, message) =>\n update({ queuedMessages: queuedMessages.add(state.queuedMessages, id, message) }),\n acknowledgeQueuedMessage: (clientId, serverId) =>\n update({\n queuedMessages: queuedMessages.acknowledge(state.queuedMessages, clientId, serverId),\n }),\n removeQueuedMessage: (clientId) =>\n update({ queuedMessages: queuedMessages.remove(state.queuedMessages, clientId) }),\n removeQueuedMessageByServerId: (serverId) =>\n update({ queuedMessages: queuedMessages.removeByServerId(state.queuedMessages, serverId) }),\n consumeQueuedMessage: (id, content) =>\n update({ queuedMessages: queuedMessages.consume(state.queuedMessages, id, content) }),\n clearQueuedMessages: (id) =>\n update({ queuedMessages: queuedMessages.clear(state.queuedMessages, id) }),\n moveQueuedMessages: (from, to) =>\n update({ queuedMessages: queuedMessages.move(state.queuedMessages, from, to) }),\n setAgentControlState: (id, control) => update(agentControl.setState(state, id, control)),\n setAgentProbeAnswer: (id, probe) => update(agentControl.setProbeAnswer(state, id, probe)),\n setAgentProbePending: (id, pending) => update(agentControl.setProbePending(state, id, pending)),\n clearAgentControl: (id) => update(agentControl.clear(state, id)),\n setDraft: (text) => setDraftOf(state.conversationId ?? 'new', text),\n setChatModel: (chatModel) => {\n if (state.chatModel !== chatModel) update({ chatModel })\n },\n setChatModelName: (chatModelName) => {\n if (state.chatModelName !== chatModelName) update({ chatModelName })\n },\n setNewConversationAssistantMode: (newConversationAssistantMode) => {\n if (state.newConversationAssistantMode !== newConversationAssistantMode)\n update({ newConversationAssistantMode })\n },\n setNewAgentChat: (newAgentChat) => {\n const current = state.newAgentChat\n if (\n current?.agentId !== newAgentChat?.agentId ||\n current?.workspaceId !== newAgentChat?.workspaceId\n )\n update({ newAgentChat })\n },\n setNewChatDocumentId: (newChatDocumentId) => {\n if (state.newChatDocumentId !== newChatDocumentId) update({ newChatDocumentId })\n },\n startEditing: (messageId, content) =>\n batch(() => {\n const key = state.conversationId ?? 'new'\n preEdit = { draft: state.drafts[key] ?? '', cursor: state.cursor }\n update({ editingMessageId: messageId })\n setDraftOf(key, content)\n }),\n cancelEditing: () => {\n if (!state.editingMessageId) return\n const restore = preEdit\n preEdit = NO_EDIT\n batch(() => {\n update({ editingMessageId: null, cursor: restore.cursor })\n setDraftOf(state.conversationId ?? 'new', restore.draft)\n })\n },\n completeEditing: () => {\n preEdit = NO_EDIT\n if (state.editingMessageId) update({ editingMessageId: null })\n },\n setDeepLinkMessageId: (deepLinkMessageId) => {\n if (state.deepLinkMessageId !== deepLinkMessageId) update({ deepLinkMessageId })\n },\n setActiveCitationKey: (activeCitationKey) => {\n if (state.activeCitationKey !== activeCitationKey) update({ activeCitationKey })\n },\n setPendingTools: (pendingTools) => update({ pendingTools }),\n setAutoSendDraft: (autoSendDraft) => {\n if (state.autoSendDraft !== autoSendDraft) update({ autoSendDraft })\n },\n setAgentChatOwner: (conversationId, agentId) => {\n const signedIn = user()\n ownersUser = signedIn ?? ownersUser\n update({ agentChatOwners: { ...state.agentChatOwners, [conversationId]: agentId } })\n },\n setMessageTimer: (key, timer) =>\n update({ messageTimers: { ...state.messageTimers, [key]: timer } }),\n clearMessageTimer: (key) => {\n if (!(key in state.messageTimers)) return\n const messageTimers = { ...state.messageTimers }\n delete messageTimers[key]\n update({ messageTimers })\n },\n startNewConversation: () =>\n batch(() => {\n preEdit = NO_EDIT\n update({\n conversationId: null,\n cursor: null,\n editingMessageId: null,\n chatModel: undefined,\n chatModelName: undefined,\n newConversationAssistantMode: 'always',\n paMode: false,\n newChatDocumentId: null,\n })\n }),\n }\n}\n"],
|
|
5
|
+
"mappings": "AAiBA;AAAA,EACE;AAAA,EACA;AAAA,OAKK;AAIP,SAAS,mBAAoE;AA+OtE,MAAM,mBAAkC;AAAA,EAC7C,gBAAgB;AAAA,EAChB,YAAY,CAAC;AAAA,EACb,QAAQ;AAAA,EACR,uBAAuB,CAAC;AAAA,EACxB,6BAA6B,CAAC;AAAA,EAC9B,mBAAmB,CAAC;AAAA,EACpB,QAAQ;AAAA,EACR,gBAAgB;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,oBAAoB,CAAC;AAAA,EACrB,mBAAmB,CAAC;AAAA,EACpB,mBAAmB,CAAC;AAAA,EACpB,QAAQ,CAAC;AAAA,EACT,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,WAAW;AAAA,EACX,eAAe;AAAA,EACf,8BAA8B;AAAA,EAC9B,cAAc;AAAA,EACd,eAAe;AAAA,EACf,iBAAiB,CAAC;AAAA,EAClB,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB,eAAe,CAAC;AAClB;AAIA,MAAM,WAAW,CAAC,UAChB,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AACrE,MAAM,WAAW,CAAC,MAA4B,OAAO,MAAM;AAC3D,MAAM,eAAe,CAAC,MAA+B,SAAS,CAAC,IAAI,IAAI;AAEvE,MAAM,WAAW,CAAI,OAAgB,SAA0D;AAC7F,MAAI,CAAC,SAAS,KAAK,EAAG,QAAO,CAAC;AAC9B,QAAM,MAAyB,CAAC;AAChC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,UAAM,SAAS,KAAK,KAAK;AACzB,QAAI,WAAW,KAAM,KAAI,GAAG,IAAI;AAAA,EAClC;AACA,SAAO;AACT;AAEA,MAAM,gBAAgB,CAAC,UACrB,MAAM,QAAQ,KAAK,IACf,MACG,OAAO,CAAC,QAAwC,SAAS,GAAG,KAAK,SAAS,IAAI,KAAK,CAAC,EACpF,IAAI,CAAC,SAAS,EAAE,OAAO,IAAI,OAAiB,UAAU,IAAI,aAAa,KAAK,EAAE,IACjF;AAEN,MAAM,YAAY,CAAC,UACjB,MAAM,QAAQ,KAAK,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,OAAO,QAAQ,CAAC,CAAC,IAAI;AAMhE,SAAS,eAAe,OAAsC;AACnE,MAAI,CAAC,SAAS,KAAK,KAAK,MAAM,YAAY,EAAG,QAAO;AACpD,SAAO;AAAA,IACL,SAAS;AAAA,IACT,UAAU,MAAM,QAAQ,MAAM,QAAQ,IAAI,MAAM,SAAS,OAAO,QAAQ,IAAI,CAAC;AAAA,IAC7E,gBAAgB,aAAa,MAAM,cAAc;AAAA,IACjD,QAAQ,aAAa,MAAM,MAAM;AAAA,IACjC,uBAAuB,SAAS,MAAM,uBAAuB,aAAa;AAAA,IAC1E,6BAA6B;AAAA,MAAS,MAAM;AAAA,MAA6B,CAAC,MACxE,OAAO,MAAM,YAAY,IAAI;AAAA,IAC/B;AAAA,IACA,mBAAmB,SAAS,MAAM,mBAAmB,SAAS;AAAA,IAC9D,iBAAiB,SAAS,MAAM,iBAAiB,CAAC,MAAO,SAAS,CAAC,IAAI,IAAI,IAAK;AAAA,IAChF,qBAAqB,aAAa,MAAM,mBAAmB;AAAA,IAC3D,WAAW,aAAa,MAAM,SAAS;AAAA,EACzC;AACF;AAGO,SAAS,YACd,OACA,UACA,sBAAqC,MACtB;AACf,SAAO;AAAA,IACL,SAAS;AAAA,IACT;AAAA,IACA,gBAAgB,MAAM;AAAA,IACtB,QAAQ,MAAM;AAAA,IACd,uBAAuB,MAAM;AAAA,IAI7B,6BAA6B,EAAE,GAAG,MAAM,4BAA4B;AAAA,IACpE,mBAAmB,MAAM;AAAA,IACzB,iBAAiB,EAAE,GAAG,MAAM,gBAAgB;AAAA,IAC5C;AAAA,IACA,WAAW,MAAM,aAAa;AAAA,EAChC;AACF;AAEA,MAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAuBA,SAAS,WAAc,QAAwD;AAC7E,QAAM,QAAQ,EAAE,GAAG,OAAO;AAC1B,SAAO,MAAM;AACb,SAAO;AACT;AAGA,SAAS,QACP,QACA,QACA,MAC6B;AAC7B,MAAI,EAAE,UAAU,QAAS,QAAO;AAChC,QAAM,OAAO,EAAE,GAAG,QAAQ,CAAC,IAAI,GAAG,OAAO,MAAM,EAAE;AACjD,SAAO,KAAK,MAAM;AAClB,SAAO;AACT;AAEA,MAAM,UAAU,EAAE,OAAO,IAAI,QAAQ,KAAsB;AAEpD,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY,MAAM;AAAA,EAClB,OAAO,MAAM,cAAc,MAAM,KAAK;AAAA,EACtC;AACF,GAAwC;AACtC,MAAI,QAAuB,EAAE,GAAG,kBAAkB,GAAG,QAAQ;AAC7D,MAAI,WAAqB,CAAC;AAE1B,MAAI,aAA4B;AAChC,MAAI,aAAa,CAAC;AAGlB,QAAM,YAAY,oBAAI,IAAgB;AACtC,QAAM,UAAU,oBAAI,IAAgB;AACpC,MAAI,QAAQ;AACZ,QAAM,SAAS,CAAC,aAA0B,QAAQ,IAAI,QAAQ,IAAI,QAAQ,IAAI,SAAS;AACvF,QAAM,SAAS,MAAM,UAAU,QAAQ,MAAM;AAC7C,QAAM,QAAQ,CAAI,WAAuB;AACvC,aAAS;AACT,QAAI;AACF,aAAO,OAAO;AAAA,IAChB,UAAE;AACA,eAAS;AACT,UAAI,UAAU,GAAG;AACf,cAAM,OAAO,CAAC,GAAG,OAAO;AACxB,gBAAQ,MAAM;AACd,aAAK,QAAQ,CAAC,aAAa,SAAS,CAAC;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAAO,MAAM;AAEjB,QAAI,WAAW,WAAY,SAAQ,KAAK,YAAY,OAAO,UAAU,UAAU,CAAC;AAAA,EAClF;AACA,QAAM,SAAS,CAAC,UAAkC;AAChD,UAAM,OAAO,EAAE,GAAG,OAAO,GAAG,MAAM;AAClC,UAAM,QAAQ,aAAa,KAAK,CAAC,QAAQ,KAAK,GAAG,MAAM,MAAM,GAAG,CAAC;AACjE,YAAQ;AACR,WAAO;AACP,QAAI,MAAO,MAAK;AAAA,EAClB;AAGA,MAAI,UAAU;AAMd,MAAI,iBAAiB,CAAC;AACtB,MAAI,YAAY;AAChB,MAAI,cAAc,cAAc,MAAM,KAAK;AAC3C,QAAM,YAAY,CAAC,WAA6C;AAC9D,QAAI,WAAW,MAAM,OAAQ;AAC7B,WAAO,EAAE,OAAO,CAAC;AACjB,QAAI,eAAgB,eAAc,KAAK,MAAM;AAAA,EAC/C;AACA,QAAM,aAAa,CAAC,KAAa,SAAiB;AAChD,SAAK,MAAM,OAAO,GAAG,KAAK,QAAQ,KAAM;AACxC,UAAM,SAAS,EAAE,GAAG,MAAM,OAAO;AACjC,QAAI,KAAM,QAAO,GAAG,IAAI;AAAA,QACnB,QAAO,OAAO,GAAG;AACtB,cAAU,MAAM;AAAA,EAClB;AAEA,QAAM,aAAa,CAAC,WAA6C;AAC/D,UAAM,OAAO,IAAI,IAAI,OAAO,UAAU,EAAE,KAAK,QAAQ,IAAI,WAAW,CAAC;AACrE,SAAK,IAAI,MAAM,kBAAkB,KAAK;AACtC,UAAM,OAAO,OAAO,KAAK,MAAM;AAC/B,QAAI,KAAK,MAAM,CAAC,QAAQ,KAAK,IAAI,GAAG,CAAC,EAAG,QAAO;AAC/C,WAAO,OAAO,YAAY,KAAK,OAAO,CAAC,QAAQ,KAAK,IAAI,GAAG,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,OAAO,GAAG,CAAC,CAAC,CAAC;AAAA,EAChG;AACA,QAAM,gBAAgB,MAAM;AAC1B,QAAI,CAAC,aAAc;AACnB,UAAM,QAAQ,aAAa,MAAM;AACjC,QAAI,UAAU,aAAa;AACzB,UAAI,gBAAgB,KAAM,QAAO,EAAE,QAAQ,CAAC,EAAE,CAAC;AAC/C,oBAAc;AACd,uBAAiB;AAAA,IACnB;AACA,QAAI,kBAAkB,aAAa,UAAU,KAAM;AACnD,gBAAY;AAEZ,SAAK,QAAQ,IAAI,CAAC,OAAO,SAAS,GAAG,SAAS,CAAC,EAC5C,KAAK,MAAM,aAAa,KAAK,CAAC,EAC9B;AAAA,MACC,CAAC,UAAU;AACT,oBAAY;AACZ,YAAI,CAAC,SAAS,aAAa,MAAM,MAAM,MAAO;AAC9C,yBAAiB;AACjB,kBAAU,WAAW,EAAE,GAAG,OAAO,GAAG,MAAM,OAAO,CAAC,CAAC;AACnD,qBAAa,KAAK,MAAM,MAAM;AAAA,MAChC;AAAA,MACA,MAAM;AACJ,oBAAY;AAAA,MACd;AAAA,IACF;AAAA,EACJ;AAEA,gBAAc,QAAQ,MAAM;AAC1B,qBAAiB;AACjB,kBAAc;AACd,cAAU;AACV,QAAI,OAAO,KAAK,MAAM,MAAM,EAAE,SAAS,EAAG,QAAO,EAAE,QAAQ,CAAC,EAAE,CAAC;AAAA,EACjE,CAAC;AAGD,QAAM,WAAW,OAA2B;AAAA,IAC1C,gBAAgB,MAAM;AAAA,IACtB,MAAM;AAAA,MACJ,QAAQ,MAAM;AAAA,MACd,kBAAkB,MAAM;AAAA,MACxB,cAAc,MAAM,mBAAmB,QAAQ,QAAQ;AAAA,MACvD,eAAe,MAAM,mBAAmB,QAAQ,SAAS;AAAA,MACzD,WAAW,MAAM;AAAA,MACjB,eAAe,MAAM;AAAA,MACrB,WAAW,UAAU;AAAA,IACvB;AAAA,EACF;AAEA,QAAM,OAAO,CAAC,SAA4B;AACxC,QAAI,SAAS,KAAM;AACnB,UAAM,SAAS,SAAS,SAAS,EAAE,gBAAgB,MAAM,MAAM,OAAU,IAAI;AAC7E,UAAM,OAAO,OAAO;AACpB,cAAU,OACN,EAAE,OAAO,KAAK,gBAAgB,IAAI,QAAQ,KAAK,iBAAiB,KAAK,IACrE;AACJ,WAAO;AAAA,MACL,gBAAgB,OAAO;AAAA,MACvB,QAAQ,MAAM,UAAU;AAAA,MACxB,kBAAkB,MAAM,oBAAoB;AAAA,MAC5C,WAAW,MAAM;AAAA,MACjB,eAAe,MAAM;AAAA,IACvB,CAAC;AAED,QAAI,CAAC,KAAM,YAAW,OAAO,kBAAkB,OAAO,EAAE;AAAA,EAC1D;AACA,QAAM,YAAY,MAAM,UAAU,WAAW,MAAM,MAAM,CAAC;AAC1D,QAAM,gBAAgB,CAAC,mBACrB,MAAM,MAAM;AAEV;AAAA,MACE,mBAAmB,OACf,EAAE,cAAc,MAAM,mBAAmB,KAAK,IAC9C,EAAE,cAAc,KAAK;AAAA,IAC3B;AACA,UAAM,EAAE,OAAO,MAAM,KAAK,IAAI,OAAO,QAAQ,KAAK,gBAAgB,SAAS,CAAC;AAC5E,SAAK,IAAI;AACT,WAAO,WAAW,iBAAiB,KAAK;AACxC,cAAU;AACV,WAAO;AAAA,EACT,CAAC;AAGH,QAAM,YAA2B,UAC7B,QAAQ,KAAK,EAAE;AAAA,IACb,CAAC,UAAU;AACT,YAAM,SAAS,eAAe,KAAK;AACnC,UAAI,QAAQ;AACV,mBAAW,OAAO;AAClB,uBAAe,OAAO;AAGtB,cAAM,iBAAiB,MAAM,kBAAkB,OAAO;AACtD,cAAM,YAAY,mBAAmB,OAAO;AAC5C,gBAAQ;AAAA,UACN,GAAG;AAAA,UACH;AAAA,UACA,QAAQ,MAAM,WAAW,YAAY,OAAO,SAAS;AAAA,UACrD,WACE,MAAM,cAAc,YAAa,OAAO,aAAa,SAAa;AAAA,UACpE,uBAAuB;AAAA,YACrB,GAAG,OAAO;AAAA,YACV,GAAG,MAAM;AAAA,UACX;AAAA,UACA,6BAA6B;AAAA,YAC3B,GAAG,OAAO;AAAA,YACV,GAAG,MAAM;AAAA,UACX;AAAA,UACA,mBAAmB,EAAE,GAAG,OAAO,mBAAmB,GAAG,MAAM,kBAAkB;AAAA,UAC7E,iBAAiB,EAAE,GAAG,OAAO,iBAAiB,GAAG,MAAM,gBAAgB;AAAA,QACzE;AAAA,MACF;AACA,mBAAa;AACb,aAAO;AAAA,IACT;AAAA,IACA,MAAM;AACJ,mBAAa;AACb,aAAO;AAAA,IACT;AAAA,EACF,IACA,QAAQ,QAAQ;AAKpB,OAAK,QAAQ,IAAI,CAAC,OAAO,SAAS,GAAG,SAAS,CAAC,EAAE,KAAK,MAAM;AAC1D,UAAM,EAAE,SAAS,aAAa,IAAI,OAAO,UAAU,EAAE;AACrD,UAAM,MAAM,eAAe,QAAQ,KAAK,CAAC,MAAM,YAAY,CAAC,MAAM,YAAY,IAAI;AAClF,QAAI,OAAO,MAAM,mBAAmB,IAAI;AACtC,aAAO,EAAE,gBAAgB,IAAI,eAAe,CAAC;AAAA,EACjD,CAAC;AAED,QAAM,eAAe,CAAC,mBAA2B,MAAM,WAAW,cAAc;AAChF,QAAM,gBAAgB,CAAC,gBAAwB,eAC7C,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,YAAY,CAAC,cAAc,GAAG,WAAW,EAAE,CAAC;AAC9E,QAAM,UAAU,MACd,OAAO,OAAO,MAAM,UAAU,EAAE,QAAQ,CAAC,eAAe,WAAW,iBAAiB,MAAM,CAAC;AAE7F,SAAO;AAAA,IACL,UAAU,MAAM;AAAA,IAChB,WAAW,CAAC,aAAa;AACvB,gBAAU,IAAI,QAAQ;AACtB,aAAO,MAAM;AACX,kBAAU,OAAO,QAAQ;AACzB,gBAAQ,OAAO,QAAQ;AAAA,MACzB;AAAA,IACF;AAAA,IACA,SAAS,CAAC,aAAa,MAAM,OAAO,QAAQ;AAAA,IAC5C,QAAQ,CAAC,aAAa,KAAK,QAAQ,OAAO,QAAQ;AAAA,IAClD;AAAA,IACA,UAAU,MAAM;AAAA,IAChB,YAAY,MAAM;AAAA,IAClB;AAAA,IACA,OAAO,MACL,MAAM,MAAM;AACV,cAAQ;AACR,gBAAU;AACV,aAAO;AAAA,QACL,gBAAgB;AAAA,QAChB,QAAQ;AAAA,QACR,kBAAkB;AAAA,QAClB,WAAW;AAAA,QACX,eAAe;AAAA,QACf,8BAA8B;AAAA,QAC9B,QAAQ;AAAA,QACR,YAAY,CAAC;AAAA;AAAA,QAEb,uBAAuB,WAAW,MAAM,qBAAqB;AAAA,QAC7D,6BAA6B,WAAW,MAAM,2BAA2B;AAAA,QACzE,mBAAmB,CAAC;AAAA,QACpB,cAAc;AAAA,QACd,mBAAmB;AAAA,QACnB,eAAe,CAAC;AAAA,MAClB,CAAC;AACD,aAAO,QAAQ,MAAM;AAErB,gBAAU,CAAC,CAAC;AAAA,IACd,CAAC;AAAA,IACH,OAAO,MACL,MAAM,MAAM;AACV,cAAQ;AACR,gBAAU;AAIV,YAAM,WAAW,KAAK;AACtB,YAAM,aAAa,aAAa,QAAQ,eAAe,QAAQ,aAAa;AAC5E,UAAI,aAAa,KAAM,cAAa;AACpC,aAAO,EAAE,GAAG,kBAAkB,iBAAiB,aAAa,MAAM,kBAAkB,CAAC,EAAE,CAAC;AAAA,IAC1F,CAAC;AAAA,IACH,mBAAmB,CAAC,OAAO,KAAK,cAAc,EAAE;AAAA,IAChD;AAAA,IACA,gBAAgB,CAAC,UACf,MAAM,MAAM;AACV,WAAK,OAAO,QAAQ,MAAM,KAAK,CAAC;AAChC,aAAO,WAAW,iBAAiB,OAAO,UAAU,EAAE,KAAK,gBAAgB,SAAS;AACpF,gBAAU;AAAA,IACZ,CAAC;AAAA,IACH,iBAAiB,CAAC,UAChB,MAAM,MAAM;AACV,UAAI,UAAU,MAAM;AAClB,aAAK,OAAO,QAAQ,OAAO,OAAO,SAAS,CAAC,CAAC;AAC7C,eAAO,WAAW,iBAAiB,KAAK;AACxC;AAAA,MACF;AAEA,aAAO,QAAQ,SAAS,SAAS,CAAC;AAClC,gBAAU;AACV,aAAO,EAAE,gBAAgB,MAAM,QAAQ,MAAM,kBAAkB,KAAK,CAAC;AACrE,aAAO,WAAW,iBAAiB,SAAS;AAC5C,gBAAU;AAAA,IACZ,CAAC;AAAA,IACH,kBAAkB,CAAC,QAAQ,SACzB,MAAM,MAAM;AACV,aAAO;AAAA,QACL,YAAY,QAAQ,MAAM,YAAY,QAAQ,IAAI;AAAA,QAClD,uBAAuB,QAAQ,MAAM,uBAAuB,QAAQ,IAAI;AAAA,QACxE,6BAA6B,QAAQ,MAAM,6BAA6B,QAAQ,IAAI;AAAA,QACpF,mBAAmB,QAAQ,MAAM,mBAAmB,QAAQ,IAAI;AAAA,QAChE,gBAAgB,MAAM,kBAAkB;AAAA,MAC1C,CAAC;AAED,aAAO,QAAQ,OAAO,QAAQ,IAAI;AAClC,gBAAU,QAAQ,MAAM,QAAQ,QAAQ,IAAI,CAAC;AAAA,IAC/C,CAAC;AAAA,IACH,2BAA2B,CAAC,gBAAgB,cAAc,oBAAoB;AAC5E,YAAM,UAAU,aAAa,cAAc;AAC3C,oBAAc,gBAAgB;AAAA,QAC5B,GAAG;AAAA,QACH;AAAA,QACA,OAAO,eAAe,OAAQ,SAAS,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMhD,iBACE,gBAAgB,oBAAoB,OAChC,OACC,mBAAmB,SAAS,mBAAmB;AAAA;AAAA,QAEtD,WAAW;AAAA,QACX,sBAAsB;AAAA,QACtB,GAAI,eAAe,EAAE,mBAAmB,MAAM,gBAAgB,KAAK,IAAI,CAAC;AAAA,MAC1E,CAAC;AAAA,IACH;AAAA,IACA,yBAAyB,CAAC,gBAAgB,sBAAsB,YAAY,KAAK,IAAI,MACnF,cAAc,gBAAgB;AAAA,MAC5B,GAAI,aAAa,cAAc,KAAK,EAAE,cAAc,OAAO,OAAO,KAAK;AAAA,MACvE;AAAA,MACA;AAAA,IACF,CAAC;AAAA,IACH,mBAAmB,CAAC,gBAAgB,mBAClC,cAAc,gBAAgB;AAAA,MAC5B,GAAI,aAAa,cAAc,KAAK,EAAE,cAAc,OAAO,OAAO,MAAM,WAAW,KAAK;AAAA,MACxF;AAAA,IACF,CAAC;AAAA,IACH,sBAAsB,CAAC,gBAAgB,OAAO,sBAAsB;AAClE,YAAM,UAAU,aAAa,cAAc;AAC3C,oBAAc,gBAAgB;AAAA,QAC5B,GAAG;AAAA,QACH,cAAc;AAAA,QACd;AAAA,QACA,WAAW,SAAS,aAAa;AAAA,QACjC,mBAAmB,qBAAqB,SAAS,qBAAqB;AAAA,MACxE,CAAC;AAAA,IACH;AAAA,IACA,wBAAwB,CAAC,mBACvB,cAAc,gBAAgB;AAAA,MAC5B,GAAI,aAAa,cAAc,KAAK,EAAE,cAAc,OAAO,WAAW,KAAK;AAAA,MAC3E,OAAO;AAAA,MACP,mBAAmB;AAAA,IACrB,CAAC;AAAA,IACH,6BAA6B,CAAC,mBAAmB;AAC/C,YAAM,UAAU,aAAa,cAAc;AAC3C,eAAS,iBAAiB,MAAM;AAChC,oBAAc,gBAAgB;AAAA,QAC5B,GAAI,WAAW,EAAE,OAAO,MAAM,WAAW,KAAK;AAAA,QAC9C,cAAc;AAAA,QACd,iBAAiB;AAAA,MACnB,CAAC;AAAA,IACH;AAAA,IACA,WAAW,CAAC,WAAW;AACrB,UAAI,MAAM,WAAW,OAAQ,QAAO,EAAE,OAAO,CAAC;AAAA,IAChD;AAAA,IACA,0BAA0B,CAAC,gBAAgB,WAAW,UAAU,UAC9D,OAAO;AAAA,MACL,uBAAuB,EAAE,GAAG,MAAM,uBAAuB,CAAC,cAAc,GAAG,UAAU;AAAA,MACrF,6BAA6B;AAAA,QAC3B,GAAG,MAAM;AAAA,QACT,CAAC,cAAc,GAAG;AAAA,MACpB;AAAA,IACF,CAAC;AAAA,IACH,sBAAsB,CAAC,gBAAgB,YACrC,OAAO;AAAA,MACL,mBAAmB;AAAA,QACjB,GAAG,MAAM;AAAA,QACT,CAAC,cAAc,GAAG,MAAM,KAAK,IAAI,IAAI,OAAO,CAAC;AAAA,MAC/C;AAAA,IACF,CAAC;AAAA,IACH,WAAW,CAAC,WAAW;AACrB,UAAI,MAAM,WAAW,OAAQ,QAAO,EAAE,OAAO,CAAC;AAAA,IAChD;AAAA,IACA,mBAAmB,CAAC,mBAAmB,OAAO,EAAE,eAAe,CAAC;AAAA,IAChE,kBAAkB,CAAC,IAAI,YACrB,OAAO,EAAE,gBAAgB,eAAe,IAAI,MAAM,gBAAgB,IAAI,OAAO,EAAE,CAAC;AAAA,IAClF,0BAA0B,CAAC,UAAU,aACnC,OAAO;AAAA,MACL,gBAAgB,eAAe,YAAY,MAAM,gBAAgB,UAAU,QAAQ;AAAA,IACrF,CAAC;AAAA,IACH,qBAAqB,CAAC,aACpB,OAAO,EAAE,gBAAgB,eAAe,OAAO,MAAM,gBAAgB,QAAQ,EAAE,CAAC;AAAA,IAClF,+BAA+B,CAAC,aAC9B,OAAO,EAAE,gBAAgB,eAAe,iBAAiB,MAAM,gBAAgB,QAAQ,EAAE,CAAC;AAAA,IAC5F,sBAAsB,CAAC,IAAI,YACzB,OAAO,EAAE,gBAAgB,eAAe,QAAQ,MAAM,gBAAgB,IAAI,OAAO,EAAE,CAAC;AAAA,IACtF,qBAAqB,CAAC,OACpB,OAAO,EAAE,gBAAgB,eAAe,MAAM,MAAM,gBAAgB,EAAE,EAAE,CAAC;AAAA,IAC3E,oBAAoB,CAAC,MAAM,OACzB,OAAO,EAAE,gBAAgB,eAAe,KAAK,MAAM,gBAAgB,MAAM,EAAE,EAAE,CAAC;AAAA,IAChF,sBAAsB,CAAC,IAAI,YAAY,OAAO,aAAa,SAAS,OAAO,IAAI,OAAO,CAAC;AAAA,IACvF,qBAAqB,CAAC,IAAI,UAAU,OAAO,aAAa,eAAe,OAAO,IAAI,KAAK,CAAC;AAAA,IACxF,sBAAsB,CAAC,IAAI,YAAY,OAAO,aAAa,gBAAgB,OAAO,IAAI,OAAO,CAAC;AAAA,IAC9F,mBAAmB,CAAC,OAAO,OAAO,aAAa,MAAM,OAAO,EAAE,CAAC;AAAA,IAC/D,UAAU,CAAC,SAAS,WAAW,MAAM,kBAAkB,OAAO,IAAI;AAAA,IAClE,cAAc,CAAC,cAAc;AAC3B,UAAI,MAAM,cAAc,UAAW,QAAO,EAAE,UAAU,CAAC;AAAA,IACzD;AAAA,IACA,kBAAkB,CAAC,kBAAkB;AACnC,UAAI,MAAM,kBAAkB,cAAe,QAAO,EAAE,cAAc,CAAC;AAAA,IACrE;AAAA,IACA,iCAAiC,CAAC,iCAAiC;AACjE,UAAI,MAAM,iCAAiC;AACzC,eAAO,EAAE,6BAA6B,CAAC;AAAA,IAC3C;AAAA,IACA,iBAAiB,CAAC,iBAAiB;AACjC,YAAM,UAAU,MAAM;AACtB,UACE,SAAS,YAAY,cAAc,WACnC,SAAS,gBAAgB,cAAc;AAEvC,eAAO,EAAE,aAAa,CAAC;AAAA,IAC3B;AAAA,IACA,sBAAsB,CAAC,sBAAsB;AAC3C,UAAI,MAAM,sBAAsB,kBAAmB,QAAO,EAAE,kBAAkB,CAAC;AAAA,IACjF;AAAA,IACA,cAAc,CAAC,WAAW,YACxB,MAAM,MAAM;AACV,YAAM,MAAM,MAAM,kBAAkB;AACpC,gBAAU,EAAE,OAAO,MAAM,OAAO,GAAG,KAAK,IAAI,QAAQ,MAAM,OAAO;AACjE,aAAO,EAAE,kBAAkB,UAAU,CAAC;AACtC,iBAAW,KAAK,OAAO;AAAA,IACzB,CAAC;AAAA,IACH,eAAe,MAAM;AACnB,UAAI,CAAC,MAAM,iBAAkB;AAC7B,YAAM,UAAU;AAChB,gBAAU;AACV,YAAM,MAAM;AACV,eAAO,EAAE,kBAAkB,MAAM,QAAQ,QAAQ,OAAO,CAAC;AACzD,mBAAW,MAAM,kBAAkB,OAAO,QAAQ,KAAK;AAAA,MACzD,CAAC;AAAA,IACH;AAAA,IACA,iBAAiB,MAAM;AACrB,gBAAU;AACV,UAAI,MAAM,iBAAkB,QAAO,EAAE,kBAAkB,KAAK,CAAC;AAAA,IAC/D;AAAA,IACA,sBAAsB,CAAC,sBAAsB;AAC3C,UAAI,MAAM,sBAAsB,kBAAmB,QAAO,EAAE,kBAAkB,CAAC;AAAA,IACjF;AAAA,IACA,sBAAsB,CAAC,sBAAsB;AAC3C,UAAI,MAAM,sBAAsB,kBAAmB,QAAO,EAAE,kBAAkB,CAAC;AAAA,IACjF;AAAA,IACA,iBAAiB,CAAC,iBAAiB,OAAO,EAAE,aAAa,CAAC;AAAA,IAC1D,kBAAkB,CAAC,kBAAkB;AACnC,UAAI,MAAM,kBAAkB,cAAe,QAAO,EAAE,cAAc,CAAC;AAAA,IACrE;AAAA,IACA,mBAAmB,CAAC,gBAAgB,YAAY;AAC9C,YAAM,WAAW,KAAK;AACtB,mBAAa,YAAY;AACzB,aAAO,EAAE,iBAAiB,EAAE,GAAG,MAAM,iBAAiB,CAAC,cAAc,GAAG,QAAQ,EAAE,CAAC;AAAA,IACrF;AAAA,IACA,iBAAiB,CAAC,KAAK,UACrB,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM,eAAe,CAAC,GAAG,GAAG,MAAM,EAAE,CAAC;AAAA,IACpE,mBAAmB,CAAC,QAAQ;AAC1B,UAAI,EAAE,OAAO,MAAM,eAAgB;AACnC,YAAM,gBAAgB,EAAE,GAAG,MAAM,cAAc;AAC/C,aAAO,cAAc,GAAG;AACxB,aAAO,EAAE,cAAc,CAAC;AAAA,IAC1B;AAAA,IACA,sBAAsB,MACpB,MAAM,MAAM;AACV,gBAAU;AACV,aAAO;AAAA,QACL,gBAAgB;AAAA,QAChB,QAAQ;AAAA,QACR,kBAAkB;AAAA,QAClB,WAAW;AAAA,QACX,eAAe;AAAA,QACf,8BAA8B;AAAA,QAC9B,QAAQ;AAAA,QACR,mBAAmB;AAAA,MACrB,CAAC;AAAA,IACH,CAAC;AAAA,EACL;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
const VIEWER_TABS = [
|
|
2
|
+
"pdf",
|
|
3
|
+
"edit",
|
|
4
|
+
"html",
|
|
5
|
+
"docx",
|
|
6
|
+
"xlsx",
|
|
7
|
+
"versions",
|
|
8
|
+
"preview"
|
|
9
|
+
];
|
|
10
|
+
const DEFAULT_DOCUMENT_VIEWER_STATE = {
|
|
11
|
+
tab: "pdf",
|
|
12
|
+
compareId: null,
|
|
13
|
+
tabRequest: null,
|
|
14
|
+
textScale: 1,
|
|
15
|
+
phonePdfChosen: false,
|
|
16
|
+
commentTarget: null,
|
|
17
|
+
unsavedChanges: false,
|
|
18
|
+
detached: false
|
|
19
|
+
};
|
|
20
|
+
const NO_PASSAGE_CITATION = {
|
|
21
|
+
active: null,
|
|
22
|
+
highlighted: [],
|
|
23
|
+
picked: [],
|
|
24
|
+
unpicked: []
|
|
25
|
+
};
|
|
26
|
+
const EMPTY_DOCUMENT_STATE = {
|
|
27
|
+
viewingDocument: null,
|
|
28
|
+
documentViewer: DEFAULT_DOCUMENT_VIEWER_STATE,
|
|
29
|
+
selectedDocumentIds: [],
|
|
30
|
+
documentsToSelect: null,
|
|
31
|
+
pinnedDocumentId: null,
|
|
32
|
+
relatedDocuments: /* @__PURE__ */ new Map(),
|
|
33
|
+
draftDocuments: {},
|
|
34
|
+
passageCitation: NO_PASSAGE_CITATION
|
|
35
|
+
};
|
|
36
|
+
const DRAFT_TITLES = {
|
|
37
|
+
text: "New Doc",
|
|
38
|
+
audio: "New Audio",
|
|
39
|
+
photo: "New Photo",
|
|
40
|
+
video: "New Video"
|
|
41
|
+
};
|
|
42
|
+
function nextViewingDocument(current, input) {
|
|
43
|
+
if (!input) return null;
|
|
44
|
+
const same = current?.id === input.id;
|
|
45
|
+
return {
|
|
46
|
+
id: input.id,
|
|
47
|
+
page: input.page !== void 0 ? input.page : same ? current?.page ?? null : null,
|
|
48
|
+
passageId: input.passageId !== void 0 ? input.passageId : current?.passageId ?? null
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
52
|
+
const isPage = (value) => typeof value === "number" && Number.isInteger(value) && value >= 1;
|
|
53
|
+
function parseSavedDocuments(saved) {
|
|
54
|
+
if (!isRecord(saved) || saved.version !== 1) return null;
|
|
55
|
+
const viewing = isRecord(saved.viewingDocument) ? saved.viewingDocument : null;
|
|
56
|
+
return {
|
|
57
|
+
version: 1,
|
|
58
|
+
viewingDocument: viewing && typeof viewing.id === "string" && viewing.id ? { id: viewing.id, page: isPage(viewing.page) ? viewing.page : null } : null,
|
|
59
|
+
pinnedDocumentId: typeof saved.pinnedDocumentId === "string" ? saved.pinnedDocumentId : null,
|
|
60
|
+
tab: VIEWER_TABS.includes(saved.tab) ? saved.tab : DEFAULT_DOCUMENT_VIEWER_STATE.tab,
|
|
61
|
+
textScale: typeof saved.textScale === "number" && Number.isFinite(saved.textScale) && saved.textScale > 0 ? saved.textScale : DEFAULT_DOCUMENT_VIEWER_STATE.textScale
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function savedDocumentsOf(state) {
|
|
65
|
+
return {
|
|
66
|
+
version: 1,
|
|
67
|
+
viewingDocument: state.viewingDocument ? { id: state.viewingDocument.id, page: state.viewingDocument.page } : null,
|
|
68
|
+
pinnedDocumentId: state.pinnedDocumentId,
|
|
69
|
+
tab: state.documentViewer.tab,
|
|
70
|
+
textScale: state.documentViewer.textScale
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function restoreSavedDocuments(base, saved) {
|
|
74
|
+
return {
|
|
75
|
+
...base,
|
|
76
|
+
viewingDocument: saved.viewingDocument ? { id: saved.viewingDocument.id, page: saved.viewingDocument.page, passageId: null } : null,
|
|
77
|
+
pinnedDocumentId: saved.pinnedDocumentId,
|
|
78
|
+
documentViewer: { ...base.documentViewer, tab: saved.tab, textScale: saved.textScale }
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function createArbiDocumentSessionStore({
|
|
82
|
+
initial = {},
|
|
83
|
+
persist,
|
|
84
|
+
showViewer
|
|
85
|
+
} = {}) {
|
|
86
|
+
let state = { ...EMPTY_DOCUMENT_STATE, ...initial };
|
|
87
|
+
if (persist) {
|
|
88
|
+
const saved = parseSavedDocuments(persist.load());
|
|
89
|
+
if (saved) state = restoreSavedDocuments(state, saved);
|
|
90
|
+
}
|
|
91
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
92
|
+
const update = (patch) => {
|
|
93
|
+
const previous = state;
|
|
94
|
+
state = { ...state, ...patch };
|
|
95
|
+
if (persist && (state.viewingDocument !== previous.viewingDocument || state.pinnedDocumentId !== previous.pinnedDocumentId || state.documentViewer.tab !== previous.documentViewer.tab || state.documentViewer.textScale !== previous.documentViewer.textScale))
|
|
96
|
+
persist.save(savedDocumentsOf(state));
|
|
97
|
+
listeners.forEach((listener) => listener());
|
|
98
|
+
};
|
|
99
|
+
const setDocumentViewer = (change) => {
|
|
100
|
+
const next = { ...state.documentViewer, ...change };
|
|
101
|
+
const keys = Object.keys(change);
|
|
102
|
+
if (keys.some((key) => next[key] !== state.documentViewer[key]))
|
|
103
|
+
update({ documentViewer: next });
|
|
104
|
+
};
|
|
105
|
+
const updateDraft = (id, change) => {
|
|
106
|
+
const draft = state.draftDocuments[id];
|
|
107
|
+
if (draft) update({ draftDocuments: { ...state.draftDocuments, [id]: change(draft) } });
|
|
108
|
+
};
|
|
109
|
+
return {
|
|
110
|
+
getState: () => state,
|
|
111
|
+
subscribe: (listener) => {
|
|
112
|
+
listeners.add(listener);
|
|
113
|
+
return () => listeners.delete(listener);
|
|
114
|
+
},
|
|
115
|
+
setViewingDocument: (input) => update({ viewingDocument: nextViewingDocument(state.viewingDocument, input) }),
|
|
116
|
+
setDocumentViewer,
|
|
117
|
+
setSelectedDocumentIds: (ids) => update({ selectedDocumentIds: ids }),
|
|
118
|
+
setDocumentsToSelect: (ids) => update({ documentsToSelect: ids }),
|
|
119
|
+
setPinnedDocumentId: (pinnedDocumentId) => update({ pinnedDocumentId }),
|
|
120
|
+
setRelatedDocuments: (relatedDocuments) => update({ relatedDocuments }),
|
|
121
|
+
setPassageCitation: (change) => update({ passageCitation: { ...state.passageCitation, ...change } }),
|
|
122
|
+
showNewDocument: (documentId, tab) => {
|
|
123
|
+
update({
|
|
124
|
+
viewingDocument: { id: documentId, page: null, passageId: null },
|
|
125
|
+
documentViewer: tab ? { ...state.documentViewer, tab } : state.documentViewer
|
|
126
|
+
});
|
|
127
|
+
showViewer?.();
|
|
128
|
+
},
|
|
129
|
+
startDraftDocument: (kind) => {
|
|
130
|
+
const id = `draft-${crypto.randomUUID()}`;
|
|
131
|
+
const draft = {
|
|
132
|
+
id,
|
|
133
|
+
title: DRAFT_TITLES[kind],
|
|
134
|
+
kind,
|
|
135
|
+
content: "",
|
|
136
|
+
mediaBlob: null,
|
|
137
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
138
|
+
};
|
|
139
|
+
update({
|
|
140
|
+
draftDocuments: { ...state.draftDocuments, [id]: draft },
|
|
141
|
+
viewingDocument: { id, page: null, passageId: null },
|
|
142
|
+
// A text draft is written in the editor; a capture's recorder replaces the tabs.
|
|
143
|
+
documentViewer: kind === "text" ? { ...state.documentViewer, tab: "edit" } : state.documentViewer
|
|
144
|
+
});
|
|
145
|
+
showViewer?.();
|
|
146
|
+
return id;
|
|
147
|
+
},
|
|
148
|
+
updateDraftDocument: (id, change) => updateDraft(id, (draft) => ({ ...draft, ...change })),
|
|
149
|
+
setDraftDocumentKind: (id, kind) => updateDraft(id, (draft) => ({
|
|
150
|
+
...draft,
|
|
151
|
+
kind,
|
|
152
|
+
mediaBlob: null,
|
|
153
|
+
title: Object.values(DRAFT_TITLES).includes(draft.title) ? DRAFT_TITLES[kind] : draft.title
|
|
154
|
+
})),
|
|
155
|
+
clearDraftDocument: (id) => {
|
|
156
|
+
if (!(id in state.draftDocuments)) return;
|
|
157
|
+
const rest = { ...state.draftDocuments };
|
|
158
|
+
delete rest[id];
|
|
159
|
+
update({ draftDocuments: rest });
|
|
160
|
+
},
|
|
161
|
+
leave: () => update({
|
|
162
|
+
viewingDocument: null,
|
|
163
|
+
selectedDocumentIds: [],
|
|
164
|
+
documentsToSelect: null,
|
|
165
|
+
pinnedDocumentId: null,
|
|
166
|
+
relatedDocuments: /* @__PURE__ */ new Map(),
|
|
167
|
+
passageCitation: NO_PASSAGE_CITATION,
|
|
168
|
+
documentViewer: {
|
|
169
|
+
...state.documentViewer,
|
|
170
|
+
compareId: null,
|
|
171
|
+
tabRequest: null,
|
|
172
|
+
commentTarget: null,
|
|
173
|
+
unsavedChanges: false,
|
|
174
|
+
detached: false
|
|
175
|
+
}
|
|
176
|
+
}),
|
|
177
|
+
reset: () => update({
|
|
178
|
+
...EMPTY_DOCUMENT_STATE,
|
|
179
|
+
relatedDocuments: /* @__PURE__ */ new Map(),
|
|
180
|
+
documentViewer: {
|
|
181
|
+
...DEFAULT_DOCUMENT_VIEWER_STATE,
|
|
182
|
+
textScale: state.documentViewer.textScale
|
|
183
|
+
}
|
|
184
|
+
})
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
export {
|
|
188
|
+
DEFAULT_DOCUMENT_VIEWER_STATE,
|
|
189
|
+
EMPTY_DOCUMENT_STATE,
|
|
190
|
+
createArbiDocumentSessionStore,
|
|
191
|
+
nextViewingDocument,
|
|
192
|
+
parseSavedDocuments,
|
|
193
|
+
restoreSavedDocuments,
|
|
194
|
+
savedDocumentsOf
|
|
195
|
+
};
|
|
196
|
+
//# sourceMappingURL=documents.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/session/documents.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * The documents part of the session: the document being viewed and the viewer's own state, the\n * documents selected in lists, the document pinned to the chat, the drafts the user started on the\n * client (no backend record until saved), the citation picking passages in the viewer, and the\n * documents related to each one (near duplicates).\n *\n * {@link createArbiDocumentSessionStore} keeps it in memory; given a `persist`, the place in the\n * documents (the viewed document and its page, the pinned one, the viewer's tab and text size) is\n * read back synchronously when the store is made, so a reload shows the document at once.\n */\n\nimport type { RelatedDocsMap } from '../documents/related-documents'\n\n/** The document being viewed. */\nexport interface ArbiViewingDocument {\n /** The document (`doc-\u2026`), or a version reference (`doc-\u2026@v2`) while an earlier version shows. */\n id: string\n /** The page being read, when known. */\n page: number | null\n /** The passage being read, when one is. */\n passageId: string | null\n}\n\n/** What to view: page and passage are left unchanged when omitted. */\nexport interface ArbiViewingDocumentInput {\n id: string\n page?: number | null\n passageId?: string | null\n}\n\n/** A tab of the document viewer. */\nexport type ArbiViewerTab = 'pdf' | 'edit' | 'html' | 'docx' | 'xlsx' | 'versions' | 'preview'\n\nconst VIEWER_TABS: readonly ArbiViewerTab[] = [\n 'pdf',\n 'edit',\n 'html',\n 'docx',\n 'xlsx',\n 'versions',\n 'preview',\n]\n\n/** A comment of a Word document to open when it shows (a notification, a link). */\nexport interface ArbiDocumentCommentTarget {\n documentId: string\n commentId: string\n}\n\n/**\n * The document viewer's own state, shared with whatever opens documents (a citation opens the text\n * view, Compare from a documents list opens the redline): the open tab, the document compared with\n * the one viewed, and a tab asked for when a document was opened (applied once it has loaded).\n */\nexport interface ArbiDocumentViewerState {\n tab: ArbiViewerTab\n /** The document (or version reference) compared with the viewed one, or null. */\n compareId: string | null\n /** A tab to show once `documentId` has loaded (a signature request opens on the PDF). */\n tabRequest: { documentId: string; tab: ArbiViewerTab } | null\n /** The text view's size, a multiplier of the normal size: a reading preference. */\n textScale: number\n /** A phone user picked the PDF by hand: documents stop opening on the text view. */\n phonePdfChosen: boolean\n /** The Word comment to open in the viewed document, or null. */\n commentTarget: ArbiDocumentCommentTarget | null\n /** The open document has edits not saved yet: closing the viewer asks first. */\n unsavedChanges: boolean\n /** The viewer shows in a window of its own (popped out). */\n detached: boolean\n}\n\n/** What a draft is: a text document, or a capture (a voice note, a photo, a video). */\nexport type ArbiDraftKind = 'text' | 'audio' | 'photo' | 'video'\n\n/**\n * A document the user started on the client (a blank document, a capture), with no backend record\n * until it is saved. Its id is minted here (`draft-\u2026`), never sent to the server.\n */\nexport interface ArbiDraftDocument {\n id: string\n title: string\n kind: ArbiDraftKind\n /** A text draft's Markdown. Empty for captures. */\n content: string\n /** A capture's recording or picture, once taken; null before (and after a kind switch). */\n mediaBlob: Blob | null\n createdAt: string\n}\n\n/** A passage picked for a citation: its chunk and, when known, its page. */\nexport interface ArbiPickedPassage {\n chunk_id: string\n page?: number\n}\n\n/**\n * A citation picking passages in the viewer (a fact's sources, a field's), handed between the\n * viewer and the page that edits the citation.\n */\nexport interface ArbiPassageCitationState {\n /** The citation picking now: the document it picks in and its key (null while unsaved). */\n active: { documentId: string; key: string | null } | null\n /** Passages to light (a fact's cited passages while its sources are open). */\n highlighted: readonly string[]\n /** Passages picked in the viewer, not yet taken by the citation. */\n picked: readonly ArbiPickedPassage[]\n /** Passages unpicked in the viewer, not yet taken off the citation. */\n unpicked: readonly string[]\n}\n\n/** The documents being viewed and selected. */\nexport interface ArbiDocumentSessionState {\n viewingDocument: ArbiViewingDocument | null\n documentViewer: ArbiDocumentViewerState\n /** The documents selected in document lists. */\n selectedDocumentIds: readonly string[]\n /** Documents to select in the documents list once they are listed (a thread's sources). */\n documentsToSelect: readonly string[] | null\n /** The document read in full with each turn (one at a time). */\n pinnedDocumentId: string | null\n /** The documents related to each listed one (near duplicates), from the documents list. */\n relatedDocuments: RelatedDocsMap\n /** The drafts started on the client, by id. */\n draftDocuments: Readonly<Record<string, ArbiDraftDocument>>\n passageCitation: ArbiPassageCitationState\n}\n\n/** The documents' changes (the session store has them). */\nexport interface ArbiDocumentSessionActions {\n /**\n * View a document, or none. Viewing another document resets the page; `page` and `passageId`\n * set them when given.\n */\n setViewingDocument(document: ArbiViewingDocumentInput | null): void\n /** Change the document viewer's state; fields not given stay. */\n setDocumentViewer(change: Partial<ArbiDocumentViewerState>): void\n setSelectedDocumentIds(ids: string[]): void\n /** Ask the documents list to select these once they are listed (null: done). */\n setDocumentsToSelect(ids: string[] | null): void\n setPinnedDocumentId(id: string | null): void\n setRelatedDocuments(related: RelatedDocsMap): void\n /** Change the passage citation; fields not given stay. */\n setPassageCitation(change: Partial<ArbiPassageCitationState>): void\n /** Show a document the session just got (a chat writing one), on `tab`, in the viewer. */\n showNewDocument(documentId: string, tab?: ArbiViewerTab): void\n /** Start a draft of `kind`, view it and show the viewer. Returns its id. */\n startDraftDocument(kind: ArbiDraftKind): string\n /** Change a draft's content, capture or title. */\n updateDraftDocument(\n id: string,\n change: Partial<Pick<ArbiDraftDocument, 'content' | 'mediaBlob' | 'title'>>\n ): void\n /**\n * Switch a draft's kind. The capture is dropped (it belonged to the other kind), and a default\n * title follows the kind; a title the user typed stays.\n */\n setDraftDocumentKind(id: string, kind: ArbiDraftKind): void\n /** Forget a draft (saved or discarded). */\n clearDraftDocument(id: string): void\n}\n\n/** The documents part of a session store. */\nexport interface ArbiDocumentSessionStore extends ArbiDocumentSessionActions {\n /** The current state. The same object until something in it changes. */\n getState(): ArbiDocumentSessionState\n subscribe(listener: () => void): () => void\n /** The workspace is being left: nothing is viewed, selected, pinned or picked. */\n leave(): void\n /** Start over (sign-in, sign-out): only the reading preference (the text size) stays. */\n reset(): void\n}\n\n/** What the documents part keeps across reloads. */\nexport interface ArbiSavedDocuments {\n version: 1\n viewingDocument: { id: string; page: number | null } | null\n pinnedDocumentId: string | null\n tab: ArbiViewerTab\n textScale: number\n}\n\n/**\n * Where the documents part keeps what it saves. `load` is synchronous (localStorage), so the store\n * starts from it and nothing waits; `save` may write later (the latest value wins).\n */\nexport interface ArbiDocumentsPersist {\n /** What was saved (any shape: it is checked), or null. Never throws. */\n load(): unknown\n save(saved: ArbiSavedDocuments): void\n}\n\nexport interface ArbiDocumentSessionStoreOptions {\n initial?: Partial<ArbiDocumentSessionState>\n /** Keep the place in the documents across reloads. */\n persist?: ArbiDocumentsPersist\n /** Show the viewer for a document the session just got (a new draft, a chat's document). */\n showViewer?: () => void\n}\n\nexport const DEFAULT_DOCUMENT_VIEWER_STATE: ArbiDocumentViewerState = {\n tab: 'pdf',\n compareId: null,\n tabRequest: null,\n textScale: 1,\n phonePdfChosen: false,\n commentTarget: null,\n unsavedChanges: false,\n detached: false,\n}\n\nconst NO_PASSAGE_CITATION: ArbiPassageCitationState = {\n active: null,\n highlighted: [],\n picked: [],\n unpicked: [],\n}\n\nexport const EMPTY_DOCUMENT_STATE: ArbiDocumentSessionState = {\n viewingDocument: null,\n documentViewer: DEFAULT_DOCUMENT_VIEWER_STATE,\n selectedDocumentIds: [],\n documentsToSelect: null,\n pinnedDocumentId: null,\n relatedDocuments: new Map(),\n draftDocuments: {},\n passageCitation: NO_PASSAGE_CITATION,\n}\n\n/** A draft's default title, by kind; a title still at one of these follows a kind switch. */\nconst DRAFT_TITLES: Record<ArbiDraftKind, string> = {\n text: 'New Doc',\n audio: 'New Audio',\n photo: 'New Photo',\n video: 'New Video',\n}\n\n/** The next viewing document, given the current one (shared by every store implementation). */\nexport function nextViewingDocument(\n current: ArbiViewingDocument | null,\n input: ArbiViewingDocumentInput | null\n): ArbiViewingDocument | null {\n if (!input) return null\n const same = current?.id === input.id\n return {\n id: input.id,\n page: input.page !== undefined ? input.page : same ? (current?.page ?? null) : null,\n passageId: input.passageId !== undefined ? input.passageId : (current?.passageId ?? null),\n }\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\nconst isPage = (value: unknown): value is number =>\n typeof value === 'number' && Number.isInteger(value) && value >= 1\n\n/**\n * Read a saved place in the documents. Each field is checked on its own: an unreadable one keeps\n * its default. Null when there is nothing readable at all.\n */\nexport function parseSavedDocuments(saved: unknown): ArbiSavedDocuments | null {\n if (!isRecord(saved) || saved.version !== 1) return null\n const viewing = isRecord(saved.viewingDocument) ? saved.viewingDocument : null\n return {\n version: 1,\n viewingDocument:\n viewing && typeof viewing.id === 'string' && viewing.id\n ? { id: viewing.id, page: isPage(viewing.page) ? viewing.page : null }\n : null,\n pinnedDocumentId: typeof saved.pinnedDocumentId === 'string' ? saved.pinnedDocumentId : null,\n tab: VIEWER_TABS.includes(saved.tab as ArbiViewerTab)\n ? (saved.tab as ArbiViewerTab)\n : DEFAULT_DOCUMENT_VIEWER_STATE.tab,\n textScale:\n typeof saved.textScale === 'number' && Number.isFinite(saved.textScale) && saved.textScale > 0\n ? saved.textScale\n : DEFAULT_DOCUMENT_VIEWER_STATE.textScale,\n }\n}\n\n/** What of `state` is kept across reloads. */\nexport function savedDocumentsOf(state: ArbiDocumentSessionState): ArbiSavedDocuments {\n return {\n version: 1,\n viewingDocument: state.viewingDocument\n ? { id: state.viewingDocument.id, page: state.viewingDocument.page }\n : null,\n pinnedDocumentId: state.pinnedDocumentId,\n tab: state.documentViewer.tab,\n textScale: state.documentViewer.textScale,\n }\n}\n\n/** The state a saved place puts back (over `base`). */\nexport function restoreSavedDocuments(\n base: ArbiDocumentSessionState,\n saved: ArbiSavedDocuments\n): ArbiDocumentSessionState {\n return {\n ...base,\n viewingDocument: saved.viewingDocument\n ? { id: saved.viewingDocument.id, page: saved.viewingDocument.page, passageId: null }\n : null,\n pinnedDocumentId: saved.pinnedDocumentId,\n documentViewer: { ...base.documentViewer, tab: saved.tab, textScale: saved.textScale },\n }\n}\n\n/** The documents part, in memory (and, given a `persist`, kept across reloads). */\nexport function createArbiDocumentSessionStore({\n initial = {},\n persist,\n showViewer,\n}: ArbiDocumentSessionStoreOptions = {}): ArbiDocumentSessionStore {\n let state: ArbiDocumentSessionState = { ...EMPTY_DOCUMENT_STATE, ...initial }\n if (persist) {\n const saved = parseSavedDocuments(persist.load())\n if (saved) state = restoreSavedDocuments(state, saved)\n }\n const listeners = new Set<() => void>()\n const update = (patch: Partial<ArbiDocumentSessionState>) => {\n const previous = state\n state = { ...state, ...patch }\n if (\n persist &&\n (state.viewingDocument !== previous.viewingDocument ||\n state.pinnedDocumentId !== previous.pinnedDocumentId ||\n state.documentViewer.tab !== previous.documentViewer.tab ||\n state.documentViewer.textScale !== previous.documentViewer.textScale)\n )\n persist.save(savedDocumentsOf(state))\n listeners.forEach((listener) => listener())\n }\n const setDocumentViewer = (change: Partial<ArbiDocumentViewerState>) => {\n const next = { ...state.documentViewer, ...change }\n const keys = Object.keys(change) as (keyof ArbiDocumentViewerState)[]\n if (keys.some((key) => next[key] !== state.documentViewer[key]))\n update({ documentViewer: next })\n }\n const updateDraft = (id: string, change: (draft: ArbiDraftDocument) => ArbiDraftDocument) => {\n const draft = state.draftDocuments[id]\n if (draft) update({ draftDocuments: { ...state.draftDocuments, [id]: change(draft) } })\n }\n return {\n getState: () => state,\n subscribe: (listener) => {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n setViewingDocument: (input) =>\n update({ viewingDocument: nextViewingDocument(state.viewingDocument, input) }),\n setDocumentViewer,\n setSelectedDocumentIds: (ids) => update({ selectedDocumentIds: ids }),\n setDocumentsToSelect: (ids) => update({ documentsToSelect: ids }),\n setPinnedDocumentId: (pinnedDocumentId) => update({ pinnedDocumentId }),\n setRelatedDocuments: (relatedDocuments) => update({ relatedDocuments }),\n setPassageCitation: (change) =>\n update({ passageCitation: { ...state.passageCitation, ...change } }),\n showNewDocument: (documentId, tab) => {\n update({\n viewingDocument: { id: documentId, page: null, passageId: null },\n documentViewer: tab ? { ...state.documentViewer, tab } : state.documentViewer,\n })\n showViewer?.()\n },\n startDraftDocument: (kind) => {\n const id = `draft-${crypto.randomUUID()}`\n const draft: ArbiDraftDocument = {\n id,\n title: DRAFT_TITLES[kind],\n kind,\n content: '',\n mediaBlob: null,\n createdAt: new Date().toISOString(),\n }\n update({\n draftDocuments: { ...state.draftDocuments, [id]: draft },\n viewingDocument: { id, page: null, passageId: null },\n // A text draft is written in the editor; a capture's recorder replaces the tabs.\n documentViewer:\n kind === 'text' ? { ...state.documentViewer, tab: 'edit' } : state.documentViewer,\n })\n showViewer?.()\n return id\n },\n updateDraftDocument: (id, change) => updateDraft(id, (draft) => ({ ...draft, ...change })),\n setDraftDocumentKind: (id, kind) =>\n updateDraft(id, (draft) => ({\n ...draft,\n kind,\n mediaBlob: null,\n title: Object.values(DRAFT_TITLES).includes(draft.title) ? DRAFT_TITLES[kind] : draft.title,\n })),\n clearDraftDocument: (id) => {\n if (!(id in state.draftDocuments)) return\n const rest = { ...state.draftDocuments }\n delete rest[id]\n update({ draftDocuments: rest })\n },\n leave: () =>\n update({\n viewingDocument: null,\n selectedDocumentIds: [],\n documentsToSelect: null,\n pinnedDocumentId: null,\n relatedDocuments: new Map(),\n passageCitation: NO_PASSAGE_CITATION,\n documentViewer: {\n ...state.documentViewer,\n compareId: null,\n tabRequest: null,\n commentTarget: null,\n unsavedChanges: false,\n detached: false,\n },\n }),\n reset: () =>\n update({\n ...EMPTY_DOCUMENT_STATE,\n relatedDocuments: new Map(),\n documentViewer: {\n ...DEFAULT_DOCUMENT_VIEWER_STATE,\n textScale: state.documentViewer.textScale,\n },\n }),\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { getUserEncryptionKeypair, sealedBoxDecrypt, sealedBoxEncrypt } from "@arbidocs/client";
|
|
2
|
+
const SAVE_DELAY_MS = 500;
|
|
3
|
+
const encoder = new TextEncoder();
|
|
4
|
+
const decoder = new TextDecoder();
|
|
5
|
+
function parseStored(raw) {
|
|
6
|
+
if (!raw) return null;
|
|
7
|
+
try {
|
|
8
|
+
const parsed = JSON.parse(raw);
|
|
9
|
+
return parsed && typeof parsed.owner === "string" && typeof parsed.sealed === "string" ? { owner: parsed.owner, sealed: parsed.sealed } : null;
|
|
10
|
+
} catch {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
const storages = /* @__PURE__ */ new Set();
|
|
15
|
+
function clearSealedDrafts() {
|
|
16
|
+
for (const storage of [...storages]) storage.clear();
|
|
17
|
+
}
|
|
18
|
+
function createSealedDraftStorage({
|
|
19
|
+
key = "arbi-drafts",
|
|
20
|
+
storage = typeof localStorage === "undefined" ? void 0 : localStorage,
|
|
21
|
+
owner
|
|
22
|
+
}) {
|
|
23
|
+
let timer;
|
|
24
|
+
let generation = 0;
|
|
25
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
26
|
+
const remove = () => {
|
|
27
|
+
try {
|
|
28
|
+
storage?.removeItem(key);
|
|
29
|
+
} catch {
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
const write = async (drafts, written) => {
|
|
33
|
+
if (!storage) return;
|
|
34
|
+
try {
|
|
35
|
+
const user = owner();
|
|
36
|
+
if (!user) return;
|
|
37
|
+
if (Object.keys(drafts).length === 0) {
|
|
38
|
+
if (parseStored(storage.getItem(key))?.owner === user) storage.removeItem(key);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const keypair = await getUserEncryptionKeypair();
|
|
42
|
+
if (!keypair || written !== generation || owner() !== user) return;
|
|
43
|
+
const plain = Uint8Array.from(encoder.encode(JSON.stringify(drafts)));
|
|
44
|
+
const record = {
|
|
45
|
+
owner: user,
|
|
46
|
+
sealed: sealedBoxEncrypt(plain, keypair.publicKey)
|
|
47
|
+
};
|
|
48
|
+
storage.setItem(key, JSON.stringify(record));
|
|
49
|
+
} catch {
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const draftStorage = {
|
|
53
|
+
owner,
|
|
54
|
+
load: async () => {
|
|
55
|
+
const user = owner();
|
|
56
|
+
if (!user) return null;
|
|
57
|
+
const keypair = await getUserEncryptionKeypair();
|
|
58
|
+
if (!keypair || owner() !== user) return null;
|
|
59
|
+
try {
|
|
60
|
+
const raw = storage?.getItem(key) ?? null;
|
|
61
|
+
if (!raw) return {};
|
|
62
|
+
const stored = parseStored(raw);
|
|
63
|
+
if (!stored || stored.owner !== user) {
|
|
64
|
+
remove();
|
|
65
|
+
return {};
|
|
66
|
+
}
|
|
67
|
+
const plain = sealedBoxDecrypt(stored.sealed, keypair.secretKey);
|
|
68
|
+
const drafts = JSON.parse(decoder.decode(plain));
|
|
69
|
+
if (!drafts || typeof drafts !== "object") return {};
|
|
70
|
+
return Object.fromEntries(
|
|
71
|
+
Object.entries(drafts).filter((entry) => {
|
|
72
|
+
return typeof entry[1] === "string";
|
|
73
|
+
})
|
|
74
|
+
);
|
|
75
|
+
} catch {
|
|
76
|
+
return {};
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
save: (drafts) => {
|
|
80
|
+
clearTimeout(timer);
|
|
81
|
+
const written = generation;
|
|
82
|
+
timer = setTimeout(() => void write(drafts, written), SAVE_DELAY_MS);
|
|
83
|
+
},
|
|
84
|
+
clear: () => {
|
|
85
|
+
clearTimeout(timer);
|
|
86
|
+
timer = void 0;
|
|
87
|
+
generation++;
|
|
88
|
+
remove();
|
|
89
|
+
for (const listener of [...listeners]) listener();
|
|
90
|
+
},
|
|
91
|
+
onClear: (listener) => {
|
|
92
|
+
listeners.add(listener);
|
|
93
|
+
return () => listeners.delete(listener);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
storages.add(draftStorage);
|
|
97
|
+
return draftStorage;
|
|
98
|
+
}
|
|
99
|
+
export {
|
|
100
|
+
clearSealedDrafts,
|
|
101
|
+
createSealedDraftStorage
|
|
102
|
+
};
|
|
103
|
+
//# sourceMappingURL=drafts.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/session/drafts.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * The composers' drafts kept across reloads: stored locally and encrypted, sealed to the signed-in\n * person's own key like the other data kept on the device, so nothing typed is readable at rest.\n *\n * Bound to the person: a record is kept under the user it belongs to and opened only while that\n * user is signed in (`owner`), never by whoever's key happens to be on the device, so a signed-out\n * page, a demo session or another account never sees it. Like the offline mail, the drafts never\n * outlive the session: a sign-out clears them (`clearSealedDrafts`).\n */\n\nimport { getUserEncryptionKeypair, sealedBoxDecrypt, sealedBoxEncrypt } from '@arbidocs/client'\n\n/** Where a session store keeps its drafts (see `createArbiSessionStore`). */\nexport interface ArbiDraftStorage {\n /** The saved drafts, or null while they cannot be opened yet (no one is signed in). */\n load(): Promise<Record<string, string> | null>\n /** Save the drafts (all of them: the record replaces what was saved). */\n save(drafts: Readonly<Record<string, string>>): void\n /** Who the drafts belong to now: the signed-in user, `null` signed out. */\n owner(): string | null\n /** Forget the saved drafts and any write still pending (the session ended). */\n clear(): void\n /** Be told when the drafts were cleared (the session store drops its copy). */\n onClear(listener: () => void): () => void\n}\n\n/** A key-value store the drafts are written to (`localStorage` by default). */\nexport interface DraftKeyValueStore {\n getItem(key: string): string | null\n setItem(key: string, value: string): void\n removeItem(key: string): void\n}\n\n/** How long typing settles before the drafts are written. */\nconst SAVE_DELAY_MS = 500\n\nconst encoder = new TextEncoder()\nconst decoder = new TextDecoder()\n\n/** What is stored: the drafts sealed to the owner's key, and who the owner is. */\ninterface StoredDrafts {\n owner: string\n sealed: string\n}\n\nfunction parseStored(raw: string | null): StoredDrafts | null {\n if (!raw) return null\n try {\n const parsed = JSON.parse(raw) as Partial<StoredDrafts> | null\n return parsed && typeof parsed.owner === 'string' && typeof parsed.sealed === 'string'\n ? { owner: parsed.owner, sealed: parsed.sealed }\n : null\n } catch {\n return null\n }\n}\n\n/** Every sealed draft storage made on this page, so a sign-out clears them all. */\nconst storages = new Set<ArbiDraftStorage>()\n\n/** The session ended (sign-out, or it could not be recovered): clear every saved draft. */\nexport function clearSealedDrafts(): void {\n for (const storage of [...storages]) storage.clear()\n}\n\nexport interface SealedDraftStorageOptions {\n /** The record's key in `storage`. */\n key?: string\n storage?: DraftKeyValueStore\n /**\n * The signed-in user (a stable id, e.g. the user's external id), `null` when no one is: the\n * drafts are opened and written only for them.\n */\n owner: () => string | null\n}\n\n/**\n * Drafts sealed to the signed-in person's key, in `storage` under `key`, for `owner` only. A record\n * of another user is removed unread; one that cannot be opened (damaged) reads as no drafts.\n */\nexport function createSealedDraftStorage({\n key = 'arbi-drafts',\n storage = typeof localStorage === 'undefined' ? undefined : localStorage,\n owner,\n}: SealedDraftStorageOptions): ArbiDraftStorage {\n let timer: ReturnType<typeof setTimeout> | undefined\n // Bumped by clear(): a write that started before it never lands after it.\n let generation = 0\n const listeners = new Set<() => void>()\n\n const remove = () => {\n try {\n storage?.removeItem(key)\n } catch {\n // Storage blocked: nothing was kept either.\n }\n }\n\n const write = async (drafts: Readonly<Record<string, string>>, written: number) => {\n if (!storage) return\n try {\n const user = owner()\n if (!user) return\n if (Object.keys(drafts).length === 0) {\n if (parseStored(storage.getItem(key))?.owner === user) storage.removeItem(key)\n return\n }\n const keypair = await getUserEncryptionKeypair()\n if (!keypair || written !== generation || owner() !== user) return\n // A plain Uint8Array of this realm, which is what the sealing accepts.\n const plain = Uint8Array.from(encoder.encode(JSON.stringify(drafts)))\n const record: StoredDrafts = {\n owner: user,\n sealed: sealedBoxEncrypt(plain, keypair.publicKey),\n }\n storage.setItem(key, JSON.stringify(record))\n } catch {\n // Storage full or blocked: the drafts stay in memory for this visit.\n }\n }\n\n const draftStorage: ArbiDraftStorage = {\n owner,\n load: async () => {\n const user = owner()\n if (!user) return null\n const keypair = await getUserEncryptionKeypair()\n if (!keypair || owner() !== user) return null\n try {\n const raw = storage?.getItem(key) ?? null\n if (!raw) return {}\n const stored = parseStored(raw)\n if (!stored || stored.owner !== user) {\n // Another user's (or an unreadable) record is not this person's to keep or open.\n remove()\n return {}\n }\n const plain = sealedBoxDecrypt(stored.sealed, keypair.secretKey)\n const drafts = JSON.parse(decoder.decode(plain)) as unknown\n if (!drafts || typeof drafts !== 'object') return {}\n return Object.fromEntries(\n Object.entries(drafts).filter((entry): entry is [string, string] => {\n return typeof entry[1] === 'string'\n })\n )\n } catch {\n return {}\n }\n },\n save: (drafts) => {\n clearTimeout(timer)\n const written = generation\n timer = setTimeout(() => void write(drafts, written), SAVE_DELAY_MS)\n },\n clear: () => {\n clearTimeout(timer)\n timer = undefined\n generation++\n remove()\n for (const listener of [...listeners]) listener()\n },\n onClear: (listener) => {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n }\n storages.add(draftStorage)\n return draftStorage\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useArbiSessionState,
|
|
3
|
+
useArbiSessionStore,
|
|
4
|
+
useSessionView,
|
|
5
|
+
useSessionPageTab,
|
|
6
|
+
useTransientView
|
|
7
|
+
} from "./session-hooks.js";
|
|
8
|
+
import {
|
|
9
|
+
useArbiSession,
|
|
10
|
+
useSignedInSession
|
|
11
|
+
} from "./signed-in.js";
|
|
12
|
+
import {
|
|
13
|
+
createArbiSessionStore,
|
|
14
|
+
composeArbiSessionStore,
|
|
15
|
+
conversationKey,
|
|
16
|
+
selectDraft,
|
|
17
|
+
selectIsGenerating,
|
|
18
|
+
selectViewingDocumentId,
|
|
19
|
+
EMPTY_SESSION_STATE,
|
|
20
|
+
layoutActionsOf
|
|
21
|
+
} from "./store.js";
|
|
22
|
+
import {
|
|
23
|
+
createArbiDocumentSessionStore,
|
|
24
|
+
nextViewingDocument,
|
|
25
|
+
parseSavedDocuments,
|
|
26
|
+
restoreSavedDocuments,
|
|
27
|
+
savedDocumentsOf,
|
|
28
|
+
DEFAULT_DOCUMENT_VIEWER_STATE,
|
|
29
|
+
EMPTY_DOCUMENT_STATE
|
|
30
|
+
} from "./documents.js";
|
|
31
|
+
import {
|
|
32
|
+
createArbiChatStore,
|
|
33
|
+
parseSavedChat,
|
|
34
|
+
savedChatOf,
|
|
35
|
+
EMPTY_CHAT_STATE
|
|
36
|
+
} from "./chat.js";
|
|
37
|
+
import {
|
|
38
|
+
createArbiLayoutStore,
|
|
39
|
+
closePanelIn,
|
|
40
|
+
defaultLayoutState,
|
|
41
|
+
DOCUMENT_VIEWER_PANEL,
|
|
42
|
+
dmTabId,
|
|
43
|
+
isPanelOpen,
|
|
44
|
+
openPanelIn,
|
|
45
|
+
panelPlace,
|
|
46
|
+
parseSavedLayout,
|
|
47
|
+
restoreLayout,
|
|
48
|
+
savedLayoutOf
|
|
49
|
+
} from "./layout.js";
|
|
50
|
+
import {
|
|
51
|
+
threadTabId,
|
|
52
|
+
MAX_THREAD_TABS
|
|
53
|
+
} from "./thread-tabs.js";
|
|
54
|
+
import {
|
|
55
|
+
createDebouncedWriter,
|
|
56
|
+
createStoragePersist,
|
|
57
|
+
flushOnPageExit
|
|
58
|
+
} from "./persist.js";
|
|
59
|
+
import {
|
|
60
|
+
createArbiWorkspaceStore,
|
|
61
|
+
browserWorkspaceStorage,
|
|
62
|
+
readWorkspaceLastOpened,
|
|
63
|
+
WORKSPACE_STORAGE_KEY,
|
|
64
|
+
WORKSPACE_LAST_OPENED_KEY
|
|
65
|
+
} from "./workspace.js";
|
|
66
|
+
import {
|
|
67
|
+
clearSealedDrafts,
|
|
68
|
+
createSealedDraftStorage
|
|
69
|
+
} from "./drafts.js";
|
|
70
|
+
import { createUiStateStorage } from "./ui-state-storage.js";
|
|
71
|
+
export {
|
|
72
|
+
DEFAULT_DOCUMENT_VIEWER_STATE,
|
|
73
|
+
DOCUMENT_VIEWER_PANEL,
|
|
74
|
+
EMPTY_CHAT_STATE,
|
|
75
|
+
EMPTY_DOCUMENT_STATE,
|
|
76
|
+
EMPTY_SESSION_STATE,
|
|
77
|
+
MAX_THREAD_TABS,
|
|
78
|
+
WORKSPACE_LAST_OPENED_KEY,
|
|
79
|
+
WORKSPACE_STORAGE_KEY,
|
|
80
|
+
browserWorkspaceStorage,
|
|
81
|
+
clearSealedDrafts,
|
|
82
|
+
closePanelIn,
|
|
83
|
+
composeArbiSessionStore,
|
|
84
|
+
conversationKey,
|
|
85
|
+
createArbiChatStore,
|
|
86
|
+
createArbiDocumentSessionStore,
|
|
87
|
+
createArbiLayoutStore,
|
|
88
|
+
createArbiSessionStore,
|
|
89
|
+
createArbiWorkspaceStore,
|
|
90
|
+
createDebouncedWriter,
|
|
91
|
+
createSealedDraftStorage,
|
|
92
|
+
createStoragePersist,
|
|
93
|
+
createUiStateStorage,
|
|
94
|
+
defaultLayoutState,
|
|
95
|
+
dmTabId,
|
|
96
|
+
flushOnPageExit,
|
|
97
|
+
isPanelOpen,
|
|
98
|
+
layoutActionsOf,
|
|
99
|
+
nextViewingDocument,
|
|
100
|
+
openPanelIn,
|
|
101
|
+
panelPlace,
|
|
102
|
+
parseSavedChat,
|
|
103
|
+
parseSavedDocuments,
|
|
104
|
+
parseSavedLayout,
|
|
105
|
+
readWorkspaceLastOpened,
|
|
106
|
+
restoreLayout,
|
|
107
|
+
restoreSavedDocuments,
|
|
108
|
+
savedChatOf,
|
|
109
|
+
savedDocumentsOf,
|
|
110
|
+
savedLayoutOf,
|
|
111
|
+
selectDraft,
|
|
112
|
+
selectIsGenerating,
|
|
113
|
+
selectViewingDocumentId,
|
|
114
|
+
threadTabId,
|
|
115
|
+
useArbiSession,
|
|
116
|
+
useArbiSessionState,
|
|
117
|
+
useArbiSessionStore,
|
|
118
|
+
useSessionPageTab,
|
|
119
|
+
useSessionView,
|
|
120
|
+
useSignedInSession,
|
|
121
|
+
useTransientView
|
|
122
|
+
};
|
|
123
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/session/index.ts"],
|
|
4
|
+
"sourcesContent": ["export {\n useArbiSessionState,\n useArbiSessionStore,\n useSessionView,\n useSessionPageTab,\n useTransientView,\n} from './session-hooks'\nexport {\n useArbiSession,\n useSignedInSession,\n type ArbiSessionStatus,\n type ArbiSignedInSession,\n} from './signed-in'\nexport {\n createArbiSessionStore,\n composeArbiSessionStore,\n conversationKey,\n selectDraft,\n selectIsGenerating,\n selectViewingDocumentId,\n EMPTY_SESSION_STATE,\n type ArbiSessionParts,\n type ArbiSessionState,\n type ArbiSessionStore,\n type ArbiSessionStoreOptions,\n type ArbiWorkspaceStatus,\n layoutActionsOf,\n} from './store'\nexport {\n createArbiDocumentSessionStore,\n nextViewingDocument,\n parseSavedDocuments,\n restoreSavedDocuments,\n savedDocumentsOf,\n DEFAULT_DOCUMENT_VIEWER_STATE,\n EMPTY_DOCUMENT_STATE,\n type ArbiDocumentCommentTarget,\n type ArbiDocumentSessionActions,\n type ArbiDocumentSessionState,\n type ArbiDocumentSessionStore,\n type ArbiDocumentSessionStoreOptions,\n type ArbiDocumentsPersist,\n type ArbiDocumentViewerState,\n type ArbiDraftDocument,\n type ArbiDraftKind,\n type ArbiPassageCitationState,\n type ArbiPickedPassage,\n type ArbiSavedDocuments,\n type ArbiViewerTab,\n type ArbiViewingDocument,\n type ArbiViewingDocumentInput,\n} from './documents'\nexport {\n createArbiChatStore,\n parseSavedChat,\n savedChatOf,\n EMPTY_CHAT_STATE,\n type ArbiChatActions,\n type ArbiChatState,\n type ArbiChatStore,\n type ArbiChatStoreOptions,\n type ArbiConversationDocument,\n type ArbiConversationGeneration,\n type ArbiMessageTimer,\n type ArbiSavedChat,\n type TurnTools,\n} from './chat'\nexport {\n createArbiLayoutStore,\n closePanelIn,\n defaultLayoutState,\n DOCUMENT_VIEWER_PANEL,\n dmTabId,\n isPanelOpen,\n openPanelIn,\n panelPlace,\n parseSavedLayout,\n restoreLayout,\n savedLayoutOf,\n type ArbiDmTab,\n type ArbiGridLayoutState,\n type ArbiLayoutActions,\n type ArbiLayoutState,\n type ArbiLayoutStore,\n type ArbiLayoutStoreOptions,\n type ArbiPanelMode,\n type ArbiPanelsState,\n type ArbiSavedLayout,\n type ArbiShellState,\n type ArbiSidebarState,\n type ArbiTabsState,\n type ArbiThreadTabsController,\n type ArbiViewsState,\n} from './layout'\nexport {\n threadTabId,\n MAX_THREAD_TABS,\n type ArbiThreadComposer,\n type ArbiThreadTab,\n type ArbiThreadTabShow,\n type ArbiThreadTabView,\n type ArbiThreadTabsState,\n} from './thread-tabs'\nexport {\n createDebouncedWriter,\n createStoragePersist,\n flushOnPageExit,\n type ArbiKeyValueStorage,\n type ArbiSessionPersist,\n type DebouncedWriter,\n type DebouncedWriterOptions,\n type StoragePersistOptions,\n} from './persist'\nexport {\n createArbiWorkspaceStore,\n browserWorkspaceStorage,\n readWorkspaceLastOpened,\n WORKSPACE_STORAGE_KEY,\n WORKSPACE_LAST_OPENED_KEY,\n type ArbiWorkspaceState,\n type ArbiWorkspaceStorage,\n type ArbiWorkspaceStore,\n type ArbiWorkspaceStoreOptions,\n type BrowserWorkspaceStorageOptions,\n} from './workspace'\nexport {\n clearSealedDrafts,\n createSealedDraftStorage,\n type ArbiDraftStorage,\n type DraftKeyValueStore,\n type SealedDraftStorageOptions,\n} from './drafts'\n\nexport { createUiStateStorage, type UiStateStorage } from './ui-state-storage'\n"],
|
|
5
|
+
"mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAMA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAgBK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAUK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAeK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAMK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAMK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAMK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AAEP,SAAS,4BAAiD;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|